数字影像与视频中的传递函数转换

定义、换算数学、失配机制、历史成因、浏览器行为与判别方法

调研截止日期: 2026 年 8 月 7 日
目标读者: 色彩科学、编解码与视频链路、浏览器/图形实现、调色与母版制作工程师
配套文件: 英文版以及可复算的 NumPy 脚本另行提供。


证据分级与符号约定

本文对每一项实质性的历史或技术结论标注来源类别:

正文中的 [A-04] 等编号指向 §11.4 的分类参考文献。凡无法由一手来源支持的精确历史说法,本文均明确写出证据限制。

除非另有说明:

文中数值表均以双精度计算。每张表下都重新说明了精确公式与假设,并在 gamma-analysis-repro.py 中实现。


1. 引言:为什么同一份素材看起来会不一样

文件本身并不以自足的方式包含“亮度”。它包含的是码值,以及有时存在的、关于这些码值含义的声明。最终图像由如下链路共同产生:

场景光
  -> 相机/场景编码
  -> RGB 或 Y'CbCr 表示
  -> 量化与合法范围
  -> 编码码流
  -> 容器元数据
  -> 解码与色彩转换
  -> 应用程序工作空间
  -> 特效、缩放、合成、tone mapping
  -> 操作系统合成器与显示配置文件
  -> 显示器 EOTF 与观看环境
  -> 最终感知外观

这条链中任何位置的差异,都可能被口头统称为“gamma shift”,即使真实错误其实是仿射的范围重映射、BT.601/BT.709 矩阵混用、显示配置文件转换、HDR tone mapper、色度重采样相位错误,或者直接在非线性样本上进行算术。正是这种宽泛用词,使这个问题长期混乱。

因此最有用的工程原则是:

不要仅凭外观诊断 gamma 错误。先确定信号域、元数据、范围、矩阵、传递函数、色度原色、工作空间、输出变换和显示路径。

真正的传递函数失配,会在对应样本之间形成特征性的非线性关系。full/limited range 混淆会形成特征性的仿射关系。矩阵混淆会以依赖颜色方向的方式改变颜色。tone mapping 往往依赖内容和亮度,无法用单一标量指数表示。这些差异都可以测量。

1.1 经常被混成一个问题的四个问题

  1. 场景光是怎样被编码的? 这是光电转换函数(opto-electronic transfer function, OETF)或其他 scene-to-code 变换。
  2. 给定码值时,参考显示器应发出多少光? 这是电光转换函数(electro-optical transfer function, EOTF)。
  3. 场景光与显示光之间意图实现怎样的呈现关系? 这是光光转换函数(opto-optical transfer function, OOTF)。
  4. 软件实际上对存储样本做了什么算术? 这种算术甚至可能完全没有色度学意义。

本文其余部分始终把这四个问题分开。

1.2 失配的分层模型

层级 正确的问题 常见误诊
编码 样本由哪一个 OETF/编码曲线产生? “这个文件是 gamma 2.2。”
信号表示 RGB、Y′CbCr、constant-luminance、ICtCp? “Y 就是亮度。”
量化 Full 还是 narrow range;位深;headroom/footroom? “对比度/gamma 变了。”
元数据 CICP/VUI、colr、ICC、PNG chunk 声明了什么? “编码器改了像素。”
处理 运算是在码值空间还是线性光中完成? “缩放器把画面变暗了。”
呈现 使用哪个 EOTF、OOTF、tone map、显示配置文件、surround? “显示器 gamma 错了。”

2. 概念地基:OETF、EOTF、OOTF 与 system gamma

2.1 严格定义

ITU-R BT.2100-3 对这些术语作如下定义 [A-07, Annex 1]:

对于一条由一个 OETF 直接馈入一个 EOTF 的参考链路:

OOTF=EOTFOETF. \operatorname{OOTF} = \operatorname{EOTF}\circ\operatorname{OETF}.

反过来,在给定 EOTF 上实现目标 OOTF 所需的 OETF 可以写为:

OETF=EOTF1OOTF. \operatorname{OETF} = \operatorname{EOTF}^{-1}\circ\operatorname{OOTF}.

这正是为什么 EOTF 一般不等于相机 OETF 的逆函数。逆 OETF 恢复的是 scene-referred 线性值;EOTF 产生的是 display-referred 线性光。两者终点不同。

2.2 为什么“gamma = 2.2”通常是不完整的说法

这句话至少可能指六种不同事物:

  1. 纯解码幂律 L=V2.2L=V^{2.2}
  2. 编码幂律 V=L1/2.2V=L^{1/2.2}
  3. 显示校准目标;
  4. 对 sRGB 传递函数的粗略描述;
  5. 端到端有效指数;
  6. 某个参数实际按 1/γ1/\gamma 使用的软件控制,例如 AviSynth/VapourSynth 的 Levels

只有前两项能无歧义地指定一个数学函数;即使如此,也仍需声明黑白归一化、裁剪行为、负值处理和定义域。sRGB 不是纯 2.2 幂律。当 LB>0L_B>0 时,BT.1886 不是纯 2.4 幂律。BT.709 是带线性 toe 与带偏移幂分支的 OETF,不是“gamma 0.45”。PQ 不能由单个 gamma 有意义地描述。HLG 则由 OETF 加一个随峰值亮度变化的显式 OOTF 构成。

2.3 编码 gamma、显示 gamma 与 system gamma

在纯幂函数这个特例中:

E=Egc,FD=(E)gd, E'=E^{g_c}, \qquad F_D=(E')^{g_d},

其中 gc<1g_c<1 是相机/编码指数,gd>1g_d>1 是显示指数。那么:

FD=Egcgd, F_D=E^{g_cg_d},

因此系统 gamma(system gamma)gs=gcgdg_s=g_cg_d

另一种记号把编码“gamma”写成 γc=1/gc\gamma_c=1/g_c。在这种记号下,同一个系统指数是 gs=gd/γcg_s=g_d/\gamma_c。混用这两套约定,是修正方向颠倒的常见原因。

对于真实电视曲线,复合结果并非严格幂律,因此“system gamma”表示的是呈现意图,或者局部/拟合斜率,而不是对所有信号电平都成立的恒等式。

2.4 BT.709 OETF 加 BT.1886 EOTF:为什么约 1.2 是设计意图而非缺陷

BT.709-6 规定了如下源端 OETF [A-03, Part 1, item 1.2]:

