1 2 /* png-fix-itxt version 1.0.0 3 * 4 * Copyright 2013 Glenn Randers-Pehrson 5 * Last changed in libpng 1.6.3 [July 18, 2013] 6 * 7 * This code is released under the libpng license. 8 * For conditions of distribution and use, see the disclaimer 9 * and license in png.h 10 * 11 * Usage: 12 * 13 * png-fix-itxt.exe < bad.png > good.png 14 * 15 * Fixes a PNG file written with libpng-1.6.0 or 1.6.1 that has one or more 16 * uncompressed iTXt chunks. Assumes that the actual length is greater 17 * than or equal to the value in the length byte, and that the CRC is 18 * correct for the actual length. This program hunts for the CRC and 19 * adjusts the length byte accordingly. It is not an error to process a 20 * PNG file that has no iTXt chunks or one that has valid iTXt chunks; 21 * such files will simply be copied. 22 * 23 * Requires zlib (for crc32 and Z_NULL); build with 24 * 25 * gcc -O -o png-fix-itxt png-fix-itxt.c -lz 26 * 27 * If you need to handle iTXt chunks larger than 500000 kbytes you must 28 * rebuild png-fix-itxt with a larger values of MAX_LENGTH (or a smaller value 29 * if you know you will never encounter such huge iTXt chunks). 30 */ 31 32 #include <stdio.h> 33 #include <zlib.h> 34 35 #define MAX_LENGTH 500000 36 37 #define GETBREAK ((unsigned char)(inchar=getchar())); if (inchar == EOF) break 38 39 int 40 main(void) 41 { 42 unsigned int i; 43 unsigned char buf[MAX_LENGTH]; 44 unsigned long crc; 45 unsigned char c; 46 int inchar; 47 48 /* Skip 8-byte signature */ 49 for (i=8; i; i--) 50 { 51 c=GETBREAK; 52 putchar(c); 53 } 54 55 if (inchar != EOF) 56 for (;;) 57 { 58 /* Read the length */ 59 unsigned long length; /* must be 32 bits! */ 60 c=GETBREAK; buf[0] = c; length = c; length <<= 8; 61 c=GETBREAK; buf[1] = c; length += c; length <<= 8; 62 c=GETBREAK; buf[2] = c; length += c; length <<= 8; 63 c=GETBREAK; buf[3] = c; length += c; 64 65 /* Read the chunkname */ 66 c=GETBREAK; buf[4] = c; 67 c=GETBREAK; buf[5] = c; 68 c=GETBREAK; buf[6] = c; 69 c=GETBREAK; buf[7] = c; 70 71 72 /* The iTXt chunk type expressed as integers is (105, 84, 88, 116) */ 73 if (buf[4] == 105 && buf[5] == 84 && buf[6] == 88 && buf[7] == 116) 74 { 75 if (length >= MAX_LENGTH-12) 76 break; /* To do: handle this more gracefully */ 77 78 /* Initialize the CRC */ 79 crc = crc32(0, Z_NULL, 0); 80 81 /* Copy the data bytes */ 82 for (i=8; i < length + 12; i++) 83 { 84 c=GETBREAK; buf[i] = c; 85 } 86 87 /* Calculate the CRC */ 88 crc = crc32(crc, buf+4, (uInt)length+4); 89 90 for (;;) 91 { 92 /* Check the CRC */ 93 if (((crc >> 24) & 0xff) == buf[length+8] && 94 ((crc >> 16) & 0xff) == buf[length+9] && 95 ((crc >> 8) & 0xff) == buf[length+10] && 96 ((crc ) & 0xff) == buf[length+11]) 97 break; 98 99 length++; 100 101 if (length >= MAX_LENGTH-12) 102 break; 103 104 c=GETBREAK; 105 buf[length+11]=c; 106 107 /* Update the CRC */ 108 crc = crc32(crc, buf+7+length, 1); 109 } 110 111 /* Update length bytes */ 112 buf[0] = (unsigned char)((length << 24) & 0xff); 113 buf[1] = (unsigned char)((length << 16) & 0xff); 114 buf[2] = (unsigned char)((length << 8) & 0xff); 115 buf[3] = (unsigned char)((length ) & 0xff); 116 117 /* Write the fixed iTXt chunk (length, name, data, crc) */ 118 for (i=0; i<length+12; i++) 119 putchar(buf[i]); 120 } 121 122 else 123 { 124 /* Copy bytes that were already read (length and chunk name) */ 125 for (i=0; i<8; i++) 126 putchar(buf[i]); 127 128 /* Copy data bytes and CRC */ 129 for (i=8; i< length+12; i++) 130 { 131 c=GETBREAK; 132 putchar(c); 133 } 134 135 if (inchar == EOF) 136 { 137 break; 138 } 139 140 /* The IEND chunk type expressed as integers is (73, 69, 78, 68) */ 141 if (buf[4] == 73 && buf[5] == 69 && buf[6] == 78 && buf[7] == 68) 142 break; 143 } 144 145 if (inchar == EOF) 146 break; 147 148 if (buf[4] == 73 && buf[5] == 69 && buf[6] == 78 && buf[7] == 68) 149 break; 150 } 151 152 return 0; 153 } 154