1*324bb76bSAndroid Build Coastguard Worker /*****************************************************************************
2*324bb76bSAndroid Build Coastguard Worker
3*324bb76bSAndroid Build Coastguard Worker giftext - dump GIF pixels and metadata as text
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 <ctype.h>
10*324bb76bSAndroid Build Coastguard Worker #include <fcntl.h>
11*324bb76bSAndroid Build Coastguard Worker #include <stdbool.h>
12*324bb76bSAndroid Build Coastguard Worker #include <stdio.h>
13*324bb76bSAndroid Build Coastguard Worker #include <stdlib.h>
14*324bb76bSAndroid Build Coastguard Worker
15*324bb76bSAndroid Build Coastguard Worker #ifdef _WIN32
16*324bb76bSAndroid Build Coastguard Worker #include <io.h>
17*324bb76bSAndroid Build Coastguard Worker #endif /* _WIN32 */
18*324bb76bSAndroid Build Coastguard Worker
19*324bb76bSAndroid Build Coastguard Worker #include "getarg.h"
20*324bb76bSAndroid Build Coastguard Worker #include "gif_lib.h"
21*324bb76bSAndroid Build Coastguard Worker
22*324bb76bSAndroid Build Coastguard Worker #define PROGRAM_NAME "giftext"
23*324bb76bSAndroid Build Coastguard Worker
24*324bb76bSAndroid Build Coastguard Worker #define MAKE_PRINTABLE(c) (isprint(c) ? (c) : ' ')
25*324bb76bSAndroid Build Coastguard Worker
26*324bb76bSAndroid Build Coastguard Worker static char *VersionStr = PROGRAM_NAME VERSION_COOKIE
27*324bb76bSAndroid Build Coastguard Worker " Gershon Elber, " __DATE__ ", " __TIME__ "\n"
28*324bb76bSAndroid Build Coastguard Worker "(C) Copyright 1989 Gershon Elber.\n";
29*324bb76bSAndroid Build Coastguard Worker static char *CtrlStr = PROGRAM_NAME " v%- c%- e%- z%- p%- r%- h%- GifFile!*s";
30*324bb76bSAndroid Build Coastguard Worker
31*324bb76bSAndroid Build Coastguard Worker static void PrintCodeBlock(GifFileType *GifFile, GifByteType *CodeBlock,
32*324bb76bSAndroid Build Coastguard Worker bool Reset);
33*324bb76bSAndroid Build Coastguard Worker static void PrintPixelBlock(GifByteType *PixelBlock, int Len, bool Reset);
34*324bb76bSAndroid Build Coastguard Worker static void PrintExtBlock(GifByteType *Extension, bool Reset);
35*324bb76bSAndroid Build Coastguard Worker static void PrintLZCodes(GifFileType *GifFile);
36*324bb76bSAndroid Build Coastguard Worker
37*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
38*324bb76bSAndroid Build Coastguard Worker Interpret the command line and scan the given GIF file.
39*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
main(int argc,char ** argv)40*324bb76bSAndroid Build Coastguard Worker int main(int argc, char **argv) {
41*324bb76bSAndroid Build Coastguard Worker int i, j, ExtCode, ErrorCode, CodeSize, NumFiles, Len, ImageNum = 1;
42*324bb76bSAndroid Build Coastguard Worker bool Error, ColorMapFlag = false, EncodedFlag = false,
43*324bb76bSAndroid Build Coastguard Worker LZCodesFlag = false, PixelFlag = false, HelpFlag = false,
44*324bb76bSAndroid Build Coastguard Worker RawFlag = false, GifNoisyPrint;
45*324bb76bSAndroid Build Coastguard Worker char *GifFileName, **FileName = NULL;
46*324bb76bSAndroid Build Coastguard Worker GifPixelType *Line;
47*324bb76bSAndroid Build Coastguard Worker GifRecordType RecordType;
48*324bb76bSAndroid Build Coastguard Worker GifByteType *CodeBlock, *Extension;
49*324bb76bSAndroid Build Coastguard Worker GifFileType *GifFile;
50*324bb76bSAndroid Build Coastguard Worker
51*324bb76bSAndroid Build Coastguard Worker if ((Error =
52*324bb76bSAndroid Build Coastguard Worker GAGetArgs(argc, argv, CtrlStr, &GifNoisyPrint, &ColorMapFlag,
53*324bb76bSAndroid Build Coastguard Worker &EncodedFlag, &LZCodesFlag, &PixelFlag, &RawFlag,
54*324bb76bSAndroid Build Coastguard Worker &HelpFlag, &NumFiles, &FileName)) != false ||
55*324bb76bSAndroid Build Coastguard Worker (NumFiles > 1 && !HelpFlag)) {
56*324bb76bSAndroid Build Coastguard Worker if (Error) {
57*324bb76bSAndroid Build Coastguard Worker GAPrintErrMsg(Error);
58*324bb76bSAndroid Build Coastguard Worker } else if (NumFiles > 1) {
59*324bb76bSAndroid Build Coastguard Worker GIF_MESSAGE("Error in command line parsing - one GIF "
60*324bb76bSAndroid Build Coastguard Worker "file please.");
61*324bb76bSAndroid Build Coastguard Worker }
62*324bb76bSAndroid Build Coastguard Worker GAPrintHowTo(CtrlStr);
63*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
64*324bb76bSAndroid Build Coastguard Worker }
65*324bb76bSAndroid Build Coastguard Worker
66*324bb76bSAndroid Build Coastguard Worker if (HelpFlag) {
67*324bb76bSAndroid Build Coastguard Worker (void)fprintf(stderr, VersionStr, GIFLIB_MAJOR, GIFLIB_MINOR);
68*324bb76bSAndroid Build Coastguard Worker GAPrintHowTo(CtrlStr);
69*324bb76bSAndroid Build Coastguard Worker exit(EXIT_SUCCESS);
70*324bb76bSAndroid Build Coastguard Worker }
71*324bb76bSAndroid Build Coastguard Worker
72*324bb76bSAndroid Build Coastguard Worker if (NumFiles == 1) {
73*324bb76bSAndroid Build Coastguard Worker GifFileName = *FileName;
74*324bb76bSAndroid Build Coastguard Worker if ((GifFile = DGifOpenFileName(*FileName, &ErrorCode)) ==
75*324bb76bSAndroid Build Coastguard Worker NULL) {
76*324bb76bSAndroid Build Coastguard Worker PrintGifError(ErrorCode);
77*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
78*324bb76bSAndroid Build Coastguard Worker }
79*324bb76bSAndroid Build Coastguard Worker } else {
80*324bb76bSAndroid Build Coastguard Worker /* Use stdin instead: */
81*324bb76bSAndroid Build Coastguard Worker GifFileName = "Stdin";
82*324bb76bSAndroid Build Coastguard Worker if ((GifFile = DGifOpenFileHandle(0, &ErrorCode)) == NULL) {
83*324bb76bSAndroid Build Coastguard Worker PrintGifError(ErrorCode);
84*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
85*324bb76bSAndroid Build Coastguard Worker }
86*324bb76bSAndroid Build Coastguard Worker }
87*324bb76bSAndroid Build Coastguard Worker
88*324bb76bSAndroid Build Coastguard Worker /* Because we write binary data - make sure no text will be written. */
89*324bb76bSAndroid Build Coastguard Worker if (RawFlag) {
90*324bb76bSAndroid Build Coastguard Worker ColorMapFlag = EncodedFlag = LZCodesFlag = PixelFlag = false;
91*324bb76bSAndroid Build Coastguard Worker #ifdef _WIN32
92*324bb76bSAndroid Build Coastguard Worker _setmode(1, O_BINARY); /* Make sure it is in binary mode. */
93*324bb76bSAndroid Build Coastguard Worker #endif /* _WIN32 */
94*324bb76bSAndroid Build Coastguard Worker } else {
95*324bb76bSAndroid Build Coastguard Worker printf("\n%s:\n\n\tScreen Size - Width = %d, Height = %d.\n",
96*324bb76bSAndroid Build Coastguard Worker GifFileName, GifFile->SWidth, GifFile->SHeight);
97*324bb76bSAndroid Build Coastguard Worker printf("\tColorResolution = %d, BitsPerPixel = %d, BackGround "
98*324bb76bSAndroid Build Coastguard Worker "= %d, Aspect = %d.\n",
99*324bb76bSAndroid Build Coastguard Worker GifFile->SColorResolution,
100*324bb76bSAndroid Build Coastguard Worker GifFile->SColorMap ? GifFile->SColorMap->BitsPerPixel
101*324bb76bSAndroid Build Coastguard Worker : 0,
102*324bb76bSAndroid Build Coastguard Worker GifFile->SBackGroundColor, GifFile->AspectByte);
103*324bb76bSAndroid Build Coastguard Worker if (GifFile->SColorMap) {
104*324bb76bSAndroid Build Coastguard Worker printf("\tHas Global Color Map.\n\n");
105*324bb76bSAndroid Build Coastguard Worker } else {
106*324bb76bSAndroid Build Coastguard Worker printf("\tNo Global Color Map.\n\n");
107*324bb76bSAndroid Build Coastguard Worker }
108*324bb76bSAndroid Build Coastguard Worker if (ColorMapFlag && GifFile->SColorMap) {
109*324bb76bSAndroid Build Coastguard Worker printf("\tGlobal Color Map:\n");
110*324bb76bSAndroid Build Coastguard Worker Len = GifFile->SColorMap->ColorCount;
111*324bb76bSAndroid Build Coastguard Worker printf("\tSort Flag: %s\n",
112*324bb76bSAndroid Build Coastguard Worker GifFile->SColorMap->SortFlag ? "on" : "off");
113*324bb76bSAndroid Build Coastguard Worker for (i = 0; i < Len; i += 4) {
114*324bb76bSAndroid Build Coastguard Worker for (j = 0; j < 4 && j < Len; j++) {
115*324bb76bSAndroid Build Coastguard Worker printf("%3d: %02xh %02xh %02xh ",
116*324bb76bSAndroid Build Coastguard Worker i + j,
117*324bb76bSAndroid Build Coastguard Worker GifFile->SColorMap->Colors[i + j]
118*324bb76bSAndroid Build Coastguard Worker .Red,
119*324bb76bSAndroid Build Coastguard Worker GifFile->SColorMap->Colors[i + j]
120*324bb76bSAndroid Build Coastguard Worker .Green,
121*324bb76bSAndroid Build Coastguard Worker GifFile->SColorMap->Colors[i + j]
122*324bb76bSAndroid Build Coastguard Worker .Blue);
123*324bb76bSAndroid Build Coastguard Worker }
124*324bb76bSAndroid Build Coastguard Worker printf("\n");
125*324bb76bSAndroid Build Coastguard Worker }
126*324bb76bSAndroid Build Coastguard Worker }
127*324bb76bSAndroid Build Coastguard Worker }
128*324bb76bSAndroid Build Coastguard Worker
129*324bb76bSAndroid Build Coastguard Worker do {
130*324bb76bSAndroid Build Coastguard Worker if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) {
131*324bb76bSAndroid Build Coastguard Worker PrintGifError(GifFile->Error);
132*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
133*324bb76bSAndroid Build Coastguard Worker }
134*324bb76bSAndroid Build Coastguard Worker switch (RecordType) {
135*324bb76bSAndroid Build Coastguard Worker case IMAGE_DESC_RECORD_TYPE:
136*324bb76bSAndroid Build Coastguard Worker if (DGifGetImageDesc(GifFile) == GIF_ERROR) {
137*324bb76bSAndroid Build Coastguard Worker PrintGifError(GifFile->Error);
138*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
139*324bb76bSAndroid Build Coastguard Worker }
140*324bb76bSAndroid Build Coastguard Worker if (!RawFlag) {
141*324bb76bSAndroid Build Coastguard Worker printf(
142*324bb76bSAndroid Build Coastguard Worker "\nImage #%d:\n\n\tImage Size - Left = %d, "
143*324bb76bSAndroid Build Coastguard Worker "Top = %d, Width = %d, Height = %d.\n",
144*324bb76bSAndroid Build Coastguard Worker ImageNum++, GifFile->Image.Left,
145*324bb76bSAndroid Build Coastguard Worker GifFile->Image.Top, GifFile->Image.Width,
146*324bb76bSAndroid Build Coastguard Worker GifFile->Image.Height);
147*324bb76bSAndroid Build Coastguard Worker printf("\tImage is %s", GifFile->Image.Interlace
148*324bb76bSAndroid Build Coastguard Worker ? "Interlaced"
149*324bb76bSAndroid Build Coastguard Worker : "Non Interlaced");
150*324bb76bSAndroid Build Coastguard Worker if (GifFile->Image.ColorMap != NULL) {
151*324bb76bSAndroid Build Coastguard Worker printf(", BitsPerPixel = %d.\n",
152*324bb76bSAndroid Build Coastguard Worker GifFile->Image.ColorMap
153*324bb76bSAndroid Build Coastguard Worker ->BitsPerPixel);
154*324bb76bSAndroid Build Coastguard Worker } else {
155*324bb76bSAndroid Build Coastguard Worker printf(".\n");
156*324bb76bSAndroid Build Coastguard Worker }
157*324bb76bSAndroid Build Coastguard Worker if (GifFile->Image.ColorMap) {
158*324bb76bSAndroid Build Coastguard Worker printf("\tImage Has Color Map.\n");
159*324bb76bSAndroid Build Coastguard Worker } else {
160*324bb76bSAndroid Build Coastguard Worker printf("\tNo Image Color Map.\n");
161*324bb76bSAndroid Build Coastguard Worker }
162*324bb76bSAndroid Build Coastguard Worker if (ColorMapFlag && GifFile->Image.ColorMap) {
163*324bb76bSAndroid Build Coastguard Worker printf("\tSort Flag: %s\n",
164*324bb76bSAndroid Build Coastguard Worker GifFile->Image.ColorMap->SortFlag
165*324bb76bSAndroid Build Coastguard Worker ? "on"
166*324bb76bSAndroid Build Coastguard Worker : "off");
167*324bb76bSAndroid Build Coastguard Worker Len = 1 << GifFile->Image.ColorMap
168*324bb76bSAndroid Build Coastguard Worker ->BitsPerPixel;
169*324bb76bSAndroid Build Coastguard Worker for (i = 0; i < Len; i += 4) {
170*324bb76bSAndroid Build Coastguard Worker for (j = 0; j < 4 && j < Len;
171*324bb76bSAndroid Build Coastguard Worker j++) {
172*324bb76bSAndroid Build Coastguard Worker printf(
173*324bb76bSAndroid Build Coastguard Worker "%3d: %02xh %02xh "
174*324bb76bSAndroid Build Coastguard Worker "%02xh ",
175*324bb76bSAndroid Build Coastguard Worker i + j,
176*324bb76bSAndroid Build Coastguard Worker GifFile->Image
177*324bb76bSAndroid Build Coastguard Worker .ColorMap
178*324bb76bSAndroid Build Coastguard Worker ->Colors[i + j]
179*324bb76bSAndroid Build Coastguard Worker .Red,
180*324bb76bSAndroid Build Coastguard Worker GifFile->Image
181*324bb76bSAndroid Build Coastguard Worker .ColorMap
182*324bb76bSAndroid Build Coastguard Worker ->Colors[i + j]
183*324bb76bSAndroid Build Coastguard Worker .Green,
184*324bb76bSAndroid Build Coastguard Worker GifFile->Image
185*324bb76bSAndroid Build Coastguard Worker .ColorMap
186*324bb76bSAndroid Build Coastguard Worker ->Colors[i + j]
187*324bb76bSAndroid Build Coastguard Worker .Blue);
188*324bb76bSAndroid Build Coastguard Worker }
189*324bb76bSAndroid Build Coastguard Worker printf("\n");
190*324bb76bSAndroid Build Coastguard Worker }
191*324bb76bSAndroid Build Coastguard Worker }
192*324bb76bSAndroid Build Coastguard Worker }
193*324bb76bSAndroid Build Coastguard Worker
194*324bb76bSAndroid Build Coastguard Worker if (EncodedFlag) {
195*324bb76bSAndroid Build Coastguard Worker if (DGifGetCode(GifFile, &CodeSize,
196*324bb76bSAndroid Build Coastguard Worker &CodeBlock) == GIF_ERROR) {
197*324bb76bSAndroid Build Coastguard Worker PrintGifError(GifFile->Error);
198*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
199*324bb76bSAndroid Build Coastguard Worker }
200*324bb76bSAndroid Build Coastguard Worker printf("\nImage LZ compressed Codes (Code Size "
201*324bb76bSAndroid Build Coastguard Worker "= %d):\n",
202*324bb76bSAndroid Build Coastguard Worker CodeSize);
203*324bb76bSAndroid Build Coastguard Worker PrintCodeBlock(GifFile, CodeBlock, true);
204*324bb76bSAndroid Build Coastguard Worker while (CodeBlock != NULL) {
205*324bb76bSAndroid Build Coastguard Worker if (DGifGetCodeNext(GifFile,
206*324bb76bSAndroid Build Coastguard Worker &CodeBlock) ==
207*324bb76bSAndroid Build Coastguard Worker GIF_ERROR) {
208*324bb76bSAndroid Build Coastguard Worker PrintGifError(GifFile->Error);
209*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
210*324bb76bSAndroid Build Coastguard Worker }
211*324bb76bSAndroid Build Coastguard Worker PrintCodeBlock(GifFile, CodeBlock,
212*324bb76bSAndroid Build Coastguard Worker false);
213*324bb76bSAndroid Build Coastguard Worker }
214*324bb76bSAndroid Build Coastguard Worker } else if (LZCodesFlag) {
215*324bb76bSAndroid Build Coastguard Worker PrintLZCodes(GifFile);
216*324bb76bSAndroid Build Coastguard Worker } else if (PixelFlag) {
217*324bb76bSAndroid Build Coastguard Worker Line = (GifPixelType *)malloc(
218*324bb76bSAndroid Build Coastguard Worker GifFile->Image.Width *
219*324bb76bSAndroid Build Coastguard Worker sizeof(GifPixelType));
220*324bb76bSAndroid Build Coastguard Worker for (i = 0; i < GifFile->Image.Height; i++) {
221*324bb76bSAndroid Build Coastguard Worker if (DGifGetLine(GifFile, Line,
222*324bb76bSAndroid Build Coastguard Worker GifFile->Image.Width) ==
223*324bb76bSAndroid Build Coastguard Worker GIF_ERROR) {
224*324bb76bSAndroid Build Coastguard Worker PrintGifError(GifFile->Error);
225*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
226*324bb76bSAndroid Build Coastguard Worker }
227*324bb76bSAndroid Build Coastguard Worker PrintPixelBlock(
228*324bb76bSAndroid Build Coastguard Worker Line, GifFile->Image.Width, i == 0);
229*324bb76bSAndroid Build Coastguard Worker }
230*324bb76bSAndroid Build Coastguard Worker PrintPixelBlock(NULL, GifFile->Image.Width,
231*324bb76bSAndroid Build Coastguard Worker false);
232*324bb76bSAndroid Build Coastguard Worker free((char *)Line);
233*324bb76bSAndroid Build Coastguard Worker } else if (RawFlag) {
234*324bb76bSAndroid Build Coastguard Worker Line = (GifPixelType *)malloc(
235*324bb76bSAndroid Build Coastguard Worker GifFile->Image.Width *
236*324bb76bSAndroid Build Coastguard Worker sizeof(GifPixelType));
237*324bb76bSAndroid Build Coastguard Worker for (i = 0; i < GifFile->Image.Height; i++) {
238*324bb76bSAndroid Build Coastguard Worker if (DGifGetLine(GifFile, Line,
239*324bb76bSAndroid Build Coastguard Worker GifFile->Image.Width) ==
240*324bb76bSAndroid Build Coastguard Worker GIF_ERROR) {
241*324bb76bSAndroid Build Coastguard Worker PrintGifError(GifFile->Error);
242*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
243*324bb76bSAndroid Build Coastguard Worker }
244*324bb76bSAndroid Build Coastguard Worker fwrite(Line, 1, GifFile->Image.Width,
245*324bb76bSAndroid Build Coastguard Worker stdout);
246*324bb76bSAndroid Build Coastguard Worker }
247*324bb76bSAndroid Build Coastguard Worker free((char *)Line);
248*324bb76bSAndroid Build Coastguard Worker } else {
249*324bb76bSAndroid Build Coastguard Worker /* Skip the image: */
250*324bb76bSAndroid Build Coastguard Worker if (DGifGetCode(GifFile, &CodeSize,
251*324bb76bSAndroid Build Coastguard Worker &CodeBlock) == GIF_ERROR) {
252*324bb76bSAndroid Build Coastguard Worker PrintGifError(GifFile->Error);
253*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
254*324bb76bSAndroid Build Coastguard Worker }
255*324bb76bSAndroid Build Coastguard Worker while (CodeBlock != NULL) {
256*324bb76bSAndroid Build Coastguard Worker if (DGifGetCodeNext(GifFile,
257*324bb76bSAndroid Build Coastguard Worker &CodeBlock) ==
258*324bb76bSAndroid Build Coastguard Worker GIF_ERROR) {
259*324bb76bSAndroid Build Coastguard Worker PrintGifError(GifFile->Error);
260*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
261*324bb76bSAndroid Build Coastguard Worker }
262*324bb76bSAndroid Build Coastguard Worker }
263*324bb76bSAndroid Build Coastguard Worker }
264*324bb76bSAndroid Build Coastguard Worker break;
265*324bb76bSAndroid Build Coastguard Worker case EXTENSION_RECORD_TYPE:
266*324bb76bSAndroid Build Coastguard Worker if (DGifGetExtension(GifFile, &ExtCode, &Extension) ==
267*324bb76bSAndroid Build Coastguard Worker GIF_ERROR) {
268*324bb76bSAndroid Build Coastguard Worker PrintGifError(GifFile->Error);
269*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
270*324bb76bSAndroid Build Coastguard Worker }
271*324bb76bSAndroid Build Coastguard Worker if (!RawFlag) {
272*324bb76bSAndroid Build Coastguard Worker putchar('\n');
273*324bb76bSAndroid Build Coastguard Worker switch (ExtCode) {
274*324bb76bSAndroid Build Coastguard Worker case COMMENT_EXT_FUNC_CODE:
275*324bb76bSAndroid Build Coastguard Worker printf("GIF89 comment");
276*324bb76bSAndroid Build Coastguard Worker break;
277*324bb76bSAndroid Build Coastguard Worker case GRAPHICS_EXT_FUNC_CODE:
278*324bb76bSAndroid Build Coastguard Worker printf("GIF89 graphics control");
279*324bb76bSAndroid Build Coastguard Worker break;
280*324bb76bSAndroid Build Coastguard Worker case PLAINTEXT_EXT_FUNC_CODE:
281*324bb76bSAndroid Build Coastguard Worker printf("GIF89 plaintext");
282*324bb76bSAndroid Build Coastguard Worker break;
283*324bb76bSAndroid Build Coastguard Worker case APPLICATION_EXT_FUNC_CODE:
284*324bb76bSAndroid Build Coastguard Worker printf("GIF89 application block");
285*324bb76bSAndroid Build Coastguard Worker break;
286*324bb76bSAndroid Build Coastguard Worker default:
287*324bb76bSAndroid Build Coastguard Worker printf(
288*324bb76bSAndroid Build Coastguard Worker "Extension record of unknown type");
289*324bb76bSAndroid Build Coastguard Worker break;
290*324bb76bSAndroid Build Coastguard Worker }
291*324bb76bSAndroid Build Coastguard Worker printf(" (Ext Code = %d [%c]):\n", ExtCode,
292*324bb76bSAndroid Build Coastguard Worker MAKE_PRINTABLE(ExtCode));
293*324bb76bSAndroid Build Coastguard Worker PrintExtBlock(Extension, true);
294*324bb76bSAndroid Build Coastguard Worker
295*324bb76bSAndroid Build Coastguard Worker if (ExtCode == GRAPHICS_EXT_FUNC_CODE) {
296*324bb76bSAndroid Build Coastguard Worker GraphicsControlBlock gcb;
297*324bb76bSAndroid Build Coastguard Worker if (Extension == NULL) {
298*324bb76bSAndroid Build Coastguard Worker printf("Invalid extension "
299*324bb76bSAndroid Build Coastguard Worker "block\n");
300*324bb76bSAndroid Build Coastguard Worker GifFile->Error =
301*324bb76bSAndroid Build Coastguard Worker D_GIF_ERR_IMAGE_DEFECT;
302*324bb76bSAndroid Build Coastguard Worker PrintGifError(GifFile->Error);
303*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
304*324bb76bSAndroid Build Coastguard Worker }
305*324bb76bSAndroid Build Coastguard Worker if (DGifExtensionToGCB(
306*324bb76bSAndroid Build Coastguard Worker Extension[0], Extension + 1,
307*324bb76bSAndroid Build Coastguard Worker &gcb) == GIF_ERROR) {
308*324bb76bSAndroid Build Coastguard Worker PrintGifError(GifFile->Error);
309*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
310*324bb76bSAndroid Build Coastguard Worker }
311*324bb76bSAndroid Build Coastguard Worker printf("\tDisposal Mode: %d\n",
312*324bb76bSAndroid Build Coastguard Worker gcb.DisposalMode);
313*324bb76bSAndroid Build Coastguard Worker printf("\tUser Input Flag: %d\n",
314*324bb76bSAndroid Build Coastguard Worker gcb.UserInputFlag);
315*324bb76bSAndroid Build Coastguard Worker printf("\tTransparency on: %s\n",
316*324bb76bSAndroid Build Coastguard Worker gcb.TransparentColor != -1
317*324bb76bSAndroid Build Coastguard Worker ? "yes"
318*324bb76bSAndroid Build Coastguard Worker : "no");
319*324bb76bSAndroid Build Coastguard Worker printf("\tDelayTime: %d\n",
320*324bb76bSAndroid Build Coastguard Worker gcb.DelayTime);
321*324bb76bSAndroid Build Coastguard Worker printf("\tTransparent Index: %d\n",
322*324bb76bSAndroid Build Coastguard Worker gcb.TransparentColor);
323*324bb76bSAndroid Build Coastguard Worker }
324*324bb76bSAndroid Build Coastguard Worker }
325*324bb76bSAndroid Build Coastguard Worker for (;;) {
326*324bb76bSAndroid Build Coastguard Worker if (DGifGetExtensionNext(GifFile, &Extension) ==
327*324bb76bSAndroid Build Coastguard Worker GIF_ERROR) {
328*324bb76bSAndroid Build Coastguard Worker PrintGifError(GifFile->Error);
329*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
330*324bb76bSAndroid Build Coastguard Worker }
331*324bb76bSAndroid Build Coastguard Worker if (Extension == NULL) {
332*324bb76bSAndroid Build Coastguard Worker break;
333*324bb76bSAndroid Build Coastguard Worker }
334*324bb76bSAndroid Build Coastguard Worker PrintExtBlock(Extension, false);
335*324bb76bSAndroid Build Coastguard Worker }
336*324bb76bSAndroid Build Coastguard Worker break;
337*324bb76bSAndroid Build Coastguard Worker case TERMINATE_RECORD_TYPE:
338*324bb76bSAndroid Build Coastguard Worker break;
339*324bb76bSAndroid Build Coastguard Worker default: /* Should be trapped by DGifGetRecordType */
340*324bb76bSAndroid Build Coastguard Worker break;
341*324bb76bSAndroid Build Coastguard Worker }
342*324bb76bSAndroid Build Coastguard Worker } while (RecordType != TERMINATE_RECORD_TYPE);
343*324bb76bSAndroid Build Coastguard Worker
344*324bb76bSAndroid Build Coastguard Worker if (DGifCloseFile(GifFile, &ErrorCode) == GIF_ERROR) {
345*324bb76bSAndroid Build Coastguard Worker PrintGifError(ErrorCode);
346*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
347*324bb76bSAndroid Build Coastguard Worker }
348*324bb76bSAndroid Build Coastguard Worker
349*324bb76bSAndroid Build Coastguard Worker if (!RawFlag) {
350*324bb76bSAndroid Build Coastguard Worker printf("\nGIF file terminated normally.\n");
351*324bb76bSAndroid Build Coastguard Worker }
352*324bb76bSAndroid Build Coastguard Worker
353*324bb76bSAndroid Build Coastguard Worker return 0;
354*324bb76bSAndroid Build Coastguard Worker }
355*324bb76bSAndroid Build Coastguard Worker
356*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
357*324bb76bSAndroid Build Coastguard Worker Print the given CodeBlock - a string in pascal notation (size in first
358*324bb76bSAndroid Build Coastguard Worker place). Save local information so printing can be performed continuously,
359*324bb76bSAndroid Build Coastguard Worker or reset to start state if Reset. If CodeBlock is NULL, output is flushed
360*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
PrintCodeBlock(GifFileType * GifFile,GifByteType * CodeBlock,bool Reset)361*324bb76bSAndroid Build Coastguard Worker static void PrintCodeBlock(GifFileType *GifFile, GifByteType *CodeBlock,
362*324bb76bSAndroid Build Coastguard Worker bool Reset) {
363*324bb76bSAndroid Build Coastguard Worker static int CrntPlace = 0;
364*324bb76bSAndroid Build Coastguard Worker static long CodeCount = 0;
365*324bb76bSAndroid Build Coastguard Worker int i, Len;
366*324bb76bSAndroid Build Coastguard Worker
367*324bb76bSAndroid Build Coastguard Worker if (Reset || CodeBlock == NULL) {
368*324bb76bSAndroid Build Coastguard Worker if (CodeBlock == NULL) {
369*324bb76bSAndroid Build Coastguard Worker long NumBytes = 0;
370*324bb76bSAndroid Build Coastguard Worker if (CrntPlace > 0) {
371*324bb76bSAndroid Build Coastguard Worker printf("\n");
372*324bb76bSAndroid Build Coastguard Worker CodeCount += CrntPlace - 16;
373*324bb76bSAndroid Build Coastguard Worker }
374*324bb76bSAndroid Build Coastguard Worker if (GifFile->Image.ColorMap) {
375*324bb76bSAndroid Build Coastguard Worker NumBytes =
376*324bb76bSAndroid Build Coastguard Worker ((((long)GifFile->Image.Width) *
377*324bb76bSAndroid Build Coastguard Worker GifFile->Image.Height) *
378*324bb76bSAndroid Build Coastguard Worker GifFile->Image.ColorMap->BitsPerPixel) /
379*324bb76bSAndroid Build Coastguard Worker 8;
380*324bb76bSAndroid Build Coastguard Worker } else if (GifFile->SColorMap != NULL) {
381*324bb76bSAndroid Build Coastguard Worker NumBytes = ((((long)GifFile->Image.Width) *
382*324bb76bSAndroid Build Coastguard Worker GifFile->Image.Height) *
383*324bb76bSAndroid Build Coastguard Worker GifFile->SColorMap->BitsPerPixel) /
384*324bb76bSAndroid Build Coastguard Worker 8;
385*324bb76bSAndroid Build Coastguard Worker }
386*324bb76bSAndroid Build Coastguard Worker /* FIXME: What should the compression ratio be if no
387*324bb76bSAndroid Build Coastguard Worker * color table? */
388*324bb76bSAndroid Build Coastguard Worker if (NumBytes > 0) {
389*324bb76bSAndroid Build Coastguard Worker int Percent = 100 * CodeCount / NumBytes;
390*324bb76bSAndroid Build Coastguard Worker printf("\nCompression ratio: %ld/%ld (%d%%).\n",
391*324bb76bSAndroid Build Coastguard Worker CodeCount, NumBytes, Percent);
392*324bb76bSAndroid Build Coastguard Worker }
393*324bb76bSAndroid Build Coastguard Worker return;
394*324bb76bSAndroid Build Coastguard Worker }
395*324bb76bSAndroid Build Coastguard Worker CrntPlace = 0;
396*324bb76bSAndroid Build Coastguard Worker CodeCount = 0;
397*324bb76bSAndroid Build Coastguard Worker }
398*324bb76bSAndroid Build Coastguard Worker
399*324bb76bSAndroid Build Coastguard Worker // cppcheck-suppress nullPointerRedundantCheck
400*324bb76bSAndroid Build Coastguard Worker Len = CodeBlock[0];
401*324bb76bSAndroid Build Coastguard Worker for (i = 1; i <= Len; i++) {
402*324bb76bSAndroid Build Coastguard Worker if (CrntPlace == 0) {
403*324bb76bSAndroid Build Coastguard Worker printf("\n%05lxh: ", CodeCount);
404*324bb76bSAndroid Build Coastguard Worker CodeCount += 16;
405*324bb76bSAndroid Build Coastguard Worker }
406*324bb76bSAndroid Build Coastguard Worker (void)printf(" %02xh", CodeBlock[i]);
407*324bb76bSAndroid Build Coastguard Worker if (++CrntPlace >= 16) {
408*324bb76bSAndroid Build Coastguard Worker CrntPlace = 0;
409*324bb76bSAndroid Build Coastguard Worker }
410*324bb76bSAndroid Build Coastguard Worker }
411*324bb76bSAndroid Build Coastguard Worker }
412*324bb76bSAndroid Build Coastguard Worker
413*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
414*324bb76bSAndroid Build Coastguard Worker Print the given Extension - a string in pascal notation (size in first
415*324bb76bSAndroid Build Coastguard Worker place). Save local information so printing can be performed continuously,
416*324bb76bSAndroid Build Coastguard Worker or reset to start state if Reset. If Extension is NULL, output is flushed
417*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
PrintExtBlock(GifByteType * Extension,bool Reset)418*324bb76bSAndroid Build Coastguard Worker static void PrintExtBlock(GifByteType *Extension, bool Reset) {
419*324bb76bSAndroid Build Coastguard Worker static int CrntPlace = 0;
420*324bb76bSAndroid Build Coastguard Worker static long ExtCount = 0;
421*324bb76bSAndroid Build Coastguard Worker static char HexForm[49], AsciiForm[17];
422*324bb76bSAndroid Build Coastguard Worker
423*324bb76bSAndroid Build Coastguard Worker if (Reset || Extension == NULL) {
424*324bb76bSAndroid Build Coastguard Worker if (Extension == NULL) {
425*324bb76bSAndroid Build Coastguard Worker if (CrntPlace > 0) {
426*324bb76bSAndroid Build Coastguard Worker HexForm[CrntPlace * 3] = 0;
427*324bb76bSAndroid Build Coastguard Worker AsciiForm[CrntPlace] = 0;
428*324bb76bSAndroid Build Coastguard Worker printf("\n%05lx: %-49s %-17s\n", ExtCount,
429*324bb76bSAndroid Build Coastguard Worker HexForm, AsciiForm);
430*324bb76bSAndroid Build Coastguard Worker return;
431*324bb76bSAndroid Build Coastguard Worker } else {
432*324bb76bSAndroid Build Coastguard Worker printf("\n");
433*324bb76bSAndroid Build Coastguard Worker }
434*324bb76bSAndroid Build Coastguard Worker }
435*324bb76bSAndroid Build Coastguard Worker CrntPlace = 0;
436*324bb76bSAndroid Build Coastguard Worker ExtCount = 0;
437*324bb76bSAndroid Build Coastguard Worker }
438*324bb76bSAndroid Build Coastguard Worker
439*324bb76bSAndroid Build Coastguard Worker if (Extension != NULL) {
440*324bb76bSAndroid Build Coastguard Worker int i, Len;
441*324bb76bSAndroid Build Coastguard Worker Len = Extension[0];
442*324bb76bSAndroid Build Coastguard Worker for (i = 1; i <= Len; i++) {
443*324bb76bSAndroid Build Coastguard Worker (void)snprintf(&HexForm[CrntPlace * 3], 3, " %02x",
444*324bb76bSAndroid Build Coastguard Worker Extension[i]);
445*324bb76bSAndroid Build Coastguard Worker (void)snprintf(&AsciiForm[CrntPlace], 3, "%c",
446*324bb76bSAndroid Build Coastguard Worker MAKE_PRINTABLE(Extension[i]));
447*324bb76bSAndroid Build Coastguard Worker if (++CrntPlace == 16) {
448*324bb76bSAndroid Build Coastguard Worker HexForm[CrntPlace * 3] = 0;
449*324bb76bSAndroid Build Coastguard Worker AsciiForm[CrntPlace] = 0;
450*324bb76bSAndroid Build Coastguard Worker printf("\n%05lx: %-49s %-17s", ExtCount,
451*324bb76bSAndroid Build Coastguard Worker HexForm, AsciiForm);
452*324bb76bSAndroid Build Coastguard Worker ExtCount += 16;
453*324bb76bSAndroid Build Coastguard Worker CrntPlace = 0;
454*324bb76bSAndroid Build Coastguard Worker }
455*324bb76bSAndroid Build Coastguard Worker }
456*324bb76bSAndroid Build Coastguard Worker }
457*324bb76bSAndroid Build Coastguard Worker }
458*324bb76bSAndroid Build Coastguard Worker
459*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
460*324bb76bSAndroid Build Coastguard Worker Print the given PixelBlock of length Len.
461*324bb76bSAndroid Build Coastguard Worker Save local information so printing can be performed continuously,
462*324bb76bSAndroid Build Coastguard Worker or reset to start state if Reset. If PixelBlock is NULL, output is flushed
463*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
PrintPixelBlock(GifByteType * PixelBlock,int Len,bool Reset)464*324bb76bSAndroid Build Coastguard Worker static void PrintPixelBlock(GifByteType *PixelBlock, int Len, bool Reset) {
465*324bb76bSAndroid Build Coastguard Worker static int CrntPlace = 0;
466*324bb76bSAndroid Build Coastguard Worker static long ExtCount = 0;
467*324bb76bSAndroid Build Coastguard Worker static char HexForm[49], AsciiForm[17];
468*324bb76bSAndroid Build Coastguard Worker int i;
469*324bb76bSAndroid Build Coastguard Worker
470*324bb76bSAndroid Build Coastguard Worker if (Reset || PixelBlock == NULL) {
471*324bb76bSAndroid Build Coastguard Worker if (PixelBlock == NULL) {
472*324bb76bSAndroid Build Coastguard Worker if (CrntPlace > 0) {
473*324bb76bSAndroid Build Coastguard Worker HexForm[CrntPlace * 3] = 0;
474*324bb76bSAndroid Build Coastguard Worker AsciiForm[CrntPlace] = 0;
475*324bb76bSAndroid Build Coastguard Worker printf("\n%05lx: %-49s %-17s\n", ExtCount,
476*324bb76bSAndroid Build Coastguard Worker HexForm, AsciiForm);
477*324bb76bSAndroid Build Coastguard Worker } else {
478*324bb76bSAndroid Build Coastguard Worker printf("\n");
479*324bb76bSAndroid Build Coastguard Worker }
480*324bb76bSAndroid Build Coastguard Worker }
481*324bb76bSAndroid Build Coastguard Worker CrntPlace = 0;
482*324bb76bSAndroid Build Coastguard Worker ExtCount = 0;
483*324bb76bSAndroid Build Coastguard Worker if (PixelBlock == NULL) {
484*324bb76bSAndroid Build Coastguard Worker return;
485*324bb76bSAndroid Build Coastguard Worker }
486*324bb76bSAndroid Build Coastguard Worker }
487*324bb76bSAndroid Build Coastguard Worker
488*324bb76bSAndroid Build Coastguard Worker for (i = 0; i < Len; i++) {
489*324bb76bSAndroid Build Coastguard Worker (void)snprintf(&HexForm[CrntPlace * 3], 3, " %02x",
490*324bb76bSAndroid Build Coastguard Worker PixelBlock[i]);
491*324bb76bSAndroid Build Coastguard Worker (void)snprintf(&AsciiForm[CrntPlace], 3, "%c",
492*324bb76bSAndroid Build Coastguard Worker MAKE_PRINTABLE(PixelBlock[i]));
493*324bb76bSAndroid Build Coastguard Worker if (++CrntPlace == 16) {
494*324bb76bSAndroid Build Coastguard Worker HexForm[CrntPlace * 3] = 0;
495*324bb76bSAndroid Build Coastguard Worker AsciiForm[CrntPlace] = 0;
496*324bb76bSAndroid Build Coastguard Worker printf("\n%05lx: %-49s %-17s", ExtCount, HexForm,
497*324bb76bSAndroid Build Coastguard Worker AsciiForm);
498*324bb76bSAndroid Build Coastguard Worker ExtCount += 16;
499*324bb76bSAndroid Build Coastguard Worker CrntPlace = 0;
500*324bb76bSAndroid Build Coastguard Worker }
501*324bb76bSAndroid Build Coastguard Worker }
502*324bb76bSAndroid Build Coastguard Worker }
503*324bb76bSAndroid Build Coastguard Worker
504*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
505*324bb76bSAndroid Build Coastguard Worker Print the image as LZ codes (each 12bits), until EOF marker is reached.
506*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
PrintLZCodes(GifFileType * GifFile)507*324bb76bSAndroid Build Coastguard Worker static void PrintLZCodes(GifFileType *GifFile) {
508*324bb76bSAndroid Build Coastguard Worker int Code, CrntPlace = 0;
509*324bb76bSAndroid Build Coastguard Worker long CodeCount = 0;
510*324bb76bSAndroid Build Coastguard Worker
511*324bb76bSAndroid Build Coastguard Worker do {
512*324bb76bSAndroid Build Coastguard Worker if (CrntPlace == 0) {
513*324bb76bSAndroid Build Coastguard Worker printf("\n%05lx:", CodeCount);
514*324bb76bSAndroid Build Coastguard Worker }
515*324bb76bSAndroid Build Coastguard Worker if (DGifGetLZCodes(GifFile, &Code) == GIF_ERROR) {
516*324bb76bSAndroid Build Coastguard Worker PrintGifError(GifFile->Error);
517*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
518*324bb76bSAndroid Build Coastguard Worker }
519*324bb76bSAndroid Build Coastguard Worker if (Code >= 0) {
520*324bb76bSAndroid Build Coastguard Worker printf(" %03x", Code); /* EOF Code is returned as -1. */
521*324bb76bSAndroid Build Coastguard Worker }
522*324bb76bSAndroid Build Coastguard Worker CodeCount++;
523*324bb76bSAndroid Build Coastguard Worker if (++CrntPlace >= 16) {
524*324bb76bSAndroid Build Coastguard Worker CrntPlace = 0;
525*324bb76bSAndroid Build Coastguard Worker }
526*324bb76bSAndroid Build Coastguard Worker } while (Code >= 0);
527*324bb76bSAndroid Build Coastguard Worker }
528*324bb76bSAndroid Build Coastguard Worker
529*324bb76bSAndroid Build Coastguard Worker /* end */
530