-
Notifications
You must be signed in to change notification settings - Fork 0
How It Works
Olivier Suritz edited this page Apr 17, 2012
·
3 revisions
As documented on The PNG Image Format, PNG files contain:
- An 8-byte "magic" header that helps identify file as a PNG Image. This header is
89h,'PNG',13,10,26,10or in hexadecimal0x89504E470D0A1A0A - A series of chunks filling up the rest of the file. Each chunk follows the layout described below.
- Note: the last chunk is going to be an IEND chunk and indicates the end of the file.

Each chunk is made up of:
-
A chunk header. This header is divided in 2 parts:
- A Big-Endian, 32-bit integer (4 bytes) indicating the number of data bytes after the header.
- A 4-byte chunk type code/identifier. For convenience in description and in examining PNG files, type codes are restricted to consist of upper- and lowercase ASCII letters (A-Z, a-z).
- ? bytes of data (where ? is the number stored in the first 4 bytes of the chunk header)
- A 32-bit CRC (4 bytes), calculated on the preceding bytes in that chunk, including the chunk type code and chunk data fields, but not including the length field.

The CgBI file format, thus named for its extra header, is Apple's proprietary extension to the PNG image format.
The CgBI format used by Apple differs from standard PNG files in the following way:
- An extra critical chunk (CgBI) - typically the first chunk after the PNG "magic" header.
- Red and blue bytes are swapped (RGBA -> BGRA), presumably for high-speed direct blitting to the framebuffer.
- Zlib header, footer, and CRC removed from the IDAT chunk. I.e. the IDAT chunk data is Deflated rather than Gzipped.
Given the above differences, it is somewhat trivial to revert the optimization. The general algorithm is:
Create a PNG "magic" header
Iterate over each chunk in the CgBI/crushed file
Ignore it if is the CgBI chunk
If it is any chunk other than IDAT, simply copy it
If it is an IDAT chunk
Deflate the original IDAT data bytes
Copy the bytes, swap the blue-red bytes back to an RGBA ordering
Gzip the resulting bytes
Write the calculated chunk data length (size of the gzipped variable)
Write the IDAT chunk type code
Write the gzipped variable
Compute and write the CRC32 of the chunk type code + gzipped variable
If it is an IEND chunk, copy it and stop.