libpng/contrib/tools/png-fix-itxt.c
Cosmin Truta 77c3a39299 Clean up comments and whitespace characters in source files
Remove all remaining "last changed" version info from source comments.
(The version control system maintains this information automatically.)

Delete the trailing whitespace characters.
2022-11-20 21:23:33 +02:00

163 lines
4.0 KiB
C

/* png-fix-itxt
*
* Copyright 2015 Glenn Randers-Pehrson
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*
* Usage:
*
* png-fix-itxt < bad.png > good.png
*
* Fixes a PNG file written with libpng-1.6.0 or 1.6.1 that has one or more
* uncompressed iTXt chunks. Assumes that the actual length is greater
* than or equal to the value in the length byte, and that the CRC is
* correct for the actual length. This program hunts for the CRC and
* adjusts the length byte accordingly. It is not an error to process a
* PNG file that has no iTXt chunks or one that has valid iTXt chunks;
* such files will simply be copied.
*
* Requires zlib (for crc32 and Z_NULL); build with
*
* gcc -O -o png-fix-itxt png-fix-itxt.c -lz
*
* If you need to handle iTXt chunks larger than 500000 kbytes you must
* rebuild png-fix-itxt with a larger values of MAX_LENGTH (or a smaller value
* if you know you will never encounter such huge iTXt chunks).
*/
#include <stdio.h>
#include <zlib.h>
#define MAX_LENGTH 500000
/* Read one character (inchar), also return octet (c), break if EOF */
#define GETBREAK inchar=getchar(); \
c=(inchar & 0xffU);\
if (inchar != c) break
int
main(void)
{
unsigned int i;
unsigned char buf[MAX_LENGTH];
unsigned long crc;
unsigned char c;
int inchar;
/* Skip 8-byte signature */
for (i=8; i; i--)
{
GETBREAK;
putchar(c);
}
if (inchar == c) /* !EOF */
for (;;)
{
/* Read the length */
unsigned long length; /* must be 32 bits! */
GETBREAK; buf[0] = c; length = c; length <<= 8;
GETBREAK; buf[1] = c; length += c; length <<= 8;
GETBREAK; buf[2] = c; length += c; length <<= 8;
GETBREAK; buf[3] = c; length += c;
/* Read the chunkname */
GETBREAK; buf[4] = c;
GETBREAK; buf[5] = c;
GETBREAK; buf[6] = c;
GETBREAK; buf[7] = c;
/* The iTXt chunk type expressed as integers is (105, 84, 88, 116) */
if (buf[4] == 105 && buf[5] == 84 && buf[6] == 88 && buf[7] == 116)
{
if (length >= MAX_LENGTH-12)
break; /* To do: handle this more gracefully */
/* Initialize the CRC */
crc = crc32(0, Z_NULL, 0);
/* Copy the data bytes */
for (i=8; i < length + 12; i++)
{
GETBREAK; buf[i] = c;
}
if (inchar != c) /* EOF */
break;
/* Calculate the CRC */
crc = crc32(crc, buf+4, (uInt)length+4);
for (;;)
{
/* Check the CRC */
if (((crc >> 24) & 0xffU) == buf[length+8] &&
((crc >> 16) & 0xffU) == buf[length+9] &&
((crc >> 8) & 0xffU) == buf[length+10] &&
((crc ) & 0xffU) == buf[length+11])
break;
length++;
if (length >= MAX_LENGTH-12)
break;
GETBREAK;
buf[length+11] = c;
/* Update the CRC */
crc = crc32(crc, buf+7+length, 1);
}
if (inchar != c) /* EOF */
break;
/* Update length bytes */
buf[0] = (unsigned char)((length >> 24) & 0xffU);
buf[1] = (unsigned char)((length >> 16) & 0xffU);
buf[2] = (unsigned char)((length >> 8) & 0xffU);
buf[3] = (unsigned char)((length ) & 0xffU);
/* Write the fixed iTXt chunk (length, name, data, crc) */
for (i=0; i<length+12; i++)
putchar(buf[i]);
}
else
{
if (inchar != c) /* EOF */
break;
/* Copy bytes that were already read (length and chunk name) */
for (i=0; i<8; i++)
putchar(buf[i]);
/* Copy data bytes and CRC */
for (i=8; i< length+12; i++)
{
GETBREAK;
putchar(c);
}
if (inchar != c) /* EOF */
{
break;
}
/* The IEND chunk type expressed as integers is (73, 69, 78, 68) */
if (buf[4] == 73 && buf[5] == 69 && buf[6] == 78 && buf[7] == 68)
break;
}
if (inchar != c) /* EOF */
break;
if (buf[4] == 73 && buf[5] == 69 && buf[6] == 78 && buf[7] == 68)
break;
}
return 0;
}