仅用 PSNR 和少量的图片样本评价编解码和视觉表现是相当局限的,结论需要更多的测试以验证。
输出格式
长期以来,在摄影软件里能选的输出格式为 JPEG,TIFF 等。我最常使用的输出格式便是软件中能选到的最高质量的 JPEG,仅在需要打印等情况下用 16bit TIFF。
这样方案的缺点是:最高质量的 JPEG 也存在一定的有损压缩(与 TIFF 对比,PSNR 在 48dB 左右),文件体积比较大,位深度也只有 8bit,如果要作为一种“存档”目的的数字母版,似乎规格有点太低。而选择 16bit TIFF 的话,虽然可以做到无损和高位深,但动辄百兆的体积有些不可接受。
现在有这么多的先进编码格式,是否可以用 JPEG-XL 或 AVIF 来改变这一情况?经过一些简单的图像质量评价和文件体积测试,我决定在未来一段时间采取如下的图片存档方案:
流程图中的文件体积和 PSNR 使用一张 3840 长边的照片测试得到的,相机得到的照片体积一般会更大些。
母版的选择:JPEG-XL
图中,从左到右是从图片编辑软件出发,逐渐降低质量和文件体积,到存档和分享的过程。
图片编辑软件最常见的高规格输出是 16bit TIFF,而 JPEG-XL 支持 16bit 位深,虽然无损压缩模式的压缩率不够理想(大约 1.5:1),但只要能接受一点点有损压缩,就能实现非常高的压缩率。
在 JPEG-XL 中,使用类似锥响应的 XYB 空间中的距离(distance)来衡量图像质量,distance 为 1 时,表示一个 JND(恰可察觉差)单位,在 JPEG-XL 中被描述为“视觉无损”。尽管 distance 为 1 时的压缩率非常诱人,有时甚至能达到 40:1,但此时的图像质量不如以往最大质量的 JPEG,PSNR 在 42dB 左右,我们的新时代数字母版在图像质量上总不能比之前还菜吧。
为了平衡压缩率和图像质量,调试出的 distance 大约会在 0.1-0.3 之间,这样能够实现高位深下,在图像质量上超越之前最大质量的 JPEG,文件体积缩小到原本的 50% 以下。例如一张图片,JPEG 和 JXL 的对比如下表:
| 格式 | distance | 文件体积 | PSNR |
|---|---|---|---|
| JPEG | - | 26.0 MB | 48.6 dB |
| JPEG-XL | 0.1 | 22.9 MB | 52.9 dB |
| JPEG-XL | 0.2 | 15.2 MB | 49.7 dB |
| JPEG-XL | 0.3 | 11.7 MB | 47.9 dB |
因此,新流程的母版格式是:一个高质量的 JPEG-XL,用于代替原本的 TIFF,在无损和视觉无损之间的质量时,文件体积仅为 TIFF 的不到 1/10,还比原本的 JPEG 小 50%。
为什么不 AVIF
如果单纯衡量 PSNR,AVIF 在相同质量下比 JPEG-XL 有更小的文件体积。在存档这一步时不选择 AVIF 的原因是位深。AVIF 本身支持 8,10,12 三种位深度,可以通过编码 12 和 8bit 两帧来实现 16bit 位深度。虽然编辑后的图像量化成 16 还是 12bit,甚至是 10bit,观看起来都没有区别,包括未来一段时间内显示终端也都只会停留在 8bit,但从存档和“洁癖”的角度,我还是希望有一个 16bit 位深的母版,至少听起来很爽。
作为对比,也使用一张图来测试:
- AVIF 在 10bit 下实现 56.78dB PSNR 时,文件体积为 10.02MB。JPEG-XL 实现基本相同的 PSNR 时,文件体积略大,为 10.79MB。
- AVIF 在 10bit 下实现 51.506dB PSNR 时,文件体积为 5.51MB。JPEG-XL 实现略低的 51.427dB PSNR 时,文件体积略大,为 7.19MB。
需要注意的是,这个结果仅有一张图测试,也许是 AVIF 更适合这张图的特性,且 PSNR 也不是一个特别好的评价指标。不过 AVIF 在稍低码率下的优势是得到了广泛共识的,在非常接近无损的情况下,AVIF 的性能则接近或略逊于 JPEG-XL。
不过得益于 AVIF 优秀的浏览器兼容性和强大的低码率性能,它将成为分享时的首选格式。
关于 AVIF 的 16bit 模式,编解码用法如下:
avifenc --depth 12,8 --lossless input.png output.avif
avifdec --sato -d 16 output.avif decode.png
AVIF 的无损模式非常糟糕,这个 16bit 模式也很一般,有损压缩时,相同 PSNR 下,JPEG-XL 体积是 AVIF 的 1/4 到 1/9。
二次压缩
数字母版听起来很美好,又小又厉害,但毕竟存在压缩,不希望影响到下一步的分享和使用。
实际使用中,还需要从母版导出用来分享的 JPEG 等格式,意味着我们需要对已经被压缩过的 JPEG-XL 再做一次压缩。这样的二重压缩会带来额外的损失,由于第一步时非常接近无损,还有从高位深到低位深带来的额外冗余。经过测试,二次压缩得到的 JPEG 或 AVIF 能够比较接近从 TIFF 直接压缩得到的 JPEG 或 AVIF。使用相同的压缩质量,相比 TIFF 的 PSNR 的降低在 1-2 dB,且随着压缩幅度的增加,差距会逐渐缩小,例如二次压缩到 AVIF 时,质量设置为 80,TIFF 获得的 AVIF PSNR 为 40.67dB,而从 JPEG-XL 二次压缩获得的 AVIF PSNR 为 40.59dB。
遗憾的是,如果原本的流程是直接输出最高质量的 JPEG,现在的流程是先输出 JPEG-XL,再用最高质量输出到 JPEG,新的 JPEG 一定比之前的 JPEG 质量略差。
但如果以前的输出流程不是最高质量的 JPEG(我有时候为了省些体积,会选择 90 或 95 的质量),那么现在的流程中,在二次压缩到 JPEG 时选择 95 或 100 的质量,得到的 JPEG 质量就会比原本的 JPEG 高。
目前,我采用的两种二次压缩格式分别是 JPEG 和 AVIF,JPEG 为了最大的兼容性(比如安卓手机),AVIF 则用在 iPhone 以及网络用途。AVIF 的质量设置通常在 70-85 之间,4K 照片的体积在 1-2 MB,比如博客中的大多数照片都是这个规格。
如何用起来?
ACR 和 Lightroom
如果你常用 ACR 或 Lightroom,在导出时就已经可选这些先进格式了。ACR 把质量选项重新映射了一遍,给用户展示的是 0-12 个等级,13 为无损。
经过少量的测试,等级 12 的 JPEG-XL 大约对应 distance 0.1,等级 10 大约是 0.6。可以尝试等级 11 或 12 的 JPEG-XL 来生成母版文件。
AVIF 方面,等级 12 的 Quality 非常高,PSNR 比等级 12 的 JPEG-XL 还要高不少,大致相当于 distance 0.035 的 JPEG-XL,等级 11 则比较接近等级 12 的 JPEG-XL。更低质量的 AVIF 则可做分享用途。
ACR 中的 JPEG 即使选到最高等级,也不如 Capture One 或其他编码器设置成 100 的质量,PSNR 略低 3dB,文件体积也会小一些。
Capture One
像 Capture One 这种格式支持比较少的(甚至不支持 16bit PNG),则要通过 TIFF 中转一下。
先保存无损的 TIFF,然后转码为 PNM 格式,这是一种约等于裸码值的无压缩格式,也可以是 PNG,这一步的目的是让 libjxl 的例程读取,然后运行:
cjxl input.pnm output.jxl -d 0.2
即可完成 JPEG-XL 的压缩,如果需要 EXIF 的话,要额外加一步从 TIFF 搬运到 JPEG-XL 的过程。
从 JPEG-XL 到 AVIF 的转换也类似,推荐使用 PNG 作为中间格式。
djxl input.jxl output.png
avifenc -d 10 -q 80 output.png output.avif
当然也可以直接修改和编译 libjxl 和 libavif 实现更高效的转换。
短暂的拥抱未来
这个方案已发现不少问题,我希望给他一些时间,先真实的用起来,逐步发现改进之处,至少能短暂的拥抱一下未来。
以下是遇到的一些问题和思路:
- JPEG-XL 的编码速度:
libjxl纯编码速度在 M1 Pro 上大约为 10 MP/s,也就是一张 30 MP 的照片大约需要 3 秒,再加上一些额外的 IO 开销,有优化的空间。 - 在 macOS 上,打开一个有很多 JPEG-XL 文件的文件夹时,需要一些时间来生成预览图。尝试通过嵌入一个很小的 JPEG 预览图来解决。
- JPEG-XL 的兼容性差,作为母版格式,兼容性差点也可以理解,但还是希望随着时间的推移,JPEG-XL 能够被更多的应用和系统支持。
- HDR 支持,涉及这么多不同的图像格式,要在它们之间实现转换,还保留 HDR 信息,估计会比较麻烦。设想一下,如果真的需要输出 HDR,16 bit 搭配 PQ 应该也足够用。
- 广色域支持,有想过在母版这一层换成 P3 甚至 2020 色域,但需要在转码为分享格式的步骤引入色彩管理和色域变换。