2016-11-24 41 views
3

我在Direct2D中绘制位图。位图使用透明度(alpha通道)。Direct2D - 如何用位图做伽马校正透明(alpha)

混合看起来不对。

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

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

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

Direct2D可以显示透明度吗?我会怎么做?任何帮助赞赏。

Direct2D vs Gamma-correct blend

+0

我想你已经倒退了。在sRGB中,50%会看起来像黑色和白色之间的中途(亮度,挺)。它看起来太亮还是太暗?这可能是由于它显示的方式。 –

+0

我的理解是sRGB色彩空间定义了像素强度与实际存储数之间的非线性转换。即伽玛曲线。 例如,一个8位颜色值的范围为0-255,但由于伽马曲线的原因,在大约20%的亮度下显示值127(半途)。 因此,伽玛校正50%黑白混合的像素值应为186(满量程的73%)。所以在Direct2d中,我的混合看起来太黑了。 –

+0

@astraycat如果您查看交替的黑白像素并将它们与固体块进行比较,则BABABA块在正确校准的显示器上应该具有相同的亮度。即使在未校准的显示器上,BABABA也应该比7F7F7F更接近。 –

回答

1

混合以线性色彩空间处理得当,因此对于混合的sRGB像素的过程中,应

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

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

查看PNG规范的alpha channel processing部分。特别要注意的是:

用于计算合成样品值的公式是

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

其中α值与输入和输出的采样值是 表示为范围为0的级分这个计算应该是 用强度样本(非伽玛编码样本)执行

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

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

+0

干杯,这是有道理的(在线性颜色空间中执行混合),但是如何在Direct2D中实现? (也许渲染目标和位图需要设置为特定的像素格式?)。 –

+1

我做了一些研究。 AFAIK Direct2D HWND渲染目标(绘制到屏幕)不支持线性像素格式,并且如果将位图转换为线性格式,则不再支持硬件加速(Direct2D的主要优势)。 DIrect3D(Direct2D基于此)确实支持位图上的操作,从而将像素转换为线性色彩空间并在混合操作期间返回。可惜Direct2D不支持这个。 –

+0

更新:Direct-2D HwndRender目标已被接口\t \t ID2D1DeviceContext取代。这些通过IDXGIFactory2 :: CreateSwapChainForHwnd()创建,并支持更多像素格式,如DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,它可在混合时自动执行正确的色彩空间转换。 –

0

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

忽略gamma会导致合成质量差,几何抗锯齿,图像大小调整和文本呈现。

有一种解决方法,它是“预先扭曲”位图的alpha值以补偿混合计算引入的错误。

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

Direct 2D Renders alpha blends to dark and 'contrasty'

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

UPDATE!:较新版本的直接-2D(1.1)的支持它们执行正确共混SRGB背缓冲器。使用IDXGIFactory2 :: CreateSwapChainForHwnd()来使用改进的颜色深度选项。