【译】重要的图像优化之五:什么是WebP?

注明:本人原创翻译,原版为Essential Image Optimization电子书,这里将其拆分为几篇文章发布。另外,文中部分链接可能会因为“网络”原因无法打开。不必着急,我会慢慢将其中一些比较好的内容翻译过来发表,都会在这个“Web图像技术深究”专题中。

目录

正文:

什么是WebP?

WebP是一个来自Google的新型图像格式,它旨在以可接受的视觉质量提供较低文件大小的无损和有损压缩。另外,WebP还包括了对alpha通道透明度和动画的支持。

在过去一年中,WebP在有损和无损模式下减少了10%的压缩体积,并且提高了10%的压缩速度。WebP并不是一个能够用于所有目的的工具,但它在图像压缩社区中已经具有了一定的地位和不断增长的用户群。那么,我们来看看为什么。

Modern-Image16.jpg

WebP:不同质量级别下文件体积和相似度对比。

WebP的表现如何?

有损压缩

根据WebP团队的描述,使用VP8或VP9视频关键帧编码进行处理的WebP压缩文件平均比JPEG文件小了25-34%。

在较低质量设置(0~50)下,WebP具有比JPEG更大的优势,因为它可以消除丑陋的块状伪影;在中等质量设置(-m 4 -q 75)下,WebP则是速度与体积平衡的默认选择;而在较高质量设置(80-99)时,WebP的优势则在缩小。WebP被推荐应用在速度比质量更重要的场景中。

无损压缩

WebP无损文件的体积比PNG文件小了26%;同时,WebP无损压缩图片的加载时间与PNG相比减少了3%。也就是说,您通常不会想在网络上为您的用户提供无损压缩的图像。另外,无损和锐利边缘(如non-JPEG)是不同的。无损模式的WebP可能更适合于档案内容。

透明度

WebP具有一个无损8位透明度通道,而只比PNG多出22%的字节。它还支持有损的RGB透明度,这是WebP独有的功能。

元数据

WebP文件格式支持EXIF照片元数据和XMP数字文档元数据,它还包含了一个ICC颜色配置文件。

WebP提供了更好的压缩,但代价是更多的CPU开销。在2013年,WebP的压缩速度会比JPEG慢10倍,但是现在已经可以忽略不计了(有些图像可能会减慢2倍)。当WebP用于生产作为你应用构建一部分的静态图像时,这不应该是一个大问题。然而,作为动态的图像生产工具,就可能会导致可察觉的CPU开销,这将是您需要考量的问题。

注意:WebP有损质量设置百分比,与JPEG的质量百分比并不能直接比较。因为WebP通过丢弃更多数据来实现更小的文件体积,因此“70%质量”的JPEG将与“70%质量”的WebP图像完全不同。

谁在生产环境中使用WebP?

许多大型公司正在生产环境中使用WebP,来降低成本并减少网页的加载时间。

Google的报告表明,以一天提供430亿图像请求来计算,使用WebP有损压缩将比其他有损压缩解决方案节省30%~35%的存储空间,而使用无损压缩则是节省26%。这种空间的节省无疑是非常重要的。而如果浏览器对WebP支持更好、更广泛,节省将会更大。Google已经将WebP应用于Google Play和YouTube等网站的生产环境。

Netflix、亚马逊、Quora、雅虎、沃尔玛、Ebay、“卫报”、“财富”和“今日美国”均是为已经支持格式的浏览器提供了WebP。VoxMedia 通过给他们使用Chrome的用户提供WebP,将The Verge网站(一个美国科技媒体网站) 减少了1~3倍的加载时间500px则表示,通过切换为WebP提供给自己的Chrome用户,在保持类似或更好的图像质量的同时将文件的体积平均降低的25%。

这个样本列表显示,有很多的公司都使用WebP。

webp-conversion.jpg

WebP在Google的应用:在YouTube、Google Play、Chrome的Data Saver以及G+(Google+,Google的社交网络服务)上,每日响应430亿的WebP请求。

WebP编码如何执行?

WebP的有损编码被设计用于与JPEG静态图像进行竞争。它有三个关键流程:

宏块分解:将图像分解成一个16×16亮度像素(宏)块集合和两个8×8色度像素块集合。这可能听起来很像JPEG的方法,通过色彩空间转换、色度通道下采样和图像细分来处理。

Modern-Image18.jpg

预测:宏块的每个4×4子块都具有一个预测模型,可以有效地进行滤波。它定义了一个块周围的两组像素,分别为A(上面的行)和L(左侧的列)。编码器会使用这两个像素块A和L,尝试填充4x4像素的测试块,并确定哪个像素块创建的测试块最接近原始块的值。Colt McAnlis在他的文章“WebP有损耗模式的工作原理”中更深入地讨论了这一点。

Modern-Image19.jpg

最后会使用离散余弦变换(DCT)执行几步类似于JPEG编码的过程。之间的一个关键区别是,这里会使用一个算术压缩器,不同于JPEG的霍夫曼编码。

如果您想深入了解WebP的压缩技术,Google开发人员的文章“ WebP压缩技术”将帮助你。

WebP的浏览器支持

不是所有的浏览器都支持WebP,然而根据CanIUse.com的统计,WebP的浏览器用户支持在全球约为74%。Chrome和Opera本地支持它。Safari,Edge和Firefox已经尝试了它,但没有在官方发行版中发布。这就将为用户获取WebP图片的任务移交给了前端开发人员,这个稍后再说。

以下是主要的浏览器和WebP的支持情况:

  • Chrome:Chrome在第23版开始全面支持。
  • Chrome for Android:自Chrome 50起。
  • Android:自Android 4.2起。
  • Opera: 从12.1版本起。
  • Opera Mini:所有版本。
  • Firefox:一些beta支持。
  • Edge:一些beta支持。
  • Internet Explorer:不支持。
  • Safari:一些beta支持。

WebP不是没有缺点的。它缺乏全分辨率的颜色空间选项,并且不支持逐行解码(渐进式)。总的来说,WebP工具是一个适合的、浏览器支持的(写作时仅限于Chrome和Opera浏览器)、可能会覆盖足够的用户的值得你去考虑的压缩选项。

怎样将图片转换为WebP格式?

一些商业和开源的图像编辑处理软件都支持WebP格式。其中有个特别有用的应用叫做XnConvert,一个免费的、跨平台的批量图片转换器。

注意: 一定要避免将低质量或一般质量的JPEG转换为WebP。这是一个很常见的错误,它会导致生成的WebP图片带有JPEG压缩产生的虚影效果。还会使保存的WebP图片效果变差和失真,甚至损失的质量会翻倍。作为转换初始的图像文件,一定要是高质量的,或者原图。

XnConvert

XnConvert能够批量的进行图像处理,并兼容500多种图像格式。你可以组合超过80种的独立操作,以多种方式转换或编辑的图像。

Modern-Image20.jpg

XnConvert支持批量的图像优化,允许原图到WebP或其他格式的直接转换。除了压缩,XnConvert还可以执行图像元数据剥离、裁剪、颜色深度定制以及其他转换等操作。

下面是XnView网站上列出的XnConvert的一些选项,包括:

  • 元数据:编辑
  • 转换:旋转、裁剪、调整尺寸
  • 调整:亮度、对比度、饱和度
  • 过滤器:模糊、浮雕、锐化
  • 效果:屏蔽、水印、渐晕

使用XnConvert,你可以导出为大约70种不同的文件格式,包括WebP。它支持Linux、Mac以及Windows操作系统。因此,我们强烈推荐XnConvert,它特别适合小企业。

Node模块

Imagemin是一个非常流行的Node.js的图像缩小模块,它还包含了一个WebP转换插件(imagemin-webp)。支持有损和无损两种模式。

要安装imagemin和imagemin-webp,需要运行:

> npm install --save imagemin imagemin-webp

然后,我们可以使用require()调用这两个模块,并且运行它们处理在项目目录中的任意图片(如JPEG)。下面是使用Imagemin,有损压缩并批量生成质量为60的WebP图片:

