同一个 15px 图标,Chrome 里总比 Firefox 粗一圈——原因不在 CSS,在 JPEG 解码器
同一个 15px 的 logo,在 Chrome 和 Firefox 里看起来不一样粗,你可能会先怀疑是 CSS 的 font-smoothing、image-rendering 或颜色配置在作怪。但这次真凶更深:Chrome 的 JPEG 解码器在「主动丢细节」,而且丢得理直气壮。
JPEG 的分块与频率域
JPEG 把图片切成 8×8 的块,通过 DCT 转到频率域。最低频对应纯色,最高频对应棋盘格状的锐边。当你把图片缩得很小时,最先消失的就是高频细节——就像把一棵树缩到 20px 高,叶子全没了,只剩一个绿色方块和一根棕色线条。
Chrome 的 partial IDCT scaling
标准做法是把 JPEG 完整解压到内存,再缩放。一个 2000×2000 的 JPEG 显示在 20×20,全量解码要占大约 12 MB,最终画面只有 1.2 KB,绝大多数信息在缩放时都会丢。
Chrome 通过 Skia + libjpeg-turbo 走了另一条路:partial IDCT scaling。它先算出最接近目标尺寸的 8 分母分数,在解码阶段就直接只取低频系数,跳过高频部分。对 1/8 缩放来说,每个 8×8 块最终只剩一个像素,而且只保留了「常量分量」——边缘柔化和渐变全被扔了。结果就是图标看起来更粗、更实,少了该有的精致感。
Firefox 没有走这条路,所以保留了完整解码再缩放的流程,图标看起来更接近原图。
这意味着什么
这不是 bug,是 deliberate trade-off:用视觉 fidelity 换内存和速度。但问题在于,JPEG 的优化目标本来就是照片,不是图标。高频细节对摄影来说是无用噪声,对图标却是生命线。
可落地的下一步
- 图标和 favicon 直接上 SVG;它不依赖解码器策略,永远 crisp。
- 小尺寸位图用 PNG / WebP / AVIF,别用 JPEG。
- 检查现有图标管道:如果构建流程里有「把 SVG 转 JPEG 做兼容」这一步,考虑砍掉。
- 如果你看到 Chrome 里某个 15px 图标莫名发粗,先看格式,再看 CSS,最后才怀疑渲染引擎。
评论区
0 条评论
登录后可评论。