AlphaBlend和16位颜色模式

时间:2014-08-12 19:50:14

标签: windows graphics alphablending

Win32图形不是我的演出,但我必须做一些alpha混合。以下代码在32位颜色模式下工作正常,但在16位模式下除了白色背景外不显示任何内容。对不起,但我不知道它出了什么问题。这和我一样紧凑。

hbm是一个32位ARGB位图,每像素alpha变化,大小为16x16(所以,cx = cy = 16)。

// Create a memory DC to construct the bits
HDC hdc = GetDC(hWnd);
HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmMem = CreateBitmap(cx, cy, 1, 32, NULL);
SelectObject(hdcMem, hbmMem);

// Fill the BG
RECT rc = { 0, 0, cx, cy };
FillRect(hdcMem, &rc, (HBRUSH)GetStockObject(WHITE_BRUSH));

// Get the bitmap bits
BITMAPINFO bmi;
ZeroMemory(&bmi, sizeof(bmi));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = cx;
bmi.bmiHeader.biHeight = cy;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biCompression = BI_RGB;
std::unique_ptr<BYTE[]> pvBits(new BYTE[cx * cy * 4]);
GetDIBits(hdcMem, hbm, 0, cy, reinterpret_cast<void*>(pvBits.get()), &bmi, DIB_RGB_COLORS);

// Premultiply all color channel values by the per-pixel alpha.
int ctPixels = cx * cy;
BYTE *prgba = pvBits.get();
for (int i = 0; i < ctPixels; ++i)
    {
    int alpha = *(prgba + 3);
    for (int j = 0; j <= 2; ++j)
        {
        int k = *prgba;
        *prgba++ = k * alpha / 255;
        }
    ++prgba;
    }

// Put the new bits back
SetDIBits(hdcMem, hbm, 0, cy, reinterpret_cast<void*>(pvBits.get()), &bmi, DIB_RGB_COLORS);

// Alpha blend into memory DC
HDC hdcSrc = CreateCompatibleDC(hdcMem);
HBITMAP hbmOld = static_cast<HBITMAP>(SelectObject(hdcSrc, hbm));
BLENDFUNCTION bfn = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
AlphaBlend(hdcMem, 0, 0, cx, cy, hdcSrc, 0, 0, cx, cy, bfn);
SelectObject(hdcSrc, hbmOld);
DeleteDC(hdcSrc);

// Blit the memory DC to the screen
BitBlt(hdc, 0, 0, cx, cy, hdcMem, 0, 0, SRCCOPY);

我对CreateCompatibleDC有一些模糊的怀疑,但除此之外我还是盲目的。

任何帮助表示赞赏。 TIA。

1 个答案:

答案 0 :(得分:1)

根据Microsoft's documentation每像素,alpha值仅支持32位位图。如果使用16位颜色的显示器和16位DDB没有空间来存储alpha值,SetDIBits会将32位DIB转换为16位DDB。您必须将bfn.SourceConstantAlpha设置为您的Alpha值才能使其生效。在这种情况下,您也不需要预先计算位图。