什么是 WebP?为什么要使用该功能?
WebP 是一种有损和无损压缩方法,可用于网上的大量照片、半透明和图形图片。有损压缩的程度是可调整的,以便用户在文件大小和图片质量之间进行权衡。与 JPEG 和 JPEG 2000 相比,WebP 通常可实现比 JPEG 和 JPEG 2000 平均多 30% 的压缩,且不会降低图片质量(请参阅比较研究)。
WebP 格式的主要目的是创建更小、更美观的图片,从而帮助加快 Web 的加载速度。
哪些网络浏览器本身支持 WebP?
希望提升网站性能的网站站长可以轻松为其当前图片创建经过优化的 WebP 替代图片,然后有针对性地将其投放给支持 WebP 的浏览器。
- WebP 有损支持
- Google Chrome(桌面版)17+
- Android 版 Google Chrome 25 或更高版本
- Microsoft Edge 18 及更高版本
- Firefox 65 及更高版本
- Opera 11.10 及更高版本
- 原生网络浏览器,Android 4.0 及更高版本 (ICS)
- Safari 14+(iOS 14+、macOS Big Sur+)
- 支持 WebP 有损、无损和 Alpha 版
- Google Chrome(桌面版)23+
- Android 版 Google Chrome 25 或更高版本
- Microsoft Edge 18 及更高版本
- Firefox 65 及更高版本
- Opera 12.10 及更高版本
- 原生网络浏览器, Android 4.2+ (JB-MR1)
- 浅月 26 岁以上
- Safari 14+(iOS 14+、macOS Big Sur+)
- WebP 动画支持
- Google Chrome(桌面和 Android)32+
- Microsoft Edge 18 及更高版本
- Firefox 65 及更高版本
- Opera 19 及更高版本
- Safari 14+(iOS 14+、macOS Big Sur+)
另请参阅:
如何检测浏览器是否支持 WebP?
您应仅向能够正确显示 WebP 图片的客户端提供 WebP 图片,对于无法正确显示 WebP 图片的客户端,则回退到旧版格式。幸运的是,可在客户端和服务器端检测 WebP 支持的多种技术。某些 CDN 提供商在其服务中提供 WebP 支持检测。
通过 Accept 标头进行服务器端内容协商
Web 客户端通常会发送“Accept”请求标头,表明它们愿意在响应中接受哪些类型的内容格式。如果浏览器事先表明它将“接受”image/webp 格式,网络服务器便会知道自己可以安全地发送 WebP 图片,从而极大地简化了内容协商过程。如需了解详情,请访问以下链接。
现代化
Modernizr 是一个 JavaScript 库,用于轻松检测网络浏览器中的 HTML5 和 CSS3 功能支持。查找 Modernizr.webp、Modernizr.webp.lossless、Modernizr.webp.alpha 和 Modernizr.webp.animation 属性。
HTML5 <picture>
元素
HTML5 支持 <picture>
元素,可让您按优先级顺序列出多个替代图片目标,以便客户端请求可以正确显示的第一张候选图片。请参阅 HTML5 Rocks 相关讨论。更多浏览器始终支持 <picture>
元素。
在您自己的 JavaScript 中
另一种检测方法是尝试解码使用特定功能的超小 WebP 图片,然后检查是否成功。例如:
// check_webp_feature:
// 'feature' can be one of 'lossy', 'lossless', 'alpha' or 'animation'.
// 'callback(feature, result)' will be passed back the detection result (in an asynchronous way!)
function check_webp_feature(feature, callback) {
var kTestImages = {
lossy: "UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA",
lossless: "UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==",
alpha: "UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",
animation: "UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"
};
var img = new Image();
img.onload = function () {
var result = (img.width > 0) && (img.height > 0);
callback(feature, result);
};
img.onerror = function () {
callback(feature, false);
};
img.src = "data:image/webp;base64," + kTestImages[feature];
}
请注意,图像加载是非阻塞和异步的。这意味着,最好将任何依赖于 WebP 支持的代码都放在回调函数中。
Google 为何将 WebP 作为开放源代码发布?
我们深信开源模型的重要性。借助开源的 WebP,任何人都可以使用这种格式并提出改进建议。基于您的意见和建议,我们相信,随着时间的推移,WebP 作为图形格式将变得更加实用。
如何将个人图片文件转换为 WebP 格式?
您可以使用 WebP 命令行实用程序将个人图片文件转换为 WebP 格式。如需了解详情,请参阅使用 WebP。
如果要转换许多图片,您可以使用平台的 shell 来简化操作。例如,如需转换文件夹中的所有 jpeg 文件,请尝试执行以下操作:
Windows:
> for /R . %I in (*.jpg) do ( cwebp.exe %I -o %~fnI.webp )
Linux / macOS:
$ for F in *.jpg; do cwebp $F -o `basename ${F%.jpg}`.webp; done
我该如何判断 WebP 图片的质量?
目前,您可以通过将 WebP 文件转换为使用无损压缩的常用格式(如 PNG)来查看 WebP 文件,然后在任何浏览器或图片查看器中查看 PNG 文件。如需快速了解 WebP 的质量,请参阅本网站上的图库,进行并排照片比较。
如何获取源代码?
您可以在 WebP 开源项目页面的下载部分中找到转换器代码。轻量级解码器的代码和 VP8 规范位于 WebM 网站上。如需了解容器规范,请参阅 RIFF 容器页面。
WebP 图片的最大尺寸是多少?
WebP 与 VP8 的比特流兼容,宽度和高度均为 14 位。 WebP 图片的最大像素尺寸为 16383 x 16383。
WebP 格式支持哪些颜色空间?
与 VP8 比特流一样,有损 WebP 专用于 8 位 Y'CbCr 4:2:0(通常称为 YUV420)图片格式。如需了解详情,请参阅 RFC 6386 中的第 2 节“格式概览”以及 VP8 数据格式和解码指南。
无损 WebP 专用于 RGBA 格式。请参阅 WebP 无损比特流规范。
WebP 图片是否可以比源图片大?
会,通常在从有损格式转换为 WebP 无损格式时,反之亦然。这主要是由于色彩空间差异(YUV420 与 ARGB)以及两者之间的转换造成的。
下面列举了三种典型的情况:
- 如果源图像采用无损 ARGB 格式,对 YUV420 的空间降采样将引入比原始颜色更难压缩的新颜色。当源是颜色很少的 PNG 格式时,通常就会发生这种情况:如果转换为有损 WebP 格式(或者,与有损 JPEG 相似),可能会导致文件变大。
- 如果来源是有损格式,则使用无损 WebP 压缩来捕获来源的有损特性通常会使文件变大。这并非 WebP 所特有的,例如,在将 JPEG 源转换为无损 WebP 或 PNG 格式时,可能会发生这种情况。
- 如果来源是有损格式,并且您尝试将其压缩为采用较高质量设置的有损 WebP 格式。例如,尝试将质量为 80 的 JPEG 文件转换为质量为 95 的 WebP 文件,往往会生成一个较大的文件,即使两种格式都有损耗。
评估来源的质量通常是不可能的,因此如果文件始终较大,建议降低目标 WebP 质量。
另一种可能性是避免使用质量设置,而是使用
cwebp
工具中的-size
选项或等效 API 来定位给定的文件大小。例如,定位到原始文件大小的 80% 可能会更可靠。
请注意,将 JPEG 源转换为有损 WebP,或者将 PNG 源转换为无损 WebP 时,不会出现这种文件大小意外情况。
WebP 是否支持逐行显示或交错显示?
WebP 不提供 JPEG 或 PNG 意义上的渐进式或隔行解码刷新。这可能会给解码客户端的 CPU 和内存带来过多的压力,因为每个刷新事件都涉及通过解压缩系统的整个过程。
平均而言,对渐进式 JPEG 图片进行解码相当于对基准进行 3 次解码。
或者,WebP 提供增量解码,它会使用比特流的所有可用传入字节来尝试尽快生成可显示的样本行。这样可以节省内存、CPU 和客户端上的重新绘制工作,同时提供有关下载状态的视觉提示。增量解码功能可通过 Advanced Decoding API 获得。
如何在 Android 项目中使用 libwebp Java 绑定?
WebP 支持 JNI 绑定到 swig/
目录中的简单编码器和解码器接口。
在 Eclipse 中构建库:
- 请确保随 NDK 工具一起安装 ADT 插件,并正确设置了 NDK 路径(Preferences > Android > NDK)。
- 创建一个新项目:File > New > Project > Android Application Project。
- 克隆 libwebp 或将 libwebp 解压缩到新项目中名为
jni
的文件夹中。 - 将
swig/libwebp_java_wrap.c
添加到LOCAL_SRC_FILES
列表中。 - 右键点击新项目,然后依次选择 Android Tools > Add Native Support ...,将该库添加到您的 build 中。
打开项目属性,然后依次转到 C/C++ Build > Behaviour。将
ENABLE_SHARED=1
添加到Build (Incremental build)
部分可将 libwebp 构建为共享库。注意:设置
NDK_TOOLCHAIN_VERSION=4.8
通常会提高 32 位构建性能。将
swig/libwebp.jar
添加到libs/
项目文件夹中。构建您的项目。这将创建
libs/<target-arch>/libwebp.so
。使用
System.loadLibrary("webp")
在运行时加载库。
请注意,您可以使用 ndk-build
和随附的 Android.mk
手动构建该库。在这种情况下,可以重复使用上文所述的一些步骤。
如何在 C# 中使用 libwebp?
WebP 可构建为可导出 libwebp API 的 DLL。然后,可以在 C# 中导入这些函数。
构建 libwebp.dll。这将正确设置 WEBP_EXTERN,以导出 API 函数。
libwebp> nmake /f Makefile.vc CFG=release-dynamic
将 libwebp.dll 添加到您的项目中并导入所需的函数。 请注意,如果您使用的是简单 API,则应调用
WebPFree()
以释放返回的所有缓冲区。[DllImport("libwebp.dll", CallingConvention = CallingConvention.Cdecl)] static extern int WebPEncodeBGRA(IntPtr rgba, int width, int height, int stride, float quality_factor, out IntPtr output); [DllImport("libwebp.dll", CallingConvention = CallingConvention.Cdecl)] static extern int WebPFree(IntPtr p); void Encode() { Bitmap source = new Bitmap("input.png"); BitmapData data = source.LockBits( new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); IntPtr webp_data; const int size = WebPEncodeBGRA(data.Scan0, source.Width, source.Height, data.Stride, 80, out webp_data); // ... WebPFree(webp_data); }
为什么应使用动画 WebP?
与动画 GIF 相比,动画 WebP 的优势
WebP 支持具有 8 位 Alpha 通道的 24 位 RGB 颜色(与 GIF 的 8 位颜色和 1 位 Alpha 通道相比)。
WebP 同时支持有损压缩和无损压缩;事实上,单个动画可以结合有损帧和无损帧。GIF 仅支持无损压缩。WebP 的有损压缩技术非常适合根据真实视频创建的动画图片,真实视频是越来越受欢迎的动画图片来源。
WebP 需要的字节数少于 GIF1。转换为有损 WebP 的 GIF 动画要小 64%,而无损 WebP 的大小要小 19%。这在移动网络上尤为重要。
WebP 在有跳转功能的情况下解码所需时间更短。在 Blink 中,滚动或更改标签页可能会隐藏和显示图片,导致动画暂停,然后跳到其他时间点。如果 CPU 使用率过高,会导致动画丢帧,则解码器还需要在动画中快进。在这些情况下,动画 WebP 占用的总解码时间2是 GIF 的 0.57 倍,从而减少了滚动期间的卡顿,并加快了从 CPU 利用率峰值中恢复的速度。这取决于 WebP 相对于 GIF 的两个优势:
WebP 图片会存储有关每个帧是否包含 Alpha 的元数据,因此无需对帧进行解码。 这样可以更准确地推断给定帧依赖于哪些先前的帧,从而减少对先前帧的不必要解码。
与新型视频编码器非常相似,WebP 编码器会以启发法的方式定期添加关键帧(大多数 GIF 编码器不会这样做)。这样可以显著改善长动画的跳转效果。为了在不明显增加图片大小的情况下插入此类帧,除了 GIF 使用的帧处理方法之外,WebP 还为每个帧添加了“混合方法”标志。这样一来,关键帧在绘制时,就像整张图片被清除为背景颜色一样,而不会将前一帧强制设置为完整尺寸。
与动画 GIF 相比,动画 WebP 的缺点
在没有跳转的情况下,WebP 的直线解码比 GIF 对 CPU 占用率更高。有损 WebP 的解码时间是 GIF 的 2.2 倍,而无损 WebP 的解码时间是 GIF 的 1.5 倍。
WebP 支持不如 GIF 支持那么广泛,GIF 支持实际上是通用的。
为浏览器添加 WebP 支持会增加代码占用空间和攻击面。在 Blink 中,这大约是另外 1500 行代码(包括 WebP 多路分配器库和 Blink 端 WebP 图片解码器)。请注意,如果 WebP 和 WebM 共享更常见的解码代码,或者 WebP 的功能被纳入 WebM,此问题在未来可能会减少。
为什么不在 <img>
中直接支持 WebM?
从长期来看,在 <img>
标记内支持视频格式可能是合理的。不过,现在这样做会导致 <img>
中的 WebM 可以填充动画 WebP 的提议角色,从而出现问题:
解码依赖于之前的帧的帧时,WebM 需要的内存比动画形式的 WebP 多 50%,以保持最少数量的先前帧3。
视频编解码器和容器支持因浏览器和设备而异。为了方便自动内容转码(例如,为节省带宽的代理),浏览器需要添加 Accept 标头,用于指明其图片代码支持哪些格式。即使这样也可能是不够的,因为“video/webm”或“video/mpeg”等 MIME 类型仍不指明支持编解码器(例如 VP8 和 VP9)。另一方面,WebP 格式实际上会被冻结,如果提供此格式的供应商同意提供动画 WebP,则 WebP 在所有 UA 中的行为应该是一致的;而且由于“image/webp”Accept 标头已用于指示 WebP 支持,因此无需更改新的接受标头。
Chromium 视频堆栈针对流畅播放进行了优化,并假设一次只播放一个或两个视频。因此,该实现会积极占用系统资源(线程、内存等),以最大限度地提高播放质量。这种实现方式并不能很好地扩展到多个同时播放的视频,并且需要进行重新设计,以适合包含大量图片的网页。
WebM 目前并未包含 WebP 的所有压缩技术。因此,与替代方案相比,此图片使用 WebP 时的压缩效果明显更好:
1 对于动画 GIF 和动画 WebP 之间的所有比较,我们使用了从网络中随机获取的大约 7000 张动画 GIF 图片的语料库。这些图片是使用“gif2webp”工具并使用默认设置(自 2013 年 10 月 8 日起基于最新的 libwebp 源代码树构建的)转换为动画 WebP 格式。比较数字是这些图片的平均值。
2 截至 2013 年 10 月 8 日,通过基准工具使用最新的 libwebp + ToT Blink 计算解码时间。“使用跳转时解码时间”的计算方式为:“解码前五个帧,清除帧缓冲区缓存,解码接下来的五个帧,依此类推”。
3 WebM 在内存中保留 4 个 YUV 参考帧,每个帧存储(宽度 + 96)*(高度 + 96)像素。对于 YUV 4:2:0,我们需要每 6 个像素 4 字节(或每像素 3/2 字节)。因此,这些参考帧使用 4*3/2*(width+96)*(height+96)
个字节的内存。另一方面,WebP 则只需要上一帧(采用 RGBA)可用,即 4*width*height
个字节的内存。
4 必须使用 Google Chrome 32 或更高版本才能呈现 WebP 动画