APNG Specification: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 1: Line 1:
APNG 0.6 <i>[DRAFT]</i>
APNG 0.7 <i>[DRAFT]</i>


Authors:
Authors:
* Stuart Parmenter <pavlov@pavlov.net>
* Stuart Parmenter <pavlov@pavlov.net>
* Vladimir Vukicevic <vladimir@pobox.com>
* Vladimir Vukicevic <vladimir@pobox.com>
* Andrew Smith <asmith15@learn.senecac.on.ca>


= Overview =
= Overview =
Line 13: Line 14:
= Structure =
= Structure =


An APNG stream is a normal PNG stream as defined in the [PNG Specification][pngspec], with four additional chunks describing the animation and providing additional frame data.  The first frame of an animation, frame 0, is encoded as a normal PNG.  This frame is what decoders that do not understand the APNG chunks will display.
An APNG stream is a normal PNG stream as defined in the [PNG Specification][pngspec], with three additional chunk types describing the animation and providing additional frame data.  The first frame of an animation, frame 0, is encoded as a normal PNG.  This frame is what decoders that do not understand the APNG chunks will display.


The size of the first frame defines the boundaries of the entire animation; hence, if extra space will be needed for later frames that is unused in the first frame, the first frame should be appropriately padded with fully transparent regions.
The size of the first frame defines the boundaries of the entire animation; hence, if extra space will be needed for later frames that is unused in the first frame, the first frame should be appropriately padded with fully transparent regions.
Line 21: Line 22:
An `fcTl` chunk must also appear before `IDAT`, providing frame information for the first frame encoded in the PNG stream's `IDAT` chunks, known as frame 0.
An `fcTl` chunk must also appear before `IDAT`, providing frame information for the first frame encoded in the PNG stream's `IDAT` chunks, known as frame 0.


Subsequent frames are encoded in `fdAt` chunks, containing information about placement and rendering of a frame in `fcTl` chunks, as well as frame data encoded as normal PNG streams.  The full layout of the `fdAt` chunk is described in section 2.3.
Subsequent frames are encoded in `fdAt` chunks containing almost the same structure of content as IDAT chunks. Information for each frame about placement and rendering is stored in `fcTl` chunks.  The full layout of `fdAt` and `fcTl` chunks is described below.


Note: For purposes of chunk descriptions, an "unsigned int" shall be a 32-bit unsigned integer in network byte order; a "signed int" shall be a 32-bit signed integer in network byte order; an "unsigned short" shall be a 16-bit unsigned integer in network byte order; a "byte" shall be a 8-bit unsigned integer.
Note: For purposes of chunk descriptions, an "unsigned int" shall be a 32-bit unsigned integer in network byte order; a "signed int" shall be a 32-bit signed integer in network byte order; an "unsigned short" shall be a 16-bit unsigned integer in network byte order; a "byte" shall be a 8-bit unsigned integer.
== Chuck Sequence Numbers ==
The `fcTl` and `fdAt` chunks have a 4 byte sequence number. Both chunk types share the sequence. The purpose of this number is to detect (and optionally correct) sequence errors in an Animated PNG, since the PNG specification does not impose orderng restrictions on ancillary chunks.
The table below illustrates the use of sequence numbers for images with more than one frame and more than one `fdAt` chunk:
    Sequence number    Chunk
    0                  `fcTl` describing frame 0
    1                  `fcTl` describing frame 1
    2                  first `fdAt` for frame 1
    3                  second `fdAt` for frame 1
    ....


== `acTl`: The Animation Control Chunk ==
== `acTl`: The Animation Control Chunk ==
Line 32: Line 46:


     byte
     byte
       0   num_frames       (unsigned int)    Number of frames
       0   num_frames     (unsigned int)    Number of frames
       4   num_iterations   (unsigned int)    Number of times to loop this APNG.  0 indicates infinite looping.
       4   num_iterations (unsigned int)    Number of times to loop this APNG.  0 indicates infinite looping.
       8   IHDR_crc         (unsigned int)    CRC of the IHDR chunk.
       8   IHDR_crc       (unsigned int)    CRC of the IHDR chunk.
     12   PLTE_crc         (unsigned int)    CRC of the PLTE chunk or 0.
     12   PLTE_crc       (unsigned int)    CRC of the PLTE chunk or 0.


