Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C++ Windows Win32 GDI
I use to draw device-independent bitmaps (DIBs) to the screen by means of either SetDIBitsToDevice (true size) or StretchDIBits (with zoom).
 
These functions move pixel data from a memory buffer directly to screen. [This operation is not the same as copying from one DC (Device Context) to another DC nor from a DDB (Device Dependent Bitmap) to another.]
 
So far so good. Works well with the image depths I am using (biBitCount = 8, 24 or 32).
 
Now I want to do partial drawing, as if parts of the image were transparent. In other words, attach an alpha value to every pixel. I can satisfy myself with binary values (fully opaque or fully transparent), but plain alpha is good too.
 
I have the option of reading the background pixels from screen and doing the blend myself, but this solution doesn't look attractive to me, because it involves costly reads, plus the need to convert to 24 bits because the background of a Window is in color.
 
So I am looking for efficient ways to achieve this effect. I expected to find BlendDIBitsToDevice or StretchBlendDIBits entries or similar, but it seems I need to roll up my sleeves.
 
Any suggestion ?
Posted 21-Feb-13 23:47pm
Edited 4-Jun-13 10:29am
v2

1 solution

Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

The solution is to use the AlphaBlend function. The latter requires two things: on one hand a source device context, and on the other hand a source bitmap, which must be selected into it (don't ask me why).
 
The device context is created as a memory DC which is compatible with the display DC. It is obtained by means of CreateCompatibleDC.
 
The bitmap is generated as a so called DIB Section, via CreateDIBSection.
 
Last but not least, you have to know that premultiplied Alpha is required, meaning that all three Red, Green, Blue components must be multiplied by Alpha (and scaled) before blitting. Here is a snippet.
		// Initialize the bitmap info structure
		struct tagBITMAPINFO 
		{ 
			BITMAPV4HEADER bmiHeader; 
			RGBQUAD bmiColors[256]; 
		} BufferInfo;
 
		BufferInfo.bmiHeader.bV4Size= sizeof(BITMAPV4HEADER); 
		BufferInfo.bmiHeader.bV4Width= Width; 
		BufferInfo.bmiHeader.bV4Height= Height; 
		BufferInfo.bmiHeader.bV4Planes= 1; 
		BufferInfo.bmiHeader.bV4BitCount= 32;
		BufferInfo.bmiHeader.bV4V4Compression= BI_BITFIELDS;
		BufferInfo.bmiHeader.bV4SizeImage= 0;
		BufferInfo.bmiHeader.bV4ClrUsed= 0;
		BufferInfo.bmiHeader.bV4ClrImportant= 0; 
		BufferInfo.bmiHeader.bV4AlphaMask= 0xff000000;
		BufferInfo.bmiHeader.bV4RedMask=   0x00ff0000;
		BufferInfo.bmiHeader.bV4GreenMask= 0x0000ff00;
		BufferInfo.bmiHeader.bV4BlueMask=  0x000000ff;
		BufferInfo.bmiHeader.bV4CSType= 0;
 
		// Create a compatible device context
		HDC hMemoryDC= CreateCompatibleDC(hDC);
 
		// Create a DIB section and select it
		byte* Section;
		HBITMAP hBitMap = CreateDIBSection(MemoryDC, (BITMAPINFO*)&BufferInfo, DIB_RGB_COLORS, (void**)&Section, NULL, 0x0);
		HGDIOBJ Save= SelectObject(hMemoryDC, hBitMap);
 
		// Premultiply by alpha
		for (int y= 0; y < Height; y++)
		{
			for (int x= 0; x < Width; x++)
			{
				RgbaPixel P= *(RgbaPixel*)&SrcBuffer[y * SrcPitch + 4 * x];
				int Q= P.Alpha * 33025; // 2^31 / 255^2
				P.Red=   (P.Red   * Q) >> 23;
				P.Green= (P.Green * Q) >> 23;
				P.Blue=  (P.Blue  * Q) >> 23;
				*(RgbaPixel*)&Section[y * SrcPitch + 4 * x]= P;
			}
		}
 
		// Blending function (required by AlphaBlend)
		BLENDFUNCTION Blend;
		Blend.BlendOp = AC_SRC_OVER;
		Blend.BlendFlags = 0;
		Blend.AlphaFormat = AC_SRC_ALPHA; 
		Blend.SourceConstantAlpha = 0xff; 
 
		// Blit with blending
		AlphaBlend(
			hDC, 0, 0, (int)(Width * Zoom), (int)(Height * Zoom), 
			hMemoryDC, 0, 0, Width, Height, 
			Blend);
 
		SelectObject(hMemoryDC, Save);
		DeleteObject(hBitMap);
		DeleteObject(hMemoryDC);
  Permalink  
v6

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 OriginalGriff 304
1 Maciej Los 285
2 Sergey Alexandrovich Kryukov 230
3 Shweta N Mishra 186
4 Aajmot Sk 153
0 OriginalGriff 7,660
1 Sergey Alexandrovich Kryukov 7,072
2 DamithSL 5,604
3 Manas Bhardwaj 4,986
4 Maciej Los 4,760


Advertise | Privacy | Mobile
Web02 | 2.8.1411023.1 | Last Updated 4 Jun 2013
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100