这是我的问题:
我正在使用光谱样本进行渲染,并希望保存显示结果的图像。我通过CIE XYZ色匹配函数对我的光谱功率函数进行加权,以获得XYZ颜色空间结果。我将这个XYZ颜色元组乘以 此页面 给出的用于转换为sRGB的矩阵,并将结果夹紧在
为了保存图像,我将转换后的元组缩放255倍并转换为字节,并将数组传递给libpng的
这是我期望它工作的方式:我将矩阵应用于XYZ,然后得到一个大致能量线性的RGB元组。我将其提高到2.2,现在有了一个感知线性的颜色元组。我按原样编码这些数字(从而有效地利用文件精度),并在文件中存储一个字段,说明“这些字节已使用gamma 2.2进行编码”。然后在图像加载时,解码系统取消应用编码的gamma,然后在显示之前应用系统gamma。(因此从作者的角度来看,我不必关心查看者的系统gamma是什么)。但是我得到的结果表明它不是这样工作的。
更糟糕的是,我尝试使用2.2和1/2.2调用
我正在使用光谱样本进行渲染,并希望保存显示结果的图像。我通过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的矩阵不匹配)-或者何时需要进行这样的转换。我找到的大部分文献都略过了这些细节。是否还有其他未在维基文章中提及的转换步骤,或者这将被自动处理?