图片压缩后糊成一片?我拿4张图跑了7个工具,说几个反直觉的结论

关键词:图片压缩,WebP,AVIF,图片画质,批量压缩

摘要:同一批原图丢进7个工具实测,对比JPEG/WebP/AVIF的体积与画质,聊聊质量参数的真实含义、4:2:0色度采样的坑,以及为什么真正毁画质的不是编码器而是缩放。

上个月帮一个做手工皂的朋友处理详情页图片,她之前的图因为「画质过低」被平台退回来了。我拿过来看,4800万像素的原图压到380KB,皂体表面的冷制纹路全糊了,看着确实像一块塑料。那天晚上我决定较个真:把同一批原图丢进手头所有的工具里跑一遍,看看到底差在哪。

图片

测试素材选了4张,都是容易被压缩算法搞死的类型:iPhone 15 Pro 主摄白天拍的皂体特写,4800万像素 HEIC,原文件4.2MB;同机夜景 ISO 3200,暗部噪点密集,降噪型编码器最容易在这儿翻车;一张 2560×1440 的聊天截图,纯色底加小字,PNG 1.1MB;还有一张 Illustrator 导出的渐变插画,大面积平滑过渡。工具方面用了 Photoshop 2024「导出为」、Squoosh、TinyPNG、ImageMagick 7.1.1、FFmpeg 的 libwebp、Node 的 sharp,以及 avifenc。

先说 JPEG 的质量参数。Photoshop「导出为」那张特写:q90 → 3.1MB,q80 → 1.4MB,q75 → 980KB,q60 → 520KB。看着 q60 很香对吧?把夜景那张放大到200%看天空,暗部一片一片的色块,边缘还有明显的 8×8 网格。q75 也不是没问题,渐变区开始出现 banding,只是缩到 1200px 宽看不太出来。这里有个很多人搞混的点:libjpeg 的 quality 不是「保留百分之多少画质」,它是个量化表的缩放系数。所以 q90 到 q80 体积能掉55%,q80 到 q70 只掉25%,q70 到 q60 掉15%。收益递减得很厉害,真正有意义的调节区间其实是 78 到 85,低于75之后你付出的画质代价和换来的体积收益完全不成比例。

图片

第二轮上 WebP 和 AVIF。用 sharp 跑的 .webp({ quality: 75, effort: 6 }),那张特写出来610KB,比 JPEG q75 小37%,肉眼差距不大。AVIF 更有意思,avifenc 用 cq-level=24,出来380KB,是 JPEG q75 的39%。但编码时间得说说——同一张 4800万像素的图,JPEG 大概0.8秒,WebP effort 6 花了11秒,AVIF 跑了47秒。批量200张的话,AVIF 就是两个半小时。这笔账得自己算。

图片

对了,4:2:0 色度采样单独拎出来讲。它把色度信息砍掉一半,亮度保留。拍人像没事,但图里要是有纯红或纯蓝的细线、小字,边缘会明显发虚发灰。我那张截图里有个红色的「¥」符号,4:2:0 下糊得厉害,换成 4:4:4 体积涨18%,字就清楚了。截图、UI 图、带彩色文字的图,别用默认的 4:2:0。

截图那块我走了另一条路。PNG 是无损,直接压体积下不来。用 pngquant 做调色板量化到256色,1.1MB 降到178KB,100% 看,纯色区域的文字边缘完全没变化,只有渐变头像那里有一点点色阶。另外 ImageMagick 的 -strip 去掉元数据,一张手机图能省 20 到 80KB,很多人不知道这件事。

图片

然后是那个说了很多遍但没什么人听的结论:真正毁掉画质的不是编码器,是缩放。你把 4000px 的图直出到 500KB,编码器只能在一个 12:1 的压缩比里挣扎,它会把细节抹平、把噪点当成冗余数据干掉。但如果你先重采样到 1200px 宽,再用 q85 编码,输出可能只有300KB,而且在手机上看细节反而更锐利——因为重采样本身就是一个低通滤波,它先替你做了编码器要做的事,而且是可控的。我用 Lanczos 缩到 1200px 的那张特写,q85 出来287KB;直接原尺寸 q60 是520KB。前者肉眼看着比后者干净。这个结果我反复对了好几次。

所以现在给这类活儿的流程基本固定了:先统一宽度,详情页 750px 或 1200px,别留着 4000px 原图直接压;截图和 UI 图走 pngquant 量化,或者直接转 WebP 无损;照片先缩到目标尺寸,JPEG q80~85 或 WebP q75,有带宽预算再上 AVIF;一定要 -strip 清理 EXIF,手机拍的图里那点缩略图和数据能占几十 KB;压完别只信自己的眼睛,SSIM 掉到0.95以下基本就能看出差别了。

图片

ImageMagick 我常用这一条,记下来省事:

图片

magick input.jpg -resize 1200x -sampling-factor 4:2:0 -strip -colorspace sRGB -quality 82 -interlace JPEG -define jpeg:dct-method=float output.jpg

最后说个坑。很多平台上传后还会再压一次,你传个200KB的图上去,它可能给你压成80KB甚至更低,画质再掉一档。我的做法是先按它的规则试传一张,下载回来对比文件大小和 SSIM,摸清二次压缩的强度,再倒推我该传多大的图。这招很土,但省事。

标签: