Web 优化:图片压缩简介

发布时间:

最后更新:

作为一个有强迫症的人,我对应用的性能相当敏感。众所周知多媒体资源是网页里最耗流量的,其中最常用的图片自然就成了优化的重点,我的博客图还是挺多的,所以在图片优化这一块下了大功夫。

首先把结果摆出来,相当好:

压缩方式 压缩率 %
AVIF 5.73
WebP 13.8
Pngquant 34.74
Mozjpeg 39.49
SVGO 65.56
SVGO + brotli 16.47

以上是本站目前全部 155 张的图片统计,压缩率指优化后的体积 / 原图体积,越低越好。

图片优化这块还是有很多细节和坑,我准备写一系列的文章,把我的经验都分享出来。本文是此系列的第一篇,主要对图片的压缩方案做介绍。

优化思路 #

要做图片优化,首先得了解主流四大格式:

现在网页上用的图基本就是这四个,都是很多年前的东西了。

相同格式的优化 #

PNG 大多用来保存原图,这类图片质量一般都很高,但相对的压缩率就不那么高了,用来存档还行,放在网络上传输有点浪费流量。

通常 PNG 被称作无损格式,这个说法实际上是错的,有没有损取决于转换过程中是否改变了原图的信息,而不是格式本身。换句话说,是否无损取决于你用的工具。

从感官学上讲,一点点的失真是可以接受的,毕竟大多数用户不会拿着放大镜看你的图,真要原图也可以单独提供下载,把 PNG 图有损压一下可以大幅降低文件体积。当然压缩的结果必须仍是 PNG 图,不能转 JPG 因为不支持透明。

JPG 图基本都是高压缩率的,但由于各种编码器实现不同,所以还有二压的空间,通过更先进的编码器重新压缩,可以实现较小的失真下继续降低体积

另外不要对二压有恐惧,只要用好的编码器、调好参数基本不会有多大的质量损失,那个图片越压越绿纯粹是安卓编码器的 BUG

SVG 不同于光栅图,对其的优化主要从两个方面入手:

  1. 写法转换,删除无用的信息。就跟 JS 的压缩一样,同样的效果换一种写法可能就短一点;另外还可以删减小数位数,不过这是有损的一般不用。JS 平台就有压缩 SVG 的库 SVGO

  2. SVG 是基于 XML 的,说白了就是文本,所以优化完了还可以再拿文本压缩算法压一遍,浏览器支持的算法有 zip、gzip 和新一代的 brotli。

GIF转视频 #

GIF 图质量之差,体积之大相信大家都体验过,它还能活着只因为有动图的功能,不过仔细想一想动图跟视频不就是一回事吗,视频还可以多个声音。

GIF 图之所以现在还能见到,全靠当年的浏览器不支持视频,如今已进入视频时代,是时候淘汰掉 GIF 了,无论是主流的 AVC、没人鸟的 HEVC 还是下一代的 VVC 视频编码都比它先进得多。

即使不想转视频,也是有 Gifsicle 这样的工具可以压缩 GIF 图的。

使用新一代编码 #

上面讲到主流的格式都是上个世纪的东西,软件技术发展这么快,当然会有新的算法出现啦,接下来就说一说这些新的编码。

这里的新一代编码指 2000 年以后发明的,且被(或未来可能被)浏览器广泛支持的编码。

视频编码的历史视频编码的历史

新一代的图片编码都是从视频编码衍生出来的,因为视频就是一连串图片,视频编码自然包含了对图片压缩的部分(帧内编码)。新一代的图片编码都同时支持透明度和动画,所以没有必要再分出三种格式了。

WebP #

WebP 是 VP8 视频编码衍生出来的,目前已经被广泛的接受(全靠他 Google 爹的垄断浏览器),成为了新一代的前端图片格式。

WebP 的兼容性WebP 的兼容性

作为新一代编码(其实也不新了),WebP 对大多数图片有着更好的压缩率和图片质量。这里有一个把图片压到相同的质量下,以 JPG 为基准,WebP 和 AVIF 图片体积的对比:

AVIF and WebP vs JPEGAVIF and WebP vs JPEG

可以看到 WebP 的体积通常比 JPG 小 30%,所以给图片转码个 WebP 作为渐进增强是十分有价值的。

下面那 2.7% 负优化情况在本文后面会有讲解。

AVIF #

AVIF 是 AV1 视频编码对应的图片格式,AV1(对应VP10) 是 VP8 的下两代,AVIF 也就成为了 WebP 的继任者,它拥有比 WebP 更高的压缩率和更好的质量。

