PDF 更偏爱 JPEG

如果制作 PDF 时需要嵌入图片,并且希望最终体积最小,那么有损压缩的图片用 JPEG,无损压缩的图片用 PNG。

PDF 更偏爱 JPEG

webp 非常省空间,有损压缩比 jpeg 省 25%~34%,无损压缩比 png 省 26%,因此我常常使用 webp。

但有一次我在 Markdown 里面嵌入了总计 1MB 的 webp,导出的 pdf 竟高达 10MB。

类似的情况:下面是一个开发者,他费尽心思将一个PNG从144KB优化到55KB,但生成的PDF体积却是143KB,几乎和优化前的原图一样大。

PDF file size too large - option to bypass png image recompression? · Issue #3359 · dompdf/dompdf
I have a problem with dompdf producing larger file sizes than expected. My document is actually very simple because it consists of a single image inserted with an <img> tag and a short text overlai…

这是为什么呢?

PDF 生成器在处理图片的时候,主要使用的是两种编码方式(其他格式不太常见,已忽略)

  1. 有损编码:DCTDecode,就是 JPEG 使用的编码方式。
  2. 无损编码:FlateDecode,就是 PNG 使用的编码方式。

当图片本身是 JPEG 的时候,(大部分) PDF 生成器会直接使用这张图片本身的数据,也就是说,图片多大,PDF 的体积就会增长多大,这被称作直通(Pass-through)

否则,图片将会被重编码(Re-encode)。也就是说,图片首先被解码成原始像素,然后使用 FlateDecode 进行编码,而这种编码方式对照片类图像(连续色彩、复杂细节)而言非常低效。

WebP 的压缩优势无法被 PDF 原生保留,因为 PDF 图像模型不支持 WebP,需要完全解码为位图后再重新编码。
而 PNG 虽然同样使用 FlateDecode,但是 PNG 是先滤波之后再打包的,PDF 使用的则是原始值,因此针对 PNG 本身的压缩也会失效。

因此,最佳方案是:

  1. 使用 JPEG:对于照片等对质量要求不大的图片,使用 jpeg 就可以了。如果原图不是 jpeg,也建议导出为 JPEG(85% 质量是甜点区)
  2. 使用 PNG:
    1. 如果是(没有大面积图片的)屏幕截图,想要让文字和 UI 等清晰可见,则选择 PNG。大部分屏幕截图本来就是 PNG。
    2. 图片有透明通道,那就只能用 PNG 了。
    3. logo 等需要清晰边缘的场景。这种场景一般 png 也不会很大。
  3. 使用 SVG: 如果有 SVG 那就无脑用 SVG,质量最高,体积最小。

如果要使用 PNG,同时还想要体积尽量小,要做的应该是减小图片的分辨率,而不是压缩。

PDF 的痛点实在是太多了。遗憾的是,PDF 已经垄断了这个世界。最重要的是,它虽然不完美,但是够用,因此估计很难看到替代品取代它了。