mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-26 05:38:22 +01:00
88f41ec6ec
Change-Id: I7eaa7be48213642e3eceaaac95ad00952e085330
690 lines
25 KiB
Plaintext
690 lines
25 KiB
Plaintext
<!--
|
|
|
|
Although you may be viewing an alternate representation, this document
|
|
is sourced in Markdown, a light-duty markup scheme, and is optimized for
|
|
the [kramdown](http://kramdown.rubyforge.org/) transformer.
|
|
|
|
See the accompanying README. External link targets are referenced at the
|
|
end of this file.
|
|
|
|
-->
|
|
|
|
|
|
WebP Container Specification
|
|
============================
|
|
|
|
_Working Draft, v0.3, 20120523_
|
|
|
|
|
|
* TOC placeholder
|
|
{:toc}
|
|
|
|
|
|
Introduction
|
|
------------
|
|
|
|
WebP is a still image format that uses the VP8 key frame encoding, and
|
|
possibly other encodings in the future, to compress image data in a
|
|
lossy way. The VP8 encoding should make it more efficient than currently
|
|
used formats. It is optimized for fast image transfer over the network
|
|
(e.g., for websites). However, it also aims for feature parity
|
|
(color profile, XMP metadata, animation, etc.) with other formats. This
|
|
document describes the structure of a WebP file.
|
|
|
|
The first version of WebP handled only the basic use case: a file
|
|
containing a single image (being one VP8 key frame), with no metadata.
|
|
The use of a RIFF container permits additional feature support. This
|
|
document describes additional support for:
|
|
|
|
* **Metadata and color profiles.** We specify chunks that can contain
|
|
this information, as other popular formats do.
|
|
|
|
* **Tiling.** A single VP8 frame has an inherent limitation for width
|
|
or height of 2^14 pixels, and a 512kB limit on the size of the first
|
|
compressed partition. To support larger images, we support images
|
|
that are composed of multiple tiles, each encoded as a separate VP8
|
|
frame. All tiles form logically a single image: they have common
|
|
metadata, color profile, etc. Tiling may also improve efficiency for
|
|
larger images, e.g., grass can be encoded differently than sky.
|
|
|
|
* **Animation.** An image may have pauses between frames, making it
|
|
an animation.
|
|
|
|
* **Transparency.** An image may have transparency, i.e., an alpha channel for
|
|
each frame/tile.
|
|
|
|
Files not using these new features are backward compatible with the
|
|
original format. Use of these features will produce files that are not
|
|
compatible with older programs.
|
|
|
|
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
|
|
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
|
|
document are to be interpreted as described in [RFC 2119][].
|
|
|
|
|
|
Terminology & Basics
|
|
------------------------
|
|
|
|
A WebP file contains either a still image (i.e., an encoded matrix of
|
|
pixels) or an animation (see below), with possibly a color profile,
|
|
metadata, etc. In case we need to refer only to the matrix of pixels,
|
|
we will call it the _canvas_ of the image.
|
|
|
|
The canvas of an image is built from one or multiple tiles. Each tile
|
|
is a separately encoded VP8 key frame (other encodings are possible in
|
|
the future). Building an image from several tiles allows us to overcome
|
|
the size limitations of a single VP8 frame. Tiles are an internal detail
|
|
of the file: they are not supposed to be exposed to the user.
|
|
|
|
Below are additional terms used throughout this document:
|
|
|
|
Code that reads WebP files is referred to as a _reader_, while
|
|
code that writes them is referred to as a _writer_.
|
|
|
|
_uint16_
|
|
|
|
: A 16-bit, little-endian, unsigned integer.
|
|
|
|
_uint32_
|
|
|
|
: A 32-bit, little-endian, unsigned integer.
|
|
|
|
The basic element of a RIFF file is a _chunk_. It consists of:
|
|
|
|
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 bits
|
|
|
|
: ASCII four character code or _chunk tag_ used for chunk identification.
|
|
|
|
Chunk Size: 32 bits (_uint32_)
|
|
|
|
: The size of the chunk (_ckSize_) not including this field, the chunk
|
|
identifier and padding.
|
|
|
|
Chunk Payload: _Chunk Size_ bytes
|
|
|
|
: The data payload. If _Chunk Size_ is odd a single padding byte that
|
|
SHOULD be `0` is added.
|
|
|
|
_ChunkHeader('ABCD')_
|
|
|
|
: This is used to describe the fourcc and size header of individual
|
|
chunks, where 'ABCD' is the fourcc for the chunk. This element's
|
|
size is 8 bytes.
|
|
|
|
: Note that, in this specification, all chunk tag characters are in
|
|
file order, not in byte order of a uint32 of any particular
|
|
architecture.
|
|
|
|
_list of chunks_
|
|
|
|
: A concatenation of multiple chunks.
|
|
|
|
: We will refer to the first chunk as having _position_ 0, the second
|
|
as position 1, etc. By _chunk with index 0 among "ABCD"_ we mean
|
|
the first chunk among the chunks of type "ABCD" in the list, the
|
|
_chunk with index 1 among "ABCD"_ is the second such chunk, etc.
|
|
|
|
A WebP file MUST begin with a single chunk with a tag 'RIFF'. All
|
|
other defined chunks are contained within this chunk. The file SHOULD
|
|
NOT contain anything after it.
|
|
|
|
The maximum size of RIFF's _ckSize_ is 2^32 minus 10 bytes. The size
|
|
of the whole file is at most 4GiB minus 2 bytes.
|
|
|
|
**Note:** some RIFF libraries are said to have bugs when handling files
|
|
larger than 1GiB or 2GiB. If you are using an existing library, check
|
|
that it handles large files correctly.
|
|
|
|
The first four bytes of the RIFF chunk contents (i.e., bytes 8-11 of the file)
|
|
MUST be the ASCII string "WEBP". They are followed by a list of chunks. As the
|
|
size of any chunk is even, the size of the RIFF chunk is also even. The
|
|
contents of the chunks in that list will be described in the following sections.
|
|
|
|
**Note:** RIFF has a convention that all-uppercase chunks are standard
|
|
chunks that apply to any RIFF file format, while chunks specific to a
|
|
file format are all lowercase. WebP does not follow this convention.
|
|
|
|
|
|
WebP file header
|
|
----------------
|
|
|
|
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 bits
|
|
|
|
: The ASCII characters 'R' 'I' 'F' 'F'.
|
|
|
|
File Size: 32 bits (_uint32_)
|
|
|
|
: The size of the file in bytes starting at offset 8.
|
|
|
|
'WEBP': 32 bits
|
|
|
|
: The ASCII characters 'W' 'E' 'B' 'P'.
|
|
|
|
Simple file format
|
|
------------------
|
|
Simple WebP file header:
|
|
|
|
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('VP8 ') |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
| VP8 data |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
VP8 data: _Chunk Size_ bytes
|
|
|
|
: VP8 bitstream data.
|
|
|
|
The content of a 'VP8 ' chunk (note the last character is a space) MUST be one
|
|
VP8 key frame (with optional padding).
|
|
|
|
The current [VP8 Data Format and Decoding Guide][vp8spec] can be found
|
|
at the IETF website, <http://www.ietf.org/>.
|
|
|
|
The VP8 specification describes how to decode the image into Y'CbCr
|
|
format. To convert to RGB, Rec. 601 SHOULD be used.
|
|
|
|
This layout SHOULD be used if the image does not require advanced
|
|
features: color profiles, XMP metadata, animation or tiling. Files with
|
|
this layout are smaller and supported by older software.
|
|
|
|
Extended file format
|
|
--------------------
|
|
|
|
**Note:** Older readers may not support files using the extended format.
|
|
|
|
An extended format file consists of:
|
|
|
|
* A 'VP8X' chunk with information about features used in the file.
|
|
|
|
* An optional 'ICCP' chunk with color profile.
|
|
|
|
* An optional 'LOOP' chunk with animation control data.
|
|
|
|
* Data for all the frames.
|
|
|
|
* An optional 'META' chunk with XMP metadata.
|
|
|
|
* Some other chunk types may be defined by future specifications and
|
|
placed anywhere in the file.
|
|
|
|
As will be described in the 'VP8X' chunk description, by checking a
|
|
flag one can distinguish animated and non-animated images. A
|
|
non-animated image has exactly one frame. An animated one may have
|
|
multiple frames. Data for each frame consists of:
|
|
|
|
* An optional 'FRM ' (fourth character is a significant space) chunk
|
|
with animation frame metadata. It MUST be present in animated
|
|
images at the beginning of data for that frame. It MUST NOT be
|
|
present in non-animated images.
|
|
|
|
* An optional 'TILE' chunk with tile position metadata. It MUST be
|
|
present at the beginning of data for an image that's represented as
|
|
multiple tile images.
|
|
|
|
* An optional 'ALPH' chunk with alpha bitstream of the tile. It MUST be
|
|
present for an image containing transparency. It MUST NOT be present
|
|
in non-transparent images.
|
|
|
|
* A 'VP8 ' chunk with the bitstream of the tile.
|
|
|
|
All chunks SHOULD be placed in the same order as listed above (except
|
|
for unknown chunks, which MAY appear anywhere). If a chunk appears
|
|
in the wrong place, the file is invalid, but readers MAY parse the
|
|
file, ignoring the chunks that come too late.
|
|
|
|
**Rationale:** Setting the order of chunks should allow quicker file
|
|
parsing. For example, if an ICCP chunk does not appear in its required
|
|
position, a decoder can choose to stop searching for it. The rule of
|
|
ignoring late chunks should make programs that need to do a full search
|
|
give the same results as the ones stopping early.
|
|
|
|
Extended WebP file header:
|
|
|
|
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 |L|M|I|A|T| Reserved |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
| Canvas Width |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
| Canvas Height |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
Tiling (T): 1 bit
|
|
|
|
: Set if the image is represented by tiles.
|
|
|
|
Animation (A): 1 bit
|
|
|
|
: Set if the file is an animation. Data in 'LOOP' and 'FRM ' chunks
|
|
should be used to control the animation.
|
|
|
|
ICC profile (I): 1 bit
|
|
|
|
: Set if the file contains an 'ICCP' chunk.
|
|
|
|
Metadata (M): 1 bit
|
|
|
|
: Set if the file contains a 'META' chunk.
|
|
|
|
Alpha (L): 1 bit
|
|
|
|
: Set if the file contains images with transparency information ("alpha").
|
|
|
|
Reserved (Rsv): 3 bits
|
|
|
|
: SHOULD be `0`.
|
|
|
|
Reserved: 24 bits
|
|
|
|
: SHOULD be `0`.
|
|
|
|
Canvas Width: 32 bits
|
|
|
|
: Width of the canvas in pixels.
|
|
|
|
Canvas Height: 32 bits
|
|
|
|
: Height of the canvas in pixels.
|
|
|
|
Future specifications MAY add more fields. If a chunk of larger size is found,
|
|
programs MUST ignore the extra bytes but SHOULD preserve them when modifying
|
|
the file.
|
|
|
|
### Chunks
|
|
|
|
#### Animation
|
|
|
|
Loop Chunk:
|
|
|
|
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('LOOP') |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
| Loop Count |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
Loop Count: 16 bits (_uint16_)
|
|
|
|
: The number of times to loop the animation. `0` means infinitely.
|
|
|
|
For images that are animations, this chunk contains the global
|
|
parameters of the animation.
|
|
|
|
This chunk MUST appear if the _Animation_ flag in chunk VP8X is set.
|
|
If the _Animation_ flag is not set and this chunk is present, it
|
|
SHOULD be ignored.
|
|
|
|
Per-frame parameters of the animation:
|
|
|
|
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('FRM ') |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
| Frame X |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
| Frame Y |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
| Frame Width |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
| Frame Height |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
| Frame Duration |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
Frame X: 32 bits (_uint32_)
|
|
|
|
: The X coordinate of the upper left corner of the frame.
|
|
|
|
Frame Y: 32 bits (_uint32_)
|
|
|
|
: The Y coordinate of the upper left corner of the frame.
|
|
|
|
Frame Width: 32 bits (_uint32_)
|
|
|
|
: The width of the frame.
|
|
|
|
Frame Height: 32 bits (_uint32_)
|
|
|
|
: The height of the frame.
|
|
|
|
Frame Duration: 16 bits (_uint16_)
|
|
|
|
: Time to wait before displaying the next tile, in 1 millisecond units.
|
|
|
|
Notes for frames containing VP8 data:
|
|
|
|
* _Frame X_ and _Frame Y_ values MUST be divisible by `32`.
|
|
|
|
**Rationale:** This ensures that pixels on U and V planes are aligned to a
|
|
16-byte boundary (even after a rotation), which may help with vector
|
|
instructions on some architectures. This also makes the tiles align to
|
|
16-pixel macroblock boundaries.
|
|
|
|
* _Frame Width_ MUST be divisible by `16` or
|
|
`Frame X + Frame Width == Canvas Width` MUST be true.
|
|
|
|
* _Frame Height_ MUST be divisible by `16` or
|
|
`Frame Y + Frame Height == Canvas Height` MUST be true.
|
|
|
|
**Rationale:** The width and height constraints simplify the handling of
|
|
macroblocks that are on the edge of a tile. VP8 decoders can overwrite
|
|
pixels outside the boundary in such a macroblock, and this guarantees they
|
|
won't overwrite any data.
|
|
|
|
#### Tiling
|
|
|
|
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('TILE') |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
| Tile Canvas X |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
| Tile Canvas Y |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
Tile Canvas X: 32 bits (_uint32_)
|
|
|
|
: X coordinate of the upper left corner of the tile.
|
|
|
|
Tile Canvas Y: 32 bits (_uint32_)
|
|
|
|
: Y coordinate of the upper left corner of the tile.
|
|
|
|
This chunk contains information about a single tile and describes the
|
|
(optional) alpha chunk and bitstream chunk that follows it.
|
|
|
|
Notes for tiles containing VP8 data:
|
|
|
|
* _Tile Canvas X_ and _Tile Canvas Y_ values MUST be
|
|
divisible by `32`.
|
|
|
|
* The _Tile Width_ and _Tile Height_ can be extracted from the VP8 data.
|
|
See 'Section 9' in the [VP8 RFC][vp8spec].
|
|
|
|
* The width of a tile MUST be divisible by `16` or
|
|
`Tile Canvas X + Tile Width == Canvas Width` MUST be true.
|
|
|
|
* The height of a tile MUST be divisible by `16` or
|
|
`Tile Canvas Y + Tile Height == Canvas Height` MUST be true.
|
|
|
|
|
|
#### 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... |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
Compression method (C): 2 bits
|
|
|
|
: The compression method used:
|
|
|
|
* `0`: No compression.
|
|
* `1`: Backward reference counts encoded with arithmetic encoder.
|
|
|
|
Filtering method (F): 2 bits
|
|
|
|
: The filtering method used:
|
|
|
|
* `0`: None.
|
|
* `1`: Horizontal filter.
|
|
* `2`: Vertical filter.
|
|
* `3`: Gradient filter.
|
|
|
|
Pre-processing (P): 2 bits
|
|
|
|
: These INFORMATIVE bits are used to signal the pre-processing that has
|
|
been performed during compression. The decoder can use this information to
|
|
e.g. dither the values or smooth the gradients prior to display.
|
|
|
|
* `0`: no pre-processing
|
|
* `1`: level reduction
|
|
|
|
Decoders are not required to use this information in any specified way.
|
|
|
|
Reserved (Rsv): 2 bits
|
|
|
|
: SHOULD be `0`.
|
|
|
|
Alpha bitstream: _Chunk Size_ - `1` bytes
|
|
|
|
: Encoded alpha bitstream.
|
|
|
|
This optional chunk contains encoded alpha data for a single tile.
|
|
Either **ALL or NONE** of the tiles must contain this chunk.
|
|
|
|
The alpha channel data is losslessly stored as raw data (when
|
|
compression method is '0') or compressed using the lossless format
|
|
(when the compression method is '1').
|
|
|
|
* raw data: consists of a byte sequence of length width * height,
|
|
containing all the 8bit transparency values in scan order.
|
|
|
|
* lossless format compression: the byte sequence is a compressed
|
|
image-stream (as described in the specification for lossless format)
|
|
of implicit dimension width x height. Note that this image-stream byte
|
|
sequence does NOT contain any headers describing the image dimension.
|
|
|
|
**Rationale**: the dimension is already known from other sources,
|
|
so storing it again would be redundant and error-prone.
|
|
|
|
Once the image-stream is decoded into ARGB color values, following
|
|
the process described in the lossless format specification, the
|
|
transparency information must be extracted from the *green* channel
|
|
of the ARGB quadruplet.
|
|
|
|
**Rationale**: the green channel is allowed extra transformation
|
|
steps in the specification -unlike the other channels- that can
|
|
improve compression.
|
|
|
|
#### Color profile
|
|
|
|
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') |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
| Compression | Color Profile |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
Compression: 8 bits
|
|
|
|
: Compression method used:
|
|
|
|
* `0`: None.
|
|
* `1`: Deflate/inflate.
|
|
|
|
Color Profile: _Chunk Size_ - `1` bytes
|
|
|
|
: ICC profile.
|
|
|
|
There SHOULD be at most one 'ICCP' chunk.
|
|
See <http://www.color.org> for specifications.
|
|
|
|
If this chunk is not present, sRGB SHOULD be assumed.
|
|
|
|
#### Metadata
|
|
|
|
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('META') |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
| Compression | XMP Metadata |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
Compression: 8 bits
|
|
|
|
: Compression method used:
|
|
|
|
* `0`: None.
|
|
* `1`: Deflate/inflate.
|
|
|
|
XMP Metadata: _Chunk Size_ - `1` bytes
|
|
|
|
: XMP metadata.
|
|
|
|
There SHOULD be at most one such chunk. If there are more such chunks, readers
|
|
MAY ignore all except the first one.
|
|
|
|
XMP packets are XML text as specified in the [XMP Specification Part
|
|
1][xmpspec]. The chunk tag is different from the one specified by Adobe
|
|
for WAV and AVI (also RIFF formats), because we have the option of
|
|
compression.
|
|
|
|
Additional guidance about handling metadata can be found in the
|
|
Metadata Working Group's [Guidelines for Handling Metadata][metadata].
|
|
Note that the sections of the document about reconciliation of EXIF,
|
|
XMP and IPTC-IIM don't apply to WebP. As WebP supports only XMP, no
|
|
reconciliation is necessary.
|
|
|
|
#### Other Chunks
|
|
|
|
A file MAY contain other chunks. Readers SHOULD be ignore these chunks. Writers
|
|
SHOULD preserve them in their original order.
|
|
|
|
### Assembling the Canvas from Tiles and Animation
|
|
|
|
Here we provide an overview of how 'TILE' chunks and 'FRM '/'LOOP' chunks are
|
|
used to assemble the canvas. The notation _VP8X.field_ means the field in
|
|
the 'VP8X' chunk with the same description.
|
|
|
|
Decoding a non-animated canvas MUST be equivalent to the following
|
|
pseudocode:
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
assert not VP8X.flags.haveAnimation
|
|
canvas ← new black image of size
|
|
VP8X.canvasWidth x VP8X.canvasHeight.
|
|
tile_params.tileCanvasX = tile_params.tileCanvasY = 0
|
|
for chunk in data_for_all_frames:
|
|
if chunk.tag == "TILE":
|
|
assert No other TILE chunk after the last "VP8 " chunk
|
|
assert No ALPH chunk after the last "VP8 " chunk
|
|
tile_params = chunk
|
|
if chunk.tag == "ALPH":
|
|
assert No other ALPH chunk after the last "VP8 " chunk
|
|
tile_params.alpha = alpha_data
|
|
if chunk.tag == "VP8 ":
|
|
render image in chunk in canvas with top-left corner in
|
|
(tile_params.tileCanvasX, tile_params.tileCanvasY).
|
|
tile_params.tileCanvasX = tile_params.tileCanvasY = 0
|
|
Ignore unknown chunks
|
|
canvas contains the decoded canvas.
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Decoding an animated canvas MUST be equivalent to the following
|
|
pseudocode:
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
assert VP8X.flags.haveAnimation
|
|
canvas ← new black image of size
|
|
VP8X.canvasWidth x VP8X.canvasHeight.
|
|
if LOOP.loopCount==0:
|
|
LOOP.loopCount=∞
|
|
current_FRM ← nil
|
|
for LOOP.loop = 0, ..., LOOP.loopCount-1
|
|
assert First chunk in data_for_all_frames is a FRM
|
|
for chunk in data_for_all_frames:
|
|
if chunk.tag == "FRM ":
|
|
assert No other FRM chunk after the last "VP8 " chunk
|
|
assert No ALPH chunk after the last "VP8 " chunk
|
|
if current_FRM != nil:
|
|
Show the contents of canvas for
|
|
current_FRM.frameDuration * 1ms.
|
|
current_FRM = chunk
|
|
if chunk.tag == "ALPH":
|
|
assert No other ALPH chunk after the last "VP8 " chunk
|
|
tile_params.alpha = alpha_data
|
|
if chunk.tag == "VP8 ":
|
|
assert tile_params.tileCanvasX >= current_FRM.frameX
|
|
assert tile_params.tileCanvasY >= current_FRM.frameY
|
|
assert tile_params.tileCanvasX + chunk.tileWidth >=
|
|
current_FRM.frameX + current_FRM.frameWidth
|
|
assert tile_params.tileCanvasY + chunk.tileHeight >=
|
|
current_FRM.frameX + current_FRM.frameHeight
|
|
render image in chunk in canvas with top-left corner in
|
|
(tile_params.tileCanvasX, tile_params.tileCanvasY).
|
|
tile_params.tileCanvasX = tile_params.tileCanvasY = 0
|
|
Ignore unknown chunks
|
|
canvas contains the decoded canvas.
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
As described earlier, if an assert related to chunk ordering fails, the reader
|
|
MAY ignore the badly-ordered chunks instead of failing to decode the file.
|
|
|
|
Example file layouts
|
|
--------------------
|
|
|
|
A non-animated, tiled image without transparency may look as follows:
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
RIFF/WEBP
|
|
+- VP8X (descriptions of features used)
|
|
+- ICCP (color profile)
|
|
+- TILE (First tile parameters)
|
|
+- VP8 (bitstream - first tile)
|
|
+- TILE (Second tile parameters)
|
|
+- VP8 (bitstream - second tile)
|
|
+- TILE (third tile parameters)
|
|
+- VP8 (bitstream - third tile)
|
|
+- TILE (fourth tile parameters)
|
|
+- VP8 (bitstream - fourth tile)
|
|
+- META (XMP metadata)
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
An animated image with transparency may look as follows:
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
RIFF/WEBP
|
|
+- VP8X (descriptions of features used)
|
|
+- LOOP (animation control parameters)
|
|
+- FRM (first animation frame parameters)
|
|
+- ALPH (alpha bitstream - first image frame)
|
|
+- VP8 (bitstream - first image frame)
|
|
+- FRM (second animation frame parameters)
|
|
+- ALPH (alpha bitstream - second image frame)
|
|
+- VP8 (bitstream - second image frame)
|
|
+- META (XMP metadata)
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
[vp8spec]: http://tools.ietf.org/html/rfc6386
|
|
[xmpspec]: http://www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart1.pdf
|
|
[metadata]: http://www.metadataworkinggroup.org/pdf/mwg_guidance.pdf
|
|
[rfc 2119]: http://tools.ietf.org/html/rfc2119
|