`num_frames` indicates the total number of frames in the animation, that is the first frame plus the number of fdAt chunks. 0 is not a valid value. 1 is a valid value for a single-frame APNG. In case this number does not match the actual number of frames, behaviour of the implementation is not specified.
`num_frames` indicates the total number of frames in the animation. 0 is not a valid value. 1 is a valid value for a single-frame APNG. In case this number does not match the actual number of frames, behaviour of the implementation is not specified.


`num_iterations` indicates the number of iterations that this animation should play; if it is 0, the animation should play indefinitely.  If nonzero, the animation should come to rest on the final non-skipped frame at the end of the last iteration.
`num_iterations` indicates the number of iterations that this animation should play; if it is 0, the animation should play indefinitely.  If nonzero, the animation should come to rest on the final non-skipped frame at the end of the last iteration.
Line 47: Line 61:
== `fcTl`: The Frame Control Chunk ==
== `fcTl`: The Frame Control Chunk ==


The `fcTl` chunk is an ancillary chunk as defined in the PNG Specification. It must appear before the IDAT chunks of the frame to which it applies, specifically:
The `fcTl` chunk is an ancillary chunk as defined in the PNG Specification. It must appear before the `IDAT` or `fdAt` chunks of the frame to which it applies, specifically:


* For the first frame, the `fcTl` chunk must appear before the first `IDAT` chunk. Position relative to the `acTl` chunk is not specified.
* For the first frame, the `fcTl` chunk must appear before the first `IDAT` chunk. Position relative to the `acTl` chunk is not specified.
* For any subsequent frames, the `fcTl` chunk must be first in the data part of the `fdAt` chunk.
* For the second frame, the `fcTl` chunk must appear immediately after the `IDAT` chunks from the first frame and immediately before the fdAt chunks for the second frame.
* For any subsequent frames, the `fcTl` chunk for the frame N must appear immediately after the `fdAt` chunks from the frame N-1 and immediately before the fdAt chunks for the frame N.


The `fcTl` chunk is mandatory for every frame. More than one `fcTl` chunk per frame is not allowed.
The `fcTl` chunk is mandatory for every frame. More than one `fcTl` chunk per frame is not allowed.
Line 57: Line 72:


     byte
     byte
     0    sequence_number   (unsigned int)     Sequence number of the frame, starting from 0
     0    sequence_number       (unsigned int)   Sequence number of the animation chunk, starting from 0
     4    x_offset         (unsigned int)     X position at which to render this frame
     4   width                (unsigned int)  Width of the following frame
    8   y_offset         (unsigned int)     Y position at which to render this frame
    8    height                (unsigned int)  Height of the following frame
     12   delay_num         (unsigned short)   Frame delay fraction numerator
    12   x_offset             (unsigned int)   X position at which to render the following frame
     14   delay_den         (unsigned short)   Frame delay fraction denominator
    16   y_offset             (unsigned int)   Y position at which to render the following frame
     16   render_op         (byte)             Type of canvas area disposal to be done after rendering this frame
     20   delay_num             (unsigned short) Frame delay fraction numerator
     22   delay_den             (unsigned short) Frame delay fraction denominator
     24   render_op             (byte)           Type of canvas area disposal to be done after rendering this frame


The `sequence_number` shall begin with 0 for the first `fdAt` in the PNG stream, and increase by one with each subsequent frame.
The frame must be rendered within the region defined by the `width`, `height`, `x_offset` and `y_offset` from the `fcTl`, and the width and height from the `IHDR`.


The frame must be rendered within the region defined by the `x_offset` and `y_offset` from the `fcTl`, and the width and height from this frame's `IHDR`. For frame 0, the `x_offset` and `y_offset` fields must be 0. Should parts
The width and height cannot be bigger than (respectively) the width and height specified in the `IHDR` chunk.
of the region fall outside the canvas defined by frame 0, rendering is to be clipped to that canvas.
 
