Allegro Masking... (bitmap - bitmap = masked bitmap?)

Started by
11 comments, last by konForce 18 years, 10 months ago
Probably one of those stupid allegro-questions, but here goes: http://www.systemsgo.se/masking/index.html I just need to know if it's possible and in any case how to have one bitmap (in my case a PNG-file with full alpha transparency - mostly for antialiasing-reasons) overlap another (any jpeg-file), thus masking the underlying content (the jpeg-file) resulting in a masked surface. (A basic feature found in Macromedia Flash for instance). In case I wasn't clear enough, I posted a graphic instance of what I want to achieve on the URL above. Just for further clarification, I want to use allegro with directX-support (so if I'm not mistaken, an openGL-solution - which probably won't be necessary in this case, won't work - right?)... Example code would be great! Best, John
Advertisement
I don't realy know how alegro does stuff. But I would do it like this:

load both images replace the colors of the transparent one with the colors of the other (don't tuch the alpha) and your done. If you substract the colors of the transparent image you will get some some effects, but I don't think this is what you want to do.
To be honest, I keep getting told Allegro can do this, but I've never seen it done in practice. You could probably write your own function to do this with the Allegro bitmaps, and if you're good it wouldn't even be that slow. [smile] If you want to use Allegro with DirectX, maybe try using DirectX to do this if that's easier, too. I've never tried DirectX though, so I won't comment.

Jesus saves ... the rest of you take 2d4 fire damage.

Is the PNG mask only used as a 1-bit black/white masking image? If so, you could use XOR drawing mode with rectfill to accomplish this.

I cannot tell by the images on the link you posted, but it looks like you want anti-aliased edges by what you said.

[Edited by - konForce on June 3, 2005 9:14:24 PM]
Create an Allegro bitmap of depth 32 bits (create_bitmap_ex).

Then blit the solid bitmap into this memory bitmap.

Then copy the alpha channel from the other image - you might need to do this pixel by pixel, or there might be an Allegro blender function which just takes the alpha channel, or you could write your own.

Either way, this is a piece of precalculation that you only need to do once, or occasionally, right, so it doesn't matter if it takes a while.

Even for a big bitmap like this, it's still only going to take 100ms probably on a slowish machine, so it's not a problem provided you only do this once per level, or occasionally.

Mark
Here is a demo that illustrates how to do it: mask.zip

In short, you need to:

  • create a 32-bit bitmap for the RGBA image
  • create an 8-bit bitmap for the mask. (Color #255 is 0% transparent, Color #0 is 100% transparent.)
  • call set_write_alpha_blender() to enable the alpha layer writing
  • use draw_trans_sprite() to apply the mask on top of the 32-bit RGBA image.
  • call set_alpha_blender() to enable the alpha blitting
  • use draw_trans_sprite() to draw the 32-bit RGBA picture to another bitmap, using the alpha layer to determine opacity.

It does exactly what you want to do, except that your PNG mask file needs to be replaced with an 8-bit image that represents the mask.
Everyone - Seriously great! Thank you! - especially nefthy - looks great. I'll just optimize it for my needs and that's one less thing to worry about ;)

Again, big thanks!
Updated question:
I'm currently testing things with the source code provided by nefthy... (available in the mask.zip above - or posted as text below)

Now, the question is: if I want to display a different background-image instead of the black which is produced by the mask-file (how do I do this?

In other words, still the same as before (circle reveals the yellow/orange picture, but instead of black surrounding, I want another image (lets say a sky-theme)... how?


_______________________________________

ORIGINAL SOURCE:


#include <allegro.h>

int main(void)
{
BITMAP *pic, *mask; // image picture and 8-bit image mask
BITMAP *buffer; // screen buffer
int x = 0, y = 0; // coords of where to draw the mask
int k=0; // used for the key code
int mx,my; // old mouse x and y values

allegro_init();
set_color_depth(32);
set_gfx_mode(GFX_AUTODETECT_WINDOWED,800,600,0,0);
install_keyboard();
install_mouse();

buffer = create_bitmap(SCREEN_W, SCREEN_H);

// the image with alpha support *must* be 32-bit
// by default, this picture will be converted to 32-bit because
// that is what the current color depth is
pic = load_bmp("layer1.bmp", NULL);

// the mask needs to stay 8-bit, so we must disable color conversion
set_color_conversion(COLORCONV_NONE);
mask = load_bmp("mask.bmp", NULL);

if (!pic || !mask) exit(1);

// center the mask
x = pic->w/2 - mask->w/2;
y = pic->h/2 - mask->h/2;

// set up initial mouse stuff
show_mouse(screen);
poll_mouse();
mx = mouse_x;
my = mouse_y;

do
{
// move mask coords with mouse
poll_mouse();
if (mx != mouse_x || my != mouse_y)
{
x = (mx = mouse_x) - mask->w / 2;
y = (my = mouse_y) - mask->h / 2;
}

// set up the masking
set_write_alpha_blender(); // used for 'draw_trans_sprite()'
drawing_mode(DRAW_MODE_TRANS, NULL, 0,0); // used for 'rectfill()'

// set all the alpha values to 0 (transparent)
// this works because we set the drawing mode to DRAW_MODE_TRANS
rectfill(pic, 0,0,pic->w,pic->h, 0);

// update the alpha values based on the image mask
// this works because we enabled the "write alpha blender"
draw_trans_sprite(pic, mask, x,y);

// reset the drawing mode to solid and draw a rectangle around the image
drawing_mode(DRAW_MODE_SOLID, NULL, 0,0);
clear(buffer);
rect(buffer, 0,0, pic->w+1, pic->h+1, makecol(255,255,255));

// set the blender to alpha drawing
set_alpha_blender();
draw_trans_sprite(buffer, pic, 1,1); // draw the picture with its alpha

// blit buffer to screen
blit(buffer, screen, 0,0, 0,0, SCREEN_W, SCREEN_H);

// move the mask coords with keys
if (keypressed())
{
k = readkey() >> 8;
if (k == KEY_LEFT) x--;
if (k == KEY_RIGHT) x++;
if (k == KEY_UP) y--;
if (k == KEY_DOWN) y++;
}
} while (k != KEY_ESC && !mouse_b);

destroy_bitmap(buffer);
destroy_bitmap(mask);
destroy_bitmap(pic);
return 0;
}
END_OF_MAIN()
Quote:In other words, still the same as before (circle reveals the yellow/orange picture, but instead of black surrounding, I want another image (lets say a sky-theme)... how?


You need to blit the sky theme to the buffer before drawing the alpha sprite to the buffer.

// reset the drawing mode to soliddrawing_mode(DRAW_MODE_SOLID, NULL, 0,0);clear(buffer);// blit the sky-theme image to the bufferblit(sky, buffer, 0,0, 0,0, sky->w,sky->h);// set the blender to alpha drawingset_alpha_blender();draw_trans_sprite(buffer, pic, 1,1); // draw the picture with its alpha 
Thx! works perfectly...

one more thing I can't figure out: I can define the X and Y coordinates of both the mask and the sky-theme - but I can't figure out how to define the X and Y of the image shown through the mask (in my case the orange/yellow image).

Let's say I want to displace this (nudge it upwards along the Y-axis about 40 pixels), without displacing the sky-image (let's call this the background image) or the mask itself.

is there some ...0,0 (x,y)... I have yet to define to do this?

Note that this may seem trivial using the images, etc I've posted as example-files in the beginning of this thread - but is vital to the effect itself, using multiple maskinglayers and other images.

Please help! ;)

This topic is closed to new replies.

Advertisement