先讲个事
上个月帮做民宿的朋友处理一批房间照,iPhone 直接导出来的 HEIC,427 张,单张从 3.8MB 到 6.2MB 不等。他要在某个订房平台后台上传,单张卡 2MB。他自己先在一个在线压缩站过了一遍,选了「高质量」那一档,结果 90 多张还是超标;勉强过线的那几张,墙面出现一圈一圈的色块,他原话是「像发霉了」。
我接过来干的第一件事,是把他压过的那批全删掉,从原图重来。没动质量参数,先把长边从 4032px 砍到 2000px——就这一步,427 张里 411 张直接掉到 1.2MB 以下。剩下十几张我调了下色度采样,全部过关,墙面也没再出色块。
所以网上那句「JPEG 质量调到 80 就能压到 200KB」,在我看来顺序是反的。质量滑块是最后才动的东西,不是第一刀。
决定一张图体积的,按权重排下来是这样
第一是像素总数。长边减半,像素数变成原来的四分之一,JPEG 编码后的体积大致也跟着掉到四分之一左右。这是最狠、最不伤观感的一刀,因为大多数屏幕根本吃不下 4000px 宽的图。
第二是编码格式和色度采样。同样是照片,WebP 在观感接近的前提下比 JPEG 小 25% 到 35%,AVIF 还能再小一截,但编码慢得让人想砸键盘(我笔记本上一张 4000px 的图转了 11 秒)。至于 JPEG 自身的 4:2:0 色度采样,相比 4:4:4 能省 15% 到 30% 体积,代价是红色边缘会稍微糊——照片上基本看不出来,红色大字海报上看得出来。
第三才是质量参数。而且它的收益是递减的:质量从 90 降到 80,体积能掉 30% 到 40%;从 80 降到 70,只掉 15% 左右,但块效应开始肉眼可见。继续往下压,掉的是体积,也是脸面。
一份我自己在用的参数表
| 用途 | 长边/尺寸 | 格式 | 质量 | 典型体积 |
|---|---|---|---|---|
| 微信朋友圈 | 1080 | JPEG | 80-85 | 150-400KB |
| 公众号正文 | 1080 | JPEG 或 WebP | 82 | 100-300KB |
| 小红书封面 3:4 | 1080×1440 | JPEG | 88 | 300-600KB |
| 电商主图 | 800×800 或 1200×1200 | JPEG | 85 | 80-200KB |
| 网站正文配图 | 1600 | WebP | 78-82 | 60-200KB |
| 一寸证件照 | 295×413 @300dpi | JPEG | 95 | 30-80KB |
| 打印 A4 照片 | 2480×3508 @300dpi | JPEG | 95 | 2-5MB |
注意最后两行。要打印的东西千万别按网图的标准压,2480×3508 是 A4 在 300dpi 下的像素数,压到 1500px 打出来就是糊的。证件照同理,295×413 是 25×35mm 在 300dpi 下的尺寸,压小了上传系统会直接打回。
说个反常识的:照片别存 PNG
我见过有人为了「无损清晰」把 5MB 的照片存成 PNG,结果变成 18MB。PNG 是无损压缩,它擅长的是另一类图——截图、UI 稿、大面积纯色、带透明通道的素材。照片这种每个像素都在渐变的画面,PNG 压不动,纯属浪费。
真要压 PNG,路子是转成 PNG-8,也就是索引色,最多 256 色。截图和扁平插画转到 PNG-8 之后经常能掉 60% 到 70% 体积,画质几乎无损。但照片转 PNG-8 会出现明显的色带,别试。
还有一点,PNG 的「质量」参数和 JPEG 完全不是一回事,那个值控制的是 zlib 压缩级别,调它只影响文件大小和编码时间,不影响画质。
可以直接抄走的批量命令
我用的是 ImageMagick,7.x 版本命令是 magick,6.x 是 convert/mogrify,下面按 7.x 写。
mkdir -p out
for f in *.jpg *.jpeg; do
magick '$f' -auto-orient -resize '2000x2000>' -sampling-factor 4:2:0 -quality 82 -strip 'out/${f%.*}.jpg'
done
几个参数解释一下:-resize 后面那个大于号表示「只缩小,不放大」,防止小图被硬拉大;-strip 会删掉 EXIF 元数据,一张手机照片的 EXIF 能有几十 KB,删了顺便还能去掉定位信息;但注意 -auto-orient 必须放在 -strip 前面,因为照片的旋转信息就存在 EXIF 的 Orientation 标签里,先把方向应用上去再删,否则竖拍照片会集体躺平。这个坑我踩过,一次导出 200 张全是横的。
PNG 批量走 pngquant:
mkdir -p out
for f in *.png; do
pngquant --quality=70-90 --speed 1 --strip --output 'out/$f' '$f'
done
转 WebP:
for f in *.jpg; do
cwebp -q 80 -m 6 -metadata none '$f' -o 'out/${f%.*}.webp'
done
-m 6 是最慢也压得最小的档位,-metadata none 相当于 WebP 版的 -strip。
AVIF 我一般用 avifenc,-q 的取值是 0 到 63,数字越小画质越高,我通常落在 30 到 45 之间。它体积确实香,但兼容性还没到可以无脑全站替换的程度,老版本的安卓浏览器就打不开。
苹果用户有个偷懒办法
macOS 自带的 sips 其实很好用,不用装任何东西:
sips -s format jpeg -Z 2000 in.heic --out out.jpg
-Z 是等比缩放到长边 2000。sips 不能批量指定输出目录这一点比较烦,得写个 for 循环。另外它转 HEIC 的速度比 ImageMagick 快不少,前提是你得装上 libheif,否则 ImageMagick 打开 HEIC 会直接报错——很多人第一次压 iPhone 照片卡住就是卡在这。
Windows 上如果不习惯命令行,XnConvert 能可视化配置上面这套流程,批量重命名加批量转换一次搞定,免费。
我自己的三条土规矩
第一,任何一批图,先按目标平台的上限尺寸缩一遍,再看体积超没超。十次里有八次,缩完就不用压了。
第二,压完必须挑三张放大到 100% 看——一张纯色墙面、一张天空、一张人脸。块效应和色带基本都在这三处露馅。
第三,原图永远单独存一份,压缩产物输出到 out 目录。我见过太多人用在线工具压完把原图覆盖了,后来要打海报,只能去相册里翻聊天记录。