638528cd1e
now, we only use 2 bits for the filtering method, and 2 bits for the compression method. There's two additional bits which are INFORMATIVE, to specify whether the source has been pre-processed (level reduction) during compression. This can be used at decompression time for some post-processing (see DequantizeLevels()). New relevant spec excerpt: 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'). Change-Id: Ied8f5fb922707a953e6a2b601c69c73e552dda6b
666 lines
24 KiB
Plaintext
666 lines
24 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.2, 20120207_
|
|
|
|
|
|
* 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') |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
| Rsrv |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.
|
|
|
|
Reserved (Rsrv): 4 bits
|
|
|
|
: SHOULD be `0`.
|
|
|
|
Reserved: 16 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').
|
|
|
|
#### 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
|