#include #include #include #include #include "pnglibconf.h.prebuilt" #include "../pngpriv.h" static const struct { png_uint_32 name; } png_known_chunks[] = /* See scripts/chunkdesc.h for how this works: */ #define PNG_CHUNK_END(n, c1, c2, c3, c4, before, after)\ { png_ ##n } #define PNG_CHUNK(n, c1, c2, c3, c4, before, after)\ PNG_CHUNK_END(n, c1, c2, c3, c4, before, after), #define PNG_CHUNK_BEGIN(n, c1, c2, c3, c4, before, after)\ PNG_CHUNK_END(n, c1, c2, c3, c4, before, after), { # include "chunkdesc.h" }; #define C_KNOWN ((sizeof png_known_chunks)/(sizeof png_known_chunks[0])) static unsigned int index_of(png_uint_32 name) { unsigned int i; if (name == 0) return 0; for (i=0; i> shift),n += n >> s1),n += n >> s2)) inline unsigned int hash(png_uint_32 name, unsigned int shift, unsigned int s1, unsigned int s2, unsigned int s3, unsigned int s4, unsigned int s5) { /* Running the search gives (shift,s1,s2) (2,8,16) */ //return PNG_CHUNK_HASH(name, shift, s1, s2, s3, s4, s5); name += name >> shift; name += name >> s1; name += name >> s2; //name += name >> s3; return 0x3f & name; /*return 0x3f & ((name) + ( ((name >> bitorder[s1]) & 0x01) + ((name >> (bitorder[s2]-1)) & 0x02) + ((name >> (bitorder[s3]-2)) & 0x04) + ((name >> (bitorder[s4]-3)) & 0x08) + ((name >> (bitorder[s5]-4)) & 0x10)));*/ } int main(void) { unsigned int s1 = 0, s2 = 0, s3 = 0, s4 = 0, s5 = 0; unsigned int shift = 0; png_uint_32 mask; unsigned int bitcount; unsigned int mineq; png_uint_32 sarray; unsigned int shift_save; png_uint_32 reverse_index_save[64]; assert(C_KNOWN <= 64); /* Check IDAT: */ assert(index_of(png_IDAT) == 0); /* Build a mask of all the bits that differ in at least one of the known * names. */ { png_uint_32 set, unset; int i; for (i=0, set=unset=0; i> j) & 1) ++ones[j]; if ((mask >> (31-j)) & 1) b[k++] = ((name >> (31-j)) & 1) ? 'o' : ' '; } b[k] = 0; //printf("%s: %s\n", s, b); } memset(bitorder, 0, sizeof bitorder); bitcount = 0; for (i=0; i>1; unsigned int hi = (C_KNOWN + i)>>1; int j; for (j=0; j<32; ++j) if (ones[j] == lo || ones[j] == hi) { //printf(" %2d,", j); bitorder[bitcount++] = j; } } //printf("\nbitcount=%u, C_KNOWN=%lu\n", bitcount, C_KNOWN); } /* s? are masks to exclude bits from the hash, one for each byte: */ mineq = C_KNOWN; sarray = 0; for (shift=0; shift<32; ++shift) for (s1=0; s1<32; ++s1) for (s2=s1+1; s2<32; ++s2) //for (s3=s2+1; s3<32; ++s3) //for (s4=s3+1; s4> %u),n += n >> %u),n += n >> %u)]\n\n", shift, s1, s2); printf("static png_byte\n" "png_chunk_index(png_uint_32 name)\n" "{\n" " name += name >> %u;\n" " name += name >> %u;\n" " name += name >> %u;\n" " return png_chunk_lut[name & 0x3f];\n" "}\n", shift, s1, s2); return 0; } if (eq < mineq) { mineq = eq; sarray = s1 + bitcount * (s2 + bitcount * (s3 + bitcount * (s4 + bitcount *s5))); memcpy(reverse_index_save, reverse_index, sizeof reverse_index_save); shift_save = shift; } } s1 = sarray % bitcount; s2 = (sarray / bitcount) % bitcount; s3 = (sarray / bitcount / bitcount) % bitcount; s4 = (sarray / bitcount / bitcount / bitcount) % bitcount; s5 = (sarray / bitcount / bitcount / bitcount / bitcount) % bitcount; printf("best: %u clashes with bits: %u, %u, %u, %u, %u, %u\n", mineq, shift_save, s1, s2, s3, s4, s5); { int i; png_uint_32 reverse_index[64]; memset(reverse_index, 0, sizeof reverse_index); for (i=0; i