WebP 容器规范

简介

WebP 是一种图片格式,它使用 (i) VP8 关键帧编码, 以有损方式压缩图像数据或 (ii) WebP 无损编码。这些 应能比 JPEG 等旧格式更加高效。 GIF 和 PNG。它针对通过网络快速传输图像进行了优化( (例如,用于网站)。WebP 格式具有同等功能 元数据、动画等)以及其他格式。本文档介绍了 WebP 文件的结构。

WebP 容器(即 WebP 的 RIFF 容器)支持功能 基本用例(即包含 编码为 VP8 关键帧的图片)。WebP 容器提供 对以下各项的支持:

  • 无损压缩:可以使用 WebP 无损格式。

  • 元数据:图片中可能有存储于可交换图片文件中的元数据 格式 (Exif) 或可扩展元数据平台 (XMP) 格式。

  • 透明度:图片可以具有透明度,即 Alpha 通道。

  • 颜色配置文件:图片可能具有如所述的嵌入式 ICC 配置文件 由国际颜色联盟 (International Color Consortium) 提供。

  • 动画:一张图片可能包含多个帧,帧之间会暂停播放; 使其成为动画

命名

建议在引用 WebP 时使用以下类型 容器:

容器格式名称WebP
文件扩展名.webp
MIME 类型image/webp
统一类型标识符org.webmproject.webp

术语和基本信息

关键字“必须”“不得”“必需”“会”“不会”“应” “不应该”“推荐”“不推荐”“可以”和“可选”在此 文档将按照 BCP 14 RFC 2119 RFC 8174 中的描述进行解释 以及所有字母均以大写形式显示的时间和时间,如此处所示。

WebP 文件包含静态图片(即经过编码的像素矩阵) 或动画。您还可以选择包含透明度 颜色配置文件和元数据。我们将像素矩阵称为 图片的画布

分块图中的位编号从 0 开始作为最高有效位 (“MSB 0”)(如 RFC 1166 中所述)。

以下是本文档中使用的其他术语:

读取者/写入者
读取 WebP 文件的代码称为读取器,而读取 WebP 文件的代码则称为读取器 写入它们称为写入器。
uint16
一个 16 位,小端字节序,无符号整数。
uint24
一个 24 位,小端字节序,无符号整数。
uint32
一个 32 位、小端字节序、无符号整数。
FourCC
由四个字符组成的代码 (FourCC) 是将四个字符串联起来创建的 uint32 采用小端字节序的 ASCII 字符。这表示“aaaa”(0x61616161) 和 “AAAA”(0x41414141) 会被视为不同的 FourCCs
1 起
一个无符号整数字段,用于存储按 -1 偏移的值,例如 字段会将值 25 存储为 24
ChunkHeader('ABCD')
用于描述各个分块的 FourCCChunk Size 标头, 这里的“ABCD”是数据块的 FourCC。该元素的大小为 8 个字节。

RIFF 文件格式

WebP 文件格式基于 RIFF(资源交换文件格式) 文档格式。

RIFF 文件的基本元素是块。其中包括:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                         Chunk FourCC                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                          Chunk Size                           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
:                         Chunk Payload                         :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Chunk FourCC:32 位
用于分块识别的四个字符的 ASCII 码。
分块大小:32 位 (uint32)
数据块的大小(以字节为单位,不包括此字段),即数据块的大小 标识符或内边距。
分块载荷:Chunk Size 字节
数据载荷。如果分块大小为奇数,则为单个填充字节 - 必须 为 0 以符合 RIFF 的要求。

注意:RIFF 有一个惯例,即全大写的分块 FourCC 是标准数据块 适用于所有 RIFF 文件格式的块,而特定于文件的 FourCC 格式全部为小写字母。WebP 并不遵循此惯例。

WebP 文件标头

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|      'R'      |      'I'      |      'F'      |      'F'      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                           File Size                           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|      'W'      |      'E'      |      'B'      |      'P'      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
“RIFF”:32 位
ASCII 字符“R”、“I”、“F”、“F”。
文件大小:32 位 (uint32)
文件的大小(以字节为单位),从偏移量 8 开始。该值的最大值 此字段为 2^32 减去 10 个字节,因此整个文件的大小为 最多 4 GiB 减去 2 个字节。
“WEBP”:32 位
ASCII 字符“W”、“E”、“B”、“P”。