const imagemin = require('imagemin');
const imageminWebp = require('imagemin-webp');

imagemin(['images/*.{jpg}'], 'images', {
    use: [
        imageminWebp({quality: 60})
    ]
}).then(() => {
    console.log('Images optimized');
});

与JPEG类似,要注意到输出后的压缩效果。评估什么样质量设置,对你的图像才是有意义的。Imagemin-webp还可通过传递lossless: true选项,来生成无损压缩的WebP图像(支持24位颜色和全透明度):

const imagemin = require('imagemin');
const imageminWebp = require('imagemin-webp');

imagemin(['images/*.{jpg,png}'], 'build/images', {
    use: [
        imageminWebp({lossless: true})
    ]
}).then(() => {
    console.log('Images optimized');
});

这里还有一个由Sindre Sorhus基于imagemin-webp构建的Gulp的WebP插件;当然,也包括WebPack的插件。Gulp插件可以接收imagemin的任何选项设置,如有损压缩:

const gulp = require('gulp');
const webp = require('gulp-webp');

gulp.task('webp', () =>
    gulp.src('src/*.jpg')
    .pipe(webp({
        quality: 80,
        preset: 'photo',
        method: 6
    }))
    .pipe(gulp.dest('dist'))
);

或无损压缩:

const gulp = require('gulp');
const webp = require('gulp-webp');

gulp.task('webp-lossless', () =>
    gulp.src('src/*.jpg')
    .pipe(webp({
        lossless: true
    }))
    .pipe(gulp.dest('dist'))
);

使用Bash批量优化图像

XNConvert支持批量的图像压缩,但是如果你希望避免使用一个应用程序或者一套构建系统,那么可以使用bash命令和图像优化二进制文件,它们同样使压缩变得简单。

你可以使用cwebp命令,将图像批量转换为WebP:

find ./ -type f -name '*.jpg' -exec cwebp -q 70 {} -o {}.webp \;

或者,使用jpeg-recompress采用MozJPEG编码,批量优化您的原图:

find ./ -type f -name '*.jpg' -exec jpeg-recompress {} {} \;

并且,使用svgo优化SVG(我们稍后将介绍):

find ./ -type f -name '*.svg' -exec svgo {} \;

Jeremy Wagner有一篇文章《使用Bash优化图像》比较全面的讨论这个问题,同时还有个姊妹篇《使用Bash快速优化图像》也值得读一下。

其他的WebP图像处理和编辑应用程序包括:

  • Leptonica — 一个开源图像处理和图像分析的应用网站。
  • Sketch支持直接导出WebP格式
    • GIMP — 免费、开源的Photoshop替代品。一个图像编辑器。
    • ImageMagick — 用于创建、设计、转换或编辑位图图像,一个免费的命令行应用。
    • Pixelmator — 适用于Mac的商用图像编辑器。
    • Photoshop的WebP插件 — 免费的,支持图像导入和导出,来自于Google。

Android: 您可以使用Android Studio将现有的BMP、JPG、PNG或静态GIF图像转换为WebP格式。有关更多信息,请参阅使用Android Studio创建WebP图像

如何在我的操作系统上浏览WebP图像?

当你将WebP图像拖放到基于Blink的浏览器(Chrome、Opera、Brave)中进行预览时,你还可以使用Mac或Windows的附加组件直接从操作系统预览它们。

几年前,当Facebook试验WebP格式时发现,用户将WebP图片通过右键另存到本地磁盘后,无法通过浏览器以外的程序打开浏览。这其中主要有三个主要问题:

  1. “另存为”但无法在本地浏览WebP图片。这个可以通过将Chrome注册为“.webp”的打开应用来解决。
  2. “另存为”并将图片加入邮件中分享给不适用Chrome的其他人。Facebook通过引入一个醒目的“下载”按钮来解决这个问题,这个按钮点击时会返回JPEG给用户。
  3. 右键 > 复制链接 -> 分享链接到网络上。这个最后通过HTTP通讯协议中的content-type来解决。

