【发布时间】:2015-03-05 16:34:21
【问题描述】:
当使用glReadPixels 保存图像时,颜色会在其 alpha 值小于 1 的位置出现失真。
表面由 QtQuick 管理。使用glGetInteger,我发现每个通道都有 8 位,包括 alpha。
使用这样的方法,我可以获得更好的结果,但并不完美:
for x := 0; x < m.Bounds().Dx(); x++ {
for y := 0; y < m.Bounds().Dy(); y++ {
c := m.RGBAAt(x, y)
w := float64(c.A) / 255
c.R = uint8(float64(c.R)*w + 255*(1-w) + 0.5)
c.G = uint8(float64(c.G)*w + 255*(1-w) + 0.5)
c.B = uint8(float64(c.B)*w + 255*(1-w) + 0.5)
c.A = 255
m.SetRGBA(x, y, c)
}
}
我尝试使用以下方法清除 OpenGL 本身中的 alpha 组件:
s.gl.ClearColor(0, 0, 0, 1)
s.gl.ColorMask(false, false, false, true)
s.gl.Clear(GL.COLOR_BUFFER_BIT)
现在的结果与我的手动构图相似,而且显示和捕获的图像相同,但仍然与之前显示的不同(并且比之前显示的更暗)。
我对 OpenGL/Qt 在显示颜色缓冲区时如何使用 alpha 通道感兴趣。也许 QtQuick 用一个支持层来组合它?
【问题讨论】:
-
您熟悉预乘 alpha 吗?您的解决方案基于它(尽管有一些我无法解释的多余细节)。但是,如果您不确定它为什么会起作用,我会觉得您可能不会。
-
不,我没有。感谢您为我指明正确的方向。如果我理解正确,我必须将图像与白色背景混合。但为什么?无论如何,我尝试了一些东西,考虑到 glReadPixels 的输出是预乘的,但我仍然无法得到精确的结果。另外,为什么这是预乘?你能帮我找到相关的文件吗?谢谢。
-
比如标签的颜色(RGBA 133,30,30,159)怎么会变成白色(RGB 255,255,255)?
-
最常用的预乘 alpha 用于 alpha 合成。预乘 alpha 混合是关联的,它允许更多的灵活性。它还避免了过滤透明像素的问题;在非透明像素之间进行插值时,具有 0 alpha 的像素应忽略其 RGB 颜色。提前将 RGB 乘以 A 可以在数学上实现这一点,而不是使用像
if (alpha == 0.0) ...这样愚蠢的东西。至于颜色,如果使用预乘 alpha 存储帧缓冲区,那么您应该能够简单地将 RGB 除以 A 以获得正确的颜色。 -
不是这样:在上面的例子中,133,30,30,159 应该变成 255,255,255。一定有别的东西。