图片压缩完又糊又大?跑完2000张图我才明白JPEG质量参数有多不靠谱

关键词:图片压缩,JPEG质量参数,mozjpeg,图片处理顺序,AVIF

摘要:JPEG的「质量80」在不同软件里根本不是一回事。这篇记录了我用2000张商品图踩坑的过程:量化表差异、先缩后锐的顺序、EXIF旋转的坑,以及MozJPEG和AVIF到底怎么取舍。

去年双十一前,一个开网店的朋友把图包丢给我,2000多张,主图800×800,详情页长图最长1200像素。他说平台自动压缩把图搞糊了,问我能不能先自己压一遍再传。我当时挺自信,ImageMagick一行命令批量走起,-quality 85,跑完一看,有几张出来的文件比原图还大。对,quality 85比quality 90出来还大,这种事是真会发生的。

图片

那天晚上我对着magick identify -verbose的输出翻来覆去看,才反应过来自己一直搞错了一件事:JPEG的「质量85」不是一个标准单位,它是个各家自说自话的百分比。

这个百分比背后是量化表,而量化表是各家的私货

ImageMagick的-quality直接映射到libjpeg的quality scale,用的是IJG那套标准量化表做缩放。Adobe不一样,Photoshop在「存储为Web所用格式」里,品质低到某个阈值之前用的根本不是标准表,是Adobe自己调过的。mozjpeg又是第三套,它默认开着trellis quantization,还会生成progressive扫描。所以你在PS里导出品质60觉得还行,换到sharp里写jpeg({quality: 60})出来一片色块,太正常了,你比的压根不是同一个东西。

图片

想验证也简单,magick identify -verbose xxx.jpg,输出里搜Quantization这个词,能看到实际的量化矩阵。同一个60,两套表的数值能差出好几倍。具体字段名我记不太清了,你搜Quantization就有,我上次是在一大堆输出里翻到的。

所以后来我测试就不看百分比了,直接看两样:文件大小和肉眼对比。方法很土,把导出的图丢进Squoosh并排看,放大到200%,重点盯三个地方——头发丝、纯色渐变、黑底白字的边缘。色块和振铃(ringing)基本都从这三个地方先冒出来。

测下来我自己的结论是:给网页用的图,mozjpeg + quality 78到82这个区间,比PS导出品质60还要小10%到15%,肉眼找不出差别。命令大概是这样:

图片

magick input.jpg -auto-orient -resize 1600x -strip -sampling-factor 4:2:0 -interlace Plane -quality 80 output.jpg

resize后面加个大于号是「只缩不放」的意思,我省略了。还有-auto-orient一定要写,而且必须放在-strip前面。

-auto-orient这个事我得单独说,因为我在它上面栽过

图片

手机拍的照片,竖图其实是横着存的,靠EXIF里一个Orientation字段等于6或8来告诉看图软件转90度。浏览器一般会认这个字段,但只要你用-strip把元数据撸掉了,就没人知道该转。我有一批300多张的商品图,脚本里-strip写在最前面,跑完整个页面躺平,全是横的,返工又跑了一遍。600张图的处理量,白烧两个小时。

处理顺序也是个大坑,比参数更容易出错。正确顺序是:转正 → 裁切 → 缩放 → 锐化。锐化必须放在缩放之后,因为锐化半径是跟输出尺寸挂钩的。你先锐化再缩小,等于把刚加上去的边缘对比度又平均掉一大半,白干。反过来的话,缩小本身会损失一点高频细节,缩完再补一点锐化刚好。我一般用-unsharp 0x0.75+0.75+0.008,radius写0让ImageMagick自己算,sigma 0.75,amount 0.75,threshold 0.008。这套数值是从ImageMagick官方示例里抄的,比我瞎调的好用。别用amount 2.0那种,网页图上一眼假,跟开了美颜似的。

图片

格式怎么选,别无脑上AVIF

AVIF压缩率确实好,同一张图能做到WebP的70%大小,问题是慢。你拿avifenc默认参数跑,一张1600宽的图编码要6到10秒,-s 4能压到2秒左右,画质掉一点点。2000张图,这就是1小时和4小时的区别。我的做法是:大图、不常变的图(首页banner之类)上AVIF,用户上传的、要及时返回的图还是WebP或者mozjpeg,别为了省那30KB让用户等。

PNG的话,如果没有透明通道,先想想是不是根本不该用PNG。有透明通道又想小,试oxipng -o4,或者pngquant --quality=65-85转成256色,一般的图标、logo够用了。

图片

一个数字上的判断标准,我一直在用

网页上正常显示的图,导出宽度别超过它实际渲染宽度的1.5倍。一栏800像素宽的正文,图给1200像素足够;需要2x屏清晰度就老老实实上srcset给两套,别拿一张3000像素的图让手机去缩。我见过一个站,首屏一张4032像素宽的图,quality 90,文件2.1MB,手机加载要四秒多。换成1600宽quality 80,280KB,肉眼看上去反而更锐——因为原来那张在缩到屏幕上的时候,锐化早被平均没了。

最后提醒一句,别信工具默认值。sharp默认quality 80、mozjpeg默认quality 75,这俩出图差别能有个两三成。你要么自己测一遍,要么在脚本里把参数写死,别让它替你决定。

标签: