How to generate a monochrome bit mask for a 32bit bitmap

You can't do it if there is an alpha channel. COLORREF's use the top 8 bits for a number of purposes, including specifying wether or not the lower 3 bytes are a color table index into the current palette, or a RGB triplet. As such you can't specify anything except 0x00 in the upper byte of clrTransparency.

If you have an alpha bitmap then, to GDI that remains "unaware" of the alpha channel, theres no sane way to actually compare a 24bit BkColor with 32bit pixels in the bitmap.

I would expect GDI to treat the alpha channel in 32bpp bitmaps as "Reserved", and only successfully compare pixels where the reserved channel is zero. i.e. your mask color must be fully transparent anyway to have a chance of succeeding. (and, if youve made a legitimate premultiplied bitmap, that implies the RGV values would be zero too, rather constraining your choice of mask colors :P)


Can do :)
As pointed out by 'Chris Becke' above, GDI can compare only if the reserved Alpha channel is zero.
The HBITMAP got from BITMAP::GetHBITMAP() returns an HBITMAP with Alpha Channel all set to 0xFF.
This must be 0x00 for SetBkColor() Comparison to work.
Hence, the Soln: Loop through each pixel and set the Alpha Component to Zero.

Bitmap img(L"X.bmp");
HBITMAP hBM;
img.GetHBITMAP(Color::White, &hBM);
BITMAP bm;
GetObject(g_hbmBall, sizeof(BITMAP), &bm);
for(UINT i = 0, n = -1; i < bm.bmHeight; i++)
    for(UINT j = 0; j < bm.bmWidth; j++)
    {
        n += 4; // Once per Pixel of 4 Bytes
        ((LPBYTE)bm.bmBits)[n] = 0;
    }
// Now SetBkColor and BitBlt will work as expected

The method that worked for me was to convert the bitmap from 32 bit to 24 bit first.

1. CreateCompatibleDC
2. CreateDIBSection with 24 as the biBitCount.
3. SelectObject
4. BitBlt from 32bit DC to 24 bit. This removes alpha.
5. BitBlt from 24 bit DC to the monochrome DC works as expected.

On my machine this executes faster than the double loop from Ujjwal's answer.