From 001b930219f3e21659076119a8a574ae2d7debec Mon Sep 17 00:00:00 2001 From: Urvang Joshi Date: Tue, 30 Oct 2012 16:06:36 -0700 Subject: [PATCH] Image fragment specification in container spec Change-Id: If8cad296738465df4327dfb6b44efa7e0356070e --- doc/webp-container-spec.txt | 148 ++++++++++++++++++++++++++++++++---- 1 file changed, 135 insertions(+), 13 deletions(-) diff --git a/doc/webp-container-spec.txt b/doc/webp-container-spec.txt index cdcad798..1a29fcd1 100644 --- a/doc/webp-container-spec.txt +++ b/doc/webp-container-spec.txt @@ -13,7 +13,7 @@ end of this file. WebP Container Specification ============================ -_Working Draft, v0.7, 20121102_ +_Working Draft, v0.8, 20121102_ * TOC placeholder @@ -46,6 +46,15 @@ for: * **Color Profile.** An image may have an embedded ICC profile as described 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", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this 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: -Code that reads WebP files is referred to as a _reader_, while -code that writes them is referred to as a _writer_. +_Reader/Writer_ + +: Code that reads WebP files is referred to as a _reader_, while code that +writes them is referred to as a _writer_. _uint16_ @@ -76,6 +87,7 @@ _uint32_ : A 32-bit, little-endian, unsigned integer. _1-based_ + : An unsigned integer field storing values offset by `-1`. e.g., Such a field 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 'ALPH' chunk with transparency information. - - * The image bitstream contained in either a 'VP8 ' or 'VP8L' chunk. + * Image data (described below). * An optional 'EXIF' chunk with EXIF 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 appears in the wrong place, the file is invalid, but readers MAY parse the 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. Extended WebP file header: +{:#extended_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 @@ -284,7 +313,7 @@ Extended WebP file header: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ChunkHeader('VP8X') | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |Rsv|I|L|E|X| R | Reserved | + |Rsv|I|L|E|X|R|F| Reserved | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Canvas Width Minus One | ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -301,7 +330,7 @@ ICC profile (I): 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"). EXIF metadata (E): 1 bit @@ -312,10 +341,14 @@ XMP metadata (X): 1 bit : Set if the file contains XMP metadata. -Reserved (R): 2 bits +Reserved (R): 1 bit : SHOULD be `0`. +Image Fragmentation (F): 1 bit + +: Set if the image is represented by fragments. + Reserved: 24 bits : SHOULD be `0`. @@ -336,6 +369,48 @@ Future specifications MAY add more fields. ### 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 0 1 2 3 @@ -390,8 +465,8 @@ where `clip(v)` is equal to: * v otherwise 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 -into the [0-255] one: +predictor and using modulo-256 arithmetic to wrap the \[256-511\] range +into the \[0-255\] one: `alpha = (predictor + X) % 256` @@ -417,10 +492,10 @@ Alpha bitstream: _Chunk Size_ - `1` bytes : 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. -**Rationale**: The transparency information of the image is already part +**Rationale**: The transparency information of the frame is already part of the 'VP8L' chunk. 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. 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 -------------------- @@ -560,6 +671,17 @@ RIFF/WEBP +- 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 [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