2 /* png-fix-itxt version 1.0.0
4 * Copyright 2013 Glenn Randers-Pehrson
5 * Last changed in libpng 1.6.3 [July 18, 2013]
7 * This code is released under the libpng license.
8 * For conditions of distribution and use, see the disclaimer
13 * png-fix-itxt.exe < bad.png > good.png
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.
23 * Requires zlib (for crc32 and Z_NULL); build with
25 * gcc -O -o png-fix-itxt png-fix-itxt.c -lz
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).
35 #define MAX_LENGTH 500000
37 #define GETBREAK ((unsigned char)(inchar=getchar())); if (inchar == EOF) break
43 unsigned char buf
[MAX_LENGTH
];
48 /* Skip 8-byte signature */
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
;
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
;
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)
75 if (length
>= MAX_LENGTH
-12)
76 break; /* To do: handle this more gracefully */
78 /* Initialize the CRC */
79 crc
= crc32(0, Z_NULL
, 0);
81 /* Copy the data bytes */
82 for (i
=8; i
< length
+ 12; i
++)
84 c
=GETBREAK
; buf
[i
] = c
;
87 /* Calculate the CRC */
88 crc
= crc32(crc
, buf
+4, (uInt
)length
+4);
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])
101 if (length
>= MAX_LENGTH
-12)
108 crc
= crc32(crc
, buf
+7+length
, 1);
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);
117 /* Write the fixed iTXt chunk (length, name, data, crc) */
118 for (i
=0; i
<length
+12; i
++)
124 /* Copy bytes that were already read (length and chunk name) */
128 /* Copy data bytes and CRC */
129 for (i
=8; i
< length
+12; i
++)
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)
148 if (buf
[4] == 73 && buf
[5] == 69 && buf
[6] == 78 && buf
[7] == 68)