For frame 0 the width and height fields must equal the width and height from the `IHDR` chunk. Also for frame 0 the `x_offset` and `y_offset` fields must be 0. Should parts of the region fall outside the canvas defined by frame 0, rendering may be clipped to that canvas or the condition may be treated as an error.


The `delay_num` and `delay_den` parameters together specify a fraction indicating the delay after the current frame, in seconds.  If the denominator is 0, it is to be treated as if it were 100 (that is, delay_num then specifies 1/100ths of a second).  If the the value of the numerator is 0 the decoder should render the next frame as quickly as possible, though viewers may impose a reasonable lower bound on the delay.
The `delay_num` and `delay_den` parameters together specify a fraction indicating the delay after the current frame, in seconds.  If the denominator is 0, it is to be treated as if it were 100 (that is, delay_num then specifies 1/100ths of a second).  If the the value of the numerator is 0 the decoder should render the next frame as quickly as possible, though viewers may impose a reasonable lower bound on the delay.
Line 109: Line 127:
== `fdAt`: The Frame Data Chunk ==
== `fdAt`: The Frame Data Chunk ==


The `fdAt` chunk contains one frame for the animation. Any `fdAt` chunks must follow any `IDAT` chunks. All `fdAt` chunks must be adjacent in the PNG stream. Should a decoder receive an APNG stream with missing or out of order `fdAt` chunks, it is under no obligation to attempt to reorder the chunks and may treat that case as an error condition.
The `fdAt` chunk has the same purpose as an `IDAT` chunk. It has the same data structure as an `IDAT` chunk, except a sequence number is appended in the beginning.
 
There may be multiple `fdAt` chunks for any one frame; if so, they shall appear consecutively with no other intervening chunks. The compressed datastream is then the concatenation of the contents of the data fields of all the `fdAt` chunks.


Format:
Format:


     byte
     byte
     0     `fcTl` chunk   29 bytes    `fcTl` chunk for this frame
     0  sequence_number      (unsigned int)  Sequence number of the animation chunk, starting from 0
     29    `IDAT` chunks  X bytes     Frame data for this frame
     4  frame_data            X bytes         Frame data for this frame
    29+X  `feND` chunk  12 bytes    `feND` chunk to mark the end of the frame data
 
Each of the chunks contained in the data section of the `fdAt` must follow all the rules in section 5 of the PNG specification, except 5.6 Chunk Ordering. The order of chunks within the `fdAt` is fixed.
 
The frame data within the `fdAt` consists of a series of `IDAT` chunks, following the rules from section 11.2.4 of the PNG Specification.
 
The `feND` is an ancillary, zero-length data field chunk, used to mark the end of the frame data. The `feND` chunk is a mandatory last chunk in the data part of the `fdAt` chunk. Only one `feND` per `fdAt` is allowed.
 
Each frame inherits every property specified by any critical or ancillary chunks before the first IDAT in the file.


Note: both the container chunk (`fdAt`) and every chunk within (`fcTl`, `IDAT`s, `feND`) must specify the length of its own data field and the CRC over its own chunk name + chunk data as required by section 5.3 of the PNG Specification.
Each frame inherits every property except the width and the height specified by any critical or ancillary chunks before the first IDAT in the file.


= Revisions to this Specification ==
= Revisions to this Specification =


== From 0.1 ==
== From 0.1 ==
Line 192: Line 203:


* The acTL fcTL and adAT are now copy safe, renamed them to acTl, fcTl and adAt
* The acTL fcTL and adAT are now copy safe, renamed them to acTl, fcTl and adAt
== From .6 ==
* The fdAt chunk is no longer a container for other chunks, but rather a replacement for an IDAT chunk
* Added a sequence number field to fdAt
* Reintroduced the width and height fields in fcTl


= Test Encoder and Sample Images =
= Test Encoder and Sample Images =

Revision as of 09:54, 6 March 2007

APNG 0.7 [DRAFT]

Authors:

  • Stuart Parmenter <pavlov@pavlov.net>
  • Vladimir Vukicevic <vladimir@pobox.com>
  • Andrew Smith <asmith15@learn.senecac.on.ca>

Overview