E={4.5E,0E<0.018,1.099E0.450.099,0.018E1. E' = \begin{cases} 4.5E, & 0\le E<0.018,\\ 1.099E^{0.45}-0.099, & 0.018\le E\le1. \end{cases}

若采用理想黑位的 BT.1886 显示器,则归一化 EOTF 为 FD=(E)2.4F_D=(E')^{2.4}。因此精确复合为:

FD={(4.5E)2.4,E<0.018,(1.099E0.450.099)2.4,E0.018. F_D= \begin{cases} (4.5E)^{2.4}, & E<0.018,\\ (1.099E^{0.45}-0.099)^{2.4}, & E\ge0.018. \end{cases}

不是 E0.45×2.4=E1.08E^{0.45\times2.4}=E^{1.08},因为 BT.709 的幂分支包含偏移。其局部 log-log 斜率为:

glocal(E)=dlnFDdlnE=2.41.0990.45E0.451.099E0.450.099(E0.018). g_{\mathrm{local}}(E)=\frac{d\ln F_D}{d\ln E} =2.4\frac{1.099\cdot0.45\,E^{0.45}} {1.099E^{0.45}-0.099} \quad(E\ge0.018).

场景线性 EE BT.709 EE' BT.1886 相对输出 局部 log 斜率
0.018 0.081248 0.002419 2.3960
0.020 0.090000 0.003092 2.2680
0.050 0.186453 0.017757 1.6534
0.100 0.290940 0.051657 1.4475
0.180 0.409008 0.116992 1.3414
0.250 0.489940 0.180444 1.2982
0.500 0.705515 0.432927 1.2315
0.750 0.866551 0.709098 1.2034
1.000 1.000000 1.000000 1.1869

计算方法: 直接复合已发布的 BT.709 OETF 与理想黑位 BT.1886,再进行解析求导;未使用拟合。

在高光端,OETF 的有效斜率约为 0.495,而不是 0.45;乘以 2.4 得到 1.187。在信号上半区间进行受约束的 log-domain 拟合,结果约为 1.202。这就是“约 1.2”这一常用工程描述的数学基础。

更重要的是,ITU-R Report BT.2390-12 明确指出,传统 SDR 电视的 OOTF/system gamma 为 1.2,并把它解释为一种呈现意图:补偿在暗或昏暗 surround 中观看自发光屏幕时的感知差异 [A-08, §6.2]。BBC 工程文献同样把有效相机指数描述为接近 0.5、显示指数接近 2.4,合成约 1.2 [L-03]。因此,把 OETF 与 EOTF 不互为逆函数说成标准缺陷,是错误的;非 1 的 OOTF 是有意设计。

toe 区域无法由任何单一 system gamma 良好表示。它反映相机噪声和历史设计约束,不能据此推断整条系统具有 2.4 的 OOTF。

2.5 相对色度学与绝对亮度

多数 SDR RGB 编码是相对的(relative)。归一化值 1 表示 reference white,但数字本身并不说明白色是 80、100、120 还是 200 cd/m²。最终外观取决于显示白、显示黑、surround、flare、适应状态与 OOTF。

PQ 不同。SMPTE ST 2084 与 BT.2100 定义的是绝对 EOTF,其输出单位为 cd/m²,最高到 10,000 cd/m² [A-06, A-07]。PQ 码值不只是“白色的一部分”。HLG 的 OETF 阶段仍然是 scene-relative,并通过显式的 system gamma 与峰值亮度参数获得显示端行为。因此:


3. 传递函数图鉴

3.1 sRGB:IEC 61966-2-1

IEC 61966-2-1:1999 定义了如下分量编码 [A-01; B-01]。对于线性 C[0,1]C\in[0,1]

C={12.92C,C0.0031308,1.055C1/2.40.055,C>0.0031308. C'= \begin{cases} 12.92C, & C\le0.0031308,\\ 1.055C^{1/2.4}-0.055, & C>0.0031308. \end{cases}

解码函数为:

C={C/12.92,C0.04045,(C+0.0551.055)2.4,C>0.04045. C= \begin{cases} C'/12.92, & C'\le0.04045,\\ \left(\frac{C'+0.055}{1.055}\right)^{2.4}, & C'>0.04045. \end{cases}

该标准发表于 1999 年;HP/Microsoft/W3C 的标准前提案可追溯到 1996 年,最终 IEC 常数修正了提案中的一个小舍入问题 [A-01; A-15]。sRGB 使用 BT.709 原色与 D65 白点,但不使用 BT.709 OETF。

“sRGB 约等于 gamma 2.2”究竟是什么意思

定义逐点有效解码指数:

geff(C)=lnClnC. g_{\mathrm{eff}}(C')=\frac{\ln C}{\ln C'}.

在码值 8、16、32、64、128、192 处,该指数分别为 1.739、1.901、2.042、2.149、2.224、2.257。因此,没有任何常数 2.2 能描述 toe 与阴影区域。

若在整个归一化码值区间上,以未加权线性光误差为目标拟合纯幂函数,最小二乘结果约为 2.2333。若仅在 C[0.25,1]C'\in[0.25,1] 上作 log-domain 拟合,结果约为 2.1959。因此,“2.2”是在指定拟合准则下对中高调的有用速记,而不是 sRGB 公式本身。

3.2 纯幂函数 2.2 作为 sRGB 替代时的暗部误差

纯 2.2 解码律为:

C2.2=(C)2.2. C_{2.2}=(C')^{2.2}.

8-bit 码值 sRGB 线性值 纯 2.2 线性值 纯 2.2 − sRGB 相对误差 100-nit 白下的差值
0 0 0 0 0 cd/m²
1 0.000303527 0.000005077 −0.000298450 −98.33% −0.029845 cd/m²
2 0.000607054 0.000023328 −0.000583726 −96.16% −0.058373 cd/m²
4 0.001214108 0.000107187 −0.001106921 −91.17% −0.110692 cd/m²
8 0.002428216 0.000492504 −0.001935712 −79.72% −0.193571 cd/m²
12 0.003676507 0.001201740 −0.002474767 −67.31% −0.247477 cd/m²
16 0.005181517 0.002262953 −0.002918564 −56.33% −0.291856 cd/m²
20 0.006995410 0.003697240 −0.003298170 −47.15% −0.329817 cd/m²
32 0.014443844 0.010397802 −0.004046042 −28.01% −0.404604 cd/m²
64 0.051269458 0.047775754 −0.003493704 −6.81% −0.349370 cd/m²
128 0.215860500 0.219519718 +0.003659218 +1.70% +0.365922 cd/m²
192 0.527115126 0.535641609 +0.008526483 +1.62% +0.852648 cd/m²
255 1 1 0 0% 0 cd/m²

计算方法: 将每个整数码值除以 255,然后分别用精确 sRGB 函数和 V2.2V^{2.2} 解码。相对误差以精确 sRGB 线性光为基准。阴影区的百分比误差很大,但绝对亮度差较小;这两个事实都必须同时考虑。

在连续区间 [0,1][0,1] 上,线性光最大绝对差为 0.00852769,出现在码值约 0.7496 处。对于整数 8-bit 样本,实际后果还取决于后续量化、显示黑位、flare 与空间上下文。

3.3 BT.1886

ITU-R BT.1886-0 于 2011 年 3 月获批,目的在 CRT 参考监视器退出后,为平板 HDTV 制作显示器提供可复现的参考 EOTF [A-04, Scope and Annex 1]。完整形式为:

L=a(max(V+b,0))γ,γ=2.4, L=a\left(\max(V+b,0)\right)^\gamma, \qquad \gamma=2.4,

其中:

a=(LW1/γLB1/γ)γ, a=\left(L_W^{1/\gamma}-L_B^{1/\gamma}\right)^\gamma,

b=LB1/γLW1/γLB1/γ. b=\frac{L_B^{1/\gamma}} {L_W^{1/\gamma}-L_B^{1/\gamma}}.

LB=0L_B=0 时,式子化简为 L=LWV2.4L=L_WV^{2.4};当 LB>0L_B>0 时则不会。例如在 LW=100L_W=100 cd/m² 时:

max 规定了有效黑位偏移以下的行为。BT.1886 还给出 10-bit narrow-range 归一化:V=(D64)/876V=(D-64)/876 [A-04, Annex 1]。

BT.1886 并非要宣称每一台 CRT 都精确等于 2.4。其动机是用一个可移植目标,取代“优秀 CRT 实际做什么就照着做”这种没有文档、依赖设备的经验准则,同时保持与历史参考行为大体等价。

3.4 CRT 的“gamma 2.5”

CRT 的主导非线性来自电子枪/阴极栅极驱动及空间电荷行为,而不是荧光粉发光本身具有非线性 [L-01, L-04]。在有效工作区间内,束流电流可以很好地近似为驱动电压的幂。工程文献常报告经正确调整的 CRT 指数约在 2.35–2.55 之间,并以 2.5 作为代表值 [L-01]。

必须加上三项限定:

  1. 实际指数取决于显像管、cutoff/黑位设置、驱动电路、测量区间与拟合方法;
  2. 早期广播系统并未把所有接收机统一标准化为精确 2.5——历史标称值随电视制式与语境而变化;
  3. CRT 实测响应在近黑区和高驱动区可能偏离单一幂律。

因此,“CRT gamma 2.5”是一个有历史用途的物理近似,不是应附着到所有旧视频上的通用元数据值。

3.5 传统 Macintosh 1.8 系统

早期 Macintosh 的约定,是通过普通 CRT 前的视频查找表(LUT)实现接近 1.8 的有效 code-to-display-light 响应;它并不意味着 Macintosh CRT 的荧光粉具有特殊的物理 1.8 指数 [L-01]。若 CRT 本身约为 2.5,则指数约 1.8/2.50.721.8/2.5\approx0.72 的 LUT 可把整体响应变成约 1.8。

Poynton 记录了它与平面设计和印前工作流的强关系:QuickDraw 码值直接发送到 imagesetter 后,与常见网点/胶印链路约 1.75 次幂的行为能得到尚可的匹配 [L-01]。这支持一种印刷/印前兼容性解释。然而,本次调研没有找到 Apple 一方的设计备忘录,能够证明更狭窄的流行说法——“1.8 是专门为了补偿某一台 LaserWriter 而选择的”。后者应视为未经证实。

Mac OS X 10.6 Snow Leopard 于 2009 年 8 月 28 日发布,并把默认显示 gamma 从 1.8 改为 2.2。Apple 当时的 system refinements 页面称,这一变化更适合数字内容生产者与消费者;原页面已下线,但当时的存档与引文保留了原句 [B-21, C-06]。Apple Newsroom 独立记录了发布日期 [B-20]。

3.6 BT.601、BT.709 与 BT.2020 OETF

BT.601-7 与 BT.709-6 使用同一标称分段 OETF [A-02, §2.6.4; A-03, item 1.2]:

E={4.5E,0E<0.018,1.099E0.450.099,0.018E1. E'=\begin{cases} 4.5E,&0\le E<0.018,\\ 1.099E^{0.45}-0.099,&0.018\le E\le1. \end{cases}

BT.2020-2 把同一形状写为 [A-05, Table 4]:

E={4.5E,0E<β,αE0.45(α1),βE1. E'=\begin{cases} 4.5E,&0\le E<\beta,\\ \alpha E^{0.45}-(\alpha-1),&\beta\le E\le1. \end{cases}

连续系数为:

α=1.09929682680944,β=0.018053968510807. \alpha=1.09929682680944\ldots, \qquad \beta=0.018053968510807\ldots.

BT.2020 的实用表列值,在 10-bit 系统中为 α=1.099,β=0.018\alpha=1.099,\beta=0.018,在 12-bit 系统中为 α=1.0993,β=0.0181\alpha=1.0993,\beta=0.0181。这些差异用于在给定精度下保持连续性与码值行为。因此,这三个标准的传递形状近乎相同,但其原色、矩阵、分辨率与数字表示并不可互换。

3.7 PQ:SMPTE ST 2084 与 BT.2100

PQ 是绝对的 display-referred EOTF。对于归一化 PQ 码值 EE',BT.2100-3 给出 [A-07, Table 4]:

FD=10000Y, F_D=10000Y,

Y=(max(E1/m2c1,0)c2c3E1/m2)1/m1, Y=\left( \frac{\max\left(E'^{1/m_2}-c_1,0\right)} {c_2-c_3E'^{1/m_2}} \right)^{1/m_1},

其中:

m1=2610/16384=0.1593017578125,m2=(2523/4096)×128=78.84375,c1=3424/4096=0.8359375,c2=(2413/4096)×32=18.8515625,c3=(2392/4096)×32=18.6875. \begin{aligned} m_1&=2610/16384=0.1593017578125,\\ m_2&=(2523/4096)\times128=78.84375,\\ c_1&=3424/4096=0.8359375,\\ c_2&=(2413/4096)\times32=18.8515625,\\ c_3&=(2392/4096)\times32=18.6875. \end{aligned}

逆函数为:

E=(c1+c2Ym11+c3Ym1)m2,Y=FD/10000. E'=\left(\frac{c_1+c_2Y^{m_1}}{1+c_3Y^{m_1}}\right)^{m_2}, \qquad Y=F_D/10000.

代表性码值约为:100 cd/m² 对应 0.50808,203 cd/m² 对应 0.58069,1000 cd/m² 对应 0.75183,4000 cd/m² 对应 0.90257。这些不是某个内容自定义白点的比例,而是按参考 EOTF 编码的绝对亮度。

BT.2100 还定义了参考 PQ OOTF,并把参考 PQ OETF 构造为 EOTF1OOTF\operatorname{EOTF}^{-1}\circ\operatorname{OOTF},明确表明 HDR 制作 OETF 不是 PQ EOTF 的简单逆函数 [A-07, Table 4 and Annex 1]。

3.8 HLG

BT.2100-3 定义的 HLG OETF 为 [A-07, Table 5]:

E={3E,0E1/12,aln(12Eb)+c,1/12<E1, E'=\begin{cases} \sqrt{3E},&0\le E\le1/12,\\ a\ln(12E-b)+c,&1/12<E\le1, \end{cases}

其中:

a=0.17883277,b=0.28466892,c=0.55991073. a=0.17883277,\quad b=0.28466892,\quad c=0.55991073.

逆函数为:

E={E2/3,0E1/2,[exp((Ec)/a)+b]/12,1/2<E1. E=\begin{cases} E'^2/3,&0\le E'\le1/2,\\ \left[\exp((E'-c)/a)+b\right]/12,&1/2<E'\le1. \end{cases}

HLG 的参考 OOTF 把系统指数施加到场景亮度,而不是分别施加到每个颜色分量:

FD=αYSγ1E, F_D=\alpha Y_S^{\gamma-1}E,

YS=0.2627RS+0.6780GS+0.0593BS, Y_S=0.2627R_S+0.6780G_S+0.0593B_S,

其中 α=LW\alpha=L_W,且在 LW=1000L_W=1000 cd/m² 时 γ=1.2\gamma=1.2。对于 400 至 2000 cd/m² 的标称峰值 [A-07, note 5f]:

γ=1.2+0.42log10(LW/1000). \gamma=1.2+0.42\log_{10}(L_W/1000).

标称峰值 LWL_W System gamma BT.2408-9 中的 HLG HDR reference white
400 cd/m² 1.03 101 cd/m²
600 cd/m² 1.11 138 cd/m²
800 cd/m² 1.16 172 cd/m²
1000 cd/m² 1.20 203 cd/m²
1500 cd/m² 1.27 276 cd/m²
2000 cd/m² 1.33 343 cd/m²

Gamma 数值由 BT.2100 公式四舍五入至两位小数;reference-white 数值来自 ITU-R BT.2408-9 Table 4 [A-09]。因此,HLG 不存在一个与峰值亮度无关的单一显示 gamma。

3.9 scRGB、Display P3 与 Adobe RGB (1998)

3.10 速查图鉴

编码/显示函数 方向 精确性质 依据
sRGB 线性 ↔︎ 码值 分段线性 + 带偏移 2.4 幂 IEC 61966-2-1:1999
Adobe RGB (1998) 线性 ↔︎ 码值 纯 563/256 解码幂律 Adobe/ICC
BT.601/709 OETF 场景线性 → 码值 4.5 toe + 带偏移 0.45 幂 BT.601-7 / BT.709-6
BT.2020 OETF 场景线性 → 码值 同一形状,α/β 随精度规定 BT.2020-2
BT.1886 码值 → 显示光 2.4,带黑白参数 BT.1886-0:2011
PQ 码值 → 绝对显示光 感知优化的有理幂函数 ST 2084 / BT.2100
HLG OETF + OOTF 场景线性 → 码值 → 显示 混合 log/sqrt,加随峰值变化的 system gamma BT.2100
scRGB 场景/显示线性存储 线性扩展范围 RGB IEC 61966-2-2:2003
Display P3 线性 ↔︎ 码值 sRGB 传递函数,P3-D65 原色 CSS Color 4 / Apple 生态

4. 转换数学

4.1 通用转换,而不是捷径

D1D_1 把源码值 V1V_1 解码到共同的线性光域,E2E_2 把该线性值编码到目标表示。正确转换为:

V2=E2(D1(V1)). V_2=E_2(D_1(V_1)).

若原色或白点不同,需要在线性光中插入色度学变换:

𝐕2=E2(MXYZ2AM1XYZD1(𝐕1)), \mathbf V_2=E_2\left(M_{XYZ\rightarrow2}\,A\,M_{1\rightarrow XYZ}\,D_1(\mathbf V_1)\right),

其中在需要时,AA 为色适应变换(chromatic-adaptation transform)。范围与矩阵解码发生在各自层级,应先于这一 RGB 线性光转换。

4.2 指数比捷径的推导

必须同时满足以下全部假设:

  1. 源和目标都使用精确的纯幂解码函数;
  2. 源和目标表示同一个线性光量;
  3. 数值归一化到 [0,1][0,1]
  4. 黑为 0、白为 1,不存在 flare 或黑位偏移;
  5. 不存在裁剪、super-white 或负值;
  6. RGB 原色与白点相同;
  7. 操作中没有折叠 Y′CbCr 矩阵或 full/limited-range 转换;
  8. 不打算引入 OOTF、tone mapping、曝光缩放或观看环境补偿。

设:

L=V1γ1,V2=L1/γ2. L=V_1^{\gamma_1}, \qquad V_2=L^{1/\gamma_2}.

则:

V2=V1γ1/γ2. \boxed{V_2=V_1^{\gamma_1/\gamma_2}}.

方向由解码指数决定。把当前按 2.2 解码的码值,转换成应按 2.4 解码的码值,应使用指数 2.2/2.4=0.91672.2/2.4=0.9167。反向转换使用 2.4/2.2=1.09092.4/2.2=1.0909

4.3 常见比值与方向

源解码指数 目标解码指数 码值域指数 对中间码值的作用
2.2 2.4 2.2/2.4 = 0.9166667 提高目标码值,使 2.4 解码后保持同一光量
2.4 2.2 2.4/2.2 = 1.0909091 降低目标码值
2.2 2.5 2.2/2.5 = 0.88 提高目标码值
2.5 2.2 2.5/2.2 = 1.1363636 降低目标码值
1.8 2.2 1.8/2.2 = 0.8181818 提高目标码值
2.2 1.8 2.2/1.8 = 1.2222222 降低目标码值

“提高码值”不等于“提高最终亮度”:在上述假设下,目标端更陡的 EOTF 会抵消码值变化。

4.4 把 sRGB 错当纯 2.2 源时的误差

考虑从 sRGB 码值 VsV_s 精确转换到为纯 2.4 EOTF 编码的目标:

Vexact=DsRGB(Vs)1/2.4. V_{\mathrm{exact}}=D_{sRGB}(V_s)^{1/2.4}.

指数比近似为:

Vapprox=Vs2.2/2.4. V_{\mathrm{approx}}=V_s^{2.2/2.4}.

输入 sRGB 码值 精确目标码值 2.2/2.4 近似 近似 − 精确
0 0.000 0.000 0.000
8 20.753 10.675 −10.078
16 28.460 20.152 −8.308
32 43.626 38.042 −5.583
64 73.957 71.814 −2.143
128 134.621 135.567 +0.946
192 195.284 196.594 +1.310
255 255.000 255.000 0.000

全部 256 个整数输入: 最大绝对误差为 10.2078 个码值,出现在输入码值 6;平均绝对误差 2.1610;RMSE 3.3063;绝对误差第 95 百分位为 8.5509。测量前未对目标值重新量化。

最大的低码值差异恰好出现在 sRGB 线性段起作用的位置。即使许多图像的中间调看起来接近,幂指数比也不是忠实的 sRGB 转换器。

反向转换中,若把纯 2.4 码值到 sRGB 的精确变换近似为 V2.4/2.2V^{2.4/2.2},最大绝对误差为 8.5471 个码值,平均绝对误差为 2.1684。

4.5 非零 BT.1886 黑位造成的误差

假设源码值 xx 表示相对光量 x2.2x^{2.2}。目标显示器白位 LW=100L_W=100、黑位为 LBL_B,则期望的绝对亮度为:

Ldesired=LB+(LWLB)x2.2. L_{\mathrm{desired}}=L_B+(L_W-L_B)x^{2.2}.

精确目标驱动为 V=BT18861(Ldesired)V=\operatorname{BT1886}^{-1}(L_{\mathrm{desired}})。把它与忽略黑位的捷径 x2.2/2.4x^{2.2/2.4} 比较:

LBL_B 对比度 最大绝对误差 最大误差处输入 平均绝对误差 RMSE
0 cd/m² 0.000 码值 0.000 0.000
0.001 cd/m² 100000:1 1.945 9 0.992 1.152
0.01 cd/m² 10000:1 4.800 17 2.546 2.940
0.1 cd/m² 1000:1 11.373 31 6.366 7.284
1.0 cd/m² 100:1 25.125 54 15.001 16.924

计算方法: 遍历全部 256 个 8-bit 输入码值;源为归一化纯 2.2;按上式在绝对黑白之间插值;精确反解 BT.1886;最终不再量化。此表是敏感性分析,不表示建议在每一种列出的黑位上制作 SDR 母版。

只有理想黑位这一行,幂指数比捷径才精确。一旦黑位非零,相对图像光在 LBL_BLWL_W 之间的仿射安置,加上 BT.1886 的 a,ba,b 项,都会改变所需码值。

4.6 sRGB/纯 2.2 近似的感知误差

下表比较精确 sRGB 解码与纯 2.2 解码,使用 BT.709/sRGB 原色、D65、CIE Lab 与 CIEDE2000。未进行色适应,也未在转换后重新量化。

样本集 平均 ΔE00 第 95 百分位 最大值 ≥ 1 的比例
256 个中性码值 0.554 1.786 码值 27 处 2.033 18.36%
17×17×17 RGB 码值立方体 0.523 1.273 (0, 0.0625, 0) 处 4.799 8.06%

ΔE00 接近 1 经常被用作受控条件下的粗略可见性尺度,但它不是普适阈值:适应状态、亮度、surround、空间频率、显示黑位和观察者差异都会影响结果。对于 HDR,ITU 的 ΔEITP 被设计为在其目标条件下约 1 对应一个 just-noticeable difference [A-20];这一结论不能机械套用到 ΔE00。

该表也说明,“平均误差不大”完全可以与可见接缝、暗色 UI 元素差异、或低电平饱和颜色差异同时存在。

4.7 可逆实现模式

对于任意一对命名传递函数:

1. 明确解析或覆盖源元数据。
2. 撤销量化范围与 Y'CbCr 矩阵,获得编码 RGB。
3. 应用精确的源逆传递函数。
4. 如有需要,在线性光中变换原色/白点。
5. 仅在任务确实需要时,应用目标 OOTF 或 tone map。
6. 应用精确的目标编码函数。
7. 转换到目标矩阵/范围。
8. 以足够精度量化,并在合适时使用 dithering。
9. 写入一致的码流层与容器层元数据。
10. 用解码像素值和受控参考显示路径验证。

只有在 §4.2 的假设已经被证明时,一行 pow() 才是正确的;不能仅凭视觉相似去猜。


5. “Gamma shift”表象的成因分类学

本章是全文的核心诊断分类。每一类都给出机制、特征症状、可复现条件和区分测试。

5.1 元数据失配:transfer、primaries、matrix、range 与冲突

现代视频基本码流可以声明 CICP 风格的数值,包括:

H.264/AVC 与 HEVC 在 SPS VUI 中携带这些声明;AV1 在 sequence header 中有对应字段。容器也可以携带色彩信息:ISO BMFF/QuickTime 使用 colr box/atom,常见 payload 为 nclcnclx。Matroska 有自己的 Colour elements。转码器完全可能保留像素,却删除、凭空生成或修改这些声明。

机制

  1. 标签缺失: 解码器/应用程序使用启发式规则——例如 SD 按 601、HD 按 709、Y′CbCr 按 narrow range、静态图像按 sRGB。
  2. 标签错误: 执行的数学转换本身有效,但解释对象错了。
  3. 转码/remux 时丢失标签: 像素保留,语义丢失。
  4. 容器与码流冲突: 例如 MP4 colr 声明 BT.709,而 SPS VUI 声明 BT.2020/PQ。
  5. 声明不完整: 有 primaries 和 matrix,却没有 transfer,或反之。
  6. 应用程序覆盖: NLE 的“interpret footage”设置取代文件元数据。

不存在跨应用通用的“容器永远优先”或“码流永远优先”规则。demuxer 暴露 side data 的方式不同;decoder 可能报告 VUI;应用程序可能合并、覆盖或忽略某一来源。FFmpeg issue 报告展示了真实存在的 mov colr 与 SPS-VUI 不一致 [B-24]。因此,优先级是特定 demuxer/decoder/application 版本的经验属性,而不是安全假设。

症状

复现与检查

ffprobe -v error -select_streams v:0 \
  -show_entries stream=color_range,color_space,color_transfer,color_primaries \
  -of default=nw=1 input.mp4

# 不要只看容器层 side data;还要检查编码头。
ffmpeg -i input.mp4 -map 0:v:0 -c copy -bsf:v trace_headers -f null - 2>&1 \
  | rg 'colour_primaries|transfer_characteristics|matrix_coefficients|video_full_range'

再使用 Bento4 mp4dump 等 ISO-BMFF 解析器单独检查 colr。然后比较:(a) 原文件;(b) 不重编码抽取出的 raw elementary stream;(c) 显式写标签后的 remux 文件。若外观变化而解码后的数值 RGB 不变,差异位于下游色彩管理,而不是 codec reconstruction。

5.2 Full 与 narrow range:它是仿射错误,不是 gamma 错误

传统 8-bit narrow-range luma/R′G′B′ 的归一化为:

xnarrow=D1623516=D16219. x_{\mathrm{narrow}}=\frac{D-16}{235-16}=\frac{D-16}{219}.

Full range 为:

xfull=D255. x_{\mathrm{full}}=\frac{D}{255}.

Chroma 传统上使用 16–240,中心值为 128。10-bit 中,标称 luma 黑/白为 64/940,chroma 两端为 64/960。

码值 DD 按 full 解释 D/255D/255 按 narrow 解释 (D16)/219(D-16)/219,未钳位
0 0.000000 −0.073059
16 0.062745 0.000000
32 0.125490 0.073059
64 0.250980 0.219178
128 0.501961 0.511416
192 0.752941 0.803653
235 0.921569 1.000000
255 1.000000 1.091324

若把 narrow 数据当 full,码值 16 变成 0.0627 的灰,码值 235 变成 0.9216:黑位抬升、白位变暗。若把 full 数据当 narrow,低于 16 和高于 235 的值会裁剪,黑白两端都被压死。

范围映射具有形式:

y=ax+b. y=ax+b.

纯 gamma 失配具有形式:

y=xp. y=x^p.

在对应样本的普通坐标图上,前者是一条直线,后者是曲线。在 log-log 坐标中,归一化后的纯幂是一条过原点直线,而带偏移的仿射变换会强烈弯曲。这是两者最快的数学区分方法。

注意: 裁剪、量化和后续 tone curve 会让范围错误看起来不再完全仿射。应先拟合中间的未饱和样本。

5.3 BT.601 与 BT.709 矩阵混用

对非线性 RGB,BT.601 与 BT.709 构造不同的 luma-like 信号:

Y601=0.299R+0.587G+0.114B, Y'_{601}=0.299R'+0.587G'+0.114B',

Y709=0.2126R+0.7152G+0.0722B. Y'_{709}=0.2126R'+0.7152G'+0.0722B'.

中性值 R=G=BR'=G'=B' 经任一矩阵都保持不变,因此矩阵失配通常不会产生统一的中性 gamma 曲线。它主要改变饱和颜色与彩色边缘。

例:把 (R,G,B)=(0.8,0.4,0.2)(R',G',B')=(0.8,0.4,0.2) 以 BT.601 full-range Y′CbCr 编码,再用 BT.709 系数解码,结果约为:

(0.83737,0.42694,0.18600). (0.83737,\ 0.42694,\ 0.18600).

反过来,以 BT.709 编码、BT.601 解码,得到:

(0.76386,0.37141,0.21219). (0.76386,\ 0.37141,\ 0.21219).

纯灰仍然是灰。高饱和红色若按 601 编码、709 解码,在裁剪前可重建为约 (1.0864,0.0965,0.0141)(1.0864,0.0965,-0.0141)。随后的裁剪会使误差更非线性,并可能形成局部“亮度变化”的观感,但根因仍是矩阵。

5.4 QuickTime 与 Apple ColorSync:多个历史机制,不是一个永恒不变的 bug

Apple 1999 年的 Technical Note TN2162 记录了 colr image-description extension,其中 nclc 数值分别表示原色、传递函数与 Y′CbCr 矩阵 [B-04]。它还明确指出:

这些表述已经说明,“QuickTime gamma bug”过于粗糙。可能的成因包括旧 gamma-level atom、nclc 解释、codec-specific Y′CbCr-to-RGB 路径、应用程序预览变换、ColorSync 显示转换、range expansion,以及对旧 Macintosh 1.8 图形系统的假设。

gama image-description extension 存储 gamma-level indication。较新的 colr/nclc 机制把 primaries、transfer 与 matrix 分开。当前 ISO-BMFF 生态还使用能携带 full-range flag 的 nclx。H.264/HEVC 又可同时携带 VUI 数值。因此,ProRes 或 H.264 文件即使压缩样本完全相同,在 Apple 与非 Apple 软件之间往返时仍可能被不同解释。

历史上观察到的模式

可靠诊断方法是导出灰阶 ramp,通过多个独立路径解码到 raw 数值样本,检查全部元数据层,并且只有在控制显示色彩管理后才比较应用截图。

5.5 NLE 工作空间与线性光选项

After Effects

当前 After Effects 色彩管理把输入解释、project working space、working-space linearization、display transform 与 output profile 分开 [B-06]。两个经常混淆的控制项是:

Adobe 建议在线性化时使用足够精度,尤其 16- 或 32-bpc。8-bpc 中反复解码、处理、再编码容易暴露 banding。

若项目没有 working space,After Effects 的行为可能更接近 pass-through/legacy 数值链路;但导入素材解释、viewer 显示色彩管理、codec 转换和导出标签仍然可能不同。“Color management off”并不能证明“任何层都没有变换”。

Premiere Pro

当前 Premiere 文档说明了一套明确的 source/input color space → working color space → output color space 架构,并带可选的输入/输出 tone mapping 与 gamut compression [B-07]。在效果之前做 tone mapping 与在效果之后做并不等价。若 HLG/PQ 源被误认成 Rec.709,用户甚至还没加任何 grade,就可能已被错误转换。

为了复现,至少记录:

时间线截图与外部播放器截图并不是有效测试,除非两条显示路径都已完成色度学表征。

5.6 在非线性码值上处理:缩放、模糊、alpha、锐化、抗锯齿

当一个空间平均模拟光的积分时,应该平均光量;直接平均编码值,平均的是感知/码值表示。

以 50% 黑白棋盘为例:

因此,在 gamma 空间把 50% 棋盘缩小时,只得到正确光量的 42.8%;在这个构造案例中,相对亮度误差为 −57.2%。

同一原理影响:

限定条件在于运算语义:某些经过作者设计的 UI/图形运算有意定义在 sRGB-like 码值空间,以保留熟悉外观,而不是模拟辐射度学。工程错误不是“永远不能做非线性算术”,而是不知情或不一致地做。

5.7 色度子采样与 chroma siting

4:2:0 不只是降低色度分辨率,它还必须规定每一个 chroma sample 相对于 luma samples 的几何位置。常见约定包括:

码流可以声明 chroma sample location,但元数据可能缺失或被忽略。若上采样相位错误,chroma 会相对 luma 偏移一小部分像素。在彩色边缘上,它形成色边、溢色以及 RGB 过冲/欠冲。由于重建 RGB 会影响感知亮度并可能发生裁剪,这种伪像可能被描述成“亮度 halo”,尽管 Y′ 平面没有改变。

诊断图应包含一像素和两像素位置的高饱和红/蓝跳变。先在 RGB 转换前比较各平面,再显式测试不同 siting。真正的 gamma 错误会影响大范围中性 ramp;siting 错误集中于彩色边缘,而且随边缘极性反向。

5.8 非恒定亮度(non-constant luminance):Y′ 不是 luminance

传统 Y′CbCr 由非线性分量形成。在 BT.709 中:

Y=0.2126R+0.7152G+0.0722B. Y'=0.2126R'+0.7152G'+0.0722B'.

物理相对亮度由线性分量形成:

Y=0.2126R+0.7152G+0.0722B. Y=0.2126R+0.7152G+0.0722B.

一般而言:

OETF1(Y)Y. \operatorname{OETF}^{-1}(Y')\ne Y.

对于线性纯红 (R,G,B)=(1,0,0)(R,G,B)=(1,0,0)Y=0.2126Y=0.2126。其非线性分量为 (1,0,0)(1,0,0),所以 Y=0.2126Y'=0.2126;把 BT.709 逆 OETF 作用到这一标量,只得到约 0.06075,而不是 0.2126。只有中性色等特殊情况才相等。

这种 non-constant-luminance 性质意味着,即使存储的 Y′ 看起来未变,chroma filtering、量化、裁剪、色域转换或非线性 RGB 运算仍可能改变重建后的物理亮度。BT.2020 的更宽色域与 HDR 更大的亮度范围会放大这一问题的重要性 [A-08]。

BT.2020 同时定义:

CL 能更好地把 luminance 与 chroma 分离,但更复杂、部署也更少。BT.2100 为 HDR 引入 ICtCp/constant-intensity 选项;NCL Y′CbCr 仍很常见,不能当成物理 luminance。

5.9 静态图像元数据:PNG 与 JPEG

PNG

PNG Third Edition 规定了如下色彩空间优先级 [A-12, §4.3]:

  1. cICP
  2. iCCP
  3. sRGB
  4. cHRMgAMA

解码器应使用其能理解的最高优先级色彩空间信息。iCCP 可以与近似的 gAMA/cHRM 共存,以兼容旧 reader;现代合规 reader 使用 ICC profile。iCCPsRGB 不应同时存在。gAMA 整数存储的是 image gamma 乘以 100000;对于标称 1/2.2 编码约为 45455。若把它误读成 2.2 的显示指数,方向就完全颠倒。

Alpha channel 是线性的 coverage/full-range,不受 gAMA gamma correction。若把 alpha 当成具有 RGB 传递函数,会产生边缘错误。

历史库并非都以相同方式实现当前优先级。因此,即使形式上只有一种解释正确,冲突 chunk 仍是可移植性风险。

JPEG

JPEG 通常把 ICC profile 嵌入 APP2 marker。ICC 约定使用 ICC_PROFILE\0 标识符、序号和总 chunk 数,因为单个 marker 容纳不了较大的 profile;profile 可以跨多个 APP2 segment [A-17]。缺失或乱序 segment 会使 profile 无效。JPEG 还可包含 EXIF color-space hints,但有效 ICC profile 是更强的色度学描述。

截图与无标签文件

截图究竟嵌入源显示 profile、把像素转换为 sRGB、嵌入 Display P3,还是完全不写 profile,取决于操作系统、API、应用程序与格式。对某一张具体截图,唯一可靠的答案是检查文件。在定义明确的生态之外,无标签图像没有统一解释规则。在现代 Web 上,浏览器大体把 untagged image content 当作 sRGB;旧式或无色彩管理应用可能把原始数字直接发送到显示器。

5.10 显示端与浏览器色彩管理

在广色域 Display-P3-like 显示器上,无标签 sRGB 图像不能被解释成原生显示 RGB。正确渲染在概念上执行:

假定/嵌入的源 RGB
 -> 源线性/PCS
 -> 显示配置文件
 -> 显示设备值

把 sRGB 数值直接发送到更宽色域的原生 framebuffer,会使颜色过饱和。给不变的 sRGB 数值直接“指派” Display P3 profile,同样会改变其意义;把 sRGB 转换到 P3 才是在改变数字的同时保持颜色。

不同操作系统把色彩转换放在不同位置——应用、graphics API、window compositor 或 display pipeline——并且 calibration curves 是否与 ICC characterization 分开施加也不同。当应用程序和另一个层级都执行本应只做一次的变换时,会出现 double color management;完全绕过管理则产生相反错误。

WebKit 关于广色域 Web 内容的文档说明了 color matching,并假定 untagged images 为 sRGB [B-18]。Firefox 89 改变了 macOS 行为,使无标签图像像 CSS color 一样一致按 sRGB 处理 [B-19]。浏览器、OS、GPU 与 display-profile 版本仍然重要;有效测试页应同时包含 tagged sRGB、tagged Display P3、无标签副本、CSS colors 与 canvas readback。

5.11 HDR↔︎SDR 与 SDR↔︎HDR:tone mapping 不是“gamma correction”

HDR-to-SDR 必须决定如何把绝对或高相对动态范围场景呈现到更低峰值、更窄色域上。变量包括:

当前 ITU 指南在关键 HDR 制作/交换语境中使用 203 cd/m² 作为 HDR reference white [A-09]。这并不把传统 BT.1886 SDR 参考显示器重新定义为 203 cd/m²;它规定 reference/diffuse white 在 HDR 系统中的位置。BT.2446 记录多种 HDR/SDR 转换方法,而不是一个指数 [A-10]。

两个实现都可能正确解码 PQ,却因为一个 hard clip、一个 global knee、另一个 dynamic/local tone mapping 而呈现不同。它们的像素关系依赖内容,且经常随空间位置变化。给结果拟合一个 gamma 只能是描述性近似,不是成因解释。

SDR-to-HDR 同样需要逆 tone-mapping/rendering 决策:什么继续作为 diffuse white、合成多少高光扩展、是否扩展颜色、目标峰值是多少。仅把 SDR 解码再编码为 PQ,只会得到一个 HDR 容器,不会自动得到 HDR rendering。


6. 历史专题:CRT 2.5、Macintosh 1.8、QuickTime 与“0.88 修正”

6.1 从 CRT 的物理响应到标准化 EOTF

早期视频系统能够利用一个有利的物理事实:CRT 电子枪驱动具有相当可重复的非线性。相机端预校正既改善了信号码阶分配,也近似补偿接收机。但电视链路从来不是完全互逆的相机/显示链:在昏暗房间观看需要一个增强对比的 OOTF。

历史可以压缩为:

CRT 物理响应族:在有效工作区间约 2.35–2.55
相机/源端预校正:约 0.45–0.5 指数,外加 toe/offset
端到端呈现:有意大于 1
平板时代:不存在共同的“天然 CRT 曲线”
2011:BT.1886 定义可复现参考 EOTF,gamma 2.4,并带 Lw/Lb

2.5 来自测量和电子枪物理,而不是要求每个文件都通过 2.5 LUT 解码的指令。后来的 2.4 参考值是一项标准化选择:在考虑显示黑位的同时,复现被认可的参考观看行为。

6.2 关于 Macintosh 1.8:哪些能够证明,哪些不能

证据充分的事实是:

  1. 早期 Macintosh 图形系统使用 LUT 加普通 CRT,实现接近 1.8 的有效响应 [L-01];
  2. CRT 本身在物理上不是“1.8 显示器”;
  3. 1.8 与平面设计/印前 tone reproduction 有实用匹配,原始 QuickDraw 码值可在 imagesetter 上得到可接受结果 [L-01];
  4. 这一约定随后在桌面出版中固化;
  5. Snow Leopard 于 2009 年把默认值改为 2.2 [B-20, B-21]。

证据较弱的是:Apple 选择精确 1.8,是为了对某一指定 LaserWriter 型号做有文档记录的数学补偿。本次调研检索了 Apple support/developer archives、QuickDraw/ColorSync 资料、LaserWriter 文档索引、Poynton 的出版物以及同期讨论,但没有找到能够确立这一狭窄说法的一方设计记录。可辩护的表述应是印刷/印前链路兼容性,而不是已证实的 LaserWriter-specific 起源

这一区分很重要,因为历史动机并不会自动构成现代文件转换的依据。1.8 桌面 LUT、印刷 dot-gain 曲线、ICC perceptual rendering 和视频 OOTF 是不同的变换。

6.3 QuickTime gamma-shift 时间线,以及为什么报告互相矛盾

按证据权重压缩后的时间线如下:

日期 证据 能够确立的事实
1999-12-14 Apple TN2162 [B-04] nclc/colr 语义、colr 优先于 gama,以及 colr 无法描述的旧 Mac Y′CbCr transfer adjustment
约 2001 年 QTFF Apple file-format docs [B-05] 容器架构中存在 gamma 与 color image-description extensions
2006 Apple/社区报告 [C-07] 用户观察到跨播放器 gamma/black 差异;机制未被唯一证明
2007 After Effects CS3 资料 [C-02] QuickTime 7.2 时代行为变化到足以让 Adobe 提供 legacy-matching 选项
2008 视频制作指南 [C-03] gamma-shift workaround 已广泛流传,但经常混入播放器、codec 与 range 问题
2009-08-28 Snow Leopard [B-20, B-21] 默认桌面 gamma 从 1.8→2.2;QuickTime X 改变应用栈
2010-12-31 受控博客测试 [C-01] 某条 AE CS5/Windows/QuickTime H.264 路径经验拟合为 x0.88x^{0.88};QuickTime Player 还显示独立的 range/contrast 重映射
2013 起 压制论坛/指南 [C-04, C-05] Levels(..., gamma=0.88) 变成可移植的社区配方,且经常脱离原始适用条件

报告互相冲突,是因为它们并没有测试同一条链路。有的比较解码字节,有的比较截图;有的使用 H.264,有的用 ProRes 或 Animation;有的在 Windows 上通过 Apple QuickTime components,有的在 macOS 上经过 ColorSync;有些误差是非线性的,另一些其实是 full/narrow range。一个口传标签把这些不同机制全部吸收进去了。

6.4 0.88 的来源与证据等级

本次调研找到的、可以独立访问、带明确日期、且精确给出 0.88 测量的最早材料,是 2010 年 12 月 31 日的文章“The QuickTime Gamma Bug” [C-01]。它报告,在所测试的 QuickTime 路径中,After Effects CS5 on Windows 编码 H.264 时,会把灰阶样本近似变换为:

y=x0.88, y=x^{0.88},

并且在输入约 88 处,8-bit 码值最大提高约 12。文章还报告了另一种 QuickTime Player 变换:提高黑位并压缩对比度——那是一种仿射/range-like 错误,不是同一条 gamma 曲线。

这是 C 类经验实测,不是 Apple 或 Adobe 规范。它能够证明所测试链路确实如此表现;不能证明所有 QuickTime H.264 编码器都如此,也不能证明 ProRes 如此,更不能证明内部设计理由就是 2.2/2.52.2/2.5

数值上:

0.88=2.2/2.5. 0.88=2.2/2.5.

这使 CRT/PC-gamma 故事看起来很诱人。然而,本次找到的一手来源中,没有任何一项说实现有意把 2.2 编码信号转换为 2.5 编码信号。2010 年文章作者也明确把原因视为未知。因此,理论起源说仍然未经证明;0.88 应被描述为经验拟合/配方,而它与 2.2/2.52.2/2.5 的数值相等,可能解释后续口传故事的形成。

检索限制:若干旧 Doom9 链接和 mailing-list 引用已失效、被阻断或未被索引,更早的精确用例可能存在。本文的主张是“本次检索中最早可获取”,不是“互联网历史上首次发布”。

6.5 方向陷阱:Levels(gamma=0.88) 并不施加 x0.88x^{0.88}

AviSynth 对 Levels 的定义为 [B-10]:

y=(xxin,minxin,maxxin,min)1/γ(xout,maxxout,min)+xout,min, y=\left(\frac{x-x_{in,min}}{x_{in,max}-x_{in,min}}\right)^{1/\gamma} (x_{out,max}-x_{out,min})+x_{out,min},

并带输入钳位与所选范围参数。VapourSynth std.Levels 暴露相同语义:大于 1 的值变亮,小于 1 的值变暗,planes 决定处理哪些平面 [B-09]。在归一化 full-range 形式下:

y=x1/γ. y=x^{1/\gamma}.

因此:

这与“把正确的纯 2.2 编码转换为正确的纯 2.5 编码”不同。后者的正向转换是 x2.2/2.5=x0.88x^{2.2/2.5}=x^{0.88},在 Levels 中需要 gamma=1.13636,而不是 0.88。大量社区讨论没有区分修正参数数学指数

6.6 0.88 什么时候有效,什么时候制造新错误

只有在测量显示源数据在同一归一化域内已经被约 x0.88x^{0.88} 提亮,且目标修正正是它的逆时,gamma=0.88 才有依据。条件包括:

下列情况会造成伤害:

正确顺序是先拟合观察到的映射,再选择其逆。不能因为两张图“看起来像 Apple 的差异”就从 0.88 开始。

6.7 只改 Y 与逐 RGB 通道 gamma:数值算例

取 full-range BT.709 非线性 RGB:

(R,G,B)=(0.8,0.4,0.2). (R',G',B')=(0.8,0.4,0.2).

其 Y′CbCr 约为:

(Y,CB,CR)=(0.470600,0.145829,0.209169). (Y',C_B,C_R)=(0.470600,-0.145829,0.209169).

施加 Levels(gamma=0.88),即指数 1.13636:

方法 结果 (R,G,B)(R',G',B') HSV hue HSV saturation 以 sRGB 解码的相对 luminance
原始 (0.800000, 0.400000, 0.200000) 20.000° 0.7500 0.22579
仅对 Y′ 做 gamma;复制 Cb/Cr (0.754033, 0.354033, 0.154033) 20.000° 0.7957 0.18751
对 R′/G′/B′ 分别施加相同 gamma (0.776024, 0.353017, 0.160589) 18.760° 0.7931 0.19466

计算方法: full-range BT.709 NCL matrix;不裁剪;HSV 在非线性 RGB 上计算;最后一列仅把各通道用 sRGB 解码,作为可复现的 display-light proxy。

在 Cb/Cr 固定时改变 Y′,会在裁剪前给 R′、G′、B′ 加上相同的码值域增量。它保持通道差,因此本例 HSV hue 不变,但 saturation 会变,也不会保持物理 luminance 或 chromaticity。逐通道 gamma 会改变通道比例,因此同时改变 hue 和 saturation。发生裁剪后,仅改 Y′ 也会突然改变 hue。

对于 YUV clip,planes=0 的含义是“处理 Y 平面”,不是“执行色度学正确的传递函数转换”。对于 RGB clip,选择三个颜色平面,会把标量函数分别施加到每一个编码分量。两者都不会自动线性化、改变原色、处理 BT.1886 黑位或更新元数据。

6.8 常用工具的横向比较

工具/filter 所在域与用途 线性光/色彩管理? 主要风险
AviSynth Levels / VS std.Levels 1/γ1/\gamma 幂做样本/范围重映射;可选平面 不自动色彩管理 参数方向、Y-only 默认/工作流、范围假设
FFmpeg eq 简单 brightness/contrast/gamma 调整,常对原生平面执行 不是标准转换 对 YUV 样本施加“gamma”并误当 TRC 转换
FFmpeg lut, lutrgb, lutyuv 任意样本域 LUT 仅在用户自行构造精确链路时 域错误、裁剪、低精度
FFmpeg colorspace transfer/primaries/matrix/range 转换 感知标准定义并按指定转换 输入声明错误/缺失或边缘情况不支持
FFmpeg zscale 基于 zimg 的缩放与色彩转换,带 dither/精度选项 可执行精确 transfer/primaries/matrix 转换 元数据默认值与参数方向仍然重要
mpv/libplacebo 播放呈现、ICC/output TRC、线性缩放、tone/gamut mapping 围绕显式色彩链设计;选项决定行为 --gamma-factor 当元数据修复、目标假设错误
madVR 专有播放 renderer,带校准/tone 控制 精确内部实现并未完整公开 根据 UI 名称或论坛描述推断数学顺序

FFmpeg 的 colorspace/zscale 才是声明式色彩空间转换的合适工具族;eq 与 LUT filters 适合有意的样本变换。mpv 的 --linear-downscaling--target-trc、ICC、--target-peak、tone-mapping 与 --treat-srgb-as-power22 等选项说明,“gamma”必须放在完整 rendering pipeline 中理解 [B-11, B-12]。--gamma-factor 是外观调整,不是正确源元数据的替代品。

对于 madVR,本次调研找到了大量社区描述,但公开的一手文档不足以为所有模式断言一个统一、精确的内部运算顺序。任何精确说法都应针对具体 build,用 ramp 和 readback/capture 实测验证。


7. Web 与浏览器实现层的特殊陷阱

7.1 SVG filter primitives 与 CSS filter functions

Filter Effects Level 1 延续了一个具有历史意义的分裂 [A-13, §10]:

因此,下列两者不保证相同:

.element-a { filter: brightness(0.5); }     /* CSS function:sRGB */
.element-b { filter: url(#svgBrightness); } /* SVG primitive:默认 linearRGB */

SVG 等价实现必须显式选择目标域:

<filter id="svgBrightness" color-interpolation-filters="sRGB">
  <feComponentTransfer>
    <feFuncR type="linear" slope="0.5"/>
    <feFuncG type="linear" slope="0.5"/>
    <feFuncB type="linear" slope="0.5"/>
  </feComponentTransfer>
</filter>

如果不写 sRGB,在线性光中把中灰减半,与把其 sRGB 编码码值减半,是不同运算。出现这一分裂,是因为 SVG filter primitives 被规定以线性光色彩处理作为默认,而 CSS filter-function 行为是在既有 sRGB-like compositing 与 Web compatibility 基础上标准化的。它是规范默认域的不一致,并不必然是浏览器 bug。

浏览器实际历史

WebKit bug 185343 报告 filter:url(#id) 错误地强制使用 sRGB,而没有遵守 SVG 的 linearRGB 默认;该问题于 2018 年 5 月 4 日报告,并于 5 月 7 日 resolved fixed [B-13]。这是一项具体证据:即使规范清楚,浏览器仍可能让两条路径产生不一致。更早的 Safari/WebKit Gaussian-blur 报告也涉及 linearRGB/sRGB 差异与 backend 行为 [B-14]。

不能从一次历史修复推断当前所有浏览器都一致。应使用显式 sRGBlinearRGB 的测试页,在可能时捕获数值输出,并记录浏览器 build、OS、GPU 与 color profile。

7.2 feComponentTransfer 的精确语义

Filter Effects Level 1 定义每个分量在 unpremultiplied color value 上的函数 [A-13, §9.12]:

默认值为 amplitude=1exponent=1offset=0slope=1intercept=0feFuncRfeFuncGfeFuncBfeFuncA 分别控制各通道。gamma primitive 的参数就是实际指数——不同于 Levels 的倒数约定——所以不能仅凭 API 中的参数名判断跨 API 的方向。

该 transfer 在 filter primitive 选定的 interpolation color space 中运算。数学上相同的 component function,在 sRGBlinearRGB 中会产生不同的可见光输出。

7.3 feComposite operator="arithmetic"、钳位与有符号中间值

Arithmetic composite 定义为 [A-13, §9.8]:

result=k1i1i2+k2i1+k3i2+k4. \mathrm{result}=k_1i_1i_2+k_2i_1+k_3i_2+k_4.

每个输出分量都会钳位到 [0,1][0,1]。filter primitive 的结果在传给后续 primitive 前,也会裁剪到允许的 premultiplied range。因此,一个名义上的减法:

<feComposite in="A" in2="B" operator="arithmetic"
             k1="0" k2="1" k3="-1" k4="0"/>

无法保留负值:负值会立即变为 0。

常见工程 workaround 是加 bias 并缩放,把有符号差打包进合法区间:

Dpacked=0.5+0.5(AB), D_{packed}=0.5+0.5(A-B),

即使用 k2=0.5,k3=0.5,k4=0.5k_2=0.5,k_3=-0.5,k_4=0.5。后续处理可把 0.5 解释为零。只有当所有中间值始终留在合法范围时,该方法才成功;后续“unpack”若再次产生负值,仍会钳位。若需要精确有符号算术,WebGL/WebGPU、float canvas 或浏览器外处理通常比串联规范要求钳位的 SVG primitives 更合适。

7.4 中间缓冲精度与 banding

规范定义函数结果与钳位,但不承诺所有实现使用相同的中间存储精度。引擎可能根据 primitive、GPU、color space、tiling 与 compositing mode,使用 8-bit unorm surface、10/16-bit 格式、half-float texture、CPU float buffer 或混合路径。

8-bit 中间缓冲在以下情况容易暴露 banding:

更高位深会降低量化误差,但不能绕过规范要求的钳位。Dither 可以在最终量化阶段打散 banding;无法恢复早先 surface 中已经裁剪或舍入掉的数值。

可复现浏览器测试应以 16-bit 或生成的 float ramp 作为源,每次只施加一个 primitive,并在 400% 放大下比较 screenshot/readback。肉眼看起来平滑并不能证明中间精度高,因为 dithering 可以掩盖低位深;直方图/readback 更有信息量。

7.5 预乘 alpha(premultiplied alpha)

Filter Effects 规定 filter image 通常表示为 premultiplied RGBA。feColorMatrixfeComponentTransfer 是例外:它们在概念上对临时 unpremultiplied color value 运算,然后重新回到 premultiplied form [A-13, §8]。

若链路错误地把非线性函数直接作用于 premultiplied channel,则对颜色 CC 与 alpha α\alpha

(αC)pαCp (\alpha C)^p\ne\alpha C^p

除非 p=1p=1 或特殊值。低 alpha 边缘会改变颜色和明暗。正确处理在概念上是:

if alpha > 0: unpremultiply RGB
在声明的 color space 中应用颜色运算
把 RGB 乘回 alpha
if alpha == 0: 安全定义 RGB,通常为零

在低 alpha 下反复 unpremultiply/premultiply 会放大量化与 hidden-color 差异。应在黑、白两种背景上测试透明边缘;在一种背景上看不出的错误,在另一种上可能非常明显。

7.6 GPU 与 CPU 路径,以及公开浏览器 issue

浏览器引擎可能把 filter 路由到 Blink/WebCore/Gecko display list、Skia/CoreGraphics/Moz2D、GPU shader 或 CPU fallback。差异可能来自:

公开案例包括:

这些 issue 编号证明路径依赖差异曾经存在,但不能据此宣称当前 Chrome、Safari 或 Firefox 总是错误渲染 filter。当前兼容性结论需要针对具体 build 测试。

7.7 Canvas 色彩空间与 getImageData

Canvas 2D 规范支持请求 context color space;当前 WHATWG 文本包含 srgbsrgb-lineardisplay-p3display-p3-linear 概念,但已部署浏览器支持范围更窄,必须 feature-test [A-14]。常见已部署语法包括:

const ctx = canvas.getContext("2d", { colorSpace: "display-p3" });

在支持这些选项的实现中,getImageData() 可以请求色彩空间和像素格式:

const image = ctx.getImageData(0, 0, w, h, {
  colorSpace: "display-p3",
  pixelFormat: "rgba-float16"
});

关键语义是:readback 可以包含向请求的 ImageData 表示所做的色彩空间转换;它不一定是 GPU framebuffer 原始字节 dump。rgba-unorm8 量化为 8-bit normalized channels;rgba-float16 在实现支持时允许 HDR/宽范围值。把一个 ImageData 绘制到不同 color space 的 context,还可能触发另一次转换。

Canvas 至少有四个必须分开的空间:

  1. 源图像的嵌入/假定 color space;
  2. canvas backing/context color space;
  3. ImageData readback/请求的 color space 与 format;
  4. 页面/compositor/display output space。

做一致性测试时,应分别用 CSS color value、解码图像与直接 ImageData 填充 patch;在 sRGB 与 P3 中分别 read back;再与独立计算的色度学数值比较。单独截图会把 canvas conversion 与显示色彩管理混在一起。


8. 判别与测量方法论

8.1 先确认像素确实可比较

只有在图像已配准、并且表示链路中同一阶段时,传递函数拟合才有意义。拟合前应:

  1. 对齐 frame/timecode 与 field order;
  2. 撤销 crop、rotation、pixel-aspect 与 scaling 差异;
  3. 若某一路径做过 resize,则以 subpixel 精度配准;
  4. 排除字幕、UI overlay、烧录元数据与边框;
  5. 识别 codec blocking、denoising、sharpening 与 chroma-resampling 差异;
  6. 在一个共同的解码 RGB 格式中比较,并明确 matrix/range/transfer 假设;
  7. 在隔离 OS/display color management 前,不要使用 screenshot。

对于同分辨率源,phase correlation 可估计平移。若图像被缩放或轻微扭曲,可使用 robust feature matching 后接 affine/homography fit,但 tone 分析应采样平滑内部区域。边缘会被 kernel 与 chroma-siting 差异污染。

8.2 只给静止画面或匹配图像对时的决策树

开始:同一帧的两张图看起来不同
 |
 |-- 在显示之前,解码后的数值像素是否完全相同?
 |      |-- 是 -> 显示/应用色彩管理、output profile、HDR mode、
 |      |         OS compositor、monitor profile 或截图路径。
 |      `-- 否 -> 继续。
 |
 |-- 黑白端点是否近似按 y = a*x + b 映射?
 |      |-- 是 -> full/narrow range、level scaling、pedestal 或 contrast/offset。
 |      |         检查 16/235(或 64/940)与裁剪。
 |      `-- 否 -> 继续。
 |
 |-- 对应中性像素是否满足 y ≈ c*x^p,且残差较小?
 |      |-- 是 -> 传递函数/幂律型失配。检查标签并拟合 p。
 |      `-- 否 -> 继续。
 |
 |-- 误差是否强烈依赖 hue,而中性值仍接近?
 |      |-- 是 -> 601/709/2020 matrix、primaries/profile、gamut mapping、
 |      |         per-channel curve 或 chroma processing。
 |      `-- 否 -> 继续。
 |
 |-- 差异是否集中在彩色边缘或精细纹理?
 |      |-- 是 -> chroma siting/upsampling、scaling kernel、nonlinear filtering、
 |      |         sharpening、alpha 或 GPU precision。
 |      `-- 否 -> 继续。
 |
 |-- 高光差异是否依赖内容、局部空间区域,或受 nit 上限约束?
 |      |-- 是 -> HDR/SDR tone mapping、local adaptation、dynamic metadata、
 |      |         target peak/reference-white mismatch。
 |      `-- 否 -> 继续。
 |
 `-- 拟合组合模型:per-channel 3x3 matrix + offset + monotonic curves;
        检查残差与链路元数据。在此之前不要称之为“gamma”。

这棵树故意把“数值是否相同”放在“外观看起来怎样”之前。若两个应用把同一解码 RGB 显示得不同,修改文件像素可能会“修好”其中一个应用,却破坏所有正确管理的路径。

8.3 拟合幂律失配

对于归一化、为正、未裁剪且彼此对应的中性样本 (xi,yi)(x_i,y_i),拟合:

y=cxp. y=cx^p.

取对数:

lny=plnx+lnc. \ln y=p\ln x+\ln c.

线性回归即可得到指数 pp 与增益 cc。但假设非常严格:

稳健流程

  1. 用测得的黑白点或已知 code range 归一化;
  2. 移除接近黑位和裁剪端的样本,例如低于 2% 与高于 98%;
  3. 选择低 chroma 像素或 neutral wedge;
  4. 同时拟合仿射模型 y=ax+by=ax+b 和幂模型 y=cxpy=cx^p
  5. 使用 Huber loss、Theil–Sen 或 RANSAC 排除边缘与 codec artifact;
  6. 检查 residual 随输入值、位置与 hue 的变化;
  7. 以 block 而不是高度相关的单像素做 bootstrap confidence interval;
  8. 在留出的 patch 上验证逆变换。

更灵活的模型为:

y=b+cmax(xx0,0)p, y=b+c\max(x-x_0,0)^p,

但参数耦合使其很容易过拟合。当元数据提示某个标准时,应优先使用已知范围端点和标准传递函数,而不是不受约束的曲线。

模型特征

8.4 无法配准时的分位数与直方图方法

若确实是同一帧但空间配准未知,可比较通道或 luminance quantile:

Qy(q)f(Qx(q)). Q_y(q)\approx f(Q_x(q)).

可从大量 quantile pair 估计单调 transfer。它适合提出 exposure/range/gamma 假设,但不能唯一识别:不同空间图像可能具有相同 histogram,matrix/gamut 变化也会改变各通道分布。应先用它提出候选曲线,再用已配准 patch 或测试图验证。

直方图线索:

8.5 推荐测试图案

A. 码值阶梯与 ramp

8-bit 测试至少包含精确码值 0、1、2、4、8、12、16、20、32、64、128、192、235、240、255,以及相应 10-bit 值。同时使用:

这样可以把 transfer interpretation 与 quantization spacing 分开。

B. PLUGE 与范围图

包括 below-black、black、near-black、white 与 above-white。8-bit narrow video 应明确标记 0、16、235、255;chroma 标记 16、128、240。范围错误会立即显现并可测量。

C. 50% 棋盘与频率扫描

用多个空间频率的等面积黑白棋盘,再做 downscale 或 blur。正确的线性光平均趋向 50% light,对应 sRGB ≈0.735357;非线性域平均趋向码值 0.5。再加入 zone plate,以暴露 kernel 与 mipmap 变化。

D. 饱和矩阵 patch

使用 red、green、blue、cyan、magenta、yellow、类肤色与中性 patch。601/709 matrix mismatch 会让 neutral gray 保持接近,却移动饱和 patch。加入接近 gamut boundary 的值以显露裁剪。

E. Chroma-siting 边缘

使用一像素宽的红/蓝、红/灰、蓝/灰垂直与水平交替边缘。分别检查 Cb/Cr plane 与重建 RGB。把假定的 chroma location 平移半个 sample,即可复现 fringe。

F. Alpha-compositing 靶标

使用 alpha 值为 1、0.75、0.5、0.25、0.01、0 的彩色形状,分别叠在黑、白和饱和背景上。比较 straight 与 premultiplied 表示。非线性错误与 premultiplication 错误会出现在不同边缘位置。

G. HDR 亮度 patch

对于 PQ,加入编码为已知绝对亮度的 patch,例如 0.005、0.1、1、10、100、203、1000、4000 cd/m²。对于 HLG,在明确 LWL_W 与 system gamma 的条件下加入 reference-white 与 peak-related 电平。若问题涉及实际 nit 而非解码数值,必须用仪器测量显示输出。

8.6 端到端验证流程

  1. 在 float linear light 中生成测试图。
  2. 用独立参考代码生成精确 sRGB、BT.709、pure-gamma、PQ 与 HLG 版本。
  3. 生成 full/narrow-range 版本,以及显式 601/709/2020 matrix 版本。
  4. 在 bitstream 与 container 两层写入匹配元数据。
  5. 生成故意冲突的文件,测试优先级。
  6. 经每个应用/工具解码到 planar float RGB。
  7. 对显示前 frame 做 hash 或数值比较。
  8. 通过已表征路径显示;关闭动态显示功能。
  9. 评估 EOTF 时,用 colorimeter/spectroradiometer 测量 patch。
  10. 归档应用版本、命令行、display profile、OS build、GPU 与截图。

如果只记录 viewer 看起来怎样,测试就是不完整的。

8.7 常见误诊


9. 正确的工程实践:应该在哪一层修

9.1 先修正语义,再改变样本

若像素正确、标签错误,就修标签。若标签正确而某个应用忽略它,就配置或替换该应用。只有在目标色彩表示确实改变,或档案修复需要反转一个已测得的历史变换时,才改变像素。

若原始像素其实是在另一套假设下创建,metadata-only repair 也并非无害;重新标注前必须对照已知参考验证。

9.2 运算应留在其语义要求的域中

不要因为“linear 永远正确”就盲目线性化。传递函数是表示的一部分;运算的物理或感知含义决定正确域。

9.3 使用足够精度与 dithering

尽可能在 float 或至少 16-bit integer 中解码和转换。避免反复 8-bit 往返。把 clipping 延迟到明确定义的 gamut/range boundary。最后降到较低整数位深时再 dither;不要用 dither 掩盖错误曲线。

9.4 让元数据冗余且一致

格式允许同时写 bitstream 与 container 声明时,应写入一致数值。保留:

自动化 CI 应拒绝互相矛盾的标签,并把解码结果与 golden patch value 比较。

9.5 分开 grading monitor、GUI viewer 与 consumer preview

参考输出应具有已知 display EOTF、peak、black、surround 与 signal range。GUI viewer 很有用,但经过 OS color management。consumer preview 本来就有意允许变化。不要为了让三者看起来一致而把无文档修正烘焙进 master。

9.6 谨慎对待 203 cd/m²

在相关 HDR 标准/工作流把 203 cd/m² 定义为 HDR reference white 时使用它。不要假定所有 SDR master、桌面白点或显示校准都应为 203 nit。记录一个数值究竟是 SDR reference-display white、HDR diffuse/reference white、graphics white 还是 display peak。

9.7 对经验 workaround 固定版本

若某个 legacy application 确实需要 corrective LUT,应按测得路径命名,例如:

AE_CS5_WIN_QT_H264_measured_inverse_x_pow_0p88.cube

记录源测试、范围、平面、精度与预期 hash。不要只命名为 quicktime_gamma_fix.cube


10. 流行说法与证据

流行说法 实际情况 证据强度
“sRGB 就是 gamma 2.2。” sRGB 是分段线性/带偏移 2.4 函数;2.2 是拟合速记,准确度取决于范围与误差指标。 A
“BT.709 gamma 是 2.4。” BT.709 规定 OETF;BT.1886 规定参考显示 EOTF。 A
“0.45 × 2.4 = 1.08,所以 1.2 是错的。” BT.709 有 offset 和变化的局部斜率;高调有效相机指数接近 0.5。ITU 明确把传统 SDR rendering intent 定义在 system gamma 约 1.2。 A/L
“相机 OETF 与显示 EOTF 应互为逆函数。” 它们的复合包含目标 OOTF;不要求等于 1。 A
“BT.1886 精确就是 V2.4V^{2.4}。” 仅当 LB=0L_B=0;否则 a,ba,b 改变曲线。 A
“CRT gamma 精确等于 2.5。” 2.5 是代表值;有效区间实测会变,常见约 2.35–2.55。 L
“Mac 显示器在物理上就是 gamma 1.8。” 有效系统由 LUT 补偿加普通 CRT 实现。 L
“Apple 专门为 LaserWriter 选择了 1.8。” 广义印刷/印前兼容性有证据;未找到一方 LaserWriter-specific 设计证明。 L/C,有限
“Snow Leopard 在 2010 年改了 Mac gamma。” Mac OS X 10.6 于 2009 年 8 月 28 日发布,并把默认 1.8→2.2。 B
“QuickTime 总会加 0.88 gamma。” 一个 2010 年测试的 AE CS5/Windows/QuickTime H.264 路径拟合为 x0.88x^{0.88};其他路径和版本不同。 C,路径特定
Levels(gamma=0.88) 会施加 x0.88x^{0.88}。” 归一化形式下实际为 x1/0.88x^{1/0.88},因此变暗。 B
“黑位抬升就是 gamma 错误。” Full/narrow mismatch 是仿射错误,应优先测试。 A/数学
“Y′ 就是 luminance。” Y′ 是非线性 RGB 的加权和;只有中性/特殊情况才等于物理 luminance Y。 A
“601/709 mismatch 只改变亮度。” 它主要造成依赖颜色的 RGB 错误;中性仍保持中性。 A/数学
“线性光处理视觉上永远正确。” 它适合辐射度学 light integration;部分标准有意规定 perceptual/code-space 运算。 A/工程
“PNG gAMA 比 ICC profile 优先。” 当前 PNG 优先级中 iCCP 高于 sRGBcHRM+gAMAcICP 最高。 A
“CSS 与 SVG brightness filter 使用同一空间。” CSS filter functions 使用 sRGB;SVG primitives 默认 linearRGB。 A
“Canvas readback 就是原始设备字节。” getImageData 可以转换到请求的 color space/pixel format。 A
“HDR-to-SDR 就是 gamma 转换。” 它是带绝对亮度/reference-white 决策的 rendering/tone/gamut mapping 问题。 A
“两张截图相同就说明链路正确。” 两条错误显示路径也可能相同;应验证解码数值、元数据与实测输出。 方法论

11. 附录

11.1 术语速查

术语 域映射 常见混淆
OETF scene-linear light → 非线性信号 被称为“display gamma”
inverse OETF 非线性信号 → scene-linear representation 与 EOTF 混淆
EOTF 非线性信号 → display-linear light 被假定为相机 OETF 的逆
OOTF scene-linear light → display-linear light 在简化 gamma 图中被省略
TRC 一般性的 tone-response curve,常指 ICC channel curve 被当成必然是纯 gamma
system gamma 在声明条件下的有效/OOTF 指数 被当成能精确描述分段曲线的单一指数
Y′ 非线性 RGB 的 luma-like 加权和 被称为物理 luminance Y
luminance Y 色度学空间中线性 RGB 的加权和 错用带撇号分量计算
narrow range 带 head/foot room 的标称合法视频范围 被称为“gamma-compressed range”
reference white rendering system 中规定的白电平 与 display peak 混淆
PQ 绝对 display EOTF 被当成相对 gamma
HLG scene-relative OETF 加 display OOTF 被当成单一固定显示曲线

11.2 参数速查

函数 关键参数
sRGB encode threshold 0.0031308;slope 12.92;exponent 1/2.4;scale 1.055;offset 0.055
sRGB decode threshold 0.04045;reciprocal slope 1/12.92;exponent 2.4
BT.601/709 OETF threshold 0.018;slope 4.5;exponent 0.45;scale 1.099;offset 0.099
BT.2020 OETF exact α=1.09929682680944…;β=0.018053968510807…;exponent 0.45
BT.2020 10-bit practical α=1.099;β=0.018
BT.2020 12-bit practical α=1.0993;β=0.0181
BT.1886 γ=2.4;a,ba,bLW,LBL_W,L_B 决定
Adobe RGB (1998) decode exponent 563/256=2.19921875
PQ m1=2610/16384m_1=2610/16384m2=2523/4096×128m_2=2523/4096\times128c1=3424/4096c_1=3424/4096c2=2413/4096×32c_2=2413/4096\times32c3=2392/4096×32c_3=2392/4096\times32
HLG a=0.17883277;b=0.28466892;c=0.55991073;1000 nits 时 γ=1.2

11.3 最小精确转换伪代码

# 编码源 RGB -> 编码目标 RGB。
# 源/目标函数必须是精确的命名函数,不能是“2.2-ish”之类标签。

def convert(rgb_code, decode_source, encode_destination,
            linear_rgb_matrix=None, rendering_transform=None):
    linear = decode_source(rgb_code)

    if linear_rgb_matrix is not None:
        linear = linear_rgb_matrix @ linear

    if rendering_transform is not None:
        # 显式选择的 OOTF、tone map、gamut map、exposure 或 adaptation。
        linear = rendering_transform(linear)

    return encode_destination(linear)

对于 Y′CbCr 输入,range normalization 与 inverse matrix 位于此函数之前。对于 Y′CbCr 输出,destination encoding 位于目标 matrix 与 range quantization 之前。对于 PQ,除非一个指定的 production transform 改变了域,否则解码值就是绝对 luminance。

11.4 分类参考文献

A — 标准与规范

[A-01] IEC 61966-2-1:1999, Multimedia systems and equipment — Colour measurement and management — Part 2-1: Colour management — Default RGB colour space — sRGB,含 Amendment 1。IEC publication page:https://webstore.iec.ch/publication/6169。公开参数 registry:https://registry.color.org/rgb-registry/srgb

[A-02] ITU-R BT.601-7 (03/2011), Studio encoding parameters of digital television for standard 4:3 and wide-screen 16:9 aspect ratios;OETF 见 §2.6.4,另见数字表示条款。https://www.itu.int/dms_pubrec/itu-r/rec/bt/r-rec-bt.601-7-201103-i!!pdf-e.pdf

[A-03] ITU-R BT.709-6 (06/2015), Parameter values for the HDTV standards for production and international programme exchange;OETF 见 Part 1 item 1.2,现行制作参数见 Part 2。https://www.itu.int/rec/R-REC-BT.709-6-201506-I/en

[A-04] ITU-R BT.1886-0 (03/2011), Reference electro-optical transfer function for flat panel displays used in HDTV studio production;见 Scope、Annex 1、Eq. (1)–(4)。https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.1886-0-201103-I!!PDF-E.pdf

[A-05] ITU-R BT.2020-2 (10/2015), Parameter values for ultra-high definition television systems for production and international programme exchange;OETF 见 Table 4,NCL/CL 见相应定义表。https://www.itu.int/rec/R-REC-BT.2020-2-201510-I/en

[A-06] SMPTE ST 2084:2014, High Dynamic Range Electro-Optical Transfer Function of Mastering Reference Displays. DOI:https://doi.org/10.5594/SMPTE.ST2084.2014

[A-07] ITU-R BT.2100-3 (02/2025), Image parameter values for high dynamic range television for use in production and international programme exchange;Tables 4–5、notes 5e–5f、Annexes 1–2。https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.2100-3-202502-I!!PDF-E.pdf

[A-08] ITU-R Report BT.2390-12 (03/2025), High dynamic range television for production and international programme exchange;尤其 §6.2 的 OOTF/system gamma。https://www.itu.int/dms_pub/itu-r/opb/rep/R-REP-BT.2390-12-2025-PDF-E.pdf

[A-09] ITU-R Report BT.2408-9 (03/2026), Operational practices in HDR television production;显示 luminance/reference white 见 Table 4。https://www.itu.int/dms_pub/itu-r/opb/rep/R-REP-BT.2408-9-2026-PDF-E.pdf

[A-10] ITU-R Report BT.2446-1 (2021), Methods for conversion of high dynamic range content to standard dynamic range content and vice-versa. https://www.itu.int/pub/R-REP-BT.2446

[A-11] ITU-T H.273 (03/2024), Coding-independent code points for video signal type identification;包含 colour primaries、transfer characteristics、matrix coefficients、range 与 chroma location 表。https://www.itu.int/rec/T-REC-H.273

[A-12] W3C, Portable Network Graphics (PNG) Specification, Third Edition,Recommendation 24 June 2025;§4.3 与 color-space chunk 各章。https://www.w3.org/TR/png-3/

[A-13] W3C, Filter Effects Module Level 1,18 December 2018;§§8–10(feCompositefeComponentTransfercolor-interpolation-filters)。https://www.w3.org/TR/filter-effects-1/

[A-14] WHATWG, HTML Living Standard;Canvas 2D context、color spaces、ImageDatagetImageData settings。https://html.spec.whatwg.org/multipage/canvas.html

[A-15] W3C, CSS Color Module Level 4;预定义 sRGB 与 Display-P3 spaces 及 transfer functions。https://www.w3.org/TR/css-color-4/

[A-16] IEC 61966-2-2:2003, Extended RGB colour space — scRGB。公开 ICC registry entry:https://registry.color.org/rgb-registry/scrgb

[A-17] ICC, Embedding ICC Profiles in JPEG Files,technical note;APP2 chunk structure。https://www.color.org/technotes/ICC-Technote-ProfileEmbedding.pdf

[A-18] ISO/CIE 11664-6:2014, Colorimetry — Part 6: CIEDE2000 colour-difference formula. https://www.iso.org/standard/63731.html

[A-19] ITU-R BT.2035, A reference viewing environment for evaluation of HDTV programme material or completed programmes. https://www.itu.int/rec/R-REC-BT.2035

[A-20] ITU-R BT.2124-0 (01/2019), Objective metric for the assessment of the potential visibility of colour differences in television. https://www.itu.int/rec/R-REC-BT.2124

[A-21] ISO/IEC 14496-12, ISO base media file formatcolr/colour-information box family;nclx 语法应查阅现行版本。ISO catalogue:https://www.iso.org/standard/83102.html

[A-22] ITU-T H Supplement 15 (2017), Conversion and coding practices for HDR/WCG Y′CbCr 4:2:0 video with PQ transfer characteristics;另见关于 HDR/WCG signalling 与 chroma location 的 H Supplement 19。https://www.itu.int/rec/T-REC-H.Sup15

B — 厂商/项目一手来源

[B-01] ICC Three Component Color Encoding Registry, sRGB;公开的精确 encoding characteristics。https://registry.color.org/rgb-registry/srgb

[B-02] Adobe, Adobe RGB (1998) Color Image Encoding,May 2005;ICC registry entry 给出 gamma 2.19921875。https://www.adobe.com/digitalimag/pdfs/AdobeRGB1998.pdfhttps://registry.color.org/rgb-registry/adobe-rgb-1998

[B-03] ICC registry, scRGBscRGB-nlhttps://registry.color.org/rgb-registry/scrgb

[B-04] Apple Technical Note TN2162, Uncompressed Y′CbCr Video in QuickTime Files,published 14 December 1999;见 colrnclcgama 与旧 Macintosh graphics conversion 各节。https://developer.apple.com/library/archive/technotes/tn2162/_index.html

[B-05] Apple, QuickTime File Format Specification(archive);包含 gamma/color information 的 image-description extensions。https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/

[B-06] Adobe, Color management — After Effects,updated 27 March 2026;working space、linearization 与“Blend Colors Using 1.0 Gamma”。https://helpx.adobe.com/after-effects/desktop/adjust-colors/color-management/color-management.html

[B-07] Adobe, How Color Management works — Premiere,updated 7 January 2026;input、working、output、tone mapping 与 gamut compression。https://helpx.adobe.com/premiere/desktop/correct-color/set-up-color-management/how-color-management-works.html

[B-08] FFmpeg project, FFmpeg Filters Documentationeqlutcolorspacezscale;应查阅与实际部署 release 相对应的源码。https://ffmpeg.org/ffmpeg-filters.html

[B-09] VapourSynth R76 documentation, std.Levels;gamma 方向与 planeshttps://www.vapoursynth.com/doc/functions/video/levels.html

[B-10] AviSynth+ documentation, Levels;精确 1/γ1/\gamma 公式与 YUV 行为。https://avisynthplus.readthedocs.io/en/latest/avisynthdoc/corefilters/levels.html

[B-11] mpv stable manual;color management、linear downscaling、target TRC/peak、ICC、gamma factor 与 tone mapping。https://mpv.io/manual/stable/

[B-12] libplacebo documentation/source;GPU color-management 与 tone-mapping pipeline。https://libplacebo.org/https://code.videolan.org/videolan/libplacebo

[B-13] WebKit Bug 185343, “CSS filters which reference SVG filters fail to respect the color-interpolation-filters of the filter”;reported/fixed May 2018。https://bugs.webkit.org/show_bug.cgi?id=185343

[B-14] WebKit Bug 136418 及相关 Bug 212649;历史 linearRGB Gaussian-blur/filter 行为。https://bugs.webkit.org/show_bug.cgi?id=136418

[B-15] Mozilla Bug 948265, “Render CSS Filters using Moz2D”;verified fixed,milestone Firefox 34。https://bugzilla.mozilla.org/show_bug.cgi?id=948265

[B-16] Chromium Issue 41007781;可公开索引的 feGaussianBlur banding 报告;本次调研期间,当前 tracker 状态因需登录而无法取得。https://issues.chromium.org/issues/41007781

[B-17] Skia Issue 362116527;可公开索引的 sRGB/Display-P3 SVG feColorMatrix 差异;本次调研期间,当前状态因需登录而无法取得。https://issues.skia.org/issues/362116527

[B-18] WebKit, Wide Gamut Color in CSS with Display-P3;浏览器 color matching 与 untagged-image assumptions。https://webkit.org/blog/10042/wide-gamut-color-in-css-with-display-p3/

[B-19] Mozilla, Firefox 89 release notes for developers / color management changes on macOS;untagged images 按 sRGB 处理。https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/89

[B-20] Apple Newsroom, “Apple to Ship Mac OS X Snow Leopard on August 28”,24 August 2009。https://www.apple.com/newsroom/2009/08/24Apple-to-Ship-Mac-OS-X-Snow-Leopard-on-August-28/

[B-21] Apple 已归档的 Mac OS X 10.6 refinements 文本:“The default gamma has been changed from 1.8 to 2.2…”。原页面已下线;同期引文保存在 [C-06]。应把这句话视为存档厂商声明,而不是仍在线的 support page。

[B-22] Microsoft, Use DirectX with Advanced Color on high/standard dynamic range displays;scRGB linear values 与 SDR white convention。https://learn.microsoft.com/windows/win32/direct3darticles/high-dynamic-range

[B-23] Adobe, Color basics — After Effects;linear-light compositing 指南。https://helpx.adobe.com/after-effects/desktop/adjust-colors/color-basics/color-basics.html

[B-24] FFmpeg Trac #9637;container colr 与 SPS VUI color metadata 行为。https://trac.ffmpeg.org/ticket/9637

C — 社区与经验来源

[C-01] Vitrolite, “The QuickTime Gamma Bug”,31 December 2010。AE CS5/Windows/QuickTime 经验测试,包括 x0.88x^{0.88} 以及独立的 QuickTime Player contrast/range 结果。https://vitrolite.wordpress.com/2010/12/31/quicktime_gamma_bug/

[C-02] ProVideo Coalition,After Effects CS3/QuickTime gamma-adjustment 讨论,31 October 2007。本文仅用它证明 Adobe 当时提供过 legacy compatibility 选项,以及同期存在相关行为报告。

[C-03] Video Copilot,QuickTime gamma-shift 工作流讨论,17 June 2008。仅用于证明这一类 workaround 当时已经流传,不作为规范机制证据。

[C-04] AnimeMusicVideos forum,2013 年讨论;使用 Levels(0,0.88,255,0,255) 并链接 2010 年实测文章。用于证明社区传播。

[C-05] SilentAperture, Advanced Encoding Guide — The 0.88 gamma bug. https://silentaperture.gitlab.io/mdbook-guide/filtering/detinting.html。当代配方;机制主张仍属于 C 类。

[C-06] Creative COW, “Great news: default gamma in Snow Leopard will be 2.2”,9 June 2009;引用 Apple 当时在线的 refinements page。https://creativecow.net/forums/thread/great-news-default-gamma-in-snow-leopard-will-be-2/

[C-07] Apple Support Communities 与制作论坛中 2006–2009 年 QuickTime/H.264/ProRes gamma-shift 报告。仅用于确立时间线与差异性;单个帖子不能证明通用变换。

L — 独立技术文献

[L-01] Charles Poynton, Frequently Asked Questions about Gamma,1998 revision;CRT 指数范围、Macintosh 有效 1.8 行为、印刷/imagesetter 讨论。https://www.poynton.ca/pdf/GammaFAQ.pdf

[L-02] Charles Poynton, “The rehabilitation of gamma”,SPIE/IS&T Electronic Imaging 时代技术论文;术语与 system-rendering 讨论。https://www.poynton.ca/PDFs/Rehabilitation_of_gamma.pdf

[L-03] BBC Research & Development, White Paper WHP 283, High Dynamic Range Television and Hybrid Log-Gamma / transfer-function engineering discussion;有效 SDR 相机指数接近 0.5、显示 2.4、系统约 1.2。https://downloads.bbc.co.uk/rd/pubs/whp/whp-pdf-files/WHP283.pdf

[L-04] GTE Laboratories, US Patent 3,934,171 (1976);电子枪驱动/束流电流幂律行为。https://patents.google.com/patent/US3934171A/en


可复算说明

配套 gamma-analysis-repro.py 实现了 sRGB、BT.709、BT.1886、PQ、HLG、CIE Lab/CIEDE2000、矩阵算例,以及本文全部数值误差表。脚本会写出机器可读的 gamma-analysis-results.json。若要把文中数字用于不同位深、黑位、白位、码值范围、传递函数组合或感知指标,应先重新计算。