这些问题可能对你的用户来说不太重要,但是对于WebP图片的通用性,Facebook的试验过程可谓是一个有趣的注解。值得庆幸的是,现在不同的操作系统上,都有用于查看和使用WebP的实用程序了。

在Mac上,可以使用Quick Look的WebP插件(qlImageSize)。它工作的很好:

Modern-Image22.jpg

如何提供WebP?

在不支持WebP的浏览器中,WebP图像最终不会显示,这明显不是我们想要的。为了避免这种情况,我们可以使用几种策略根据浏览器支持情况有条件地提供WebP图像服务。

play-format-webp.jpg

Chrome的开发者工具中的网络面板中“类型”一栏显示,网站对Blink内核的浏览器返回了WebP格式。

image.png

可以看到Google Play对Blink内核浏览器返回WebP的同时,对于像Firefox这样不支持WebP的浏览器返回JPEG。

以下是从服务端返回WebP给你的用户的几个方案:

使用 .htaccess配置来提供WebP的副本

下面将说明当在服务器上存在与JPEG或PNG图像相匹配的.webp版本时,如何使用.htaccess文件将WebP文件提供给支持的浏览器。

Vincent Orback推荐使用如下方法:

浏览器可以通过Header中指定Accept来显式的指定WebP支持。通过这个标识,你就可以控制你的服务端,返回图像的WebP版本(如果这个WebP图像已经储存在磁盘上,而不是JPEG或PNG格式)。这个方法并不总是有效(例如,对于静态化的网站,如Github或S3),所以在选择这种方案时请先检查下它对于你的网站是否有效。

以下是Apache Web服务器的.htaccess文件示例:

<IfModule mod_rewrite.c>

  RewriteEngine On

  # Check if browser support WebP images
  RewriteCond %{HTTP_ACCEPT} image/webp

  # Check if WebP replacement image exists
  RewriteCond %{DOCUMENT_ROOT}/$1.webp -f

  # Serve WebP image instead
  RewriteRule (.+)\.(jpe?g|png)$ $1.webp [T=image/webp,E=accept:1]

</IfModule>

<IfModule mod_headers.c>

    Header append Vary Accept env=REDIRECT_accept

</IfModule>

AddType  image/webp .webp

如果页面上显示的.webp图像有问题,那么请确保在服务器上启用了image/webp类型支持。开启方法如下:

Apache:将以下代码添加到.htaccess文件中:

AddType image/webp .webp

Nginx:将以下代码添加到您的mime.types文件中:

image/webp webp;

注意:Vincent Orback提供了一个htaccess配置示例,可以作为参考;Ilya Grigorik维护一组用于为WebP提供服务配置脚本

使用 <picture> 标签

浏览器本身能够通过使用<picture>标签,来选择要显示的图像格式。<picture>标签利用多个<source>和一个<img>来设置显示的图像,其中<img>是包含了图像的、真实的DOM元素。浏览器会循环遍历<source>提供的链接,并检索到第一个匹配的结果。如果用户的浏览器中不支持<picture>,浏览器将会将它渲染为一个<div>,并使用其中的<img>

注意: 注意<source>的排列顺序。不要将image/webp的格式放在旧格式的后面,而是将它们放在前面。浏览器将会先解析到它们并得到匹配,而不会解析到其他支持更广泛的格式。如果物理尺寸相同(不使用media属性),也可以按照文件大小的顺序放置图像。一般来说,解析的顺序就是摆放的顺序。

以下是一些HTML示例:

<picture>
  <source srcset="/path/to/image.webp" type="image/webp">
  ![](/path/to/image.jpg)
</picture>

<picture>   
    <source srcset='paul_irish.jxr' type='image/vnd.ms-photo'>  
    <source srcset='paul_irish.jp2' type='image/jp2'>
    <source srcset='paul_irish.webp' type='image/webp'>
    ![](paul_irish.jpg)
</picture>

