Difference between revisions of "APNG Specification"

From MozillaWiki
Jump to: navigation, search
(Describe the treatment of the placeholder image consistently)
Line 16: Line 16:
 
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 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.
+
APNG is backwards-compatible with PNG; any PNG decoder should be able to ignore the APNG-specific chunks and display a single image.
  
 
= Structure =
 
= 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.
+
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 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 placeholder image defines the boundaries of the entire animation; hence, the placeholder image should be appropriately padded with fully transparent pixels if extra space will be needed for later frames.
  
 
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.
 
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 may also appear before `IDAT`, providing frame information for the first frame encoded in the PNG stream's `IDAT` chunks, known as frame 0. If there is no fcTL chunk before IDAT, then frame 0 is intialized to RGBA(0,0,0,0) and the IDAT chunks are not used.
+
The placeholder image may be treated as the first frame of the animation by the presence of a single `fcTL` chunk before `IDAT`. Otherwise, the placeholder image is not part of the animation, and the output buffer must be completely initialized to RGBA(0,0,0,0) at the beginning of each iteration.
  
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.
+
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 limited to the range 0 to (2^31)-1; an "unsigned short" shall be a 16-bit unsigned integer in network byte order; a "byte" shall be an 8-bit unsigned integer.
+
== Terminology ==
 +
 
 +
The "placeholder image" is the image described by the standard `IDAT` chunks, and is the image that displayed by decoders that do not support APNG.
  
== Terminology ==
+
The "canvas" is the area on the output device on which the frames are to be displayed.  The contents of the canvas are not necessarily available to the decoder.
  
The "canvas" is the area on the output device on which the images are to be written.  The contents of the canvas are not available to the decoder.
+
The "output buffer" is a pixel array with dimensions specified by the width and height parameters of the PNG IHDR chunk.  Conceptually, each frame is constructed in the output buffer before being composited onto the canvas.  The contents of the output buffer are available to the decoder.  The corner pixels of the output buffer are mapped to the corners of the canvas.
  
The "output buffer" is a pixel array with dimensions specified by the width and height parameters of the PNG IHDR chunk.  Conceptually, the images are constructed in the output buffer and then written to the canvas.  The contents of the output buffer are available to the decoder.  The corner pixels of the output buffer are mapped to the corners of the canvas.
+
For purposes of chunk descriptions, an "unsigned int" shall be a 32-bit unsigned integer in network byte order limited to the range 0 to (2^31)-1; an "unsigned short" shall be a 16-bit unsigned integer in network byte order; a "byte" shall be an 8-bit unsigned integer.
  
 
== Chunk Sequence Numbers ==
 
== Chunk Sequence Numbers ==
Line 42: Line 44:
 
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 `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 first fcTL chunk must contain sequence number 0, and the sequence numbers in the remaining fcTL and fdAT chunks must be in order, with no gaps or duplicates.
+
The first `fcTL` chunk must contain sequence number 0, and the sequence numbers in the remaining `fcTL` and `fdAT` chunks must be in order, with no gaps or duplicates.
 +
 
 +
The tables below illustrates the use of sequence numbers for images with more than one frame and more than one `fdAT` chunk.
  
The table below illustrates the use of sequence numbers for images with more than one frame and more than one `fdAT` chunk:
+
If the placeholder image is the first frame:
  
 
     Sequence number    Chunk
 
     Sequence number    Chunk
     0                  `fcTL` describing frame 0
+
     0                  `fcTL` first frame (before `IDAT`)
     1                  `fcTL` describing frame 1
+
     1                  `fcTL` second frame
     2                  first `fdAT` for frame 1
+
     2                  first `fdAT` for second frame
     3                  second `fdAT` for frame 1
+
     3                  second `fdAT` for second frame
 
     ....
 
     ....
  
or, when frame 0 is implicitly a transparent black frame:
+
If the placeholder image is not part of the animation:
  
 
     Sequence number    Chunk
 
     Sequence number    Chunk
     0                  fcTL describing frame 1
+
     0                  `fcTL` first frame
     1                  first fdAT for frame 1
+
     1                  first `fdAT` for first frame
     2                  second fdAT for frame 1
+
     2                  second `fdAT` for first frame
 
     ....
 
     ....
  
APNG viewers must abandon the APNG chunks in a datastream with out-of-order APNG chunks and display frame 0 instead. APNG-aware PNG editors should restore them to correct order using the sequence numbers.
+
APNG viewers must abandon the APNG chunks in a datastream with out-of-order APNG chunks and display the placeholder image. APNG-aware PNG editors should restore them to correct order using the sequence numbers.
  
 
== `acTL`: The Animation Control Chunk ==
 
== `acTL`: The Animation Control Chunk ==
Line 73: Line 77:
 
       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.
  
`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_frames` indicates the total number of frames in the animation. This should  equal the number of `fcTL` 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_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 frame at the end of the last iteration.
  
 
== `fcTL`: The Frame Control Chunk ==
 
== `fcTL`: The Frame Control Chunk ==
Line 81: Line 85:
 
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:
 
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, if the fcTL chunk is present it must appear before the first `IDAT` chunk. Position relative to the `acTL` chunk is not specified.
+
* For the placeholder image, if a `fcTL` chunk is present it 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 after the `IDAT` chunks from the first frame and before the fdAT chunks for the second frame.
+
* For the first non-placeholder frame (which may be either the first or second frame), the `fcTL` chunk must appear after all `IDAT` chunks and before the `fdAT` chunks for the frame.
* For any subsequent frames, the `fcTL` chunk for the frame N must appear after the `fdAT` chunks from the frame N-1 and before the fdAT chunks for the frame N.
+
* For all subsequent frames, the `fcTL` chunk for frame N must appear after the `fdAT` chunks from frame N-1 and before the `fdAT` chunks for frame N.
* Other ancillary chunks are allowed to appear among the APNG chunks, including between fdAT chunks.
+
* Other ancillary chunks are allowed to appear among the APNG chunks, including between `fdAT` chunks.
  
The fcTL chunk is mandatory for every frame except for frame 0. When it is present for frame 0, decoders must render frame 0 from the data in the IDAT chunks.  When it is not present for frame 0, frame 0 is a transparent black frame (all pixels are RGBA(0,0,0,0)) and the IDAT chunks are ignored.  More than one fcTL chunk per frame is not allowed.
+
Exactly one `fcTL` chunk is required for each frame.
  
 
Format:
 
Format:
Line 101: Line 105:
 
     25    blend_op              (byte)          Type of frame area rendering for this frame  
 
     25    blend_op              (byte)          Type of frame area rendering for 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` chunk.
+
The frame must be rendered within the region defined by `x_offset`, `y_offset`, `width`, and `height`. The offsets must be non-negative, the dimensions must be positive, and the region may not fall outside of the placeholder image:
 
 
The width and height must be greater than zero and must not 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. No part of the region may fall outside the area defined by frame 0.
+
    `x_offset` >= 0
 +
    `y_offset` >= 0
 +
    `width`    > 0
 +
    `height`  > 0
 +
    `x_offset` + `width`  <= `IHDR` width
 +
    `y_offset` + `height` <= `IHDR` height
  
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.
  
 
Valid values for `dispose_op` are:
 
Valid values for `dispose_op` are:
Line 116: Line 123:
 
     2          APNG_DISPOSE_OP_PREVIOUS
 
     2          APNG_DISPOSE_OP_PREVIOUS
  
* APNG_DISPOSE_OP_NONE: no disposal is done on this frame before rendering the next; its contents are left on the output buffer.  This is the default.
+
* APNG_DISPOSE_OP_NONE: no disposal is done on this frame before rendering the next; its contents are left on the output buffer.
* APNG_DISPOSE_OP_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_DISPOSE_OP_BACKGROUND: the frame's region of the output buffer 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_DISPOSE_OP_PREVIOUS: the frame's region is to be reverted to the previous contents.
+
* APNG_DISPOSE_OP_PREVIOUS: the frame's region of the output buffer is to be reverted to the previous contents.
 +
 
 +
`blend_op` specifies whether the frame is to be alpha blended into the current output buffer content, or whether it should completely replace its region in the output buffer.
  
`blend_op` specifies whether the frame is to be alpha blended into the current output buffer content, or whether it should completely replace its region in the output buffer. Valid `blend_op` values are:
+
Valid values for `blend_op` are:
  
 
     value
 
     value
Line 130: Line 139:
 
APNG_BLEND_OP_OVER 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.
 
APNG_BLEND_OP_OVER 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.
  
`blend_op` must be APNG_BLEND_OP_SOURCE for frame 0.
+
The `fcTL` chunk corresponding to the placeholder image has additional restrictions, if it exists:
 +
* The `x_offset` and `y_offset` fields must be 0.
 +
* The `width` and `height` fields must equal the corresponding fields from the `IHDR` chunk.
 +
* `blend_op` must be APNG_BLEND_OP_SOURCE
 +
* `dispose_op` must not be APNG_DISPOSE_OP_PREVIOUS
 +
 
 +
As noted earlier, if a `fcTL` chunk does not precede `IDAT`, the placeholder image is not part of the animation, and the output buffer must be completely initialized to RGBA(0,0,0,0) at the beginning of each iteration.
 +
 
 +
Together these requirements serve to ensure that each iteration of the animation will be identical.
  
 
== `fdAT`: The Frame Data Chunk ==
 
== `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.
+
The `fdAT` chunk has the same purpose as an `IDAT` chunk. It has the same structure as an `IDAT` chunk, except preceded by a sequence number.
  
Each frame must contain at least one fdAT chunk. The compressed datastream is then the concatenation of the contents of the data fields of all the fdAT chunks within a frame.  When decompressed, the datastream is a complete PNG image, including the filter byte at the beginning of each scanline. It utilizes the same bit depth, color type, compression method, filter method, interlace method, and palette (if any) as the main image.
+
Each frame must contain at least one `fdAT` chunk. The compressed datastream is then the concatenation of the contents of the data fields of all the `fdAT` chunks within a frame.  When decompressed, the datastream is a complete PNG image, including the filter byte at the beginning of each scanline. It utilizes the same bit depth, color type, compression method, filter method, interlace method, and palette (if any) as the placeholder image.
  
 
Format:
 
Format:
Line 144: Line 161:
 
     4    frame_data            X bytes          Frame data for this frame
 
     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.
+
Each frame inherits every property specified by any critical or ancillary chunks before the first `IDAT` in the file, except the width and height, which come from the `fcTL` chunk.
  
If the PNG oFFs chunk is present, it supplies offsets of the canvas that are in addition to the frame's "x_offset" and "y_offset".
+
If the PNG `oFFs` chunk is present, it supplies offsets of the canvas that are in addition to the frame's `x_offset` and `y_offset`.
  
If the PNG pHYs chunk is present, the APNG images and their "x_offset" and "y_offset" values must be scaled in the same way as the main image. Conceptually, such scaling occurs while mapping the output buffer onto the canvas.
+
If the PNG `pHYs` chunk is present, the APNG images and their `x_offset` and `y_offset` values must be scaled in the same way as the main image. Conceptually, such scaling occurs while mapping the output buffer onto the canvas.
  
 
= Revisions to this Specification =
 
= Revisions to this Specification =

Revision as of 01:56, 23 March 2007

APNG 0.10 [DRAFT]

Authors:

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

Big Important Note

We are currently waiting on the PNG group to approve our use of our chunks as public chunks (i.e. 2nd letter is capitalized.) Once they have approved the chunk names only the public chunk names will be valid and APNGs created before that point will become invalid.

acTL -> aCTL, fcTL -> fCTL, fdAT -> fDAT

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 ignore the APNG-specific chunks and display a single image.

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 size of the placeholder image defines the boundaries of the entire animation; hence, the placeholder image should be appropriately padded with fully transparent pixels if extra space will be needed for later frames.

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.

The placeholder image may be treated as the first frame of the animation by the presence of a single `fcTL` chunk before `IDAT`. Otherwise, the placeholder image is not part of the animation, and the output buffer must be completely initialized to RGBA(0,0,0,0) at the beginning of each iteration.

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.

Terminology

The "placeholder image" is the image described by the standard `IDAT` chunks, and is the image that displayed by decoders that do not support APNG.

The "canvas" is the area on the output device on which the frames are to be displayed. The contents of the canvas are not necessarily available to the decoder.

The "output buffer" is a pixel array with dimensions specified by the width and height parameters of the PNG IHDR chunk. Conceptually, each frame is constructed in the output buffer before being composited onto the canvas. The contents of the output buffer are available to the decoder. The corner pixels of the output buffer are mapped to the corners of the canvas.

For purposes of chunk descriptions, an "unsigned int" shall be a 32-bit unsigned integer in network byte order limited to the range 0 to (2^31)-1; an "unsigned short" shall be a 16-bit unsigned integer in network byte order; a "byte" shall be an 8-bit unsigned integer.

Chunk 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 first `fcTL` chunk must contain sequence number 0, and the sequence numbers in the remaining `fcTL` and `fdAT` chunks must be in order, with no gaps or duplicates.

The tables below illustrates the use of sequence numbers for images with more than one frame and more than one `fdAT` chunk.

If the placeholder image is the first frame:

    Sequence number    Chunk
    0                  `fcTL` first frame (before `IDAT`)
    1                  `fcTL` second frame
    2                  first `fdAT` for second frame
    3                  second `fdAT` for second frame
    ....

If the placeholder image is not part of the animation:

    Sequence number    Chunk
    0                  `fcTL` first frame
    1                  first `fdAT` for first frame
    2                  second `fdAT` for first frame
    ....

APNG viewers must abandon the APNG chunks in a datastream with out-of-order APNG chunks and display the placeholder image. APNG-aware PNG editors should restore them to correct order using the sequence numbers.

`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.

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.

`num_frames` indicates the total number of frames in the animation. This should equal the number of `fcTL` 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_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 frame at the end of the last iteration.

`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 placeholder image, if a `fcTL` chunk is present it must appear before the first `IDAT` chunk. Position relative to the `acTL` chunk is not specified.
  • For the first non-placeholder frame (which may be either the first or second frame), the `fcTL` chunk must appear after all `IDAT` chunks and before the `fdAT` chunks for the frame.
  • For all subsequent frames, the `fcTL` chunk for frame N must appear after the `fdAT` chunks from frame N-1 and before the `fdAT` chunks for frame N.
  • Other ancillary chunks are allowed to appear among the APNG chunks, including between `fdAT` chunks.

Exactly one `fcTL` chunk is required for each frame.

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    dispose_op            (byte)           Type of frame area disposal to be done after rendering this frame
   25    blend_op              (byte)           Type of frame area rendering for this frame 

The frame must be rendered within the region defined by `x_offset`, `y_offset`, `width`, and `height`. The offsets must be non-negative, the dimensions must be positive, and the region may not fall outside of the placeholder image:

   `x_offset` >= 0
   `y_offset` >= 0
   `width`    > 0
   `height`   > 0
   `x_offset` + `width`  <= `IHDR` width
   `y_offset` + `height` <= `IHDR` height

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.

Valid values for `dispose_op` are:

   value
   0           APNG_DISPOSE_OP_NONE
   1           APNG_DISPOSE_OP_BACKGROUND
   2           APNG_DISPOSE_OP_PREVIOUS
  • APNG_DISPOSE_OP_NONE: no disposal is done on this frame before rendering the next; its contents are left on the output buffer.
  • APNG_DISPOSE_OP_BACKGROUND: the frame's region of the output buffer 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_DISPOSE_OP_PREVIOUS: the frame's region of the output buffer is to be reverted to the previous contents.

`blend_op` specifies whether the frame is to be alpha blended into the current output buffer content, or whether it should completely replace its region in the output buffer.

Valid values for `blend_op` are:

   value
   0       APNG_BLEND_OP_SOURCE
   1       APNG_BLEND_OP_OVER

If `blend_op` is APNG_BLEND_OP_SOURCE all color components of the frame, including alpha, overwrite the current contents of the frame's output buffer region. If `blend_op` is APNG_BLEND_OP_OVER the frame should be composited onto the output buffer based on its alpha, using a simple OVER operation as described in the "Alpha Channel Processing" section of the PNG specification [PNG-1.2]. Note that Variation 2 of the sample code is applicable.

APNG_BLEND_OP_OVER 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.

The `fcTL` chunk corresponding to the placeholder image has additional restrictions, if it exists:

  • The `x_offset` and `y_offset` fields must be 0.
  • The `width` and `height` fields must equal the corresponding fields from the `IHDR` chunk.
  • `blend_op` must be APNG_BLEND_OP_SOURCE
  • `dispose_op` must not be APNG_DISPOSE_OP_PREVIOUS

As noted earlier, if a `fcTL` chunk does not precede `IDAT`, the placeholder image is not part of the animation, and the output buffer must be completely initialized to RGBA(0,0,0,0) at the beginning of each iteration.

Together these requirements serve to ensure that each iteration of the animation will be identical.

`fdAT`: The Frame Data Chunk

The `fdAT` chunk has the same purpose as an `IDAT` chunk. It has the same structure as an `IDAT` chunk, except preceded by a sequence number.

Each frame must contain at least one `fdAT` chunk. The compressed datastream is then the concatenation of the contents of the data fields of all the `fdAT` chunks within a frame. When decompressed, the datastream is a complete PNG image, including the filter byte at the beginning of each scanline. It utilizes the same bit depth, color type, compression method, filter method, interlace method, and palette (if any) as the placeholder image.

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 specified by any critical or ancillary chunks before the first `IDAT` in the file, except the width and height, which come from the `fcTL` chunk.

If the PNG `oFFs` chunk is present, it supplies offsets of the canvas that are in addition to the frame's `x_offset` and `y_offset`.

If the PNG `pHYs` chunk is present, the APNG images and their `x_offset` and `y_offset` values must be scaled in the same way as the main image. Conceptually, such scaling occurs while mapping the output buffer onto the canvas.

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 0.6

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

From 0.7

  • Removed 'hidden' flag, instead only the first frame can be hidden and it is signaled with a missing fcTl
  • IDAT, fcTl and fdAt are no longer required to have no other chunks in between them

From 0.8

  • Removed CRCs for IHDR and PLTE from acTl
  • The acTL fcTL and adAT are now not copy safe, renamed them to acTL, fcTL and adAT

From 0.9

  • Split render_op into dispose_op and blend_op

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"