gifsicle  1.92
About: Gifsicle is a UNIX command-line tool for creating, editing, and getting information about GIF images and animations.
  Fossies Dox: gifsicle-1.92.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

gifsicle.c
Go to the documentation of this file.
1 /* -*- c-basic-offset: 2 -*- */
2 /* gifsicle.c - gifsicle's main loop.
3  Copyright (C) 1997-2019 Eddie Kohler, ekohler@gmail.com
4  This file is part of gifsicle.
5 
6  Gifsicle is free software. It is distributed under the GNU Public License,
7  version 2; you can copy, distribute, or alter it at will, as long
8  as this notice is kept intact and this source code is made available. There
9  is no warranty, express or implied. */
10 
11 #include <config.h>
12 #include "gifsicle.h"
13 #include "kcolor.h"
14 #include <string.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <ctype.h>
18 #include <assert.h>
19 #include <errno.h>
20 #if HAVE_UNISTD_H
21 # include <unistd.h>
22 #endif
23 
24 #ifndef static_assert
25 #define static_assert(x, msg) switch ((int) (x)) case 0: case !!((int) (x)):
26 #endif
27 
29 
33 
35 const char *input_name = 0;
36 static int unoptimizing = 0;
37 
39 int thread_count = 0;
40 
41 static int gif_read_flags = 0;
42 static int nextfile = 0;
44 
45 static int frames_done = 0;
46 static int files_given = 0;
47 
49 
52 
54 int nested_mode = 0;
55 
56 static int infoing = 0;
57 int verbosing = 0;
58 static int no_ignore_errors = 0;
59 
60 
61 #define CHANGED(next, flag) (((next) & (1<<(flag))) != 0)
62 #define UNCHECKED_MARK_CH(where, what) \
63  next_##where |= 1<<what;
64 #define MARK_CH(where, what) do { \
65  if (CHANGED(next_##where, what)) \
66  redundant_option_warning(where##_option_types[what]); \
67  UNCHECKED_MARK_CH(where, what); \
68  } while (0)
69 
70 /* frame option types */
71 static int next_frame = 0;
72 #define CH_INTERLACE 0
73 #define CH_DISPOSAL 1
74 #define CH_DELAY 2
75 #define CH_TRANSPARENT 3
76 #define CH_COMMENT 4
77 #define CH_NAME 5
78 #define CH_POSITION 6
79 #define CH_CROP 7
80 #define CH_EXTENSION 8
81 #define CH_FLIP 9
82 #define CH_ROTATE 10
83 static const char *frame_option_types[] = {
84  "interlace", "disposal", "delay", "transparency",
85  "comment", "name", "position", "crop",
86  "extension", "flip", "rotation"
87 };
88 
89 /* input option types */
90 static int next_input = 0;
91 #define CH_UNOPTIMIZE 0
92 #define CH_CHANGE_COLOR 1
93 static const char *input_option_types[] = {
94  "unoptimization", "color change"
95 };
96 
97 /* output option types */
100 static int next_output = 0;
101 static int active_next_output = 0;
102 static int any_output_successful = 0;
103 #define CH_LOOPCOUNT 0
104 #define CH_LOGICAL_SCREEN 1
105 #define CH_OPTIMIZE 2
106 #define CH_OUTPUT 3
107 #define CH_COLORMAP 4
108 #define CH_DITHER 5
109 #define CH_USE_COLORMAP 6
110 #define CH_COLORMAP_METHOD 7
111 #define CH_BACKGROUND 8
112 #define CH_COLOR_TRANSFORM 9
113 #define CH_RESIZE 10
114 #define CH_MEMORY 11
115 #define CH_GAMMA 12
116 #define CH_RESIZE_METHOD 13
117 #define CH_SCALE_COLORS 14
118 static const char *output_option_types[] = {
119  "loopcount", "logical screen", "optimization", "output file",
120  "colormap size", "dither", "colormap", "colormap method",
121  "background", "color transformation", "resize", "memory conservation",
122  "gamma", "resize method", "resize colors"
123 };
124 
125 
126 #define SAME_INTERLACE_OPT 300
127 #define INFO_OPT 301
128 #define DISPOSAL_OPT 302
129 #define SAME_LOOPCOUNT_OPT 303
130 #define SAME_DISPOSAL_OPT 304
131 #define SAME_DELAY_OPT 305
132 #define SAME_TRANSPARENT_OPT 308
133 #define LOGICAL_SCREEN_OPT 309
134 #define COMMENT_OPT 310
135 #define UNOPTIMIZE_OPT 311
136 #define CAREFUL_OPT 312
137 #define OPTIMIZE_OPT 313
138 #define SAME_LOGICAL_SCREEN_OPT 314
139 #define DELETE_OPT 315
140 #define REPLACE_OPT 316
141 #define INSERT_OPT 317
142 #define ALTER_DONE_OPT 318
143 #define APPEND_OPT 319
144 #define COLOR_INFO_OPT 320
145 #define VERBOSE_OPT 321
146 #define NO_COMMENTS_OPT 322
147 #define SAME_COMMENTS_OPT 323
148 #define NAME_OPT 324
149 #define SAME_NAME_OPT 325
150 #define NO_NAME_OPT 326
151 #define POSITION_OPT 327
152 #define SAME_POSITION_OPT 328
153 #define VERSION_OPT 329
154 #define HELP_OPT 330
155 #define OUTPUT_OPT 331
156 #define CROP_OPT 332
157 #define SAME_CROP_OPT 333
158 #define CHANGE_COLOR_OPT 334
159 #define COLORMAP_OPT 335
160 #define COLORMAP_ALGORITHM_OPT 336
161 #define DITHER_OPT 337
162 #define USE_COLORMAP_OPT 338
163 #define NO_EXTENSIONS_OPT 339
164 #define SAME_EXTENSIONS_OPT 340
165 #define EXTENSION_INFO_OPT 341
166 #define BACKGROUND_OPT 342
167 #define SAME_BACKGROUND_OPT 343
168 #define FLIP_HORIZ_OPT 344
169 #define FLIP_VERT_OPT 345
170 #define NO_FLIP_OPT 346
171 #define ROTATE_90_OPT 347
172 #define ROTATE_180_OPT 348
173 #define ROTATE_270_OPT 349
174 #define NO_ROTATE_OPT 350
175 #define APP_EXTENSION_OPT 351
176 #define EXTENSION_OPT 352
177 #define COLOR_TRANSFORM_OPT 353
178 #define RESIZE_OPT 354
179 #define SCALE_OPT 355
180 #define NO_WARNINGS_OPT 356
181 #define WARNINGS_OPT 357
182 #define RESIZE_WIDTH_OPT 358
183 #define RESIZE_HEIGHT_OPT 359
184 #define CROP_TRANSPARENCY_OPT 360
185 #define CONSERVE_MEMORY_OPT 361
186 #define MULTIFILE_OPT 362
187 #define NEXTFILE_OPT 363
188 #define RESIZE_FIT_OPT 364
189 #define RESIZE_FIT_WIDTH_OPT 365
190 #define RESIZE_FIT_HEIGHT_OPT 366
191 #define SIZE_INFO_OPT 367
192 #define GAMMA_OPT 368
193 #define GRAY_OPT 369
194 #define RESIZE_METHOD_OPT 370
195 #define RESIZE_COLORS_OPT 371
196 #define NO_APP_EXTENSIONS_OPT 372
197 #define SAME_APP_EXTENSIONS_OPT 373
198 #define IGNORE_ERRORS_OPT 374
199 #define THREADS_OPT 375
200 #define RESIZE_GEOMETRY_OPT 376
201 #define RESIZE_TOUCH_OPT 377
202 #define RESIZE_TOUCH_WIDTH_OPT 378
203 #define RESIZE_TOUCH_HEIGHT_OPT 379
204 #define LOSSY_OPT 380
205 
206 #define LOOP_TYPE (Clp_ValFirstUser)
207 #define DISPOSAL_TYPE (Clp_ValFirstUser + 1)
208 #define DIMENSIONS_TYPE (Clp_ValFirstUser + 2)
209 #define FRAME_SPEC_TYPE (Clp_ValFirstUser + 3)
210 #define COLOR_TYPE (Clp_ValFirstUser + 4)
211 #define POSITION_TYPE (Clp_ValFirstUser + 5)
212 #define RECTANGLE_TYPE (Clp_ValFirstUser + 6)
213 #define TWO_COLORS_TYPE (Clp_ValFirstUser + 7)
214 #define COLORMAP_ALG_TYPE (Clp_ValFirstUser + 8)
215 #define SCALE_FACTOR_TYPE (Clp_ValFirstUser + 9)
216 #define OPTIMIZE_TYPE (Clp_ValFirstUser + 10)
217 #define RESIZE_METHOD_TYPE (Clp_ValFirstUser + 11)
218 
219 const Clp_Option options[] = {
220 
221  { "append", 0, APPEND_OPT, 0, 0 },
222  { "app-extension", 'x', APP_EXTENSION_OPT, Clp_ValString, 0 },
223  { "no-app-extensions", 0, NO_APP_EXTENSIONS_OPT, 0, 0 },
224 
225  { "background", 'B', BACKGROUND_OPT, COLOR_TYPE, Clp_Negate },
226  { "batch", 'b', 'b', 0, 0 },
227  { "bg", 0, BACKGROUND_OPT, COLOR_TYPE, Clp_Negate },
228 
229  { "careful", 0, CAREFUL_OPT, 0, Clp_Negate },
230  { "change-color", 0, CHANGE_COLOR_OPT, TWO_COLORS_TYPE, Clp_Negate },
231  { "cinfo", 0, COLOR_INFO_OPT, 0, Clp_Negate },
232  { "clip", 0, CROP_OPT, RECTANGLE_TYPE, Clp_Negate },
233  { "colors", 'k', COLORMAP_OPT, Clp_ValInt, Clp_Negate },
234  { "color-method", 0, COLORMAP_ALGORITHM_OPT, COLORMAP_ALG_TYPE, 0 },
235  { "color-info", 0, COLOR_INFO_OPT, 0, Clp_Negate },
236  { "comment", 'c', COMMENT_OPT, Clp_ValString, 0 },
237  { "no-comments", 'c', NO_COMMENTS_OPT, 0, 0 },
238  { "conserve-memory", 0, CONSERVE_MEMORY_OPT, 0, Clp_Negate },
239  { "crop", 0, CROP_OPT, RECTANGLE_TYPE, Clp_Negate },
240  { "crop-transparency", 0, CROP_TRANSPARENCY_OPT, 0, Clp_Negate },
241 
242  { "delay", 'd', 'd', Clp_ValInt, Clp_Negate },
243  { "delete", 0, DELETE_OPT, 0, 0 },
244  { "disposal", 'D', DISPOSAL_OPT, DISPOSAL_TYPE, Clp_Negate },
245  { 0, 'f', DITHER_OPT, 0, Clp_Negate },
246  { "dither", 0, DITHER_OPT, Clp_ValString, Clp_Negate | Clp_Optional },
247  { "done", 0, ALTER_DONE_OPT, 0, 0 },
248 
249  { "explode", 'e', 'e', 0, 0 },
250  { "explode-by-name", 'E', 'E', 0, 0 },
251  { "extension", 0, EXTENSION_OPT, Clp_ValString, 0 },
252  { "no-extension", 0, NO_EXTENSIONS_OPT, 0, 0 },
253  { "no-extensions", 'x', NO_EXTENSIONS_OPT, 0, 0 },
254  { "extension-info", 0, EXTENSION_INFO_OPT, 0, Clp_Negate },
255 
256  { "flip-horizontal", 0, FLIP_HORIZ_OPT, 0, Clp_Negate },
257  { "flip-vertical", 0, FLIP_VERT_OPT, 0, Clp_Negate },
258  { "no-flip", 0, NO_FLIP_OPT, 0, 0 },
259 
260  { "gamma", 0, GAMMA_OPT, Clp_ValString, Clp_Negate },
261  { "gray", 0, GRAY_OPT, 0, 0 },
262 
263  { "help", 'h', HELP_OPT, 0, 0 },
264 
265  { "ignore-errors", 0, IGNORE_ERRORS_OPT, 0, Clp_Negate },
266  { "info", 'I', INFO_OPT, 0, Clp_Negate },
267  { "insert-before", 0, INSERT_OPT, FRAME_SPEC_TYPE, 0 },
268  { "interlace", 'i', 'i', 0, Clp_Negate },
269 
270  { "logical-screen", 'S', LOGICAL_SCREEN_OPT, DIMENSIONS_TYPE, Clp_Negate },
271  { "loopcount", 'l', 'l', LOOP_TYPE, Clp_Optional | Clp_Negate },
272  { "lossy", 0, LOSSY_OPT, Clp_ValInt, Clp_Optional },
273 
274  { "merge", 'm', 'm', 0, 0 },
275  { "method", 0, COLORMAP_ALGORITHM_OPT, COLORMAP_ALG_TYPE, 0 },
276  { "multifile", 0, MULTIFILE_OPT, 0, Clp_Negate },
277 
278  { "name", 'n', NAME_OPT, Clp_ValString, 0 },
279  { "nextfile", 0, NEXTFILE_OPT, 0, Clp_Negate },
280  { "no-names", 'n', NO_NAME_OPT, 0, 0 },
281 
282  { "optimize", 'O', OPTIMIZE_OPT, OPTIMIZE_TYPE, Clp_Negate | Clp_Optional },
283  { "output", 'o', OUTPUT_OPT, Clp_ValStringNotOption, 0 },
284 
285  { "position", 'p', POSITION_OPT, POSITION_TYPE, Clp_Negate },
286 
287  { "replace", 0, REPLACE_OPT, FRAME_SPEC_TYPE, 0 },
288  { "resize", 0, RESIZE_OPT, DIMENSIONS_TYPE, Clp_Negate },
289  { "resize-width", 0, RESIZE_WIDTH_OPT, Clp_ValUnsigned, Clp_Negate },
290  { "resize-height", 0, RESIZE_HEIGHT_OPT, Clp_ValUnsigned, Clp_Negate },
291  { "resiz", 0, RESIZE_OPT, DIMENSIONS_TYPE, Clp_Negate },
292  { "resi", 0, RESIZE_OPT, DIMENSIONS_TYPE, Clp_Negate },
293  { "res", 0, RESIZE_OPT, DIMENSIONS_TYPE, Clp_Negate },
294  { "resize-fit", 0, RESIZE_FIT_OPT, DIMENSIONS_TYPE, Clp_Negate },
295  { "resize-fit-width", 0, RESIZE_FIT_WIDTH_OPT, Clp_ValUnsigned, Clp_Negate },
296  { "resize-fit-height", 0, RESIZE_FIT_HEIGHT_OPT, Clp_ValUnsigned, Clp_Negate },
297  { "resize-fi", 0, RESIZE_FIT_OPT, DIMENSIONS_TYPE, Clp_Negate },
298  { "resize-f", 0, RESIZE_FIT_OPT, DIMENSIONS_TYPE, Clp_Negate },
299  { "resize-touch", 0, RESIZE_TOUCH_OPT, DIMENSIONS_TYPE, Clp_Negate },
300  { "resize-touch-width", 0, RESIZE_TOUCH_WIDTH_OPT, Clp_ValUnsigned, Clp_Negate },
301  { "resize-touch-height", 0, RESIZE_TOUCH_HEIGHT_OPT, Clp_ValUnsigned, Clp_Negate },
302  { "resize-touc", 0, RESIZE_TOUCH_OPT, DIMENSIONS_TYPE, Clp_Negate },
303  { "resize-tou", 0, RESIZE_TOUCH_OPT, DIMENSIONS_TYPE, Clp_Negate },
304  { "resize-to", 0, RESIZE_TOUCH_OPT, DIMENSIONS_TYPE, Clp_Negate },
305  { "resize-t", 0, RESIZE_TOUCH_OPT, DIMENSIONS_TYPE, Clp_Negate },
306  { "resize-geometry", 0, RESIZE_GEOMETRY_OPT, Clp_ValString, Clp_Negate },
307  { "resize-method", 0, RESIZE_METHOD_OPT, RESIZE_METHOD_TYPE, 0 },
308  { "resize-colors", 0, RESIZE_COLORS_OPT, Clp_ValInt, Clp_Negate },
309  { "rotate-90", 0, ROTATE_90_OPT, 0, 0 },
310  { "rotate-180", 0, ROTATE_180_OPT, 0, 0 },
311  { "rotate-270", 0, ROTATE_270_OPT, 0, 0 },
312  { "no-rotate", 0, NO_ROTATE_OPT, 0, 0 },
313 
314  { "same-app-extensions", 0, SAME_APP_EXTENSIONS_OPT, 0, 0 },
315  { "same-background", 0, SAME_BACKGROUND_OPT, 0, 0 },
316  { "same-bg", 0, SAME_BACKGROUND_OPT, 0, 0 },
317  { "same-clip", 0, SAME_CROP_OPT, 0, 0 },
318  { "same-comments", 0, SAME_COMMENTS_OPT, 0, 0 },
319  { "same-crop", 0, SAME_CROP_OPT, 0, 0 },
320  { "same-extensions", 0, SAME_EXTENSIONS_OPT, 0, 0 },
321  { "same-interlace", 0, SAME_INTERLACE_OPT, 0, 0 },
322  { "same-logical-screen", 0, SAME_LOGICAL_SCREEN_OPT, 0, 0 },
323  { "same-loopcount", 0, SAME_LOOPCOUNT_OPT, 0, 0 },
324  { "same-disposal", 0, SAME_DISPOSAL_OPT, 0, 0 },
325  { "same-delay", 0, SAME_DELAY_OPT, 0, 0 },
326  { "same-names", 0, SAME_NAME_OPT, 0, 0 },
327  { "same-position", 0, SAME_POSITION_OPT, 0, 0 },
328  { "same-screen", 0, SAME_LOGICAL_SCREEN_OPT, 0, 0 },
329  { "same-transparent", 0, SAME_TRANSPARENT_OPT, 0, 0 },
330  { "scale", 0, SCALE_OPT, SCALE_FACTOR_TYPE, Clp_Negate },
331  { "scale-method", 0, RESIZE_METHOD_OPT, RESIZE_METHOD_TYPE, 0 },
332  { "scale-colors", 0, RESIZE_COLORS_OPT, Clp_ValInt, Clp_Negate },
333  { "screen", 0, LOGICAL_SCREEN_OPT, DIMENSIONS_TYPE, Clp_Negate },
334  { "sinfo", 0, SIZE_INFO_OPT, 0, Clp_Negate },
335  { "size-info", 0, SIZE_INFO_OPT, 0, Clp_Negate },
336 
337  { "transform-colormap", 0, COLOR_TRANSFORM_OPT, Clp_ValStringNotOption,
338  Clp_Negate },
339  { "transparent", 't', 't', COLOR_TYPE, Clp_Negate },
340 
341  { "unoptimize", 'U', UNOPTIMIZE_OPT, 0, Clp_Negate },
342  { "use-colormap", 0, USE_COLORMAP_OPT, Clp_ValString, Clp_Negate },
343 
344  { "verbose", 'V', VERBOSE_OPT, 0, Clp_Negate },
345  { 0, 'v', VERBOSE_OPT, 0, Clp_Negate },
346  { "version", 0, VERSION_OPT, 0, 0 },
347 
348  { 0, 'w', NO_WARNINGS_OPT, 0, Clp_Negate },
349  { "warnings", 0, WARNINGS_OPT, 0, Clp_Negate },
350 
351  { "xinfo", 0, EXTENSION_INFO_OPT, 0, Clp_Negate },
352  { "threads", 'j', THREADS_OPT, Clp_ValUnsigned, Clp_Optional | Clp_Negate },
353 
354 };
355 
357 
358 
359 static void combine_output_options(void);
360 static void initialize_def_frame(void);
361 static void redundant_option_warning(const char *);
362 
363 #if 0
364 void resize_check(void)
365 {
366  int nw, nh;
367  nw = nh = 256;
368  resize_dimensions(&nw, &nh, 640, 480, 0);
369  assert(nw == 640 && nh == 480);
370 
371  nw = nh = 256;
372  resize_dimensions(&nw, &nh, 640, 480, GT_RESIZE_FIT);
373  assert(nw == 480 && nh == 480);
374 
375  nw = nh = 512;
376  resize_dimensions(&nw, &nh, 640, 480, GT_RESIZE_FIT);
377  assert(nw == 480 && nh == 480);
378 
379  nw = nh = 256;
380  resize_dimensions(&nw, &nh, 640, 480, GT_RESIZE_FIT | GT_RESIZE_FIT_DOWN);
381  assert(nw == 256 && nh == 256);
382 
383  nw = nh = 512;
384  resize_dimensions(&nw, &nh, 640, 480, GT_RESIZE_FIT | GT_RESIZE_FIT_DOWN);
385  assert(nw == 480 && nh == 480);
386 
387  nw = nh = 256;
388  resize_dimensions(&nw, &nh, 640, 480, GT_RESIZE_FIT | GT_RESIZE_FIT_UP);
389  assert(nw == 480 && nh == 480);
390 
391  nw = nh = 512;
392  resize_dimensions(&nw, &nh, 640, 480, GT_RESIZE_FIT | GT_RESIZE_FIT_UP);
393  assert(nw == 512 && nh == 512);
394 
395  nw = nh = 256;
397  assert(nw == 640 && nh == 640);
398 
399  fprintf(stderr, "got\n");
400 }
401 #endif
402 
403 
404 static void
405 set_mode(int newmode)
406 {
407  if (mode == BLANK_MODE) {
408  if (newmode != BLANK_MODE)
409  mode = newmode;
410  else if (infoing == 1)
411  mode = INFOING;
412  else
413  mode = MERGING;
414  }
415 
416  if (mode != INFOING && infoing == 1)
417  fatal_error("%<--info%> suppresses normal output, can%,t use with an\n output mode like %<--merge%> or %<--batch%>.\n (Try %<-II%>, which doesn%,t suppress normal output.)");
418  if (newmode != BLANK_MODE && newmode != mode)
419  fatal_error("too late to change modes");
420 }
421 
422 
423 void
425 {
426  int i;
427  Gt_Frameset *fset;
428 
430  if (mode < DELETING && frames_done) {
431  fatal_error("frame selection and frame changes don%,t mix");
432  return;
433  }
434  assert(!nested_mode);
435  nested_mode = mode;
436  if (frame_spec_1 > frame_spec_2) {
437  i = frame_spec_1;
439  frame_spec_2 = i;
440  }
441 
442  switch (kind) {
443 
444  case DELETE_OPT:
445  mode = DELETING;
446  break;
447 
448  case REPLACE_OPT:
449  for (i = frame_spec_1; i < frame_spec_2; i++)
450  FRAME(frames, i).use = 0;
451  /* We want to use the last frame's delay, but nothing else about it. */
452  FRAME(frames, i).use = -1;
453  /* FALLTHRU */
454 
455  case INSERT_OPT:
456  /* Define a nested frameset (or use an existing one). */
457  fset = FRAME(frames, frame_spec_2).nest;
458  if (!fset) fset = new_frameset(8);
459  FRAME(frames, frame_spec_2).nest = fset;
460 
461  /* Later: Merge frames at the end of the nested frameset. */
462  mode = INSERTING;
464  frames = fset;
465  break;
466 
467  case APPEND_OPT:
468  /* Just merge frames at the end of this frameset. */
469  mode = INSERTING;
470  break;
471 
472  }
473 }
474 
475 static void
477 {
478  if (nested_mode)
479  mode = nested_mode;
480  if (nested_frames)
482  nested_mode = 0;
483  nested_frames = 0;
484 }
485 
486 
487 static void
488 show_frame(int imagenumber, int usename)
489 {
490  Gif_Image *gfi;
491  Gt_Frame *frame;
492 
493  if (!input || !(gfi = Gif_GetImage(input, imagenumber)))
494  return;
495 
496  switch (mode) {
497 
498  case MERGING:
499  case INSERTING:
500  case EXPLODING:
501  case INFOING:
502  case BATCHING:
503  if (!frames_done)
505  frame = add_frame(frames, input, gfi);
506  if (usename)
507  frame->explode_by_name = 1;
508  break;
509 
510  case DELETING:
511  frame = &FRAME(frames, first_input_frame + imagenumber);
512  frame->use = 0;
513  break;
514 
515  }
516 
517  next_frame = 0;
518  frames_done = 1;
519 }
520 
521 
522 /*****
523  * input a stream
524  **/
525 
526 static void
528  int is_error, const char* message)
529 {
530  static int last_is_error = 0;
531  static char last_landmark[256];
532  static char last_message[256];
533  static int different_error_count = 0;
534  static int same_error_count = 0;
535  char landmark[256];
536  int which_image = Gif_ImageNumber(gfs, gfi);
537  if (gfs && which_image < 0)
538  which_image = gfs->nimages;
539 
540  /* ignore warnings if "no_warning" */
541  if (no_warnings && is_error == 0)
542  return;
543 
544  if (message) {
545  const char *filename = gfs && gfs->landmark ? gfs->landmark : "<unknown>";
546  if (gfi && (which_image != 0 || gfs->nimages != 1))
547  snprintf(landmark, sizeof(landmark), "%s:#%d",
548  filename, which_image < 0 ? gfs->nimages : which_image);
549  else
550  snprintf(landmark, sizeof(landmark), "%s", filename);
551  }
552 
553  if (last_message[0]
554  && different_error_count <= 10
555  && (!message
556  || strcmp(message, last_message) != 0
557  || strcmp(landmark, last_landmark) != 0)) {
558  const char* etype = last_is_error ? "read error: " : "";
559  void (*f)(const char*, const char*, ...) = last_is_error ? lerror : lwarning;
560  if (gfi && gfi->user_flags)
561  /* error already reported */;
562  else if (same_error_count == 1)
563  f(last_landmark, "%s%s", etype, last_message);
564  else if (same_error_count > 0)
565  f(last_landmark, "%s%s (%d times)", etype, last_message, same_error_count);
566  same_error_count = 0;
567  last_message[0] = 0;
568  }
569 
570  if (message) {
571  if (last_message[0] == 0)
572  different_error_count++;
573  same_error_count++;
574  strncpy(last_message, message, sizeof(last_message));
575  last_message[sizeof(last_message) - 1] = 0;
576  strncpy(last_landmark, landmark, sizeof(last_landmark));
577  last_landmark[sizeof(last_landmark) - 1] = 0;
578  last_is_error = is_error;
579  if (different_error_count == 11) {
580  if (!(gfi && gfi->user_flags))
581  error(0, "(plus more errors; is this GIF corrupt?)");
582  different_error_count++;
583  }
584  } else
585  last_message[0] = 0;
586 
587  {
588  unsigned long missing;
589  if (message && sscanf(message, "missing %lu pixel", &missing) == 1
590  && missing > 10000 && no_ignore_errors) {
591  gifread_error(gfs, 0, -1, 0);
592  lerror(landmark, "fatal error: too many missing pixels, giving up");
593  exit(1);
594  }
595  }
596 
597  if (gfi && is_error < 0)
598  gfi->user_flags |= 1;
599 }
600 
601 struct StoredFile {
602  FILE *f;
603  struct StoredFile *next;
604  char name[1];
605 };
606 
607 static struct StoredFile *stored_files = 0;
608 
609 static FILE *
610 open_giffile(const char *name)
611 {
612  struct StoredFile *sf;
613  FILE *f;
614 
615  if (name == 0 || strcmp(name, "-") == 0) {
616 #ifndef OUTPUT_GIF_TO_TERMINAL
617  if (isatty(fileno(stdin))) {
618  lerror("<stdin>", "Is a terminal");
619  return NULL;
620  }
621 #endif
622 #if defined(_MSDOS) || defined(_WIN32)
623  _setmode(_fileno(stdin), _O_BINARY);
624 #elif defined(__DJGPP__)
625  setmode(fileno(stdin), O_BINARY);
626 #elif defined(__EMX__)
627  _fsetmode(stdin, "b");
628 #endif
629  return stdin;
630  }
631 
632  if (nextfile)
633  for (sf = stored_files; sf; sf = sf->next)
634  if (strcmp(name, sf->name) == 0)
635  return sf->f;
636 
637  f = fopen(name, "rb");
638 
639  if (f && nextfile) {
640  sf = (struct StoredFile *) malloc(sizeof(struct StoredFile) + strlen(name));
641  sf->f = f;
642  sf->next = stored_files;
643  stored_files = sf;
644  strcpy(sf->name, name);
645  } else if (!f)
646  lerror(name, "%s", strerror(errno));
647 
648  return f;
649 }
650 
651 static void
652 close_giffile(FILE *f, int final)
653 {
654  struct StoredFile **sf_pprev, *sf;
655 
656  if (!final && nextfile) {
657  int c = getc(f);
658  if (c == EOF)
659  final = 1;
660  else
661  ungetc(c, f);
662  }
663 
664  for (sf_pprev = &stored_files; (sf = *sf_pprev); sf_pprev = &sf->next)
665  if (sf->f == f) {
666  if (final) {
667  fclose(f);
668  *sf_pprev = sf->next;
669  free((void *) sf);
670  }
671  return;
672  }
673 
674  if (f != stdin)
675  fclose(f);
676 }
677 
678 void
679 input_stream(const char *name)
680 {
681  char* component_namebuf;
682  FILE *f;
683  Gif_Stream *gfs;
684  int i;
685  int saved_next_frame = next_frame;
686  int componentno = 0;
687  const char *main_name = 0;
688  Gt_Frame old_def_frame;
689 
690  input = 0;
691  input_name = name;
692  frames_done = 0;
693  next_frame = 0;
694  next_input = 0;
695  if (next_output)
697  files_given++;
698 
700 
701  f = open_giffile(name);
702  if (!f)
703  return;
704  if (f == stdin) {
705  name = "<stdin>";
706  input_name = 0;
707  }
708  main_name = name;
709 
710  retry_file:
711  /* change filename for component files */
712  componentno++;
713  if (componentno > 1) {
714  component_namebuf = (char*) malloc(strlen(main_name) + 10);
715  sprintf(component_namebuf, "%s~%d", main_name, componentno);
716  name = component_namebuf;
717  } else
718  component_namebuf = 0;
719 
720  /* check for empty file */
721  i = getc(f);
722  if (i == EOF) {
724  lerror(name, "empty file");
725  else if (nextfile)
726  lerror(name, "no more images in file");
727  goto error;
728  }
729  ungetc(i, f);
730 
731  if (verbosing)
732  verbose_open('<', name);
733 
734  /* read file */
735  {
736  int old_error_count = error_count;
739  if ((!gfs || (Gif_ImageCount(gfs) == 0 && gfs->errors > 0))
740  && componentno != 1)
741  lerror(name, "trailing garbage ignored");
742  if (!no_ignore_errors)
743  error_count = old_error_count;
744  }
745 
746  if (!gfs || (Gif_ImageCount(gfs) == 0 && gfs->errors > 0)) {
747  if (componentno == 1)
748  lerror(name, "file not in GIF format");
749  Gif_DeleteStream(gfs);
750  if (verbosing)
751  verbose_close('>');
752  goto error;
753  }
754 
755  /* special processing for components after the first */
756  if (componentno > 1) {
757  if (mode == BATCHING || mode == INSERTING)
758  fatal_error("%s: %<--multifile%> is useful only in merge mode", name);
759  input_done();
760  }
761 
762  input = gfs;
763 
764  /* Processing when we've got a new input frame */
766 
767  if (active_output_data.output_name == 0) {
768  /* Don't override explicit output names.
769  This code works 'cause output_name is reset to 0 after each output. */
770  if (mode == BATCHING)
772  else if (mode == EXPLODING) {
773  /* Explode into current directory. */
774  const char *explode_name = (input_name ? input_name : "#stdin#");
775  const char *slash = strrchr(explode_name, PATHNAME_SEPARATOR);
776  if (slash)
777  active_output_data.output_name = slash + 1;
778  else
779  active_output_data.output_name = explode_name;
780  }
781  }
782 
783  /* This code rather sucks. Here's the problem: Since we consider options
784  strictly sequentially, one at a time, we can't tell the difference
785  between these:
786 
787  --name=X g.gif h.gif // name on g.gif #0
788  --name=X g.gif #2 h.gif // name on g.gif #2
789  g.gif --name=X #2 h.gif // name on g.gif #2
790  g.gif --name=X h.gif // name on h.gif #0 !!!
791 
792  Here's the solution. Mark when we CHANGE an option. After processing
793  an input GIF, mark all the options as 'unchanged' -- but leave the
794  VALUES as is. Then when we read the next frame, CLEAR the unchanged
795  options. So it's like so: (* means changed, . means not.)
796 
797  [-.] --name=X [X*] g.gif [X.] #2 [-.] h.gif == name on g.gif #2
798  [-.] g.gif [-.] --name=X [X*] #2 [-.] h.gif == name on g.gif #2
799  [-.] --name=X [X*] g.gif [X.|-.] h.gif == name on g.gif #0
800  [-.] g.gif [-.] --name=X [X*] h.gif == name on h.gif #0 */
801 
802  /* Clear old options from the last input stream */
803  if (!CHANGED(saved_next_frame, CH_NAME))
804  def_frame.name = 0;
805  if (!CHANGED(saved_next_frame, CH_COMMENT))
806  def_frame.comment = 0;
807  if (!CHANGED(saved_next_frame, CH_EXTENSION))
808  def_frame.extensions = 0;
810 
811  old_def_frame = def_frame;
814  for (i = 0; i < gfs->nimages; i++)
815  add_frame(frames, gfs, gfs->images[i]);
816  def_frame = old_def_frame;
817 
818  if (unoptimizing)
820  static int context = 0;
821  if (!context) {
822  lwarning(name, "GIF too complex to unoptimize\n"
823  " (The reason was local color tables or complex transparency.\n"
824  " Try running the GIF through %<gifsicle --colors=255%> first.)");
825  context = 1;
826  } else
827  lwarning(name, "GIF too complex to unoptimize");
828  }
829 
831  gfs->refcount++;
832 
833  /* Read more files. */
834  free(component_namebuf);
836  goto retry_file;
837  close_giffile(f, 0);
838  return;
839 
840  error:
841  free(component_namebuf);
842  close_giffile(f, 1);
843 }
844 
845 void
846 input_done(void)
847 {
848  if (!input) return;
849 
850  if (verbosing) verbose_close('>');
851 
853  input = 0;
854 
855  if (mode == DELETING)
857  if (mode == BATCHING || mode == EXPLODING)
858  output_frames();
859 }
860 
861 
862 /*****
863  * colormap stuff
864  **/
865 
866 static void
867 set_new_fixed_colormap(const char *name)
868 {
869  int i;
870  if (name && strcmp(name, "web") == 0) {
871  Gif_Colormap *cm = Gif_NewFullColormap(216, 256);
872  Gif_Color *col = cm->col;
873  for (i = 0; i < 216; i++) {
874  col[i].gfc_red = (i / 36) * 0x33;
875  col[i].gfc_green = ((i / 6) % 6) * 0x33;
876  col[i].gfc_blue = (i % 6) * 0x33;
877  }
879 
880  } else if (name && (strcmp(name, "gray") == 0
881  || strcmp(name, "grey") == 0)) {
882  Gif_Colormap *cm = Gif_NewFullColormap(256, 256);
883  Gif_Color *col = cm->col;
884  for (i = 0; i < 256; i++)
885  col[i].gfc_red = col[i].gfc_green = col[i].gfc_blue = i;
887 
888  } else if (name && strcmp(name, "bw") == 0) {
889  Gif_Colormap *cm = Gif_NewFullColormap(2, 256);
890  cm->col[0].gfc_red = cm->col[0].gfc_green = cm->col[0].gfc_blue = 0;
891  cm->col[1].gfc_red = cm->col[1].gfc_green = cm->col[1].gfc_blue = 255;
893 
894  } else
896 }
897 
898 static void
900 {
904 
908 
910  kchist kch;
911  Gif_Colormap* (*adapt_func)(kchist*, Gt_OutputData*);
912  Gif_Colormap *new_cm;
913 
914  /* set up the histogram */
915  {
916  uint32_t ntransp;
917  int i, any_locals = 0;
918  for (i = 0; i < gfs->nimages; i++)
919  if (gfs->images[i]->local)
920  any_locals = 1;
921  kchist_make(&kch, gfs, &ntransp);
923  && !any_locals
925  warning(1, "trivial adaptive palette (only %d colors in source)", kch.n);
926  kchist_cleanup(&kch);
927  return;
928  }
930  }
931 
933  case COLORMAP_DIVERSITY:
934  adapt_func = &colormap_flat_diversity;
935  break;
937  adapt_func = &colormap_blend_diversity;
938  break;
939  case COLORMAP_MEDIAN_CUT:
940  adapt_func = &colormap_median_cut;
941  break;
942  default:
943  fatal_error("can't happen");
944  }
945 
946  new_cm = (*adapt_func)(&kch, &active_output_data);
947  colormap_stream(gfs, new_cm, &active_output_data);
948 
949  Gif_DeleteColormap(new_cm);
950  kchist_cleanup(&kch);
951  }
952 }
953 
954 
955 /*****
956  * output GIF images
957  **/
958 
959 static void
960 write_stream(const char *output_name, Gif_Stream *gfs)
961 {
962  FILE *f;
963 
964  if (output_name)
965  f = fopen(output_name, "wb");
966  else {
967 #ifndef OUTPUT_GIF_TO_TERMINAL
968  if (isatty(fileno(stdout))) {
969  lerror("<stdout>", "Is a terminal: try `-o OUTPUTFILE`");
970  return;
971  }
972 #endif
973 #if defined(_MSDOS) || defined(_WIN32)
974  _setmode(_fileno(stdout), _O_BINARY);
975 #elif defined(__DJGPP__)
976  setmode(fileno(stdout), O_BINARY);
977 #elif defined(__EMX__)
978  _fsetmode(stdout, "b");
979 #endif
980  f = stdout;
981  output_name = "<stdout>";
982  }
983 
984  if (f) {
986  fclose(f);
988  } else
989  lerror(output_name, "%s", strerror(errno));
990 }
991 
992 static void
993 merge_and_write_frames(const char *outfile, int f1, int f2)
994 {
995  Gif_Stream *out;
996  int compress_immediately;
997  int colormap_change;
998  int huge_stream;
999  assert(!nested_mode);
1000  if (verbosing)
1001  verbose_open('[', outfile ? outfile : "#stdout#");
1003 
1004  colormap_change = active_output_data.colormap_size > 0
1006  warn_local_colormaps = !colormap_change;
1007 
1010  || colormap_change))
1011  compress_immediately = 1;
1012  else
1013  compress_immediately = active_output_data.conserve_memory;
1014 
1016  compress_immediately, &huge_stream);
1017 
1018  if (out) {
1019  double w, h;
1023  } else {
1026  }
1031  if (colormap_change)
1032  do_colormap_change(out);
1033  if (output_transforms)
1037  write_stream(outfile, out);
1038  Gif_DeleteStream(out);
1039  }
1040 
1041  if (verbosing)
1042  verbose_close(']');
1045 
1046 static void
1047 output_information(const char *outfile)
1048 {
1049  FILE *f;
1050  int i, j;
1051  Gt_Frame *fr;
1052  Gif_Stream *gfs;
1053 
1054  if (infoing == 2)
1055  f = stderr;
1056  else if (outfile == 0)
1057  f = stdout;
1058  else {
1059  f = fopen(outfile, "w");
1060  if (!f) {
1061  lerror(outfile, "%s", strerror(errno));
1062  return;
1063  }
1064  }
1065 
1066  for (i = 0; i < frames->count; i++)
1067  FRAME(frames, i).stream->user_flags = 97;
1068 
1069  for (i = 0; i < frames->count; i++)
1070  if (FRAME(frames, i).stream->user_flags == 97) {
1071  fr = &FRAME(frames, i);
1072  gfs = fr->stream;
1073  gfs->user_flags = 0;
1074  stream_info(f, gfs, fr->input_filename, fr->info_flags);
1075  for (j = i; j < frames->count; j++)
1076  if (FRAME(frames, j).stream == gfs) {
1077  fr = &FRAME(frames, j);
1078  image_info(f, gfs, fr->image, fr->info_flags);
1079  }
1080  }
1081 
1082  if (f != stderr && f != stdout)
1083  fclose(f);
1085 
1086 void
1087 output_frames(void)
1088 {
1089  /* Use the current output name, not the stored output name.
1090  This supports 'gifsicle a.gif -o xxx'.
1091  It's not like any other option, but seems right: it fits the natural
1092  order -- input, then output. */
1093  int i;
1094  const char *outfile = active_output_data.output_name;
1096 
1097  /* Output information only now. */
1098  if (infoing)
1099  output_information(outfile);
1100 
1101  if (infoing != 1 && frames->count > 0)
1102  switch (mode) {
1103 
1104  case MERGING:
1105  case BATCHING:
1106  case INFOING:
1107  merge_and_write_frames(outfile, 0, -1);
1108  break;
1109 
1110  case EXPLODING: {
1111  /* Use the current output name for consistency, even though that means
1112  we can't explode different frames to different names. Not a big deal
1113  anyway; they can always repeat the gif on the cmd line. */
1114  int max_nimages = 0;
1115  for (i = 0; i < frames->count; i++) {
1116  Gt_Frame *fr = &FRAME(frames, i);
1117  if (fr->stream->nimages > max_nimages)
1118  max_nimages = fr->stream->nimages;
1119  }
1120 
1121  if (!outfile) /* Watch out! */
1122  outfile = "-";
1123 
1124  for (i = 0; i < frames->count; i++) {
1125  Gt_Frame *fr = &FRAME(frames, i);
1126  int imagenumber = Gif_ImageNumber(fr->stream, fr->image);
1127  char *explodename;
1128 
1129  const char *imagename = 0;
1130  if (fr->explode_by_name)
1131  imagename = fr->name ? fr->name : fr->image->identifier;
1132 
1133  explodename = explode_filename(outfile, imagenumber, imagename,
1134  max_nimages);
1135  merge_and_write_frames(explodename, i, i);
1136  }
1137  break;
1138  }
1139 
1140  case INSERTING:
1141  /* do nothing */
1142  break;
1143 
1144  }
1145 
1146  active_next_output = 0;
1147  clear_frameset(frames, 0);
1148 
1149  /* cropping: clear the 'crop->ready' information, which depended on the last
1150  input image. */
1151  if (def_frame.crop)
1152  def_frame.crop->ready = 0;
1153 }
1154 
1155 
1156 /*****
1157  * parsing arguments
1158  **/
1159 
1160 int
1161 frame_argument(Clp_Parser *clp, const char *arg)
1162 {
1163  /* Returns 0 iff you should try a file named 'arg'. */
1164  int val = parse_frame_spec(clp, arg, -1, 0);
1165  if (val == -97)
1166  return 0;
1167  else if (val > 0) {
1168  int i, delta = (frame_spec_1 <= frame_spec_2 ? 1 : -1);
1169  for (i = frame_spec_1; i != frame_spec_2 + delta; i += delta)
1170  show_frame(i, frame_spec_name != 0);
1171  if (next_output)
1173  return 1;
1174  } else
1175  return 1;
1176 }
1177 
1178 static int
1179 handle_extension(Clp_Parser *clp, int is_app)
1180 {
1181  Gif_Extension *gfex;
1182  const char *extension_type = clp->vstr;
1183  const char *extension_body = Clp_Shift(clp, 1);
1184  if (!extension_body) {
1185  Clp_OptionError(clp, "%O requires two arguments");
1186  return 0;
1187  }
1188 
1190  if (is_app)
1191  gfex = Gif_NewExtension(255, extension_type, 11);
1192  else if (!isdigit(extension_type[0]) && extension_type[1] == 0)
1193  gfex = Gif_NewExtension(extension_type[0], 0, 0);
1194  else {
1195  long l = strtol(extension_type, (char **)&extension_type, 0);
1196  if (*extension_type != 0 || l < 0 || l >= 256)
1197  fatal_error("bad extension type: must be a number between 0 and 255");
1198  gfex = Gif_NewExtension(l, 0, 0);
1199  }
1200 
1201  gfex->data = (uint8_t *)extension_body;
1202  gfex->length = strlen(extension_body);
1203  gfex->next = def_frame.extensions;
1204  def_frame.extensions = gfex;
1205 
1206  return 1;
1207 }
1208 
1209 
1210 /*****
1211  * option processing
1212  **/
1213 
1214 static void
1216 {
1217  /* frame defaults */
1218  def_frame.stream = 0;
1219  def_frame.image = 0;
1220  def_frame.use = 1;
1221 
1222  def_frame.name = 0;
1223  def_frame.no_name = 0;
1224  def_frame.comment = 0;
1225  def_frame.no_comments = 0;
1226 
1227  def_frame.interlacing = -1;
1229  def_frame.left = -1;
1230  def_frame.top = -1;
1232 
1233  def_frame.crop = 0;
1234 
1235  def_frame.delay = -1;
1236  def_frame.disposal = -1;
1237 
1238  def_frame.nest = 0;
1240 
1243  def_frame.extensions = 0;
1244 
1247  def_frame.total_crop = 0;
1248 
1249  /* output defaults */
1251 
1256 
1261  def_output_data.dither_name = "none";
1264 
1269 
1273 }
1274 
1275 static void
1277 {
1278  int recent = next_output;
1280 #define COMBINE_ONE_OUTPUT_OPTION(value, field) \
1281  if (CHANGED(recent, value)) { \
1282  MARK_CH(output, value); \
1283  active_output_data.field = def_output_data.field; \
1284  }
1285 
1286  COMBINE_ONE_OUTPUT_OPTION(CH_OUTPUT, output_name);
1287 
1288  if (CHANGED(recent, CH_LOGICAL_SCREEN)) {
1289  MARK_CH(output, CH_LOGICAL_SCREEN);
1292  }
1295 
1297  COMBINE_ONE_OUTPUT_OPTION(CH_COLORMAP, colormap_size);
1298  COMBINE_ONE_OUTPUT_OPTION(CH_COLORMAP_METHOD, colormap_algorithm);
1299  if (CHANGED(recent, CH_USE_COLORMAP)) {
1300  MARK_CH(output, CH_USE_COLORMAP);
1305  }
1306  if (CHANGED(recent, CH_DITHER)) {
1307  MARK_CH(output, CH_DITHER);
1310  }
1311  if (CHANGED(recent, CH_GAMMA)) {
1312  MARK_CH(output, CH_GAMMA);
1315  }
1316 
1317  if (CHANGED(recent, CH_RESIZE)) {
1318  MARK_CH(output, CH_RESIZE);
1325  }
1326 
1327  if (CHANGED(recent, CH_RESIZE_METHOD)) {
1328  MARK_CH(output, CH_RESIZE_METHOD);
1330  }
1331 
1332  if (CHANGED(recent, CH_SCALE_COLORS)) {
1333  MARK_CH(output, CH_SCALE_COLORS);
1335  }
1336 
1337  COMBINE_ONE_OUTPUT_OPTION(CH_MEMORY, conserve_memory);
1338 
1341 
1343  next_output = 0;
1344 }
1345 
1346 static void
1347 redundant_option_warning(const char* opttype)
1348 {
1349  static int context = 0;
1350  if (!context) {
1351  warning(0, "redundant %s option\n"
1352  " (The %s option was overridden by another %s option\n"
1353  " before it had any effect.)", opttype, opttype, opttype);
1354  context = 1;
1355  } else
1356  warning(0, "redundant %s option", opttype);
1357 }
1358 
1359 static void
1360 print_useless_options(const char *type_name, int value, const char *names[])
1361 {
1362  int explanation_printed = 0;
1363  int i;
1364  if (!value) return;
1365  for (i = 0; i < 32; i++)
1366  if (CHANGED(value, i)) {
1367  if (!explanation_printed) {
1368  warning(0, "useless %s-related %s option\n"
1369  " (It didn%,t affect any %s.)", names[i], type_name, type_name);
1370  explanation_printed = 1;
1371  } else
1372  warning(0, "useless %s-related %s option", names[i], type_name);
1373  }
1374 }
1375 
1376 static Gt_Crop *
1377 copy_crop(Gt_Crop *oc)
1378 {
1379  Gt_Crop *nc = Gif_New(Gt_Crop);
1380  /* Memory leak on crops, but this just is NOT a problem. */
1381  if (oc)
1382  *nc = *oc;
1383  else
1384  memset(nc, 0, sizeof(Gt_Crop));
1385  nc->ready = 0;
1386  return nc;
1387 }
1388 
1389 static void
1390 parse_resize_geometry_opt(Gt_OutputData* odata, const char* str, Clp_Parser* clp)
1391 {
1392  double x, y;
1393  int flags = GT_RESIZE_FIT, scale = 0;
1394 
1395  if (*str == '_' || *str == 'x') {
1396  x = 0;
1397  str += (*str == '_');
1398  } else if (isdigit((unsigned char) *str))
1399  x = strtol(str, (char**) &str, 10);
1400  else
1401  goto error;
1402 
1403  if (*str == 'x') {
1404  ++str;
1405  if (*str == '_' || !isdigit((unsigned char) *str)) {
1406  y = 0;
1407  str += (*str == '_');
1408  } else
1409  y = strtol(str, (char**) &str, 10);
1410  } else
1411  y = x;
1412 
1413  for (; *str != 0; ++str)
1414  if (*str == '%')
1415  scale = 1;
1416  else if (*str == '!')
1417  flags = 0;
1418  else if (*str == '^')
1420  else if (*str == '<')
1421  flags |= GT_RESIZE_FIT | GT_RESIZE_FIT_UP;
1422  else if (*str == '>')
1423  flags |= GT_RESIZE_FIT | GT_RESIZE_FIT_DOWN;
1424  else
1425  goto error;
1426 
1427  if (scale) {
1428  odata->scaling = GT_SCALING_SCALE;
1429  odata->scale_x = x / 100.0;
1430  odata->scale_y = y / 100.0;
1431  } else {
1432  odata->scaling = GT_SCALING_RESIZE;
1433  odata->resize_width = x;
1434  odata->resize_height = y;
1435  }
1436  odata->resize_flags = flags;
1437  return;
1438 
1439 error:
1440  Clp_OptionError(clp, "argument to %O must be a valid geometry specification");
1441 }
1442 
1443 
1445 /*****
1446  * main
1447  **/
1448 
1449 int
1450 main(int argc, char *argv[])
1451 {
1452  /* Check SIZEOF constants (useful for Windows). If these assertions fail,
1453  you've used the wrong Makefile. You should've used Makefile.w32 for
1454  32-bit Windows and Makefile.w64 for 64-bit Windows. */
1455  static_assert(sizeof(unsigned int) == SIZEOF_UNSIGNED_INT, "unsigned int has the wrong size.");
1456  static_assert(sizeof(unsigned long) == SIZEOF_UNSIGNED_LONG, "unsigned long has the wrong size.");
1457  static_assert(sizeof(void*) == SIZEOF_VOID_P, "void* has the wrong size.");
1458 
1459  clp = Clp_NewParser(argc, (const char * const *)argv, sizeof(options) / sizeof(options[0]), options);
1460 
1463  "infinite", 0, "forever", 0,
1464  (const char*) 0);
1467  "none", GIF_DISPOSAL_NONE,
1468  "asis", GIF_DISPOSAL_ASIS,
1469  "background", GIF_DISPOSAL_BACKGROUND,
1471  "previous", GIF_DISPOSAL_PREVIOUS,
1472  (const char*) 0);
1474  (clp, COLORMAP_ALG_TYPE, 0,
1475  "diversity", COLORMAP_DIVERSITY,
1476  "blend-diversity", COLORMAP_BLEND_DIVERSITY,
1477  "median-cut", COLORMAP_MEDIAN_CUT,
1478  (const char*) 0);
1481  "keep-empty", GT_OPT_KEEPEMPTY + 1,
1482  "no-keep-empty", GT_OPT_KEEPEMPTY,
1483  "drop-empty", GT_OPT_KEEPEMPTY,
1484  "no-drop-empty", GT_OPT_KEEPEMPTY + 1,
1485  (const char*) 0);
1487  (clp, RESIZE_METHOD_TYPE, 0,
1488  "point", SCALE_METHOD_POINT,
1489  "sample", SCALE_METHOD_POINT,
1490  "mix", SCALE_METHOD_MIX,
1491  "box", SCALE_METHOD_BOX,
1492  "catrom", SCALE_METHOD_CATROM,
1493  "lanczos", SCALE_METHOD_LANCZOS3,
1494  "lanczos2", SCALE_METHOD_LANCZOS2,
1495  "lanczos3", SCALE_METHOD_LANCZOS3,
1496  "mitchell", SCALE_METHOD_MITCHELL,
1497  "fast", SCALE_METHOD_POINT,
1498  "good", SCALE_METHOD_MIX,
1499  (const char*) 0);
1509 
1511 
1512  frames = new_frameset(16);
1516 
1517 #if ENABLE_THREADS
1518  pthread_mutex_init(&kd3_sort_lock, 0);
1519 #endif
1520 
1521  /* Yep, I'm an idiot.
1522  GIF dimensions are unsigned 16-bit integers. I assume that these
1523  numbers will fit in an 'int'. This assertion tests that assumption.
1524  Really I should go through & change everything over, but it doesn't
1525  seem worth my time. */
1526  {
1527  uint16_t m = 0xFFFFU;
1528  int i = m;
1529  assert(i > 0 && "configuration/lameness failure! bug the author!");
1530  }
1531 
1532  while (1) {
1533  int opt = Clp_Next(clp);
1534  switch (opt) {
1535 
1536  /* MODE OPTIONS */
1537 
1538  case 'b':
1539  set_mode(BATCHING);
1540  break;
1541 
1542  case 'm':
1543  set_mode(MERGING);
1544  break;
1545 
1546  case 'e':
1549  break;
1550 
1551  case 'E':
1554  break;
1555 
1556  /* INFORMATION OPTIONS */
1557 
1558  case INFO_OPT:
1559  if (clp->negated)
1560  infoing = 0;
1561  else
1562  /* switch between infoing == 1 (suppress regular output) and 2 (don't
1563  suppress) */
1564  infoing = (infoing == 1 ? 2 : 1);
1565  break;
1566 
1567  case COLOR_INFO_OPT:
1568  if (clp->negated)
1570  else {
1572  if (!infoing)
1573  infoing = 1;
1574  }
1575  break;
1576 
1577  case EXTENSION_INFO_OPT:
1578  if (clp->negated)
1580  else {
1582  if (!infoing)
1583  infoing = 1;
1584  }
1585  break;
1586 
1587  case SIZE_INFO_OPT:
1588  if (clp->negated)
1590  else {
1592  if (!infoing)
1593  infoing = 1;
1594  }
1595  break;
1596 
1597  case VERBOSE_OPT:
1598  verbosing = clp->negated ? 0 : 1;
1599  break;
1600 
1601  /* FRAME CHANGE OPTIONS */
1602 
1603  case DELETE_OPT:
1604  case REPLACE_OPT:
1605  case INSERT_OPT:
1606  case APPEND_OPT:
1608  set_frame_change(opt);
1609  break;
1610 
1611  case ALTER_DONE_OPT:
1613  break;
1614 
1615  /* IMAGE OPTIONS */
1616 
1617  case NAME_OPT:
1618  if (clp->negated) goto no_names;
1619  MARK_CH(frame, CH_NAME);
1620  def_frame.name = clp->vstr;
1621  break;
1622 
1623  no_names:
1624  case NO_NAME_OPT:
1625  MARK_CH(frame, CH_NAME);
1626  def_frame.no_name = 1;
1627  def_frame.name = 0;
1628  break;
1629 
1630  case SAME_NAME_OPT:
1631  def_frame.no_name = 0;
1632  def_frame.name = 0;
1633  break;
1634 
1635  case COMMENT_OPT:
1636  if (clp->negated) goto no_comments;
1637  MARK_CH(frame, CH_COMMENT);
1640  break;
1641 
1642  no_comments:
1643  case NO_COMMENTS_OPT:
1645  def_frame.comment = 0;
1646  def_frame.no_comments = 1;
1647  break;
1648 
1649  case SAME_COMMENTS_OPT:
1650  def_frame.no_comments = 0;
1651  break;
1652 
1653  case 'i':
1654  MARK_CH(frame, CH_INTERLACE);
1655  def_frame.interlacing = clp->negated ? 0 : 1;
1656  break;
1657 
1658  case SAME_INTERLACE_OPT:
1659  def_frame.interlacing = -1;
1660  break;
1661 
1662  case POSITION_OPT:
1663  MARK_CH(frame, CH_POSITION);
1664  def_frame.left = clp->negated ? 0 : position_x;
1665  def_frame.top = clp->negated ? 0 : position_y;
1666  break;
1667 
1668  case SAME_POSITION_OPT:
1669  def_frame.left = -1;
1670  def_frame.top = -1;
1671  break;
1672 
1673  case 't':
1674  MARK_CH(frame, CH_TRANSPARENT);
1675  if (clp->negated)
1677  else {
1680  }
1681  break;
1682 
1683  case SAME_TRANSPARENT_OPT:
1685  break;
1686 
1687  case BACKGROUND_OPT:
1688  MARK_CH(output, CH_BACKGROUND);
1689  if (clp->negated) {
1692  } else {
1695  }
1696  break;
1697 
1698  case SAME_BACKGROUND_OPT:
1699  MARK_CH(output, CH_BACKGROUND);
1701  break;
1702 
1703  case LOGICAL_SCREEN_OPT:
1704  MARK_CH(output, CH_LOGICAL_SCREEN);
1705  if (clp->negated)
1707  else {
1710  }
1711  break;
1712 
1714  MARK_CH(output, CH_LOGICAL_SCREEN);
1716  break;
1717 
1718  case CROP_OPT:
1719  if (clp->negated) goto no_crop;
1720  MARK_CH(frame, CH_CROP);
1721  {
1722  Gt_Crop *crop = copy_crop(def_frame.crop);
1723  /* Memory leak on crops, but this just is NOT a problem. */
1724  crop->spec_x = position_x;
1725  crop->spec_y = position_y;
1726  crop->spec_w = dimensions_x;
1727  crop->spec_h = dimensions_y;
1728  def_frame.crop = crop;
1729  }
1730  break;
1731 
1732  no_crop:
1733  case SAME_CROP_OPT:
1734  def_frame.crop = 0;
1735  break;
1736 
1737  case CROP_TRANSPARENCY_OPT:
1738  if (clp->negated)
1739  goto no_crop_transparency;
1742  break;
1743 
1744  no_crop_transparency:
1748  }
1749  break;
1750 
1751  /* extensions options */
1752 
1753  case NO_EXTENSIONS_OPT:
1755  break;
1756 
1757  case NO_APP_EXTENSIONS_OPT:
1759  break;
1760 
1761  case SAME_EXTENSIONS_OPT:
1763  break;
1764 
1767  break;
1768 
1769  case EXTENSION_OPT:
1770  if (!handle_extension(clp, 0))
1771  goto bad_option;
1772  break;
1773 
1774  case APP_EXTENSION_OPT:
1775  if (!handle_extension(clp, 1))
1776  goto bad_option;
1777  break;
1778 
1779  /* IMAGE DATA OPTIONS */
1780 
1781  case FLIP_HORIZ_OPT:
1782  MARK_CH(frame, CH_FLIP);
1784  break;
1785 
1786  case FLIP_VERT_OPT:
1787  MARK_CH(frame, CH_FLIP);
1789  break;
1790 
1791  case NO_FLIP_OPT:
1793  break;
1794 
1795  case NO_ROTATE_OPT:
1796  def_frame.rotation = 0;
1797  break;
1798 
1799  case ROTATE_90_OPT:
1800  MARK_CH(frame, CH_ROTATE);
1801  def_frame.rotation = 1;
1802  break;
1803 
1804  case ROTATE_180_OPT:
1805  MARK_CH(frame, CH_ROTATE);
1806  def_frame.rotation = 2;
1807  break;
1808 
1809  case ROTATE_270_OPT:
1810  MARK_CH(frame, CH_ROTATE);
1811  def_frame.rotation = 3;
1812  break;
1813 
1814  /* ANIMATION OPTIONS */
1815 
1816  case 'd':
1817  MARK_CH(frame, CH_DELAY);
1818  def_frame.delay = clp->negated ? 0 : clp->val.i;
1819  break;
1820 
1821  case SAME_DELAY_OPT:
1822  def_frame.delay = -1;
1823  break;
1824 
1825  case DISPOSAL_OPT:
1826  MARK_CH(frame, CH_DISPOSAL);
1827  if (clp->negated)
1829  else if (clp->val.i < 0 || clp->val.i > 7)
1830  error(0, "disposal must be between 0 and 7");
1831  else
1832  def_frame.disposal = clp->val.i;
1833  break;
1834 
1835  case SAME_DISPOSAL_OPT:
1836  def_frame.disposal = -1;
1837  break;
1838 
1839  case 'l':
1840  MARK_CH(output, CH_LOOPCOUNT);
1841  if (clp->negated)
1843  else
1845  break;
1846 
1847  case SAME_LOOPCOUNT_OPT:
1848  MARK_CH(output, CH_LOOPCOUNT);
1850  break;
1851 
1852  case OPTIMIZE_OPT: {
1853  int o;
1854  UNCHECKED_MARK_CH(output, CH_OPTIMIZE);
1855  if (clp->negated || (clp->have_val && clp->val.i < 0))
1856  o = 0;
1857  else
1858  o = (clp->have_val ? clp->val.i : 1);
1859  if (o > GT_OPT_MASK && (o & 1))
1860  def_output_data.optimizing |= o - 1;
1861  else if (o > GT_OPT_MASK)
1863  else
1865  break;
1866  }
1867 
1868  case UNOPTIMIZE_OPT:
1870  unoptimizing = clp->negated ? 0 : 1;
1871  break;
1872 
1873  case THREADS_OPT:
1874  if (clp->negated)
1875  thread_count = 0;
1876  else if (clp->have_val)
1877  thread_count = clp->val.i;
1878  else
1880  break;
1881 
1882  /* WHOLE-GIF OPTIONS */
1883 
1884  case CAREFUL_OPT: {
1885  if (clp->negated)
1886  gif_write_info.flags = 0;
1887  else
1889  break;
1890  }
1891 
1892  case CHANGE_COLOR_OPT: {
1893  next_input |= 1 << CH_CHANGE_COLOR;
1894  if (clp->negated)
1897  else if (parsed_color2.haspixel)
1898  error(0, "COLOR2 must be in RGB format in %<--change-color COLOR1 COLOR2%>");
1899  else
1902  break;
1903  }
1904 
1905  case COLOR_TRANSFORM_OPT:
1907  if (clp->negated)
1910  else
1913  break;
1914 
1915  case COLORMAP_OPT:
1916  MARK_CH(output, CH_COLORMAP);
1917  if (clp->negated)
1919  else {
1922  || def_output_data.colormap_size > 256) {
1923  Clp_OptionError(clp, "argument to %O must be between 2 and 256");
1925  }
1926  }
1927  break;
1928 
1929  case GRAY_OPT:
1930  MARK_CH(output, CH_USE_COLORMAP);
1932  set_new_fixed_colormap("gray");
1933  break;
1934 
1935  case USE_COLORMAP_OPT:
1936  MARK_CH(output, CH_USE_COLORMAP);
1938  if (clp->negated)
1940  else
1942  break;
1943 
1945  MARK_CH(output, CH_COLORMAP_METHOD);
1947  break;
1948 
1949  case DITHER_OPT: {
1950  const char* name;
1951  if (clp->negated)
1952  name = "none";
1953  else if (!clp->have_val)
1954  name = "default";
1955  else
1956  name = clp->val.s;
1957  if (strcmp(name, "posterize") == 0)
1958  name = "none";
1959  if (strcmp(name, def_output_data.dither_name) != 0
1960  && (strcmp(name, "none") == 0
1961  || strcmp(def_output_data.dither_name, "default") != 0))
1962  MARK_CH(output, CH_DITHER);
1963  UNCHECKED_MARK_CH(output, CH_DITHER);
1965  Clp_OptionError(clp, "%<%s%> is not a valid dither", name);
1967  break;
1968  }
1969 
1970  case GAMMA_OPT: {
1971 #if HAVE_POW
1972  char* ends;
1973  MARK_CH(output, CH_GAMMA);
1974  if (clp->negated) {
1977  } else if (strcmp(clp->val.s, "sRGB") == 0
1978  || strcmp(clp->val.s, "srgb") == 0)
1980  else {
1981  double gamma = strtod(clp->val.s, &ends);
1982  if (*clp->val.s && !*ends && !isspace((unsigned char) *clp->val.s)) {
1985  } else
1986  Clp_OptionError(clp, "%O should be a number or %<srgb%>");
1987  }
1988 #else
1989  Clp_OptionError(clp, "this version of Gifsicle does not support %O");
1990 #endif
1991  break;
1992  }
1993 
1994  case RESIZE_OPT:
1995  case RESIZE_FIT_OPT:
1996  case RESIZE_TOUCH_OPT:
1997  MARK_CH(output, CH_RESIZE);
1998  if (clp->negated)
2000  else if (dimensions_x <= 0 && dimensions_y <= 0) {
2001  error(0, "one of W and H must be positive in %<%s WxH%>", Clp_CurOptionName(clp));
2003  } else {
2008  if (opt != RESIZE_OPT)
2010  if (opt == RESIZE_FIT_OPT)
2012  }
2013  break;
2014 
2015  case RESIZE_WIDTH_OPT:
2016  case RESIZE_HEIGHT_OPT:
2017  case RESIZE_FIT_WIDTH_OPT:
2018  case RESIZE_FIT_HEIGHT_OPT:
2021  MARK_CH(output, CH_RESIZE);
2022  if (clp->negated)
2024  else if (clp->val.u == 0) {
2025  error(0, "%s argument must be positive", Clp_CurOptionName(clp));
2027  } else {
2028  unsigned dimen[2] = {0, 0};
2029  dimen[(opt == RESIZE_HEIGHT_OPT || opt == RESIZE_FIT_HEIGHT_OPT)] = clp->val.u;
2031  def_output_data.resize_width = dimen[0];
2032  def_output_data.resize_height = dimen[1];
2034  if (opt != RESIZE_WIDTH_OPT && opt != RESIZE_HEIGHT_OPT)
2036  if (opt == RESIZE_FIT_WIDTH_OPT || opt == RESIZE_FIT_HEIGHT_OPT)
2038  }
2039  break;
2040 
2041  case SCALE_OPT:
2042  MARK_CH(output, CH_RESIZE);
2043  if (clp->negated)
2045  else if (parsed_scale_factor_x <= 0 || parsed_scale_factor_y <= 0) {
2046  error(0, "%s X and Y factors must be positive", Clp_CurOptionName(clp));
2048  } else {
2053  }
2054  break;
2055 
2056  case RESIZE_GEOMETRY_OPT:
2057  MARK_CH(output, CH_RESIZE);
2058  if (clp->negated)
2060  else
2062  break;
2063 
2064  case RESIZE_METHOD_OPT:
2065  MARK_CH(output, CH_RESIZE_METHOD);
2067  break;
2068 
2069  case RESIZE_COLORS_OPT:
2070  MARK_CH(output, CH_SCALE_COLORS);
2072  if (def_output_data.scale_colors > 256) {
2073  error(0, "%s can be at most 256", Clp_CurOptionName(clp));
2075  }
2076  break;
2077 
2078  case LOSSY_OPT:
2079  if (clp->have_val)
2081  else
2082  gif_write_info.loss = 20;
2083  break;
2084 
2085  /* RANDOM OPTIONS */
2086 
2087  case NO_WARNINGS_OPT:
2088  no_warnings = !clp->negated;
2089  break;
2090 
2091  case WARNINGS_OPT:
2092  no_warnings = clp->negated;
2093  break;
2094 
2095  case IGNORE_ERRORS_OPT:
2097  break;
2098 
2099  case CONSERVE_MEMORY_OPT:
2100  MARK_CH(output, CH_MEMORY);
2102  break;
2103 
2104  case MULTIFILE_OPT:
2105  if (clp->negated)
2107  else {
2109  nextfile = 0;
2110  }
2111  break;
2112 
2113  case NEXTFILE_OPT:
2114  if (clp->negated)
2116  else {
2118  nextfile = 1;
2119  }
2120  break;
2121 
2122  case VERSION_OPT:
2123 #ifdef GIF_UNGIF
2124  printf("LCDF Gifsicle %s (ungif)\n", VERSION);
2125 #else
2126  printf("LCDF Gifsicle %s\n", VERSION);
2127 #endif
2128  printf("Copyright (C) 1997-2019 Eddie Kohler\n\
2129 This is free software; see the source for copying conditions.\n\
2130 There is NO warranty, not even for merchantability or fitness for a\n\
2131 particular purpose.\n");
2132  exit(EXIT_OK);
2133  break;
2134 
2135  case HELP_OPT:
2136  usage();
2137  exit(EXIT_OK);
2138  break;
2139 
2140  case OUTPUT_OPT:
2141  MARK_CH(output, CH_OUTPUT);
2142  if (strcmp(clp->vstr, "-") == 0)
2144  else
2146  break;
2147 
2148  /* NONOPTIONS */
2149 
2150  case Clp_NotOption:
2151  if (clp->vstr[0] != '#' || !frame_argument(clp, clp->vstr)) {
2152  input_done();
2153  input_stream(clp->vstr);
2154  }
2155  break;
2156 
2157  case Clp_Done:
2158  goto done;
2159 
2160  bad_option:
2161  case Clp_BadOption:
2162  short_usage();
2163  exit(EXIT_USER_ERR);
2164  break;
2165 
2166  default:
2167  break;
2168 
2169  }
2170  }
2171 
2172  done:
2173 
2174  if (next_output)
2176  if (!files_given)
2177  input_stream(0);
2178 
2180  input_done();
2181  if ((mode == MERGING && !error_count) || mode == INFOING)
2182  output_frames();
2183 
2184  verbose_endline();
2189  blank_frameset(frames, 0, 0, 1);
2191  return (error_count ? EXIT_ERR : EXIT_OK);
2192 }
RESIZE_OPT
#define RESIZE_OPT
Definition: gifsicle.c:178
LOOP_TYPE
#define LOOP_TYPE
Definition: gifsicle.c:206
parse_scale_factor
int parse_scale_factor(Clp_Parser *, const char *, int, void *)
Definition: support.c:685
kchist
Definition: kcolor.h:221
Gt_OutputData::background
Gif_Color background
Definition: gifsicle.h:114
parse_two_colors
int parse_two_colors(Clp_Parser *, const char *, int, void *)
Definition: support.c:841
IGNORE_ERRORS_OPT
#define IGNORE_ERRORS_OPT
Definition: gifsicle.c:198
nested_mode
int nested_mode
Definition: gifsicle.c:54
GIF_DISPOSAL_ASIS
#define GIF_DISPOSAL_ASIS
Definition: gif.h:118
Gt_Frame::extensions
Gif_Extension * extensions
Definition: gifsicle.h:59
NEXTFILE_OPT
#define NEXTFILE_OPT
Definition: gifsicle.c:187
set_new_fixed_colormap
static void set_new_fixed_colormap(const char *name)
Definition: gifsicle.c:865
BATCHING
#define BATCHING
Definition: gifsicle.h:323
Gt_ColorTransform
Definition: gifsicle.h:98
Gt_Frame::left
int left
Definition: gifsicle.h:44
Clp_OptionError
int Clp_OptionError(Clp_Parser *clp, const char *format,...)
Report a parser error.
Definition: clp.c:2261
Gif_Extension
Definition: gif.h:222
COLORMAP_MEDIAN_CUT
#define COLORMAP_MEDIAN_CUT
Definition: gifsicle.h:267
active_next_output
static int active_next_output
Definition: gifsicle.c:101
DISPOSAL_TYPE
#define DISPOSAL_TYPE
Definition: gifsicle.c:207
Gt_Frame::total_crop
unsigned total_crop
Definition: gifsicle.h:65
ROTATE_270_OPT
#define ROTATE_270_OPT
Definition: gifsicle.c:173
Gt_OutputData::screen_height
int screen_height
Definition: gifsicle.h:112
DELETE_OPT
#define DELETE_OPT
Definition: gifsicle.c:139
Gt_Crop::spec_y
int spec_y
Definition: gifsicle.h:84
Gif_GetImage
Gif_Image * Gif_GetImage(Gif_Stream *gfs, int i)
Definition: giffunc.c:675
CH_COLORMAP
#define CH_COLORMAP
Definition: gifsicle.c:107
dither_none
Definition: gifsicle.h:270
stored_files
static struct StoredFile * stored_files
Definition: gifsicle.c:606
SAME_COMMENTS_OPT
#define SAME_COMMENTS_OPT
Definition: gifsicle.c:147
GT_RESIZE_FIT
#define GT_RESIZE_FIT
Definition: gifsicle.h:149
Gif_NewFullColormap
Gif_Colormap * Gif_NewFullColormap(int count, int capacity)
Definition: giffunc.c:90
NO_FLIP_OPT
#define NO_FLIP_OPT
Definition: gifsicle.c:170
Gt_Frame::image
Gif_Image * image
Definition: gifsicle.h:34
DISPOSAL_OPT
#define DISPOSAL_OPT
Definition: gifsicle.c:128
input_done
void input_done(void)
Definition: gifsicle.c:845
Clp_AddType
int Clp_AddType(Clp_Parser *clp, int val_type, int flags, Clp_ValParseFunc parser, void *user_data)
Define a new value type for clp.
Definition: clp.c:1041
Gt_Frame::top
int top
Definition: gifsicle.h:45
Gif_InitCompressInfo
void Gif_InitCompressInfo(Gif_CompressInfo *gcinfo)
Definition: giffunc.c:821
short_usage
void short_usage(void)
Definition: gifdiff.c:402
kchist_make
void kchist_make(kchist *kch, Gif_Stream *gfs, uint32_t *ntransp)
Definition: quantize.c:279
parsed_color
Gif_Color parsed_color
Definition: support.c:548
CH_INTERLACE
#define CH_INTERLACE
Definition: gifsicle.c:72
Gif_Image::local
Gif_Colormap * local
Definition: gif.h:97
CAREFUL_OPT
#define CAREFUL_OPT
Definition: gifsicle.c:136
Gt_OutputData::scale_colors
int scale_colors
Definition: gifsicle.h:136
Gif_Color::gfc_red
uint8_t gfc_red
Definition: gif.h:173
Gt_Frameset::count
int count
Definition: gifsicle.h:74
RESIZE_HEIGHT_OPT
#define RESIZE_HEIGHT_OPT
Definition: gifsicle.c:183
dimensions_x
int dimensions_x
Definition: support.c:544
SAME_INTERLACE_OPT
#define SAME_INTERLACE_OPT
Definition: gifsicle.c:126
Gif_Colormap
Definition: gif.h:180
CH_NAME
#define CH_NAME
Definition: gifsicle.c:77
Gt_OutputData::loopcount
int loopcount
Definition: gifsicle.h:115
CH_LOOPCOUNT
#define CH_LOOPCOUNT
Definition: gifsicle.c:103
UNOPTIMIZE_OPT
#define UNOPTIMIZE_OPT
Definition: gifsicle.c:135
PATHNAME_SEPARATOR
#define PATHNAME_SEPARATOR
Definition: win32cfg.h:122
RESIZE_GEOMETRY_OPT
#define RESIZE_GEOMETRY_OPT
Definition: gifsicle.c:200
parse_frame_spec
int parse_frame_spec(Clp_Parser *, const char *, int, void *)
Definition: support.c:554
Gif_CompressInfo
Definition: gif.h:146
CONSERVE_MEMORY_OPT
#define CONSERVE_MEMORY_OPT
Definition: gifsicle.c:185
Clp_Negate
#define Clp_Negate
Option flag: option may be negated.
Definition: clp.h:139
output_option_types
static const char * output_option_types[]
Definition: gifsicle.c:118
append_color_transform
Gt_ColorTransform * append_color_transform(Gt_ColorTransform *list, color_transform_func, void *)
Definition: xform.c:37
mode
int mode
Definition: gifsicle.c:53
Clp_Shift
const char * Clp_Shift(Clp_Parser *clp, int allow_options)
Return the next argument from clp without option parsing.
Definition: clp.c:1983
gifread_error
static void gifread_error(Gif_Stream *gfs, Gif_Image *gfi, int is_error, const char *message)
Definition: gifsicle.c:526
OPTIMIZE_OPT
#define OPTIMIZE_OPT
Definition: gifsicle.c:137
Gt_Frame::rotation
unsigned rotation
Definition: gifsicle.h:66
StoredFile::name
char name[1]
Definition: gifsicle.c:603
NO_APP_EXTENSIONS_OPT
#define NO_APP_EXTENSIONS_OPT
Definition: gifsicle.c:196
Clp_ValStringNotOption
#define Clp_ValStringNotOption
Option value is a non-option string.
Definition: clp.h:62
CH_TRANSPARENT
#define CH_TRANSPARENT
Definition: gifsicle.c:75
LOSSY_OPT
#define LOSSY_OPT
Definition: gifsicle.c:204
Gif_Color
Definition: gif.h:171
SAME_TRANSPARENT_OPT
#define SAME_TRANSPARENT_OPT
Definition: gifsicle.c:132
frame_spec_name
char * frame_spec_name
Definition: support.c:543
GIF_WRITE_CAREFUL_MIN_CODE_SIZE
#define GIF_WRITE_CAREFUL_MIN_CODE_SIZE
Definition: gif.h:255
frame_option_types
static const char * frame_option_types[]
Definition: gifsicle.c:83
frame_spec_2
int frame_spec_2
Definition: support.c:542
Gif_Extension::length
uint32_t length
Definition: gif.h:227
def_output_data
static Gt_OutputData def_output_data
Definition: gifsicle.c:98
Gt_OutputData::scaling
int scaling
Definition: gifsicle.h:129
Gt_OutputData::colormap_algorithm
int colormap_algorithm
Definition: gifsicle.h:119
parse_position
int parse_position(Clp_Parser *, const char *, int, void *)
Definition: support.c:651
Gt_OutputData::scale_y
double scale_y
Definition: gifsicle.h:134
Clp_NewParser
Clp_Parser * Clp_NewParser(int argc, const char *const *argv, int nopt, const Clp_Option *opt)
Create a new Clp_Parser.
Definition: clp.c:503
Gt_OutputData::dither_type
int dither_type
Definition: gifsicle.h:121
Clp_AddStringListType
int Clp_AddStringListType(Clp_Parser *clp, int val_type, int flags,...) CLP_SENTINEL
Define a new string list value type for clp.
Definition: clp.c:1285
VERBOSE_OPT
#define VERBOSE_OPT
Definition: gifsicle.c:145
static_assert
#define static_assert(x, msg)
Definition: gifsicle.c:25
MULTIFILE_OPT
#define MULTIFILE_OPT
Definition: gifsicle.c:186
Gif_ImageCount
#define Gif_ImageCount(gfs)
Definition: gif.h:71
GRAY_OPT
#define GRAY_OPT
Definition: gifsicle.c:193
Gif_Stream::landmark
const char * landmark
Definition: gif.h:59
Clp_SetErrorHandler
Clp_ErrorHandler Clp_SetErrorHandler(Clp_Parser *clp, Clp_ErrorHandler errh)
Set clp's error handler function.
copy_crop
static Gt_Crop * copy_crop(Gt_Crop *oc)
Definition: gifsicle.c:1372
SAME_LOGICAL_SCREEN_OPT
#define SAME_LOGICAL_SCREEN_OPT
Definition: gifsicle.c:138
Gt_Crop::spec_h
int spec_h
Definition: gifsicle.h:86
Clp_ValUnsigned
#define Clp_ValUnsigned
Option value is an unsigned int.
Definition: clp.h:91
NO_WARNINGS_OPT
#define NO_WARNINGS_OPT
Definition: gifsicle.c:180
MERGING
#define MERGING
Definition: gifsicle.h:322
image_info
void image_info(FILE *f, Gif_Stream *gfs, Gif_Image *gfi, int flags)
Definition: support.c:464
Gt_Frame::no_extensions
int no_extensions
Definition: gifsicle.h:57
COLOR_TRANSFORM_OPT
#define COLOR_TRANSFORM_OPT
Definition: gifsicle.c:177
add_frame
Gt_Frame * add_frame(Gt_Frameset *, Gif_Stream *, Gif_Image *)
Definition: support.c:1028
set_frame_change
void set_frame_change(int kind)
Definition: gifsicle.c:424
EXTENSION_OPT
#define EXTENSION_OPT
Definition: gifsicle.c:176
CH_CHANGE_COLOR
#define CH_CHANGE_COLOR
Definition: gifsicle.c:92
error
void error(const char *format,...)
Definition: gifdiff.c:439
parse_dimensions
int parse_dimensions(Clp_Parser *, const char *, int, void *)
Definition: support.c:624
Clp_Done
#define Clp_Done
Clp_Next value: there are no more arguments.
Definition: clp.h:194
Clp_ValInt
#define Clp_ValInt
Option value is a signed int.
Definition: clp.h:78
Gt_OutputData::colormap_fixed
Gif_Colormap * colormap_fixed
Definition: gifsicle.h:118
RESIZE_FIT_OPT
#define RESIZE_FIT_OPT
Definition: gifsicle.c:188
Gt_OutputData::conserve_memory
int conserve_memory
Definition: gifsicle.h:138
SCALE_METHOD_BOX
#define SCALE_METHOD_BOX
Definition: gifsicle.h:155
frame_change_done
static void frame_change_done(void)
Definition: gifsicle.c:476
blank_frameset
void blank_frameset(Gt_Frameset *, int from, int to, int delete_ob)
Definition: support.c:1727
INFO_SIZES
#define INFO_SIZES
Definition: gifsicle.h:208
Clp_NotOption
#define Clp_NotOption
Clp_Next value: argument was not an option.
Definition: clp.h:191
verbosing
int verbosing
Definition: gifsicle.c:57
first_input_frame
int first_input_frame
Definition: gifsicle.c:31
Gt_Frame::no_comments
int no_comments
Definition: gifsicle.h:40
GT_RESIZE_MIN_DIMEN
#define GT_RESIZE_MIN_DIMEN
Definition: gifsicle.h:152
handle_extension
static int handle_extension(Clp_Parser *clp, int is_app)
Definition: gifsicle.c:1175
input_stream
void input_stream(const char *name)
Definition: gifsicle.c:678
frame_spec_1
int frame_spec_1
Definition: support.c:541
Gt_OutputData::scale_method
int scale_method
Definition: gifsicle.h:135
open_giffile
static FILE * open_giffile(const char *name)
Definition: gifsicle.c:609
NO_COMMENTS_OPT
#define NO_COMMENTS_OPT
Definition: gifsicle.c:146
CROP_TRANSPARENCY_OPT
#define CROP_TRANSPARENCY_OPT
Definition: gifsicle.c:184
SAME_APP_EXTENSIONS_OPT
#define SAME_APP_EXTENSIONS_OPT
Definition: gifsicle.c:197
SAME_EXTENSIONS_OPT
#define SAME_EXTENSIONS_OPT
Definition: gifsicle.c:164
BLANK_MODE
#define BLANK_MODE
Definition: gifsicle.h:321
parse_color
int parse_color(Clp_Parser *, const char *, int, void *)
Definition: support.c:778
input
Gif_Stream * input
Definition: gifsicle.c:34
Gt_OutputData::colormap_gamma
double colormap_gamma
Definition: gifsicle.h:125
COMBINE_ONE_OUTPUT_OPTION
#define COMBINE_ONE_OUTPUT_OPTION(value, field)
colormap_stream
void colormap_stream(Gif_Stream *, Gif_Colormap *, Gt_OutputData *)
Definition: quantize.c:1563
input_name
const char * input_name
Definition: gifsicle.c:35
Gt_Frame::stream
Gif_Stream * stream
Definition: gifsicle.h:33
Clp_Parser
Command line parser.
Definition: clp.h:234
Gt_OutputData::screen_width
int screen_width
Definition: gifsicle.h:111
nextfile
static int nextfile
Definition: gifsicle.c:42
FRAME
#define FRAME(fs, i)
Definition: gifsicle.h:308
CH_COLORMAP_METHOD
#define CH_COLORMAP_METHOD
Definition: gifsicle.c:110
Gt_Frame::crop
Gt_Crop * crop
Definition: gifsicle.h:47
verbose_endline
void verbose_endline(void)
Definition: support.c:274
KC_GAMMA_NUMERIC
#define KC_GAMMA_NUMERIC
Definition: gifsicle.h:262
def_frame
Gt_Frame def_frame
Definition: gifsicle.c:28
close_giffile
static void close_giffile(FILE *f, int final)
Definition: gifsicle.c:651
Gt_OutputData::active_output_name
const char * active_output_name
Definition: gifsicle.h:109
COLORMAP_BLEND_DIVERSITY
#define COLORMAP_BLEND_DIVERSITY
Definition: gifsicle.h:266
Gt_Crop::spec_w
int spec_w
Definition: gifsicle.h:85
active_output_data
Gt_OutputData active_output_data
Definition: gifsicle.c:99
merge_and_write_frames
static void merge_and_write_frames(const char *outfile, int f1, int f2)
Definition: gifsicle.c:990
Clp_DisallowOptions
#define Clp_DisallowOptions
Value type flag: value can't be an option string.
Definition: clp.h:314
Gt_OutputData::optimizing
int optimizing
Definition: gifsicle.h:127
no_ignore_errors
static int no_ignore_errors
Definition: gifsicle.c:58
RESIZE_METHOD_TYPE
#define RESIZE_METHOD_TYPE
Definition: gifsicle.c:217
CH_DISPOSAL
#define CH_DISPOSAL
Definition: gifsicle.c:73
position_x
int position_x
Definition: support.c:546
verbose_close
void verbose_close(char)
Definition: support.c:266
CH_MEMORY
#define CH_MEMORY
Definition: gifsicle.c:114
Gt_Crop::transparent_edges
int transparent_edges
Definition: gifsicle.h:82
EXPLODING
#define EXPLODING
Definition: gifsicle.h:324
StoredFile::next
struct StoredFile * next
Definition: gifsicle.c:602
OPTIMIZE_TYPE
#define OPTIMIZE_TYPE
Definition: gifsicle.c:216
ROTATE_180_OPT
#define ROTATE_180_OPT
Definition: gifsicle.c:172
Gif_Color::gfc_green
uint8_t gfc_green
Definition: gif.h:174
Gt_Frame::flip_vertical
unsigned flip_vertical
Definition: gifsicle.h:62
Gif_DeleteColormap
void Gif_DeleteColormap(Gif_Colormap *)
Definition: giffunc.c:546
DIMENSIONS_TYPE
#define DIMENSIONS_TYPE
Definition: gifsicle.c:208
Gt_OutputData::colormap_size
int colormap_size
Definition: gifsicle.h:117
Gif_ImageNumber
int Gif_ImageNumber(Gif_Stream *gfs, Gif_Image *gfi)
Definition: giffunc.c:294
Gt_OutputData::colormap_gamma_type
int colormap_gamma_type
Definition: gifsicle.h:124
Gt_Frame::info_flags
unsigned info_flags
Definition: gifsicle.h:63
EXIT_OK
#define EXIT_OK
Definition: gifsicle.h:200
do_colormap_change
static void do_colormap_change(Gif_Stream *gfs)
Definition: gifsicle.c:897
output_information
static void output_information(const char *outfile)
Definition: gifsicle.c:1044
resize_stream
void resize_stream(Gif_Stream *gfs, double new_width, double new_height, int flags, int method, int scale_colors)
Definition: xform.c:1295
Gif_Color::gfc_blue
uint8_t gfc_blue
Definition: gif.h:175
CROP_OPT
#define CROP_OPT
Definition: gifsicle.c:156
POSITION_OPT
#define POSITION_OPT
Definition: gifsicle.c:151
Clp_Optional
#define Clp_Optional
Option flag: value is optional.
Definition: clp.h:136
verbose_open
void verbose_open(char, const char *)
Definition: support.c:248
strerror
char * strerror(int errno)
Definition: strerror.c:13
Clp_Parser::s
const char * s
Definition: clp.h:249
GT_RESIZE_FIT_UP
#define GT_RESIZE_FIT_UP
Definition: gifsicle.h:151
Gt_Frame::name
const char * name
Definition: gifsicle.h:37
FRAME_SPEC_TYPE
#define FRAME_SPEC_TYPE
Definition: gifsicle.c:209
FLIP_VERT_OPT
#define FLIP_VERT_OPT
Definition: gifsicle.c:169
SIZEOF_VOID_P
#define SIZEOF_VOID_P
Definition: win32cfg.h:140
Clp_ShortNegated
#define Clp_ShortNegated
Option character begins a set of negated short options.
Definition: clp.h:178
LOGICAL_SCREEN_OPT
#define LOGICAL_SCREEN_OPT
Definition: gifsicle.c:133
clear_frameset
void clear_frameset(Gt_Frameset *, int from)
Definition: support.c:1750
thread_count
int thread_count
Definition: gifsicle.c:39
Gif_Stream::errors
unsigned errors
Definition: gif.h:56
UNCHECKED_MARK_CH
#define UNCHECKED_MARK_CH(where, what)
Definition: gifsicle.c:62
Gif_Stream::nimages
int nimages
Definition: gif.h:43
options
const Clp_Option options[]
Definition: gifsicle.c:219
Gt_OutputData::resize_width
int resize_width
Definition: gifsicle.h:130
GT_OPT_KEEPEMPTY
#define GT_OPT_KEEPEMPTY
Definition: gifsicle.h:163
Gt_Frame::transparent
Gif_Color transparent
Definition: gifsicle.h:42
write_stream
static void write_stream(const char *output_name, Gif_Stream *gfs)
Definition: gifsicle.c:957
Gt_Frame::input_filename
const char * input_filename
Definition: gifsicle.h:68
Gif_FullWriteFile
int Gif_FullWriteFile(Gif_Stream *gfs, const Gif_CompressInfo *gcinfo, FILE *f)
Definition: gifwrite.c:1070
warning
void warning(int need_file, const char *format,...)
Definition: support.c:108
INFO_OPT
#define INFO_OPT
Definition: gifsicle.c:127
Gif_Stream::refcount
int refcount
Definition: gif.h:60
GIF_WRITE_EAGER_CLEAR
#define GIF_WRITE_EAGER_CLEAR
Definition: gif.h:256
Clp_Parser::negated
int negated
Definition: clp.h:237
redundant_option_warning
static void redundant_option_warning(const char *)
Definition: gifsicle.c:1342
USE_COLORMAP_OPT
#define USE_COLORMAP_OPT
Definition: gifsicle.c:162
dimensions_y
int dimensions_y
Definition: support.c:545
Gt_OutputData::colormap_needs_transparency
int colormap_needs_transparency
Definition: gifsicle.h:120
warn_local_colormaps
int warn_local_colormaps
Definition: gifsicle.c:48
Gt_Crop::ready
int ready
Definition: gifsicle.h:81
GIF_READ_COMPRESSED
#define GIF_READ_COMPRESSED
Definition: gif.h:251
Gif_CompressInfo::loss
int loss
Definition: gif.h:148
input_option_types
static const char * input_option_types[]
Definition: gifsicle.c:93
Gif_Extension::next
Gif_Extension * next
Definition: gif.h:232
GAMMA_OPT
#define GAMMA_OPT
Definition: gifsicle.c:192
print_useless_options
static void print_useless_options(const char *type_name, int value, const char *names[])
Definition: gifsicle.c:1355
parsed_scale_factor_x
double parsed_scale_factor_x
Definition: support.c:550
kchist::n
int n
Definition: kcolor.h:223
GT_RESIZE_FIT_DOWN
#define GT_RESIZE_FIT_DOWN
Definition: gifsicle.h:150
INSERTING
#define INSERTING
Definition: gifsicle.h:327
SCALE_METHOD_LANCZOS3
#define SCALE_METHOD_LANCZOS3
Definition: gifsicle.h:159
Gif_Image::user_flags
uint32_t user_flags
Definition: gif.h:110
colormap_blend_diversity
Gif_Colormap * colormap_blend_diversity(kchist *kch, Gt_OutputData *od)
Definition: quantize.c:722
RESIZE_FIT_WIDTH_OPT
#define RESIZE_FIT_WIDTH_OPT
Definition: gifsicle.c:189
Gif_Stream::screen_height
uint16_t screen_height
Definition: gif.h:50
RESIZE_FIT_HEIGHT_OPT
#define RESIZE_FIT_HEIGHT_OPT
Definition: gifsicle.c:190
Gif_SetErrorHandler
void Gif_SetErrorHandler(Gif_ReadErrorHandler handler)
Definition: gifread.c:963
files_given
static int files_given
Definition: gifsicle.c:46
Gif_FullReadFile
Gif_Stream * Gif_FullReadFile(FILE *f, int flags, const char *landmark, Gif_ReadErrorHandler handler)
Definition: gifread.c:920
Gif_Reader::f
FILE * f
Definition: gifread.c:48
infoing
static int infoing
Definition: gifsicle.c:56
resize_dimensions
void resize_dimensions(int *w, int *h, double new_width, double new_height, int flags)
Definition: xform.c:1250
CH_USE_COLORMAP
#define CH_USE_COLORMAP
Definition: gifsicle.c:109
RESIZE_METHOD_OPT
#define RESIZE_METHOD_OPT
Definition: gifsicle.c:194
Gt_Frame::disposal
int disposal
Definition: gifsicle.h:52
Clp_Parser::u
unsigned u
Definition: clp.h:245
Gt_Frame::no_name
int no_name
Definition: gifsicle.h:38
Gt_Frame::use
int use
Definition: gifsicle.h:35
OUTPUT_OPT
#define OUTPUT_OPT
Definition: gifsicle.c:155
MARK_CH
#define MARK_CH(where, what)
Definition: gifsicle.c:64
SAME_POSITION_OPT
#define SAME_POSITION_OPT
Definition: gifsicle.c:152
frame_argument
int frame_argument(Clp_Parser *clp, const char *arg)
Definition: gifsicle.c:1157
stream_info
void stream_info(FILE *f, Gif_Stream *gfs, const char *filename, int flags)
Definition: support.c:417
INFO_EXTENSIONS
#define INFO_EXTENSIONS
Definition: gifsicle.h:207
Clp_BadOption
#define Clp_BadOption
Clp_Next value: argument was an erroneous option.
Definition: clp.h:197
RESIZE_WIDTH_OPT
#define RESIZE_WIDTH_OPT
Definition: gifsicle.c:182
output_frames
void output_frames(void)
Definition: gifsicle.c:1084
gifsicle.h
DELETING
#define DELETING
Definition: gifsicle.h:326
Gif_Stream::screen_width
uint16_t screen_width
Definition: gif.h:49
Gt_OutputData::output_name
const char * output_name
Definition: gifsicle.h:108
VERSION
#define VERSION
Definition: win32cfg.h:147
APP_EXTENSION_OPT
#define APP_EXTENSION_OPT
Definition: gifsicle.c:175
WARNINGS_OPT
#define WARNINGS_OPT
Definition: gifsicle.c:181
Gif_Image
Definition: gif.h:84
Gt_Frameset
Definition: gifsicle.h:73
Gt_Frame::explode_by_name
int explode_by_name
Definition: gifsicle.h:55
TWO_COLORS_TYPE
#define TWO_COLORS_TYPE
Definition: gifsicle.c:213
delete_color_transforms
Gt_ColorTransform * delete_color_transforms(Gt_ColorTransform *list, color_transform_func)
Definition: xform.c:56
output_transforms
static Gt_ColorTransform * output_transforms
Definition: gifsicle.c:51
SCALE_METHOD_POINT
#define SCALE_METHOD_POINT
Definition: gifsicle.h:154
Gt_Frame::flip_horizontal
unsigned flip_horizontal
Definition: gifsicle.h:61
RESIZE_COLORS_OPT
#define RESIZE_COLORS_OPT
Definition: gifsicle.c:195
parse_resize_geometry_opt
static void parse_resize_geometry_opt(Gt_OutputData *odata, const char *str, Clp_Parser *clp)
Definition: gifsicle.c:1385
SAME_BACKGROUND_OPT
#define SAME_BACKGROUND_OPT
Definition: gifsicle.c:167
SAME_LOOPCOUNT_OPT
#define SAME_LOOPCOUNT_OPT
Definition: gifsicle.c:129
CH_RESIZE_METHOD
#define CH_RESIZE_METHOD
Definition: gifsicle.c:116
Gt_Crop::spec_x
int spec_x
Definition: gifsicle.h:83
GIF_UNOPTIMIZE_SIMPLEST_DISPOSAL
#define GIF_UNOPTIMIZE_SIMPLEST_DISPOSAL
Definition: gif.h:73
Gt_OutputData::scale_x
double scale_x
Definition: gifsicle.h:133
Clp_Next
int Clp_Next(Clp_Parser *clp)
Parse and return the next argument from clp.
Definition: clp.c:1835
Gif_Stream::user_flags
uint32_t user_flags
Definition: gif.h:57
unoptimizing
static int unoptimizing
Definition: gifsicle.c:36
SCALE_FACTOR_TYPE
#define SCALE_FACTOR_TYPE
Definition: gifsicle.c:215
Gif_New
#define Gif_New(t)
Definition: gif.h:310
CH_OPTIMIZE
#define CH_OPTIMIZE
Definition: gifsicle.c:105
FLIP_HORIZ_OPT
#define FLIP_HORIZ_OPT
Definition: gifsicle.c:168
NO_ROTATE_OPT
#define NO_ROTATE_OPT
Definition: gifsicle.c:174
colormap_median_cut
Gif_Colormap * colormap_median_cut(kchist *kch, Gt_OutputData *od)
Definition: quantize.c:391
Gif_Stream::images
Gif_Image ** images
Definition: gif.h:42
Clp_Option
Option description.
Definition: clp.h:41
CH_OUTPUT
#define CH_OUTPUT
Definition: gifsicle.c:106
Gif_Stream
Definition: gif.h:41
COLOR_INFO_OPT
#define COLOR_INFO_OPT
Definition: gifsicle.c:144
COLORMAP_DIVERSITY
#define COLORMAP_DIVERSITY
Definition: gifsicle.h:265
Gt_Frame::interlacing
int interlacing
Definition: gifsicle.h:43
CH_ROTATE
#define CH_ROTATE
Definition: gifsicle.c:82
CHANGED
#define CHANGED(next, flag)
Definition: gifsicle.c:61
new_frameset
Gt_Frameset * new_frameset(int initial_cap)
Definition: support.c:993
Gif_NewComment
Gif_Comment * Gif_NewComment(void)
Definition: giffunc.c:113
SIZE_INFO_OPT
#define SIZE_INFO_OPT
Definition: gifsicle.c:191
RESIZE_TOUCH_OPT
#define RESIZE_TOUCH_OPT
Definition: gifsicle.c:201
Gif_Image::identifier
char * identifier
Definition: gif.h:99
no_warnings
int no_warnings
Definition: support.c:22
Gif_CompressInfo::flags
int flags
Definition: gif.h:147
color_change_transformer
void color_change_transformer(Gif_Colormap *, void *)
Definition: xform.c:94
SAME_DELAY_OPT
#define SAME_DELAY_OPT
Definition: gifsicle.c:131
Gt_OutputData::dither_name
const char * dither_name
Definition: gifsicle.h:123
SCALE_METHOD_MIX
#define SCALE_METHOD_MIX
Definition: gifsicle.h:156
lerror
void lerror(const char *landmark, const char *format,...)
Definition: support.c:87
COLORMAP_ALG_TYPE
#define COLORMAP_ALG_TYPE
Definition: gifsicle.c:214
StoredFile
Definition: gifsicle.c:600
Gif_Color::pixel
uint32_t pixel
Definition: gif.h:176
Gif_DeleteComment
void Gif_DeleteComment(Gif_Comment *)
Definition: giffunc.c:562
GT_SCALING_SCALE
#define GT_SCALING_SCALE
Definition: gifsicle.h:147
Gt_OutputData::resize_height
int resize_height
Definition: gifsicle.h:131
COLORMAP_ALGORITHM_OPT
#define COLORMAP_ALGORITHM_OPT
Definition: gifsicle.c:160
frames
Gt_Frameset * frames
Definition: gifsicle.c:30
Clp_Parser::have_val
int have_val
Definition: clp.h:239
EXTENSION_INFO_OPT
#define EXTENSION_INFO_OPT
Definition: gifsicle.c:165
Clp_Parser::vstr
const char * vstr
Definition: clp.h:240
Gif_DeleteStream
void Gif_DeleteStream(Gif_Stream *)
Definition: giffunc.c:494
RESIZE_TOUCH_HEIGHT_OPT
#define RESIZE_TOUCH_HEIGHT_OPT
Definition: gifsicle.c:203
gif_write_info
Gif_CompressInfo gif_write_info
Definition: gifsicle.c:43
program_name
const char * program_name
Definition: gifdiff.c:41
INFOING
#define INFOING
Definition: gifsicle.h:325
next_output
static int next_output
Definition: gifsicle.c:100
ALTER_DONE_OPT
#define ALTER_DONE_OPT
Definition: gifsicle.c:142
colormap_flat_diversity
Gif_Colormap * colormap_flat_diversity(kchist *kch, Gt_OutputData *od)
Definition: quantize.c:726
frames_done
static int frames_done
Definition: gifsicle.c:45
parsed_scale_factor_y
double parsed_scale_factor_y
Definition: support.c:551
parse_rectangle
int parse_rectangle(Clp_Parser *, const char *, int, void *)
Definition: support.c:707
CH_GAMMA
#define CH_GAMMA
Definition: gifsicle.c:115
CH_CROP
#define CH_CROP
Definition: gifsicle.c:79
VERSION_OPT
#define VERSION_OPT
Definition: gifsicle.c:153
CH_FLIP
#define CH_FLIP
Definition: gifsicle.c:81
CH_COLOR_TRANSFORM
#define CH_COLOR_TRANSFORM
Definition: gifsicle.c:112
SAME_NAME_OPT
#define SAME_NAME_OPT
Definition: gifsicle.c:149
background
static unsigned background
Definition: optimize.c:58
Gif_Color::haspixel
uint8_t haspixel
Definition: gif.h:172
INSERT_OPT
#define INSERT_OPT
Definition: gifsicle.c:141
SCALE_METHOD_MITCHELL
#define SCALE_METHOD_MITCHELL
Definition: gifsicle.h:160
StoredFile::f
FILE * f
Definition: gifsicle.c:601
Gt_OutputData::resize_flags
int resize_flags
Definition: gifsicle.h:132
show_frame
static void show_frame(int imagenumber, int usename)
Definition: gifsicle.c:488
EXIT_USER_ERR
#define EXIT_USER_ERR
Definition: gifsicle.h:202
pipe_color_transformer
void pipe_color_transformer(Gif_Colormap *, void *)
Definition: xform.c:139
Gt_Frame::comment
Gif_Comment * comment
Definition: gifsicle.h:39
input_transforms
static Gt_ColorTransform * input_transforms
Definition: gifsicle.c:50
CH_EXTENSION
#define CH_EXTENSION
Definition: gifsicle.c:80
NO_EXTENSIONS_OPT
#define NO_EXTENSIONS_OPT
Definition: gifsicle.c:163
CH_POSITION
#define CH_POSITION
Definition: gifsicle.c:78
Gt_Frame::nest
Gt_Frameset * nest
Definition: gifsicle.h:54
SCALE_OPT
#define SCALE_OPT
Definition: gifsicle.c:179
Gif_NewExtension
Gif_Extension * Gif_NewExtension(int kind, const char *appname, int applength)
Definition: giffunc.c:126
position_y
int position_y
Definition: support.c:547
GIFSICLE_DEFAULT_THREAD_COUNT
const int GIFSICLE_DEFAULT_THREAD_COUNT
Definition: gifsicle.c:38
INFO_COLORMAPS
#define INFO_COLORMAPS
Definition: gifsicle.h:206
RESIZE_TOUCH_WIDTH_OPT
#define RESIZE_TOUCH_WIDTH_OPT
Definition: gifsicle.c:202
APPEND_OPT
#define APPEND_OPT
Definition: gifsicle.c:143
NAME_OPT
#define NAME_OPT
Definition: gifsicle.c:148
CH_DITHER
#define CH_DITHER
Definition: gifsicle.c:108
BACKGROUND_OPT
#define BACKGROUND_OPT
Definition: gifsicle.c:166
combine_output_options
static void combine_output_options(void)
Definition: gifsicle.c:1271
Gt_Crop
Definition: gifsicle.h:80
Clp_DeleteParser
void Clp_DeleteParser(Clp_Parser *clp)
Destroy a Clp_Parser object.
Definition: clp.c:579
CHANGE_COLOR_OPT
#define CHANGE_COLOR_OPT
Definition: gifsicle.c:158
initialize_def_frame
static void initialize_def_frame(void)
Definition: gifsicle.c:1210
clp
Clp_Parser * clp
Definition: gifsicle.c:356
read_colormap_file
Gif_Colormap * read_colormap_file(const char *, FILE *)
Definition: support.c:940
error_count
int error_count
Definition: support.c:21
lwarning
void lwarning(const char *landmark, const char *format,...)
Definition: support.c:101
Clp_Parser::val
union Clp_Parser::@0 val
SIZEOF_UNSIGNED_INT
#define SIZEOF_UNSIGNED_INT
Definition: win32cfg.h:131
Gif_Colormap::refcount
int refcount
Definition: gif.h:184
Gif_Colormap::col
Gif_Color * col
Definition: gif.h:185
ROTATE_90_OPT
#define ROTATE_90_OPT
Definition: gifsicle.c:171
GIF_DISPOSAL_BACKGROUND
#define GIF_DISPOSAL_BACKGROUND
Definition: gif.h:119
kc_set_gamma
void kc_set_gamma(int type, double gamma)
Definition: quantize.c:115
GIF_DISPOSAL_NONE
#define GIF_DISPOSAL_NONE
Definition: gif.h:117
CH_RESIZE
#define CH_RESIZE
Definition: gifsicle.c:113
usage
void usage(void)
Definition: gifdiff.c:408
CH_COMMENT
#define CH_COMMENT
Definition: gifsicle.c:76
GIF_DISPOSAL_PREVIOUS
#define GIF_DISPOSAL_PREVIOUS
Definition: gif.h:120
apply_color_transforms
void apply_color_transforms(Gt_ColorTransform *, Gif_Stream *)
Definition: xform.c:73
SCALE_METHOD_CATROM
#define SCALE_METHOD_CATROM
Definition: gifsicle.h:157
Gt_Frame
Definition: gifsicle.h:31
Gif_FullUnoptimize
int Gif_FullUnoptimize(Gif_Stream *, int flags)
Definition: gifunopt.c:176
SAME_DISPOSAL_OPT
#define SAME_DISPOSAL_OPT
Definition: gifsicle.c:130
CH_UNOPTIMIZE
#define CH_UNOPTIMIZE
Definition: gifsicle.c:91
COLOR_TYPE
#define COLOR_TYPE
Definition: gifsicle.c:210
any_output_successful
static int any_output_successful
Definition: gifsicle.c:102
Clp_ValString
#define Clp_ValString
Option value is an arbitrary string.
Definition: clp.h:59
THREADS_OPT
#define THREADS_OPT
Definition: gifsicle.c:199
parsed_color2
Gif_Color parsed_color2
Definition: support.c:549
Gif_AddComment
int Gif_AddComment(Gif_Comment *, const char *, int)
Definition: giffunc.c:259
set_dither_type
int set_dither_type(Gt_OutputData *od, const char *name)
Definition: quantize.c:1932
GT_OPT_MASK
#define GT_OPT_MASK
Definition: gifsicle.h:162
Clp_ProgramName
const char * Clp_ProgramName(Clp_Parser *clp)
Return clp's program name.
Definition: clp.c:1407
GIF_READ_TRAILING_GARBAGE_OK
#define GIF_READ_TRAILING_GARBAGE_OK
Definition: gif.h:254
fatal_error
void fatal_error(const char *format,...)
Definition: gifdiff.c:428
KC_GAMMA_SRGB
#define KC_GAMMA_SRGB
Definition: gifsicle.h:261
NO_NAME_OPT
#define NO_NAME_OPT
Definition: gifsicle.c:150
Gif_Extension::data
uint8_t * data
Definition: gif.h:226
kcolor.h
Clp_AllowNumbers
#define Clp_AllowNumbers
String list flag: allow explicit numbers.
Definition: clp.h:327
nested_frames
Gt_Frameset * nested_frames
Definition: gifsicle.c:32
clp_error_handler
void clp_error_handler(Clp_Parser *clp, const char *clp_message)
Definition: support.c:116
Clp_SetOptionChar
int Clp_SetOptionChar(Clp_Parser *clp, int c, int type)
Set clp's treatment of character c.
Definition: clp.c:710
CH_SCALE_COLORS
#define CH_SCALE_COLORS
Definition: gifsicle.c:117
set_mode
static void set_mode(int newmode)
Definition: gifsicle.c:405
Clp_Parser::i
int i
Definition: clp.h:244
COMMENT_OPT
#define COMMENT_OPT
Definition: gifsicle.c:134
merge_frame_interval
Gif_Stream * merge_frame_interval(Gt_Frameset *, int f1, int f2, Gt_OutputData *, int compress, int *huge)
Definition: support.c:1468
REPLACE_OPT
#define REPLACE_OPT
Definition: gifsicle.c:140
next_frame
static int next_frame
Definition: gifsicle.c:71
SAME_CROP_OPT
#define SAME_CROP_OPT
Definition: gifsicle.c:157
SIZEOF_UNSIGNED_LONG
#define SIZEOF_UNSIGNED_LONG
Definition: win32cfg.h:134
SCALE_METHOD_LANCZOS2
#define SCALE_METHOD_LANCZOS2
Definition: gifsicle.h:158
CH_LOGICAL_SCREEN
#define CH_LOGICAL_SCREEN
Definition: gifsicle.c:104
main
int main(int argc, char *argv[])
Definition: gifsicle.c:1444
append_color_change
Gt_ColorTransform * append_color_change(Gt_ColorTransform *list, Gif_Color, Gif_Color)
Definition: xform.c:116
next_input
static int next_input
Definition: gifsicle.c:90
HELP_OPT
#define HELP_OPT
Definition: gifsicle.c:154
GT_SCALING_RESIZE
#define GT_SCALING_RESIZE
Definition: gifsicle.h:146
Clp_CurOptionName
const char * Clp_CurOptionName(Clp_Parser *clp)
Extract the current option as a string.
Definition: clp.c:2460
RECTANGLE_TYPE
#define RECTANGLE_TYPE
Definition: gifsicle.c:212
Gt_OutputData
Definition: gifsicle.h:106
explode_filename
char * explode_filename(const char *filename, int number, const char *name, int max_nimg)
Definition: support.c:513
gif_read_flags
static int gif_read_flags
Definition: gifsicle.c:41
optimize_fragments
void optimize_fragments(Gif_Stream *, int optimizeness, int huge_stream)
Definition: optimize.c:451
EXIT_ERR
#define EXIT_ERR
Definition: gifsicle.h:201
POSITION_TYPE
#define POSITION_TYPE
Definition: gifsicle.c:211
DITHER_OPT
#define DITHER_OPT
Definition: gifsicle.c:161
kchist_cleanup
void kchist_cleanup(kchist *kch)
Definition: quantize.c:205
Gt_Frame::position_is_offset
unsigned position_is_offset
Definition: gifsicle.h:64
Gt_Frame::no_app_extensions
int no_app_extensions
Definition: gifsicle.h:58
GT_SCALING_NONE
#define GT_SCALING_NONE
Definition: gifsicle.h:145
COLORMAP_OPT
#define COLORMAP_OPT
Definition: gifsicle.c:159
Gt_OutputData::dither_data
const uint8_t * dither_data
Definition: gifsicle.h:122
CH_BACKGROUND
#define CH_BACKGROUND
Definition: gifsicle.c:111
Gt_Frame::delay
int delay
Definition: gifsicle.h:51
CH_DELAY
#define CH_DELAY
Definition: gifsicle.c:74