注明:本人原创翻译,原版为Essential Image Optimization电子书,这里将其拆分为几篇文章发布。另外,文中部分链接可能会因为“网络”原因无法打开。不必着急,我会慢慢将其中一些比较好的内容翻译过来发表,都会在这个“Web图像技术深究”专题中。
目录
- 介绍
- 如何判断我的图像是否需要优化?
- 如何选择正确的图像格式?
- “素人”JPEG
- JPEG的压缩模式
-
什么是WebP?
- WebP的表现如何?
- 谁在生产环境中使用WebP?
- WebP编码如何执行?
- WebP的浏览器支持
- 如何将我的图像转换为WebP?
- 如何在我的操作系统上查看WebP图像?
- 如何提供WebP?
- SVG优化
- 避免使用有损编解码器重复压缩图像
-
减少不必要的图像解码和尺寸调整带来的损耗
- 使用srcset提供HiDPI图像
- 艺术化的响应
- 颜色管理
- 图像拼合技术
- 延迟加载非关键图像
- 避免<code>display: none;</code>的陷阱
- 图像CDN服务对你有意义吗?
- 缓存图像资源
- 预加载关键图像资源
- 图像的网络性能预算
- 最后的建议
- 附注
正文:
“素人”JPEG
JPEG可能是世界上使用最广泛的图像格式。如前所述,HTTP Archive抓取的站点上看到的图像中有45%是JPEG格式。您的手机、数码相机、旧的网络摄像机——一切的设备都支持这种编解码器。它也很确实很古老,第一次发布可以一直追溯到1992年。在这期间,已经有很多人进行了大量研究,试图改进它,让它变得更好。
JPEG是一种有损压缩算法,它丢弃信息以节省存储空间,并在尝试保持文件尽可能小的同时保留图像质量的方面做出了许多努力。
你的用例可以接受什么样的图像质量?
像JPEG这样的格式最适用于那些具有多个颜色区域的照片或图像。而且大多数优化工具都允许您设置您喜欢的压缩级别;较高级别的压缩可以减小文件的大小,但可能会引起重影、光晕或马赛克等失真效果。
JPEG: 从最佳质量转变到最低质量时,可以感觉到的压缩影响可能会增加。请注意,不同工具中的质量得分可能会有较大的差异。
选择什么样的质量设置,请根据你的业务需求:
- 最高质量:在质量要求远比带宽重要时使用。可能是因为这个图片在你的设计中很重要或者它需要全分辨率显示。
- 一般质量:当你追求较小的图片,但又不想对图片质量产生较大影响时使用。你的用户可能仍然希望看到的图片比较清晰。
- 较低质量:当网络带宽更重要时使用。这些图片更适用于不稳定或带宽较低的网络。
- 最低质量:节省带宽是至关重要时使用。用户可以接受一个较差的视觉体验,以便更快速的加载页面。
下面,我们来谈谈JPEG的压缩模式,因为它们对图片的视觉体验有很大的影响。
注意:我们有时有可能会高估用户需要的图像质量。图像质量可能被认为是高保真资源的一个偏差值。但它同样也可以是很主观的。
JPEG的压缩模式
JPEG图像格式具有多种不同的压缩模式。其中,三种流行的模式分别是基线(顺序),渐进式JPEG(PJPEG)和无损。
基线(或顺序)JPEG和渐进式JPEG有什么不同?
基线JPEG(大多数图像编辑和优化工具的默认项)以相对简单的方式进行编码和解码:从上到下。当基线JPEG加载缓慢时,用户会先看到图像的顶部,然后更多的图像将在图像逐步加载时显示。无损JPEG与基线JPEG类似,但具有更小的压缩比。
基线JPEG是从顶部到底部加载,而渐进式JPEG是从模糊到清晰。
而渐进式JPEG则是将图片进行多次扫描。第一次扫描会以模糊或低质量显示图片,后面多次扫描可逐步提高图像质量,这便是“渐进式”的意义。图像的每个“扫描”增加了更多的图片细节。最终组合时,就会创建一个最终质量的图像。
无损JPEG是通过删除由数码相机或编辑器添加的EXIF数据、优化一个图片的霍夫曼编码或者重新扫描图像等手段实现的。诸如jpegtran等工具都可以通过重新排列压缩数据而无需图像降级来实现无损压缩。jpegrescan,jpegoptim和mozjpeg(我们将在稍后介绍)同样也支持无损JPEG压缩。
渐进式JPEG的优点
PJPEGs能提供图像低分辨率“预览”功能,可以提高用户的使用体验:用户会感觉图像的加载速度更快。
在较慢的3G网络连接中,这允许用户在只收到一部分文件时就可以(大概)看到图像中的内容,并确定是否等待它完全加载完成。这会比基线JPEG所提供的图像从上到下显示方式让人更加乐于接受。
PJPEG还可以提高图像压缩率;同样10KB以上的图像,渐进式JPEG比基线JPEG可以节省2-10%的带宽。渐进式JPEG有较高压缩比,是由于JPEG中的每个扫描都能够拥有自己专用的可选霍夫曼编码。现代化的JPEG编码器(例如libjpeg-turbo,MozJPEG等)都是利用了PJPEG的灵活性,更好地打包图像数据。
注意:为什么PJPEG的压缩更好?因为基线JPEG的所有块是一次性压缩编码的。而在PJPEG中,利用一种类似离散余弦变换系数的方法可以将多个不连续的块编码在一起,从而带来更好的压缩比率。
谁在生产环境中使用了渐进式JPEG?
- Twitter.com:推特使用了质量基准为85%的渐进式JPEG。通过他们对用户延迟感知(首次扫描的时间和总体加载时间)的测试显示,总体而言,PJPEG在解决他们对较低的文件大小和可接受范围内的转码及解码时间的需求方面具有很强的竞争力。
- Facebook:脸书为他们的iOS应用使用了渐进式JPEG。他们发现数据的使用量减少了10%,并且他们载入高质量图像的速度提高了15%。
- Yelp:在切换到渐进式JPEG后,发现他们的图像尺寸减少了4.5%。另外,他们还使用MozJPEG节省了13.8%的额外费用。
包括许多以图片为核心业务的网站,比如Pinterest同样都是在生产环境中使用渐进式JPEG。
Pinterest的JPEG图像都使用了渐进式模式的编码。这可以通过多次扫描来加载来,优化用户体验。
渐进式JPEG的缺点
PJPEG解码速度更慢:有时候甚至多出3倍的时间。在具有强大CPU的台式机上,这种差异可能无法感觉到,但在性能有限的移动设备上就会很明显。为了不完整的图层可以正常工作,这需要对图像进行多次解码,而每次解码都需要消耗一定的CPU运算周期。
渐进式JPEG也并不总是更小:对于一些非常小的图像(如缩略图),渐进式JPEG的文件可能反而会大于基线JPEG。而且,对于这样小的缩略图,渐进渲染并没有什么意义。
这意味着,你在决定是否使用PJPEG时,需要进行一些测试,并找到文件大小、网络延迟和CPU周期使用的平衡点。
注意: PJPEG(和所有JPEG)有时可以在移动设备上进行硬件解码。它不会改善图片在内存中的大小,但它可以解决一些CPU负载的问题。但是并不是所有的Android设备都具有硬件加速支持;但是高端设备都会支持,所有的iOS设备也都支持。
有些用户可能会认为渐进式加载是一个缺点,因为当图像完成加载时可能会变得很难分辨。由于每个受众的感官差异很大,在使用PJPEG时请评估它对自己用户的体验是否有意义。
如何生成一个渐进式JPEG?
很多工具和库都支持导出渐进式JPEG,比如ImageMagick, libjpeg, jpegtran, jpeg-recompress以及imagemin。如果你已经有了一个现有的图片优化方案,那么增加渐进式图片加载支持可能是非常容易的:
const gulp = require('gulp');
const imagemin = require('gulp-imagemin');
gulp.task('images', function () {
return gulp.src('images/*.jpg')
.pipe(imagemin({
progressive: true
}))
.pipe(gulp.dest('dist'));
});
大多数的图像编辑工具默认情况下都是将图像保存为基线式。
色度(或颜色)抽样
我们的眼睛相对于图像中的光亮度(或者luma—一种光亮度量单位)损失来说,更易忽略图像(色度)中的颜色细节的损失。色度抽样是一种压缩方式,通过在色差通道上进行较低(相对亮度通道)清晰度的抽样从而可以减少文件大小,在某些情况下可减少15-17%,而不会对图像质量产生影响,这是JPEG图像的一个压缩选项。抽样同时也可以减少显示图像时对内存的占用。
同我们看到的图片中的形状相比,定义它的亮度(luma)反而是非常重要的。比较旧的或经过过滤的黑白照片可能并不包含颜色,但是由于亮度的作用,这些照片与有颜色的照片一样能表现各种细节。色度(色彩)其实对视觉感受影响是较小的。
在谈论色度抽样时,经常会提到一些常见的样本。一般来说有4:4:4
,4:2:2
和4:2:0
。那么这些代表什么呢?假设样本采用格式A:B:C。A是一行中的像素数,对于JPEG来说这个值一般为4;B表示第一行中的颜色数量;C表示第二行中的颜色数量。
- 4:4:4 —— 没有压缩,颜色和亮度被完全传输。
- 4:2:2 —— 水平半抽样,垂直全部抽样。
- 4:2:0 —— 第一行像素中的一半取样,并第二行忽略。
注意:jpegtran和cjpeg支持单独的亮度和色度的质量配置。通过添加
-sample
标志(例如-sample 2x1
)。并且有一些常用的规则:subsampling(-sample 2x2
)可以生成美妙的照片;no-subsampling(-sample 1x1
)最适合于截图、横幅和按钮;最终的compromise(2x1
)用于你不确定将图片使用在哪里。
通过减少色度分量中的像素,可以显著减小颜色分量的大小,从而最终减少图像文件的字节大小。
质量为80的JPEG在Chrome中不同样本配置下的显示对比。
色度抽样值得被用于大多数类型的图像。但是它确实有一些例外:由于抽样依赖于我们眼中的视觉限制,当对于压缩图像而言,色彩细节可能与亮度(例如医学图像)一样重要时,使用色度抽样就不是很好。
另外,包含字体的图像也可能会受到明显的影响,因为文本的抽样可能会降低其可读性。而一些更为锐利的边缘也是难以被压缩的,因为色度取样是被设计为更好地处理具有更多软过渡的摄影场景。
提示:在JPEG规范中其实并没有规定Chroma子采样的确切方法,因此不同的解码器的处理方式可能不同。MozJPEG和libjpeg-turbo都是使用了缩放方法。而较旧版本的libjpeg使用了不同方法:在颜色中增加边缘震荡效应。
注意:Photoshop在使用“Save for web”功能时是自动设置色度抽样样本的。当图像质量设置在51-100之间时,根本不使用抽样(即样本
4:4:4
)。当质量低于此值时,将使用4:2:0
进行抽样。这也就是将质量从51切换到50时,可以明显观察到的文件大小减少的一个原因。
注意:在抽样讨论中,常常提到YCbCr这个术语。这是一个可以表示伽玛校正的RGB颜色空间的模型。Y是伽马校正亮度,Cb是蓝色的色度分量,Cr是红色的色度分量。如果您查看ExifData,您将在采样级别旁边看到YCbCr。
如果想进一步了解色度抽样,请参阅《为什么你的图像不使用色度抽样?》
JPEG引发的格式拓展
以下是网络上当前图像格式的情况:
总的来说——碎片化严重。我们经常需要有条件地为不同的浏览器提供不同的图像格式,以充分利用浏览器任何先进的功能。
- JPEG 2000 (2000) - 从基于离散余弦变换到基于小波的切换方式改进。浏览器支持:Safari桌面+ iOS。**
- JPEG XR (2009) - 替代JPEG和JPEG 2000,支持 HDR和宽色域色彩空间。编码/解码速度比较慢,但是产生比JPEG更小的文件。浏览器支持:Edge,IE。
- WebP (2010) - Google支持的基于块预测的图像格式,包括有损和无损压缩。WebP同时提供JPEG的字节压缩特性和一般文件较大PNG才能提供的透明度特性。但是不支持色度抽样和渐进式加载。另外解码也比JPEG解码速度慢。浏览器支持:Chrome,Opera。通过Safari和Firefox进行实验。
- FLIF (2015) - 基于压缩比的一种无损图像格式,并声称胜过PNG、无损WebP、无损BPG和无损JPEG 2000。浏览器支持:无。注意,有一个JS浏览器解码器。
- HEIF和BPG。从压缩的角度来看,它们是一样的,但是有不同的包装:
- BPG (2015) - 旨在基于HEVC(高效率视频编码)进行高效压缩的JPEG替代者。与MozJPEG和WebP相比,可以压缩出更小的文件。由于许可证问题,不太可能获得广泛的支持。浏览器支持:无。注意,有一个JS浏览器解码器。**
- HEIF (2015) - 用于存储HEVC编码的图像和图像序列的一种格式。苹果公司在 WWDC宣布,他们将在iOS上将JPEG转换为HEIF,从而节省了2倍的文件存储空间。浏览器支持:无,在文章创建时。现在Safari(Mac和iOS 11)可以支持。
如果你想更直观的了解,你可以欣赏一些上述格式的视觉比较工具,比如这里或这里。
综上所述可以看到,浏览器对图像格式的支持是很分散的。如果你希望利用上述任何一种格式,那么你就可能需要有条件地为每个目标浏览器提供不同的返回内容。在Google,我们已经看到了对WebP的一些支持,所以我们后面会做更深入的介绍。
您还可以使用.jpg扩展名(或任何其他扩展名)来表示一个图像格式(例如WebP,JPEG 2000),因为浏览器可以决定它渲染图像的媒体类型。这就允许服务器端使用请求中的Content-Type设置来决定要发送哪种格式的图像,而无需更改HTML中的内容。像Instart Logic这样的服务商在向他们的客户传送图像时,都是使用的这种方法。
接下来,让我们讨论另一种情况,当你无法有条件地提供不同的图像格式时使用的方法:使用JPEG优化编码器工具。