如何处理PNG文件格式中的色彩空间和伽马?

4
这是我的问题:
我正在使用光谱样本进行渲染,并希望保存显示结果的图像。我通过CIE XYZ色匹配函数对我的光谱功率函数进行加权,以获得XYZ颜色空间结果。我将这个XYZ颜色元组乘以 此页面 给出的用于转换为sRGB的矩阵,并将结果夹紧在(0,1)之间。
为了保存图像,我将转换后的元组缩放255倍并转换为字节,并将数组传递给libpng的png_write_image()。当我以这种方式渲染均匀强度、纯色光谱时,它看起来不对劲;在颜色之间的过渡中有黑色条纹。这也许并不奇怪,因为从XYZ转换到sRGB时,颜色分量必须在矩阵乘法之后被提高到2.4(或者如果它们足够小,则线性缩放)。但是如果我这样做,它看起来会更糟糕!只有在提高到1/2.2之后,它才开始看起来正确。似乎在我没有做任何事情的情况下,解码图像应用了约2.2的gamma 两次
这是我期望它工作的方式:我将矩阵应用于XYZ,然后得到一个大致能量线性的RGB元组。我将其提高到2.2,现在有了一个感知线性的颜色元组。我按原样编码这些数字(从而有效地利用文件精度),并在文件中存储一个字段,说明“这些字节已使用gamma 2.2进行编码”。然后在图像加载时,解码系统取消应用编码的gamma,然后在显示之前应用系统gamma。(因此从作者的角度来看,我不必关心查看者的系统gamma是什么)。但是我得到的结果表明它不是这样工作的。
更糟糕的是,我尝试使用2.2和1/2.2调用png_set_gAMA(),但图像没有任何区别。我使用png_set_sRGB()也获得类似的结果(我认为应该强制gamma为1/2.2)。 对于如何转换我的颜色值或PNG如何处理gamma和颜色空间,必须有一些我理解错误的地方。为了澄清问题,可以分解为以下几个问题:
  • 我需要传递给write_png()的字节值所对应的颜色空间是什么?
  • 为了确保正确显示,必须通过哪些调用来指定传递的字节的颜色空间和伽马值,它们可能会失败吗?
  • png文件中的伽马字段与我已应用于传递的颜色通道值的指数有何关系(如果有)?
  • 如果我需要在发送图像数据之前反转伽马曲线(这点我还有疑问,但现在看起来似乎必要),那么是否应该包括sRGB曲线的线性部分?

此外,我看到提示,XYZ和sRGB之间的转换中“白点”很重要。我不清楚上述网站的矩阵是否包括对D65的重新归一化(它与Wikipedia的矩阵不匹配)-或者何时需要进行这样的转换。我找到的大部分文献都略过了这些细节。是否还有其他未在维基文章中提及的转换步骤,或者这将被自动处理?


可能有用的链接:https://hsivonen.fi/png-gamma/ 和 http://morris-photographics.com/photoshop/articles/png-gamma.html - leonbloy
3个回答

1
这基本上是您所期望的方式。png_set_gAMA()会导致libpng在输出PNG文件中写入gAMA块。它不会改变像素本身。一个符合png标准的查看器应该使用从块中获得的伽马值,与显示器的伽马值相结合,在显示器上正确地写入像素强度值。大多数解码器实际上不会执行您描述的两步(取消应用图像伽马,然后应用系统伽马)方法,尽管结果在概念上是相同的:它将组合图像伽马和系统伽马以创建查找表,然后使用该表将像素转换为一步。从您观察到的情况来看(gamma=2.2和gamma=1/2.2表现相同),似乎您正在使用一个不对PNG gAMA块数据做任何处理的查看器。

1
你说:
因为从XYZ到sRGB的转换,在矩阵乘法之后,颜色分量必须升高到2.4...
不,这是不正确的。从线性(XYZ)到sRGB,你不需要升高到2.4或2.2,这是用于从sRGB到线性的。
从线性到sRGB,你需要升高到^(1/2.2),或者如果使用sRGB分段函数,则会看到1/2.4 - 你应用的有效伽马值为^0.45455。
在你链接的维基百科页面上,这是正向变换。
从XYZ到sRGB:

sRGB Forward TRC math

当然,前提是应用了正确的矩阵。假设一切都在D65下,那么:

enter image description here

线性的直白谈

在现实世界中,光是线性的。如果你把100个光子三倍,那么你就有了300个光子。但人眼看不到三倍增加,我们只能看到相对较小的增加。

这部分原因是为什么转换曲线或“伽马”被使用,以利用8位图像中可用的代码空间(我知道这是过度简化)。

为了做到这一点,线性光值被提高到0.455的幂,并且为了将sRGB值恢复到线性空间,然后我们将其提高到反向的幂,即^1/0.455,也称为^2.2

矩阵的使用必须在线性空间中完成。但在经过矩阵变换后,需要应用trc或“gamma”编码。根据您的陈述,不,事物并没有添加两次2.2,您只是走错了路。


0
你写道:“似乎在我没有做任何事情的情况下,解码后的图像已经应用了大约2.2的伽马两次。”
我认为你的显示器(硬件或系统ICC配置文件)已经有一个伽马设置。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接