WebP 文件必须以 FourCC“WEBP”的 RIFF 标头开头。文件大小 是后续数据块的总大小加上 4 个字节, “WEBP”FourCC。该文件不应在数据之后包含任何数据 File Size 指定的大小。读者可以解析此类文件,并忽略末尾 数据。由于任何块的大小都是偶数,因此 RIFF 标头给出的大小 均匀。下面介绍了各个分块的内容 部分。

简单文件格式(有损)

如果图片需要进行有损编码,并且不采用 需要扩展格式提供的透明度或其他高级功能。 采用这种布局的文件比较小,并且受旧版软件支持。

简单的 WebP(有损)文件格式:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
|                    WebP file header (12 bytes)                |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
:                        'VP8 ' Chunk                           :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

“VP8 ”文本块:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      ChunkHeader('VP8 ')                      |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
:                           VP8 data                            :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
VP8 数据:Chunk Size 字节
VP8 比特流数据。

请注意,“VP8 ”中的FourCC 是一个 ASCII 空间 (0x20)。

VP8 数据格式和 解码指南。请注意,VP8 帧头包含 VP8 帧 宽度和高度。它假定为画布的宽度和高度。

VP8 规范介绍了如何将图片解码为 Y'CbCr 格式。接收者 转换为 RGB,应使用建议 BT.601。应用可以 使用其他转换方法,但不同解码器的视觉效果可能会有所不同。

简单文件格式(无损)

注意:成人读者可能不支持采用无损格式的文件。

如果图像需要无损编码(采用 可选的透明度渠道)且不需要提供的高级功能 扩展格式。

简单的 WebP(无损)文件格式:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
|                    WebP file header (12 bytes)                |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
:                         'VP8L' Chunk                          :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

“VP8L”文本块:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      ChunkHeader('VP8L')                      |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
:                           VP8L data                           :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
VP8L 数据:Chunk Size 字节数
VP8L 比特流数据。

有关 VP8L 比特流的当前规范,请参阅 WebP 无损比特流格式。请注意,VP8L 标头 包含 VP8L 图片宽度和高度。这里假设宽度为 画布的高度和高度

扩展文件格式

注意:成人读者可能不支持使用扩展格式的文件。

扩展格式文件包含以下内容:

  • “VP8X”通过有关文件中使用的特征的信息进行分块。

  • 可选的“ICCP”具有颜色配置文件的分块。

  • 可选的“ANIM”包含动画控件数据的数据块。

  • 图片数据。

  • 可选的“EXIF”使用 Exif 元数据进行分块。

  • 一个可选的“XMP”使用 XMP 元数据进行分块。

  • 未知分块的可选列表。

对于静态图片图片数据由单个帧组成, 最多:

对于动画图片图片数据包含多个帧。更多 您可以在动画部分中找到有关帧的详细信息。

重构和色彩校正所需的所有分块,即“VP8X”, “ICCP”“ANIM”“ANMF”“ALPH”“VP8”和“VP8L” 。当重建所需的数据块时,读取器应失败 和色彩校正功能的顺序错误。

元数据未知数据块可能会出现在 订单。

说明:重建所需的数据块应在 以便读者在接收所有图片之前 数据。更改元数据和 自定义数据块。

扩展的 WebP 文件标头:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
|                   WebP file header (12 bytes)                 |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      ChunkHeader('VP8X')                      |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Rsv|I|L|E|X|A|R|                   Reserved                    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          Canvas Width Minus One               |             ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
...  Canvas Height Minus One    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
预留 (Rsv):2 位
必须为 0。读者必须忽略此字段。
ICC 配置文件 (I):1 位
在文件包含“ICCP”时设置文本块。
Alpha (L):1 位
设置图片中是否有任何帧包含透明度信息 (“alpha”)。
Exif 元数据 (E):1 位
设置文件是否包含 Exif 元数据。
XMP 元数据 (X):1 位
在文件包含 XMP 元数据时设置。
动画 (A):1 位
设置该图片是否为动画图片。“ANIM”中的数据和“ANMF”数据块应 用于控制动画。
预留 (R):1 位
必须为 0。读者必须忽略此字段。
预留:24 位
必须为 0。读者必须忽略此字段。
画布宽度减一:24 位
画布宽度,从 1 开始,以像素为单位。 实际画布宽度为 1 + Canvas Width Minus One
画布高度减一:24 位
画布高度,从 1 开始,以像素为单位。 实际画布高度为 1 + Canvas Height Minus One

画布宽度画布高度的乘积不得超过 2^32 - 1

未来的规范可能会添加更多字段。必须忽略未知字段。

