Current Location: Home> Latest Articles> PNG file header: pack() + file structure analysis

PNG file header: pack() + file structure analysis

M66 2025-05-28

In the field of image processing, PNG (Portable Network Graphics) is a widely used lossless compressed image format. Its file structure has clear specifications, including multiple "chunks", each containing specific image or metadata information. Understanding these structures not only helps to develop custom image processing tools, but also can be of great benefit to learning binary data operations and protocol design.

This article will manually parse the header of the PNG file through PHP's pack() and unpack() functions and analyze its structure. Although PHP is a web-based language, it also has excellent abilities in processing binary data.

1. Overview of PNG file structure

A legal PNG file must start with an 8 byte fixed signature:

 89 50 4E 47 0D 0A 1A 0A

Next is one or more blocks (Chunk), each of which consists of the following parts:

  • Length (4 bytes) – length of the data part

  • Block type (4 bytes) – such as IHDR, IDAT, IEND, etc.

  • Block data (variable)

  • CRC Verification (4 bytes)

2. Use PHP to parse PNG file headers

The following example code will read the first several bytes of a PNG file, extracting the file header and the first block (usually IHDR).

 <?php
$filename = 'https://m66.net/sample.png';

// Before reading the file 33 byte:8 bytesign + 4+4+13+4(IHDR Total block length)
$data = file_get_contents($filename, false, null, 0, 33);

if ($data === false || strlen($data) < 33) {
    die("Unable to read PNG File or file too small。");
}

// Analysis PNG sign
$signature = substr($data, 0, 8);
$expectedSignature = "\x89PNG\r\n\x1a\n";

if ($signature !== $expectedSignature) {
    die("This is not a valid one PNG document。");
}

echo "PNG sign验证成功。\n";

// Analysis第一个 Chunk(Should be IHDR)
$chunkData = substr($data, 8);

// use unpack Extract fields
$unpacked = unpack("Nlength/A4type", substr($chunkData, 0, 8));
$length = $unpacked['length'];
$type = $unpacked['type'];

echo "The first block type: $type\n";
echo "Data length: $length\n";

// extract IHDR data
$ihdrData = substr($chunkData, 8, 13);

$ihdr = unpack("Nwidth/Nheight/CbitDepth/CcolorType/Ccompression/Cfilter/Cinterlace", $ihdrData);

echo "width: {$ihdr['width']} px\n";
echo "high: {$ihdr['height']} px\n";
echo "Deep: {$ihdr['bitDepth']}\n";
echo "Color Type: {$ihdr['colorType']}\n";
echo "Compression method: {$ihdr['compression']}\n";
echo "Filter method: {$ihdr['filter']}\n";
echo "Interlaced scan: {$ihdr['interlace']}\n";
?>

3. Key functions description

unpack()

unpack() is used to parse binary data into PHP arrays. It uses a format string to describe the type and order of each field. For example:

 unpack("Nlength/A4type", $binary);
  • Nlength means reading a large-endian unsigned long integer (4 bytes), named length

  • A4type means reading an ASCII string of fixed length (4 bytes) named type

pack()

Instead, pack() can package variables into binary format. For example, when packaging PNG file headers, you can use:

 $signature = pack("C8", 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A);

This is very useful when customizing the generation of PNG files.

4. Advanced Analysis

To continue parsing subsequent PNG blocks (such as IDAT, IEND, etc.), just loop through each block as follows:

  1. Read 8 bytes: 4 byte length + 4 byte type

  2. Read the corresponding data field according to the length

  3. Skip 4 byte CRC check

  4. Continue to read the next block until IEND is encountered

This analysis method can also be applied to more complex PNG characteristics, such as transparency (tRNS), color palette (PLTE), and other blocks.

V. Conclusion

By using PHP's unpack() and pack() functions, we can easily parse PNG files in a low-level way and understand their underlying structure. This skill is very useful for in-depth understanding of image formats, writing customized image processing tools, or developing related security tools. Mastering these skills can also make you more comfortable in daily PHP development.