9
votes

I created a few 4x4 pixel, 16-bit grayscale, images in Photoshop and saved them as non-compressed, no interlace, PNG files. I am trying to write a program to extract the image data from these files but I have become a bit confused with the IDAT chunk. This is for self-education purposes, so I am not using a library.

Here is the hex code for the IDAT chunk of one of the images where every pixel is white.

hex code

I have color coded what I believe I understand at this point.

Red = Ignore because it is part of the IEND chunk and not relevant to IDAT.
Yellow = Chunk information. The first 4 yellow bytes are the data length. Second 4 yellows bytes are the chunk identifier. The last 4 yellow bytes at the end of the image are the Cyclic Redundancy Check.
Blue = zlib compression format information. Where the first blue byte is the compression method and compression information. The second blue byte is Flag information. The last four blue bytes near the bottom of the image are the ADLER-32 checksum. I am assuming there is no DICTID in this case.
Grey = Information for the Deflate compression algorithm. In the first grey byte, bit one is the last block marker and bits two and three are the encoding method. The rest of the first grey byte is ignored. Since this method is the non-compressed method, the second and third grey bytes are the length of the data bytes in the block and the fourth and fifth grey byte are the one's compliment of the second and third grey bytes.
No Box = The Image data compressed with the LZ77 algorithm (no Huffman code because of uncompressed method) with the algorithm using 8-bits for potential duplicates length and 15-bits for search back distance.

Either I am understanding something incorrectly or I am not understanding how to decode the bytes in the image with no box using the LZ77 algorithm correctly. If someone can please correct me or show what I am not understanding I would greatly appreciate it. Thank you.

1
Added few tags... also it looks like you got the IDAT yellow start/end chunk decoded correctly (size+12 BYTEs) at least it is the same on pngs I tested on.Spektre

1 Answers

9
votes

Top row: 01 ff fd 00 00 00 00 00 00 ("sub" filter, first pixel is fffd, subsequent pixels are each the same as the pixel to its left (difference = 0)

Remaining 3 rows: 02 00 00 00 00 00 00 00 00 ("up" filter, all same as row above)

Last block: 01 00 00 ff ff (last byte marker 01, len 0000, ~len ffff)

So the image is 4x4, all pixels are 16-bit fffd, which is almost white.

If you had used filter-type 0 for all bytes, it might have been clearer to understand; the rows would each have been 00 ff fd ff fd ff fd ff fd

By the way, the IEND chunk should have 4 more bytes (the CRC); either something is wrong with your encoder or you edited them out of the picture of the hex dump.