Paint Alpha Mask / Alpha Channel Code
Andy S (2979) 504 posts |
I wrote an experimental block of code as part of the Improvements to Paint bounty, to attempt to create alpha mask or alpha channel sprites. Please be gentle as although I’m no stranger to C nor RISC OS programming, I’m only just getting to grips with using C in RISC OS. OS_SpriteOp 38 seemed to me to be the most flexible way to achieve this and I’ve inserted my code in PSprite in create_create_sprite(). My code comes after the existing call to sprite_create_rp() (RISCOS_Lib), the idea being that the requested alpha mask or alpha channel will be added to the new sprite. I intend to put in UI validation (on Create new sprite) to stop attempts to use alpha with the sprite formats that don’t support it (I’m thinking only 4K, 32K and 16M colour sprites should permit it, right?). Please can someone knowledgeable have a look at the below code and tell me if I’m on the right track? I’ve left bits 0 to 8 of the R3 flags as zero as I’m dealing with the newly created (blank) sprite (though it’s not clear from the proposal whether adding alpha to existing sprite files should be supported). Will this work? OK, here goes with the code: /*Add an alpha channel or alpha mask if wanted and available AJS 2 Jun 2016*/ if (want_alpha_mask || want_alpha_chan) { int flags=0; if (want_alpha_mask) { /*Convert to 8bpp alpha mask*/ flags = (int) 0x8000000; } else if (want_alpha_chan) { /*Convert to RISC OS 5-compatible alpha channel*/ flags = (int) 0xC0000000; } int space_needed = 0; if ((error = os_swix4r(OS_SpriteOp, 38 | 0x200, (int)*sarea, (int)addr, flags, NULL, NULL, NULL, &space_needed)) != NULL || space_needed > 0 ) { /*TODO if r3 > 0 it will give amount of extra space needed in area*/ /*TODO fail gracefully on older machines*/ if (space_needed > 0) { /*TODO put code here to allocate the extra space*/ msg = "More space needed."; } else msg = error->errmess; goto finish; } } My biggest concern at the moment with the above is knowing whether enough memory has been reserved. Will space_needed be a number of bytes? The documentation doesn’t say. Also, assuming the existing sprite format already has room in the form of either an 8bpp mask (for an alpha mask) or in the pixel data (for an alpha channel, assuming it’s a 4K, 32K or 16M colour sprite), am I right in thinking I won’t ever need to allocate any additional memory for this? |
Andy S (2979) 504 posts |
Apologies, the forum seems to be ignoring most of my line breaks in the code I pasted in. I’ll try and reformat it. |
Chris (121) 472 posts |
Hi Andy. If you use
Ah – you already got it! :) |
Andy S (2979) 504 posts |
Cheers Chris ;) I found the “pre” tag did what I wanted. |
Jeffrey Lee (213) 6048 posts |
Yeah, that seems like a reasonable way of doing things.
Yes, alpha channels are only supported with 4K, 32K and 16M colour depths (yielding 4bpp, 1bpp and 8bpp alpha respectively). Alpha masks are supported with any colour depth. One thing to watch out for is that OS_SpriteOp 38 won’t operate on “old format” sprites (where the mode word is a mode number), so if an alpha channel or mask is desired then you’ll have to make sure Paint generates one of the newer mode word formats for that case (i.e. either the “new” RISC OS 3.5 format or the RISC OS 5 format). This restriction is partly because the “alpha mask” flag is a flag in the mode word, and that flag only exists for the newer formats.
Looks good to me. However you might want to replace the 38 and any other magic constants you come across with defines from the relevant global header (e.g. Global/Sprite.h, which should be at Export.APCS-32.C.Global.h.Sprite). A lot of the global headers are generated from assembler versions, so if you’re confused as to what a certain value is then looking at the assembler version might help (e.g. Export.APCS-32.Hdr.Global.Sprite)
Yeah that will work fine. Since Paint allows you to add/remove the mask from a sprite after it’s been created it would seem sensible to me that adding/removing alpha should be supported as well (along with converting between the three types OS_SpriteOp 38 supports). Perhaps this would best be handled by a new dialogue box since there are at least a couple of settings the user would want to specify (sorry! :-))
Yes, space_needed will be in bytes. The routine doesn’t use any temporary buffers, so as long as the sprite area is large enough to hold the final sprite it won’t ask you to extend it. Adding an alpha channel will never ask for more memory because the spare bits are already present in the pixel data. |
Jeffrey Lee (213) 6048 posts |
Please can someone knowledgeable have a look at the below code and tell me if I’m on the right track? Actually, if you’re going to grow the sprite area in response to the “not enough space” error then you’re going to hit an issue with the way SWI errors are handled. Many generic C functions for calling SWIs ( |
Andy S (2979) 504 posts |
Excellent, thanks Jeffrey! if an alpha channel or mask is desired then you’ll have to make sure Paint generates one of the newer mode word formats for that case Ah, that’s interesting. It should be fine for alpha channels, at least on Create sprite, as I think > 256 colour sprites can’t have mode numbers (Paint creates a mode word for the higher coloured ones at least), but I’ll have to stick some logic in for the alpha masks. However you might want to replace the 38 and any other magic constants you come across with defines from the relevant global header Consider it done. adding/removing alpha should be supported as well (along with converting between the three types OS_SpriteOp 38 supports). Perhaps this would best be handled by a new dialogue box since there are at least a couple of settings the user would want to specify (sorry! :-)) I agree in principle but I guess this will have to go on the end of my list for if and when I ever complete all the other bits! :) Actually, if you’re going to grow the sprite area in response to the “not enough space” error then you’re going to hit an issue with the way SWI errors are handled. I’m inclined to just try to avoid this approach in that case. The documentation certainly made it sound like there’s nothing extra in these sprites than the mask, pixel data and standard header but I just wanted to be sure there were no undocumented gaps or other data added (given that the offsets in the header would seem to permit this). |