Direct2D - 如何使用位图进行伽马校正透明度 (alpha)

Direct2D - How to do gamma-correct transparency (alpha) with bitmaps

我在 Direct2D 中绘制位图。位图利用透明度(alpha 通道)。

混合看起来不对。

作为测试,我加载了一张透明度为 50% 的纯黑色 png 图像,并将其绘制在白色背景上。结果是红色、绿色和蓝色值为 127 (0x7F7F7F) 的像素。这表明 Direct2D 的混合忽略伽玛并将颜色值视为线性。

(位图使用常规 sRGB 颜色 space,每像素 32 位,红色、绿色、蓝色和 Alpha 各 8 位)。它们以 GUID_WICPixelFormat32bppPBGRA 格式加载。

在 sRGB 中,黑色和白色之间的中间混合是 186 (0xBABABA)。这就是我想要的理想结果。

Direct2D 可以根据伽玛显示透明度吗?我该怎么做?任何帮助表示赞赏。

线性颜色混合正确space,所以混合 sRGB 像素的过程应该是

  1. 转换为线性
  2. 混合
  3. 转换回 sRGB。

请注意,对于黑色或白色像素,步骤 (1) 和 (3) 是空操作,可以省略。

请参阅 PNG 规范的 alpha channel processing 部分。特别要注意这一点:

The equation for computing a composited sample value is

output = alpha * foreground + (1-alpha) * background

where the alpha value and the input and output sample values are expressed as fractions in the range 0 to 1. This computation should be performed with intensity samples (not gamma-encoded samples)

该部分包含用于 alpha 通道处理的示例 C 代码

提出这个问题时,HWND 渲染目标(绘制到屏幕)不支持线性像素格式;但是,Direct-2D HwndRender 目标现在已被接口 ID2D1DeviceContext 取代。这些是通过 IDXGIFactory2::CreateSwapChainForHwnd() 创建的,支持更多像素格式,如 DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,它在混合时自动执行正确的颜色-space 转换(信息由@Jeff McClintock 提供)。

Direct-2D 1.0 HwndRenderTarget 直接对像素值执行混合计算。这会导致使用 alpha 通道合成标准 sRGB 图像时出错。该错误是因为 Direct 2D 将伽马压缩强度值视为线性强度值。

忽略 Gamma 会导致低质量的合成、几何抗锯齿、图像大小调整和文本渲染。

有一个解决方法,即 'pre-warp' 位图的 alpha 值来补偿混合计算引入的错误。

示例: 左边的图像是通过在线性色彩空间中执行混合的正确合成,中间图像是 Direct 2D(阴影太暗并且 'contrasty'),右边的图像是预扭曲 alpha 通道后的 Direct2D。

参见:https://bel.fi/alankila/lcd/alpcor.html

更新!:较新版本的 Direct-2D (1.1) 支持正确执行混合的 SRGB 后台缓冲区。使用 IDXGIFactory2::CreateSwapChainForHwnd() 以使用改进的颜色深度选项。