xref: /aosp_15_r20/external/giflib/gifclrmp.c (revision 324bb76b8d05e2a05aa88511fff61cf3f9ca5892)
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