1 /*****************************************************************************
3 gifclrmap - extract colormaps from GIF images
5 SPDX-License-Identifier: MIT
7 *****************************************************************************/
20 #define PROGRAM_NAME "gifclrmp"
22 __attribute__((__section__(".tizen.build-id")))
28 __DATE__ ", " __TIME__ "\n"
29 "(C) Copyright 1989 Gershon Elber.\n";
33 " v%- s%- t%-TranslationFile!s l%-ColorMapFile!s g%-Gamma!F i%-Image#!d h%- GifFile!*s";
37 TranslateFlag = false,
43 FILE *ColorFile = NULL;
44 FILE *TranslateFile = NULL;
46 GifPixelType Translation[256];
48 static ColorMapObject *ModifyColorMap(ColorMapObject *ColorMap);
49 static void QuitGifError(GifFileType *GifFileIn, GifFileType *GifFileOut);
51 /******************************************************************************
52 Interpret the command line and scan the given GIF file.
53 ******************************************************************************/
54 int main(int argc, char **argv)
56 int NumFiles, ExtCode, CodeSize, ImageNum = 0,
57 ImageN, HasGIFOutput, ErrorCode;
58 bool Error, ImageNFlag = false, HelpFlag = false;
59 GifRecordType RecordType;
60 GifByteType *Extension, *CodeBlock;
61 char **FileName = NULL, *ColorFileName, *TranslateFileName;
62 GifFileType *GifFileIn = NULL, *GifFileOut = NULL;
64 if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifNoisyPrint, &SaveFlag,
65 &TranslateFlag, &TranslateFileName,
66 &LoadFlag, &ColorFileName,
67 &GammaFlag, &Gamma, &ImageNFlag, &ImageN,
68 &HelpFlag, &NumFiles, &FileName)) != false ||
69 (NumFiles > 1 && !HelpFlag)) {
72 else if (NumFiles > 1)
73 GIF_MESSAGE("Error in command line parsing - one GIF file please.");
74 GAPrintHowTo(CtrlStr);
79 (void)fprintf(stderr, VersionStr, GIFLIB_MAJOR, GIFLIB_MINOR);
80 GAPrintHowTo(CtrlStr);
84 if (SaveFlag + LoadFlag + GammaFlag + TranslateFlag > 1)
85 GIF_EXIT("Can not handle more than one of -s -l, -t, or -g at the same time.");
87 /* Default action is to dump colormaps */
88 if (!SaveFlag && !LoadFlag && !GammaFlag && !TranslateFlag)
92 if ((GifFileIn = DGifOpenFileName(*FileName, &ErrorCode)) == NULL) {
93 PrintGifError(ErrorCode);
98 /* Use stdin instead: */
99 if ((GifFileIn = DGifOpenFileHandle(0, &ErrorCode)) == NULL) {
100 PrintGifError(ErrorCode);
106 /* We are dumping out the color map as text file to stdout: */
111 /* We are loading new color map from specified file: */
112 if ((TranslateFile = fopen(TranslateFileName, "rt")) == NULL)
113 GIF_EXIT("Failed to open specified color translation file.");
117 /* We are loading new color map from specified file: */
118 if ((ColorFile = fopen(ColorFileName, "rt")) == NULL)
119 GIF_EXIT("Failed to open specified color map file.");
123 if ((HasGIFOutput = (LoadFlag || TranslateFlag || GammaFlag)) != 0) {
124 /* Open stdout for GIF output file: */
125 if ((GifFileOut = EGifOpenFileHandle(1, &ErrorCode)) == NULL) {
126 PrintGifError(ErrorCode);
132 /* We are supposed to modify the screen color map, so do it: */
133 if (!GifFileIn->SColorMap)
134 GIF_EXIT("No colormap to modify");
135 GifFileIn->SColorMap = ModifyColorMap(GifFileIn->SColorMap);
137 /* We can quit here, as we have the color map: */
138 DGifCloseFile(GifFileIn, NULL);
143 /* And dump out its new possible repositioned screen information: */
145 if (EGifPutScreenDesc(GifFileOut,
146 GifFileIn->SWidth, GifFileIn->SHeight,
147 GifFileIn->SColorResolution, GifFileIn->SBackGroundColor,
148 GifFileIn->SColorMap) == GIF_ERROR)
149 QuitGifError(GifFileIn, GifFileOut);
151 /* Scan the content of the GIF file and load the image(s) in: */
153 if (DGifGetRecordType(GifFileIn, &RecordType) == GIF_ERROR)
154 QuitGifError(GifFileIn, GifFileOut);
156 switch (RecordType) {
157 case IMAGE_DESC_RECORD_TYPE:
158 if (DGifGetImageDesc(GifFileIn) == GIF_ERROR)
159 QuitGifError(GifFileIn, GifFileOut);
160 if ((++ImageNum == ImageN) && ImageNFlag) {
161 /* We are suppose to modify this image color map, do it: */
162 GifFileIn->SColorMap =ModifyColorMap(GifFileIn->SColorMap);
164 /* We can quit here, as we have the color map: */
165 DGifCloseFile(GifFileIn, NULL);
171 if (EGifPutImageDesc(GifFileOut,
172 GifFileIn->Image.Left, GifFileIn->Image.Top,
173 GifFileIn->Image.Width, GifFileIn->Image.Height,
174 GifFileIn->Image.Interlace,
175 GifFileIn->Image.ColorMap) == GIF_ERROR)
176 QuitGifError(GifFileIn, GifFileOut);
178 if (!TranslateFlag || (ImageNFlag && (ImageN != ImageNum)))
180 /* Now read image itself in decoded form as we don't */
181 /* really care what we have there, and this is much */
183 if (DGifGetCode(GifFileIn, &CodeSize, &CodeBlock) == GIF_ERROR)
184 QuitGifError(GifFileIn, GifFileOut);
186 if (EGifPutCode(GifFileOut, CodeSize, CodeBlock) == GIF_ERROR)
187 QuitGifError(GifFileIn, GifFileOut);
188 while (CodeBlock != NULL) {
189 if (DGifGetCodeNext(GifFileIn, &CodeBlock) == GIF_ERROR)
190 QuitGifError(GifFileIn, GifFileOut);
192 if (EGifPutCodeNext(GifFileOut, CodeBlock) == GIF_ERROR)
193 QuitGifError(GifFileIn, GifFileOut);
196 else /* we need to mung pixels intices */
199 register GifPixelType *cp;
202 = (GifPixelType *) malloc(GifFileIn->Image.Width *
203 sizeof(GifPixelType));
204 for (i = 0; i < GifFileIn->Image.Height; i++) {
205 if (DGifGetLine(GifFileIn, Line,GifFileIn->Image.Width)
207 QuitGifError(GifFileIn, GifFileOut);
210 /* translation step goes here */
211 for (cp = Line; cp < Line+GifFileIn->Image.Width; cp++)
212 *cp = Translation[*cp];
214 if (EGifPutLine(GifFileOut,
215 Line, GifFileIn->Image.Width)
217 QuitGifError(GifFileIn, GifFileOut);
223 case EXTENSION_RECORD_TYPE:
224 assert(GifFileOut != NULL); /* might pacify Coverity */
225 /* pass through extension records */
226 if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) == GIF_ERROR)
227 QuitGifError(GifFileIn, GifFileOut);
228 if (Extension == NULL)
230 if (EGifPutExtensionLeader(GifFileOut, ExtCode) == GIF_ERROR)
231 QuitGifError(GifFileIn, GifFileOut);
232 if (EGifPutExtensionBlock(GifFileOut,
234 Extension + 1) == GIF_ERROR)
235 QuitGifError(GifFileIn, GifFileOut);
236 while (Extension != NULL) {
237 if (DGifGetExtensionNext(GifFileIn, &Extension)==GIF_ERROR)
238 QuitGifError(GifFileIn, GifFileOut);
239 if (Extension != NULL)
240 if (EGifPutExtensionBlock(GifFileOut,
242 Extension + 1) == GIF_ERROR)
243 QuitGifError(GifFileIn, GifFileOut);
245 if (EGifPutExtensionTrailer(GifFileOut) == GIF_ERROR)
246 QuitGifError(GifFileIn, GifFileOut);
248 case TERMINATE_RECORD_TYPE:
250 default: /* Should be trapped by DGifGetRecordType. */
254 while (RecordType != TERMINATE_RECORD_TYPE);
256 if (DGifCloseFile(GifFileIn, &ErrorCode) == GIF_ERROR)
258 PrintGifError(ErrorCode);
262 if (EGifCloseFile(GifFileOut, &ErrorCode) == GIF_ERROR)
264 PrintGifError(ErrorCode);
271 /******************************************************************************
272 Modify the given colormap according to global variables setting.
273 ******************************************************************************/
274 static ColorMapObject *ModifyColorMap(ColorMapObject *ColorMap)
276 int i, Dummy, Red, Green, Blue;
279 /* Save this color map to ColorFile: */
280 for (i = 0; i < ColorMap->ColorCount; i++)
281 fprintf(ColorFile, "%3d %3d %3d %3d\n", i,
282 ColorMap->Colors[i].Red,
283 ColorMap->Colors[i].Green,
284 ColorMap->Colors[i].Blue);
288 /* Read the color map in ColorFile into this color map: */
289 for (i = 0; i < ColorMap->ColorCount; i++) {
291 GIF_EXIT("Color file to load color map from, too small.");
292 if (fscanf(ColorFile, "%3d %3d %3d %3d\n", &Dummy, &Red, &Green, &Blue) == 4) {
293 ColorMap->Colors[i].Red = Red;
294 ColorMap->Colors[i].Green = Green;
295 ColorMap->Colors[i].Blue = Blue;
300 else if (GammaFlag) {
301 /* Apply gamma correction to this color map: */
302 double Gamma1 = 1.0 / Gamma;
303 for (i = 0; i < ColorMap->ColorCount; i++) {
304 ColorMap->Colors[i].Red =
305 ((int) (255 * pow(ColorMap->Colors[i].Red / 255.0, Gamma1)));
306 ColorMap->Colors[i].Green =
307 ((int) (255 * pow(ColorMap->Colors[i].Green / 255.0, Gamma1)));
308 ColorMap->Colors[i].Blue =
309 ((int) (255 * pow(ColorMap->Colors[i].Blue / 255.0, Gamma1)));
313 else if (TranslateFlag) {
314 ColorMapObject *NewMap;
317 /* Read the translation table in TranslateFile: */
318 for (i = 0; i < ColorMap->ColorCount; i++) {
320 if (feof(TranslateFile))
321 GIF_EXIT("Color file to load color map from, too small.");
322 if (fscanf(TranslateFile, "%3d %3d\n", &Dummy, &tmp) == 2) {
323 Translation[i] = tmp & 0xff;
324 if (Translation[i] > Max)
325 Max = Translation[i];
329 if ((NewMap = GifMakeMapObject(1 << GifBitSize(Max+1), NULL)) == NULL)
330 GIF_EXIT("Out of memory while allocating color map!");
332 /* Apply the translation; we'll do it to the pixels, too */
333 for (i = 0; i < ColorMap->ColorCount; i++) {
334 NewMap->Colors[i] = ColorMap->Colors[Translation[i]];
341 GIF_EXIT("Nothing to do!");
346 /******************************************************************************
347 Close both input and output file (if open), and exit.
348 ******************************************************************************/
349 static void QuitGifError(GifFileType *GifFileIn, GifFileType *GifFileOut)
351 if (GifFileIn != NULL) {
352 PrintGifError(GifFileIn->Error);
353 EGifCloseFile(GifFileIn, NULL);
355 if (GifFileOut != NULL) {
356 PrintGifError(GifFileOut->Error);
357 EGifCloseFile(GifFileOut, NULL);