How is a PNG file built?

How is a PNG file built. Find here an answer more synthetic than RFC 2083 focusing on the mandatory aspects to read and write PNG files.

A word on PNG

PNG stands for Portable Network Graphics. This is an image file format described in the RFC 2083 document which this post is largely based on. Any software writing or reading PNG files must implement the mandatory aspects of this RFC and can implement the non-mandatory ones. This post focuses on the question “How is a PNG file built?”.

General structure of a PNG file

To get how a PNG file is built, here is the general structure:

  • Start of the file: PNG header signature on 8 bytes: decimal: 137 80 78 71 13 10 26 10 hexadecimal: 0x89 0x50 0x4E 0x47 0x0D 0x0A 0x1A 0x0A
  • Chunks

PNG chunks

PNG chunks are portions of data organized as follows:

Field nameField length in bytesComment
Length of data field4Can be 0
Chunk type4In ASCII
DataLength of data field
CRC4See below

CRC as ISO 3309 on fields Chunk type and Data with polynomial x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 .

PNG chunk type name conventions

Property bits of the chunk type field:

PropertyBit of the chunk type fieldWhat if 0What if 1
AncillaryByte 1 bit 5Critical
(ex: IHDR)
(ex: tIME)
PrivateByte 2 bit 5Public
(PNG spec)
ReservedByte 3 bit 5Should be 0
Safe to copyByte 4 bit 5Not safe to copy
(0 for critical)
Safe to copy
PNG chunk types

Critical chunks in this order:

ChunkNameMultiOrder constraints
IHDRImage headerNoFirst
PLTEPaletteNoMandatory for color type 3
(color palette)
Optional for color types 2 and 4
IDATImage dataYesMultiple IDATs must be consecutive
IENDImage trailerNoLast with empty data field

Ancillary chunks:

ChunkNameMultiOrder constraints
cHRMPrimary chromaticities
and white point
NoBefore PLTE and IDAT
gAMAImage gammaNoBefore PLTE and IDAT
sBITSignificant bitsNoBefore PLTE and IDAT
bKGDBackground colorNoAfter PLTE; before IDAT
hISTImage histogramNoAfter PLTE; before IDAT
tRNSTransparencyNoAfter PLTE; before IDAT
pHYsPhysical pixel dimensionsNoAfter PLTE; before IDAT
tIMEImage last-modification timeNoNone
tEXtTextual dataYesNone
zTXtCompressed textual dataYesNone

Note that the PNG format supports that encoders write additional unrecognized public or private chunks. So that, a reader needs to be able to read them without errors.

PNG chunk IHDR image header

IHDR image header PNG chunk is made of the following fields:

FieldSize in bytesPossible values
Width4Pixels (> 0)
Height4Pixels (> 0)
Bit depth11, 2, 4, 8, 16
depends on color type
Color type10, 2, 3, 4, 6
Compression method10 for deflate/inflate
Filter method10 for adaptive filtering
Interlace method10 for no interlace
1 for ADAM7
Color type

The color type is the sum of 3 variables:

  • 1 if palette is used
  • 2 if color is used
  • 4 if alpha channel (opacity/transparency) is used

Note that palette use is only possible with color and without alpha channel. Therefore, color type can only take the values of 0, 2, 3, 4, and 6.

Bit depth

The bit depth is the number of bits per sample or per palette index. The differences between the sample and the pixel are that a pixel is represented by two samples in case of alpha channel and that the sample bit depth is always 8 in case of palette. Possible values for the bit depth are powers of 2 from 1 to 16: 1, 2, 4, 8, 16. Though, possible values depend on the color type:

Color typeAllowed bit depthsPixel description
0 (grayscale)1, 2, 4, 8, 16
grayscale sample
2 (color)8, 16
RGB sample
3 (palette + color)1, 2, 4, 8
Palette index
(requires PLTE chunk)
4 (grayscale + alpha)8, 16
grayscale sample
+ alpha sample
6 (color + alpha)8, 16
RGB sample
+ alpha sample
Compression method

The deflate/inflate compression method is implemented by the zlib library. This is the same algorithm as the one used for the gz file format.

Adaptive filter method

