Transparency and translucency together
Nathan Holts

First off, my apologies for bothering you folk with what may well be a ridiculously simple problem. I'm sure there's an obvious solution that I just keep overlooking, but I can't for the life of me see it.

Alright, so I have a sprite('A'), which has a pure magenta (transparency) background. I want to draw another image ('B') over it translucently, in such a way as to only draw over the non-transparent pixels in A, whilst leaving the transparent pixels their current colour.

I can't think of a clearer way to word that, so perhaps an example would be better.

http://img293.imageshack.us/img293/8356/examplewh7.png
(please excuse the atrocious placeholder graphics, they're just for example's sake)

A is the original sprite, B the image I want to draw over it. When I use draw_trans_sprite to do this, I get C as a result, whilst the result I want is labelled D.

If anyone can please tell me how I can get that result, short of writing my own blitting function, I'd be grateful.

Onewing

My guess is your solution is in

Matt Smith

drawing_mode won't help. I think you'll need your own blitting function.
e.g (untested)

 1 2 bitmap * bmp_a, * bmp_b, * bmp_d; //all same size. OK if *bmp_d==*bmp_a or *bmp_d==*bmp_b; 3 int d_alpha = 0 to 255 4 int color_a,color_b; //temp vars used to store pixel colors 5 6 for (y=0; yheight; y++) 7 for (x=0 ;x< bmp_d->width; x++) 8 if ((color_a = _getpixel(bmp_a,x,y))!=bitmap_mask_color(bmp_a)) 9 { 10 color_b = _getpixel(bmp_b, x, y); 11 12 r = (getr(color_a) * d_alpha + getr(color_b) * (255 - d_alpha)) /255; 13 g = (getg(color_a) * d_alpha + getg(color_b) * (255 - d_alpha)) /255; 14 b = (getb(color_a) * d_alpha + getb(color_b) * (255 - d_alpha)) /255; 15 16 _putpixel(bmp_d, x, y, makecol(r,g,b); 17 } else _putpixel(bmp_d, x, y, color_a); //saves need to pre-clear bmp_d;

HardTranceFan

Or create a mask of image A (making all none-magenta colours transparent), resulting in B, combine it with C to create D, and use that on A to produce E?

Nathan Holts

One Wing: Thanks but I'd already tried this one (asuming you're thinking the same way I am), it seems it wont work with sprites taller than 64 pixels (mine are 80).

Matt Smith: That's what I was afraid of... My main concern with a custom blit function being one of speed.

HardTranceFan: This is what I was originally thinking, but am stuck on combining B and C. I can't figure out how to make the white transparent instead of magenta, or is there another way to do this? (again, my apologies if this is really simple, I've checked the documentation and couldn't see anything, but then again I'm not sure exactly what I'm looking for)

Matt Smith

Surprisingly, a custom blit function written like that isn't too slow. It can be optimised somewhat (usually at the expense of having seperate versions for each color depth) but this is basically what all allegro's blit functions do anyway. As it is, it is roughly half the speed of the best possible software solution.

Dustin Dettmer

A custom blit function is overkill. Heres one idea:

 1 static unsigned long reverseTransBlender24(int x, int y, int n) 2 { 3 unsigned long ret = y; 4 5 if(y != makecol24(255, 0, 255)) 6 ret = makecol24( 7 getr24(x) * n + getr24(y) * (255 - n), 8 getg24(x) * n + getg24(y) * (255 - n), 9 getb24(x) * n + getb24(y) * (255 - n)); 10 11 return ret; 12 } 13 14 ... 15 16 17 BITMAP *theGuy, *thePattern; 18 19 set_blender_mode(0, 0, reverseTransBlender24, 255, 255, 255, 127); 20 21 draw_trans_sprite(theGuy, thePattern, 0, 0); 22 blit(theGuy, screen, ... );

Kris Asick

HardTranceFan's got the right idea, but there's a simpler method than his, and it takes advantage of Allegro's ability to blit 8-bit images onto images of a higher bit depth.

You will end up with four bitmaps. All of which should be truecolour, except B, which should be 8-bit:

C: Transparent Image
D: Final Bitmap

Image B should have the transparent area of A set to a palleted magic pink and the non-transparent area set to colour index 0.

Then, all you do:

Step 1: Blit C to D.
Step 2: Blit A translucently to D.
Step 3: Use draw_sprite() to blit B to D.

Done! (NOTE: You can also swap A and C between steps 1 and 2. It depends on how you want to control the translucency.)

--- Kris Asick (Gemini)
--- http://www.pixelships.com

Nathan Holts

Dustin Dettmer: I couldn't get the code you supplied to work, even after tinkering for a while, but it did point me in the right direction. I wouldn't have even thought of a custom blender (alright, I didn't even know they existed, I've been learning this stuff as it comes up), but I've now managed to get one working that does what I needed it to. Many thanks for your help.

orz

AASTR2 will happily do that sort of thing. It's reasonably fast if you disable the anti-aliasing part.

Dustin Dettmer
Nathan said:

... but I've now managed to get one working that does what I needed it to. Many thanks for your help.

Awesome