图片越压越糊?我在400张电商图上踩过的重采样坑

关键词:图片压缩,图片重采样,ImageMagick批量处理,图片变模糊,srcset

摘要:从一次400多张商品图的处理经历出发,聊聊为什么图片压缩后反而变糊,问题往往不在压缩率,而在缩放链条。包含 ImageMagick、sharp、mozjpeg 的实际参数和落地工作流。

先说个事

图片

上个月接了个小活,帮一个卖宠物用品的店主整理商品图。摄影师给的是 6000×4000 的 TIFF,一共 412 张,我一看这尺寸就头大,随手写了段 shell 准备一把梭。结果第一批图发过去,店主回了一句“怎么看着不如原来的清楚”。我当时还不太服气,自己放大对比了一下,发现猫毛的边缘确实是发虚的,那种说不清的糊,不是马赛克那种糊。

问题不在压缩率,在缩放链条

图片

我一开始的直觉是压缩质量给低了,把 mozjpeg 的 q 从 82 提到 95,单张从 70KB 涨到 210KB,看着还是不对。后来盯着脚本看了半天才反应过来,我干了这么一件事:原图先缩到 1200×800 存了一份,再从 1200×800 缩到 800×800 当主图。等于同一张图被重采样了两次。重采样本质上是拿周围像素做加权平均,Lanczos 那个核函数在边缘附近会产生过冲,也就是你放大之后能看到的白边或者黑边。一次还能忍,叠两次,锐利的边缘就被磨圆了。这跟压缩质量一点关系都没有,你把 q 开到 100 也救不回来。

我后来把脚本改成每次都从原图出发,算好目标尺寸,一次 resize 直接输出,中间不落地成文件。就这一改,同样的 q82,同样的文件大小,肉眼观感完全两样。所以我现在判断一张图处理得好不好,不看它多大,先看它被缩了几次。

图片

那些藏在参数里的坑

改成一次缩放之后又踩了几个。ImageMagick 的 -thumbnail 比 -resize 快,但它默认会把 EXIF 和 ICC profile 一起抹掉,我那批图有一部分是 AdobeRGB 的,缩完直接发灰,店主还以为是显示器的问题。要留色彩空间就得自己加 -profile 或者干脆用 -resize 手动控制。sharp 那边也有类似的,它的 kernel 默认是 lanczos3,处理那种带噪点的高感照片时,噪点周围会起振铃,改成 mitchell 会稳很多,代价是锐度稍微降一点点。

另一个很多人不看的东西是色度子采样。JPEG 默认走 4:2:0,意思是每四个亮度像素共用一组色度信息。风景照上完全没感觉,但你的图里有红色小字、细的彩色线条,边缘就会糊成一坨。带文字的产品图可以试试 4:4:4,文件大概大两到三成,清晰度是肉眼能看出来的差别。

图片

我最后落地的参数

412 张跑完一共 4 分 20 秒,M1 Mac mini,ImageMagick 7.1.1 配 cjpeg 4.1.1。主图 800×800 走 mozjpeg q82、4:4:4、加 -tune-ms-ssim,平均 68KB;详情页 750 宽出 WebP -q 80 -m 6,平均 41KB;小程序要的 1200 宽用 AVIF,cq-level 28,平均 33KB。图标那类纯色图不走 JPEG,用 pngquant --quality=65-90 --speed 1,从 40KB 压到 9KB 左右。

图片

这些数字不是标准答案,是我这批图跑出来相对舒服的位置,你换个素材可能就不一样。但有个顺序是通用的:先定尺寸,再定格式,最后才动质量参数。反过来做,基本就是白折腾。

前端那一层也别忘了

图片

还有个事挺多店主不知道的,图糊不一定是图本身糊,是 <img> 没配 srcset。800px 的图在 iPhone 上按 375 逻辑宽度显示,CSS 里写死 width:100%,3x 屏就得拉一张 800 的图去填 1170 个物理像素,不糊才怪。正确写法是 srcset 给 800w/1200w/1600w,sizes 写对,浏览器自己挑。这事儿跟后端压缩是两码事,两边都得管。

我也不是什么专业人士,就是踩坑踩多了有点心得。如果你手上就十张图,PS 里手动处理完全没问题。但到了几百张这个量级,每一步能不能复现、能不能从原图重来一遍,比某个参数调得多精贵重要多了。

标签: