先说结论:把 quality 当第一参数,基本会走弯路
我今年 4 月帮朋友处理民宿房源图,原图是索尼 A7M3 拍的 6000×4000 JPEG,单张 8-14MB,一共 1372 张。 平台后台上传后,长边会被压到 1440px 左右,但前台看起来像蒙了层灰。 我一开始把 ImageMagick 的 -quality 从 82 调到 90,体积涨了 47%,肉眼几乎没变化。 后来把色度采样从 4:2:0 改回 4:4:4,体积只多 12%-18%,红色木门、绿植边缘和菜单小字明显干净。 所以我的独立观点是:图片处理先看缩放算法、色度采样、输出后锐化,最后才看 quality。
我测了 5 个工具,别急着装全家桶
测试样本是 500 张 6000×4000 JPEG,目标长边 2000px,机器是 M1 MacBook Air 16GB,系统 macOS 14.5。
- ImageMagick 7.1.1-32 Q16-HDRI:命令 magick mogrify -path out -auto-orient -colorspace sRGB -resize 2000x2000> -strip -sampling-factor 4:2:0 -interlace Plane -quality 78 -unsharp 0x1+0.7+0.02 *.jpg。500 张总耗时约 6 分 40 秒,平均 286KB。
- ffmpeg 6.1.1:命令 ffmpeg -i in.jpg -vf scale=2000:-2:flags=lanczos,unsharp=5:5:0.8:5:5:0.0 -c:v libwebp -quality 75 -compression_level 6 -map_metadata -1 out.webp。500 张约 9 分 20 秒,平均 198KB,但文字截图有轻微彩边。
- sharp 0.33.2 Node:resize(2000, null, { fit: 'inside', withoutEnlargement: true, kernel: 'lanczos3' }).sharpen({ sigma: 0.8, m1: 0.5, m2: 0.5 }).webp({ quality: 76, effort: 5, smartSubsample: true })。500 张约 4 分 10 秒,平均 205KB,适合接自动化。
- Squoosh CLI:webp quality 75、method 6,500 张约 12 分钟,平均 210KB,界面直观但批处理弱。
- jpegoptim 1.5.5 + mozjpeg:命令 jpegoptim --strip-all --all-progressive -m78 *.jpg。500 张约 3 分 30 秒,平均 410KB,只适合最后一道压缩,不适合先缩放。
真正影响糊不糊的 4 个参数
第一,长边。网页主图 1600px 就够,电商详情 1200px,缩略图 480px,手机壁纸 2160px;把 6000px 直接交给平台,它可能用双线性或最近邻,边缘更脏。 第二,缩放算法。Lanczos 比默认 Mitchell 锐,但过锐会有黑边,我一般用 -filter Lanczos 或 sharp 的 lanczos3。 第三,色度采样。4:4:4 适合截图、文字、红蓝纯色,4:2:0 适合风景、食物,体积差约 8%-15%。 第四,锐化时机。压缩前用 -unsharp 0x1+0.7+0.02 容易把噪点放大,我改成先缩放、再压缩、最后用 -unsharp 0x0.8+0.5+0.02,或者 sharp 的 sigma 0.5-0.8。 补充一个调色顺序:如果非要拉对比度,先曝光和对比度,再缩放,再压缩;顺序反了,暗部色带会被压出来。
直接可抄的批量步骤
- 用 exiftool 看色彩空间和方向:exiftool -Orientation -ICC_Profile -ColorSpace *.jpg。如果是 Adobe RGB 或 Display P3,先转 sRGB,否则 Chrome 和微信会偏色。
- 用 ImageMagick 批量转 sRGB、自动旋转、去元数据:magick mogrify -path out_srgb -auto-orient -colorspace sRGB -profile /path/sRGB.icc -strip *.jpg。没有 sRGB.icc 时,至少加 -colorspace sRGB,但不如带 ICC 稳。
- 按用途缩到目标长边:magick mogrify -path out_web -resize 1600x1600> -filter Lanczos -sampling-factor 4:2:0 -interlace Plane -quality 78 -unsharp 0x0.8+0.5+0.02 *.jpg。注意 > 在 Windows PowerShell 里要写成 ^> 或加引号。
- 要更小就出 WebP:ffmpeg -i out_web/img.jpg -c:v libwebp -quality 76 -compression_level 6 -preset picture -map_metadata -1 out_web/img.webp。我测 500 张,WebP 平均比 JPEG 小 28%,但带小字截图建议 quality 82 以上或保持 4:4:4。
- 最后抽查 10 张:看红色物体边缘、头发、菜单小字、渐变天空。如果出现色带,把 WebP 的 quality 提到 80,或换 AVIF quality 50,但 AVIF 编码慢 3-8 倍,老安卓和旧 Safari 不一定吃。
几个容易踩的坑
透明背景别直接转 JPEG,会变黑或白,先拼白底或输出 PNG。 PNG 不是永远大,UI 截图用 pngquant --quality=65-85 或 oxipng -o4 --strip safe 往往能小 40%-70%。 平台二次压缩躲不过,但上传 2000px 长边通常比 4000px 更清晰,因为平台采样比例更接近整数。 别迷信无损,对 8-bit 摄影图,4:2:0 + quality 76 的 WebP 在手机上看和 4:4:4 + quality 90 差距极小,体积却差 2 倍。 批量处理前先备份原图,所有命令先在 20 张样本上跑;我当时偷懒直接跑全量,结果把带透明通道的 37 张图转成黑底,只能从备份里捞回来。