mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-26 13:48:21 +01:00
Image fragment specification in container spec
Change-Id: If8cad296738465df4327dfb6b44efa7e0356070e
This commit is contained in:
parent
391f9db9fa
commit
001b930219
@ -13,7 +13,7 @@ end of this file.
|
|||||||
WebP Container Specification
|
WebP Container Specification
|
||||||
============================
|
============================
|
||||||
|
|
||||||
_Working Draft, v0.7, 20121102_
|
_Working Draft, v0.8, 20121102_
|
||||||
|
|
||||||
|
|
||||||
* TOC placeholder
|
* TOC placeholder
|
||||||
@ -46,6 +46,15 @@ for:
|
|||||||
* **Color Profile.** An image may have an embedded ICC profile as described
|
* **Color Profile.** An image may have an embedded ICC profile as described
|
||||||
by the [International Color Consortium][iccspec].
|
by the [International Color Consortium][iccspec].
|
||||||
|
|
||||||
|
* **Image Fragmentation.** A single bitstream in WebP has an inherent
|
||||||
|
limitation for width or height of 2^14 pixels, and, when using VP8, a 512
|
||||||
|
KiB limit on the size of the first compressed partition. To support larger
|
||||||
|
images, the format supports images that are composed of multiple fragments,
|
||||||
|
each encoded as a separate bitstream. All fragments logically form a single
|
||||||
|
image: they have common metadata, color profile, etc. Image fragmentation
|
||||||
|
may also improve efficiency for larger images, e.g., grass can be encoded
|
||||||
|
differently than sky.
|
||||||
|
|
||||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
|
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
|
||||||
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
|
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
|
||||||
document are to be interpreted as described in [RFC 2119][].
|
document are to be interpreted as described in [RFC 2119][].
|
||||||
@ -60,8 +69,10 @@ matrix of pixels, we will call it the _canvas_ of the image.
|
|||||||
|
|
||||||
Below are additional terms used throughout this document:
|
Below are additional terms used throughout this document:
|
||||||
|
|
||||||
Code that reads WebP files is referred to as a _reader_, while
|
_Reader/Writer_
|
||||||
code that writes them is referred to as a _writer_.
|
|
||||||
|
: Code that reads WebP files is referred to as a _reader_, while code that
|
||||||
|
writes them is referred to as a _writer_.
|
||||||
|
|
||||||
_uint16_
|
_uint16_
|
||||||
|
|
||||||
@ -76,6 +87,7 @@ _uint32_
|
|||||||
: A 32-bit, little-endian, unsigned integer.
|
: A 32-bit, little-endian, unsigned integer.
|
||||||
|
|
||||||
_1-based_
|
_1-based_
|
||||||
|
|
||||||
: An unsigned integer field storing values offset by `-1`. e.g., Such a field
|
: An unsigned integer field storing values offset by `-1`. e.g., Such a field
|
||||||
would store value _25_ as _24_.
|
would store value _25_ as _24_.
|
||||||
|
|
||||||
@ -257,14 +269,30 @@ An extended format file consists of:
|
|||||||
|
|
||||||
* An optional 'ICCP' chunk with color profile.
|
* An optional 'ICCP' chunk with color profile.
|
||||||
|
|
||||||
* An optional 'ALPH' chunk with transparency information.
|
* Image data (described below).
|
||||||
|
|
||||||
* The image bitstream contained in either a 'VP8 ' or 'VP8L' chunk.
|
|
||||||
|
|
||||||
* An optional 'EXIF' chunk with EXIF metadata.
|
* An optional 'EXIF' chunk with EXIF metadata.
|
||||||
|
|
||||||
* An optional 'XMP ' chunk with XMP metadata.
|
* An optional 'XMP ' chunk with XMP metadata.
|
||||||
|
|
||||||
|
The image can be fragmented or non-fragmented, as will be described in the
|
||||||
|
[Extended WebP file header](#extended_header) section.
|
||||||
|
|
||||||
|
For a _non-fragmented_ image, the _image data_ consists of:
|
||||||
|
|
||||||
|
* An optional 'ALPH' chunk with transparency information.
|
||||||
|
|
||||||
|
* The image bitstream contained in either a 'VP8 ' or 'VP8L' chunk.
|
||||||
|
|
||||||
|
For a _fragmented_ image, the _image data_ consists of multiple fragments,
|
||||||
|
where each fragment consists of:
|
||||||
|
|
||||||
|
* A 'FRGM' chunk with the fragment information.
|
||||||
|
|
||||||
|
* An optional 'ALPH' chunk with transparency information.
|
||||||
|
|
||||||
|
* The bitstream for the fragment contained in either a 'VP8 ' or 'VP8L' chunk.
|
||||||
|
|
||||||
All chunks SHOULD be placed in the same order as listed above. If a chunk
|
All chunks SHOULD be placed in the same order as listed above. If a chunk
|
||||||
appears in the wrong place, the file is invalid, but readers MAY parse the
|
appears in the wrong place, the file is invalid, but readers MAY parse the
|
||||||
file, ignoring the chunks that come too late.
|
file, ignoring the chunks that come too late.
|
||||||
@ -276,6 +304,7 @@ ignoring late chunks should make programs that need to do a full search
|
|||||||
give the same results as the ones stopping early.
|
give the same results as the ones stopping early.
|
||||||
|
|
||||||
Extended WebP file header:
|
Extended WebP file header:
|
||||||
|
{:#extended_header}
|
||||||
|
|
||||||
0 1 2 3
|
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
|
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
|
||||||
@ -284,7 +313,7 @@ Extended WebP file header:
|
|||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
| ChunkHeader('VP8X') |
|
| ChunkHeader('VP8X') |
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|Rsv|I|L|E|X| R | Reserved |
|
|Rsv|I|L|E|X|R|F| Reserved |
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
| Canvas Width Minus One | ...
|
| Canvas Width Minus One | ...
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
@ -301,7 +330,7 @@ ICC profile (I): 1 bit
|
|||||||
|
|
||||||
Alpha (L): 1 bit
|
Alpha (L): 1 bit
|
||||||
|
|
||||||
: Set if the file contains some (or all) images with transparency information
|
: Set if any of the frames of the image contain transparency information
|
||||||
("alpha").
|
("alpha").
|
||||||
|
|
||||||
EXIF metadata (E): 1 bit
|
EXIF metadata (E): 1 bit
|
||||||
@ -312,10 +341,14 @@ XMP metadata (X): 1 bit
|
|||||||
|
|
||||||
: Set if the file contains XMP metadata.
|
: Set if the file contains XMP metadata.
|
||||||
|
|
||||||
Reserved (R): 2 bits
|
Reserved (R): 1 bit
|
||||||
|
|
||||||
: SHOULD be `0`.
|
: SHOULD be `0`.
|
||||||
|
|
||||||
|
Image Fragmentation (F): 1 bit
|
||||||
|
|
||||||
|
: Set if the image is represented by fragments.
|
||||||
|
|
||||||
Reserved: 24 bits
|
Reserved: 24 bits
|
||||||
|
|
||||||
: SHOULD be `0`.
|
: SHOULD be `0`.
|
||||||
@ -336,6 +369,48 @@ Future specifications MAY add more fields.
|
|||||||
|
|
||||||
### Chunks
|
### Chunks
|
||||||
|
|
||||||
|
#### Image Fragments
|
||||||
|
|
||||||
|
For images that are represented by fragments, this chunk contains data for
|
||||||
|
a single fragment. If the _Image Fragmentation Flag_ is not set, then this chunk
|
||||||
|
SHOULD NOT be present.
|
||||||
|
|
||||||
|
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('FRGM') |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| Fragment X | ...
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
... Fragment Y | Fragment Data |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
|
||||||
|
Fragment X: 24 bits (_uint24_)
|
||||||
|
|
||||||
|
: The X coordinate of the upper left corner of the fragment is `Fragment X * 2`
|
||||||
|
|
||||||
|
Fragment Y: 24 bits (_uint24_)
|
||||||
|
|
||||||
|
: The Y coordinate of the upper left corner of the fragment is `Fragment Y * 2`
|
||||||
|
|
||||||
|
Fragment Data: _Chunk Size_ - `6` bytes
|
||||||
|
|
||||||
|
: It contains:
|
||||||
|
|
||||||
|
* An optional [alpha subchunk](#alpha) for the fragment.
|
||||||
|
* The [bitstream subchunk](#bitstream-vp8vp8l) for the fragment.
|
||||||
|
|
||||||
|
Note: The width and height of the fragment is obtained from the bitstream
|
||||||
|
subchunk.
|
||||||
|
|
||||||
|
The fragments of an image SHOULD have the following properties:
|
||||||
|
|
||||||
|
* They collectively cover the whole canvas.
|
||||||
|
|
||||||
|
* No pair of fragments have any overlapping region on the canvas.
|
||||||
|
|
||||||
|
* No portion of any fragment should be located outside of the canvas.
|
||||||
|
|
||||||
#### Alpha
|
#### Alpha
|
||||||
|
|
||||||
0 1 2 3
|
0 1 2 3
|
||||||
@ -390,8 +465,8 @@ where `clip(v)` is equal to:
|
|||||||
* v otherwise
|
* v otherwise
|
||||||
|
|
||||||
The final value is derived by adding the decompressed value `X` to the
|
The final value is derived by adding the decompressed value `X` to the
|
||||||
predictor and using modulo-256 arithmetic to wrap the [256-511] range
|
predictor and using modulo-256 arithmetic to wrap the \[256-511\] range
|
||||||
into the [0-255] one:
|
into the \[0-255\] one:
|
||||||
|
|
||||||
`alpha = (predictor + X) % 256`
|
`alpha = (predictor + X) % 256`
|
||||||
|
|
||||||
@ -417,10 +492,10 @@ Alpha bitstream: _Chunk Size_ - `1` bytes
|
|||||||
|
|
||||||
: Encoded alpha bitstream.
|
: Encoded alpha bitstream.
|
||||||
|
|
||||||
This optional chunk contains encoded alpha data for the image. An image
|
This optional chunk contains encoded alpha data for this frame. A frame
|
||||||
containing a 'VP8L' chunk SHOULD NOT contain this chunk.
|
containing a 'VP8L' chunk SHOULD NOT contain this chunk.
|
||||||
|
|
||||||
**Rationale**: The transparency information of the image is already part
|
**Rationale**: The transparency information of the frame is already part
|
||||||
of the 'VP8L' chunk.
|
of the 'VP8L' chunk.
|
||||||
|
|
||||||
The alpha channel data is stored as uncompressed raw data (when
|
The alpha channel data is stored as uncompressed raw data (when
|
||||||
@ -528,6 +603,42 @@ Metadata Working Group's [Guidelines for Handling Metadata][metadata].
|
|||||||
A file MAY contain other unknown chunks. Readers SHOULD ignore these chunks.
|
A file MAY contain other unknown chunks. Readers SHOULD ignore these chunks.
|
||||||
Writers SHOULD preserve them in their original order.
|
Writers SHOULD preserve them in their original order.
|
||||||
|
|
||||||
|
### Assembling the Canvas from fragments
|
||||||
|
|
||||||
|
Here we provide an overview of how 'FRGM' chunks are used to assemble the
|
||||||
|
canvas in case of a fragmented-image. The notation _VP8X.field_ means the field
|
||||||
|
in the 'VP8X' chunk with the same description.
|
||||||
|
|
||||||
|
Displaying a _fragmented image_ canvas MUST be equivalent to the following
|
||||||
|
pseudocode:
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
assert VP8X.flags.hasFragments
|
||||||
|
canvas ← new black image of size VP8X.canvasWidth x VP8X.canvasHeight.
|
||||||
|
frgm_params ← nil
|
||||||
|
for chunk in image_data:
|
||||||
|
assert chunk.tag is "FRGM"
|
||||||
|
frgm_params.fragmentX = Fragment X
|
||||||
|
frgm_params.fragmentY = Fragment Y
|
||||||
|
for subchunk in 'Fragment Data':
|
||||||
|
if subchunk.tag == "ALPH":
|
||||||
|
assert alpha subchunks not found in 'Fragment Data' earlier
|
||||||
|
frgm_params.alpha = alpha_data
|
||||||
|
else if subchunk.tag == "VP8 " OR subchunk.tag == "VP8L":
|
||||||
|
assert bitstream subchunks not found in 'Fragment Data' earlier
|
||||||
|
frgm_params.bitstream = bitstream_data
|
||||||
|
frgm_params.fragmentWidth = Width extracted from bitstream subchunk
|
||||||
|
frgm_params.fragmentHeight = Height extracted from bitstream subchunk
|
||||||
|
assert VP8X.canvasWidth >=
|
||||||
|
frgm_params.fragmentX + frgm_params.fragmentWidth
|
||||||
|
assert VP8X.canvasHeight >=
|
||||||
|
frgm_params.fragmentY + frgm_params.fragmentHeight
|
||||||
|
assert fragment has the properties mentioned in "Image Fragments" section.
|
||||||
|
render fragment with frame_params.alpha and frame_params.bitstream on canvas
|
||||||
|
with top-left corner in (frgm_params.fragmentX, frgm_params.fragmentY).
|
||||||
|
canvas contains the decoded canvas.
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Example file layouts
|
Example file layouts
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
@ -560,6 +671,17 @@ RIFF/WEBP
|
|||||||
+- XMP (metadata)
|
+- XMP (metadata)
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
A fragmented image may look as follows:
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
RIFF/WEBP
|
||||||
|
+- VP8X (descriptions of features used)
|
||||||
|
+- FRGM (fragment1 parameters + data)
|
||||||
|
+- FRGM (fragment2 parameters + data)
|
||||||
|
+- FRGM (fragment3 parameters + data)
|
||||||
|
+- FRGM (fragment4 parameters + data)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
[vp8spec]: http://tools.ietf.org/html/rfc6386
|
[vp8spec]: http://tools.ietf.org/html/rfc6386
|
||||||
[webpllspec]: https://gerrit.chromium.org/gerrit/gitweb?p=webm/libwebp.git;a=blob;f=doc/webp-lossless-bitstream-spec.txt;hb=master
|
[webpllspec]: https://gerrit.chromium.org/gerrit/gitweb?p=webm/libwebp.git;a=blob;f=doc/webp-lossless-bitstream-spec.txt;hb=master
|
||||||
[iccspec]: http://www.color.org/icc_specs2.xalter
|
[iccspec]: http://www.color.org/icc_specs2.xalter
|
||||||
|
Loading…
Reference in New Issue
Block a user