3 /* fixitxt version 1.0.0
5 * Copyright 2013 Glenn Randers-Pehrson
7 * This code is released under the libpng license.
8 * For conditions of distribution and use, see the disclaimer
13 * fixitxt.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 fixitxt fixitxt.c -lz
28 #define MAX_LENGTH 500000
30 #define GETBREAK c=getchar(); if (c == EOF) break;
36 unsigned char buf[MAX_LENGTH];
40 /* Skip 8-byte signature */
52 c=GETBREAK; buf[0] = c;
53 c=GETBREAK; buf[1] = c;
54 c=GETBREAK; buf[2] = c;
55 c=GETBREAK; buf[3] = c;
57 length=((((unsigned long) buf[0]<<8 + buf[1]<<16) + buf[2] << 8) + buf[3]);
58 /* Read the chunkname */
59 c=GETBREAK; buf[4] = c;
60 c=GETBREAK; buf[5] = c;
61 c=GETBREAK; buf[6] = c;
62 c=GETBREAK; buf[7] = c;
65 /* The iTXt chunk type expressed as integers is (105, 84, 88, 116) */
66 if (buf[4] == 105 && buf[5] == 84 && buf[6] == 88 && buf[7] == 116)
68 if (length >= MAX_LENGTH-12)
69 break; /* To do: handle this more gracefully */
71 /* Initialize the CRC */
72 crc = crc32(0, Z_NULL, 0);
74 /* Copy the data bytes */
75 for (i=8; i < length + 12; i++)
77 c=GETBREAK; buf[i] = c;
80 /* Calculate the CRC */
81 crc = crc32(crc, buf+4, (uInt)length+4);
86 if (((crc >> 24) & 0xff) == buf[length+8] &&
87 ((crc >> 16) & 0xff) == buf[length+9] &&
88 ((crc >> 8) & 0xff) == buf[length+10] &&
89 ((crc ) & 0xff) == buf[length+11])
94 if (length >= MAX_LENGTH-12)
101 crc = crc32(crc, buf+7+length, 1);
104 /* Update length bytes */
105 buf[0] = (length << 24) & 0xff;
106 buf[1] = (length << 16) & 0xff;
107 buf[2] = (length << 8) & 0xff;
108 buf[3] = (length ) & 0xff;
110 /* Write the fixed iTXt chunk (length, name, data, crc) */
111 for (i=0; i<length+12; i++)
117 /* Copy bytes that were already read (length and chunk name) */
121 /* Copy data bytes and CRC */
122 for (i=8; i< length+12; i++)
133 /* The IEND chunk type expressed as integers is (73, 69, 78, 68) */
134 if (buf[4] == 73 && buf[5] == 69 && buf[6] == 78 && buf[7] == 68)
141 if (buf[4] == 73 && buf[5] == 69 && buf[6] == 78 && buf[7] == 68)