常见问题解答

什么是 WebP?为什么要使用它?

WebP 是一种有损和无损压缩方法,可用于网络上各种各样的照片、透明图片和图形图片。有损压缩程度可调,因此用户可以选择文件大小与图片质量之间的权衡。与 JPEG 和 JPEG 2000 相比,WebP 通常可实现平均 30% 的压缩率,且不会损失图片质量(请参阅比较研究)。

WebP 格式旨在创建体积更小、外观更精美的图片,从而有助于提高网络访问速度。

哪些网络浏览器原生支持 WebP?

希望提升网站性能的站长可以轻松为其当前图片创建优化的 WebP 替代图片,并有针对性地向支持 WebP 的浏览器提供这些图片。

  • WebP 有损支持
    • Google Chrome(桌面版)17 及更高版本
    • Android 版 Google Chrome 25 及更高版本
    • Microsoft Edge 18 及更高版本
    • Firefox 65 及更高版本
    • Opera 11.10+
    • 原生 Web 浏览器,Android 4.0 及更高版本 (ICS)
    • Safari 14 及更高版本 (iOS 14 及更高版本、macOS Big Sur 及更高版本)
  • 支持有损、无损和 Alpha WebP
    • Google Chrome(桌面版)23 及更高版本
    • Android 版 Google Chrome 25 及更高版本
    • Microsoft Edge 18 及更高版本
    • Firefox 65 及更高版本
    • Opera 12.10+
    • 原生网络浏览器,Android 4.2 及更高版本 (JB-MR1)
    • Pale Moon 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 格式,Web 服务器就知道它可以安全地发送 WebP 图片,从而大大简化内容协商。如需了解详情,请参阅以下链接。

Modernizr

Modernizr 是一个 JavaScript 库,可用于方便地检测 Web 浏览器对 HTML5 和 CSS3 功能的支持情况。查找属性 Modernizr.webpModernizr.webp.losslessModernizr.webp.alphaModernizr.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),然后在任何浏览器或图片查看器中查看 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(VP8 数据格式和解码指南)的第 2 部分“格式概览”。

无损 WebP 仅支持 RGBA 格式。请参阅 WebP 无损位流规范

为什么我的无损 WebP 文件与原始文件不同?

简单编码 API 函数(WebPEncodeLosslessRGB()WebPEncodeLosslessBGR()WebPEncodeLosslessRGBA()WebPEncodeLosslessBGRA())使用库的默认设置。对于无损压缩,这意味着“精确”处于停用状态。完全透明区域(即 Alpha 值等于 0 的区域)中的 RGB 值将被修改,以提高压缩率。为避免这种情况,请使用 WebPEncode() 并将 WebPConfig::exact 设置为 1。请参阅高级编码 API 文档。

WebP 图片的大小是否会超过其源图片?

是的,通常是在从有损格式转换为 WebP 无损格式或反之亦然时。这主要是由于色彩空间差异(YUV420 与 ARGB)以及两者之间的转换所致。

有三种典型情况:

  1. 如果源图像采用无损 ARGB 格式,则空间降采样到 YUV420 会引入比原始颜色更难压缩的新颜色。这种情况通常发生在源文件为颜色较少的 PNG 格式时:转换为有损 WebP(或类似的有损 JPEG)可能会导致文件大小变大。
  2. 如果来源采用有损格式,使用无损 WebP 压缩来捕获来源的有损性质通常会导致文件变大。这并非 WebP 特有的问题,例如,在将 JPEG 源转换为无损 WebP 或 PNG 格式时,也可能会出现此问题。
  3. 如果来源采用有损格式,而您尝试将其压缩为质量设置更高的有损 WebP。例如,尝试将以质量 80 保存的 JPEG 文件转换为质量为 95 的 WebP 文件通常会导致文件变大,即使这两种格式都是有损的。评估来源的质量通常是不可能的,因此建议在文件大小始终较大时降低目标 WebP 质量。另一种方法是避免使用质量设置,而是使用 cwebp 工具中的 -size 选项或等效的 API 来指定目标文件大小。例如,将目标文件大小设为原始文件大小的 80% 可能更稳健。

