PNG 为什么天生体积大
PNG 是无损格式。这句话的意思是,它不允许为了缩小体积而丢弃任何一个像素的信息。解码出来的图必须和原图逐位相同。
能做到的只有压缩冗余。PNG 用的是 DEFLATE,先把数据里重复的模式找出来,再用更短的编码表示。它擅长对付大片同色和规则重复,对照片那种每个像素都在变的图像基本无能为力。
算一下就清楚了。一张 1920 × 1080 的真彩色 PNG,每个像素占 24 位,RGB 各 8 位。原始数据 1920 × 1080 × 3 字节约等于 6.2MB。多数照片压完还剩 2 到 4MB。
作为对比,同样一张照片存成 JPEG 质量 85,通常只有 300 到 600KB。差了将近十倍,代价就是丢掉了一部分肉眼不太容易察觉的细节。
调色板量化在做什么
真彩色 PNG 每个像素独立存 RGB 三个值。但很多图里的颜色其实没那么多,界面截图、图标、图表,经常只有几十种到几百种颜色。既然用不到几万种,为什么每个像素还占 24 位。
调色板量化就是冲着这个浪费去的。它把整张图用到的颜色归并到一个色表里,最多 256 种,然后每个像素只存一个索引值,指向色表里的哪一格。
1920 × 1080 的图,从每像素 24 位降到 8 位,数据量直接掉到三分之一。再叠加 DEFLATE,实测压缩率通常在 60% 到 80% 之间。这就是界面截图能被压掉七成的原因。
代价在于归并。原本有 2,000 种颜色的图,硬塞进 256 格,就得让一些相近的颜色合并成同一个值。合并的痕迹在渐变区域最明显,会看到一圈一圈的色带。
颜色数越少,量化越接近无损。这是理解这套方法的关键。一张只有 40 种颜色的扁平图标,量化到 256 色一个像素都不会错,压缩率还极高。一张有 20 万种颜色的日落照片,量化必然留下可见的画面损失。
透明通道为什么不能丢
带透明的 PNG 多了一层麻烦。每个像素除了 RGB,还有 alpha 值,控制这个像素的透明程度。
纯透明和纯不透明好办,二分就行。麻烦的是半透明像素,也就是抠图边缘那些和背景混了一点的过渡点。
索引色格式要在 256 格里同时安排颜色和透明度,空间非常紧张。处理不当的结果很直观,抠好的图贴到别的背景上,边缘出现一圈白边或者锯齿。白边来自原来的白色背景残留,锯齿来自半透明像素被粗暴地二值化了。
所以判断一个 PNG 压缩工具靠不靠谱,看它有没有保留透明通道,以及边缘处理得干不干净。把半透明区域直接砍掉的做法,压缩率会很好看,图也基本废了。
截图和照片的差别在哪
回到开头那个观察,同一套参数,截图能压掉七成,照片几乎压不动。原因就是颜色数。
界面截图的颜色来自设计稿,是一组离散的确定值。白色背景、灰色边框、蓝色按钮、黑色文字,加起来常见也就几十种,复杂点的界面几百种。量化到 256 色,基本能把所有颜色装下,视觉上找不出差别。
照片是连续色调。光线在每个表面的过渡都在产生新颜色,一张普通照片的颜色数轻松过十万。把它压到 256 色,等于把连续渐变切成 256 个台阶,色带会非常明显,看一眼就知道。
想让照片的体积降下来,路子不是量化,是有损压缩。JPEG 和 WebP 那类格式做的事情,正是允许丢掉人眼不敏感的高频细节,换体积。用无损的方法压有损的内容,方向本来就是错的。
什么时候该换成 WebP
WebP 是这几个问题的一个折中答案。它有有损和无损两种模式,无损模式在同等画质下通常比 PNG 小两成到三成,有损模式比同画质的 JPEG 小两成半到三成半。而且它支持透明通道。
但别急着全换。几个场合还是 PNG 更合适。
需要老系统兼容。现代浏览器都支持 WebP,但一些老旧的系统内置浏览器、旧版办公软件、部分印刷流程仍然不认。要发给别人、对方用什么软件打开你不确定的时候,PNG 更稳妥。
要进印刷流程。印前环节对格式的支持比网页严格,PNG 的接受度高于 WebP。
体积本来就不大。一张 20KB 的图标,换成 WebP 省下 5KB,不值得为它多一个格式。
判断标准可以简化成这样。用于自己网页上展示的照片类图片,转 WebP 是更省的选择。要发给别人、要印刷、或者图片本身就很小,继续用 PNG。