图片压到200KB以内还不糊?我拿5100张商品图实测了一轮,说几个反常识的地方

关键词:图片压缩,批量压缩图片,图片压缩到200KB,JPEG色度抽样,WebP转换

摘要:用5100张商品图做的一轮真实压缩测试,聊聊JPEG质量参数在不同软件里根本不是一回事、色度抽样怎么省体积、以及几个我亲自踩过的坑(ICC被删、mogrify原地覆盖、在线工具重采样)。

先说个让我后背发凉的事

图片

去年11月,我一个开淘宝店的朋友找我救火。她上了一批新品,5100多张图,用某个「在线图片压缩」网站批量处理了一遍,图是变小了,从平均 3.8MB 压到了 190KB 左右,看着挺美。结果平台审核打回来 40 多张,说主图不清晰。我去看她本地文件,原图已经被覆盖了。iPhone 拍的 4032×3024,全没了。

我拿到的是压缩后的残骸。放大到 200% 看,商品边缘有一圈很淡的灰边,文字标签的地方有红蓝色的小噪点。这不是压缩质量的问题,是被重新采样过了,而且是那种偷懒的双线性。我当时就有点上火,不是因为技术,是因为这个网站压根没告诉用户它动了什么。

所以这篇文章我想把一个事说透:压缩这件事,参数只是表象,关键是你得知道软件在背后干了什么。

JPEG 的「质量 80」,在不同软件里不是同一个东西

这个是我最想让人知道的一个点。很多教程说「质量 80 是甜点值」,但它没告诉你,Photoshop 的质量 80、ImageMagick 的质量 80、某个国产小工具的质量 80,出来的文件能差 3 倍。

图片

原因在 libjpeg。这个库里的 quality 参数不是百分比,它是个量化表的缩放系数。具体逻辑大概是:quality 小于 50 的时候,缩放系数 = 5000 / quality;大于等于 50 的时候,系数 = 200 - quality × 2。也就是说,quality 50 的时候系数是 100,用的是 JPEG 标准量化表原样;quality 75 的时候系数是 50,量化表每一项砍一半;到 90 就是 20。

这意味着两件事。第一,从 90 降到 80,实际量化强度是从 20 涨到 40,翻了一倍,体积掉得很猛。第二,不同软件对滑块的映射方式不一样,有的直接把滑块值当 quality 传进去,有的做了自己的曲线。我见过一个工具,滑块拉到「高质量」,它内部实际传的是 62。用户以为自己在用 85。

还有个更少人提的参数:色度抽样,也就是 chroma subsampling。JPEG 存的是 YCbCr,Y 是亮度,CbCr 是色度。人眼对亮度敏感、对色度迟钝,所以可以只保留 1/4 的色度数据,这就是 4:2:0。默认很多软件用的是 4:4:4(不抽样)或者 4:2:2,你手动改成 4:2:0,体积通常能再降 15% 到 25%,肉眼在照片上基本看不出来。但在文字、logo、线稿上,4:2:0 会让黑色文字边缘出现彩色噪点,这个后面细说。

我那次实际跑的命令,以及三个翻车现场

图片

目标:边长 800×800 方图,单张 200KB 以内。工具用的 ImageMagick 7,我这台是 2019 款的 MacBook Pro,i7 八核。命令大概是这样:

magick mogrify -path ./out \
  -resize 800x800^ -gravity center -extent 800x800 \
  -filter Lanczos -quality 82 -sampling-factor 4:2:0 \
  -interlace Plane -strip *.jpg

800x800^ 那个尖角号是填充模式,意思是先把图缩到能盖住 800×800,再 -extent 从中间裁。-filter Lanczos 是重采样算法,降采样的话 Lanczos 比默认的 Mitchell 锐一点,但边缘容易出现轻微的振铃。-interlace Plane 是生成渐进式 JPEG,网页加载时先出模糊轮廓再变清晰,体积会稍微大一点点,大概 1% 到 3%。

翻车一:mogrify 是原地覆盖的。我第一次直接跑在素材目录里,幸好之前备份了。后来乖乖加 -path ./out。这个坑很蠢,但我相信不止我一个人踩。

