The PNG Guide is an eBook based on Greg Roelofs' book, originally published by O'Reilly.

MNG Structure

So that's some of what MNG can do; now let's take a closer look at what the format looks like and how it works. To begin with, MNG is chunk-based, just like PNG. It has an 8-byte signature similar to PNG's, but it differs in the first two bytes, as shown in Table 12-1.

Table 12-1. MNG Signature Bytes

ASCII Interpretation
138 A byte with its most significant bit set (``8-bit character'')
77 M
78 N
71 G
13 Carriage-return (CR) character, a.k.a. CTRL-M or ^M
10 Line-feed (LF) character, a.k.a. CTRL-J or ^J
26 CTRL-Z or ^Z
10 Line-feed (LF) character, a.k.a. CTRL-J or ^J

So while a PNG-supporting application could be trivially modified to identify and parse a MNG stream,[92] there is no danger that an older PNG application might mistake a MNG stream for a PNG image. Since the file extensions differ as well (.mng instead of .png), ordinary users are unlikely to confuse images with animations. The only cases in which they might do so are when an allowed component type (e.g., a PNG or a JNG) is renamed with a .mng extension; such files are considered legal MNGs.

[92] Actually making sense of the MNG stream would require considerably more work, of course.

With the exception of such renamed image formats, all MNG streams begin with the MNG signature and MHDR chunk, and they all end with the MEND chunk. The latter, like PNG's IEND, is an empty chunk that simply indicates the end of the stream. MHDR, however, contains seven fields, all unsigned 32-bit integers: frame width, frame height, ticks per second, number of layers, number of frames, total play time, and the complexity (or simplicity) profile.

Frame width and height are just what they sound like: they give the overall size of the displayable region in pixels. A MNG stream that contains no visible images--say, a collection of palettes--should have its frame dimensions set to zero.

The ticks-per-second value is essentially a scale factor for time-related fields in other chunks, including the frame rate. In the absence of any other timing information, animations are recommended to be displayed at a rate of one frame per tick. For single-frame MNGs, the ticks-per-second value is recommended to be 0, providing decoders with an easy way to detect non-animations. Conversely, if the value is 0 for a multiframe MNG, decoders are required to display only the first frame unless the user specifically intervenes in some way.

``Number of layers'' refers to the total number of displayable images in the MNG stream, including the background. This may be many more than the number of frames, since a single frame often consists of multiple images composited (or layered) on top of one another. Some of the layers may be empty if they lie completely outside the clipping boundaries. The layer count is purely advisory; if it is 0, the count is considered unspecified. At the other end of the spectrum, a value of 231-1 (2,147,483,647) is considered infinite.

The frame-count and play-time values are also basically what they sound like: on an ideal computer (i.e., one with infinite processing speed), they respectively indicate the number of frames that correspond to distinct instants of time[93] and the overall duration of the complete animation. As with the layer count, these values are advisory; 0 and 231-1 correspond to ``unspecified'' and ``infinite,'' respectively.

[93] MNG's concept of frames and subframes allows one to speak of two or more distinct frames with precisely zero delay between them, but these are considered just one frame for the purpose of counting the total number of frames in the stream.

Finally, MHDR's complexity profile provides some indication of the level of complexity in the stream, in order to allow simple decoders to give up immediately if the MNG file contains features they are unable to render. The profile field is also advisory; a value of zero is allowed and indicates that the complexity level is unspecified. But a nonzero value indicates that the encoder has provided information about the presence or absence of JPEG (JNG) chunks, transparency, or complex MNG features. The latter category includes most of the animation features mentioned earlier, including looping and object manipulation (i.e., sprites). All possible combinations of the three categories are encoded in the lower 4 bits of the field as odd values only--all even values other than zero are invalid, which means the lowest bit is always set if the profile contains any useful information. The remaining bits of the 2 lower bytes are reserved for public expansion, and all but the most significant bit of the 2 upper bytes are available for private or experimental use. The topmost bit must be zero.

Note that any unset (0) bit guarantees that the corresponding feature is not present or the MNG stream is invalid. A set bit, on the other hand, does not automatically guarantee that the feature is included, but encoders should be as accurate as possible to avoid causing simple decoders to reject MNGs unnecessarily.

The stuff that goes between the MHDR and MEND chunks can be divided into a few basic categories:

  • Image-defining chunks
  • Image-displaying chunks
  • Control chunks
  • Ancillary (optional) chunks

Note the distinction between defining an image and displaying it. This will make sense in the context of a composite frame made up of many subimages. Alternatively, consider a sprite-based animation composed of several sprite ``poses'' that should be read into memory (i.e., defined) as part of the animation's initialization procedure. The sprite frames may not actually be used until much later, perhaps only in response to user input.

Last Update: 2010-Nov-26