mirror of
https://github.com/webmproject/libwebp.git
synced 2024-11-20 12:28:26 +01:00
Merge "webp-container-spec: remove references to fragments"
This commit is contained in:
commit
4ba8e07425
@ -46,25 +46,13 @@ for:
|
|||||||
* **Animation.** An image may have multiple frames with pauses between them,
|
* **Animation.** An image may have multiple frames with pauses between them,
|
||||||
making it an animation.
|
making it an animation.
|
||||||
|
|
||||||
* **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][].
|
||||||
|
|
||||||
**Note:** Out of the features mentioned above, lossy compression, lossless
|
**Note:** Out of the features mentioned above, lossy compression, lossless
|
||||||
compression, transparency, metadata, color profile and animation are finalized
|
compression, transparency, metadata, color profile and animation are finalized
|
||||||
and are to be considered stable. On the other hand, image fragmentation is
|
and are to be considered stable.
|
||||||
experimental as of now, and is open to discussion, feedback and comments.
|
|
||||||
The same is indicated using annotation "_status: experimental_" in the relevant
|
|
||||||
sections of this document.
|
|
||||||
|
|
||||||
Terminology & Basics
|
Terminology & Basics
|
||||||
------------------------
|
------------------------
|
||||||
@ -278,10 +266,6 @@ For a _still image_, the _image data_ consists of a single frame, whereas for
|
|||||||
an _animated image_, it consists of multiple frames. More details about frames
|
an _animated image_, it consists of multiple frames. More details about frames
|
||||||
can be found in the [Animation](#animation) section.
|
can be found in the [Animation](#animation) section.
|
||||||
|
|
||||||
Moreover, each frame can be fragmented or non-fragmented, as will be described
|
|
||||||
in the [Extended WebP file header](#extended_header) section. More details about
|
|
||||||
fragments can be found in the [Fragments](#fragments) section.
|
|
||||||
|
|
||||||
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.
|
||||||
@ -302,7 +286,7 @@ Extended WebP file header:
|
|||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
| ChunkHeader('VP8X') |
|
| ChunkHeader('VP8X') |
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|Rsv|I|L|E|X|A|F| Reserved |
|
|Rsv|I|L|E|X|A|R| Reserved |
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
| Canvas Width Minus One | ...
|
| Canvas Width Minus One | ...
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
@ -335,9 +319,9 @@ Animation (A): 1 bit
|
|||||||
: Set if this is an animated image. Data in 'ANIM' and 'ANMF' chunks should be
|
: Set if this is an animated image. Data in 'ANIM' and 'ANMF' chunks should be
|
||||||
used to control the animation.
|
used to control the animation.
|
||||||
|
|
||||||
Image Fragmentation (F): 1 bit _\[status: experimental\]_
|
Reserved (R): 1 bit
|
||||||
|
|
||||||
: Set if any of the frames in the image are represented by fragments.
|
: SHOULD be `0`.
|
||||||
|
|
||||||
Reserved: 24 bits
|
Reserved: 24 bits
|
||||||
|
|
||||||
@ -506,9 +490,7 @@ Disposal method (D): 1 bit
|
|||||||
|
|
||||||
Frame Data: _Chunk Size_ - `16` bytes
|
Frame Data: _Chunk Size_ - `16` bytes
|
||||||
|
|
||||||
: For a fragmented frame, it consists of multiple [fragment chunks](#fragments).
|
: Consists of:
|
||||||
|
|
||||||
: For a non-fragmented frame, it consists of:
|
|
||||||
|
|
||||||
* An optional [alpha subchunk](#alpha) for the frame.
|
* An optional [alpha subchunk](#alpha) for the frame.
|
||||||
|
|
||||||
@ -519,49 +501,6 @@ Frame Data: _Chunk Size_ - `16` bytes
|
|||||||
**Note**: The 'ANMF' payload, _Frame Data_ above, consists of individual
|
**Note**: The 'ANMF' payload, _Frame Data_ above, consists of individual
|
||||||
_padded_ chunks as described by the [RIFF file format](#riff-file-format).
|
_padded_ chunks as described by the [RIFF file format](#riff-file-format).
|
||||||
|
|
||||||
#### Fragments _\[status: experimental\]_
|
|
||||||
|
|
||||||
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.
|
|
||||||
* An optional list of [unknown chunks](#unknown-chunks).
|
|
||||||
|
|
||||||
Note: The width and height of the fragment is obtained from the bitstream
|
|
||||||
subchunk.
|
|
||||||
|
|
||||||
The fragments of a frame SHOULD have the following properties:
|
|
||||||
|
|
||||||
* They collectively cover the whole frame.
|
|
||||||
|
|
||||||
* No pair of fragments have any overlapping region on the frame.
|
|
||||||
|
|
||||||
* No portion of any fragment should be located outside of the canvas.
|
|
||||||
|
|
||||||
#### Alpha
|
#### Alpha
|
||||||
|
|
||||||
0 1 2 3
|
0 1 2 3
|
||||||
@ -643,8 +582,8 @@ Alpha bitstream: _Chunk Size_ - `1` bytes
|
|||||||
|
|
||||||
: Encoded alpha bitstream.
|
: Encoded alpha bitstream.
|
||||||
|
|
||||||
This optional chunk contains encoded alpha data for this frame/fragment. A
|
This optional chunk contains encoded alpha data for this frame. A
|
||||||
frame/fragment containing a 'VP8L' chunk SHOULD NOT contain this chunk.
|
frame containing a 'VP8L' chunk SHOULD NOT contain this chunk.
|
||||||
|
|
||||||
**Rationale**: The transparency information is already part of the 'VP8L'
|
**Rationale**: The transparency information is already part of the 'VP8L'
|
||||||
chunk.
|
chunk.
|
||||||
@ -675,7 +614,7 @@ compression method is '0') or compressed using the lossless format
|
|||||||
|
|
||||||
#### Bitstream (VP8/VP8L)
|
#### Bitstream (VP8/VP8L)
|
||||||
|
|
||||||
This chunk contains compressed bitstream data for a single frame/fragment.
|
This chunk contains compressed bitstream data for a single frame.
|
||||||
|
|
||||||
A bitstream chunk may be either (i) a VP8 chunk, using "VP8 " (note the
|
A bitstream chunk may be either (i) a VP8 chunk, using "VP8 " (note the
|
||||||
significant fourth-character space) as its tag _or_ (ii) a VP8L chunk, using
|
significant fourth-character space) as its tag _or_ (ii) a VP8L chunk, using
|
||||||
@ -762,47 +701,17 @@ A file MAY contain unknown chunks:
|
|||||||
|
|
||||||
* At the end of the file as described in [Extended WebP file
|
* At the end of the file as described in [Extended WebP file
|
||||||
header](#extended_header) section.
|
header](#extended_header) section.
|
||||||
* At the end of FRGM and ANMF chunks as described in [Fragments](#fragments)
|
* At the end of ANMF chunks as described in the
|
||||||
and [Animation](#animation) sections.
|
[Animation](#animation) section.
|
||||||
|
|
||||||
Readers SHOULD ignore these chunks. Writers SHOULD preserve them in their
|
Readers SHOULD ignore these chunks. Writers SHOULD preserve them in their
|
||||||
original order (unless they specifically intend to modify these chunks).
|
original order (unless they specifically intend to modify these chunks).
|
||||||
|
|
||||||
### Assembling the Canvas from fragments/frames
|
### Assembling the Canvas from frames
|
||||||
|
|
||||||
Here we provide an overview of how a reader should assemble a canvas in case
|
Here we provide an overview of how a reader should assemble a canvas in the
|
||||||
of a fragmented-image and in case of an animated image. The notation
|
case of an animated image. The notation _VP8X.field_ means the field in the
|
||||||
_VP8X.field_ means the field in the 'VP8X' chunk with the same description.
|
'VP8X' chunk with the same description.
|
||||||
|
|
||||||
Displaying a _fragmented image_ canvas MUST be equivalent to the following
|
|
||||||
pseudocode: _\[status: experimental\]_
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
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.
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Displaying an _animated image_ canvas MUST be equivalent to the following
|
Displaying an _animated image_ canvas MUST be equivalent to the following
|
||||||
pseudocode:
|
pseudocode:
|
||||||
@ -825,13 +734,6 @@ for loop = 0, ..., loop_count - 1
|
|||||||
frame_params.frameDuration = Frame Duration
|
frame_params.frameDuration = Frame Duration
|
||||||
assert VP8X.canvasWidth >= frame_params.frameX + frame_params.frameWidth
|
assert VP8X.canvasWidth >= frame_params.frameX + frame_params.frameWidth
|
||||||
assert VP8X.canvasHeight >= frame_params.frameY + frame_params.frameHeight
|
assert VP8X.canvasHeight >= frame_params.frameY + frame_params.frameHeight
|
||||||
if VP8X.flags.hasFragments and first subchunk in 'Frame Data' is FRGM
|
|
||||||
// Fragmented frame.
|
|
||||||
frame_params.{bitstream,alpha} = canvas decoded from subchunks in
|
|
||||||
'Frame Data' as per the pseudocode for
|
|
||||||
_fragmented image_ above.
|
|
||||||
else
|
|
||||||
// Non-fragmented frame.
|
|
||||||
for subchunk in 'Frame Data':
|
for subchunk in 'Frame Data':
|
||||||
if subchunk.tag == "ALPH":
|
if subchunk.tag == "ALPH":
|
||||||
assert alpha subchunks not found in 'Frame Data' earlier
|
assert alpha subchunks not found in 'Frame Data' earlier
|
||||||
@ -878,17 +780,6 @@ 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)
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
An animated image with EXIF metadata may look as follows:
|
An animated image with EXIF metadata may look as follows:
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Loading…
Reference in New Issue
Block a user