The adaptive filter method which purpose is to prepare the data with less complexity for the deflate compression allows 5 filter types encoded at the beginning of the IDAT scanlines:

1st byte
of scanline
1Subbyte(x) += byte(x-bpp) % 256
2Upbyte(x) += byte(prior(x)) % 256
3Averagebyte(x) += floor((byte(x-bpp)+byte(prior(x)))/2) % 256
4Paetha = left
b = above
c = above left
p = a + b – c
paeth(a,b,c) = closest{a,b,c}(p)
byte(x) += paeth(byte(x-bpp),byte(prior(x)),byte(prior(x-bpp))) % 256

The filtering applied to bytes, not pixels. This applies to alpha channel as well. When the image is interlaced, the filtering is applied per scanline, byte, not per pixel/pixel row. Filtering is not applied when interlaced subimage is empty. Left byte is zero for 1st byte. Prior scanline is zero for 1st scanline (or interlaced pass). Filter uses decoded previous byte/scanline.

bpp = nb bytes per pixel rounded up
nb bytes per pixel = ceil(nb channels * bitdepth / 8)

ADAM7 interlacing

ADAM7 interlacing allows an improved progressive display. Please refer to progressive reading of PNG for more details on this topic. This comes usually at the cost of more space used but not always as shown in this article.
Interpretation of interlaced data is mandatory even if image is not displayed progressively
Method 0 -> no interlacing -> left to right, top to bottom
Method 1 -> ADAM7 -> image is cut in 8-by-8 pixels pattern through 7 passes as follows:

         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

Filters apply to interlaced scanlines. All the scanlines within a pass have the same number of pixels. There is a special case when the side is smaller than 5 pixels, then, some passes are empty, then there is no filter type byte for those empty passes.

PLTE the palette chunk

The palette chunk contains 1 to 256 three bytes RGB colors. The number of colors in the palette must be within what bit depth allows (2^4 = 16 colors maximum for bit depth 4 for example). This chunk is necessary for color type 3 (palette + color) and optional for color types 2 and 6 (color and color + alpha). Each pixel value is the number of the palette entry encoding its color. This means that a palette encoded PNG can represent 1 to 256 colors chosen among 2 ^ (3 * 8) = 16,777,216 possible RGB colors where 2 is the binary possibilities of bits, 3 is the number of bytes (RGB) and 8 is the number of bits for each byte.

For more details on the possibilities offered by the PNG format regarding the number of colors, please refer to Colors in PNG.

IDAT image data chunks

IDAT chunks are made of image scanlines as defined by IHDR. Each scanline starts with the filter type encoded on one byte. The compression is not done per data chunk but on the continuation of the chunks. Data chunks can be zero length.

Text chunks

Text chunks are encoded as tEXt or zTXt if compressed. They can describe arbitrary keyword-text pairs. RFC recommends ISO 8859-1 (Latin-1) encoding. Keyword is encoded on 1-79 bytes, followed by a 0x00 byte and followed by the text for the rest of the chunk data. Keywords can repeat. A PNG file can contain any number of text chunks. Here is a list of RFC recommended text keywords and their intended use:

KeywordIntended use
TitleShort (one line) title or caption for image
AuthorName of image’s creator
DescriptionDescription of image (possibly long)
CopyrightCopyright notice
Creation TimeTime of original image creation
SoftwareSoftware used to create the image
DisclaimerLegal disclaimer
WarningWarning of nature of content
SourceDevice used to create the image
CommentMiscellaneous comment; conversion from GIF comment

Note that PNG files can embed XMP in iTXt chunks with keyword “XML:com.adobe.xmp”.

Also, PNG files can contain EXIF data in eXIf chunks.

Other chunks

For the other non mandatory chunk types not described in details in this post, please refer to the section below for more readings.

Other readings on how a PNG file is built

Information technology — Computer graphics and image processing — Portable Network Graphics (PNG): Functional specification. ISO/IEC 15948:2003 (E)

PNG (Portable Network Graphics) Specification Version 1.0

PNG The Definitive Guide Paperback

Leave a comment

Thanks for your visit. I hope this post helped you understand how a PNG file is built. I would be very excited to know what you think of this explanation on how PNG files are built through the comments section below.