依旧先进编码
在上一篇 介绍 DXO 是如何实现高效率压缩的文章中,提到他的提高压缩效率的方式之一就是引入了 JPEG-XL 这种先进编码格式来存储 DNG 中的图像数据。
最著名的 DNG 转换软件 Adobe DNG Converter 其实也是支持 JPEG-XL 编码的,虽然它还没有正式出现在 UI 中,但可以通过命令行参数来调用这个功能,比如说实现近似于 DXO 的压缩效果:
EXE -lossy -jxl_effort 3 -jxl_distance 0.01 file.ARW
这个参数组合产出的是 “Linear RAW” 而非 “Bayer RAW”,已经经过了解马赛克,线性化等处理。文件体积相比输入的 RAW 文件可能会更大,比如某一张 33MP 的索尼 a7C2 的无损压缩 RAW 文件体积是 39.7MB,经过 Adobe DNG Converter 处理后是 45.5MB,显然不太符合我们的需求。
通过另一个参数 -lossyMosaicJXL 可以输出使用 JPEG-XL 压缩的 Bayer RAW 文件,但无法控制压缩参数,实际使用的 JXL Effort 是 7,JXL Distance 是 0.2,Decode Speed 是 4。
EXE -lossyMosaicJXL file.ARW
对于同一张 RAW,压缩后的 DNG 文件体积仅为 13.3 MB。
如果希望使用 JPEG-XL 的无损模式,可以替换为 -losslessJXL 参数,文件体积为 27.9 MB,这是目前压缩效率最高的无损 RAW 文件格式,在 Adobe 的软件中打开也是无缝的体验,如果你需要一个高效的无损格式,推荐使用。
依旧非线性映射
直接用 tifffile 打开这个有损压缩的 DNG 文件,发现它并不能和原始的 RAW 在数值上很好的对齐,其数值撑满了 0-65535 范围,且亮度分布也与原来的 RAW 不太相同,这时就需要考虑是否也像 DXO 那样引入了某种非线性映射来优化码值分布或压缩码值范围。
但这个 DNG 里并没有 LinearizationTable 标签,经过 Codex 的一番查找,在 OpcodeList2 中找到一个名为 MapPolynomial 的字段,以下是这一字段在规范中描述的中文翻译。
此操作码通过多项式函数映射图像的指定区域和平面范围。 要受影响的图像区域的边界由 Top、Left、Bottom、Right 参数指定。 要修改的第一个平面以及平面数量由 Plane 和 Planes 参数指定。如果 RowPitch 不等于 1,则仅从 Top 开始每隔 RowPitch 行受到影响。如果 ColPitch 不等于 1,则仅从 Left 开始每隔 ColPitch 列受到影响。 映射函数是 Degree 次多项式。Degree 的最大允许值为 8。系数按递增顺序存储,从零次系数(常数项)开始。
总之,就是需要对图像中的指定区域做一个多项式映射函数,LossyMosiacJXL 模式下采用的是一个三次多项式,系数可能与 RAW 的最大值和最小值有关,用于将原本 RAW 的数值经过黑白电平矫正后拉伸到占满整个 16 bit 范围的数值分布。
这一步实际上增加了需要压缩的数据量,如果原本的 RAW 是 14 bit 的,且占满了码值范围,会增加 (16 - 14) / 14 = 14.3% 的数据量,下图展示一个占满码值范围的 RAW 的非线性映射的解码函数。
如果原先的 RAW 没有占满 14 bit,则增加的更多,极端的例子是黑场图片,原本的 RAW 的数值可能只是 512 ± 20,经过映射后也占满了整个 16 bit 范围,增加了大量数据,下图展示了一个黑场图片的非线性映射的解码函数。
作为代价,这个黑场图片拉伸后再用 JPEG-XL 压缩的文件体积达到了 20.8 MB,而直接用无损模式的 JPEG-XL 编码只需要 4.8 MB,出现了有损模式反而更大的情况。
这种非线性映射也起到了将码值更多分配给暗部的功能,但目前这样直接拉伸码值的做法值得商榷。
CFA RAW 重排
在编码 CFA RAW 的时候,并不会直接将原始图像进行编码,而是会按照 CFA 的排列方式进行重排,把同一个颜色的像素放在一起,这样可以提高压缩效率,重拍后的图像相当于几个子图按照原本的 CFA 位置排列在一起。

还是以之前那张 RAW 作为例子,Adobe DNG Converter 获得的无损压缩 JXL DNG 的文件体积是 27.9 MB。使用 JXL 编码器直接以无损模式编码 numpy array 形式的数据来模拟,如果直接编码 CFA RAW 而不重排,文件体积是 36.63 MB,重排后再编码的文件体积是 26.77 MB,比较接近 Adobe 的结果。
JPEG-XL 这种先进编码格式还支持多通道图像的编码,可以把不同位置的 CFA 当作多个通道,重排后的图像相当于一个 4 通道的图像,编码后获得的文件体积是 26.84 MB。
富士的 X-Trans 这种比较复杂的排列也是一样,重排为 X-Trans 的最小重复单元,为 6x6 共 36 个子图(看得我有点密恐)。

下一步?
在无损方面,采用 JPEG-XL 无损模式编码的 DNG 无论是兼容性还是压缩效率都是目前最好的选择了。
而对于 RAW 这种信息密度较低的图像来说,适当的接受一些有损压缩,就可以大幅提高压缩效率,目前两种高效的有损压缩方式是 DXO 的高保真压缩和 Adobe DNG Converter 的 LossyMosaicJXL 模式,但都存在一些实践上的小问题,比如存一个 10bit 的 Linear RAW 是否划算,这个非线性映射的方式是否合理等。
接下来,我会尝试使用 JPEG-XL 的一些高级设置,尝试在保持视觉质量和轻微有损的前提下,进一步提高压缩效率。