xref: /aosp_15_r20/external/giflib/giffilter.c (revision 324bb76b8d05e2a05aa88511fff61cf3f9ca5892)
1 /******************************************************************************
2 
3 giffilter.c - skeleton file for generic GIF `filter' program
4 
5 Sequentially read GIF records from stdin, process them, send them out.
6 Most of the junk above `int main' isn't needed for the skeleton, but
7 is likely to be for what you'll do with it.
8 
9 If you compile this, it will turn into an expensive GIF copying routine;
10 stdin to stdout with no changes and minimal validation.  Well, it's a
11 decent test of the low-level routines, anyway.
12 
13 Note: due to the vicissitudes of Lempel-Ziv compression, the output of this
14 copier may not be bitwise identical to its input.  This can happen if you
15 copy an image from a much more (or much *less*) memory-limited system; your
16 compression may use more (or fewer) bits.  The uncompressed rasters should,
17 however, be identical (you can check this with gifbuild -d).
18 
19 SPDX-License-Identifier: MIT
20 
21 ******************************************************************************/
22 
23 #include <fcntl.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 
28 #include "getarg.h"
29 #include "gif_lib.h"
30 
31 #define PROGRAM_NAME "giffilter"
32 
33 /******************************************************************************
34  Close both input and output file (if open), and exit.
35 ******************************************************************************/
QuitGifError(GifFileType * GifFileIn,GifFileType * GifFileOut)36 static void QuitGifError(GifFileType *GifFileIn, GifFileType *GifFileOut) {
37 	if (GifFileIn != NULL) {
38 		PrintGifError(GifFileIn->Error);
39 		EGifCloseFile(GifFileIn, NULL);
40 	}
41 	if (GifFileOut != NULL) {
42 		PrintGifError(GifFileOut->Error);
43 		EGifCloseFile(GifFileOut, NULL);
44 	}
45 	exit(EXIT_FAILURE);
46 }
47 
48 /******************************************************************************
49  Main sequence
50 ******************************************************************************/
main(int argc,char ** argv)51 int main(int argc, char **argv) {
52 	GifFileType *GifFileIn = NULL, *GifFileOut = NULL;
53 	GifRecordType RecordType;
54 	int CodeSize, ExtCode, ErrorCode;
55 	GifByteType *CodeBlock, *Extension;
56 
57 	/*
58 	 * Command-line processing goes here.
59 	 */
60 
61 	/* Use stdin as input (note this also read screen descriptor in: */
62 	if ((GifFileIn = DGifOpenFileHandle(0, &ErrorCode)) == NULL) {
63 		PrintGifError(ErrorCode);
64 		exit(EXIT_FAILURE);
65 	}
66 
67 	/* Use the stdout as output: */
68 	if ((GifFileOut = EGifOpenFileHandle(1, &ErrorCode)) == NULL) {
69 		PrintGifError(ErrorCode);
70 		exit(EXIT_FAILURE);
71 	}
72 
73 	/* And dump out its screen information: */
74 	if (EGifPutScreenDesc(GifFileOut, GifFileIn->SWidth, GifFileIn->SHeight,
75 	                      GifFileIn->SColorResolution,
76 	                      GifFileIn->SBackGroundColor,
77 	                      GifFileIn->SColorMap) == GIF_ERROR) {
78 		QuitGifError(GifFileIn, GifFileOut);
79 	}
80 
81 	/* Scan the content of the input GIF file and load the image(s) in: */
82 	do {
83 		if (DGifGetRecordType(GifFileIn, &RecordType) == GIF_ERROR) {
84 			QuitGifError(GifFileIn, GifFileOut);
85 		}
86 
87 		switch (RecordType) {
88 		case IMAGE_DESC_RECORD_TYPE:
89 			if (DGifGetImageDesc(GifFileIn) == GIF_ERROR) {
90 				QuitGifError(GifFileIn, GifFileOut);
91 			}
92 			/* Put image descriptor to out file: */
93 			if (EGifPutImageDesc(
94 			        GifFileOut, GifFileIn->Image.Left,
95 			        GifFileIn->Image.Top, GifFileIn->Image.Width,
96 			        GifFileIn->Image.Height,
97 			        GifFileIn->Image.Interlace,
98 			        GifFileIn->Image.ColorMap) == GIF_ERROR) {
99 				QuitGifError(GifFileIn, GifFileOut);
100 			}
101 
102 			/* Now read image itself in decoded form as we dont
103 			 * really   */
104 			/* care what we have there, and this is much faster.
105 			 */
106 			if (DGifGetCode(GifFileIn, &CodeSize, &CodeBlock) ==
107 			        GIF_ERROR ||
108 			    EGifPutCode(GifFileOut, CodeSize, CodeBlock) ==
109 			        GIF_ERROR) {
110 				QuitGifError(GifFileIn, GifFileOut);
111 			}
112 			while (CodeBlock != NULL) {
113 				if (DGifGetCodeNext(GifFileIn, &CodeBlock) ==
114 				        GIF_ERROR ||
115 				    EGifPutCodeNext(GifFileOut, CodeBlock) ==
116 				        GIF_ERROR) {
117 					QuitGifError(GifFileIn, GifFileOut);
118 				}
119 			}
120 			break;
121 		case EXTENSION_RECORD_TYPE:
122 			/* pass through extension records */
123 			if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) ==
124 			        GIF_ERROR ||
125 			    Extension == NULL) {
126 				QuitGifError(GifFileIn, GifFileOut);
127 			}
128 			if (EGifPutExtensionLeader(GifFileOut, ExtCode) ==
129 			    GIF_ERROR) {
130 				QuitGifError(GifFileIn, GifFileOut);
131 			}
132 			if (EGifPutExtensionBlock(GifFileOut, Extension[0],
133 			                          Extension + 1) == GIF_ERROR) {
134 				QuitGifError(GifFileIn, GifFileOut);
135 			}
136 			while (Extension != NULL) {
137 				if (DGifGetExtensionNext(
138 				        GifFileIn, &Extension) == GIF_ERROR) {
139 					QuitGifError(GifFileIn, GifFileOut);
140 				}
141 				if (Extension != NULL) {
142 					if (EGifPutExtensionBlock(
143 					        GifFileOut, Extension[0],
144 					        Extension + 1) == GIF_ERROR) {
145 						QuitGifError(GifFileIn,
146 						             GifFileOut);
147 					}
148 				}
149 			}
150 			if (EGifPutExtensionTrailer(GifFileOut) == GIF_ERROR) {
151 				QuitGifError(GifFileIn, GifFileOut);
152 			}
153 			break;
154 		case TERMINATE_RECORD_TYPE:
155 			break;
156 		default: /* Should be trapped by DGifGetRecordType */
157 			break;
158 		}
159 	} while (RecordType != TERMINATE_RECORD_TYPE);
160 
161 	if (DGifCloseFile(GifFileIn, &ErrorCode) == GIF_ERROR) {
162 		PrintGifError(ErrorCode);
163 		exit(EXIT_FAILURE);
164 	}
165 	if (EGifCloseFile(GifFileOut, &ErrorCode) == GIF_ERROR) {
166 		PrintGifError(ErrorCode);
167 		exit(EXIT_FAILURE);
168 	}
169 
170 	return 0;
171 }
172 
173 /* end */
174