先说结论:你一直调的那个"质量80",只占最终体积的15%
去年年底我整理自己的素材库,硬盘里躺着21437张图,加起来186GB。第一反应是"该压了",然后打开用了六七年的老工具,把质量从95拉到80,导出,一看体积——从4.1MB变成3.6MB。省了12%。
那一刻我是有点崩溃的。
后来我把这些图按像素总量重新算了一遍,才发现问题根本不在质量参数上。一张4000×3000的图,像素总量1200万;而我实际用到的展示尺寸是1200×900,108万像素。也就是说有91%的像素从来没被人看见过,但它们照样占着体积。
真正该砍的第一刀是尺寸。这一刀下去,体积直接掉到原来的8%左右。质量参数那一刀,是后面才该考虑的——顺序搞反了,你会觉得自己怎么调都调不动。
不同来源的图,处理逻辑完全不是一回事
我把素材按来源分成四类,参数完全不同,这块踩坑最多。
第一类,相机和手机拍的照片。 色彩连续、噪点多,压缩算法发挥空间大。我的参数是:长边缩到1920,JPEG质量82,色度采样4:2:0,加-strip去掉EXIF。平均4.2MB降到280KB。单独说下EXIF,很多人不知道那玩意能占30到80KB,相机型号、GPS坐标、拍摄时间全在里面。我见过一张240KB的图,EXIF自己占了71KB,去掉之后什么都没变,就是小了三分之一。
第二类,手机截图和UI稿。 这类最容易被误伤。大片纯色加锐利文字边缘,JPEG一压,文字周围就冒彩色噪点,糊成一团。但你也不能无脑转WebP——我实测过200张App截图,转WebP无损后平均体积反而涨了18%,WebP无损模式对大面积纯色的压缩效率不如PNG。
截图我最后用的是PNG-8量化到128色。一张1080×2340的截图从1.8MB掉到190KB,肉眼基本看不出来。前提是图里没有渐变,有渐变的场景PNG-8会出现明显色带,这个只能一张张看。
第三类,图标和logo。 别存位图,直接SVG。我素材库里300多个logo,转成SVG之后总共400多KB。同样这批图如果存PNG是12MB。
第四类,带透明通道的商品图。 最麻烦的一类。PNG无损转WebP通常能省25%到35%,但如果你图边缘有半透明羽化,WebP的alpha通道处理和PNG有细微差异,某些电商平台的审核系统会判定"图片异常"。我踩过这个坑,一次传200张,47张被打回,当时没反应过来是格式的问题,还以为是网络。
具体怎么批量做,命令和参数
照片批量处理,ImageMagick 7:
magick mogrify -path ./out -resize '1920x1920>' -quality 82 -sampling-factor 4:2:0 -strip ./photos/*.jpg
几个参数解释一下。-resize '1920x1920>' 里的 > 是指"只在原图超过这个尺寸时缩小",不会把小的放大。-strip去掉所有元数据。-sampling-factor 4:2:0是色度采样,人眼对亮度敏感、对色度不敏感,砍掉一半色度信息体积能掉一截,画质损失你基本看不出来。
对比很残酷:只加-quality 82不加缩放的,输出3.6MB;两个都加的,280KB。差了接近13倍。
截图处理:
pngquant --quality=65-85 --speed 1 --strip *.png
转WebP:
cwebp -q 80 -m 6 -mt input.jpg -o output.webp
-m 6是压缩方法,范围0到6,6最慢但最小,默认是4,改成6大概能再小5%到8%。-mt开多线程。
Node项目里我更喜欢sharp:
sharp(input)
.resize(1920, 1920, { fit: 'inside', withoutEnlargement: true })
.jpeg({ quality: 82, mozjpeg: true, chromaSubsampling: '4:2:0' })
.toFile(output)
mozjpeg: true这个参数挺关键,用的是Mozilla那套编码器,同等质量下比默认的再小10%到15%,代价是编码慢大概2倍。我压2万张图,开mozjpeg之后总耗时从11分钟涨到26分钟。这15分钟我觉得花得值,但如果你是那种按秒计费的场景,自己权衡。
格式对比,数据摆出来
下面都是同一张1920×1280的风景照和一张1080×2340的App截图,我跑出来的平均值:
| 格式 | 适用场景 | 实测体积 | 编码速度 | 兼容性 |
|---|---|---|---|---|
| JPEG q82 | 照片 | 280KB | 快 | 100% |
| WebP q80 | 照片/网页 | 186KB | 中 | 97%+ |
| AVIF q60 | 照片/网页 | 141KB | 慢 | 约88% |
| PNG-8 128色 | 截图/UI | 190KB | 中 | 100% |
| SVG | 图标/logo | 1-3KB | 不适用 | 100% |
AVIF用的是q60不是q80,因为它质量刻度和JPEG不一样,q60的AVIF大概相当于JPEG的q80。这个数字不要直接混用。
一个我到现在也没完全想明白的事
AVIF的体积画质比确实好。同画质下平均比WebP小20%到30%,我测的那张风景照,WebP是186KB,AVIF是141KB,SSIM还更高一点。数据上毫无争议。
但编码速度是个坑。同一张图,WebP编码0.3秒,AVIF要4.7秒。2万张图的话,这就是26小时的事,而且我只是跑一次,那些每天要处理用户上传的站点呢。
iOS 16之前的Safari完全不支持AVIF,我后台数据里还有6.2%的用户在用旧设备。所以最后方案是用<picture>做渐进增强:AVIF优先,WebP兜底,JPEG保底。多存一份文件,CDN多花点钱,覆盖率100%。
说实话我到现在也没想清楚这个代价值不值。如果目标用户集中在安卓新机型,可能压根不用管JPEG保底。这个东西没有标准答案,得看你的实际用户构成。
最后
如果你只记一句话:先砍尺寸,再选格式,最后才调质量。
我见过太多人打开压缩工具第一件事就是拖那个质量滑块,包括三年前的我。那个滑块能给你的收益,通常不到整体优化空间的10%。大头在尺寸和格式上,而这两样是要分类讨论的,没有一键方案。
谁要跟你说有个按钮能一键搞定所有图片压缩,他要么没压过两万张图,要么就是想卖你东西。