Home | History | Annotate | Download | only in tools
      1 
      2 /* png-fix-itxt version 1.0.0
      3  *
      4  * Copyright 2015 Glenn Randers-Pehrson
      5  * Last changed in libpng 1.6.18 [July 23, 2015]
      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 /* Read one character (inchar), also return octet (c), break if EOF */
     38 #define GETBREAK inchar=getchar(); \
     39                  c=(inchar & 0xffU);\
     40                  if (inchar != c) break
     41 int
     42 main(void)
     43 {
     44    unsigned int i;
     45    unsigned char buf[MAX_LENGTH];
     46    unsigned long crc;
     47    unsigned char c;
     48    int inchar;
     49 
     50 /* Skip 8-byte signature */
     51    for (i=8; i; i--)
     52    {
     53       GETBREAK;
     54       putchar(c);
     55    }
     56 
     57 if (inchar == c) /* !EOF */
     58 for (;;)
     59  {
     60    /* Read the length */
     61    unsigned long length; /* must be 32 bits! */
     62    GETBREAK; buf[0] = c; length  = c; length <<= 8;
     63    GETBREAK; buf[1] = c; length += c; length <<= 8;
     64    GETBREAK; buf[2] = c; length += c; length <<= 8;
     65    GETBREAK; buf[3] = c; length += c;
     66 
     67    /* Read the chunkname */
     68    GETBREAK; buf[4] = c;
     69    GETBREAK; buf[5] = c;
     70    GETBREAK; buf[6] = c;
     71    GETBREAK; buf[7] = c;
     72 
     73 
     74    /* The iTXt chunk type expressed as integers is (105, 84, 88, 116) */
     75    if (buf[4] == 105 && buf[5] == 84 && buf[6] == 88 && buf[7] == 116)
     76    {
     77       if (length >= MAX_LENGTH-12)
     78          break;  /* To do: handle this more gracefully */
     79 
     80       /* Initialize the CRC */
     81       crc = crc32(0, Z_NULL, 0);
     82 
     83       /* Copy the data bytes */
     84       for (i=8; i < length + 12; i++)
     85       {
     86          GETBREAK; buf[i] = c;
     87       }
     88 
     89       if (inchar != c) /* EOF */
     90          break;
     91 
     92       /* Calculate the CRC */
     93       crc = crc32(crc, buf+4, (uInt)length+4);
     94 
     95       for (;;)
     96       {
     97         /* Check the CRC */
     98         if (((crc >> 24) & 0xffU) == buf[length+8] &&
     99             ((crc >> 16) & 0xffU) == buf[length+9] &&
    100             ((crc >>  8) & 0xffU) == buf[length+10] &&
    101             ((crc      ) & 0xffU) == buf[length+11])
    102            break;
    103 
    104         length++;
    105 
    106         if (length >= MAX_LENGTH-12)
    107            break;
    108 
    109         GETBREAK;
    110         buf[length+11] = c;
    111 
    112         /* Update the CRC */
    113         crc = crc32(crc, buf+7+length, 1);
    114       }
    115 
    116       if (inchar != c) /* EOF */
    117          break;
    118 
    119       /* Update length bytes */
    120       buf[0] = (unsigned char)((length >> 24) & 0xffU);
    121       buf[1] = (unsigned char)((length >> 16) & 0xffU);
    122       buf[2] = (unsigned char)((length >>  8) & 0xffU);
    123       buf[3] = (unsigned char)((length      ) & 0xffU);
    124 
    125       /* Write the fixed iTXt chunk (length, name, data, crc) */
    126       for (i=0; i<length+12; i++)
    127          putchar(buf[i]);
    128    }
    129 
    130    else
    131    {
    132       if (inchar != c) /* EOF */
    133          break;
    134 
    135       /* Copy bytes that were already read (length and chunk name) */
    136       for (i=0; i<8; i++)
    137          putchar(buf[i]);
    138 
    139       /* Copy data bytes and CRC */
    140       for (i=8; i< length+12; i++)
    141       {
    142          GETBREAK;
    143          putchar(c);
    144       }
    145 
    146       if (inchar != c) /* EOF */
    147       {
    148          break;
    149       }
    150 
    151    /* The IEND chunk type expressed as integers is (73, 69, 78, 68) */
    152       if (buf[4] == 73 && buf[5] == 69 && buf[6] == 78 && buf[7] == 68)
    153          break;
    154    }
    155 
    156    if (inchar != c) /* EOF */
    157       break;
    158 
    159    if (buf[4] == 73 && buf[5] == 69 && buf[6] == 78 && buf[7] == 68)
    160      break;
    161  }
    162 
    163  return 0;
    164 }
    165