请注意,将 JPEG 源转换为有损 WebP 或将 PNG 源转换为无损 WebP 不太容易出现此类文件大小意外情况。

WebP 是否支持渐进式或隔行扫描显示?

WebP 不提供 JPEG 或 PNG 意义上的渐进式或交错式解码刷新。由于每次刷新事件都涉及对解压缩系统的完整遍历,因此这可能会给解码客户端的 CPU 和内存带来过大的压力。

平均而言,解码渐进式 JPEG 图片相当于解码 baseline 图片 3 次。

或者,WebP 提供增量解码,即使用比特流的所有可用传入字节,尽快尝试生成可显示的样本行。这样既可以节省客户端的内存、CPU 和重绘工作,又可以提供有关下载状态的视觉提示。增量解码功能可通过 Advanced Decoding API 使用。

如何在 Android 项目中使用 libwebp Java 绑定?

WebP 支持 JNI 绑定到 swig/ 目录中的简单编码器和解码器接口。

Eclipse 中构建库:

  1. 确保您已安装 ADT 插件以及 NDK 工具,并且 NDK 路径已正确设置(Preferences > Android > NDK)。
  2. 创建新项目:File > New > Project > Android Application Project
  3. 将 libwebp 克隆或解压缩到新项目中名为 jni 的文件夹。
  4. swig/libwebp_java_wrap.c 添加到 LOCAL_SRC_FILES 列表。
  5. 右键点击新项目,然后依次选择 Android Tools > Add Native Support ...,以将该库纳入您的 build 中。
  6. 打开项目属性,然后依次前往 C/C++ Build > Behaviour。将 ENABLE_SHARED=1 添加到 Build (Incremental build) 部分,以将 libwebp 构建为共享库。

    注意:设置 NDK_TOOLCHAIN_VERSION=4.8 通常会提高 32 位 build 的性能。

  7. swig/libwebp.jar 添加到 libs/ 项目文件夹。

  8. 构建项目。这会创建 libs/<target-arch>/libwebp.so

  9. 使用 System.loadLibrary("webp") 在运行时加载库。

请注意,可以使用 ndk-build 和随附的 Android.mk 手动构建库。在这种情况下,您可以重复使用上述部分步骤。

如何将 libwebp 与 C# 搭配使用?

WebP 可以构建为导出 libwebp API 的 DLL。然后,可以在 C# 中导入这些函数。

  1. 构建 libwebp.dll。这会将 WEBP_EXTERN 正确设置为导出 API 函数。

    libwebp> nmake /f Makefile.vc CFG=release-dynamic
    
  2. 将 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 动画的优势

  1. WebP 支持 24 位 RGB 颜色和 8 位 Alpha 通道,而 GIF 仅支持 8 位颜色和 1 位 Alpha 通道。

  2. WebP 同时支持有损压缩和无损压缩;事实上,单个动画可以同时包含有损帧和无损帧。GIF 仅支持无损压缩。WebP 的有损压缩技术非常适合从真实视频创建的动画图片,而这正是越来越受欢迎的动画图片来源。

  3. WebP 所需的字节数比 GIF 少1。 转换为有损 WebP 的 GIF 动画缩小了 64%,而转换为无损 WebP 的 GIF 动画缩小了 19%。这在移动网络上尤为重要。

  4. 在存在搜索的情况下,WebP 的解码时间更短。在 Blink 中,滚动或更改标签页可能会隐藏和显示图片,导致动画暂停,然后跳到其他时间点。如果 CPU 使用率过高导致动画丢帧,也可能需要解码器在动画中向前搜索。在这些场景中,动画 WebP 的总解码时间2是 GIF 的 0.57 倍,因此在滚动时卡顿更少,并且能更快地从 CPU 利用率高峰中恢复。这是因为 WebP 相较于 GIF 有两个优势:

    • WebP 图像会存储有关每个帧是否包含 Alpha 的元数据,从而无需解码帧即可做出此判断。 这样可以更准确地推断出给定帧所依赖的先前帧,从而减少对先前帧的不必要解码。

    • 与现代视频编码器非常相似,WebP 编码器会以启发式方式定期添加关键帧(大多数 GIF 编码器不会这样做)。这可大幅改进长动画中的搜索体验。为了便于插入此类帧而不显著增加图片大小,WebP 除了 GIF 使用的帧处置方法之外,还为每个帧添加了“混合方法”标志。这样一来,关键帧就可以像整个图片已清除为背景颜色一样进行绘制,而无需强制前一帧为全尺寸。

