1*324bb76bSAndroid Build Coastguard Worker /*****************************************************************************
2*324bb76bSAndroid Build Coastguard Worker
3*324bb76bSAndroid Build Coastguard Worker gifclrmap - extract colormaps from GIF images
4*324bb76bSAndroid Build Coastguard Worker
5*324bb76bSAndroid Build Coastguard Worker SPDX-License-Identifier: MIT
6*324bb76bSAndroid Build Coastguard Worker
7*324bb76bSAndroid Build Coastguard Worker *****************************************************************************/
8*324bb76bSAndroid Build Coastguard Worker
9*324bb76bSAndroid Build Coastguard Worker #include <assert.h>
10*324bb76bSAndroid Build Coastguard Worker #include <ctype.h>
11*324bb76bSAndroid Build Coastguard Worker #include <math.h>
12*324bb76bSAndroid Build Coastguard Worker #include <stdbool.h>
13*324bb76bSAndroid Build Coastguard Worker #include <stdio.h>
14*324bb76bSAndroid Build Coastguard Worker #include <stdlib.h>
15*324bb76bSAndroid Build Coastguard Worker #include <string.h>
16*324bb76bSAndroid Build Coastguard Worker
17*324bb76bSAndroid Build Coastguard Worker #include "getarg.h"
18*324bb76bSAndroid Build Coastguard Worker #include "gif_lib.h"
19*324bb76bSAndroid Build Coastguard Worker
20*324bb76bSAndroid Build Coastguard Worker #define PROGRAM_NAME "gifclrmp"
21*324bb76bSAndroid Build Coastguard Worker
22*324bb76bSAndroid Build Coastguard Worker static char *VersionStr = PROGRAM_NAME VERSION_COOKIE
23*324bb76bSAndroid Build Coastguard Worker " Gershon Elber, " __DATE__ ", " __TIME__ "\n"
24*324bb76bSAndroid Build Coastguard Worker "(C) Copyright 1989 Gershon Elber.\n";
25*324bb76bSAndroid Build Coastguard Worker static char *CtrlStr =
26*324bb76bSAndroid Build Coastguard Worker PROGRAM_NAME " v%- s%- t%-TranslationFile!s l%-ColorMapFile!s g%-Gamma!F "
27*324bb76bSAndroid Build Coastguard Worker "i%-Image#!d h%- GifFile!*s";
28*324bb76bSAndroid Build Coastguard Worker
29*324bb76bSAndroid Build Coastguard Worker static bool SaveFlag = false, TranslateFlag = false, LoadFlag = false,
30*324bb76bSAndroid Build Coastguard Worker GammaFlag = false;
31*324bb76bSAndroid Build Coastguard Worker static double Gamma = 1.0;
32*324bb76bSAndroid Build Coastguard Worker static FILE *ColorFile = NULL;
33*324bb76bSAndroid Build Coastguard Worker FILE *TranslateFile = NULL;
34*324bb76bSAndroid Build Coastguard Worker static GifPixelType Translation[256];
35*324bb76bSAndroid Build Coastguard Worker
36*324bb76bSAndroid Build Coastguard Worker static ColorMapObject *ModifyColorMap(ColorMapObject *ColorMap);
37*324bb76bSAndroid Build Coastguard Worker static void QuitGifError(GifFileType *GifFileIn, GifFileType *GifFileOut);
38*324bb76bSAndroid Build Coastguard Worker
39*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
40*324bb76bSAndroid Build Coastguard Worker Interpret the command line and scan the given GIF file.
41*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
main(int argc,char ** argv)42*324bb76bSAndroid Build Coastguard Worker int main(int argc, char **argv) {
43*324bb76bSAndroid Build Coastguard Worker int NumFiles, ExtCode, CodeSize, ImageNum = 0, ImageN, HasGIFOutput,
44*324bb76bSAndroid Build Coastguard Worker ErrorCode;
45*324bb76bSAndroid Build Coastguard Worker bool Error, ImageNFlag = false, HelpFlag = false, GifNoisyPrint = false;
46*324bb76bSAndroid Build Coastguard Worker GifRecordType RecordType;
47*324bb76bSAndroid Build Coastguard Worker GifByteType *Extension, *CodeBlock;
48*324bb76bSAndroid Build Coastguard Worker char **FileName = NULL, *ColorFileName, *TranslateFileName;
49*324bb76bSAndroid Build Coastguard Worker GifFileType *GifFileIn = NULL, *GifFileOut = NULL;
50*324bb76bSAndroid Build Coastguard Worker
51*324bb76bSAndroid Build Coastguard Worker if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifNoisyPrint, &SaveFlag,
52*324bb76bSAndroid Build Coastguard Worker &TranslateFlag, &TranslateFileName, &LoadFlag,
53*324bb76bSAndroid Build Coastguard Worker &ColorFileName, &GammaFlag, &Gamma, &ImageNFlag,
54*324bb76bSAndroid Build Coastguard Worker &ImageN, &HelpFlag, &NumFiles, &FileName)) !=
55*324bb76bSAndroid Build Coastguard Worker false ||
56*324bb76bSAndroid Build Coastguard Worker (NumFiles > 1 && !HelpFlag)) {
57*324bb76bSAndroid Build Coastguard Worker if (Error) {
58*324bb76bSAndroid Build Coastguard Worker GAPrintErrMsg(Error);
59*324bb76bSAndroid Build Coastguard Worker } else if (NumFiles > 1) {
60*324bb76bSAndroid Build Coastguard Worker GIF_MESSAGE("Error in command line parsing - one GIF "
61*324bb76bSAndroid Build Coastguard Worker "file please.");
62*324bb76bSAndroid Build Coastguard Worker }
63*324bb76bSAndroid Build Coastguard Worker GAPrintHowTo(CtrlStr);
64*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
65*324bb76bSAndroid Build Coastguard Worker }
66*324bb76bSAndroid Build Coastguard Worker
67*324bb76bSAndroid Build Coastguard Worker if (HelpFlag) {
68*324bb76bSAndroid Build Coastguard Worker (void)fprintf(stderr, VersionStr, GIFLIB_MAJOR, GIFLIB_MINOR);
69*324bb76bSAndroid Build Coastguard Worker GAPrintHowTo(CtrlStr);
70*324bb76bSAndroid Build Coastguard Worker exit(EXIT_SUCCESS);
71*324bb76bSAndroid Build Coastguard Worker }
72*324bb76bSAndroid Build Coastguard Worker
73*324bb76bSAndroid Build Coastguard Worker if (SaveFlag + LoadFlag + GammaFlag + TranslateFlag > 1) {
74*324bb76bSAndroid Build Coastguard Worker GIF_EXIT("Can not handle more than one of -s -l, -t, or -g at "
75*324bb76bSAndroid Build Coastguard Worker "the same time.");
76*324bb76bSAndroid Build Coastguard Worker }
77*324bb76bSAndroid Build Coastguard Worker
78*324bb76bSAndroid Build Coastguard Worker /* Default action is to dump colormaps */
79*324bb76bSAndroid Build Coastguard Worker if (!SaveFlag && !LoadFlag && !GammaFlag && !TranslateFlag) {
80*324bb76bSAndroid Build Coastguard Worker SaveFlag = true;
81*324bb76bSAndroid Build Coastguard Worker }
82*324bb76bSAndroid Build Coastguard Worker
83*324bb76bSAndroid Build Coastguard Worker if (NumFiles == 1) {
84*324bb76bSAndroid Build Coastguard Worker if ((GifFileIn = DGifOpenFileName(*FileName, &ErrorCode)) ==
85*324bb76bSAndroid Build Coastguard Worker NULL) {
86*324bb76bSAndroid Build Coastguard Worker PrintGifError(ErrorCode);
87*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
88*324bb76bSAndroid Build Coastguard Worker }
89*324bb76bSAndroid Build Coastguard Worker } else {
90*324bb76bSAndroid Build Coastguard Worker /* Use stdin instead: */
91*324bb76bSAndroid Build Coastguard Worker if ((GifFileIn = DGifOpenFileHandle(0, &ErrorCode)) == NULL) {
92*324bb76bSAndroid Build Coastguard Worker PrintGifError(ErrorCode);
93*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
94*324bb76bSAndroid Build Coastguard Worker }
95*324bb76bSAndroid Build Coastguard Worker }
96*324bb76bSAndroid Build Coastguard Worker
97*324bb76bSAndroid Build Coastguard Worker if (SaveFlag) {
98*324bb76bSAndroid Build Coastguard Worker /* We are dumping out the color map as text file to stdout: */
99*324bb76bSAndroid Build Coastguard Worker ColorFile = stdout;
100*324bb76bSAndroid Build Coastguard Worker } else {
101*324bb76bSAndroid Build Coastguard Worker if (TranslateFlag) {
102*324bb76bSAndroid Build Coastguard Worker /* We are loading new color map from specified file: */
103*324bb76bSAndroid Build Coastguard Worker if ((TranslateFile = fopen(TranslateFileName, "rt")) ==
104*324bb76bSAndroid Build Coastguard Worker NULL) {
105*324bb76bSAndroid Build Coastguard Worker GIF_EXIT("Failed to open specified color "
106*324bb76bSAndroid Build Coastguard Worker "translation file.");
107*324bb76bSAndroid Build Coastguard Worker }
108*324bb76bSAndroid Build Coastguard Worker }
109*324bb76bSAndroid Build Coastguard Worker
110*324bb76bSAndroid Build Coastguard Worker if (LoadFlag) {
111*324bb76bSAndroid Build Coastguard Worker /* We are loading new color map from specified file: */
112*324bb76bSAndroid Build Coastguard Worker if ((ColorFile = fopen(ColorFileName, "rt")) == NULL) {
113*324bb76bSAndroid Build Coastguard Worker GIF_EXIT(
114*324bb76bSAndroid Build Coastguard Worker "Failed to open specified color map file.");
115*324bb76bSAndroid Build Coastguard Worker }
116*324bb76bSAndroid Build Coastguard Worker }
117*324bb76bSAndroid Build Coastguard Worker }
118*324bb76bSAndroid Build Coastguard Worker
119*324bb76bSAndroid Build Coastguard Worker if ((HasGIFOutput = (LoadFlag || TranslateFlag || GammaFlag)) != 0) {
120*324bb76bSAndroid Build Coastguard Worker /* Open stdout for GIF output file: */
121*324bb76bSAndroid Build Coastguard Worker if ((GifFileOut = EGifOpenFileHandle(1, &ErrorCode)) == NULL) {
122*324bb76bSAndroid Build Coastguard Worker PrintGifError(ErrorCode);
123*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
124*324bb76bSAndroid Build Coastguard Worker }
125*324bb76bSAndroid Build Coastguard Worker }
126*324bb76bSAndroid Build Coastguard Worker
127*324bb76bSAndroid Build Coastguard Worker if (!ImageNFlag) {
128*324bb76bSAndroid Build Coastguard Worker /* We are supposed to modify the screen color map, so do it: */
129*324bb76bSAndroid Build Coastguard Worker if (!GifFileIn->SColorMap) {
130*324bb76bSAndroid Build Coastguard Worker GIF_EXIT("No colormap to modify");
131*324bb76bSAndroid Build Coastguard Worker }
132*324bb76bSAndroid Build Coastguard Worker GifFileIn->SColorMap = ModifyColorMap(GifFileIn->SColorMap);
133*324bb76bSAndroid Build Coastguard Worker if (!HasGIFOutput) {
134*324bb76bSAndroid Build Coastguard Worker /* We can quit here, as we have the color map: */
135*324bb76bSAndroid Build Coastguard Worker DGifCloseFile(GifFileIn, NULL);
136*324bb76bSAndroid Build Coastguard Worker fclose(ColorFile);
137*324bb76bSAndroid Build Coastguard Worker exit(EXIT_SUCCESS);
138*324bb76bSAndroid Build Coastguard Worker }
139*324bb76bSAndroid Build Coastguard Worker }
140*324bb76bSAndroid Build Coastguard Worker /* And dump out its new possible repositioned screen information: */
141*324bb76bSAndroid Build Coastguard Worker if (HasGIFOutput) {
142*324bb76bSAndroid Build Coastguard Worker if (EGifPutScreenDesc(GifFileOut, GifFileIn->SWidth,
143*324bb76bSAndroid Build Coastguard Worker GifFileIn->SHeight,
144*324bb76bSAndroid Build Coastguard Worker GifFileIn->SColorResolution,
145*324bb76bSAndroid Build Coastguard Worker GifFileIn->SBackGroundColor,
146*324bb76bSAndroid Build Coastguard Worker GifFileIn->SColorMap) == GIF_ERROR) {
147*324bb76bSAndroid Build Coastguard Worker QuitGifError(GifFileIn, GifFileOut);
148*324bb76bSAndroid Build Coastguard Worker }
149*324bb76bSAndroid Build Coastguard Worker }
150*324bb76bSAndroid Build Coastguard Worker
151*324bb76bSAndroid Build Coastguard Worker /* Scan the content of the GIF file and load the image(s) in: */
152*324bb76bSAndroid Build Coastguard Worker do {
153*324bb76bSAndroid Build Coastguard Worker if (DGifGetRecordType(GifFileIn, &RecordType) == GIF_ERROR) {
154*324bb76bSAndroid Build Coastguard Worker QuitGifError(GifFileIn, GifFileOut);
155*324bb76bSAndroid Build Coastguard Worker }
156*324bb76bSAndroid Build Coastguard Worker
157*324bb76bSAndroid Build Coastguard Worker switch (RecordType) {
158*324bb76bSAndroid Build Coastguard Worker case IMAGE_DESC_RECORD_TYPE:
159*324bb76bSAndroid Build Coastguard Worker if (DGifGetImageDesc(GifFileIn) == GIF_ERROR) {
160*324bb76bSAndroid Build Coastguard Worker QuitGifError(GifFileIn, GifFileOut);
161*324bb76bSAndroid Build Coastguard Worker }
162*324bb76bSAndroid Build Coastguard Worker if ((++ImageNum == ImageN) && ImageNFlag) {
163*324bb76bSAndroid Build Coastguard Worker /* We are suppose to modify this image color
164*324bb76bSAndroid Build Coastguard Worker * map, do it: */
165*324bb76bSAndroid Build Coastguard Worker GifFileIn->SColorMap =
166*324bb76bSAndroid Build Coastguard Worker ModifyColorMap(GifFileIn->SColorMap);
167*324bb76bSAndroid Build Coastguard Worker if (!HasGIFOutput) {
168*324bb76bSAndroid Build Coastguard Worker /* We can quit here, as we have the
169*324bb76bSAndroid Build Coastguard Worker * color map: */
170*324bb76bSAndroid Build Coastguard Worker DGifCloseFile(GifFileIn, NULL);
171*324bb76bSAndroid Build Coastguard Worker fclose(ColorFile);
172*324bb76bSAndroid Build Coastguard Worker exit(EXIT_SUCCESS);
173*324bb76bSAndroid Build Coastguard Worker }
174*324bb76bSAndroid Build Coastguard Worker }
175*324bb76bSAndroid Build Coastguard Worker if (HasGIFOutput) {
176*324bb76bSAndroid Build Coastguard Worker if (EGifPutImageDesc(
177*324bb76bSAndroid Build Coastguard Worker GifFileOut, GifFileIn->Image.Left,
178*324bb76bSAndroid Build Coastguard Worker GifFileIn->Image.Top,
179*324bb76bSAndroid Build Coastguard Worker GifFileIn->Image.Width,
180*324bb76bSAndroid Build Coastguard Worker GifFileIn->Image.Height,
181*324bb76bSAndroid Build Coastguard Worker GifFileIn->Image.Interlace,
182*324bb76bSAndroid Build Coastguard Worker GifFileIn->Image.ColorMap) ==
183*324bb76bSAndroid Build Coastguard Worker GIF_ERROR) {
184*324bb76bSAndroid Build Coastguard Worker QuitGifError(GifFileIn, GifFileOut);
185*324bb76bSAndroid Build Coastguard Worker }
186*324bb76bSAndroid Build Coastguard Worker }
187*324bb76bSAndroid Build Coastguard Worker
188*324bb76bSAndroid Build Coastguard Worker if (!TranslateFlag ||
189*324bb76bSAndroid Build Coastguard Worker (ImageNFlag && (ImageN != ImageNum))) {
190*324bb76bSAndroid Build Coastguard Worker /* Now read image itself in decoded form as we
191*324bb76bSAndroid Build Coastguard Worker * don't */
192*324bb76bSAndroid Build Coastguard Worker /* really care what we have there, and this is
193*324bb76bSAndroid Build Coastguard Worker * much */
194*324bb76bSAndroid Build Coastguard Worker /* faster.
195*324bb76bSAndroid Build Coastguard Worker */
196*324bb76bSAndroid Build Coastguard Worker if (DGifGetCode(GifFileIn, &CodeSize,
197*324bb76bSAndroid Build Coastguard Worker &CodeBlock) == GIF_ERROR) {
198*324bb76bSAndroid Build Coastguard Worker QuitGifError(GifFileIn, GifFileOut);
199*324bb76bSAndroid Build Coastguard Worker }
200*324bb76bSAndroid Build Coastguard Worker if (HasGIFOutput) {
201*324bb76bSAndroid Build Coastguard Worker if (EGifPutCode(GifFileOut, CodeSize,
202*324bb76bSAndroid Build Coastguard Worker CodeBlock) ==
203*324bb76bSAndroid Build Coastguard Worker GIF_ERROR) {
204*324bb76bSAndroid Build Coastguard Worker QuitGifError(GifFileIn,
205*324bb76bSAndroid Build Coastguard Worker GifFileOut);
206*324bb76bSAndroid Build Coastguard Worker }
207*324bb76bSAndroid Build Coastguard Worker }
208*324bb76bSAndroid Build Coastguard Worker while (CodeBlock != NULL) {
209*324bb76bSAndroid Build Coastguard Worker if (DGifGetCodeNext(GifFileIn,
210*324bb76bSAndroid Build Coastguard Worker &CodeBlock) ==
211*324bb76bSAndroid Build Coastguard Worker GIF_ERROR) {
212*324bb76bSAndroid Build Coastguard Worker QuitGifError(GifFileIn,
213*324bb76bSAndroid Build Coastguard Worker GifFileOut);
214*324bb76bSAndroid Build Coastguard Worker }
215*324bb76bSAndroid Build Coastguard Worker if (HasGIFOutput) {
216*324bb76bSAndroid Build Coastguard Worker if (EGifPutCodeNext(
217*324bb76bSAndroid Build Coastguard Worker GifFileOut,
218*324bb76bSAndroid Build Coastguard Worker CodeBlock) ==
219*324bb76bSAndroid Build Coastguard Worker GIF_ERROR) {
220*324bb76bSAndroid Build Coastguard Worker QuitGifError(
221*324bb76bSAndroid Build Coastguard Worker GifFileIn,
222*324bb76bSAndroid Build Coastguard Worker GifFileOut);
223*324bb76bSAndroid Build Coastguard Worker }
224*324bb76bSAndroid Build Coastguard Worker }
225*324bb76bSAndroid Build Coastguard Worker }
226*324bb76bSAndroid Build Coastguard Worker } else /* we need to mung pixels intices */
227*324bb76bSAndroid Build Coastguard Worker {
228*324bb76bSAndroid Build Coastguard Worker int i;
229*324bb76bSAndroid Build Coastguard Worker register GifPixelType *cp;
230*324bb76bSAndroid Build Coastguard Worker
231*324bb76bSAndroid Build Coastguard Worker GifPixelType *Line = (GifPixelType *)malloc(
232*324bb76bSAndroid Build Coastguard Worker GifFileIn->Image.Width *
233*324bb76bSAndroid Build Coastguard Worker sizeof(GifPixelType));
234*324bb76bSAndroid Build Coastguard Worker for (i = 0; i < GifFileIn->Image.Height; i++) {
235*324bb76bSAndroid Build Coastguard Worker if (DGifGetLine(
236*324bb76bSAndroid Build Coastguard Worker GifFileIn, Line,
237*324bb76bSAndroid Build Coastguard Worker GifFileIn->Image.Width) ==
238*324bb76bSAndroid Build Coastguard Worker GIF_ERROR) {
239*324bb76bSAndroid Build Coastguard Worker QuitGifError(GifFileIn,
240*324bb76bSAndroid Build Coastguard Worker GifFileOut);
241*324bb76bSAndroid Build Coastguard Worker }
242*324bb76bSAndroid Build Coastguard Worker
243*324bb76bSAndroid Build Coastguard Worker /* translation step goes here */
244*324bb76bSAndroid Build Coastguard Worker for (cp = Line;
245*324bb76bSAndroid Build Coastguard Worker cp < Line + GifFileIn->Image.Width;
246*324bb76bSAndroid Build Coastguard Worker cp++) {
247*324bb76bSAndroid Build Coastguard Worker *cp = Translation[*cp];
248*324bb76bSAndroid Build Coastguard Worker }
249*324bb76bSAndroid Build Coastguard Worker
250*324bb76bSAndroid Build Coastguard Worker if (EGifPutLine(
251*324bb76bSAndroid Build Coastguard Worker GifFileOut, Line,
252*324bb76bSAndroid Build Coastguard Worker GifFileIn->Image.Width) ==
253*324bb76bSAndroid Build Coastguard Worker GIF_ERROR) {
254*324bb76bSAndroid Build Coastguard Worker QuitGifError(GifFileIn,
255*324bb76bSAndroid Build Coastguard Worker GifFileOut);
256*324bb76bSAndroid Build Coastguard Worker }
257*324bb76bSAndroid Build Coastguard Worker }
258*324bb76bSAndroid Build Coastguard Worker free((char *)Line);
259*324bb76bSAndroid Build Coastguard Worker }
260*324bb76bSAndroid Build Coastguard Worker break;
261*324bb76bSAndroid Build Coastguard Worker case EXTENSION_RECORD_TYPE:
262*324bb76bSAndroid Build Coastguard Worker assert(GifFileOut != NULL); /* might pacify Coverity */
263*324bb76bSAndroid Build Coastguard Worker /* pass through extension records */
264*324bb76bSAndroid Build Coastguard Worker if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) ==
265*324bb76bSAndroid Build Coastguard Worker GIF_ERROR) {
266*324bb76bSAndroid Build Coastguard Worker QuitGifError(GifFileIn, GifFileOut);
267*324bb76bSAndroid Build Coastguard Worker }
268*324bb76bSAndroid Build Coastguard Worker if (Extension == NULL) {
269*324bb76bSAndroid Build Coastguard Worker break;
270*324bb76bSAndroid Build Coastguard Worker }
271*324bb76bSAndroid Build Coastguard Worker if (EGifPutExtensionLeader(GifFileOut, ExtCode) ==
272*324bb76bSAndroid Build Coastguard Worker GIF_ERROR) {
273*324bb76bSAndroid Build Coastguard Worker QuitGifError(GifFileIn, GifFileOut);
274*324bb76bSAndroid Build Coastguard Worker }
275*324bb76bSAndroid Build Coastguard Worker if (EGifPutExtensionBlock(GifFileOut, Extension[0],
276*324bb76bSAndroid Build Coastguard Worker Extension + 1) == GIF_ERROR) {
277*324bb76bSAndroid Build Coastguard Worker QuitGifError(GifFileIn, GifFileOut);
278*324bb76bSAndroid Build Coastguard Worker }
279*324bb76bSAndroid Build Coastguard Worker while (Extension != NULL) {
280*324bb76bSAndroid Build Coastguard Worker if (DGifGetExtensionNext(
281*324bb76bSAndroid Build Coastguard Worker GifFileIn, &Extension) == GIF_ERROR) {
282*324bb76bSAndroid Build Coastguard Worker QuitGifError(GifFileIn, GifFileOut);
283*324bb76bSAndroid Build Coastguard Worker }
284*324bb76bSAndroid Build Coastguard Worker if (Extension != NULL) {
285*324bb76bSAndroid Build Coastguard Worker if (EGifPutExtensionBlock(
286*324bb76bSAndroid Build Coastguard Worker GifFileOut, Extension[0],
287*324bb76bSAndroid Build Coastguard Worker Extension + 1) == GIF_ERROR) {
288*324bb76bSAndroid Build Coastguard Worker QuitGifError(GifFileIn,
289*324bb76bSAndroid Build Coastguard Worker GifFileOut);
290*324bb76bSAndroid Build Coastguard Worker }
291*324bb76bSAndroid Build Coastguard Worker }
292*324bb76bSAndroid Build Coastguard Worker }
293*324bb76bSAndroid Build Coastguard Worker if (EGifPutExtensionTrailer(GifFileOut) == GIF_ERROR) {
294*324bb76bSAndroid Build Coastguard Worker QuitGifError(GifFileIn, GifFileOut);
295*324bb76bSAndroid Build Coastguard Worker }
296*324bb76bSAndroid Build Coastguard Worker break;
297*324bb76bSAndroid Build Coastguard Worker case TERMINATE_RECORD_TYPE:
298*324bb76bSAndroid Build Coastguard Worker break;
299*324bb76bSAndroid Build Coastguard Worker default: /* Should be trapped by DGifGetRecordType. */
300*324bb76bSAndroid Build Coastguard Worker break;
301*324bb76bSAndroid Build Coastguard Worker }
302*324bb76bSAndroid Build Coastguard Worker } while (RecordType != TERMINATE_RECORD_TYPE);
303*324bb76bSAndroid Build Coastguard Worker
304*324bb76bSAndroid Build Coastguard Worker if (DGifCloseFile(GifFileIn, &ErrorCode) == GIF_ERROR) {
305*324bb76bSAndroid Build Coastguard Worker PrintGifError(ErrorCode);
306*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
307*324bb76bSAndroid Build Coastguard Worker }
308*324bb76bSAndroid Build Coastguard Worker if (HasGIFOutput) {
309*324bb76bSAndroid Build Coastguard Worker if (EGifCloseFile(GifFileOut, &ErrorCode) == GIF_ERROR) {
310*324bb76bSAndroid Build Coastguard Worker PrintGifError(ErrorCode);
311*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
312*324bb76bSAndroid Build Coastguard Worker }
313*324bb76bSAndroid Build Coastguard Worker }
314*324bb76bSAndroid Build Coastguard Worker
315*324bb76bSAndroid Build Coastguard Worker return 0;
316*324bb76bSAndroid Build Coastguard Worker }
317*324bb76bSAndroid Build Coastguard Worker
318*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
319*324bb76bSAndroid Build Coastguard Worker Modify the given colormap according to global variables setting.
320*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
ModifyColorMap(ColorMapObject * ColorMap)321*324bb76bSAndroid Build Coastguard Worker static ColorMapObject *ModifyColorMap(ColorMapObject *ColorMap) {
322*324bb76bSAndroid Build Coastguard Worker int i, Dummy, Red, Green, Blue;
323*324bb76bSAndroid Build Coastguard Worker
324*324bb76bSAndroid Build Coastguard Worker if (SaveFlag) {
325*324bb76bSAndroid Build Coastguard Worker /* Save this color map to ColorFile: */
326*324bb76bSAndroid Build Coastguard Worker for (i = 0; i < ColorMap->ColorCount; i++) {
327*324bb76bSAndroid Build Coastguard Worker fprintf(ColorFile, "%3d %3d %3d %3d\n", i,
328*324bb76bSAndroid Build Coastguard Worker ColorMap->Colors[i].Red,
329*324bb76bSAndroid Build Coastguard Worker ColorMap->Colors[i].Green,
330*324bb76bSAndroid Build Coastguard Worker ColorMap->Colors[i].Blue);
331*324bb76bSAndroid Build Coastguard Worker }
332*324bb76bSAndroid Build Coastguard Worker return (ColorMap);
333*324bb76bSAndroid Build Coastguard Worker } else if (LoadFlag) {
334*324bb76bSAndroid Build Coastguard Worker /* Read the color map in ColorFile into this color map: */
335*324bb76bSAndroid Build Coastguard Worker for (i = 0; i < ColorMap->ColorCount; i++) {
336*324bb76bSAndroid Build Coastguard Worker if (feof(ColorFile)) {
337*324bb76bSAndroid Build Coastguard Worker GIF_EXIT("Color file to load color map from, "
338*324bb76bSAndroid Build Coastguard Worker "too small.");
339*324bb76bSAndroid Build Coastguard Worker }
340*324bb76bSAndroid Build Coastguard Worker if (fscanf(ColorFile, "%3d %3d %3d %3d\n", &Dummy, &Red,
341*324bb76bSAndroid Build Coastguard Worker &Green, &Blue) == 4) {
342*324bb76bSAndroid Build Coastguard Worker ColorMap->Colors[i].Red = Red;
343*324bb76bSAndroid Build Coastguard Worker ColorMap->Colors[i].Green = Green;
344*324bb76bSAndroid Build Coastguard Worker ColorMap->Colors[i].Blue = Blue;
345*324bb76bSAndroid Build Coastguard Worker }
346*324bb76bSAndroid Build Coastguard Worker }
347*324bb76bSAndroid Build Coastguard Worker return (ColorMap);
348*324bb76bSAndroid Build Coastguard Worker } else if (GammaFlag) {
349*324bb76bSAndroid Build Coastguard Worker /* Apply gamma correction to this color map: */
350*324bb76bSAndroid Build Coastguard Worker double Gamma1 = 1.0 / Gamma;
351*324bb76bSAndroid Build Coastguard Worker for (i = 0; i < ColorMap->ColorCount; i++) {
352*324bb76bSAndroid Build Coastguard Worker ColorMap->Colors[i].Red =
353*324bb76bSAndroid Build Coastguard Worker ((int)(255 * pow(ColorMap->Colors[i].Red / 255.0,
354*324bb76bSAndroid Build Coastguard Worker Gamma1)));
355*324bb76bSAndroid Build Coastguard Worker ColorMap->Colors[i].Green =
356*324bb76bSAndroid Build Coastguard Worker ((int)(255 * pow(ColorMap->Colors[i].Green / 255.0,
357*324bb76bSAndroid Build Coastguard Worker Gamma1)));
358*324bb76bSAndroid Build Coastguard Worker ColorMap->Colors[i].Blue =
359*324bb76bSAndroid Build Coastguard Worker ((int)(255 * pow(ColorMap->Colors[i].Blue / 255.0,
360*324bb76bSAndroid Build Coastguard Worker Gamma1)));
361*324bb76bSAndroid Build Coastguard Worker }
362*324bb76bSAndroid Build Coastguard Worker return (ColorMap);
363*324bb76bSAndroid Build Coastguard Worker } else if (TranslateFlag) {
364*324bb76bSAndroid Build Coastguard Worker ColorMapObject *NewMap;
365*324bb76bSAndroid Build Coastguard Worker int Max = 0;
366*324bb76bSAndroid Build Coastguard Worker
367*324bb76bSAndroid Build Coastguard Worker /* Read the translation table in TranslateFile: */
368*324bb76bSAndroid Build Coastguard Worker for (i = 0; i < ColorMap->ColorCount; i++) {
369*324bb76bSAndroid Build Coastguard Worker int tmp;
370*324bb76bSAndroid Build Coastguard Worker if (feof(TranslateFile)) {
371*324bb76bSAndroid Build Coastguard Worker GIF_EXIT("Color file to load color map from, "
372*324bb76bSAndroid Build Coastguard Worker "too small.");
373*324bb76bSAndroid Build Coastguard Worker }
374*324bb76bSAndroid Build Coastguard Worker if (fscanf(TranslateFile, "%3d %3d\n", &Dummy, &tmp) ==
375*324bb76bSAndroid Build Coastguard Worker 2) {
376*324bb76bSAndroid Build Coastguard Worker Translation[i] = tmp & 0xff;
377*324bb76bSAndroid Build Coastguard Worker if (Translation[i] > Max) {
378*324bb76bSAndroid Build Coastguard Worker Max = Translation[i];
379*324bb76bSAndroid Build Coastguard Worker }
380*324bb76bSAndroid Build Coastguard Worker }
381*324bb76bSAndroid Build Coastguard Worker }
382*324bb76bSAndroid Build Coastguard Worker
383*324bb76bSAndroid Build Coastguard Worker if ((NewMap = GifMakeMapObject(1 << GifBitSize(Max + 1),
384*324bb76bSAndroid Build Coastguard Worker NULL)) == NULL) {
385*324bb76bSAndroid Build Coastguard Worker GIF_EXIT("Out of memory while allocating color map!");
386*324bb76bSAndroid Build Coastguard Worker }
387*324bb76bSAndroid Build Coastguard Worker
388*324bb76bSAndroid Build Coastguard Worker /* Apply the translation; we'll do it to the pixels, too */
389*324bb76bSAndroid Build Coastguard Worker for (i = 0; i < ColorMap->ColorCount; i++) {
390*324bb76bSAndroid Build Coastguard Worker NewMap->Colors[i] = ColorMap->Colors[Translation[i]];
391*324bb76bSAndroid Build Coastguard Worker }
392*324bb76bSAndroid Build Coastguard Worker
393*324bb76bSAndroid Build Coastguard Worker return (NewMap);
394*324bb76bSAndroid Build Coastguard Worker } else {
395*324bb76bSAndroid Build Coastguard Worker GIF_EXIT("Nothing to do!");
396*324bb76bSAndroid Build Coastguard Worker return (ColorMap);
397*324bb76bSAndroid Build Coastguard Worker }
398*324bb76bSAndroid Build Coastguard Worker }
399*324bb76bSAndroid Build Coastguard Worker
400*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
401*324bb76bSAndroid Build Coastguard Worker Close both input and output file (if open), and exit.
402*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
QuitGifError(GifFileType * GifFileIn,GifFileType * GifFileOut)403*324bb76bSAndroid Build Coastguard Worker static void QuitGifError(GifFileType *GifFileIn, GifFileType *GifFileOut) {
404*324bb76bSAndroid Build Coastguard Worker if (GifFileIn != NULL) {
405*324bb76bSAndroid Build Coastguard Worker PrintGifError(GifFileIn->Error);
406*324bb76bSAndroid Build Coastguard Worker EGifCloseFile(GifFileIn, NULL);
407*324bb76bSAndroid Build Coastguard Worker }
408*324bb76bSAndroid Build Coastguard Worker if (GifFileOut != NULL) {
409*324bb76bSAndroid Build Coastguard Worker PrintGifError(GifFileOut->Error);
410*324bb76bSAndroid Build Coastguard Worker EGifCloseFile(GifFileOut, NULL);
411*324bb76bSAndroid Build Coastguard Worker }
412*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
413*324bb76bSAndroid Build Coastguard Worker }
414*324bb76bSAndroid Build Coastguard Worker
415*324bb76bSAndroid Build Coastguard Worker /* end */
416