一张 4.2MB 的图,把朋友的详情页卡了三天
前阵子帮开店的姐们儿收拾商品详情页,后台单张图卡 500KB,她上传老失败。她就找了个“在线图片压缩”,压完传上去,自己看着还行,结果买家评论区有人说“图好糊,是不是盗图”。她急了,来回压了五六遍,越压越糊,最后那张图连瓶身上的成分表都认不出来。
我拿她那张原图做了个测试——iPhone 14 Pro 拍的 HEIC,4032×3024,4.2MB。目标是压到 200KB 上下,一共试了 7 种方式,在同一块 4K 显示器上并排放大到 200% 看。结果挺打脸的,问题真的不在“质量”那个数字上。
7 种压法,实测体积和观感
下面这些数字是同一张图跑出来的,你的图不一样,但趋势差不多。
| 压法 | 参数 | 体积 | 200% 下能看出什么 |
|---|---|---|---|
| 某在线压缩站 | 默认 | 186KB | 整体还行,但瓶身红色标签边缘有一圈彩色噪点 |
| PS 另存 JPEG | 品质 45 | 192KB | 大块色斑,天空过渡出现明显台阶 |
| ImageMagick q60 | -quality 60 -sampling-factor 4:2:0 |
178KB | 糊,毛发细节全平了 |
| mozjpeg q78 | -quality 78 -sampling-factor 4:2:0 -strip |
205KB | 基本和原图分不出来 |
| WebP q72 | cwebp -q 72 -m 6 -mt |
164KB | 比 mozjpeg 那版还干净一点 |
| AVIF q30 | avifenc --min 20 --max 32 -s 6 |
142KB | 最干净,体积也最小 |
| JPEG q78 不降采样 | -quality 78 -sampling-factor 4:4:4 |
268KB | 体积超标,观感提升却很有限 |
看出来了吧,同样 180KB 上下,mozjpeg 和 WebP 出来的东西比老式 JPEG 编码器好一大截,AVIF 甚至能用 142KB 干掉别人 268KB 的效果。这不是玄学,是编码器本身的进步——mozjpeg 重写了熵编码和量化表,AVIF 直接换成了 AV1 的帧内编码。
所以第一个反直觉的点:把图压糊的往往不是 quality 数字,而是编码器和色度子采样这两个你根本没注意的东西。 4:2:0 的意思是把色彩信息砍成宽高各一半,亮度保留原样,人眼对色彩本来就不敏感,一般看不出来。但你要是拍的是红底商品图、或者图里有大片饱和色,4:2:0 就会在边缘爆出一圈彩色噪点——这就是我朋友那张图“看起来脏”的真正原因。
比参数更致命的,是你压了五遍
这个坑我自己也踩过。以前图省事,觉得“每压一次只掉一点点”,就反复来回导。实际上 JPEG 每存一次就是一次新的有损编码,误差会累积,行话叫 generation loss。我试过把同一张图 q80 连压 5 次,和一次 q55 比——五次的明显更烂,尤其天空和大面积渐变区域,会出现一层一层的色带,学名叫 banding。
所以压缩这个事,原则是从原图出发,一次压到位。手里的图已经被压过一轮了,就尽量只做尺寸缩放,别再动质量参数。
顺带说个我见过最多人问的:改 dpi 能不能减小文件?不能。对 JPEG/PNG 来说 dpi 就是写在文件头里的一个数字,72 改成 300,像素一个没变,文件大小一个字节都不掉。网页上显示多大只取决于像素宽高和 CSS,跟 dpi 半毛钱关系没有。那些“把 dpi 调到 72 就能变小”的教程,纯属误导。
还有一个更隐蔽的:iPhone 拍的 HEIC 转成 JPEG 的时候,HDR 增益图会丢,天空、逆光那部分会直接塌成死白。要转的话用支持 HDR gain map 的工具,或者干脆别转,直接输出 AVIF。
我自己常用的一套流程,照着敲就行
前提:装个 ImageMagick 7(命令是 magick 不是 convert),再装 cwebp、avifenc。
第一步,先定尺寸,别急着压。 网页正文图 1920 宽基本够;要上 Retina 就出两套,用 srcset 让浏览器自己挑。这一步能省掉 80% 的体积,比调 quality 有用得多。
magick input.heic -resize 1920x -strip -quality 82 -sampling-factor 4:2:0 out.jpg
-strip 是砍掉 EXIF 和缩略图,手机照片这一下能省 3%~10%,有时候能省几十 KB。
第二步,要更小就上 WebP。 -m 6 是压缩强度拉满,慢一点但值得;-mt 开多线程。
cwebp -q 75 -m 6 -mt -metadata none in.png -o out.webp
第三步,追求极致上 AVIF。 就是慢,4000px 的图我笔记本上跑了十几秒。别批量跑几千张,除非你有得是时间。
avifenc -s 6 --min 20 --max 32 in.png out.avif
第四步,验证。 别用眼睛,用数据:
magick compare -metric SSIM 原图.png 压过的.webp 差异图.png
我的经验值:SSIM 0.98 以上,普通人基本看不出来;0.96~0.98 得贴脸看;掉到 0.95 以下就能挑毛病了。但 SSIM 对文字截图会虚高,那种图还是自己放大看。
什么图配什么格式,别一刀切
- 人像、风景照:AVIF > WebP > mozjpeg,这个顺序基本不会错。Chrome 85 / Firefox 93 / Safari 16 之后 AVIF 都能用了,实在不放心就 WebP 兜底。
- 带文字的截图、UI 图、表格:千万别用有损 JPEG,文字边缘会糊出彩边。用 PNG,或者 WebP 无损模式。PNG 太胖就上
pngquant --quality=65-85量化成 8 位,一般能砍 60% 以上,肉眼几乎无感。 - 纯色 logo、图标:能上 SVG 就上 SVG,几 KB 搞定,还随便放大。非要位图就用 PNG-8,别用 PNG-24。
- 动图:GIF 这格式该退休了。同样一段动图,WebP 能小 60%~70%,画质还好。再大就直接转 MP4,加个
autoplay muted loop playsinline。
最后说个可能不太讨喜的观点
现在到处都在吹“把图压到 30KB”,我觉得这个方向有点歪。一张商品主图,你从 200KB 压到 80KB,用户可能根本没感觉;但因为压缩把瓶身文字压糊了,用户直接判断“这家店不专业”,损失的是转化率。
省流量的收益是有天花板的,掉画质的代价没有。 我的做法是:定一个观感底线(我一般卡 SSIM 0.97),在这个底线之上能压多小压多小,一旦要越过这条线,宁可让图大一点。
当然这只是我的做法,你的场景不一样,结论可能完全不同。有不同意见欢迎来抬杠。