<picture>
   <source srcset="photo.jxr" type="image/vnd.ms-photo">
   <source srcset="photo.jp2" type="image/jp2">
   <source srcset="photo.webp" type="image/webp">
   ![](photo.jpg)
</picture>

使用自动化的CDN转换WebP

一些CDN支持将图像自动转换为WebP,可以使用Client Hints来让后端尽可能地提供WebP图像。请检查您的CDN,查看服务中是否包含了WebP支持。你可能有一个简单的解决方案,只是等待着你去寻找。

WordPress的WebP支持

Jetpack — Jetpack是一款流行的WordPress插件,它包括一个名为Photon的CDN映像服务。使用Photon,你就可以获得无缝的WebP图像支持。这个叫Photon的CDN服务是包含在Jetpack的免费清单中的,因此这是一个很棒很有效的实现。不过,缺点是Photon会调整您的图像大小,将一个查询字符串放在您的URL中,并且每个图像都需要额外的DNS查找。

Cache Enabler and Optimizer — 如果您使用的是WordPress,那么你至少有一个半开源的选项。WordPress的开源插件Cache Enabler有一个菜单复选框可以勾选,用于缓存WebP图像,如果当前用户的浏览器支持它就会提供给用户。这使得WebP图像服务变得容易。但是,这个插件有一个缺点:Cache Enabler需要使用一个名为Optimizer的姐妹程序,而它则是需要支付年费的。这对于一个需要真正的开源解决方案的情况来说,显然是不合适的。

Short Pixel — Cache Enabler的另一个搭配选择是使用Short Pixel,它的功能和Optimizer很像,也是付费的。但是,Short Pixel可以每个月免费优化100张图片。

最好使用<video>压缩GIF动画

动画GIF使用依然广泛,尽管这是一个功能非常有限的格式。虽然从社交网络到流行的媒体网站都大量嵌入了动画GIF,但是其实这个格式从未被设计用于视频或动画存储。事实上,GIF89a规范一个在提示“GIF不是作为动画的平台”。格式中颜色、图层和纬度的数量都影响GIF动画文件的体积,切换到视频格式可以提供最大的空间节省。

image.png

动画GIF对比视频:同等质量下不同文件格式的文件大小对比。

提供相同内容和质量的MP4文件可能会在文件体积上节省达到80%或更多。GIF通常不仅会浪费大量的带宽,而且加载时间较长、只支持较少的颜色,因此只能使网站提供的用户体验大打折扣。您可能已经注意到,上传到Twitter的动画GIF在Twitter上的表现是要优于其他网站的。这是因为,Twitter上的动画GIF实际上并不是GIF。为了提高用户体验和减少带宽占用,上传到Twitter的动画GIF实际上是被转换成为了视频。同样,Imgur也将上传的GIF转换为了静音的MP4视频。

为什么GIF多数情况下要大很多?因为,动画GIF将每个帧存储为了无损GIF图像 - 是的,无损。我们经常遇到的GIF的质量下降,其实是因为GIF受限于它的256色调色板。GIF格式下文件通常很大,因为它不像H.264这样的视频编解码器会考虑压缩相邻帧。MP4视频将每个关键帧存储为有损的JPEG,并其丢弃一些原始数据以实现更好的压缩。

如果您可以切换到视频

  • 使用ffmpeg转换你的动画GIF(或原动画)为H.264 MP4视频。我一般是使用Rigor提供的一行命令:
ffmpeg -i animated.gif -movflags faststart -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" video.mp4

如果您必须使用动画GIF

  • 可以使用像Gifsicle这样的工具,清除元数据和未使用的调色板条目,并最小化帧之间的变化。
  • 考虑使用一个有损的GIF编码器。Gifsicle派生的Giflossy支持一个—lossy命令标识,可以删除掉60%~65%文件体积。还有一个很好的基于它的工具,称为Gifify。对于非动画GIF,将其转换为PNG或WebP。

有关更多信息,请查阅Rigor编写的关于GIF的电子书

下一篇:【译】重要的图像优化之六:SVG的优化

推荐阅读更多精彩内容