有损压缩实践
质量参数 80 是怎么来的?
上线初期,我在 generate_thumbnails 函数里硬编码了一个数字:quality=80。
为什么是 80?说实话,我当时在 Google 上搜了一下”WebP 最佳质量参数”,看到一个回答推荐 75~85,就选了中间值。
直到有一天,摄影师老王在群里吐槽:“光影上的照片颜色有点糊,跟我原图比差了不少。”
我下载了老王上传的原图和压缩后的版本,放在一起对比:
原图: 6000×4000, JPEG, 8.7MB, 细节丰富,噪点清晰
压缩后(80): 800×533, WebP, 45KB, 远看还行,放大后细节丢失明显远看确实差别不大。但摄影师的眼睛是挑剔的——他们会放大看细节,会注意天空的色带、暗部的噪点、高光的过渡。
我意识到,quality=80 不是一个万能数字。不同类型的图片,需要不同的压缩策略。
第一组实验:JPEG vs WebP 质量扫描
我用小李的 5 张夜景照片做了第一组实验,测试不同质量参数下的文件大小和主观质量:
结果出来了:
质量参数对比(1200×800 夜景照片)
JPEG:
q30: 18 KB ← 严重色块,不可用
q50: 35 KB ← 可见色块,勉强
q60: 48 KB ← 轻微色块
q70: 68 KB ← 大部分场景可接受
q75: 82 KB ← 摄影师可接受的底线
q80: 105 KB ← 肉眼几乎看不出差异
q85: 135 KB ← 细节保留很好
q90: 185 KB ← 接近无损
q95: 290 KB ← 体积增大明显,收益递减
WebP:
q30: 12 KB ← 同样不可用
q50: 24 KB ← 比 JPEG q50 好一些
q60: 32 KB ← 可接受的起点
q70: 46 KB ← 与 JPEG q75 接近
q75: 56 KB ← 摄影师可接受
q80: 71 KB ← 肉眼几乎看不出差异
q85: 92 KB ← 细节保留很好
q90: 128 KB ← 接近无损
q95: 198 KB ← 收益递减关键发现:
同等主观质量下,WebP 比 JPEG 小约 30%~40%
WebP q75 ≈ JPEG q80(主观质量相当)
JPEG q80: 105 KB
WebP q75: 56 KB ← 小 47%!也就是说,我一直用的 quality=80,在 WebP 下实际上”质量过剩”了——WebP 的 80 对应的是 JPEG 的 85+。
第二组实验:不同内容类型的压缩差异
夜景照片只是其中一种。我又测了 4 种典型内容:
结果让我很意外:
不同内容类型在 800px 宽度下的最佳质量参数(SSIM ≥ 0.95)
内容类型 最佳质量参数 文件大小 说明
───────────────────────────────────────────────────
夜景照片 q78 62 KB 噪点被压缩算法"利用",天然适合有损压缩
人像照片 q75 48 KB 肤色过渡区域需要更多比特,但焦外可压缩
风景照片 q72 38 KB 大面积渐变(天空)压缩效果极好
白底产品 q82 28 KB 纯白背景压缩比极高,但产品边缘需要清晰
UI 截图 q90 85 KB 文字和线条对压缩极敏感,质量参数低了糊
结论:最佳质量参数从 72 到 90,跨度很大!一句话总结:用固定的 quality=80,有的图片过度压缩(UI 截图),有的图片浪费带宽(风景照)。
第三步:基于内容类型的自适应压缩
我决定实现一个智能压缩策略:根据图片的内容特征,自动选择最佳质量参数。
但问题来了——这个分类逻辑太粗糙了。analyze_content 用的是简单的阈值判断,分类准确率大概只有 70%。有些照片被误判了,比如一张暗色人像被分到了”夜景”。
第四步:更务实的方案——二分搜索找最佳质量
与其费劲做内容分类,不如换一个思路:给定目标质量(SSIM),二分搜索找到最小文件大小对应的质量参数。
实际上,二分搜索的方案更适合生产环境——不依赖内容分类的准确性,直接以目标质量为准。
最终方案:混合策略
最终的方案结合了两种思路:
- 先用简单规则做粗分类(白底 vs 非白底,截图 vs 照片)
- 在分类基础上调整目标 SSIM
- 用二分搜索找到最佳质量参数
效果对比
用最终方案跑了一遍”光影”上最热门的 100 张图:
优化前后对比(800px 宽,WebP 格式)
指标 固定 q=80 智能压缩 改善
─────────────────────────────────────────────────
平均文件大小 78 KB 52 KB ↓ 33%
最大文件大小 210 KB 120 KB ↓ 43%
最小文件大小 25 KB 15 KB ↓ 40%
SSIM ≥ 0.95 98% 100% ↑ 2%
SSIM < 0.90 2% 0% ↑ 消除
带宽节省:每月约 35% 的 CDN 流量费摄影师老王也没再吐槽了。
前端适配
智能压缩是后端的事,但前端也需要配合——告诉浏览器自己支持什么格式: