The critical chunks describe the image and hold its pixels: IHDR first, PLTE for a
palette, IDAT for the image data and IEND last. A reader that understands these four
can show the picture, even if it skips every other chunk.
IHDR, the image header
The first chunk, 13 bytes of data.
| Offset | Size | Field | Meaning |
|---|---|---|---|
| 0 | 4 | Width | Pixels across, 1 to 231 − 1. |
| 4 | 4 | Height | Pixels down, 1 to 231 − 1. |
| 8 | 1 | Bit depth | Bits per sample or per palette index; see the table below. |
| 9 | 1 | Colour type | Which samples a pixel holds; see the table below. |
| 10 | 1 | Compression method | Always 0: zlib Deflate. |
| 11 | 1 | Filter method | Always 0: adaptive filtering, five filter types. |
| 12 | 1 | Interlace method | 0 none; 1 Adam7. |
Colour types and bit depths
The colour type is built from three flags that add up: 1 a palette is used, 2 colour, 4 an alpha channel. Only the combinations below are allowed.
| Type | Image | Samples | Allowed bit depths |
|---|---|---|---|
| 0 | Greyscale | Grey | 1, 2, 4, 8, 16 |
| 2 | Truecolour | Red, green, blue | 8, 16 |
| 3 | Indexed colour | A palette index; PLTE is required | 1, 2, 4, 8 |
| 4 | Greyscale with alpha | Grey, alpha | 8, 16 |
| 6 | Truecolour with alpha | Red, green, blue, alpha | 8, 16 |
Samples and scanlines
Pixels are stored row by row, top first and left to right, each row starting with a filter byte (see filters). Within a pixel the samples come in the order the table above gives, so RGBA is red, green, blue, alpha.
Below eight bits a sample does not fill a byte: pixels are packed into bytes starting from the most significant bit, and a row is padded with zeros to a whole number of bytes. A 16-bit sample is stored big-endian. Any bits at the end of a byte that a row does not use are ignored.
A row of width w takes ⌈w × b ÷ 8⌉ + 1 bytes, where
b is the number of bits a pixel takes (the bit depth times the number of samples), and the
extra byte is the filter type.
Adam7 interlacing
With interlace method 1, the image is stored as seven reduced images, each a separate set of rows that starts afresh with no row above it. A pass with no columns or no rows has no bytes at all, not even filter bytes. The table gives each pass’s starting column and row, and the step between its pixels.
| Pass | Start column | Start row | Column step | Row step |
|---|---|---|---|---|
| 1 | 0 | 0 | 8 | 8 |
| 2 | 4 | 0 | 8 | 8 |
| 3 | 0 | 4 | 4 | 8 |
| 4 | 2 | 0 | 4 | 4 |
| 5 | 0 | 2 | 2 | 4 |
| 6 | 1 | 0 | 2 | 2 |
| 7 | 0 | 1 | 1 | 2 |
The same passes cover the whole image, repeating every eight pixels across and down. Each pixel belongs to exactly one pass, as this pattern of an 8 × 8 tile shows:
1 6 4 6 2 6 4 6
7 7 7 7 7 7 7 7
5 6 5 6 5 6 5 6
7 7 7 7 7 7 7 7
3 6 4 6 3 6 4 6
7 7 7 7 7 7 7 7
5 6 5 6 5 6 5 6
7 7 7 7 7 7 7 7
PLTE, the palette
One to 256 entries of three bytes each (red, green, blue), always eight bits a sample whatever the image’s bit depth. The chunk’s length must be divisible by 3. For indexed colour (type 3) the palette is required, and may not have more entries than the bit depth can index. For greyscale (types 0 and 4) it may not appear. For truecolour (types 2 and 6) it is optional, and is only a suggestion of colours for a display that has few.
A palette index in the image data that is past the end of the palette is an error.
| Offset | Size | Field |
|---|---|---|
| 0 | 1 | Entry 0: red |
| 1 | 1 | Entry 0: green |
| 2 | 1 | Entry 0: blue |
| 3 … | 3 each | Further entries |
IDAT, the image data
One or more consecutive chunks that hold the filtered scanlines as a single zlib stream, split across them wherever the encoder chose (see the zlib stream). A chunk’s boundary means nothing to the compressed data.
IEND, the end of the image
The last chunk, with no data. It marks the end of the datastream, so a reader knows the file has not been cut short. Any bytes after it are not part of the PNG.