在上面的对比图里 AVIF 压缩率比 WebP 高了 20%,而且没有负优化的情况。

AVIF兼容性AVIF兼容性

不过目前 AVIF 的生态还未成型,在写本文时 AVIF 正迎来一个爆发期,各种评测层出不穷,可见其受欢迎的程度。

未来的编码 #

H.266 / VVC #

视频和图片的压缩还远未达到终点,新的技术正在不断的开发。从 2015 年 10 月开始的新一代的视频编码 H.266/VVC 前不久终于确定了标准,不知道会不会像 HEVC 一样推出图片编码呢。

JPEG XL #

https://jpeg.org/jpegxl

编码的竞争如此激烈,以至于 JPEG 专家组也坐不住了,于 2017 年推出了新的编码,JPG 的正统继承者 JPEG XL。在同样支持一堆新特性及更高的压缩率的同时,还向后兼容 JPEG 解码器,升级更加顺滑。

WebP 2 #

https://chromium.googlesource.com/codecs/libwebp2

WebP 的第二代,2020 年 10 月开始的新项目,目标是进一步提高压缩率(+30%)以及支持新一代图片特性(10bit HDR)。因为 WebP 的效果不错所以下一版也是很值得期待的。

没能成为主流的编码 #

顺便提一下那些没能火的,这些编码也有很好的压缩率,但是因为一些原因与主流支持失之交臂。

从上面这些嗝屁的编码中,可以总结出被广泛支持需要的的两个条件:

  1. 开放专利,如果有专利问题各大厂商肯定会犹豫,只有开放的技术才有可能成为主流。

  2. 谷歌支持,浏览器上的技术,只要没有没有谷歌爸爸的肯首,那肯定是火不起来的,毕竟主流浏览器内核 = Chromium。

总结一下 #

画个流程图就是这样了,当然这里面还有很多细节问题需要处理,在后续的文章中再做讲解。

流程图流程图

免费工具推荐:

WebP 的缺陷 #

通常 WebP 被视为传统格式的替代者,但在实际使用中我发现它并不一定比旧格式更好。

WebP的质量损失WebP的质量损失

这个图就是本站在宽屏下最顶部的 Banner,压出来的结果不是很好,可以看到斜边和阴影产生了严重的马赛克。

我统计了博客里所有的图,发现 WebP 有损压缩对锐利的边缘失真严重,并增加体积,这可能是算法本身的缺陷。

另外 WebP 压缩后的图片甚至能比原图还大,在官网上也有对此的描述:can_a_webp_image_grow_larger_than_its_source_image

举个例子,在本站的一张图上:

WebP两种压缩对比WebP两种压缩对比

左边的是有损模式,可以看到红色的字符串、紫色的关键字、以及绿色的注释部分都有色彩失真,而且文件体积是无损模式的7倍。有损压缩我还加了-sharp_yuv参数的,要是没这个参数那简直没法看。

你可以自己尝试一下,把这张图 上传到 Squoosh 并选择 WebP Compress,看看它是怎么把你的图压成一坨屎的。

因为有这些问题,所以不能无脑把所有图片全用 cwebp 默认参数直接压。

这个的解决方案在我的另一篇文章《WebP 参数分析》里有解释,就是同时使用无损和有损压缩,然后选择体积更小的。

渐进式图片? #

渐进式指先显示模糊版,随着加载逐渐清晰的图片。我经常听到有人吹渐进式图片,说先显示一个模糊图体验更好,但我怀疑他们没有真的想过这个问题。

一张全是马赛克的图能看吗?相反,非渐进式的载入到一半起码还能看一部分。

很多图片比如漫画、文字类的,其局部就包含独立的信息,非渐进式的能边加载边看,而渐进式图片在完成之前只能傻等。

当然这是我的经验,我眼睛没有从一张马赛克图还原出原图的能力,也许那些吹渐进式图片的人有。所以以载入体验更好的理由使用渐进式图片是站不住脚的。

当然这并不意味着渐进式就一无是处,它对体积是影响的,还是统计博客里所有的图,测试 JPG(Mozjpeg 的-progressive 选项),和 PNG(libpng 的 interlace选项)使用和不使用时转换结果的大小,结果:

十几个点的体积还是挺重要的,所以为了压缩率,JPG 应当使用渐进式而 PNG 不用。 顺便一提 WebP 和 AVIF 都没有渐进式这功能。

版权声明 #

图片 AVIF and WebP vs JPEG 来自 Comparing AVIF vs WebP file sizes at the same DSSIM,作者 Daniel Aleksandersen 使用 CC BY-SA 4.0 许可。

图片 视频编码器的历史 没能找到原作者。

评论加载中