diff options
Diffstat (limited to 'Build/source/libs/libpng/libpng-1.6.18/contrib/tools/png-fix-itxt.c')
-rw-r--r-- | Build/source/libs/libpng/libpng-1.6.18/contrib/tools/png-fix-itxt.c | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/Build/source/libs/libpng/libpng-1.6.18/contrib/tools/png-fix-itxt.c b/Build/source/libs/libpng/libpng-1.6.18/contrib/tools/png-fix-itxt.c new file mode 100644 index 00000000000..5730d9f792d --- /dev/null +++ b/Build/source/libs/libpng/libpng-1.6.18/contrib/tools/png-fix-itxt.c @@ -0,0 +1,164 @@ + +/* png-fix-itxt version 1.0.0 + * + * Copyright 2015 Glenn Randers-Pehrson + * Last changed in libpng 1.6.18 [July 23, 2015] + * + * 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.exe < 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; +} |