/third_party/giflib-5.1.3/util/giffix.c

https://github.com/onecoolx/picasso · C · 216 lines · 171 code · 23 blank · 22 comment · 67 complexity · 651f115eb573e4921ff3bf2d281dc5d9 MD5 · raw file

  1. /*****************************************************************************
  2. giffix - attempt to fix a truncated GIF
  3. *****************************************************************************/
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <ctype.h>
  7. #include <string.h>
  8. #include <stdbool.h>
  9. #include "gif_lib.h"
  10. #include "getarg.h"
  11. #define PROGRAM_NAME "giffix"
  12. static char
  13. *VersionStr =
  14. PROGRAM_NAME
  15. VERSION_COOKIE
  16. " Gershon Elber, "
  17. __DATE__ ", " __TIME__ "\n"
  18. "(C) Copyright 1989 Gershon Elber.\n";
  19. static char
  20. *CtrlStr =
  21. PROGRAM_NAME
  22. " v%- h%- GifFile!*s";
  23. static void QuitGifError(GifFileType *GifFileIn, GifFileType *GifFileOut);
  24. /******************************************************************************
  25. Interpret the command line and scan the given GIF file.
  26. ******************************************************************************/
  27. int main(int argc, char **argv)
  28. {
  29. int i, j, NumFiles, ExtCode, Row, Col, Width, Height, ErrorCode,
  30. DarkestColor = 0, ColorIntens = 10000;
  31. bool Error, HelpFlag = false;
  32. GifRecordType RecordType;
  33. GifByteType *Extension;
  34. char **FileName = NULL;
  35. GifRowType LineBuffer;
  36. ColorMapObject *ColorMap;
  37. GifFileType *GifFileIn = NULL, *GifFileOut = NULL;
  38. int ImageNum = 0;
  39. if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifNoisyPrint, &HelpFlag,
  40. &NumFiles, &FileName)) != false ||
  41. (NumFiles > 1 && !HelpFlag)) {
  42. if (Error)
  43. GAPrintErrMsg(Error);
  44. else if (NumFiles > 1)
  45. GIF_MESSAGE("Error in command line parsing - one GIF file please.");
  46. GAPrintHowTo(CtrlStr);
  47. exit(EXIT_FAILURE);
  48. }
  49. if (HelpFlag) {
  50. (void)fprintf(stderr, VersionStr, GIFLIB_MAJOR, GIFLIB_MINOR);
  51. GAPrintHowTo(CtrlStr);
  52. exit(EXIT_SUCCESS);
  53. }
  54. if (NumFiles == 1) {
  55. if ((GifFileIn = DGifOpenFileName(*FileName, &ErrorCode)) == NULL) {
  56. PrintGifError(ErrorCode);
  57. exit(EXIT_FAILURE);
  58. }
  59. }
  60. else
  61. {
  62. /* Use stdin instead: */
  63. if ((GifFileIn = DGifOpenFileHandle(0, &ErrorCode)) == NULL) {
  64. PrintGifError(ErrorCode);
  65. exit(EXIT_FAILURE);
  66. }
  67. }
  68. /* Open stdout for the output file: */
  69. if ((GifFileOut = EGifOpenFileHandle(1, &ErrorCode)) == NULL) {
  70. PrintGifError(ErrorCode);
  71. exit(EXIT_FAILURE);
  72. }
  73. /* Dump out exactly same screen information: */
  74. /* coverity[var_deref_op] */
  75. if (EGifPutScreenDesc(GifFileOut,
  76. GifFileIn->SWidth, GifFileIn->SHeight,
  77. GifFileIn->SColorResolution, GifFileIn->SBackGroundColor,
  78. GifFileIn->SColorMap) == GIF_ERROR)
  79. QuitGifError(GifFileIn, GifFileOut);
  80. if ((LineBuffer = (GifRowType) malloc(GifFileIn->SWidth)) == NULL)
  81. GIF_EXIT("Failed to allocate memory required, aborted.");
  82. /* Scan the content of the GIF file and load the image(s) in: */
  83. do {
  84. if (DGifGetRecordType(GifFileIn, &RecordType) == GIF_ERROR)
  85. QuitGifError(GifFileIn, GifFileOut);
  86. switch (RecordType) {
  87. case IMAGE_DESC_RECORD_TYPE:
  88. if (DGifGetImageDesc(GifFileIn) == GIF_ERROR)
  89. QuitGifError(GifFileIn, GifFileOut);
  90. if (GifFileIn->Image.Interlace)
  91. GIF_EXIT("Cannot fix interlaced images.");
  92. Row = GifFileIn->Image.Top; /* Image Position relative to Screen. */
  93. Col = GifFileIn->Image.Left;
  94. Width = GifFileIn->Image.Width;
  95. Height = GifFileIn->Image.Height;
  96. GifQprintf("\n%s: Image %d at (%d, %d) [%dx%d]: ",
  97. PROGRAM_NAME, ++ImageNum, Col, Row, Width, Height);
  98. if (Width > GifFileIn->SWidth)
  99. GIF_EXIT("Image is wider than total");
  100. /* Put the image descriptor to out file: */
  101. if (EGifPutImageDesc(GifFileOut, Col, Row, Width, Height,
  102. false, GifFileIn->Image.ColorMap) == GIF_ERROR)
  103. QuitGifError(GifFileIn, GifFileOut);
  104. /* Find the darkest color in color map to use as a filler. */
  105. ColorMap = (GifFileIn->Image.ColorMap ? GifFileIn->Image.ColorMap :
  106. GifFileIn->SColorMap);
  107. for (i = 0; i < ColorMap->ColorCount; i++) {
  108. j = ((int) ColorMap->Colors[i].Red) * 30 +
  109. ((int) ColorMap->Colors[i].Green) * 59 +
  110. ((int) ColorMap->Colors[i].Blue) * 11;
  111. if (j < ColorIntens) {
  112. ColorIntens = j;
  113. DarkestColor = i;
  114. }
  115. }
  116. /* Load the image, and dump it. */
  117. for (i = 0; i < Height; i++) {
  118. GifQprintf("\b\b\b\b%-4d", i);
  119. if (DGifGetLine(GifFileIn, LineBuffer, Width)
  120. == GIF_ERROR) break;
  121. if (EGifPutLine(GifFileOut, LineBuffer, Width)
  122. == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut);
  123. }
  124. if (i < Height) {
  125. fprintf(stderr,"\nFollowing error occurred (and ignored):");
  126. PrintGifError(GifFileIn->Error);
  127. /* Fill in with the darkest color in color map. */
  128. for (j = 0; j < Width; j++)
  129. LineBuffer[j] = DarkestColor;
  130. for (; i < Height; i++)
  131. if (EGifPutLine(GifFileOut, LineBuffer, Width)
  132. == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut);
  133. }
  134. break;
  135. case EXTENSION_RECORD_TYPE:
  136. /* pass through extension records */
  137. if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) == GIF_ERROR)
  138. QuitGifError(GifFileIn, GifFileOut);
  139. if (EGifPutExtensionLeader(GifFileOut, ExtCode) == GIF_ERROR)
  140. QuitGifError(GifFileIn, GifFileOut);
  141. if (Extension != NULL)
  142. if (EGifPutExtensionBlock(GifFileOut,
  143. Extension[0],
  144. Extension + 1) == GIF_ERROR)
  145. QuitGifError(GifFileIn, GifFileOut);
  146. while (Extension != NULL) {
  147. if (DGifGetExtensionNext(GifFileIn, &Extension)==GIF_ERROR)
  148. QuitGifError(GifFileIn, GifFileOut);
  149. if (Extension != NULL)
  150. if (EGifPutExtensionBlock(GifFileOut,
  151. Extension[0],
  152. Extension + 1) == GIF_ERROR)
  153. QuitGifError(GifFileIn, GifFileOut);
  154. }
  155. if (EGifPutExtensionTrailer(GifFileOut) == GIF_ERROR)
  156. QuitGifError(GifFileIn, GifFileOut);
  157. break;
  158. case TERMINATE_RECORD_TYPE:
  159. break;
  160. default: /* Should be trapped by DGifGetRecordType. */
  161. break;
  162. }
  163. }
  164. while (RecordType != TERMINATE_RECORD_TYPE);
  165. if (DGifCloseFile(GifFileIn, &ErrorCode) == GIF_ERROR) {
  166. PrintGifError(ErrorCode);
  167. exit(EXIT_FAILURE);
  168. }
  169. if (EGifCloseFile(GifFileOut, &ErrorCode) == GIF_ERROR) {
  170. PrintGifError(ErrorCode);
  171. exit(EXIT_FAILURE);
  172. }
  173. return 0;
  174. }
  175. /******************************************************************************
  176. Close both input and output file (if open), and exit.
  177. ******************************************************************************/
  178. static void QuitGifError(GifFileType *GifFileIn, GifFileType *GifFileOut)
  179. {
  180. fprintf(stderr, "\nFollowing unrecoverable error occured:");
  181. if (GifFileIn != NULL) {
  182. PrintGifError(GifFileIn->Error);
  183. EGifCloseFile(GifFileIn, NULL);
  184. }
  185. if (GifFileOut != NULL) {
  186. PrintGifError(GifFileOut->Error);
  187. EGifCloseFile(GifFileOut, NULL);
  188. }
  189. exit(EXIT_FAILURE);
  190. }
  191. /* end */