1 /*****************************************************************************
3 giftext - dump GIF pixels and metadata as text
5 SPDX-License-Identifier: MIT
7 *****************************************************************************/
22 #define PROGRAM_NAME "giftext"
24 #define MAKE_PRINTABLE(c) (isprint(c) ? (c) : ' ')
26 __attribute__((__section__(".tizen.build-id")))
32 __DATE__ ", " __TIME__ "\n"
33 "(C) Copyright 1989 Gershon Elber.\n";
37 " v%- c%- e%- z%- p%- r%- h%- GifFile!*s";
39 static void PrintCodeBlock(GifFileType *GifFile, GifByteType *CodeBlock, bool Reset);
40 static void PrintPixelBlock(GifByteType *PixelBlock, int Len, bool Reset);
41 static void PrintExtBlock(GifByteType *Extension, bool Reset);
42 static void PrintLZCodes(GifFileType *GifFile);
44 /******************************************************************************
45 Interpret the command line and scan the given GIF file.
46 ******************************************************************************/
47 int main(int argc, char **argv)
49 int i, j, ExtCode, ErrorCode, CodeSize, NumFiles, Len, ImageNum = 1;
51 ColorMapFlag = false, EncodedFlag = false, LZCodesFlag = false,
52 PixelFlag = false, HelpFlag = false, RawFlag = false;
53 char *GifFileName, **FileName = NULL;
55 GifRecordType RecordType;
56 GifByteType *CodeBlock, *Extension;
59 if ((Error = GAGetArgs(argc, argv, CtrlStr,
60 &GifNoisyPrint, &ColorMapFlag, &EncodedFlag,
61 &LZCodesFlag, &PixelFlag, &RawFlag, &HelpFlag,
62 &NumFiles, &FileName)) != false ||
63 (NumFiles > 1 && !HelpFlag)) {
66 else if (NumFiles > 1)
67 GIF_MESSAGE("Error in command line parsing - one GIF file please.");
68 GAPrintHowTo(CtrlStr);
73 (void)fprintf(stderr, VersionStr, GIFLIB_MAJOR, GIFLIB_MINOR);
74 GAPrintHowTo(CtrlStr);
79 GifFileName = *FileName;
80 if ((GifFile = DGifOpenFileName(*FileName, &ErrorCode)) == NULL) {
81 PrintGifError(ErrorCode);
86 /* Use stdin instead: */
87 GifFileName = "Stdin";
88 if ((GifFile = DGifOpenFileHandle(0, &ErrorCode)) == NULL) {
89 PrintGifError(ErrorCode);
94 /* Because we write binary data - make sure no text will be written. */
96 ColorMapFlag = EncodedFlag = LZCodesFlag = PixelFlag = false;
98 _setmode(1, O_BINARY); /* Make sure it is in binary mode. */
102 printf("\n%s:\n\n\tScreen Size - Width = %d, Height = %d.\n",
103 GifFileName, GifFile->SWidth, GifFile->SHeight);
104 printf("\tColorResolution = %d, BitsPerPixel = %d, BackGround = %d, Aspect = %d.\n",
105 GifFile->SColorResolution,
106 GifFile->SColorMap ? GifFile->SColorMap->BitsPerPixel : 0,
107 GifFile->SBackGroundColor,
108 GifFile->AspectByte);
109 if (GifFile->SColorMap)
110 printf("\tHas Global Color Map.\n\n");
112 printf("\tNo Global Color Map.\n\n");
113 if (ColorMapFlag && GifFile->SColorMap) {
114 printf("\tGlobal Color Map:\n");
115 Len = GifFile->SColorMap->ColorCount;
116 printf("\tSort Flag: %s\n",
117 GifFile->SColorMap->SortFlag ? "on":"off");
118 for (i = 0; i < Len; i+=4) {
119 for (j = 0; j < 4 && j < Len; j++) {
120 printf("%3d: %02xh %02xh %02xh ", i + j,
121 GifFile->SColorMap->Colors[i + j].Red,
122 GifFile->SColorMap->Colors[i + j].Green,
123 GifFile->SColorMap->Colors[i + j].Blue);
131 if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) {
132 PrintGifError(GifFile->Error);
135 switch (RecordType) {
136 case IMAGE_DESC_RECORD_TYPE:
137 if (DGifGetImageDesc(GifFile) == GIF_ERROR) {
138 PrintGifError(GifFile->Error);
142 printf("\nImage #%d:\n\n\tImage Size - Left = %d, Top = %d, Width = %d, Height = %d.\n",
143 ImageNum++, GifFile->Image.Left, GifFile->Image.Top,
144 GifFile->Image.Width, GifFile->Image.Height);
145 printf("\tImage is %s",
146 GifFile->Image.Interlace ? "Interlaced" :
148 if (GifFile->Image.ColorMap != NULL)
149 printf(", BitsPerPixel = %d.\n",
150 GifFile->Image.ColorMap->BitsPerPixel);
153 if (GifFile->Image.ColorMap)
154 printf("\tImage Has Color Map.\n");
156 printf("\tNo Image Color Map.\n");
157 if (ColorMapFlag && GifFile->Image.ColorMap) {
158 printf("\tSort Flag: %s\n",
159 GifFile->Image.ColorMap->SortFlag ? "on":"off");
160 Len = 1 << GifFile->Image.ColorMap->BitsPerPixel;
161 for (i = 0; i < Len; i+=4) {
162 for (j = 0; j < 4 && j < Len; j++) {
163 printf("%3d: %02xh %02xh %02xh ", i + j,
164 GifFile->Image.ColorMap->Colors[i + j].Red,
165 GifFile->Image.ColorMap->Colors[i + j].Green,
166 GifFile->Image.ColorMap->Colors[i + j].Blue);
174 if (DGifGetCode(GifFile, &CodeSize, &CodeBlock) == GIF_ERROR) {
175 PrintGifError(GifFile->Error);
178 printf("\nImage LZ compressed Codes (Code Size = %d):\n",
180 PrintCodeBlock(GifFile, CodeBlock, true);
181 while (CodeBlock != NULL) {
182 if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR) {
183 PrintGifError(GifFile->Error);
186 PrintCodeBlock(GifFile, CodeBlock, false);
189 else if (LZCodesFlag) {
190 PrintLZCodes(GifFile);
192 else if (PixelFlag) {
193 Line = (GifPixelType *) malloc(GifFile->Image.Width *
194 sizeof(GifPixelType));
195 for (i = 0; i < GifFile->Image.Height; i++) {
196 if (DGifGetLine(GifFile, Line, GifFile->Image.Width)
198 PrintGifError(GifFile->Error);
201 PrintPixelBlock(Line, GifFile->Image.Width, i == 0);
203 PrintPixelBlock(NULL, GifFile->Image.Width, false);
207 Line = (GifPixelType *) malloc(GifFile->Image.Width *
208 sizeof(GifPixelType));
209 for (i = 0; i < GifFile->Image.Height; i++) {
210 if (DGifGetLine(GifFile, Line, GifFile->Image.Width)
212 PrintGifError(GifFile->Error);
215 fwrite(Line, 1, GifFile->Image.Width, stdout);
220 /* Skip the image: */
221 if (DGifGetCode(GifFile, &CodeSize, &CodeBlock) == GIF_ERROR) {
222 PrintGifError(GifFile->Error);
225 while (CodeBlock != NULL) {
226 if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR) {
227 PrintGifError(GifFile->Error);
234 case EXTENSION_RECORD_TYPE:
235 if (DGifGetExtension(GifFile, &ExtCode, &Extension) == GIF_ERROR) {
236 PrintGifError(GifFile->Error);
243 case COMMENT_EXT_FUNC_CODE:
244 printf("GIF89 comment");
246 case GRAPHICS_EXT_FUNC_CODE:
247 printf("GIF89 graphics control");
249 case PLAINTEXT_EXT_FUNC_CODE:
250 printf("GIF89 plaintext");
252 case APPLICATION_EXT_FUNC_CODE:
253 printf("GIF89 application block");
256 printf("Extension record of unknown type");
259 printf(" (Ext Code = %d [%c]):\n",
260 ExtCode, MAKE_PRINTABLE(ExtCode));
261 PrintExtBlock(Extension, true);
263 if (ExtCode == GRAPHICS_EXT_FUNC_CODE) {
264 GraphicsControlBlock gcb;
265 if (Extension == NULL) {
266 printf("Invalid extension block\n");
267 GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
268 PrintGifError(GifFile->Error);
271 if (DGifExtensionToGCB(Extension[0], Extension+1, &gcb) == GIF_ERROR) {
272 PrintGifError(GifFile->Error);
275 printf("\tDisposal Mode: %d\n", gcb.DisposalMode);
276 printf("\tUser Input Flag: %d\n", gcb.UserInputFlag);
277 printf("\tTransparency on: %s\n",
278 gcb.TransparentColor != -1 ? "yes" : "no");
279 printf("\tDelayTime: %d\n", gcb.DelayTime);
280 printf("\tTransparent Index: %d\n", gcb.TransparentColor);
284 if (DGifGetExtensionNext(GifFile, &Extension) == GIF_ERROR) {
285 PrintGifError(GifFile->Error);
288 if (Extension == NULL)
290 PrintExtBlock(Extension, false);
293 case TERMINATE_RECORD_TYPE:
295 default: /* Should be trapped by DGifGetRecordType */
299 while (RecordType != TERMINATE_RECORD_TYPE);
301 if (DGifCloseFile(GifFile, &ErrorCode) == GIF_ERROR) {
302 PrintGifError(ErrorCode);
306 if (!RawFlag) printf("\nGIF file terminated normally.\n");
311 /******************************************************************************
312 Print the given CodeBlock - a string in pascal notation (size in first
313 place). Save local information so printing can be performed continuously,
314 or reset to start state if Reset. If CodeBlock is NULL, output is flushed
315 ******************************************************************************/
316 static void PrintCodeBlock(GifFileType *GifFile, GifByteType *CodeBlock, bool Reset)
318 static int CrntPlace = 0;
319 static long CodeCount = 0;
322 if (Reset || CodeBlock == NULL) {
323 if (CodeBlock == NULL) {
327 CodeCount += CrntPlace - 16;
329 if (GifFile->Image.ColorMap)
330 NumBytes = ((((long) GifFile->Image.Width) * GifFile->Image.Height)
331 * GifFile->Image.ColorMap->BitsPerPixel) / 8;
332 else if (GifFile->SColorMap != NULL)
333 NumBytes = ((((long) GifFile->Image.Width) * GifFile->Image.Height)
334 * GifFile->SColorMap->BitsPerPixel) / 8;
335 /* FIXME: What should the compression ratio be if no color table? */
337 int Percent = 100 * CodeCount / NumBytes;
338 printf("\nCompression ratio: %ld/%ld (%d%%).\n",
339 CodeCount, NumBytes, Percent);
348 for (i = 1; i <= Len; i++) {
349 if (CrntPlace == 0) {
350 printf("\n%05lxh: ", CodeCount);
353 (void)printf(" %02xh", CodeBlock[i]);
354 if (++CrntPlace >= 16) CrntPlace = 0;
358 /******************************************************************************
359 Print the given Extension - a string in pascal notation (size in first
360 place). Save local information so printing can be performed continuously,
361 or reset to start state if Reset. If Extension is NULL, output is flushed
362 ******************************************************************************/
363 static void PrintExtBlock(GifByteType *Extension, bool Reset)
365 static int CrntPlace = 0;
366 static long ExtCount = 0;
367 static char HexForm[49], AsciiForm[17];
369 if (Reset || Extension == NULL) {
370 if (Extension == NULL) {
372 HexForm[CrntPlace * 3] = 0;
373 AsciiForm[CrntPlace] = 0;
374 printf("\n%05lx: %-49s %-17s\n", ExtCount, HexForm, AsciiForm);
384 if (Extension != NULL) {
387 for (i = 1; i <= Len; i++) {
388 (void)snprintf(&HexForm[CrntPlace * 3], 3,
389 " %02x", Extension[i]);
390 (void)snprintf(&AsciiForm[CrntPlace], 3,
391 "%c", MAKE_PRINTABLE(Extension[i]));
392 if (++CrntPlace == 16) {
393 HexForm[CrntPlace * 3] = 0;
394 AsciiForm[CrntPlace] = 0;
395 printf("\n%05lx: %-49s %-17s", ExtCount, HexForm, AsciiForm);
403 /******************************************************************************
404 Print the given PixelBlock of length Len.
405 Save local information so printing can be performed continuously,
406 or reset to start state if Reset. If PixelBlock is NULL, output is flushed
407 ******************************************************************************/
408 static void PrintPixelBlock(GifByteType *PixelBlock, int Len, bool Reset)
410 static int CrntPlace = 0;
411 static long ExtCount = 0;
412 static char HexForm[49], AsciiForm[17];
415 if (Reset || PixelBlock == NULL) {
416 if (PixelBlock == NULL) {
418 HexForm[CrntPlace * 3] = 0;
419 AsciiForm[CrntPlace] = 0;
420 printf("\n%05lx: %-49s %-17s\n", ExtCount, HexForm, AsciiForm);
427 if (PixelBlock == NULL) return;
430 for (i = 0; i < Len; i++) {
431 (void)snprintf(&HexForm[CrntPlace * 3], 3,
432 " %02x", PixelBlock[i]);
433 (void)snprintf(&AsciiForm[CrntPlace], 3,
434 "%c", MAKE_PRINTABLE(PixelBlock[i]));
435 if (++CrntPlace == 16) {
436 HexForm[CrntPlace * 3] = 0;
437 AsciiForm[CrntPlace] = 0;
438 printf("\n%05lx: %-49s %-17s", ExtCount, HexForm, AsciiForm);
445 /******************************************************************************
446 Print the image as LZ codes (each 12bits), until EOF marker is reached.
447 ******************************************************************************/
448 static void PrintLZCodes(GifFileType *GifFile)
450 int Code, CrntPlace = 0;
454 if (CrntPlace == 0) printf("\n%05lx:", CodeCount);
455 if (DGifGetLZCodes(GifFile, &Code) == GIF_ERROR) {
456 PrintGifError(GifFile->Error);
460 printf(" %03x", Code); /* EOF Code is returned as -1. */
462 if (++CrntPlace >= 16) CrntPlace = 0;