【问题标题】:AlphaBlend generating incorrect colorsAlphaBlend 生成不正确的颜色
【发布时间】:2014-08-27 01:22:45
【问题描述】:

几十年来我一直设法避免使用 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 的像素更接近应有的值。

任何帮助表示赞赏。 TIA。

【问题讨论】:

  • AlphaBlend 的一个问题是,当 RGB 与 A 值相乘时,它的工作最正确。 IE。位图不应该有 R > A 或 G > A 或 B > A。由于这种约定,对于 RGBA 完全透明是全零,对于 RGBx 是黑色,因此例如将透明位图粘贴到 Word,并将 Word 文档导出为 PDF,会导致位图应完全透明的黑色区域。
  • 除了你需要做的预乘位图,听起来你的源是 ABGR 顺序的,而 GDI 需要 ARGB 顺序的像素数据。尝试交换每个像素的红色和蓝色值。
  • @JonathanPotter:嗯,我记得那是不正确的。我可能是错的。但我记得COLORREF 格式的布局是为了在小端内存转储中轻松读取为 RGB...。
  • @Jonathan Potter:像素值没问题。我缺少的是预乘法。见下文。谢谢大家。

标签: c++ windows winapi bitmap alphablending


【解决方案1】:

答案,来自 cmets 中的提示:每个像素中的每个颜色通道在混合之前必须预乘 alpha。

get DIB bits
for each pixel
  r = r * alpha / 255
  g = g * alpha / 255
  b = b * alpha / 255
set DIB bits

MS 并不容易找到这些东西。在我能找到的唯一 alpha 混合样本中没有任何提示:

http://msdn.microsoft.com/en-us/library/windows/desktop/dd183353(v=vs.85).aspx

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多