APNG is an extension of the [PNG][pngspec] format, adding support for animated images. It is intended to be a replacement for simple animated images that have traditionally used the [GIF][gifspec] format, while adding support for 24-bit images and 8-bit transparency. APNG is a simpler alternative to MNG, providing a spec suitable for the most common usage of animated images on the Internet.

APNG is backwards-compatible with PNG; any PNG decoder should be able to decode the first frame of an APNG and treat it as a normal single-frame PNG.

Structure

An APNG stream is a normal PNG stream as defined in the [PNG Specification][pngspec], with three additional chunk types describing the animation and providing additional frame data. The first frame of an animation, frame 0, is encoded as a normal PNG. This frame is what decoders that do not understand the APNG chunks will display.

The size of the first frame defines the boundaries of the entire animation; hence, if extra space will be needed for later frames that is unused in the first frame, the first frame should be appropriately padded with fully transparent regions.

To be recognized as an APNG, an `acTl` chunk must appear in the stream before any `IDAT` chunks. The `acTl` structure is described in the next section.

An `fcTl` chunk must also appear before `IDAT`, providing frame information for the first frame encoded in the PNG stream's `IDAT` chunks, known as frame 0.

Subsequent frames are encoded in `fdAt` chunks containing almost the same structure of content as IDAT chunks. Information for each frame about placement and rendering is stored in `fcTl` chunks. The full layout of `fdAt` and `fcTl` chunks is described below.

Note: For purposes of chunk descriptions, an "unsigned int" shall be a 32-bit unsigned integer in network byte order; a "signed int" shall be a 32-bit signed integer in network byte order; an "unsigned short" shall be a 16-bit unsigned integer in network byte order; a "byte" shall be a 8-bit unsigned integer.

Chuck Sequence Numbers

The `fcTl` and `fdAt` chunks have a 4 byte sequence number. Both chunk types share the sequence. The purpose of this number is to detect (and optionally correct) sequence errors in an Animated PNG, since the PNG specification does not impose orderng restrictions on ancillary chunks.

The table below illustrates the use of sequence numbers for images with more than one frame and more than one `fdAt` chunk:

    Sequence number    Chunk
    0                  `fcTl` describing frame 0
    1                  `fcTl` describing frame 1
    2                  first `fdAt` for frame 1
    3                  second `fdAt` for frame 1
    ....

`acTl`: The Animation Control Chunk

The `acTl` chunk is an ancillary chunk as defined in the PNG Specification. It must appear before the first `IDAT` chunk within a valid PNG stream. If the color type of the image is PNG_COLOR_TYPE_PALETTE the `acTl` chunk must appear after the `PLTE` chunk.

The `acTl` chunk contains:

    byte
     0   num_frames     (unsigned int)    Number of frames
     4   num_iterations (unsigned int)    Number of times to loop this APNG.  0 indicates infinite looping.
     8   IHDR_crc       (unsigned int)    CRC of the IHDR chunk.
    12   PLTE_crc       (unsigned int)    CRC of the PLTE chunk or 0.

`num_frames` indicates the total number of frames in the animation. 0 is not a valid value. 1 is a valid value for a single-frame APNG. In case this number does not match the actual number of frames, behaviour of the implementation is not specified.

`num_iterations` indicates the number of iterations that this animation should play; if it is 0, the animation should play indefinitely. If nonzero, the animation should come to rest on the final non-skipped frame at the end of the last iteration.

`IHDR_crc` must contain a copy of the CRC from the IHDR chunk. If the two checksums do not match, any further frames must be discarded.

`PLTE_crc` must contain a copy of the CRC from the PLTE chunk if the color type for the PNG is PNG_COLOR_TYPE_PALETTE, and 0 otherwise. If the two checksums do not match, any further frames must be discarded.

`fcTl`: The Frame Control Chunk

The `fcTl` chunk is an ancillary chunk as defined in the PNG Specification. It must appear before the `IDAT` or `fdAt` chunks of the frame to which it applies, specifically:

  • For the first frame, the `fcTl` chunk must appear before the first `IDAT` chunk. Position relative to the `acTl` chunk is not specified.
  • For the second frame, the `fcTl` chunk must appear immediately after the `IDAT` chunks from the first frame and immediately before the fdAt chunks for the second frame.
  • For any subsequent frames, the `fcTl` chunk for the frame N must appear immediately after the `fdAt` chunks from the frame N-1 and immediately before the fdAt chunks for the frame N.

The `fcTl` chunk is mandatory for every frame. More than one `fcTl` chunk per frame is not allowed.

Format:

   byte
    0    sequence_number       (unsigned int)   Sequence number of the animation chunk, starting from 0
    4    width                 (unsigned int)   Width of the following frame
    8    height                (unsigned int)   Height of the following frame
   12    x_offset              (unsigned int)   X position at which to render the following frame
   16    y_offset              (unsigned int)   Y position at which to render the following frame
   20    delay_num             (unsigned short) Frame delay fraction numerator
   22    delay_den             (unsigned short) Frame delay fraction denominator
   24    render_op             (byte)           Type of canvas area disposal to be done after rendering this frame

The frame must be rendered within the region defined by the `width`, `height`, `x_offset` and `y_offset` from the `fcTl`, and the width and height from the `IHDR`.

The width and height cannot be bigger than (respectively) the width and height specified in the `IHDR` chunk.

For frame 0 the width and height fields must equal the width and height from the `IHDR` chunk. Also for frame 0 the `x_offset` and `y_offset` fields must be 0. Should parts of the region fall outside the canvas defined by frame 0, rendering may be clipped to that canvas or the condition may be treated as an error.

The `delay_num` and `delay_den` parameters together specify a fraction indicating the delay after the current frame, in seconds. If the denominator is 0, it is to be treated as if it were 100 (that is, delay_num then specifies 1/100ths of a second). If the the value of the numerator is 0 the decoder should render the next frame as quickly as possible, though viewers may impose a reasonable lower bound on the delay.

The `render_op` parameter contains flags describing how the frame is to be disposed before rendering the next frame; it also specifies whether the frame is to be alpha blended into the current canvas content, or whether it should completely replace its region in the canvas. Valid render_op flags are:

   bit
   +-------------------------------+
   | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
   +-------------|---|---|---|---|-+
                 |   |   +---+---+------ bits 0-2: dispose_op
                 |   |
                 |   +------------------ bit 3: APNG_RENDER_OP_BLEND_FLAG
                 |
                 +---------------------- bit 4: APNG_RENDER_OP_SKIP_FRAME

Bits 5 through 7 are reserved and must be set to 0. Valid values for `dispose_op` are:

   value:
      0   APNG_RENDER_OP_DISPOSE_NONE
      1   APNG_RENDER_OP_DISPOSE_BACKGROUND
      2   APNG_RENDER_OP_DISPOSE_PREVIOUS
  • `APNG_RENDER_OP_DISPOSE_NONE`: no disposal is done on this frame before rendering the next; its contents are left on the canvas. This is the default.
  • `APNG_RENDER_OP_DISPOSE_BACKGROUND`: the frame's region is to be cleared to the background color. If no `bKGD` chunk is specified, the result is fully transparent black (r, g, b, and a all 0).
  • `APNG_RENDER_OP_DISPOSE_PREVIOUS`: the frame's region is to be reverted to the previous contents.

`APNG_RENDER_OP_BLEND_FLAG` may be added to any of the above disposal operations. If this flag is not set, all color components of the frame, including alpha, overwrite the current contents of the frame's canvas region. If the BLEND_FLAG is set the frame should be composited onto the canvas based on its alpha, using a simple OVER operation:

   Csrc - component of pixel in the frame
   Asrc - alpha component of a pixel in the frame
   Cdst - component of pixel in the canvas region
   C - resulting component value to be rendered in the canvas region
   
   C = Csrc * Asrc + Cdst * (1 - Asrc)

`APNG_RENDER_OP_BLEND_FLAG` is not valid for color types 0 (greyscale without alpha) or 2 (truecolor without alpha). It is valid for type 3 (indexed) images; however, the resulting pixel values may not be present in the specified palette. It is always valid for type 4 (greyscale with alpha) and type 6 (truecolor with alpha) images.

