我几十年来一直设法避免使用 Windows GDI,现在我付出了代价。以下 C++ 代码不会产生正确的颜色。它只是应该对窗口进行白色填充,然后对单个位图进行 alpha 混合。所有 alpha 都是位图中每个像素的 alpha。
// Create a memory DC
HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmMem = CreateCompatibleBitmap(hdc, cxWnd, cyWnd);
SelectObject(hdcMem, hbmMem);
// White-fill the BG
FillRect(hdcMem, &rectWnd, static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)));
// Alpha blend the bitmap into the 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, x, y, cxBmp, cyBmp, hdcSrc, 0, 0, cxBmp, cyBmp, bfn);
SelectObject(hdcSrc, hbmOld);
DeleteDC(hdcSrc);
// Blit the memory DC to the screen
BitBlt(hdc, 0, 0, cxWnd, cyWnd, hdcMem, 0, 0, SRCCOPY);
我已验证所有变量值均正确,并且
hbm
中的位图具有正确的像素颜色和 Alpha。
结果显示了许多错误的颜色,例如,具有低 alpha 的蓝色像素应该是浅蓝色,但实际上是深红色。具有高 Alpha 的像素更接近应有的像素。
任何帮助表示赞赏。短暂性脑缺血发作。
答案来自评论中的提示:每个像素中的每个颜色通道在混合之前必须预乘 alpha。
get DIB bits
for each pixel
r = r * alpha / 255
g = g * alpha / 255
b = b * alpha / 255
set DIB bits
MS 并没有让这些东西变得容易找到。在我能找到的唯一 alpha 混合示例中没有任何提示:
https://learn.microsoft.com/en-us/windows/win32/gdi/alpha-blending-a-bitmap