与 GIF 动画相比,WebP 动画的缺点

  1. 在不进行搜索的情况下,WebP 的直线解码比 GIF 更消耗 CPU 资源。有损 WebP 的解码时间是 GIF 的 2.2 倍,而无损 WebP 的解码时间是 GIF 的 1.5 倍。

  2. WebP 支持的普及程度远不及 GIF 支持,后者几乎是通用的。

  3. 向浏览器添加 WebP 支持会增加代码占用空间和攻击面。在 Blink 中,这大约需要 1500 行额外的代码(包括 WebP 解复用库和 Blink 端 WebP 图片解码器)。请注意,如果 WebP 和 WebM 共享更多通用解码代码,或者 WebP 的功能被纳入 WebM 的功能中,未来可能会减少此问题。

为什么不直接在 <img> 中支持 WebM?

从长远来看,支持 <img> 标记内的视频格式可能是有意义的。不过,现在这样做,目的是让 <img> 中的 WebM 能够发挥动画 WebP 的拟议作用,这存在问题:

  1. 在解码依赖于之前帧的帧时,WebM 需要比动画 WebP 多 50% 的内存来保存最少数量的之前帧3

  2. 浏览器和设备对视频编解码器和容器的支持情况各不相同。为了方便自动内容转码(例如,用于节省带宽的代理),浏览器需要添加 accept 标头,以指明其图像标记支持的格式。即使这样可能也不够,因为“video/webm”或“video/mpeg”等 MIME 类型仍然无法指示编解码器支持情况(例如 VP8 与 VP9)。另一方面,WebP 格式实际上已冻结,如果提供商同意发布动画 WebP,那么所有用户代理中的 WebP 行为都应保持一致;由于“image/webp”接受标头已用于指示 WebP 支持,因此无需进行新的接受标头更改。

  3. Chromium 视频堆栈经过优化,可实现流畅播放,并假定一次只播放一个或两个视频。因此,该实现会积极消耗系统资源(线程、内存等),以最大限度地提高播放质量。此类实现无法很好地扩展到许多同步视频,需要重新设计才能适合用于包含大量图片的网页。

  4. WebM 目前并未纳入 WebP 的所有压缩技术。因此,与替代格式相比,此图片使用 WebP 压缩的效果要好得多:


1 在所有 GIF 动画与 WebP 动画的比较中,我们使用了从网络上随机获取的约 7, 000 张 GIF 动画图片语料库。这些图片使用“gif2webp”工具以默认设置(根据截至 2013 年 10 月 8 日的最新 libwebp 源代码树构建)转换为 WebP 动画。比较数字是这些图片的平均值。

2 解码时间是使用截至 2013 年 10 月 8 日的最新版 libwebp + ToT Blink 通过基准化分析工具计算得出的。“解码时间(含搜索)”的计算方式为“解码前 5 帧,清除帧缓冲区缓存,解码接下来的 5 帧,依此类推”。

3 WebM 会在内存中保留 4 个 YUV 参考帧,每个帧存储 (width+96)*(height+96) 个像素。对于 YUV 4:2:0,我们需要每 6 个像素 4 个字节(或每个像素 3/2 个字节)。因此,这些参考帧会使用 4*3/2*(width+96)*(height+96) 字节的内存。另一方面,WebP 只需要提供前一帧(采用 RGBA 格式),即 4*width*height 字节的内存。

4 动画 WebP 渲染需要 Google Chrome 版本 32 及更高版本