1*324bb76bSAndroid Build Coastguard Worker /****************************************************************************
2*324bb76bSAndroid Build Coastguard Worker
3*324bb76bSAndroid Build Coastguard Worker giftool.c - GIF transformation tool.
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 <fcntl.h>
10*324bb76bSAndroid Build Coastguard Worker #include <stdbool.h>
11*324bb76bSAndroid Build Coastguard Worker #include <stdio.h>
12*324bb76bSAndroid Build Coastguard Worker #include <stdlib.h>
13*324bb76bSAndroid Build Coastguard Worker #include <string.h>
14*324bb76bSAndroid Build Coastguard Worker
15*324bb76bSAndroid Build Coastguard Worker #include "getarg.h"
16*324bb76bSAndroid Build Coastguard Worker #include "getopt.h"
17*324bb76bSAndroid Build Coastguard Worker #include "gif_lib.h"
18*324bb76bSAndroid Build Coastguard Worker
19*324bb76bSAndroid Build Coastguard Worker #define PROGRAM_NAME "giftool"
20*324bb76bSAndroid Build Coastguard Worker
21*324bb76bSAndroid Build Coastguard Worker #define MAX_OPERATIONS 256
22*324bb76bSAndroid Build Coastguard Worker #define MAX_IMAGES 2048
23*324bb76bSAndroid Build Coastguard Worker
24*324bb76bSAndroid Build Coastguard Worker enum boolmode { numeric, onoff, tf, yesno };
25*324bb76bSAndroid Build Coastguard Worker
putbool(bool flag,enum boolmode mode)26*324bb76bSAndroid Build Coastguard Worker char *putbool(bool flag, enum boolmode mode) {
27*324bb76bSAndroid Build Coastguard Worker if (flag) {
28*324bb76bSAndroid Build Coastguard Worker switch (mode) {
29*324bb76bSAndroid Build Coastguard Worker case numeric:
30*324bb76bSAndroid Build Coastguard Worker return "1";
31*324bb76bSAndroid Build Coastguard Worker break;
32*324bb76bSAndroid Build Coastguard Worker case onoff:
33*324bb76bSAndroid Build Coastguard Worker return "on";
34*324bb76bSAndroid Build Coastguard Worker break;
35*324bb76bSAndroid Build Coastguard Worker case tf:
36*324bb76bSAndroid Build Coastguard Worker return "true";
37*324bb76bSAndroid Build Coastguard Worker break;
38*324bb76bSAndroid Build Coastguard Worker case yesno:
39*324bb76bSAndroid Build Coastguard Worker return "yes";
40*324bb76bSAndroid Build Coastguard Worker break;
41*324bb76bSAndroid Build Coastguard Worker }
42*324bb76bSAndroid Build Coastguard Worker } else {
43*324bb76bSAndroid Build Coastguard Worker switch (mode) {
44*324bb76bSAndroid Build Coastguard Worker case numeric:
45*324bb76bSAndroid Build Coastguard Worker return "0";
46*324bb76bSAndroid Build Coastguard Worker break;
47*324bb76bSAndroid Build Coastguard Worker case onoff:
48*324bb76bSAndroid Build Coastguard Worker return "off";
49*324bb76bSAndroid Build Coastguard Worker break;
50*324bb76bSAndroid Build Coastguard Worker case tf:
51*324bb76bSAndroid Build Coastguard Worker return "false";
52*324bb76bSAndroid Build Coastguard Worker break;
53*324bb76bSAndroid Build Coastguard Worker case yesno:
54*324bb76bSAndroid Build Coastguard Worker return "no";
55*324bb76bSAndroid Build Coastguard Worker break;
56*324bb76bSAndroid Build Coastguard Worker }
57*324bb76bSAndroid Build Coastguard Worker }
58*324bb76bSAndroid Build Coastguard Worker
59*324bb76bSAndroid Build Coastguard Worker return "FAIL"; /* should never happen */
60*324bb76bSAndroid Build Coastguard Worker }
61*324bb76bSAndroid Build Coastguard Worker
getbool(char * from)62*324bb76bSAndroid Build Coastguard Worker bool getbool(char *from) {
63*324bb76bSAndroid Build Coastguard Worker struct valmap {
64*324bb76bSAndroid Build Coastguard Worker char *name;
65*324bb76bSAndroid Build Coastguard Worker bool val;
66*324bb76bSAndroid Build Coastguard Worker } boolnames[] =
67*324bb76bSAndroid Build Coastguard Worker {
68*324bb76bSAndroid Build Coastguard Worker {"yes", true}, {"on", true}, {"1", true},
69*324bb76bSAndroid Build Coastguard Worker {"t", true}, {"no", false}, {"off", false},
70*324bb76bSAndroid Build Coastguard Worker {"0", false}, {"f", false}, {NULL, false},
71*324bb76bSAndroid Build Coastguard Worker },
72*324bb76bSAndroid Build Coastguard Worker *sp;
73*324bb76bSAndroid Build Coastguard Worker
74*324bb76bSAndroid Build Coastguard Worker // cppcheck-suppress nullPointerRedundantCheck
75*324bb76bSAndroid Build Coastguard Worker for (sp = boolnames; sp->name; sp++) {
76*324bb76bSAndroid Build Coastguard Worker if (strcmp(sp->name, from) == 0) {
77*324bb76bSAndroid Build Coastguard Worker return sp->val;
78*324bb76bSAndroid Build Coastguard Worker }
79*324bb76bSAndroid Build Coastguard Worker }
80*324bb76bSAndroid Build Coastguard Worker
81*324bb76bSAndroid Build Coastguard Worker if (sp == NULL) {
82*324bb76bSAndroid Build Coastguard Worker (void)fprintf(stderr,
83*324bb76bSAndroid Build Coastguard Worker "giftool: %s is not a valid boolean argument.\n",
84*324bb76bSAndroid Build Coastguard Worker // cppcheck-suppress nullPointerRedundantCheck
85*324bb76bSAndroid Build Coastguard Worker sp->name);
86*324bb76bSAndroid Build Coastguard Worker }
87*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
88*324bb76bSAndroid Build Coastguard Worker }
89*324bb76bSAndroid Build Coastguard Worker
90*324bb76bSAndroid Build Coastguard Worker struct operation {
91*324bb76bSAndroid Build Coastguard Worker enum {
92*324bb76bSAndroid Build Coastguard Worker aspect,
93*324bb76bSAndroid Build Coastguard Worker delaytime,
94*324bb76bSAndroid Build Coastguard Worker background,
95*324bb76bSAndroid Build Coastguard Worker info,
96*324bb76bSAndroid Build Coastguard Worker interlace,
97*324bb76bSAndroid Build Coastguard Worker position,
98*324bb76bSAndroid Build Coastguard Worker screensize,
99*324bb76bSAndroid Build Coastguard Worker transparent,
100*324bb76bSAndroid Build Coastguard Worker userinput,
101*324bb76bSAndroid Build Coastguard Worker disposal,
102*324bb76bSAndroid Build Coastguard Worker } mode;
103*324bb76bSAndroid Build Coastguard Worker union {
104*324bb76bSAndroid Build Coastguard Worker GifByteType numerator;
105*324bb76bSAndroid Build Coastguard Worker int delay;
106*324bb76bSAndroid Build Coastguard Worker int color;
107*324bb76bSAndroid Build Coastguard Worker int dispose;
108*324bb76bSAndroid Build Coastguard Worker char *format;
109*324bb76bSAndroid Build Coastguard Worker bool flag;
110*324bb76bSAndroid Build Coastguard Worker struct {
111*324bb76bSAndroid Build Coastguard Worker int x, y;
112*324bb76bSAndroid Build Coastguard Worker } p;
113*324bb76bSAndroid Build Coastguard Worker };
114*324bb76bSAndroid Build Coastguard Worker };
115*324bb76bSAndroid Build Coastguard Worker
main(int argc,char ** argv)116*324bb76bSAndroid Build Coastguard Worker int main(int argc, char **argv) {
117*324bb76bSAndroid Build Coastguard Worker extern char *optarg; /* set by getopt */
118*324bb76bSAndroid Build Coastguard Worker extern int optind; /* set by getopt */
119*324bb76bSAndroid Build Coastguard Worker struct operation operations[MAX_OPERATIONS];
120*324bb76bSAndroid Build Coastguard Worker struct operation *top = operations;
121*324bb76bSAndroid Build Coastguard Worker int selected[MAX_IMAGES], nselected = 0;
122*324bb76bSAndroid Build Coastguard Worker bool have_selection = false;
123*324bb76bSAndroid Build Coastguard Worker char *cp;
124*324bb76bSAndroid Build Coastguard Worker int i, status, ErrorCode;
125*324bb76bSAndroid Build Coastguard Worker GifFileType *GifFileIn, *GifFileOut = (GifFileType *)NULL;
126*324bb76bSAndroid Build Coastguard Worker struct operation *op;
127*324bb76bSAndroid Build Coastguard Worker
128*324bb76bSAndroid Build Coastguard Worker /*
129*324bb76bSAndroid Build Coastguard Worker * Gather operations from the command line. We use regular
130*324bb76bSAndroid Build Coastguard Worker * getopt(3) here rather than Gershom's argument getter because
131*324bb76bSAndroid Build Coastguard Worker * preserving the order of operations is important.
132*324bb76bSAndroid Build Coastguard Worker */
133*324bb76bSAndroid Build Coastguard Worker while ((status = getopt(argc, argv, "a:b:d:f:i:n:p:s:u:x:")) != EOF) {
134*324bb76bSAndroid Build Coastguard Worker if (top >= operations + MAX_OPERATIONS) {
135*324bb76bSAndroid Build Coastguard Worker (void)fprintf(stderr, "giftool: too many operations.");
136*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
137*324bb76bSAndroid Build Coastguard Worker }
138*324bb76bSAndroid Build Coastguard Worker
139*324bb76bSAndroid Build Coastguard Worker switch (status) {
140*324bb76bSAndroid Build Coastguard Worker case 'a':
141*324bb76bSAndroid Build Coastguard Worker top->mode = aspect;
142*324bb76bSAndroid Build Coastguard Worker top->numerator = (GifByteType)atoi(optarg);
143*324bb76bSAndroid Build Coastguard Worker break;
144*324bb76bSAndroid Build Coastguard Worker
145*324bb76bSAndroid Build Coastguard Worker case 'b':
146*324bb76bSAndroid Build Coastguard Worker top->mode = background;
147*324bb76bSAndroid Build Coastguard Worker top->color = atoi(optarg);
148*324bb76bSAndroid Build Coastguard Worker break;
149*324bb76bSAndroid Build Coastguard Worker
150*324bb76bSAndroid Build Coastguard Worker case 'd':
151*324bb76bSAndroid Build Coastguard Worker top->mode = delaytime;
152*324bb76bSAndroid Build Coastguard Worker top->delay = atoi(optarg);
153*324bb76bSAndroid Build Coastguard Worker break;
154*324bb76bSAndroid Build Coastguard Worker
155*324bb76bSAndroid Build Coastguard Worker case 'f':
156*324bb76bSAndroid Build Coastguard Worker top->mode = info;
157*324bb76bSAndroid Build Coastguard Worker top->format = optarg;
158*324bb76bSAndroid Build Coastguard Worker break;
159*324bb76bSAndroid Build Coastguard Worker
160*324bb76bSAndroid Build Coastguard Worker case 'i':
161*324bb76bSAndroid Build Coastguard Worker top->mode = interlace;
162*324bb76bSAndroid Build Coastguard Worker top->flag = getbool(optarg);
163*324bb76bSAndroid Build Coastguard Worker break;
164*324bb76bSAndroid Build Coastguard Worker
165*324bb76bSAndroid Build Coastguard Worker case 'n':
166*324bb76bSAndroid Build Coastguard Worker have_selection = true;
167*324bb76bSAndroid Build Coastguard Worker nselected = 0;
168*324bb76bSAndroid Build Coastguard Worker cp = optarg;
169*324bb76bSAndroid Build Coastguard Worker for (;;) {
170*324bb76bSAndroid Build Coastguard Worker size_t span = strspn(cp, "0123456789");
171*324bb76bSAndroid Build Coastguard Worker
172*324bb76bSAndroid Build Coastguard Worker if (span > 0) {
173*324bb76bSAndroid Build Coastguard Worker selected[nselected++] = atoi(cp) - 1;
174*324bb76bSAndroid Build Coastguard Worker cp += span;
175*324bb76bSAndroid Build Coastguard Worker if (*cp == '\0') {
176*324bb76bSAndroid Build Coastguard Worker break;
177*324bb76bSAndroid Build Coastguard Worker } else if (*cp == ',') {
178*324bb76bSAndroid Build Coastguard Worker continue;
179*324bb76bSAndroid Build Coastguard Worker }
180*324bb76bSAndroid Build Coastguard Worker }
181*324bb76bSAndroid Build Coastguard Worker
182*324bb76bSAndroid Build Coastguard Worker (void)fprintf(stderr,
183*324bb76bSAndroid Build Coastguard Worker "giftool: bad selection.\n");
184*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
185*324bb76bSAndroid Build Coastguard Worker }
186*324bb76bSAndroid Build Coastguard Worker break;
187*324bb76bSAndroid Build Coastguard Worker
188*324bb76bSAndroid Build Coastguard Worker case 'p':
189*324bb76bSAndroid Build Coastguard Worker case 's':
190*324bb76bSAndroid Build Coastguard Worker if (status == 'p') {
191*324bb76bSAndroid Build Coastguard Worker top->mode = position;
192*324bb76bSAndroid Build Coastguard Worker } else {
193*324bb76bSAndroid Build Coastguard Worker top->mode = screensize;
194*324bb76bSAndroid Build Coastguard Worker }
195*324bb76bSAndroid Build Coastguard Worker cp = strchr(optarg, ',');
196*324bb76bSAndroid Build Coastguard Worker if (cp == NULL) {
197*324bb76bSAndroid Build Coastguard Worker (void)fprintf(stderr, "giftool: missing comma "
198*324bb76bSAndroid Build Coastguard Worker "in coordinate pair.\n");
199*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
200*324bb76bSAndroid Build Coastguard Worker }
201*324bb76bSAndroid Build Coastguard Worker top->p.x = atoi(optarg);
202*324bb76bSAndroid Build Coastguard Worker top->p.y = atoi(cp + 1);
203*324bb76bSAndroid Build Coastguard Worker if (top->p.x < 0 || top->p.y < 0) {
204*324bb76bSAndroid Build Coastguard Worker (void)fprintf(
205*324bb76bSAndroid Build Coastguard Worker stderr, "giftool: negative coordinate.\n");
206*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
207*324bb76bSAndroid Build Coastguard Worker }
208*324bb76bSAndroid Build Coastguard Worker break;
209*324bb76bSAndroid Build Coastguard Worker
210*324bb76bSAndroid Build Coastguard Worker case 'u':
211*324bb76bSAndroid Build Coastguard Worker top->mode = userinput;
212*324bb76bSAndroid Build Coastguard Worker top->flag = getbool(optarg);
213*324bb76bSAndroid Build Coastguard Worker break;
214*324bb76bSAndroid Build Coastguard Worker
215*324bb76bSAndroid Build Coastguard Worker case 'x':
216*324bb76bSAndroid Build Coastguard Worker top->mode = disposal;
217*324bb76bSAndroid Build Coastguard Worker top->dispose = atoi(optarg);
218*324bb76bSAndroid Build Coastguard Worker break;
219*324bb76bSAndroid Build Coastguard Worker
220*324bb76bSAndroid Build Coastguard Worker default:
221*324bb76bSAndroid Build Coastguard Worker fprintf(stderr,
222*324bb76bSAndroid Build Coastguard Worker "usage: giftool [-b color] [-d delay] [-iI] "
223*324bb76bSAndroid Build Coastguard Worker "[-t color] -[uU] [-x disposal]\n");
224*324bb76bSAndroid Build Coastguard Worker break;
225*324bb76bSAndroid Build Coastguard Worker }
226*324bb76bSAndroid Build Coastguard Worker
227*324bb76bSAndroid Build Coastguard Worker ++top;
228*324bb76bSAndroid Build Coastguard Worker }
229*324bb76bSAndroid Build Coastguard Worker
230*324bb76bSAndroid Build Coastguard Worker /* read in a GIF */
231*324bb76bSAndroid Build Coastguard Worker if ((GifFileIn = DGifOpenFileHandle(0, &ErrorCode)) == NULL) {
232*324bb76bSAndroid Build Coastguard Worker PrintGifError(ErrorCode);
233*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
234*324bb76bSAndroid Build Coastguard Worker }
235*324bb76bSAndroid Build Coastguard Worker if (DGifSlurp(GifFileIn) == GIF_ERROR) {
236*324bb76bSAndroid Build Coastguard Worker PrintGifError(GifFileIn->Error);
237*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
238*324bb76bSAndroid Build Coastguard Worker }
239*324bb76bSAndroid Build Coastguard Worker if ((GifFileOut = EGifOpenFileHandle(1, &ErrorCode)) == NULL) {
240*324bb76bSAndroid Build Coastguard Worker PrintGifError(ErrorCode);
241*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
242*324bb76bSAndroid Build Coastguard Worker }
243*324bb76bSAndroid Build Coastguard Worker
244*324bb76bSAndroid Build Coastguard Worker /* if the selection is defaulted, compute it; otherwise bounds-check it
245*324bb76bSAndroid Build Coastguard Worker */
246*324bb76bSAndroid Build Coastguard Worker if (!have_selection) {
247*324bb76bSAndroid Build Coastguard Worker for (i = nselected = 0; i < GifFileIn->ImageCount; i++) {
248*324bb76bSAndroid Build Coastguard Worker selected[nselected++] = i;
249*324bb76bSAndroid Build Coastguard Worker }
250*324bb76bSAndroid Build Coastguard Worker } else {
251*324bb76bSAndroid Build Coastguard Worker for (i = 0; i < nselected; i++) {
252*324bb76bSAndroid Build Coastguard Worker if (selected[i] >= GifFileIn->ImageCount ||
253*324bb76bSAndroid Build Coastguard Worker selected[i] < 0) {
254*324bb76bSAndroid Build Coastguard Worker (void)fprintf(stderr, "giftool: selection "
255*324bb76bSAndroid Build Coastguard Worker "index out of bounds.\n");
256*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
257*324bb76bSAndroid Build Coastguard Worker }
258*324bb76bSAndroid Build Coastguard Worker }
259*324bb76bSAndroid Build Coastguard Worker }
260*324bb76bSAndroid Build Coastguard Worker
261*324bb76bSAndroid Build Coastguard Worker /* perform the operations we've gathered */
262*324bb76bSAndroid Build Coastguard Worker for (op = operations; op < top; op++) {
263*324bb76bSAndroid Build Coastguard Worker switch (op->mode) {
264*324bb76bSAndroid Build Coastguard Worker case background:
265*324bb76bSAndroid Build Coastguard Worker GifFileIn->SBackGroundColor = op->color;
266*324bb76bSAndroid Build Coastguard Worker break;
267*324bb76bSAndroid Build Coastguard Worker
268*324bb76bSAndroid Build Coastguard Worker case delaytime:
269*324bb76bSAndroid Build Coastguard Worker for (i = 0; i < nselected; i++) {
270*324bb76bSAndroid Build Coastguard Worker GraphicsControlBlock gcb;
271*324bb76bSAndroid Build Coastguard Worker
272*324bb76bSAndroid Build Coastguard Worker DGifSavedExtensionToGCB(GifFileIn, selected[i],
273*324bb76bSAndroid Build Coastguard Worker &gcb);
274*324bb76bSAndroid Build Coastguard Worker gcb.DelayTime = op->delay;
275*324bb76bSAndroid Build Coastguard Worker EGifGCBToSavedExtension(&gcb, GifFileIn,
276*324bb76bSAndroid Build Coastguard Worker selected[i]);
277*324bb76bSAndroid Build Coastguard Worker }
278*324bb76bSAndroid Build Coastguard Worker break;
279*324bb76bSAndroid Build Coastguard Worker
280*324bb76bSAndroid Build Coastguard Worker case info:
281*324bb76bSAndroid Build Coastguard Worker for (i = 0; i < nselected; i++) {
282*324bb76bSAndroid Build Coastguard Worker SavedImage *ip =
283*324bb76bSAndroid Build Coastguard Worker &GifFileIn->SavedImages[selected[i]];
284*324bb76bSAndroid Build Coastguard Worker GraphicsControlBlock gcb;
285*324bb76bSAndroid Build Coastguard Worker for (cp = op->format; *cp; cp++) {
286*324bb76bSAndroid Build Coastguard Worker if (*cp == '\\') {
287*324bb76bSAndroid Build Coastguard Worker char c;
288*324bb76bSAndroid Build Coastguard Worker switch (*++cp) {
289*324bb76bSAndroid Build Coastguard Worker case 'b':
290*324bb76bSAndroid Build Coastguard Worker (void)putchar('\b');
291*324bb76bSAndroid Build Coastguard Worker break;
292*324bb76bSAndroid Build Coastguard Worker case 'e':
293*324bb76bSAndroid Build Coastguard Worker (void)putchar(0x1b);
294*324bb76bSAndroid Build Coastguard Worker break;
295*324bb76bSAndroid Build Coastguard Worker case 'f':
296*324bb76bSAndroid Build Coastguard Worker (void)putchar('\f');
297*324bb76bSAndroid Build Coastguard Worker break;
298*324bb76bSAndroid Build Coastguard Worker case 'n':
299*324bb76bSAndroid Build Coastguard Worker (void)putchar('\n');
300*324bb76bSAndroid Build Coastguard Worker break;
301*324bb76bSAndroid Build Coastguard Worker case 'r':
302*324bb76bSAndroid Build Coastguard Worker (void)putchar('\r');
303*324bb76bSAndroid Build Coastguard Worker break;
304*324bb76bSAndroid Build Coastguard Worker case 't':
305*324bb76bSAndroid Build Coastguard Worker (void)putchar('\t');
306*324bb76bSAndroid Build Coastguard Worker break;
307*324bb76bSAndroid Build Coastguard Worker case 'v':
308*324bb76bSAndroid Build Coastguard Worker (void)putchar('\v');
309*324bb76bSAndroid Build Coastguard Worker break;
310*324bb76bSAndroid Build Coastguard Worker case 'x':
311*324bb76bSAndroid Build Coastguard Worker switch (*++cp) {
312*324bb76bSAndroid Build Coastguard Worker case '0':
313*324bb76bSAndroid Build Coastguard Worker c = (char)0x00;
314*324bb76bSAndroid Build Coastguard Worker break;
315*324bb76bSAndroid Build Coastguard Worker case '1':
316*324bb76bSAndroid Build Coastguard Worker c = (char)0x10;
317*324bb76bSAndroid Build Coastguard Worker break;
318*324bb76bSAndroid Build Coastguard Worker case '2':
319*324bb76bSAndroid Build Coastguard Worker c = (char)0x20;
320*324bb76bSAndroid Build Coastguard Worker break;
321*324bb76bSAndroid Build Coastguard Worker case '3':
322*324bb76bSAndroid Build Coastguard Worker c = (char)0x30;
323*324bb76bSAndroid Build Coastguard Worker break;
324*324bb76bSAndroid Build Coastguard Worker case '4':
325*324bb76bSAndroid Build Coastguard Worker c = (char)0x40;
326*324bb76bSAndroid Build Coastguard Worker break;
327*324bb76bSAndroid Build Coastguard Worker case '5':
328*324bb76bSAndroid Build Coastguard Worker c = (char)0x50;
329*324bb76bSAndroid Build Coastguard Worker break;
330*324bb76bSAndroid Build Coastguard Worker case '6':
331*324bb76bSAndroid Build Coastguard Worker c = (char)0x60;
332*324bb76bSAndroid Build Coastguard Worker break;
333*324bb76bSAndroid Build Coastguard Worker case '7':
334*324bb76bSAndroid Build Coastguard Worker c = (char)0x70;
335*324bb76bSAndroid Build Coastguard Worker break;
336*324bb76bSAndroid Build Coastguard Worker case '8':
337*324bb76bSAndroid Build Coastguard Worker c = (char)0x80;
338*324bb76bSAndroid Build Coastguard Worker break;
339*324bb76bSAndroid Build Coastguard Worker case '9':
340*324bb76bSAndroid Build Coastguard Worker c = (char)0x90;
341*324bb76bSAndroid Build Coastguard Worker break;
342*324bb76bSAndroid Build Coastguard Worker case 'A':
343*324bb76bSAndroid Build Coastguard Worker case 'a':
344*324bb76bSAndroid Build Coastguard Worker c = (char)0xa0;
345*324bb76bSAndroid Build Coastguard Worker break;
346*324bb76bSAndroid Build Coastguard Worker case 'B':
347*324bb76bSAndroid Build Coastguard Worker case 'b':
348*324bb76bSAndroid Build Coastguard Worker c = (char)0xb0;
349*324bb76bSAndroid Build Coastguard Worker break;
350*324bb76bSAndroid Build Coastguard Worker case 'C':
351*324bb76bSAndroid Build Coastguard Worker case 'c':
352*324bb76bSAndroid Build Coastguard Worker c = (char)0xc0;
353*324bb76bSAndroid Build Coastguard Worker break;
354*324bb76bSAndroid Build Coastguard Worker case 'D':
355*324bb76bSAndroid Build Coastguard Worker case 'd':
356*324bb76bSAndroid Build Coastguard Worker c = (char)0xd0;
357*324bb76bSAndroid Build Coastguard Worker break;
358*324bb76bSAndroid Build Coastguard Worker case 'E':
359*324bb76bSAndroid Build Coastguard Worker case 'e':
360*324bb76bSAndroid Build Coastguard Worker c = (char)0xe0;
361*324bb76bSAndroid Build Coastguard Worker break;
362*324bb76bSAndroid Build Coastguard Worker case 'F':
363*324bb76bSAndroid Build Coastguard Worker case 'f':
364*324bb76bSAndroid Build Coastguard Worker c = (char)0xf0;
365*324bb76bSAndroid Build Coastguard Worker break;
366*324bb76bSAndroid Build Coastguard Worker default:
367*324bb76bSAndroid Build Coastguard Worker return -1;
368*324bb76bSAndroid Build Coastguard Worker }
369*324bb76bSAndroid Build Coastguard Worker switch (*++cp) {
370*324bb76bSAndroid Build Coastguard Worker case '0':
371*324bb76bSAndroid Build Coastguard Worker c += 0x00;
372*324bb76bSAndroid Build Coastguard Worker break;
373*324bb76bSAndroid Build Coastguard Worker case '1':
374*324bb76bSAndroid Build Coastguard Worker c += 0x01;
375*324bb76bSAndroid Build Coastguard Worker break;
376*324bb76bSAndroid Build Coastguard Worker case '2':
377*324bb76bSAndroid Build Coastguard Worker c += 0x02;
378*324bb76bSAndroid Build Coastguard Worker break;
379*324bb76bSAndroid Build Coastguard Worker case '3':
380*324bb76bSAndroid Build Coastguard Worker c += 0x03;
381*324bb76bSAndroid Build Coastguard Worker break;
382*324bb76bSAndroid Build Coastguard Worker case '4':
383*324bb76bSAndroid Build Coastguard Worker c += 0x04;
384*324bb76bSAndroid Build Coastguard Worker break;
385*324bb76bSAndroid Build Coastguard Worker case '5':
386*324bb76bSAndroid Build Coastguard Worker c += 0x05;
387*324bb76bSAndroid Build Coastguard Worker break;
388*324bb76bSAndroid Build Coastguard Worker case '6':
389*324bb76bSAndroid Build Coastguard Worker c += 0x06;
390*324bb76bSAndroid Build Coastguard Worker break;
391*324bb76bSAndroid Build Coastguard Worker case '7':
392*324bb76bSAndroid Build Coastguard Worker c += 0x07;
393*324bb76bSAndroid Build Coastguard Worker break;
394*324bb76bSAndroid Build Coastguard Worker case '8':
395*324bb76bSAndroid Build Coastguard Worker c += 0x08;
396*324bb76bSAndroid Build Coastguard Worker break;
397*324bb76bSAndroid Build Coastguard Worker case '9':
398*324bb76bSAndroid Build Coastguard Worker c += 0x09;
399*324bb76bSAndroid Build Coastguard Worker break;
400*324bb76bSAndroid Build Coastguard Worker case 'A':
401*324bb76bSAndroid Build Coastguard Worker case 'a':
402*324bb76bSAndroid Build Coastguard Worker c += 0x0a;
403*324bb76bSAndroid Build Coastguard Worker break;
404*324bb76bSAndroid Build Coastguard Worker case 'B':
405*324bb76bSAndroid Build Coastguard Worker case 'b':
406*324bb76bSAndroid Build Coastguard Worker c += 0x0b;
407*324bb76bSAndroid Build Coastguard Worker break;
408*324bb76bSAndroid Build Coastguard Worker case 'C':
409*324bb76bSAndroid Build Coastguard Worker case 'c':
410*324bb76bSAndroid Build Coastguard Worker c += 0x0c;
411*324bb76bSAndroid Build Coastguard Worker break;
412*324bb76bSAndroid Build Coastguard Worker case 'D':
413*324bb76bSAndroid Build Coastguard Worker case 'd':
414*324bb76bSAndroid Build Coastguard Worker c += 0x0d;
415*324bb76bSAndroid Build Coastguard Worker break;
416*324bb76bSAndroid Build Coastguard Worker case 'E':
417*324bb76bSAndroid Build Coastguard Worker case 'e':
418*324bb76bSAndroid Build Coastguard Worker c += 0x0e;
419*324bb76bSAndroid Build Coastguard Worker break;
420*324bb76bSAndroid Build Coastguard Worker case 'F':
421*324bb76bSAndroid Build Coastguard Worker case 'f':
422*324bb76bSAndroid Build Coastguard Worker c += 0x0f;
423*324bb76bSAndroid Build Coastguard Worker break;
424*324bb76bSAndroid Build Coastguard Worker default:
425*324bb76bSAndroid Build Coastguard Worker return -2;
426*324bb76bSAndroid Build Coastguard Worker }
427*324bb76bSAndroid Build Coastguard Worker putchar(c);
428*324bb76bSAndroid Build Coastguard Worker break;
429*324bb76bSAndroid Build Coastguard Worker default:
430*324bb76bSAndroid Build Coastguard Worker putchar(*cp);
431*324bb76bSAndroid Build Coastguard Worker break;
432*324bb76bSAndroid Build Coastguard Worker }
433*324bb76bSAndroid Build Coastguard Worker } else if (*cp == '%') {
434*324bb76bSAndroid Build Coastguard Worker enum boolmode boolfmt;
435*324bb76bSAndroid Build Coastguard Worker SavedImage *sp =
436*324bb76bSAndroid Build Coastguard Worker &GifFileIn->SavedImages[i];
437*324bb76bSAndroid Build Coastguard Worker
438*324bb76bSAndroid Build Coastguard Worker if (cp[1] == 't') {
439*324bb76bSAndroid Build Coastguard Worker boolfmt = tf;
440*324bb76bSAndroid Build Coastguard Worker ++cp;
441*324bb76bSAndroid Build Coastguard Worker } else if (cp[1] == 'o') {
442*324bb76bSAndroid Build Coastguard Worker boolfmt = onoff;
443*324bb76bSAndroid Build Coastguard Worker ++cp;
444*324bb76bSAndroid Build Coastguard Worker } else if (cp[1] == 'y') {
445*324bb76bSAndroid Build Coastguard Worker boolfmt = yesno;
446*324bb76bSAndroid Build Coastguard Worker ++cp;
447*324bb76bSAndroid Build Coastguard Worker } else if (cp[1] == '1') {
448*324bb76bSAndroid Build Coastguard Worker boolfmt = numeric;
449*324bb76bSAndroid Build Coastguard Worker ++cp;
450*324bb76bSAndroid Build Coastguard Worker } else {
451*324bb76bSAndroid Build Coastguard Worker boolfmt = numeric;
452*324bb76bSAndroid Build Coastguard Worker }
453*324bb76bSAndroid Build Coastguard Worker
454*324bb76bSAndroid Build Coastguard Worker switch (*++cp) {
455*324bb76bSAndroid Build Coastguard Worker case '%':
456*324bb76bSAndroid Build Coastguard Worker putchar('%');
457*324bb76bSAndroid Build Coastguard Worker break;
458*324bb76bSAndroid Build Coastguard Worker case 'a':
459*324bb76bSAndroid Build Coastguard Worker (void)printf(
460*324bb76bSAndroid Build Coastguard Worker "%d",
461*324bb76bSAndroid Build Coastguard Worker GifFileIn
462*324bb76bSAndroid Build Coastguard Worker ->AspectByte);
463*324bb76bSAndroid Build Coastguard Worker break;
464*324bb76bSAndroid Build Coastguard Worker case 'b':
465*324bb76bSAndroid Build Coastguard Worker (void)printf(
466*324bb76bSAndroid Build Coastguard Worker "%d",
467*324bb76bSAndroid Build Coastguard Worker GifFileIn
468*324bb76bSAndroid Build Coastguard Worker ->SBackGroundColor);
469*324bb76bSAndroid Build Coastguard Worker break;
470*324bb76bSAndroid Build Coastguard Worker case 'd':
471*324bb76bSAndroid Build Coastguard Worker DGifSavedExtensionToGCB(
472*324bb76bSAndroid Build Coastguard Worker GifFileIn,
473*324bb76bSAndroid Build Coastguard Worker selected[i], &gcb);
474*324bb76bSAndroid Build Coastguard Worker (void)printf(
475*324bb76bSAndroid Build Coastguard Worker "%d",
476*324bb76bSAndroid Build Coastguard Worker gcb.DelayTime);
477*324bb76bSAndroid Build Coastguard Worker break;
478*324bb76bSAndroid Build Coastguard Worker case 'h':
479*324bb76bSAndroid Build Coastguard Worker (void)printf(
480*324bb76bSAndroid Build Coastguard Worker "%d", ip->ImageDesc
481*324bb76bSAndroid Build Coastguard Worker .Height);
482*324bb76bSAndroid Build Coastguard Worker break;
483*324bb76bSAndroid Build Coastguard Worker case 'n':
484*324bb76bSAndroid Build Coastguard Worker (void)printf(
485*324bb76bSAndroid Build Coastguard Worker "%d",
486*324bb76bSAndroid Build Coastguard Worker selected[i] + 1);
487*324bb76bSAndroid Build Coastguard Worker break;
488*324bb76bSAndroid Build Coastguard Worker case 'p':
489*324bb76bSAndroid Build Coastguard Worker (void)printf(
490*324bb76bSAndroid Build Coastguard Worker "%d,%d",
491*324bb76bSAndroid Build Coastguard Worker ip->ImageDesc.Left,
492*324bb76bSAndroid Build Coastguard Worker ip->ImageDesc.Top);
493*324bb76bSAndroid Build Coastguard Worker break;
494*324bb76bSAndroid Build Coastguard Worker case 's':
495*324bb76bSAndroid Build Coastguard Worker (void)printf(
496*324bb76bSAndroid Build Coastguard Worker "%d,%d",
497*324bb76bSAndroid Build Coastguard Worker GifFileIn->SWidth,
498*324bb76bSAndroid Build Coastguard Worker GifFileIn->SHeight);
499*324bb76bSAndroid Build Coastguard Worker break;
500*324bb76bSAndroid Build Coastguard Worker case 'w':
501*324bb76bSAndroid Build Coastguard Worker (void)printf(
502*324bb76bSAndroid Build Coastguard Worker "%d", ip->ImageDesc
503*324bb76bSAndroid Build Coastguard Worker .Width);
504*324bb76bSAndroid Build Coastguard Worker break;
505*324bb76bSAndroid Build Coastguard Worker case 't':
506*324bb76bSAndroid Build Coastguard Worker DGifSavedExtensionToGCB(
507*324bb76bSAndroid Build Coastguard Worker GifFileIn,
508*324bb76bSAndroid Build Coastguard Worker selected[i], &gcb);
509*324bb76bSAndroid Build Coastguard Worker (void)printf(
510*324bb76bSAndroid Build Coastguard Worker "%d",
511*324bb76bSAndroid Build Coastguard Worker gcb.TransparentColor);
512*324bb76bSAndroid Build Coastguard Worker break;
513*324bb76bSAndroid Build Coastguard Worker case 'u':
514*324bb76bSAndroid Build Coastguard Worker DGifSavedExtensionToGCB(
515*324bb76bSAndroid Build Coastguard Worker GifFileIn,
516*324bb76bSAndroid Build Coastguard Worker selected[i], &gcb);
517*324bb76bSAndroid Build Coastguard Worker (void)printf(
518*324bb76bSAndroid Build Coastguard Worker "%s",
519*324bb76bSAndroid Build Coastguard Worker putbool(
520*324bb76bSAndroid Build Coastguard Worker gcb.UserInputFlag,
521*324bb76bSAndroid Build Coastguard Worker boolfmt));
522*324bb76bSAndroid Build Coastguard Worker break;
523*324bb76bSAndroid Build Coastguard Worker case 'v':
524*324bb76bSAndroid Build Coastguard Worker fputs(EGifGetGifVersion(
525*324bb76bSAndroid Build Coastguard Worker GifFileIn),
526*324bb76bSAndroid Build Coastguard Worker stdout);
527*324bb76bSAndroid Build Coastguard Worker break;
528*324bb76bSAndroid Build Coastguard Worker case 'x':
529*324bb76bSAndroid Build Coastguard Worker DGifSavedExtensionToGCB(
530*324bb76bSAndroid Build Coastguard Worker GifFileIn,
531*324bb76bSAndroid Build Coastguard Worker selected[i], &gcb);
532*324bb76bSAndroid Build Coastguard Worker (void)printf(
533*324bb76bSAndroid Build Coastguard Worker "%d",
534*324bb76bSAndroid Build Coastguard Worker gcb.DisposalMode);
535*324bb76bSAndroid Build Coastguard Worker break;
536*324bb76bSAndroid Build Coastguard Worker case 'z':
537*324bb76bSAndroid Build Coastguard Worker (void)printf(
538*324bb76bSAndroid Build Coastguard Worker "%s",
539*324bb76bSAndroid Build Coastguard Worker putbool(
540*324bb76bSAndroid Build Coastguard Worker sp->ImageDesc
541*324bb76bSAndroid Build Coastguard Worker .ColorMap &&
542*324bb76bSAndroid Build Coastguard Worker sp->ImageDesc
543*324bb76bSAndroid Build Coastguard Worker .ColorMap
544*324bb76bSAndroid Build Coastguard Worker ->SortFlag,
545*324bb76bSAndroid Build Coastguard Worker boolfmt));
546*324bb76bSAndroid Build Coastguard Worker break;
547*324bb76bSAndroid Build Coastguard Worker default:
548*324bb76bSAndroid Build Coastguard Worker (void)fprintf(
549*324bb76bSAndroid Build Coastguard Worker stderr,
550*324bb76bSAndroid Build Coastguard Worker "giftool: bad "
551*324bb76bSAndroid Build Coastguard Worker "format %%%c\n",
552*324bb76bSAndroid Build Coastguard Worker *cp);
553*324bb76bSAndroid Build Coastguard Worker }
554*324bb76bSAndroid Build Coastguard Worker } else {
555*324bb76bSAndroid Build Coastguard Worker (void)putchar(*cp);
556*324bb76bSAndroid Build Coastguard Worker }
557*324bb76bSAndroid Build Coastguard Worker }
558*324bb76bSAndroid Build Coastguard Worker }
559*324bb76bSAndroid Build Coastguard Worker exit(EXIT_SUCCESS);
560*324bb76bSAndroid Build Coastguard Worker break;
561*324bb76bSAndroid Build Coastguard Worker
562*324bb76bSAndroid Build Coastguard Worker case interlace:
563*324bb76bSAndroid Build Coastguard Worker for (i = 0; i < nselected; i++) {
564*324bb76bSAndroid Build Coastguard Worker GifFileIn->SavedImages[selected[i]]
565*324bb76bSAndroid Build Coastguard Worker .ImageDesc.Interlace = op->flag;
566*324bb76bSAndroid Build Coastguard Worker }
567*324bb76bSAndroid Build Coastguard Worker break;
568*324bb76bSAndroid Build Coastguard Worker
569*324bb76bSAndroid Build Coastguard Worker case position:
570*324bb76bSAndroid Build Coastguard Worker for (i = 0; i < nselected; i++) {
571*324bb76bSAndroid Build Coastguard Worker GifFileIn->SavedImages[selected[i]]
572*324bb76bSAndroid Build Coastguard Worker .ImageDesc.Left = op->p.x;
573*324bb76bSAndroid Build Coastguard Worker GifFileIn->SavedImages[selected[i]]
574*324bb76bSAndroid Build Coastguard Worker .ImageDesc.Top = op->p.y;
575*324bb76bSAndroid Build Coastguard Worker }
576*324bb76bSAndroid Build Coastguard Worker break;
577*324bb76bSAndroid Build Coastguard Worker
578*324bb76bSAndroid Build Coastguard Worker case screensize:
579*324bb76bSAndroid Build Coastguard Worker GifFileIn->SWidth = op->p.x;
580*324bb76bSAndroid Build Coastguard Worker GifFileIn->SHeight = op->p.y;
581*324bb76bSAndroid Build Coastguard Worker break;
582*324bb76bSAndroid Build Coastguard Worker
583*324bb76bSAndroid Build Coastguard Worker case transparent:
584*324bb76bSAndroid Build Coastguard Worker for (i = 0; i < nselected; i++) {
585*324bb76bSAndroid Build Coastguard Worker GraphicsControlBlock gcb;
586*324bb76bSAndroid Build Coastguard Worker
587*324bb76bSAndroid Build Coastguard Worker DGifSavedExtensionToGCB(GifFileIn, selected[i],
588*324bb76bSAndroid Build Coastguard Worker &gcb);
589*324bb76bSAndroid Build Coastguard Worker gcb.TransparentColor = op->color;
590*324bb76bSAndroid Build Coastguard Worker EGifGCBToSavedExtension(&gcb, GifFileIn,
591*324bb76bSAndroid Build Coastguard Worker selected[i]);
592*324bb76bSAndroid Build Coastguard Worker }
593*324bb76bSAndroid Build Coastguard Worker break;
594*324bb76bSAndroid Build Coastguard Worker
595*324bb76bSAndroid Build Coastguard Worker case userinput:
596*324bb76bSAndroid Build Coastguard Worker for (i = 0; i < nselected; i++) {
597*324bb76bSAndroid Build Coastguard Worker GraphicsControlBlock gcb;
598*324bb76bSAndroid Build Coastguard Worker
599*324bb76bSAndroid Build Coastguard Worker DGifSavedExtensionToGCB(GifFileIn, selected[i],
600*324bb76bSAndroid Build Coastguard Worker &gcb);
601*324bb76bSAndroid Build Coastguard Worker gcb.UserInputFlag = op->flag;
602*324bb76bSAndroid Build Coastguard Worker EGifGCBToSavedExtension(&gcb, GifFileIn,
603*324bb76bSAndroid Build Coastguard Worker selected[i]);
604*324bb76bSAndroid Build Coastguard Worker }
605*324bb76bSAndroid Build Coastguard Worker break;
606*324bb76bSAndroid Build Coastguard Worker
607*324bb76bSAndroid Build Coastguard Worker case disposal:
608*324bb76bSAndroid Build Coastguard Worker for (i = 0; i < nselected; i++) {
609*324bb76bSAndroid Build Coastguard Worker GraphicsControlBlock gcb;
610*324bb76bSAndroid Build Coastguard Worker
611*324bb76bSAndroid Build Coastguard Worker DGifSavedExtensionToGCB(GifFileIn, selected[i],
612*324bb76bSAndroid Build Coastguard Worker &gcb);
613*324bb76bSAndroid Build Coastguard Worker gcb.DisposalMode = op->dispose;
614*324bb76bSAndroid Build Coastguard Worker EGifGCBToSavedExtension(&gcb, GifFileIn,
615*324bb76bSAndroid Build Coastguard Worker selected[i]);
616*324bb76bSAndroid Build Coastguard Worker }
617*324bb76bSAndroid Build Coastguard Worker break;
618*324bb76bSAndroid Build Coastguard Worker
619*324bb76bSAndroid Build Coastguard Worker default:
620*324bb76bSAndroid Build Coastguard Worker (void)fprintf(stderr,
621*324bb76bSAndroid Build Coastguard Worker "giftool: unknown operation mode\n");
622*324bb76bSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
623*324bb76bSAndroid Build Coastguard Worker }
624*324bb76bSAndroid Build Coastguard Worker }
625*324bb76bSAndroid Build Coastguard Worker
626*324bb76bSAndroid Build Coastguard Worker /* write out the results */
627*324bb76bSAndroid Build Coastguard Worker GifFileOut->SWidth = GifFileIn->SWidth;
628*324bb76bSAndroid Build Coastguard Worker GifFileOut->SHeight = GifFileIn->SHeight;
629*324bb76bSAndroid Build Coastguard Worker GifFileOut->SColorResolution = GifFileIn->SColorResolution;
630*324bb76bSAndroid Build Coastguard Worker GifFileOut->SBackGroundColor = GifFileIn->SBackGroundColor;
631*324bb76bSAndroid Build Coastguard Worker if (GifFileIn->SColorMap != NULL) {
632*324bb76bSAndroid Build Coastguard Worker GifFileOut->SColorMap =
633*324bb76bSAndroid Build Coastguard Worker GifMakeMapObject(GifFileIn->SColorMap->ColorCount,
634*324bb76bSAndroid Build Coastguard Worker GifFileIn->SColorMap->Colors);
635*324bb76bSAndroid Build Coastguard Worker }
636*324bb76bSAndroid Build Coastguard Worker
637*324bb76bSAndroid Build Coastguard Worker for (i = 0; i < GifFileIn->ImageCount; i++) {
638*324bb76bSAndroid Build Coastguard Worker (void)GifMakeSavedImage(GifFileOut, &GifFileIn->SavedImages[i]);
639*324bb76bSAndroid Build Coastguard Worker }
640*324bb76bSAndroid Build Coastguard Worker
641*324bb76bSAndroid Build Coastguard Worker if (EGifSpew(GifFileOut) == GIF_ERROR) {
642*324bb76bSAndroid Build Coastguard Worker PrintGifError(GifFileOut->Error);
643*324bb76bSAndroid Build Coastguard Worker } else if (DGifCloseFile(GifFileIn, &ErrorCode) == GIF_ERROR) {
644*324bb76bSAndroid Build Coastguard Worker PrintGifError(ErrorCode);
645*324bb76bSAndroid Build Coastguard Worker }
646*324bb76bSAndroid Build Coastguard Worker
647*324bb76bSAndroid Build Coastguard Worker return 0;
648*324bb76bSAndroid Build Coastguard Worker }
649*324bb76bSAndroid Build Coastguard Worker
650*324bb76bSAndroid Build Coastguard Worker /* end */
651