← 探索新知
ASTERXOR / 探索新知

平均两种颜色,为什么中间反而发暗

图像保存的数字,通常不与屏幕应该发出的光成正比。

上条在编码值中插值;下条在线性光中插值,再编码。
上条在编码值中插值;下条在线性光中插值,再编码。
探索新知ASTERXOR / LEON LEUNG

黑与白的正中间,应该是128吗?

在八位图像里,128似乎理所当然是中点。但sRGB值是经过编码的指令,不是直接的光测量。平均指令,与平均它们代表的光,可能得到不同结果。淡入淡出、透明边缘和图像缩放都会碰到这个区别。

一半的编码值,不是一半的光。
THE IDEA

数字里面藏着一条曲线

sRGB使用非线性传递函数,把线性光值变成保存的数值。接近黑色时,它有一小段线性部分;其他区域则遵循幂函数形状。这样可以在整个范围内分配不同的数值精度。人们常把问题简称为伽马,但精确的sRGB函数并不是单一幂律。

本文把线性光归一化:零代表黑,一代表模型的参考白。这没有指定屏幕的物理亮度。0.5意味着参考线性光分量的一半,不是某个通用的每平方米坎德拉数。

上条在编码值中插值;下条在线性光中插值,再编码。
FIG 01上条在编码值中插值;下条在线性光中插值,再编码。
THE MODEL

两种不同的中点

取一个黑像素和一个白像素,直接平均编码值会得到0.5。用sRGB传递函数解码,线性光值约为0.214。因此,虽然保存的数字处在两个端点正中间,它只代表约21.4%的参考光水平。

另一种做法是先解码端点,平均线性值,再重新编码。一半的光变成约0.735的sRGB值,也就是八位尺度上的188左右。两种运算都产生了中点,但属于不同空间。只有后者符合这里所说的等量光混合。

THE RESULT

渐变条揭示了选择

两条渐变有相同的黑白端点。编码值渐变在保存数值中等步长前进;线性光渐变则让光贡献等步长变化,再编码。在正常解释sRGB的显示器上,后者的中部会明显更亮。

两者都不保证感知上的均匀步长。人的明度判断受环境和适应影响,感知色彩空间服务于不同目标。当操作本意是混合光时,线性光计算合适;设计师若想做视觉上均匀的配色,可能有意采用另一种空间。

sRGB 0.5解码为约0.214线性光;一半线性光编码为约0.735。
FIG 02sRGB 0.5解码为约0.214线性光;一半线性光编码为约0.735。
THE TRADE-OFF

颜色也遇到同样问题

红绿示例中,直接平均编码值得到(0.5, 0.5, 0)。先平均对应的线性分量再编码,则约为(0.735, 0.735, 0)。第二种更亮,因为显示编码之前,各通道保留了预期的光贡献。

这并不是颜料混色。颜料会吸收和散射照明光谱中的部分成分,减色材料的混合遵循不同物理过程。三个数也不能唯一识别所有真实光谱分布。这里是基于sRGB假设的加色RGB演示,不评价任何显示器的原色或校准。

在sRGB假设下,用两种算术规则混合红与绿。
FIG 03在sRGB假设下,用两种算术规则混合红与绿。
IN PRACTICE

透明边缘继承了这套算术

假设黑底上的白色形状覆盖半个像素。若把覆盖率理解为光混合权重,线性合成应得到一半的白光。把编码中点当成答案,会让边界变暗。缩小图像时平均多个像素,或混合图层时,也可能遇到类似问题。

真实软件会明确或隐含地选择工作色彩空间、透明度表示方式和输出转换。仅写着RGB,并不能说明这些选择。判断结果之前,应确认值是编码的还是线性的,以及操作是为了模拟光,还是为了特定艺术效果。

LOOK AGAIN

解码,运算,再编码

实用流程很短:先把编码分量转换为线性光,完成基于光的计算,再转换回来用于保存或显示。不要把转换重复应用两次。文件和应用也需要正确的色彩空间信息,让下一个环节知道数字该怎么解释。

这不意味着所有偏暗的混合都是软件故障,而是说算术本身有含义。如果目标是让光等量贡献,直接平均编码值回答的就是另一个问题。把空间说明白,隐藏的选择才能被检查。

留一个想法带走

平均两种颜色之前,先弄清它们的数字在计量什么。