Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

Mike

2D Alpha Blending with the Win32 GDI....

This topic is 6238 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Here is the code:
void cGUI::DrawImageBlended( int image, int x_pos, int y_pos, bool to_back_buffer )
{
	HDC		hDCBg;
	HDC		hDCImage;

	int		x,	y;
	int		y1, y2;
	int		w,	h;

	hDCBg		= (to_back_buffer)? m_hDCBackBuffer : ::GetDC( m_hWnd );
	hDCImage	= m_sImage[ image ].m_hDC;
	w			= m_sImage[ image ].m_nWidth;
	h			= m_sImage[ image ].m_nHeight;

	HBITMAP hBmp1 = (HBITMAP)GetCurrentObject( hDCBg, OBJ_BITMAP );
	HBITMAP hBmp2 = (HBITMAP)GetCurrentObject( hDCImage, OBJ_BITMAP );
	BITMAP	bmp1;
	BITMAP	bmp2;

	GetObject( hBmp1, sizeof( BITMAP ), &bmp1 );
	GetObject( hBmp2, sizeof( BITMAP ), &bmp2 );
	
	int bmpSize1 = bmp1.bmWidthBytes*bmp1.bmHeight;
	int	bmpSize2 = bmp2.bmWidthBytes*bmp2.bmHeight;

	WORD* p1 = new WORD[ bmpSize1 ];
	WORD* p2 = new WORD[ bmpSize2 ];

	GetBitmapBits( hBmp1, bmpSize1, p1 );
	GetBitmapBits( hBmp2, bmpSize2, p2 );

	y1 = 0;
	y2 = 0;

	for( y = 0; y < h; y++ )
	{
		for( x = 0; x < bmp2.bmWidth; x++)
		{
			if( x_pos+x > 0 && y_pos+y > 0 && 
				x_pos+x < bmp1.bmWidth && y_pos+y < bmp1.bmHeight 
				&& p2[x+y2] != 0 )
			{
				p1[x_pos+(x)+y1] = (p2[x+y2]+p1[x_pos+(x)+y1])>>1;	
			}
		}

		y1 = (y_pos+y)*bmp1.bmWidth;
		y2 = y*bmp2.bmWidth;
	}

	SetBitmapBits( hBmp1, bmpSize1, p1 );

	delete[] p1;
	delete[] p2;

	if( !to_back_buffer ) ::ReleaseDC( m_hWnd, hDCBg );
}
 
Before anyone points it out, I know that alpha blending with the Win32 GDI is slow. Anyway, I cannot get the colors to appear correctly. Does anyone see any obvious error? I realize the above code only works when using a 16 bit desktop (upon loading all images are converted to the same bit depth as the desktop). if I don''t add the two WORDs and devide then everthing turns out okay (i.e. only use the value from the image source, so its just a straight blit); however, when I combine the two and devide the colors turn out incorectly. I''m shooting for a straight up 50/50 blend, hence the simple equation. Thanks, mike

Share this post


Link to post
Share on other sites
Advertisement
Guest Anonymous Poster
I quickly looked over it and I think I know what the problem is. You are using 16 bit color, and each word contains 3 colors, red green and blue. You can''t just divide the words, you have to divide the individual components.

For example, say you have RGB = F0F. (I am simplifying a bit, each color will be 4 bits for this example) This is all red, no greend, all blue.

Now, take half of F0F, you get 787. 787 is about equal parts of red, green and blue. But logically you should really have something that is half red, NO green, half blue. The problem is that the division crosses over the logical color boundaries.

So, what you need to do is mask out each color and divide it seperately. For example:

-----------
int color = 0xF0F;

int red = color & 0xF00; //mask out red
red = red/2; //now, red = 0x700
red &= 0xF00; //make sure that the red only contains values
//in the first four bits. For example, if red was 0x100, it will
//become 0x080 after dividing. We should consider this to be NO
//red

//do same for green and blue...


newcolor= red | green | blue; //combine the bit patterns
//this newcolor is half intensity the old color
------------------

In short, you have to divide and then add the components individually, instead of as a whole word. The above example does the divinding, but not the addtion. The addition would just be:

int red1 = color & 0xF00; //mask out red
int red2 = color2 & 0xF00;

red1 = (red1 / 2) & 0xF00;
red1 = (red2 / 2) & 0xF00;

combinedRed = (red1 + red2) & 0xF00; //make sure we only take the red bits. Actually if you think about this you shouldn''t need it, if you take 1/2 of each they should not overflow, but if you take more than 1/2 of each it could, so this is more general. For example, if you took 9/10 of one blue and 9/10 of the other blue the blue bits could overflow into the red bits. Now sure why you would do this, but you might

I tried to make this clear, hope it helped

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I''m aware of the need to break the word into its three colors, but I read somewhere that you could just add the to words and devide. I changed the line:

  
//p1[x_pos+(x)+y1] = (p2[x+y2]+p1[x_pos+(x)+y1])>>1;



to:

  
int r1 = (p2[x+y2] >> 16) & 0xFF;
int g1 = (p2[x+y2] >> 8) & 0xFF;
int b1 = p2[x+y2] & 0xFF;
int r2 = (p1[x_pos+(x)+y1] >> 16) & 0xFF;
int g2 = (p1[x_pos+(x)+y1] >> 8) & 0xFF;
int b2 = p1[x_pos+(x)+y1] & 0xFF;

int ar, ag, ab;

ar = int(.5 * double(r1 - r2) + r2);
ag = int(.5 * double(g1 - g2) + g2);
ab = int(.5 * double(b1 - b2) + b2);
p1[x_pos+(x)+y1] = ab | (ag << 8) | (ar << 16);


The above code yeilds the same, incorect, result. I realize that the above code is not optimized, but I''m just trying to get some code to work. Any ideas?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Ok, two more things:

#1: You said 16 bit color, right? 16 bit color is 5 bits per color, with a leading bit that can be either zero or one. (You are supposed to ignore it) But you are shifting by 16 to get the red and 8 to get the blue, then masking by 0xff?

it should be:

red = (color>> 10) & 0x001f //shift left ten bits, take only the first 5 of the six bits

green = (color>>5) & (0x001f)//

blue = color & 0x001f//last 5 bits

Did you mean 24 bit?

#2: You have ar = int(.5 * double(r1 - r2) + r2);

why not just have (r1>>1) + (r2>>1)? I suppose it might not make a difference, but it is a lot cleaner.

Are the bitmaps the same size? Are they supposed to be?

If you are still having problems, I would take a bitmap that is all red and combine it with a bitmap that is all green, and see what happens. Or try all white with all black. Try things where the expected outcome is obvious and you might be able to see what the problem is.

Share this post


Link to post
Share on other sites
This project is at work (a lunch-time toy), so I won''t be able to play with it until tomarrow, but just so you know...

The things are as they are becuase I just took someone elses code that they said works (it was in a reponse to a question on this forum). I didn''t change anything so that there would not be a code error on my part. Yes, I know that (r1>>1) + (r2>>1) is better, but again, I left the working code as is (only changed the variable "alpha" to .5)

I''ll se what I can do tomarrow.

Share this post


Link to post
Share on other sites
Thanks for all the help. I''ve got it working properly now. The problem was in the shifting and masking for the r g b values. Thanks again.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
No problem, glad I could help. I remember how long I struggled before I figured out that the leading bit in a 5-5-5 scheme could be 1 or 0. I thought it was always 0 and had some horrible headaches as a result. My transparent colors wouldn''t come out transparent on other computers...

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!