上周帮朋友处理一张 3000×2000 的探店照,要发小红书。我顺手丢进某个在线压缩站,选了高压缩,出来 180KB,肉眼扫一遍还成。结果她发来一句:怎么我毛衣上有彩色的小格子?
放大到 100% 一看,针织纹理里全是红绿蓝的色块。这就是 JPEG 的色度抽样在咬人。JPEG 内部的颜色空间是 YCbCr,亮度 Y 保留完整分辨率,色度 CbCr 可以只存一半甚至四分之一。你导出时如果用的是 4:2:0,色度信息在横竖两个方向都被砍半——数字上看起来「清晰度没损失」,但红绿交界的地方就开始乱,细密的彩色纹理首当其冲。
这三种抽样方式的差别不小:4:4:4 色度不降采样,4:2:2 横向砍半,4:2:0 横竖各砍半。同一组风景图我实测过,4:4:4 是 142KB,4:2:0 是 108KB,差了 31%,而人像皮肤、衣物纹理这种高频区域,4:2:0 的观感损失肉眼可见。所以别一味迷信「文件小就是好」,得看这张图里有没有值得保的颜色细节。
再说缩放。3000×2000 缩到 1080×720,中间那一步叫重采样,算法不同结果差得很远。PS 里有「两次立方(较平滑)」和「两次立方(较锐利)」,前者缩图偏软,后者会往边缘加一圈轻微过冲,压完看着更精神。最近邻法是直接扔像素,缩放比例非整数时必出锯齿,所以它只配用来处理像素画。Lanczos3 被吹得最多,但它会振铃——高对比边缘会出现鬼影一样的波纹,拿它缩文字截图特别明显。
我自己摸索出来的土办法是:先缩到目标尺寸的 2 倍,比如要 1080 就先缩到 2160,再用两次立方(较锐利)一步到位。多这一步,画面稳定性确实好一些,代价就是麻烦。
命令行流程我现在基本固定下来了,先缩放再压:
magick input.jpg -resize 1080x -filter Lanczos \
-quality 82 -sampling-factor 4:2:0 -interlace Plane out.jpg
想让颜色边缘干净,就把 -sampling-factor 4:2:0 换成 4:4:4。WebP 那边参数更讲究:cwebp -q 82 -m 6 -sharp_yuv -metadata none in.png -o out.webp。-sharp_yuv 这个参数知道的人不多,它能明显缓解 4:2:0 采样带来的色度糊边,代价是编码慢;-m 6 是最慢的压缩档,同一张图比 -m 4 小 3% 到 5%,我一般只在最终成品上开,中间调试阶段用 -m 4 就够了。
顺序这件事值得单独拎出来讲:先缩放、再压缩、最后可选锐化。很多人是反的——先压成小文件,再拿去缩放,等于把压缩噪点一起放大,糊上加糊。锐化也别当成美化步骤,它本质是给压缩擦屁股。ImageMagick 里我常用的写法是 -unsharp 0x0.75+0.75+0.008,sigma 取 0.75 是冲着重采样后的软边去的,量 0.75 已经够,阈值 0.008 是为了不碰平坦区域。手机屏上看不出差别,27 寸显示器上一眼就有。
最后一个我反复踩的坑:屏幕上的图其实是三档需求。列表页缩略图可能就 300px 宽,正文里 750px,点开看大图得 1440px 往上。大部分人只导一张,剩下的交给浏览器和平台去缩。浏览器缩得还行,但很多平台后台会再压一遍,第二次压缩是叠加的,不是重来一次。微信朋友圈长边大概压到 1080px,公众号正文显示宽度我记得是 677px 上下,这些数字不一定精确到个位,但足够说明问题:你按 1440px 出图,最后被平台压到 677px,中间那两步缩放和一次重编码全是你控制不了的。
所以现在我出图会做三个版本:640px 给缩略图,1080px 给正文,2048px 留给点开大图。听着费事,但脚本跑一遍就完了,比事后对着糊图发愁强。