动画

动画由“ANIM”控制和“ANMF”块。

“ANIM”文本块:

对于动画图片,此数据块包含 动画。

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      ChunkHeader('ANIM')                      |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                       Background Color                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          Loop Count           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
背景颜色:32 位 (uint32)
画布的默认背景颜色,以 [蓝色、绿色、红色、Alpha] 表示 字节顺序。此颜色可用于填充画布上未使用的空间 以及第一帧的透明像素。 当处理方法为 1 时,也会使用背景颜色。

注意

  • 背景颜色可以包含非不透明 Alpha 值,即使 “VP8X”中的 Alpha 标志未设置分块

  • 查看器应用应将背景颜色值视为提示, 并非必须使用它

  • 系统会在每个循环开始时清空画布。背景颜色可以是 来实现此目标的方法。

循环计数:16 位 (uint16)
循环播放动画的次数。如果值为 0,则表示 无限可能。

如果“VP8X”中有动画标志,则必须显示此分块文本块已设置。 如果未设置动画标记,且此分块存在,则必须为 已忽略。

“ANMF”文本块:

对于动画图片,此数据块包含有关单个帧的信息。 如果未设置动画标志,则不应存在此分块。

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      ChunkHeader('ANMF')                      |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        Frame X                |             ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
...          Frame Y            |   Frame Width Minus One     ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
...             |           Frame Height Minus One              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                 Frame Duration                |  Reserved |B|D|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
:                         Frame Data                            :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
帧 X:24 位 (uint24)
帧左上角的 X 坐标为 Frame X * 2
帧 Y:24 位 (uint24)
帧左上角的 Y 坐标为 Frame Y * 2
帧宽度减一:24 位 (uint24)
帧的宽度(从 1 开始)。 帧宽度为 1 + Frame Width Minus One
帧高度减 1:24 位 (uint24)
帧的高度(从 1 开始)。 帧高度为 1 + Frame Height Minus One
帧时长:24 位 (uint24)
在显示下一帧之前等待的时间,以 1 毫秒为单位。 请注意,帧持续时间为 0(通常小于或等于 10)的解释为 由实现定义的变量许多工具和浏览器都会指定 时长与 GIF 相似。
预留:6 位
必须为 0。读者必须忽略此字段。
混合方法 (B):1 位

指示当前帧的透明像素如何混合 替换为上一个画布的对应像素:

  • 0:使用 alpha 混合。在处置上一帧之后, 使用 alpha 混合处理画布的当前帧(见下文)。如果 当前帧没有 alpha 通道,则假设 alpha 值为 255,相当于替换了矩形。

  • 1:不混合。在处置上一帧之后, 来覆盖画布上的当前帧 帧。

处理方法 (D):1 位

指示在播放完当前帧后应如何处理该帧。 在画布上显示(渲染下一帧之前):

  • 0:请勿处置。保持画布不变。

  • 1:处理为背景颜色。在画布上填充矩形当前框架覆盖,且其背景色为 “ANIM”分块

注意

  • 框架处理仅适用于框架矩形,即 由 Frame XFrame Yframe widthframe 高度。可能会覆盖整个画布,也可能不会。

  • Alpha 混合:

    假设 R、G、B 和 A 通道都是 8 位, 通道不预乘 alpha,后者是混合公式 “dst”输入“src”:

    blend.A = src.A + dst.A * (1 - src.A / 255)
    if blend.A = 0 then
      blend.RGB = 0
    else
      blend.RGB =
          (src.RGB * src.A +
           dst.RGB * dst.A * (1 - src.A / 255)) / blend.A
    
  • 应该在线性颜色空间中完成 Alpha 混合,同时要考虑到 图片的颜色配置文件。如果颜色配置文件 不存在,则假定为标准 RGB (sRGB)。(请注意,sRGB 也 需要进行线性化处理,因为 gamma 约为 2.2。)

帧数据:分块大小 - 16 个字节

包含:

注意:“ANMF”即有效负载,即帧数据 填充的数据块,如 RIFF 文件格式中所述。

Alpha 版

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      ChunkHeader('ALPH')                      |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Rsv| P | F | C |     Alpha Bitstream...                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
预留 (Rsv):2 位
必须为 0。读者必须忽略此字段。
预处理 (P):2 位

这些信息性位用于指示 执行了某项操作解码器可以使用这些信息 例如,在显示之前,对值进行抖动或平滑处理。

  • 0:不进行预处理。
  • 1:降低级别。