翻车二:-strip 会删掉 ICC 色彩配置。她那批图里有 300 多张是早期用单反拍的,Adobe RGB 色彩空间。strip 之后浏览器按 sRGB 解释,颜色发闷、发灰,红色特别明显。后来我的做法是转换后再 strip:先 -profile /path/AdobeRGB1998.icc -profile /path/sRGB.icc 把色彩空间转过去,再删。

图片

翻车三:方图裁剪切掉了主体。有几张图商品标签在左下角,居中裁剪刚好切一半。这种只能人工过一遍,或者改成 -resize 800x800 加白底补边(-background white -gravity center -extent 800x800),但补边会有白条,平台主图讲究白底满幅的就不行。

最后结果:5100 张跑完用了 23 分钟,输出平均 118KB,最大的 187KB,没有一个超 200KB。体积比原图降了大概 96.9%。

几个工具的横向对比,我个人的实测口径

工具 批量能力 色度抽样可调 保留 ICC 我测的平均输出 备注
ImageMagick 强,命令行 是(需手动) 118KB 参数最透明,学习成本高
XnConvert 强,图形界面 是(藏在高级选项) 142KB 免费,界面丑得像 2008 年
Photoshop 存储为 Web 弱,动作可批 是(勾选) 否(默认丢) 178KB 同质量数值下体积偏大
Squoosh 网页版 单张为主 131KB 实时对比做得好,不适合几千张
Lightroom 导出 变化极大 那个「限制文件大小」会反复试,偶尔直接掉到质量 40

图片

要注意这不是说 Photoshop 不行,它的算法其实很好,只是同一个「质量 80」,PS 出来的文件确实比 ImageMagick 大。我怀疑是它保留了更多的高频信息和色度数据。清晰度上,放大到 300% 去看,PS 那版确实更干净一点点,但代价是体积大 50%。

什么时候你就不该压

含文字的截图和线稿,别用 4:2:0。黑色文字在 YCbCr 里亮度接近 0,色度是中性,被下采样再还原之后,边缘会渗进相邻像素的色度,出现红蓝色描边。你截图存成 JPEG 之后放大看边缘发彩色,就是这个原因。这类图我的做法是:要么 PNG-8,用 pngquant 降到 256 色,一个 1080p 的界面截图能从 1.8MB 降到 180KB 左右,而且文字锐利;要么就用 4:4:4 加质量 90。

证件照也别乱压。身份证照片、签证照通常有明确要求,比如 295×413 像素、300dpi、白底、文件 20KB 到 40KB。20KB 这个数是很紧的,295×413 的 JPEG 压到 20KB 基本得用质量 60 到 70,脸部细节会糊。我一般会告诉人:先确认对方要的是像素尺寸还是厘米尺寸,很多要求冲突的时候,像素优先。

印刷用途的图,压缩这事跟你就没关系,直接 TIFF 或者高质量 JPEG,300dpi 起步。有人拿 72dpi 的图去印名片,出来的字边缘是锯齿的,这个不是压缩的问题,是分辨率不够。

图片

我的一般性判断

如果图是要放到网页或者 App 里,我现在基本直接转 WebP,质量 80,平均比 JPEG 小 25% 到 35%,浏览器支持早就没问题了。但如果是往某些平台后台上传,先小批量试几张,确认它接不接受 WebP,别一口气转完 5000 张发现被转回了 JPEG,那就白折腾还多一层损失。

在线压缩工具我一般不用。三个原因:一是图要上传到别人服务器,商品图、证件照这种我不放心;二是有些会悄悄重采样,就像我朋友遇到的那个;三是很多工具的输出是二次压缩,你输入一张已经压过的图,它再压一遍,伪影叠加,画质掉得比单次压到同等体积更狠。

最后说个心态上的事。很多人压图的时候盯着那个文件体积的数字,觉得越小越好。但真正该盯的是「这张图在最终展示尺寸下看起来怎么样」。一张 800×800 的图在手机上看,200KB 和 400KB 的差别,大部分人分不出来。为了省 100KB 把质量从 82 压到 60,那才是真亏。

标签: