File: png-apng-proposal-20070309 This proposal is derived from the proposal posted on March 6, 2007, at bugzilla.mozilla.org, bug #257263, with editorial changes mentioned there in comments 67 and 68. It is proposed to register animated PNG (APNG) chunks: aCTl, fCTl, and fDAt. In this proposal, the new chunk names are shown in public form (second letter uppercase). Until the proposal is approved, the private form (second letter lowercase) must be used in any test implementations. It is proposed to document Animated PNG (APNG) in the Extensions to the PNG 1.2 Specification, Version 1.3.0 A. (change version to 1.4.0) B. Add to the chunk ordering table: aCTl No After PLTE, before IDAT fCTl Yes Before and after IDAT fDAt Yes After IDAT C. Add paragraph 4 and renumber subsequent paragraphs 4. APNG Animation Chunks Overview APNG is an extension of the PNG format, adding support for animated images. It is intended to be a replacement for simple animated images that have traditionally used the GIF [GIF-SPEC] 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, version 1.2 [PNG-1.2], 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 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 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 .... If a decoder detects that the chunks are in the wrong order it must either treat the condition as an error or correct the order using the sequence numbers. 4.1. aCTl 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 3 (indexed color) 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 3 (indexed color), and 0 otherwise. If the two checksums do not match, any further frames must be discarded. 4.2. fCTl 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 must be greater than zero and 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. No part of the region may fall outside the canvas defined by frame 0. 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 0. Valid values for "dispose_op" are: value bit 1 0 APNG_RENDER_OP_DISPOSE_NONE 2 1 APNG_RENDER_OP_DISPOSE_BACKGROUND 4 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 0, all color components of the frame, including alpha, overwrite the current contents of the frame's canvas region. If the APNG_RENDER_OP_BLEND_FLAG is not 0 the frame should be composited onto the canvas 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_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 not 0, then the decoder should not render the current frame as part of the animation. Though this flag can be set (not 0) 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 is explicitly disabled by the user, the viewer should display frame 0 even if AP_RENDER_OP_SKIP_FRAME is not 0 on frame 0. This provides content authors with a means to provide a still image to be used in lieu of the full animation. 4.3. fDAt 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. Each frame must contain at least one fDAt chunk. 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 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. 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. 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. Test Encoder/Decoder and Sample Images A test implementation in Mozilla is available at https://bugzilla.mozilla.org/show_bug.cgi?id=257197 Sample images are available from the APNG implementation page at http://littlesvr.ca/apng/ D. Add to the Appendix: Revision History * 30 April 2007 (version 1.4.0): * Added the aCTl, fCTl, and fDAt animation chunks. D. Add to the References [GIF-SPEC] "Graphics Interchange Format 89a" available at http://www.w3.org/Graphics/GIF/spec-gif89a.txt E. Add to the Credits * Stuart Parmenter, pavlov@pavlov.net * Andrew Smith, asmith15@learn.senecac.on.ca * Vladimir Vukicevic, vladimir@pobox.com