If `APNG_RENDER_OP_SKIP_FRAME` is present, then the decoder should not render the current frame as part of the animation. Though this flag can be set on any frame and must be honored, it is most useful for frame 0, to prevent the frame that would be visible to PNG viewers not supporting animation from being part of the animated frame set. If animation in the viewer is not desired or explicitly disabled by the user, the viewer should display frame 0 even if `SKIP_FRAME` is set on frame 0. This provides content authors with a means to provide a still image to be used in lieu of the full animation.

`fdAt`: The Frame Data Chunk

The `fdAt` chunk has the same purpose as an `IDAT` chunk. It has the same data structure as an `IDAT` chunk, except a sequence number is appended in the beginning.

There may be multiple `fdAt` chunks for any one frame; if so, they shall appear consecutively with no other intervening chunks. The compressed datastream is then the concatenation of the contents of the data fields of all the `fdAt` chunks.

Format:

    byte
    0   sequence_number       (unsigned int)   Sequence number of the animation chunk, starting from 0
    4   frame_data            X bytes          Frame data for this frame

Each frame inherits every property except the width and the height specified by any critical or ancillary chunks before the first IDAT in the file.

Revisions to this Specification

From 0.1

  • Renamed chunks to `anIm` and `frAm` to comply with chunk naming conventions in the PNG spec.
  • Added a more detailed explanation of APNG structure in Section 2.
  • Added information for png interaction with other chunks in section 3.2.
  • Changed `frAm` chunk offsets and delay into signed integers.

From 0.2

  • Changed `frAm` chunk to `afRa` to avoid conflict with MNG `FRAM` chunk.
  • Changed format: instead of sequences of IHDR..IDAT..IEND, frames other than frame 0 are stored in `afRa` chunks.
  • Added `start_frame` to `anIm` to indicate which frame the animation should start on.
  • Removed `num_frames` from `anIm` chunk

From 0.3

  • Added `aCTL`, `fdAT`, `fcTL` chunk descriptions as per the latest png-list discussion
  • Added section 4, "Interactions with other PNG chunks"; described global and local palettes and

transparency

  • Changed `oFFs` chunk section to refer to more general chunks
  • Updated `aDAT` description to indicate that all frames must either be in a single chunk, or that the first

chunk must have empty data.

  • Added notice that each frame's region (x,y,width,height) must lie completely within the parent PNG canvas
  • Fixed dispose_op description (after, not before)
  • Changed dipose_op to render_op; added disposal description; added BLEND flag
  • Changed delay_time to a delay numerator and denominator, for specifying delays that don't into integer

numbers of milliseconds.

  • Added note to clarify that palette animation is not supported.
  • Removed start_frame from aCTL; require fcTL for frame 0; added SKIP_FRAME fCTL flag.

From 0.4

  • Reintroduced num_frames into aCTL
  • Moved sequence_number from aDAT into fCTL
  • Changed contents of aDAT to fCTL+IDATs+fEND
  • Added clarifications on what's allowed and what isn't
  • Renamed aCTL to acTL, fCTL to fcTL, aDAT to fdAT and fEND to feND to comply with the PNG spec chunk naming requirements

From 0.5

  • Added the IHDR and PLTE CRCs to the acTl chunk
  • The acTL fcTL and adAT are now copy safe, renamed them to acTl, fcTl and adAt

From .6

  • The fdAt chunk is no longer a container for other chunks, but rather a replacement for an IDAT chunk
  • Added a sequence number field to fdAt
  • Reintroduced the width and height fields in fcTl

Test Encoder and Sample Images

Sample images are available from the APNG implementation page at http://littlesvr.ca/apng/

A. References

[pngspec]: http://www.w3.org/TR/PNG/ "Portable Network Graphics (PNG) Specification (Second Edition)"

[pngext]: http://www.libpng.org/pub/png/spec/register/pngext-1.2.0-pdg.html "Extensions to the PNG Specification, Version 1.2.0"

[gifspec]: http://www.w3.org/Graphics/GIF/spec-gif89a.txt "Graphics Interchange Format 89a"