这是我的问题:
我正在使用光谱样本进行渲染,并希望保存显示结果的图像。我通过CIE XYZ颜色匹配函数对光谱功率函数进行加权,以获得XYZ颜色空间结果。我将此XYZ颜色元组乘以this page给出的矩阵以转换为sRGB,并将结果钳制到(0,1)
。
要保存图像,我将转换后的元组缩放255并将其转换为字节,然后将数组传递给libpng的png_write_image()
。当我看到均匀的强度,以这种方式渲染的纯色光谱时,它看起来是错误的;颜色之间的过渡中有暗带。这也许并不奇怪,因为要从XYZ转换为sRGB,矩阵乘法后的颜色分量must be raised to 2.4(或者如果它们足够小则线性缩放)。但如果我这样做,它看起来更糟!只有在提高到1 / 2.2后才会开始向右看。看起来,在我没有做任何事情的情况下,解码的图像具有~2.2的伽马值两次。
这是我期望它的工作方式:我将矩阵应用于XYZ,并且我有一个大致能量线性的RGB元组。我把它提高到2.2,现在有一个感知线性颜色元组。我按原样编码这些数字(从而有效地利用文件精度),并在文件中存储一个字段,表示“这些字节已经用gamma 2.2编码”。然后在图像加载时,解码系统取消应用编码的伽马,然后在显示之前应用系统伽玛。 (因此从创作的角度来看,我不应该关心观众的系统伽玛是什么)。但我得到的结果表明它不会这样。
更糟糕的是,我尝试使用2.2和1 / 2.2调用png_set_gAMA()
并且看不到图像的差异。我得到与png_set_sRGB()
类似的结果(我相信应该将伽玛强制为1 / 2.2)。
对于我应该如何转换颜色值,或者PNG如何处理伽玛和颜色空间,必须有一些我反向或不理解的东西。将此分解为几个澄清问题:
write_png()
的字节值的颜色空间是什么?此外,我看到提示“白点”在XYZ和sRGB之间的转换中很重要。我不清楚上面给出的网站中的矩阵是否包括对D65的重整化(它与维基百科的矩阵不匹配) - 或者甚至在需要这样的转换时。我发现的大部分文献都掩盖了细节。在维基文章中没有提到转换中的另一个步骤,还是会自动处理?
答案 0 :(得分:1)
你说:
<块引用>因为要从XYZ转换为sRGB,矩阵相乘后颜色分量必须提升到2.4...
不,这是不正确的。从线性 (XYZ) 到 sRGB,你不提高到 2.4 或 2.2,即从 sRGB 到线性。 >
从线性到 sRGB,你提高到 ^(1/2.2)
或者如果使用 sRGB 分段,你会看到 1/2.4 — 你应用的有效伽玛是 ^0.45455
在您链接的维基百科页面上,这是FORWARD 转换。
那当然是在应用了正确的矩阵之后。假设一切都在 D65 中,那么:
现实世界中的光是线性的。如果将 100 个光子增加三倍,那么您将拥有 300 个光子。但人眼看不到三倍,相比之下,我们只能看到适度的增加。
这就是为什么要使用传输曲线或“伽马”的部分原因,以充分利用 8 位图像中的可用代码空间(我知道是过度简化了)。
为此,将线性光值提高到 0.455 的次方,然后将该 sRGB 值恢复到线性空间,然后我们将其提高到相反值,即 ^1/0.455,也称为 ^2.2< /p>
矩阵的使用必须在线性空间中完成。但是在传输矩阵之后,您需要应用 trc 或“伽马”编码。根据您的陈述,不,事情并没有将 2.2 添加两次,您只是走错了路。
答案 1 :(得分:0)
这几乎是你期望的方式。 png_set_gAMA()使libpng编写gAMA 输出PNG文件中的块。它不会改变像素本身。符合png标准 观察者应该使用来自块的伽马值,结合显示器的伽玛,在显示器上正确地写入像素强度值。大多数解码器实际上不会执行您描述的两步(不应用图像伽玛,然后应用系统伽玛)方法,尽管结果在概念上是相同的:它将图像伽马与系统伽玛组合以创建查找表,然后使用该表一步转换像素。
根据您观察到的情况(gamma = 2.2和gamma = 1 / 2.2表现相同),您似乎使用的查看器对PNG gAMA块数据没有任何作用。
答案 2 :(得分:0)
您写道:&#34;看起来,在我没有做任何事情的情况下,解码图像的伽玛值为~2.2两倍。 &#34;
我认为你的显示器(hardwrare或你的系统icc配置文件)已经有了伽玛设置。