解码器并非必须要以任何指定方式使用这些信息。

过滤方法 (F):2 位

所使用的过滤方法如下所述:

  • 0:无。
  • 1:横向滤镜。
  • 2:纵向过滤条件。
  • 3:渐变过滤器。

对于每个像素,使用以下计算执行过滤。 假设当前 X 位置周围的 Alpha 值标记为:

 C | B |
---+---+
 A | X |

我们尝试计算位置 X 处的 alpha 值。首先,预测结果是 具体取决于过滤方法:

  • 方法 0:预测器 = 0
  • 方法 1:预测器 = A
  • 方法 2:预测器 = B
  • 3 方法:预测器 = 剪辑(A + B - C)

其中,clip(v) 等于:

  • 如果 v <,则为 00、
  • 255,如果 v >255 或
  • 否则为 v

最终值是通过将解压缩后的值 X 添加到 预测器并使用 modulo-256 算术将 [256..511] 范围括起来 [0..255] 中:

alpha = (predictor + X) % 256

最左侧和最顶部的像素位置存在特殊情况。对于 位置 (0, 0) 处的左上角值将 0 用作预测器值。 否则:

  • 对于水平或渐变过滤方法,最左侧的像素在 位置 (0, y) 是使用上面位置 (0, y-1) 预测的。
  • 对于垂直或渐变过滤方法, 位置 (x, 0) 是使用左侧位置 (x-1, 0) 预测的。
压缩方法 (C):2 位

使用的压缩方法:

  • 0:不压缩。
  • 1:使用 WebP 无损格式进行压缩。
Alpha 版比特流:分块大小 - 1 个字节

编码的 Alpha 比特流。

此可选数据块包含此帧的已编码 Alpha 数据。框架 包含“VP8L”的数据块不应包含此数据块。

说明:透明度信息已包含在“VP8L”中 文本块。

Alpha 渠道数据被存储为未压缩的原始数据(当 压缩方法为“0”)或使用无损格式进行压缩 (压缩方法为“1”)。

  • 原始数据:由长度 = 宽度 * 高度的字节序列组成, 包含扫描顺序中的所有 8 位透明度值。

  • 无损格式压缩:字节序列是经过压缩的 隐式尺寸“宽 x 高”的图片流(如“WebP 无损比特流格式”中所述)。也就是说, image-stream 不包含任何描述图片尺寸的标头。

    依据:其他来源已经知道这些维度, 因此再次存储它们是多余的,并且容易出错。

    将图片流解码为 Alpha、红、绿、蓝 (ARGB) 颜色后, 遵循无损格式中描述的过程, 透明度信息必须从 ARGB 四元组的绿色通道。

    说明:绿色通道可以进行额外转换 (与其他渠道不同), 提高压缩率

比特流 (VP8/VP8L)

此区块包含单个帧的压缩比特流数据。

比特流块可以是 (i) “VP8 ”文本块,使用“VP8”(请注意, 明显的第四字符空格)作为其 FourCC, (ii)“VP8L”文本块 使用“VP8L”作为其 FourCC。

“VP8 ”的格式和“VP8L”数据块按照各部分的说明 简单文件格式(有损)简单文件格式(无损)

颜色配置文件

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      ChunkHeader('ICCP')                      |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
:                       Color Profile                           :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
颜色配置文件:Chunk Size 字节
ICC 配置文件。

该数据块必须显示在图片数据之前。

此类分块最多只能有一个。如果有更多这样的分块,读者 可以忽略除第一个以外的所有项。 有关详情,请参阅 ICC 规范

如果该数据块不存在,应假定为 sRGB。

元数据

元数据可以存储在“EXIF”中或“XMP”块。

每种类型(“EXIF”和“XMP”)最多应有一个分块。如果有 读取器可以忽略除第一个区块以外的所有区块。

这些块的定义如下:

“EXIF”文本块:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      ChunkHeader('EXIF')                      |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
:                        Exif Metadata                          :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Exif 元数据:Chunk Size 字节
Exif 格式的图片元数据。

“XMP”文本块:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      ChunkHeader('XMP ')                      |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
:                        XMP Metadata                           :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
XMP 元数据:Chunk Size 字节
XMP 格式的图片元数据。

请注意,“XMP”中的第四个字符FourCC 是一个 ASCII 空间 (0x20)。

有关处理元数据的其他指南,请参阅 元数据工作组的“处理元数据的准则”

未知数据块

