|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Although you may be viewing an alternate representation, this document
|
|
Packit |
9c6abc |
is sourced in Markdown, a light-duty markup scheme, and is optimized for
|
|
Packit |
9c6abc |
the [kramdown](http://kramdown.rubyforge.org/) transformer.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
See the accompanying README. External link targets are referenced at the
|
|
Packit |
9c6abc |
end of this file.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
-->
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
WebP Container Specification
|
|
Packit |
9c6abc |
============================
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* TOC placeholder
|
|
Packit |
9c6abc |
{:toc}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Introduction
|
|
Packit |
9c6abc |
------------
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
WebP is an image format that uses either (i) the VP8 key frame encoding
|
|
Packit |
9c6abc |
to compress image data in a lossy way, or (ii) the WebP lossless encoding
|
|
Packit |
9c6abc |
(and possibly other encodings in the future). These encoding schemes should
|
|
Packit |
9c6abc |
make it more efficient than currently used formats. It is optimized for fast
|
|
Packit |
9c6abc |
image transfer over the network (e.g., for websites). The WebP format has
|
|
Packit |
9c6abc |
feature parity (color profile, metadata, animation etc) with other formats as
|
|
Packit |
9c6abc |
well. This document describes the structure of a WebP file.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
The WebP container (i.e., RIFF container for WebP) allows feature support over
|
|
Packit |
9c6abc |
and above the basic use case of WebP (i.e., a file containing a single image
|
|
Packit |
9c6abc |
encoded as a VP8 key frame). The WebP container provides additional support
|
|
Packit |
9c6abc |
for:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* **Lossless compression.** An image can be losslessly compressed, using the
|
|
Packit |
9c6abc |
WebP Lossless Format.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* **Metadata.** An image may have metadata stored in EXIF or XMP formats.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* **Transparency.** An image may have transparency, i.e., an alpha channel.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* **Color Profile.** An image may have an embedded ICC profile as described
|
|
Packit |
9c6abc |
by the [International Color Consortium][iccspec].
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* **Animation.** An image may have multiple frames with pauses between them,
|
|
Packit |
9c6abc |
making it an animation.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
|
|
Packit |
9c6abc |
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
|
|
Packit |
9c6abc |
document are to be interpreted as described in [RFC 2119][].
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Bit numbering in chunk diagrams starts at `0` for the most significant bit
|
|
Packit |
9c6abc |
('MSB 0') as described in [RFC 1166][].
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
**Note:** Out of the features mentioned above, lossy compression, lossless
|
|
Packit |
9c6abc |
compression, transparency, metadata, color profile and animation are finalized
|
|
Packit |
9c6abc |
and are to be considered stable.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Terminology & Basics
|
|
Packit |
9c6abc |
------------------------
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
A WebP file contains either a still image (i.e., an encoded matrix of pixels)
|
|
Packit |
9c6abc |
or an [animation](#animation). Optionally, it can also contain transparency
|
|
Packit |
9c6abc |
information, color profile and metadata. In case we need to refer only to the
|
|
Packit |
9c6abc |
matrix of pixels, we will call it the _canvas_ of the image.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Below are additional terms used throughout this document:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
_Reader/Writer_
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: Code that reads WebP files is referred to as a _reader_, while code that
|
|
Packit |
9c6abc |
writes them is referred to as a _writer_.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
_uint16_
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: A 16-bit, little-endian, unsigned integer.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
_uint24_
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: A 24-bit, little-endian, unsigned integer.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
_uint32_
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: A 32-bit, little-endian, unsigned integer.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
_FourCC_
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: A _FourCC_ (four-character code) is a _uint32_ created by concatenating four
|
|
Packit |
9c6abc |
ASCII characters in little-endian order.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
_1-based_
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: An unsigned integer field storing values offset by `-1`. e.g., Such a field
|
|
Packit |
9c6abc |
would store value _25_ as _24_.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
RIFF File Format
|
|
Packit |
9c6abc |
----------------
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
The WebP file format is based on the RIFF (resource interchange file format)
|
|
Packit |
9c6abc |
document format.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
The basic element of a RIFF file is a _chunk_. It consists of:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
0 1 2 3
|
|
Packit |
9c6abc |
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
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| Chunk FourCC |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| Chunk Size |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| Chunk Payload |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Chunk FourCC: 32 bits
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: ASCII four-character code used for chunk identification.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Chunk Size: 32 bits (_uint32_)
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: The size of the chunk not including this field, the chunk identifier or
|
|
Packit |
9c6abc |
padding.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Chunk Payload: _Chunk Size_ bytes
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: The data payload. If _Chunk Size_ is odd, a single padding byte -- that
|
|
Packit |
9c6abc |
SHOULD be `0` -- is added.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
_ChunkHeader('ABCD')_
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: This is used to describe the _FourCC_ and _Chunk Size_ header of individual
|
|
Packit |
9c6abc |
chunks, where 'ABCD' is the FourCC for the chunk. This element's
|
|
Packit |
9c6abc |
size is 8 bytes.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
**Note:** RIFF has a convention that all-uppercase chunk FourCCs are standard
|
|
Packit |
9c6abc |
chunks that apply to any RIFF file format, while FourCCs specific to a file
|
|
Packit |
9c6abc |
format are all lowercase. WebP does not follow this convention.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
WebP File Header
|
|
Packit |
9c6abc |
----------------
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
0 1 2 3
|
|
Packit |
9c6abc |
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
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| 'R' | 'I' | 'F' | 'F' |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| File Size |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| 'W' | 'E' | 'B' | 'P' |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
'RIFF': 32 bits
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: The ASCII characters 'R' 'I' 'F' 'F'.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
File Size: 32 bits (_uint32_)
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: The size of the file in bytes starting at offset 8. The maximum value of
|
|
Packit |
9c6abc |
this field is 2^32 minus 10 bytes and thus the size of the whole file is at
|
|
Packit |
9c6abc |
most 4GiB minus 2 bytes.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
'WEBP': 32 bits
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: The ASCII characters 'W' 'E' 'B' 'P'.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
A WebP file MUST begin with a RIFF header with the FourCC 'WEBP'. The file size
|
|
Packit |
9c6abc |
in the header is the total size of the chunks that follow plus `4` bytes for
|
|
Packit |
9c6abc |
the 'WEBP' FourCC. The file SHOULD NOT contain anything after it. As the size
|
|
Packit |
9c6abc |
of any chunk is even, the size given by the RIFF header is also even. The
|
|
Packit |
9c6abc |
contents of individual chunks will be described in the following sections.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Simple File Format (Lossy)
|
|
Packit |
9c6abc |
--------------------------
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
This layout SHOULD be used if the image requires _lossy_ encoding and does not
|
|
Packit |
9c6abc |
require transparency or other advanced features provided by the extended format.
|
|
Packit |
9c6abc |
Files with this layout are smaller and supported by older software.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Simple WebP (lossy) file format:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
0 1 2 3
|
|
Packit |
9c6abc |
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
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| WebP file header (12 bytes) |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| VP8 chunk |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
VP8 chunk:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
0 1 2 3
|
|
Packit |
9c6abc |
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
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| ChunkHeader('VP8 ') |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| VP8 data |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
VP8 data: _Chunk Size_ bytes
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: VP8 bitstream data.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
The VP8 bitstream format specification can be found at [VP8 Data Format and
|
|
Packit |
9c6abc |
Decoding Guide][vp8spec]. Note that the VP8 frame header contains the VP8 frame
|
|
Packit |
9c6abc |
width and height. That is assumed to be the width and height of the canvas.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
The VP8 specification describes how to decode the image into Y'CbCr
|
|
Packit |
9c6abc |
format. To convert to RGB, Rec. 601 SHOULD be used.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Simple File Format (Lossless)
|
|
Packit |
9c6abc |
-----------------------------
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
**Note:** Older readers may not support files using the lossless format.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
This layout SHOULD be used if the image requires _lossless_ encoding (with an
|
|
Packit |
9c6abc |
optional transparency channel) and does not require advanced features provided
|
|
Packit |
9c6abc |
by the extended format.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Simple WebP (lossless) file format:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
0 1 2 3
|
|
Packit |
9c6abc |
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
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| WebP file header (12 bytes) |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| VP8L chunk |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
VP8L chunk:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
0 1 2 3
|
|
Packit |
9c6abc |
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
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| ChunkHeader('VP8L') |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| VP8L data |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
VP8L data: _Chunk Size_ bytes
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: VP8L bitstream data.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
The current specification of the VP8L bitstream can be found at
|
|
Packit |
9c6abc |
[WebP Lossless Bitstream Format][webpllspec]. Note that the VP8L header
|
|
Packit |
9c6abc |
contains the VP8L image width and height. That is assumed to be the width
|
|
Packit |
9c6abc |
and height of the canvas.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Extended File Format
|
|
Packit |
9c6abc |
--------------------
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
**Note:** Older readers may not support files using the extended format.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
An extended format file consists of:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* A 'VP8X' chunk with information about features used in the file.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* An optional 'ICCP' chunk with color profile.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* An optional 'ANIM' chunk with animation control data.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* Image data.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* An optional 'EXIF' chunk with EXIF metadata.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* An optional 'XMP ' chunk with XMP metadata.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* An optional list of [unknown chunks](#unknown-chunks). _\[status: experimental\]_
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
For a _still image_, the _image data_ consists of a single frame, which is made
|
|
Packit |
9c6abc |
up of:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* An optional [alpha subchunk](#alpha).
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* A [bitstream subchunk](#bitstream-vp8vp8l).
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
For an _animated image_, the _image data_ consists of multiple frames. More
|
|
Packit |
9c6abc |
details about frames can be found in the [Animation](#animation) section.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
All chunks SHOULD be placed in the same order as listed above. If a chunk
|
|
Packit |
9c6abc |
appears in the wrong place, the file is invalid, but readers MAY parse the
|
|
Packit |
9c6abc |
file, ignoring the chunks that come too late.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
**Rationale:** Setting the order of chunks should allow quicker file
|
|
Packit |
9c6abc |
parsing. For example, if an 'ALPH' chunk does not appear in its required
|
|
Packit |
9c6abc |
position, a decoder can choose to stop searching for it. The rule of
|
|
Packit |
9c6abc |
ignoring late chunks should make programs that need to do a full search
|
|
Packit |
9c6abc |
give the same results as the ones stopping early.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Extended WebP file header:
|
|
Packit |
9c6abc |
{:#extended_header}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
0 1 2 3
|
|
Packit |
9c6abc |
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
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| WebP file header (12 bytes) |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| ChunkHeader('VP8X') |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
|Rsv|I|L|E|X|A|R| Reserved |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| Canvas Width Minus One | ...
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
... Canvas Height Minus One |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Reserved (Rsv): 2 bits
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: SHOULD be `0`.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
ICC profile (I): 1 bit
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: Set if the file contains an ICC profile.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Alpha (L): 1 bit
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: Set if any of the frames of the image contain transparency information
|
|
Packit |
9c6abc |
("alpha").
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
EXIF metadata (E): 1 bit
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: Set if the file contains EXIF metadata.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
XMP metadata (X): 1 bit
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: Set if the file contains XMP metadata.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Animation (A): 1 bit
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: Set if this is an animated image. Data in 'ANIM' and 'ANMF' chunks should be
|
|
Packit |
9c6abc |
used to control the animation.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Reserved (R): 1 bit
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: SHOULD be `0`.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Reserved: 24 bits
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: SHOULD be `0`.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Canvas Width Minus One: 24 bits
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: _1-based_ width of the canvas in pixels.
|
|
Packit |
9c6abc |
The actual canvas width is '1 + Canvas Width Minus One'
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Canvas Height Minus One: 24 bits
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: _1-based_ height of the canvas in pixels.
|
|
Packit |
9c6abc |
The actual canvas height is '1 + Canvas Height Minus One'
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
The product of _Canvas Width_ and _Canvas Height_ MUST be at most `2^32 - 1`.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Future specifications MAY add more fields.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
### Chunks
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
#### Animation
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
An animation is controlled by ANIM and ANMF chunks.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
ANIM Chunk:
|
|
Packit |
9c6abc |
{:#anim_chunk}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
For an animated image, this chunk contains the _global parameters_ of the
|
|
Packit |
9c6abc |
animation.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
0 1 2 3
|
|
Packit |
9c6abc |
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
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| ChunkHeader('ANIM') |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| Background Color |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| Loop Count |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Background Color: 32 bits (_uint32_)
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: The default background color of the canvas in \[Blue, Green, Red, Alpha\]
|
|
Packit |
9c6abc |
byte order. This color MAY be used to fill the unused space on the canvas
|
|
Packit |
9c6abc |
around the frames, as well as the transparent pixels of the first frame.
|
|
Packit |
9c6abc |
Background color is also used when disposal method is `1`.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
**Note**:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* Background color MAY contain a transparency value (alpha), even if the
|
|
Packit |
9c6abc |
_Alpha_ flag in [VP8X chunk](#extended_header) is unset.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* Viewer applications SHOULD treat the background color value as a hint, and
|
|
Packit |
9c6abc |
are not required to use it.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* The canvas is cleared at the start of each loop. The background color MAY be
|
|
Packit |
9c6abc |
used to achieve this.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Loop Count: 16 bits (_uint16_)
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: The number of times to loop the animation. `0` means infinitely.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
This chunk MUST appear if the _Animation_ flag in the VP8X chunk is set.
|
|
Packit |
9c6abc |
If the _Animation_ flag is not set and this chunk is present, it
|
|
Packit |
9c6abc |
SHOULD be ignored.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
ANMF chunk:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
For animated images, this chunk contains information about a _single_ frame.
|
|
Packit |
9c6abc |
If the _Animation flag_ is not set, then this chunk SHOULD NOT be present.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
0 1 2 3
|
|
Packit |
9c6abc |
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
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| ChunkHeader('ANMF') |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| Frame X | ...
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
... Frame Y | Frame Width Minus One ...
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
... | Frame Height Minus One |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| Frame Duration | Reserved |B|D|
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| Frame Data |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Frame X: 24 bits (_uint24_)
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: The X coordinate of the upper left corner of the frame is `Frame X * 2`
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Frame Y: 24 bits (_uint24_)
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: The Y coordinate of the upper left corner of the frame is `Frame Y * 2`
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Frame Width Minus One: 24 bits (_uint24_)
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: The _1-based_ width of the frame.
|
|
Packit |
9c6abc |
The frame width is `1 + Frame Width Minus One`
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Frame Height Minus One: 24 bits (_uint24_)
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: The _1-based_ height of the frame.
|
|
Packit |
9c6abc |
The frame height is `1 + Frame Height Minus One`
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Frame Duration: 24 bits (_uint24_)
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: The time to wait before displaying the next frame, in 1 millisecond units.
|
|
Packit |
9c6abc |
Note the interpretation of frame duration of 0 (and often <= 10) is
|
|
Packit |
9c6abc |
implementation defined. Many tools and browsers assign a minimum duration
|
|
Packit |
9c6abc |
similar to GIF.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Reserved: 6 bits
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: SHOULD be 0.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Blending method (B): 1 bit
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: Indicates how transparent pixels of _the current frame_ are to be blended
|
|
Packit |
9c6abc |
with corresponding pixels of the previous canvas:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* `0`: Use alpha blending. After disposing of the previous frame, render the
|
|
Packit |
9c6abc |
current frame on the canvas using [alpha-blending](#alpha-blending). If
|
|
Packit |
9c6abc |
the current frame does not have an alpha channel, assume alpha value of
|
|
Packit |
9c6abc |
255, effectively replacing the rectangle.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* `1`: Do not blend. After disposing of the previous frame, render the
|
|
Packit |
9c6abc |
current frame on the canvas by overwriting the rectangle covered by the
|
|
Packit |
9c6abc |
current frame.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Disposal method (D): 1 bit
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: Indicates how _the current frame_ is to be treated after it has been
|
|
Packit |
9c6abc |
displayed (before rendering the next frame) on the canvas:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* `0`: Do not dispose. Leave the canvas as is.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* `1`: Dispose to background color. Fill the _rectangle_ on the canvas
|
|
Packit |
9c6abc |
covered by the _current frame_ with background color specified in the
|
|
Packit |
9c6abc |
[ANIM chunk](#anim_chunk).
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
**Notes**:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* The frame disposal only applies to the _frame rectangle_, that is, the
|
|
Packit |
9c6abc |
rectangle defined by _Frame X_, _Frame Y_, _frame width_ and _frame height_.
|
|
Packit |
9c6abc |
It may or may not cover the whole canvas.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
{:#alpha-blending}
|
|
Packit |
9c6abc |
* **Alpha-blending**:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Given that each of the R, G, B and A channels is 8-bit, and the RGB
|
|
Packit |
9c6abc |
channels are _not premultiplied_ by alpha, the formula for blending
|
|
Packit |
9c6abc |
'dst' onto 'src' is:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
~~~~~
|
|
Packit |
9c6abc |
blend.A = src.A + dst.A * (1 - src.A / 255)
|
|
Packit |
9c6abc |
if blend.A = 0 then
|
|
Packit |
9c6abc |
blend.RGB = 0
|
|
Packit |
9c6abc |
else
|
|
Packit |
9c6abc |
blend.RGB = (src.RGB * src.A +
|
|
Packit |
9c6abc |
dst.RGB * dst.A * (1 - src.A / 255)) / blend.A
|
|
Packit |
9c6abc |
~~~~~
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* Alpha-blending SHOULD be done in linear color space, by taking into account
|
|
Packit |
9c6abc |
the [color profile](#color-profile) of the image. If the color profile is
|
|
Packit |
9c6abc |
not present, sRGB is to be assumed. (Note that sRGB also needs to be
|
|
Packit |
9c6abc |
linearized due to a gamma of ~2.2).
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Frame Data: _Chunk Size_ - `16` bytes
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: Consists of:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* An optional [alpha subchunk](#alpha) for the frame.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* A [bitstream subchunk](#bitstream-vp8vp8l) for the frame.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* An optional list of [unknown chunks](#unknown-chunks).
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
**Note**: The 'ANMF' payload, _Frame Data_ above, consists of individual
|
|
Packit |
9c6abc |
_padded_ chunks as described by the [RIFF file format](#riff-file-format).
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
#### Alpha
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
0 1 2 3
|
|
Packit |
9c6abc |
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
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| ChunkHeader('ALPH') |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
|Rsv| P | F | C | Alpha Bitstream... |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Reserved (Rsv): 2 bits
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: SHOULD be `0`.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Pre-processing (P): 2 bits
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: These INFORMATIVE bits are used to signal the pre-processing that has
|
|
Packit |
9c6abc |
been performed during compression. The decoder can use this information to
|
|
Packit |
9c6abc |
e.g. dither the values or smooth the gradients prior to display.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* `0`: no pre-processing
|
|
Packit |
9c6abc |
* `1`: level reduction
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Filtering method (F): 2 bits
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: The filtering method used:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* `0`: None.
|
|
Packit |
9c6abc |
* `1`: Horizontal filter.
|
|
Packit |
9c6abc |
* `2`: Vertical filter.
|
|
Packit |
9c6abc |
* `3`: Gradient filter.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
For each pixel, filtering is performed using the following calculations.
|
|
Packit |
9c6abc |
Assume the alpha values surrounding the current `X` position are labeled as:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
C | B |
|
|
Packit |
9c6abc |
---+---+
|
|
Packit |
9c6abc |
A | X |
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
We seek to compute the alpha value at position `X`. First, a prediction is
|
|
Packit |
9c6abc |
made depending on the filtering method:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* Method `0`: predictor = 0
|
|
Packit |
9c6abc |
* Method `1`: predictor = A
|
|
Packit |
9c6abc |
* Method `2`: predictor = B
|
|
Packit |
9c6abc |
* Method `3`: predictor = clip(A + B - C)
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
where `clip(v)` is equal to:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* 0 if v < 0
|
|
Packit |
9c6abc |
* 255 if v > 255
|
|
Packit |
9c6abc |
* v otherwise
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
The final value is derived by adding the decompressed value `X` to the
|
|
Packit |
9c6abc |
predictor and using modulo-256 arithmetic to wrap the \[256-511\] range
|
|
Packit |
9c6abc |
into the \[0-255\] one:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
`alpha = (predictor + X) % 256`
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
There are special cases for left-most and top-most pixel positions:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* Top-left value at location (0,0) uses 0 as predictor value. Otherwise,
|
|
Packit |
9c6abc |
* For horizontal or gradient filtering methods, the left-most pixels at
|
|
Packit |
9c6abc |
location (0, y) are predicted using the location (0, y-1) just above.
|
|
Packit |
9c6abc |
* For vertical or gradient filtering methods, the top-most pixels at
|
|
Packit |
9c6abc |
location (x, 0) are predicted using the location (x-1, 0) on the left.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Decoders are not required to use this information in any specified way.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Compression method (C): 2 bits
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: The compression method used:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* `0`: No compression.
|
|
Packit |
9c6abc |
* `1`: Compressed using the WebP lossless format.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Alpha bitstream: _Chunk Size_ - `1` bytes
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: Encoded alpha bitstream.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
This optional chunk contains encoded alpha data for this frame. A frame
|
|
Packit |
9c6abc |
containing a 'VP8L' chunk SHOULD NOT contain this chunk.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
**Rationale**: The transparency information is already part of the 'VP8L'
|
|
Packit |
9c6abc |
chunk.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
The alpha channel data is stored as uncompressed raw data (when
|
|
Packit |
9c6abc |
compression method is '0') or compressed using the lossless format
|
|
Packit |
9c6abc |
(when the compression method is '1').
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* Raw data: consists of a byte sequence of length width * height,
|
|
Packit |
9c6abc |
containing all the 8-bit transparency values in scan order.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* Lossless format compression: the byte sequence is a compressed
|
|
Packit |
9c6abc |
image-stream (as described in the [WebP Lossless Bitstream Format]
|
|
Packit |
9c6abc |
[webpllspec]) of implicit dimension width x height. That is, this
|
|
Packit |
9c6abc |
image-stream does NOT contain any headers describing the image dimension.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
**Rationale**: the dimension is already known from other sources,
|
|
Packit |
9c6abc |
so storing it again would be redundant and error-prone.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Once the image-stream is decoded into ARGB color values, following
|
|
Packit |
9c6abc |
the process described in the lossless format specification, the
|
|
Packit |
9c6abc |
transparency information must be extracted from the *green* channel
|
|
Packit |
9c6abc |
of the ARGB quadruplet.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
**Rationale**: the green channel is allowed extra transformation
|
|
Packit |
9c6abc |
steps in the specification -- unlike the other channels -- that can
|
|
Packit |
9c6abc |
improve compression.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
#### Bitstream (VP8/VP8L)
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
This chunk contains compressed bitstream data for a single frame.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
A bitstream chunk may be either (i) a VP8 chunk, using "VP8 " (note the
|
|
Packit |
9c6abc |
significant fourth-character space) as its tag _or_ (ii) a VP8L chunk, using
|
|
Packit |
9c6abc |
"VP8L" as its tag.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
The formats of VP8 and VP8L chunks are as described in sections
|
|
Packit |
9c6abc |
[Simple File Format (Lossy)](#simple-file-format-lossy)
|
|
Packit |
9c6abc |
and [Simple File Format (Lossless)](#simple-file-format-lossless) respectively.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
#### Color profile
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
0 1 2 3
|
|
Packit |
9c6abc |
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
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| ChunkHeader('ICCP') |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| Color Profile |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Color Profile: _Chunk Size_ bytes
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: ICC profile.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
This chunk MUST appear before the image data.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
There SHOULD be at most one such chunk. If there are more such chunks, readers
|
|
Packit |
9c6abc |
MAY ignore all except the first one.
|
|
Packit |
9c6abc |
See the [ICC Specification][iccspec] for details.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
If this chunk is not present, sRGB SHOULD be assumed.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
#### Metadata
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Metadata can be stored in 'EXIF' or 'XMP ' chunks.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
There SHOULD be at most one chunk of each type ('EXIF' and 'XMP '). If there
|
|
Packit |
9c6abc |
are more such chunks, readers MAY ignore all except the first one. Also, a file
|
|
Packit |
9c6abc |
may possibly contain both 'EXIF' and 'XMP ' chunks.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
The chunks are defined as follows:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
EXIF chunk:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
0 1 2 3
|
|
Packit |
9c6abc |
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
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| ChunkHeader('EXIF') |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| EXIF Metadata |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
EXIF Metadata: _Chunk Size_ bytes
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: image metadata in EXIF format.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
XMP chunk:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
0 1 2 3
|
|
Packit |
9c6abc |
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
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| ChunkHeader('XMP ') |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
| XMP Metadata |
|
|
Packit |
9c6abc |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
XMP Metadata: _Chunk Size_ bytes
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
: image metadata in XMP format.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Additional guidance about handling metadata can be found in the
|
|
Packit |
9c6abc |
Metadata Working Group's [Guidelines for Handling Metadata][metadata].
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
#### Unknown Chunks _\[status: experimental\]_
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
A RIFF chunk (described in [this](#terminology-amp-basics) section) whose _chunk
|
|
Packit |
9c6abc |
tag_ is different from any of the chunks described in this document, is
|
|
Packit |
9c6abc |
considered an _unknown chunk_.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
**Rationale**: Allowing unknown chunks gives a provision for future extension
|
|
Packit |
9c6abc |
of the format, and also allows storage of any application-specific data.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
A file MAY contain unknown chunks:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
* At the end of the file as described in [Extended WebP file
|
|
Packit |
9c6abc |
header](#extended_header) section.
|
|
Packit |
9c6abc |
* At the end of ANMF chunks as described in the
|
|
Packit |
9c6abc |
[Animation](#animation) section.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Readers SHOULD ignore these chunks. Writers SHOULD preserve them in their
|
|
Packit |
9c6abc |
original order (unless they specifically intend to modify these chunks).
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
### Assembling the Canvas from frames
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Here we provide an overview of how a reader should assemble a canvas in the
|
|
Packit |
9c6abc |
case of an animated image. The notation _VP8X.field_ means the field in the
|
|
Packit |
9c6abc |
'VP8X' chunk with the same description.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Displaying an _animated image_ canvas MUST be equivalent to the following
|
|
Packit |
9c6abc |
pseudocode:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
Packit |
9c6abc |
assert VP8X.flags.hasAnimation
|
|
Packit |
9c6abc |
canvas ← new image of size VP8X.canvasWidth x VP8X.canvasHeight with
|
|
Packit |
9c6abc |
background color ANIM.background_color.
|
|
Packit |
9c6abc |
loop_count ← ANIM.loopCount
|
|
Packit |
9c6abc |
dispose_method ← ANIM.disposeMethod
|
|
Packit |
9c6abc |
if loop_count == 0:
|
|
Packit |
9c6abc |
loop_count = ∞
|
|
Packit |
9c6abc |
frame_params ← nil
|
|
Packit |
9c6abc |
assert next chunk in image_data is ANMF
|
|
Packit |
9c6abc |
for loop = 0..loop_count - 1
|
|
Packit |
9c6abc |
clear canvas to ANIM.background_color or application defined color
|
|
Packit |
9c6abc |
until eof or non-ANMF chunk
|
|
Packit |
9c6abc |
frame_params.frameX = Frame X
|
|
Packit |
9c6abc |
frame_params.frameY = Frame Y
|
|
Packit |
9c6abc |
frame_params.frameWidth = Frame Width Minus One + 1
|
|
Packit |
9c6abc |
frame_params.frameHeight = Frame Height Minus One + 1
|
|
Packit |
9c6abc |
frame_params.frameDuration = Frame Duration
|
|
Packit |
9c6abc |
frame_right = frame_params.frameX + frame_params.frameWidth
|
|
Packit |
9c6abc |
frame_bottom = frame_params.frameY + frame_params.frameHeight
|
|
Packit |
9c6abc |
assert VP8X.canvasWidth >= frame_right
|
|
Packit |
9c6abc |
assert VP8X.canvasHeight >= frame_bottom
|
|
Packit |
9c6abc |
for subchunk in 'Frame Data':
|
|
Packit |
9c6abc |
if subchunk.tag == "ALPH":
|
|
Packit |
9c6abc |
assert alpha subchunks not found in 'Frame Data' earlier
|
|
Packit |
9c6abc |
frame_params.alpha = alpha_data
|
|
Packit |
9c6abc |
else if subchunk.tag == "VP8 " OR subchunk.tag == "VP8L":
|
|
Packit |
9c6abc |
assert bitstream subchunks not found in 'Frame Data' earlier
|
|
Packit |
9c6abc |
frame_params.bitstream = bitstream_data
|
|
Packit |
9c6abc |
render frame with frame_params.alpha and frame_params.bitstream on
|
|
Packit |
9c6abc |
canvas with top-left corner at (frame_params.frameX,
|
|
Packit |
9c6abc |
frame_params.frameY), using dispose method dispose_method.
|
|
Packit |
9c6abc |
canvas contains the decoded image.
|
|
Packit |
9c6abc |
Show the contents of the canvas for frame_params.frameDuration * 1ms.
|
|
Packit |
9c6abc |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
Example File Layouts
|
|
Packit |
9c6abc |
--------------------
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
A lossy encoded image with alpha may look as follows:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
Packit |
9c6abc |
RIFF/WEBP
|
|
Packit |
9c6abc |
+- VP8X (descriptions of features used)
|
|
Packit |
9c6abc |
+- ALPH (alpha bitstream)
|
|
Packit |
9c6abc |
+- VP8 (bitstream)
|
|
Packit |
9c6abc |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
A losslessly encoded image may look as follows:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
Packit |
9c6abc |
RIFF/WEBP
|
|
Packit |
9c6abc |
+- VP8X (descriptions of features used)
|
|
Packit |
9c6abc |
+- XYZW (unknown chunk)
|
|
Packit |
9c6abc |
+- VP8L (lossless bitstream)
|
|
Packit |
9c6abc |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
A lossless image with ICC profile and XMP metadata may
|
|
Packit |
9c6abc |
look as follows:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
Packit |
9c6abc |
RIFF/WEBP
|
|
Packit |
9c6abc |
+- VP8X (descriptions of features used)
|
|
Packit |
9c6abc |
+- ICCP (color profile)
|
|
Packit |
9c6abc |
+- VP8L (lossless bitstream)
|
|
Packit |
9c6abc |
+- XMP (metadata)
|
|
Packit |
9c6abc |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
An animated image with EXIF metadata may look as follows:
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
Packit |
9c6abc |
RIFF/WEBP
|
|
Packit |
9c6abc |
+- VP8X (descriptions of features used)
|
|
Packit |
9c6abc |
+- ANIM (global animation parameters)
|
|
Packit |
9c6abc |
+- ANMF (frame1 parameters + data)
|
|
Packit |
9c6abc |
+- ANMF (frame2 parameters + data)
|
|
Packit |
9c6abc |
+- ANMF (frame3 parameters + data)
|
|
Packit |
9c6abc |
+- ANMF (frame4 parameters + data)
|
|
Packit |
9c6abc |
+- EXIF (metadata)
|
|
Packit |
9c6abc |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
[vp8spec]: http://tools.ietf.org/html/rfc6386
|
|
Packit |
9c6abc |
[webpllspec]: https://chromium.googlesource.com/webm/libwebp/+/master/doc/webp-lossless-bitstream-spec.txt
|
|
Packit |
9c6abc |
[iccspec]: http://www.color.org/icc_specs2.xalter
|
|
Packit |
9c6abc |
[metadata]: http://www.metadataworkinggroup.org/pdf/mwg_guidance.pdf
|
|
Packit |
9c6abc |
[rfc 1166]: http://tools.ietf.org/html/rfc1166
|
|
Packit |
9c6abc |
[rfc 2119]: http://tools.ietf.org/html/rfc2119
|