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