Last modified: Thu Jul 23 14:48:27 UTC+0200 2026 © A. Tarpai
PNG file structure
8-byte
SIGNATURE
| % P N G . . . . | .. CHUNK .. .. | .. CHUNK .. .. .. .. .. .. | .. CHUNK .. .. .. .. .. .. .. | .. CHUNK .. |
The chunks
Each CHUNK consists of four parts (the boxes are bytes):
+---+---+---+---+ +---+---+---+---+ +---+--- - - --+---+---+---+---+ +---+---+---+---+
| | | | | | | | | | | | | | | | |
+---+---+---+---+ +---+---+---+---+ +---+--- - - --+---+---+---+---+ +---+---+---+---+
Length Chunk Type Chunk Data (Length bytes) CRC
"Critical chunks (must appear in this order, except PLTE is optional):
Name Multiple Ordering constraints
IHDR No Must be first
PLTE No Before IDAT (optional)
IDAT Yes Multiple IDATs must be consecutive
IEND No Must be last"
This decoder supports only critical chunks (the others are quite client-dependent) with multiple IDAT:
SIG..IHDR...PLTE........IDAT..................IDAT...........................IDAT..........IEND
Traversing the chunk structure
Read SIG
{
Length <- GetDWord
Type <- GetDWord
seek(Length)
CRC <- GetDWord
}
until (Type == IEND)
The IDAT chunk(s)
Concatenation of all IDAT contains a zlib-compressed bit-stream using the Deflate algorithm. The first
"There can be multiple IDAT chunks; if so, they must appear consecutively with no other intervening chunks." (http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html)
IDAT .. .. .. .. .. .. .. .. .. .. .. IDAT .. .. .. .. .. .. .. IDAT .. .. .. .. ..
|
|
| NextByte
|
+-------- inflate --------+
| |
| | ------> uncompressed data bytes
| |
| |
+-------------------------+
Notes.
I wanted to implement 'transparently' for inflate() to get the next byte from the compressed datastream. It simply calls back a function (NextByte) set by the client (run-time binding, OS dev habits..). Again, allocated buffers vs. speed to 'concatenate' or not the IDAT chunks.
- Inflate v1: output buffer is the Window buffer (full deflate buffer) Good for small png-s.
- Inflate v2: NO output buffer: call returns one byte of inflated data. 32K Window buffer. Good for big png-s.
Concatenation of all IDAT contains a zlib-compressed bit-stream (lsb-first)
zlib-block......zlib-block......zlib-block......zlib-block* (*final zlib-block has first bit set, bfinal)
zlib-block:
HEAD HT DEFINITIONS COMPRESSED DATA EOD
\____/\_______________/\_____________________________________/\___/
[0][10][10010][10010][1110][010][110][000]...[001][01][01001][1110][010]...........[0001][010][1110][10010]....[10][......COMPRESSED DATA......][EOD]
\_/\__/\_____/\_____/\____/\_____________________/\________________________________/\______________________________/\__________________________/\___/
bfinal btype hlit hdist hclen len-of-len len-of-literals/ptr-lenghts len-of-distance
|
/ \ / \ / \ |
2 x x x x x |
/ \ / \ / \ / \ / \ ----- literal
4 x x x 4 7 x x ----- length/dist
/\ /\ /\ /\ /\ ----- EOD
..we build 3 Huffman trees..