简介
WebP 是一种图片格式,它使用 (i) VP8 关键帧编码以有损方式压缩图片数据,或 (ii) WebP 无损编码。这些编码方案应该比 JPEG、GIF 和 PNG 等旧格式更高效。它针对通过网络快速传输图片进行了优化(例如,针对网站)。WebP 格式与其他格式在功能(色彩配置文件、元数据、动画等)方面也具有同等性。本文档介绍了 WebP 文件的结构。
除了 WebP 的基本用例(即包含编码为 VP8 关键帧的单个图片的文件)之外,WebP 容器(即 WebP 的 RIFF 容器)还支持其他功能。WebP 容器对以下内容提供了额外支持:
无损压缩:可以使用 WebP 无损格式对图片进行无损压缩。
元数据:图片的元数据可能存储为可交换图片文件格式 (Exif) 或可扩展元数据平台 (XMP) 格式。
透明度:图片可以具有透明度,即 alpha 通道。
颜色配置文件:图片可能具有如国际色彩联盟所述的嵌入式 ICC 配置文件。
动画:图片可能包含多个帧,帧之间有停顿,因此属于动画。
命名
建议在引用 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 开始
- 存储值偏移的无符号整数字段,例如,此类字段会将值 25 存储为 24。
- ChunkHeader('ABCD')
- 用于描述各个分块的 FourCC 和 Chunk Size 标头,其中“ABCD”是分块的 FourCC。该元素的大小为 8 个字节。
-1
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 标头开头。标头中的文件大小是后续数据块的总大小加上“WEBP”FourCC 的 4
字节。文件不应在文件大小指定的数据后面包含任何数据。读取器可以解析此类文件,并忽略尾随数据。由于任何分块的大小都是偶数,因此 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 数据:数据块大小(字节)
- VP8 比特流数据。
请注意,“VP8 ” FourCC 中的第四个字符是 ASCII 空格 (0x20)。
VP8 数据格式和解码指南中介绍了 VP8 比特流格式规范。请注意,VP8 帧标头包含 VP8 帧的宽度和高度。它假定为画布的宽度和高度。
VP8 规范介绍了如何将图片解码为 Y'CbCr 格式。如需转换为 RGB,应使用 Recommendation 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 数据:数据块大小(字节)
- 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
。读者必须忽略此字段。 - 画布宽度减 1:24 位
- 从 1 开始的画布宽度(以像素为单位)。实际画布宽度为
1 + Canvas Width Minus One
。 - 画布高度减 1: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] 字节顺序表示。此颜色可用于填充框架周围画布上未使用的空间,以及第一帧的透明像素。当 Dispose 方法为
1
时,系统也会使用背景颜色。
注意:
即使未设置“VP8X”块中的 Alpha 标志,背景颜色也可以包含非不透明的 Alpha 值。
观看器应用应将背景颜色值视为提示,但无需使用该值。
系统会在每次循环开始时清除画布。可以使用背景颜色来实现此目的。
- 循环计数:16 位 (uint16)
- 循环播放动画的次数。如果为
0
,则表示无限。
如果“VP8X”分块中设置了动画标志,则必须显示此分块。如果未设置 Animation 标志且存在此分块,则必须忽略此分块。
“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
。 - 帧宽度减 1: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 X、Frame Y、帧宽度和帧高度定义的矩形。它可能或不可能覆盖整个画布。
Alpha 混合:
假设 R、G、B 和 A 通道均为 8 位,并且 RGB 通道未乘以 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)。(请注意,由于伽玛值约为 2.2,因此 sRGB 也需要线性化。)
注意:“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
:predictor = clip(A + B - C)
其中 clip(v)
等于:
- 如果 v < 0,则为 0;
- 255(如果 v > 255),或
- v otherwise
最终值的推导过程如下:将解压缩值 X
添加到预测器,然后使用模 256 算术将 [256..511] 范围封装到 [0..255] 范围中:
alpha = (predictor + X) % 256
最左和最上的像素位置有特殊情况。例如,位置 (0, 0) 处的左上角值使用 0 作为预测器值。否则:
- 对于水平滤波或梯度滤波方法,系统会使用上方位置 (0, y-1) 预测位置 (0, y) 的左侧像素。
- 对于垂直或梯度滤除方法,系统会使用左侧位置 (x-1, 0) 来预测位置 (x, 0) 的顶部像素。
- 压缩方法 (C):2 位
使用的压缩方法:
0
:不压缩。1
:使用 WebP 无损格式压缩。
- Alpha 比特流:数据块大小(字节)-
1
编码的 Alpha 比特流。
此可选数据块包含此帧的已编码 Alpha 数据。包含“VP8L”分块的帧不应包含此分块。
原因:透明度信息已包含在“VP8L”分块中。
阿尔法通道数据会存储为未压缩的原始数据(当压缩方法为“0”时),或使用无损格式进行压缩(当压缩方法为“1”时)。
原始数据:由长度 = 宽度 * 高度的字节序列组成,其中包含按扫描顺序排列的所有 8 位透明度值。
无损格式压缩:字节序列是隐式尺寸(宽 x 高)的压缩图片流(如“WebP 无损比特流格式”中所述)。也就是说,此图片流不包含任何描述图片尺寸的标头。
原因:这些维度已从其他来源获得,因此再次存储它们是多余的,而且容易出错。
将图片串流解码为 Alpha、红色、绿色、蓝色 (ARGB) 颜色值后,必须按照无损格式规范中所述的过程,从 ARGB 四元组的绿色通道中提取透明度信息。
说明:与其他渠道不同,绿色通道可以在规范中为其留出额外的转换步骤,以便提升压缩率。
比特流 (VP8/VP8L)
此分块包含单个帧的压缩比特流数据。
比特流分块可以是 (i) 使用“VP8”(请注意重要的第四个字符空格)作为其 FourCC 的“VP8”分块,或 (ii) 使用“VP8L”作为其 FourCC 的“VP8L”分块。
“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 :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- 色彩配置文件:数据块大小(字节)
- ICC 配置文件。
此分块必须显示在图片数据之前。
此类分块应不超过 1 个。如果有更多此类分块,读者可以忽略除第一个之外的所有分块。如需了解详情,请参阅 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 元数据:分块大小(字节)
- 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 元数据:分块大小(字节)
- XMP 格式的图片元数据。
请注意,“XMP”FourCC 中的第四个字符是 ASCII 空格 (0x20)。
如需有关处理元数据的更多指导,请参阅元数据工作组的“处理元数据指南”。
未知数据块
如果 RIFF 块(RIFF 文件格式部分中所述)的 FourCC 与本文档中所述的任何块不同,则被视为未知块。
原因:允许未知分块有助于未来扩展格式,还允许存储任何特定于应用的数据。
文件可以包含未知分块:
- 在文件末尾(如扩展的 WebP 文件标头部分所述),或
- 在“ANMF”分块的末尾,如动画部分所述。
读者应忽略这些分块。写入者应按原始顺序保留这些分块(除非他们特别打算修改这些分块)。
从帧组装画布
下面简要介绍了在动画图片的情况下,读取器必须如何组装画布。
该过程首先使用“VP8X”分块中给出的尺寸(宽 Canvas Width Minus One + 1
像素,高 Canvas Height Minus
One + 1
像素)创建画布。“ANIM”块中的 Loop Count
字段用于控制动画过程的重复次数。如果 Loop Count
值不为零,则为 Loop Count - 1
;如果 Loop Count
为零,则为无穷大。
在每次循环迭代的开头,系统都会使用“ANIM”分块中的背景颜色或应用定义的颜色填充画布。
“ANMF”分块包含按显示顺序给出的各个帧。在渲染每个帧之前,系统都会应用上一帧的 Disposal method
。
已解码帧的渲染从笛卡尔坐标 (2 *
Frame X
, 2 * Frame Y
) 开始,并将画布的左上角用作原点。使用 Blending method
将宽度为 Frame Width Minus One + 1
像素、高度为 Frame Height Minus One + 1
像素的矩形渲染到画布上。
画布会显示 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)