Search code examples
c++cpngchecksumcrc32

CRC32 calculations for png chunk doesn't match the real one


I'm attempting to mimic the function used for creating CRC's in PNG files, I'm using the autodin II polynomial and the source code from:
http://www.opensource.apple.com/source/xnu/xnu-1456.1.26/bsd/libkern/crc32.c

My tests have all been for the IHDR chunk, so my parameters have been:
crc - 0xffffffff and 0 (both have been suggested)
buff - the address of the IHDR Chunk's type.
length - the IHDR Chunk's length + 4 (the length of the chunk's data + the length of the type)

I printed the calculated CRC in binary, which I compared to the actual CRC of the chunk. I can see no similarities (little-big endian, reversed bits, XOR'd, etc).

This is the data for the IHDR chunk (hexadecimal format):
length(big endian): d0 00 00 00 (13)
type: 49 48 44 52
data: 00 00 01 77 00 00 01 68 08 06 00 00 00
existing CRC: b0 bb 40 ac

If anyone can tell me why my calculations are off, or give me a CRC32 function that will work I would greatly appreciate it. Thank-you!


Solution

  • The CRC-32 algorithm used in PNG images is described here: http://www.w3.org/TR/PNG-Structure.html#CRC-algorithm (there's also a link to C code for doing test calculations).

    But as @Jigsore pointed out, you won't get sensible results from the data you posted here. You've given us a 4-byte type identifier and what looks like 7.5 bytes of data to follow it. There should be a total of 13 bytes according to the length header.

    EDIT: This works using the function from w3.org:

    int main() {
        char input[] = { 0x49,0x48,0x44,0x52,0x00,0x00,0x01,0x77,0x00,
                         0x00,0x01,0x68,0x08,0x06,0x00,0x00,0x00 };
        printf("%08lx\n",crc(input,17));
        return 0;
    }
    

    Output: ac40bbb0