RIFF 数据块(如 RIFF 文件格式部分所述) 且其 FourCC 与本文档中描述的任何块均不同, 被视为未知数据块

说明:允许未知分块可预留用于未来的扩展 而且支持存储任何应用特定数据。

文件可以包含未知数据块:

读取器应忽略这些区块。写入者应将其保留在 原始顺序(除非他们特别打算修改这些分块)。

框架画布组装

我们在这里简要介绍读者必须在充电盒中组装画布 动画图像。

该流程从使用 “VP8X”文本块,宽 Canvas Width Minus One + 1 像素,高 Canvas Height Minus One + 1 像素。“ANIM”中的 Loop Count 字段数据块控制方式 会多次重复执行动画过程这是针对以下用户的Loop Count - 1: 非零 Loop Count 值;如果 Loop Count 为零,则为无穷大。

在每次循环迭代开始时,使用 “ANIM”的背景颜色数据块或应用定义的颜色。

“ANMF”数据块包含按显示顺序指定的各个帧。呈现之前 系统会应用上一帧的 Disposal method

以画布的左上角为原点,从笛卡尔坐标(2 * Frame X2 * Frame Y)开始渲染已解码帧。 Frame Width Minus One + 1 像素宽 x Frame Height Minus One + 1 像素 并使用 Blending method 渲染到画布上。

画布会显示 Frame Duration 毫秒。这种情况会一直持续到 由“ANMF”指定的所有帧已显示文本块。新的循环迭代 或此时画布处于最终状态(如果所有迭代均已完成) 已完成。

以下伪代码说明了呈现过程。表示法 VP8X.field 是指“VP8X”具有相同说明的分块。

VP8X.flags.hasAnimation MUST be TRUE
canvas ← new image of size VP8X.canvasWidth x VP8X.canvasHeight with
         background color ANIM.background_color or
         application-defined color.
loop_count ← ANIM.loopCount
dispose_method ← Dispose to background color
if loop_count == 0:
  loop_count = ∞
frame_params ← nil
next chunk in image_data is ANMF MUST be TRUE
for loop = 0..loop_count - 1
  clear canvas to ANIM.background_color or application-defined color
  until eof or non-ANMF chunk
    frame_params.frameX = Frame X
    frame_params.frameY = Frame Y
    frame_params.frameWidth = Frame Width Minus One + 1
    frame_params.frameHeight = Frame Height Minus One + 1
    frame_params.frameDuration = Frame Duration
    frame_right = frame_params.frameX + frame_params.frameWidth
    frame_bottom = frame_params.frameY + frame_params.frameHeight
    VP8X.canvasWidth >= frame_right MUST be TRUE
    VP8X.canvasHeight >= frame_bottom MUST be TRUE
    for subchunk in 'Frame Data':
      if subchunk.tag == "ALPH":
        alpha subchunks not found in 'Frame Data' earlier MUST be
          TRUE
        frame_params.alpha = alpha_data
      else if subchunk.tag == "VP8 " OR subchunk.tag == "VP8L":
        bitstream subchunks not found in 'Frame Data' earlier MUST
          be TRUE
        frame_params.bitstream = bitstream_data
    apply dispose_method.
    render frame with frame_params.alpha and frame_params.bitstream
      on canvas with top-left corner at (frame_params.frameX,
      frame_params.frameY), using Blending method
      frame_params.blendingMethod.
    canvas contains the decoded image.
    Show the contents of the canvas for
    frame_params.frameDuration * 1 ms.
    dispose_method = frame_params.disposeMethod

文件布局示例

采用 alpha 通道的有损编码图片可能如下所示:

RIFF/WEBP
+- VP8X (descriptions of features used)
+- ALPH (alpha bitstream)
+- VP8 (bitstream)

无损编码图片可能如下所示:

RIFF/WEBP
+- VP8X (descriptions of features used)
+- VP8L (lossless bitstream)
+- XYZW (unknown chunk)

具有 ICC 配置文件和 XMP 元数据的无损图像 如下所示:

RIFF/WEBP
+- VP8X (descriptions of features used)
+- ICCP (color profile)
+- VP8L (lossless bitstream)
+- XMP  (metadata)

带有 Exif 元数据的动画图片可能如下所示:

RIFF/WEBP
+- VP8X (descriptions of features used)
+- ANIM (global animation parameters)
+- ANMF (frame1 parameters + data)
+- ANMF (frame2 parameters + data)
+- ANMF (frame3 parameters + data)
+- ANMF (frame4 parameters + data)
+- EXIF (metadata)