png-fix-itxt.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /* png-fix-itxt version 1.0.0
  2. *
  3. * Copyright 2015 Glenn Randers-Pehrson
  4. * Last changed in libpng 1.6.18 [July 23, 2015]
  5. *
  6. * This code is released under the libpng license.
  7. * For conditions of distribution and use, see the disclaimer
  8. * and license in png.h
  9. *
  10. * Usage:
  11. *
  12. * png-fix-itxt.exe < bad.png > good.png
  13. *
  14. * Fixes a PNG file written with libpng-1.6.0 or 1.6.1 that has one or more
  15. * uncompressed iTXt chunks. Assumes that the actual length is greater
  16. * than or equal to the value in the length byte, and that the CRC is
  17. * correct for the actual length. This program hunts for the CRC and
  18. * adjusts the length byte accordingly. It is not an error to process a
  19. * PNG file that has no iTXt chunks or one that has valid iTXt chunks;
  20. * such files will simply be copied.
  21. *
  22. * Requires zlib (for crc32 and Z_NULL); build with
  23. *
  24. * gcc -O -o png-fix-itxt png-fix-itxt.c -lz
  25. *
  26. * If you need to handle iTXt chunks larger than 500000 kbytes you must
  27. * rebuild png-fix-itxt with a larger values of MAX_LENGTH (or a smaller value
  28. * if you know you will never encounter such huge iTXt chunks).
  29. */
  30. #include <stdio.h>
  31. #include <zlib.h>
  32. #define MAX_LENGTH 500000
  33. /* Read one character (inchar), also return octet (c), break if EOF */
  34. #define GETBREAK inchar=getchar(); \
  35. c=(inchar & 0xffU);\
  36. if (inchar != c) break
  37. int
  38. main(void)
  39. {
  40. unsigned int i;
  41. unsigned char buf[MAX_LENGTH];
  42. unsigned long crc;
  43. unsigned char c;
  44. int inchar;
  45. /* Skip 8-byte signature */
  46. for (i=8; i; i--)
  47. {
  48. GETBREAK;
  49. putchar(c);
  50. }
  51. if (inchar == c) /* !EOF */
  52. for (;;)
  53. {
  54. /* Read the length */
  55. unsigned long length; /* must be 32 bits! */
  56. GETBREAK; buf[0] = c; length = c; length <<= 8;
  57. GETBREAK; buf[1] = c; length += c; length <<= 8;
  58. GETBREAK; buf[2] = c; length += c; length <<= 8;
  59. GETBREAK; buf[3] = c; length += c;
  60. /* Read the chunkname */
  61. GETBREAK; buf[4] = c;
  62. GETBREAK; buf[5] = c;
  63. GETBREAK; buf[6] = c;
  64. 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)
  67. {
  68. if (length >= MAX_LENGTH-12)
  69. break; /* To do: handle this more gracefully */
  70. /* Initialize the CRC */
  71. crc = crc32(0, Z_NULL, 0);
  72. /* Copy the data bytes */
  73. for (i=8; i < length + 12; i++)
  74. {
  75. GETBREAK; buf[i] = c;
  76. }
  77. if (inchar != c) /* EOF */
  78. break;
  79. /* Calculate the CRC */
  80. crc = crc32(crc, buf+4, (uInt)length+4);
  81. for (;;)
  82. {
  83. /* Check the CRC */
  84. if (((crc >> 24) & 0xffU) == buf[length+8] &&
  85. ((crc >> 16) & 0xffU) == buf[length+9] &&
  86. ((crc >> 8) & 0xffU) == buf[length+10] &&
  87. ((crc ) & 0xffU) == buf[length+11])
  88. break;
  89. length++;
  90. if (length >= MAX_LENGTH-12)
  91. break;
  92. GETBREAK;
  93. buf[length+11] = c;
  94. /* Update the CRC */
  95. crc = crc32(crc, buf+7+length, 1);
  96. }
  97. if (inchar != c) /* EOF */
  98. break;
  99. /* Update length bytes */
  100. buf[0] = (unsigned char)((length >> 24) & 0xffU);
  101. buf[1] = (unsigned char)((length >> 16) & 0xffU);
  102. buf[2] = (unsigned char)((length >> 8) & 0xffU);
  103. buf[3] = (unsigned char)((length ) & 0xffU);
  104. /* Write the fixed iTXt chunk (length, name, data, crc) */
  105. for (i=0; i<length+12; i++)
  106. putchar(buf[i]);
  107. }
  108. else
  109. {
  110. if (inchar != c) /* EOF */
  111. break;
  112. /* Copy bytes that were already read (length and chunk name) */
  113. for (i=0; i<8; i++)
  114. putchar(buf[i]);
  115. /* Copy data bytes and CRC */
  116. for (i=8; i< length+12; i++)
  117. {
  118. GETBREAK;
  119. putchar(c);
  120. }
  121. if (inchar != c) /* EOF */
  122. {
  123. break;
  124. }
  125. /* The IEND chunk type expressed as integers is (73, 69, 78, 68) */
  126. if (buf[4] == 73 && buf[5] == 69 && buf[6] == 78 && buf[7] == 68)
  127. break;
  128. }
  129. if (inchar != c) /* EOF */
  130. break;
  131. if (buf[4] == 73 && buf[5] == 69 && buf[6] == 78 && buf[7] == 68)
  132. break;
  133. }
  134. return 0;
  135. }