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.
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;
HDC hMemoryDC= CreateCompatibleDC(hDC);
byte* Section;
HBITMAP hBitMap = CreateDIBSection(MemoryDC, (BITMAPINFO*)&BufferInfo, DIB_RGB_COLORS, (void**)&Section, NULL, 0x0);
HGDIOBJ Save= SelectObject(hMemoryDC, hBitMap);
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; 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;
}
}
BLENDFUNCTION Blend;
Blend.BlendOp = AC_SRC_OVER;
Blend.BlendFlags = 0;
Blend.AlphaFormat = AC_SRC_ALPHA;
Blend.SourceConstantAlpha = 0xff;
AlphaBlend(
hDC, 0, 0, (int)(Width * Zoom), (int)(Height * Zoom),
hMemoryDC, 0, 0, Width, Height,
Blend);
SelectObject(hMemoryDC, Save);
DeleteObject(hBitMap);
DeleteObject(hMemoryDC);