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

后端 未结 4 1214
情书的邮戳
情书的邮戳 2020-12-30 10:34

Under Win32, it is a common technique to generate a monochrome bitmask from a bitmap for transparency use by doing the following:

SetBkColor(hdcSource, clrTr         


        
相关标签:
4条回答
  • 2020-12-30 11:11

    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
    0 讨论(0)
  • 2020-12-30 11:16

    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.

    0 讨论(0)
  • 2020-12-30 11:35

    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)

    0 讨论(0)
  • 2020-12-30 11:36

    An alternate method would be to scan the pixels yourself and generate and monochrome bitmap based on the source color (or source alpha versus a threshold).

    Note that if you're using GDI+, then, depending on the operation, the pixels may have been antialiased, resulting in none of them being an exact match for your "transparent" color.

    0 讨论(0)
提交回复
热议问题