Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

support.c File Reference

#include "config.h"
#include "gifsicle.h"
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <errno.h>

Go to the source code of this file.


Defines

#define COLORMAP_COLS   4

Functions

void verror (int seriousness, char *message, va_list val)
void fatal_error (char *message,...)
void error (char *message,...)
void warning (char *message,...)
void warncontext (char *message,...)
void clp_error_handler (char *message)
void short_usage (void)
void usage (void)
void verbose_open (char open, const char *name)
void verbose_close (char close)
void verbose_endline (void)
void safe_puts (const char *s, u_int32_t len, FILE *f)
void comment_info (FILE *where, Gif_Comment *gfcom, char *prefix)
void colormap_info (FILE *where, Gif_Colormap *gfcm, char *prefix)
void extension_info (FILE *where, Gif_Stream *gfs, Gif_Extension *gfex, int count)
void stream_info (FILE *where, Gif_Stream *gfs, const char *filename, int colormaps, int extensions)
void image_info (FILE *where, Gif_Stream *gfs, Gif_Image *gfi, int colormaps)
char * explode_filename (char *filename, int number, char *name, int max_nimages)
int parse_frame_spec (Clp_Parser *clp, const char *arg, int complain, void *thunk)
int parse_dimensions (Clp_Parser *clp, const char *arg, int complain, void *thunk)
int parse_position (Clp_Parser *clp, const char *arg, int complain, void *thunk)
int parse_scale_factor (Clp_Parser *clp, const char *arg, int complain, void *thunk)
int parse_rectangle (Clp_Parser *clp, const char *arg, int complain, void *thunk)
int xvalue (char c)
int parse_hex_color_channel (const char *s, int ndigits)
int parse_color (Clp_Parser *clp, const char *arg, int complain, void *thunk)
int parse_two_colors (Clp_Parser *clp, const char *arg, int complain, void *thunk)
Gif_Colormapread_text_colormap (FILE *f, char *name)
Gif_Colormapread_colormap_file (char *name, FILE *f)
Gt_Framesetnew_frameset (int initial_cap)
void clear_def_frame_once_options (void)
Gt_Frameadd_frame (Gt_Frameset *fset, int number, Gif_Stream *gfs, Gif_Image *gfi)
Gif_Extensioncopy_extension (Gif_Extension *src)
void merger_add (Gt_Frame *fp)
void merger_flatten (Gt_Frameset *fset, int f1, int f2)
void find_background (Gif_Colormap *dest_global, Gif_Color *background)
int find_color_or_error (Gif_Color *color, Gif_Stream *gfs, Gif_Image *gfi, char *color_context)
void fix_total_crop (Gif_Stream *dest, Gif_Image *srci, int merger_index)
void handle_screen (Gif_Stream *dest, u_int16_t width, u_int16_t height)
void handle_flip_and_screen (Gif_Stream *dest, Gif_Image *desti, Gt_Frame *fr, int first_image)
Gif_Streammerge_frame_interval (Gt_Frameset *fset, int f1, int f2, Gt_OutputData *output_data, int compress_immediately)
void blank_frameset (Gt_Frameset *fset, int f1, int f2, int delete_object)
void clear_frameset (Gt_Frameset *fset, int f1)

Variables

const char * program_name = "gifsicle"
int verbose_pos = 0
int error_count = 0
int no_warnings = 0
char * disposal_names []
int frame_spec_1
int frame_spec_2
char * frame_spec_name
int dimensions_x
int dimensions_y
int position_x
int position_y
Gif_Color parsed_color
Gif_Color parsed_color2
double parsed_scale_factor_x
double parsed_scale_factor_y
Gt_Frame ** merger = 0
int nmerger = 0
int mergercap = 0

Define Documentation

#define COLORMAP_COLS   4
 

Definition at line 284 of file support.c.

Referenced by colormap_info().


Function Documentation

Gt_Frame* add_frame Gt_Frameset   fset,
int    number,
Gif_Stream   gfs,
Gif_Image   gfi
 

Definition at line 929 of file support.c.

References blank_frameset(), Gt_Frameset::cap, clear_def_frame_once_options(), Gt_Frameset::count, Gt_Frameset::f, Gif_ReArray, Gt_Frame::image, Gif_Image::refcount, Gif_Stream::refcount, and Gt_Frame::stream.

Referenced by input_stream(), and show_frame().

00930 {
00931   if (number < 0) {
00932     while (fset->count >= fset->cap) {
00933       fset->cap *= 2;
00934       Gif_ReArray(fset->f, Gt_Frame, fset->cap);
00935     }
00936     number = fset->count++;
00937   } else {
00938     assert(number < fset->count);
00939     blank_frameset(fset, number, number, 0);
00940   }
00941 
00942   /* Mark the stream and the image both */
00943   gfs->refcount++;
00944   gfi->refcount++;
00945   fset->f[number] = def_frame;
00946   fset->f[number].stream = gfs;
00947   fset->f[number].image = gfi;
00948   
00949   clear_def_frame_once_options();
00950   
00951   return &fset->f[number];
00952 }

void blank_frameset Gt_Frameset   fset,
int    f1,
int    f2,
int    delete_object
 

END MERGE LOOP *

Definition at line 1405 of file support.c.

References Gt_Frameset::count, Gt_Frameset::f, FRAME, Gif_Delete, Gif_DeleteArray, Gif_DeleteComment(), Gif_DeleteStream(), and i.

Referenced by add_frame(), clear_frameset(), and main().

01406 {
01407   int i;
01408   if (delete_object) f1 = 0, f2 = -1;
01409   if (f2 < 0) f2 = fset->count - 1;
01410   for (i = f1; i <= f2; i++) {
01411     /* We may have deleted stream and image earlier to save on memory; see
01412        above in merge_frame_interval(); but if we didn't, do it now. */
01413     if (FRAME(fset, i).image && FRAME(fset, i).image->refcount > 1)
01414       FRAME(fset, i).image->refcount--;
01415     Gif_DeleteStream(FRAME(fset, i).stream);
01416     Gif_DeleteComment(FRAME(fset, i).comment);
01417     if (FRAME(fset, i).nest)
01418       blank_frameset(FRAME(fset, i).nest, 0, 0, 1);
01419   }
01420   if (delete_object) {
01421     Gif_DeleteArray(fset->f);
01422     Gif_Delete(fset);
01423   }
01424 }

void clear_def_frame_once_options void   
 

Definition at line 906 of file support.c.

Referenced by add_frame().

00907 {
00908   /* Get rid of next-frame-only options.
00909      
00910      This causes problems with frame selection. In the command `gifsicle
00911      -nblah f.gif', the name should be applied to frame 0 of f.gif. This will
00912      happen automatically when f.gif is read, since all of its frames will be
00913      added when it is input. After frame 0, the name in def_frame will be
00914      cleared.
00915      
00916      Now, `gifsicle -nblah f.gif #1' should apply the name to frame 1 of
00917      f.gif. But once f.gif is input, its frames are added, and the name
00918      component of def_frame is cleared!! So when #1 comes around it's gone!
00919      
00920      We handle this in gifsicle.c using the _change fields. */
00921   
00922   def_frame.name = 0;
00923   def_frame.comment = 0;
00924   def_frame.extensions = 0;
00925 }

void clear_frameset Gt_Frameset   fset,
int    f1
 

Definition at line 1428 of file support.c.

References blank_frameset(), and Gt_Frameset::count.

Referenced by output_frames(), and show_frame().

01429 {
01430   blank_frameset(fset, f1, -1, 0);
01431   fset->count = f1;
01432 }

void clp_error_handler char *    message
 

Definition at line 95 of file support.c.

References verbose_endline().

00096 {
00097   verbose_endline();
00098   fputs(message, stderr);
00099 }

void colormap_info FILE *    where,
Gif_Colormap   gfcm,
char *    prefix
[static]
 

Definition at line 287 of file support.c.

References Gif_Color::blue, Gif_Colormap::col, COLORMAP_COLS, Gif_Color::green, i, Gif_Colormap::ncol, and Gif_Color::red.

Referenced by image_info(), and stream_info().

00288 {
00289   int i, j;
00290   int nrows = ((gfcm->ncol - 1) / COLORMAP_COLS) + 1;
00291   
00292   for (j = 0; j < nrows; j++) {
00293     int which = j;
00294     fputs(prefix, where);
00295     for (i = 0; i < COLORMAP_COLS && which < gfcm->ncol; i++, which += nrows) {
00296       if (i) fputs("    ", where);
00297       fprintf(where, " %3d: #%02X%02X%02X", which, gfcm->col[which].red,
00298               gfcm->col[which].green, gfcm->col[which].blue);
00299     }
00300     fputc('\n', where);
00301   }
00302 }

void comment_info FILE *    where,
Gif_Comment   gfcom,
char *    prefix
[static]
 

Definition at line 273 of file support.c.

References Gif_Comment::count, i, Gif_Comment::len, safe_puts(), and Gif_Comment::str.

Referenced by image_info(), and stream_info().

00274 {
00275   int i;
00276   for (i = 0; i < gfcom->count; i++) {
00277     fputs(prefix, where);
00278     safe_puts(gfcom->str[i], gfcom->len[i], where);
00279     fputc('\n', where);
00280   }
00281 }

Gif_Extension* copy_extension Gif_Extension   src [static]
 

Definition at line 956 of file support.c.

References Gif_Extension::application, Gif_Extension::data, Gif_Extension::free_data, Gif_DeleteArrayFunc, Gif_DeleteExtension(), Gif_NewArray, Gif_NewExtension(), Gif_Extension::kind, and Gif_Extension::length.

Referenced by merge_frame_interval().

00957 {
00958   Gif_Extension *dest = Gif_NewExtension(src->kind, src->application);
00959   if (!dest) return 0;
00960   dest->data = Gif_NewArray(byte, src->length);
00961   dest->length = src->length;
00962   dest->free_data = Gif_DeleteArrayFunc;
00963   if (!dest->data) {
00964     Gif_DeleteExtension(dest);
00965     return 0;
00966   }
00967   memcpy(dest->data, src->data, src->length);
00968   return dest;
00969 }

void error char *    message,
...   
 

Definition at line 68 of file support.c.

References verror().

Referenced by parse_color().

00069 {
00070   va_list val;
00071   va_start(val, message);
00072   verror(2, message, val);
00073   va_end(val);
00074 }

char* explode_filename char *    filename,
int    number,
char *    name,
int    max_nimages
 

Definition at line 446 of file support.c.

References Gif_Delete, Gif_NewArray, l, and name.

Referenced by output_frames().

00447 {
00448   static char *s;
00449   int l = strlen(filename);
00450   l += name ? strlen(name) : 10;
00451   
00452   Gif_Delete(s);
00453   s = Gif_NewArray(char, l + 3);
00454   if (name)
00455     sprintf(s, "%s.%s", filename, name);
00456   else if (max_nimages <= 1000)
00457     sprintf(s, "%s.%03d", filename, number);
00458   else {
00459     int digits;
00460     unsigned j;
00461     unsigned max = (max_nimages < 0 ? 0 : max_nimages);
00462     for (digits = 4, j = 10000; max > j; digits++)
00463       j *= 10;
00464     sprintf(s, "%s.%0*d", filename, digits, number);
00465   }
00466   
00467   return s;
00468 }

void extension_info FILE *    where,
Gif_Stream   gfs,
Gif_Extension   gfex,
int    count
[static]
 

Definition at line 306 of file support.c.

References Gif_Extension::application, Gif_Extension::data, i, Gif_Extension::kind, Gif_Extension::length, Gif_Stream::nimages, Gif_Extension::position, safe_puts(), and u_int32_t.

Referenced by stream_info().

00307 {
00308   byte *data = gfex->data;
00309   u_int32_t pos = 0;
00310   u_int32_t len = gfex->length;
00311   
00312   fprintf(where, "  extension %d: ", count);
00313   if (gfex->kind == 255) {
00314     fprintf(where, "app `");
00315     safe_puts(gfex->application, strlen(gfex->application), where);
00316     fprintf(where, "'");
00317   } else {
00318     if (gfex->kind >= 32 && gfex->kind < 127)
00319       fprintf(where, "`%c' (0x%02X)", gfex->kind, gfex->kind);
00320     else
00321       fprintf(where, "0x%02X", gfex->kind);
00322   }
00323   if (gfex->position >= gfs->nimages)
00324     fprintf(where, " at end\n");
00325   else
00326     fprintf(where, " before #%d\n", gfex->position);
00327   
00328   /* Now, hexl the data. */
00329   while (len > 0) {
00330     u_int32_t row = 16;
00331     u_int32_t i;
00332     if (row > len) row = len;
00333     fprintf(where, "    %08x: ", pos);
00334     
00335     for (i = 0; i < row; i += 2) {
00336       if (i + 1 >= row)
00337         fprintf(where, "%02x   ", data[i]);
00338       else
00339         fprintf(where, "%02x%02x ", data[i], data[i+1]);
00340     }
00341     for (; i < 16; i += 2)
00342       fputs("     ", where);
00343     
00344     putc(' ', where);
00345     for (i = 0; i < row; i++, data++)
00346       putc((*data >= ' ' && *data < 127 ? *data : '.'), where);
00347     putc('\n', where);
00348     
00349     pos += row;
00350     len -= row;
00351   }
00352 }

void fatal_error char *    message,
...   
 

Definition at line 58 of file support.c.

References EXIT_USER_ERR, and verror().

Referenced by colormap_diversity(), colormap_median_cut(), do_colormap_change(), get_used_colors(), handle_extension(), main(), merge_image(), pipe_color_transformer(), scale_image(), set_frame_change(), and set_mode().

00059 {
00060   va_list val;
00061   va_start(val, message);
00062   verror(3, message, val);
00063   va_end(val);
00064   exit(EXIT_USER_ERR);
00065 }

void find_background Gif_Colormap   dest_global,
Gif_Color   background
[static]
 

Definition at line 1021 of file support.c.

References Gif_Stream::background, Gif_Color::blue, Gif_Colormap::col, COLORMAP_ENSURE_SLOT_255, error(), GIF_COLOREQ, GIF_DISPOSAL_BACKGROUND, Gif_Stream::global, Gif_Color::green, Gif_Color::haspixel, i, Gt_Frame::image, Gif_Stream::images, Gif_Colormap::ncol, nmerger, Gif_Color::pixel, Gif_Color::red, Gt_Frame::stream, Gif_Image::transparent, Gt_Frame::transparent, Gif_Colormap::userflags, warncontext(), and warning().

Referenced by merge_frame_interval().

01022 {
01023   int i;
01024   /* This code is SUCH a PAIN in the PATOOTIE!! */
01025   
01026   /* 0. report warnings if the user wants an impossible background setting */
01027   if (background->haspixel) {
01028     int first_img_transp = 0;
01029     if (merger[0]->transparent.haspixel < 255)
01030       first_img_transp = (merger[0]->image->transparent >= 0
01031                           || merger[0]->transparent.haspixel);
01032     if (first_img_transp) {
01033       static int context = 0;
01034       warning("irrelevant background color");
01035       if (!context) {
01036         warncontext("(The background will appear transparent because");
01037         warncontext("the first image contains transparency.)");
01038         context = 1;
01039       }
01040     }
01041   }
01042   
01043   /* 1. user set the background to a color index
01044      -> find the associated color */
01045   if (background->haspixel == 2) {
01046     Gif_Stream *gfs = merger[0]->stream;
01047     if (gfs->global && background->pixel < gfs->global->ncol) {
01048       *background = gfs->global->col[ background->pixel ];
01049       background->haspixel = 1;
01050     } else {
01051       error("background color index `%d' out of range", background->pixel);
01052       background->haspixel = 0;
01053     }
01054   }
01055   
01056   /* 2. search the existing streams and images for background colors
01057         (prefer colors from images with disposal == BACKGROUND)
01058      -> choose the color. warn if two such images have conflicting colors */
01059   if (background->haspixel == 0) {
01060     int relevance = 0;
01061     int saved_bg_transparent = 0;
01062     for (i = 0; i < nmerger; i++) {
01063       Gif_Stream *gfs = merger[i]->stream;
01064       int bg_disposal = merger[i]->image->disposal == GIF_DISPOSAL_BACKGROUND;
01065       int bg_transparent = gfs->images[0]->transparent >= 0;
01066       int bg_exists = gfs->global && gfs->background < gfs->global->ncol;
01067       
01068       if ((!bg_exists && !bg_transparent) || (bg_disposal + 1 < relevance))
01069         continue;
01070       else if (bg_disposal + 1 > relevance) {
01071         if (bg_exists)
01072           *background = gfs->global->col[gfs->background];
01073         else
01074           background->red = background->green = background->blue = 0;
01075         saved_bg_transparent = bg_transparent;
01076         relevance = bg_disposal + 1;
01077         continue;
01078       }
01079       
01080       /* check for conflicting background requirements */
01081       if (bg_transparent != saved_bg_transparent
01082           || (!saved_bg_transparent &&
01083               !GIF_COLOREQ(background, &gfs->global->col[gfs->background]))) {
01084         static int context = 0;
01085         warning("input images have conflicting background colors");
01086         if (!context) {
01087           warncontext("(This means some animation frames may appear incorrect.)");
01088           context = 1;
01089         }
01090         break;
01091       }
01092     }
01093     background->haspixel = relevance != 0;
01094   }
01095   
01096   /* 3. we found a background color
01097      -> force the merging process to keep it in the global colormap with
01098      COLORMAP_ENSURE_SLOT_255. See merge.c function ensure_slot_255 */
01099   if (background->haspixel) {
01100     dest_global->userflags |= COLORMAP_ENSURE_SLOT_255;
01101     dest_global->col[255] = *background;
01102   }
01103 }

int find_color_or_error Gif_Color   color,
Gif_Stream   gfs,
Gif_Image   gfi,
char *    color_context
[static]
 

Definition at line 1107 of file support.c.

References color, error(), Gif_FindColor(), Gif_Stream::global, Gif_Color::haspixel, Gif_Image::local, Gif_Colormap::ncol, and Gif_Color::pixel.

Referenced by merge_frame_interval().

01109 {
01110   Gif_Colormap *gfcm = gfs->global;
01111   int index;
01112   if (gfi && gfi->local) gfcm = gfi->local;
01113   
01114   if (color->haspixel == 2) {   /* have pixel value, not color */
01115     if (color->pixel < gfcm->ncol)
01116       return color->pixel;
01117     else {
01118       if (color_context) error("%s color out of range", color_context);
01119       return -1;
01120     }
01121   }
01122   
01123   index = Gif_FindColor(gfcm, color);
01124   if (index < 0 && color_context)
01125     error("%s color not in colormap", color_context);
01126   return index;
01127 }

void fix_total_crop Gif_Stream   dest,
Gif_Image   srci,
int    merger_index
[static]
 

Definition at line 1131 of file support.c.

References Gt_Frame::comment, Gif_Image::comment, Gif_Image::delay, Gt_Frame::delay, Gif_DeleteComment(), Gif_NewComment(), Gif_Stream::images, merge_comments(), Gif_Stream::nimages, nmerger, and Gt_Frame::no_comments.

Referenced by merge_frame_interval().

01132 {
01133   /* Salvage any relevant information from a frame that's been completely
01134      cropped away. This ends up being comments and delay. */
01135   Gt_Frame *fr = merger[merger_index];
01136   Gt_Frame *next_fr = 0;
01137   Gif_Image *prev_image = 0;
01138   if (dest->nimages > 0) prev_image = dest->images[dest->nimages - 1];
01139   if (merger_index < nmerger - 1) next_fr = merger[merger_index + 1];
01140   
01141   /* Don't save identifiers since the frame that was to be identified, is
01142      gone. Save comments though. */
01143   if (!fr->no_comments && srci->comment && next_fr) {
01144     if (!next_fr->comment) next_fr->comment = Gif_NewComment();
01145     merge_comments(next_fr->comment, srci->comment);
01146   }
01147   if (fr->comment && next_fr) {
01148     if (!next_fr->comment) next_fr->comment = Gif_NewComment();
01149     merge_comments(next_fr->comment, fr->comment);
01150     Gif_DeleteComment(fr->comment);
01151     fr->comment = 0;
01152   }
01153   
01154   /* Save delay by adding it to the previous frame's delay. */
01155   if (fr->delay < 0)
01156     fr->delay = srci->delay;
01157   prev_image->delay += fr->delay;
01158 }

void handle_flip_and_screen Gif_Stream   dest,
Gif_Image   desti,
Gt_Frame   fr,
int    first_image
[static]
 

Definition at line 1173 of file support.c.

References first_image, Gt_Frame::flip_horizontal, flip_image(), Gt_Frame::flip_vertical, handle_screen(), rotate_image(), Gt_Frame::rotation, Gif_Stream::screen_height, Gif_Stream::screen_width, Gt_Frame::stream, and u_int16_t.

Referenced by merge_frame_interval().

01175 {
01176   Gif_Stream *gfs = fr->stream;
01177   
01178   u_int16_t screen_width = gfs->screen_width;
01179   u_int16_t screen_height = gfs->screen_height;
01180   
01181   if (fr->flip_horizontal)
01182     flip_image(desti, screen_width, screen_height, 0);
01183   if (fr->flip_vertical)
01184     flip_image(desti, screen_width, screen_height, 1);
01185   
01186   if (fr->rotation == 1)
01187     rotate_image(desti, screen_width, screen_height, 1);
01188   else if (fr->rotation == 2) {
01189     flip_image(desti, screen_width, screen_height, 0);
01190     flip_image(desti, screen_width, screen_height, 1);
01191   } else if (fr->rotation == 3)
01192     rotate_image(desti, screen_width, screen_height, 3);
01193   
01194   /* handle screen size, which might have height & width exchanged */
01195   if (fr->rotation == 1 || fr->rotation == 3)
01196     handle_screen(dest, screen_height, screen_width);
01197   else
01198     handle_screen(dest, screen_width, screen_height);
01199 }

void handle_screen Gif_Stream   dest,
u_int16_t    width,
u_int16_t    height
[static]
 

Definition at line 1162 of file support.c.

References Gif_Stream::screen_height, Gif_Stream::screen_width, and u_int16_t.

Referenced by handle_flip_and_screen(), and merge_frame_interval().

01163 {
01164   /* Set the screen width & height, if the current input width and height are
01165      larger */
01166   if (dest->screen_width < width)
01167     dest->screen_width = width;
01168   if (dest->screen_height < height)
01169     dest->screen_height = height;
01170 }

void image_info FILE *    where,
Gif_Stream   gfs,
Gif_Image   gfi,
int    colormaps
 

Definition at line 397 of file support.c.

References colormap_info(), Gif_Image::comment, comment_info(), Gif_Image::compressed, Gif_Image::compressed_len, Gif_Image::delay, Gif_Image::disposal, disposal_names, Gif_ImageNumber(), Gif_Image::height, Gif_Image::identifier, Gif_Image::interlace, Gif_Image::left, Gif_Image::local, Gif_Colormap::ncol, Gif_Image::top, Gif_Image::transparent, verbose_endline(), and Gif_Image::width.

Referenced by output_information().

00398 {
00399   int num;
00400   if (!gfs || !gfi) return;
00401   num = Gif_ImageNumber(gfs, gfi);
00402   
00403   verbose_endline();
00404   fprintf(where, "  + image #%d ", num);
00405   if (gfi->identifier)
00406     fprintf(where, "#%s ", gfi->identifier);
00407   
00408   fprintf(where, "%dx%d", gfi->width, gfi->height);
00409   if (gfi->left || gfi->top)
00410     fprintf(where, " at %d,%d", gfi->left, gfi->top);
00411   
00412   if (gfi->interlace)
00413     fprintf(where, " interlaced");
00414   
00415   if (gfi->transparent >= 0)
00416     fprintf(where, " transparent %d", gfi->transparent);
00417   
00418 #if defined(PRINT_SIZE)
00419   if (gfi->compressed)
00420     fprintf(where, " compressed size %u min_code_size %d", gfi->compressed_len, *gfi->compressed);
00421 #endif
00422   
00423   fprintf(where, "\n");
00424   
00425   if (gfi->comment)
00426     comment_info(where, gfi->comment, "    comment ");
00427   
00428   if (gfi->local) {
00429     fprintf(where, "    local color table [%d]\n", gfi->local->ncol);
00430     if (colormaps) colormap_info(where, gfi->local, "    |");
00431   }
00432   
00433   if (gfi->disposal || gfi->delay) {
00434     fprintf(where, "   ");
00435     if (gfi->disposal)
00436       fprintf(where, " disposal %s", disposal_names[gfi->disposal]);
00437     if (gfi->delay)
00438       fprintf(where, " delay %d.%02ds",
00439               gfi->delay / 100, gfi->delay % 100);
00440     fprintf(where, "\n");
00441   }
00442 }

Gif_Stream* merge_frame_interval Gt_Frameset   fset,
int    f1,
int    f2,
Gt_OutputData   output_data,
int    compress_immediately
 

Definition at line 1203 of file support.c.

References Gif_Stream::background, Gt_OutputData::background, Gif_Colormap::col, Gt_Frame::comment, Gif_Image::comment, copy_extension(), Gt_Frameset::count, Gt_Frame::crop, crop_image(), Gif_Image::delay, Gt_Frame::delay, Gif_Image::disposal, Gt_Frame::disposal, error(), Gt_Frame::extensions, Gif_Stream::extensions, find_background(), find_color_or_error(), fix_total_crop(), Gt_Frame::flip_horizontal, Gt_Frame::flip_vertical, Gif_AddExtension(), Gif_CalculateScreenSize(), Gif_CopyImage(), Gif_CopyString(), Gif_DeleteArray, Gif_DeleteComment(), Gif_DeleteImage(), Gif_DeleteStream(), Gif_FullCompressImage(), Gif_NewComment(), Gif_NewFullColormap(), Gif_NewStream(), Gif_ReleaseCompressedImage(), Gif_ReleaseUncompressedImage(), Gif_UncompressImage, Gif_Stream::global, global, handle_flip_and_screen(), handle_screen(), Gif_Color::haspixel, i, Gif_Image::identifier, Gt_Frame::image, Gif_Stream::images, Gif_Image::interlace, Gt_Frame::interlacing, Gif_Image::left, Gt_Frame::left, Gif_Stream::loopcount, Gt_OutputData::loopcount, merge_comments(), merge_image(), merge_stream(), merger_flatten(), Gt_Frame::name, Gif_Colormap::ncol, Gif_Extension::next, nmerger, Gt_Frame::no_comments, Gt_Frame::no_extensions, Gt_Frame::no_name, Gif_Extension::position, Gt_Frame::position_is_offset, Gif_Image::refcount, Gt_Frame::rotation, Gt_OutputData::screen_height, Gif_Stream::screen_height, Gt_OutputData::screen_width, Gif_Stream::screen_width, Gt_Frame::stream, Gif_Image::top, Gt_Frame::top, Gt_Frame::transparent, Gif_Image::transparent, unmark_colors_2(), Gif_Stream::userflags, and Gt_Crop::whole_stream.

Referenced by merge_and_write_frames().

01205 {
01206   Gif_Stream *dest = Gif_NewStream();
01207   Gif_Colormap *global = Gif_NewFullColormap(256, 256);
01208   Gif_Color dest_background;
01209   int i;
01210   
01211   global->ncol = 0;
01212   dest->global = global;
01213   /* 11/23/98 A new stream's screen size is 0x0; we'll use the max of the
01214      merged-together streams' screen sizes by default (in merge_stream()) */
01215   
01216   if (f2 < 0) f2 = fset->count - 1;
01217   nmerger = 0;
01218   merger_flatten(fset, f1, f2);
01219   if (nmerger == 0) {
01220     error("empty output GIF not written");
01221     return 0;
01222   }
01223   
01224   /* merge stream-specific info and clear colormaps */
01225   for (i = 0; i < nmerger; i++)
01226     merger[i]->stream->userflags = 1;
01227   for (i = 0; i < nmerger; i++) {
01228     if (merger[i]->stream->userflags) {
01229       Gif_Stream *src = merger[i]->stream;
01230       Gif_CalculateScreenSize(src, 0);
01231       /* merge_stream() unmarks the global colormap */
01232       merge_stream(dest, src, merger[i]->no_comments);
01233       src->userflags = 0;
01234     }
01235     if (merger[i]->image->local)
01236       unmark_colors_2(merger[i]->image->local);
01237   }
01238   
01239   /* decide on the background. use the one from output_data */
01240   dest_background = output_data->background;
01241   find_background(global, &dest_background);
01242   
01243   /* check for cropping the whole stream */
01244   for (i = 0; i < nmerger; i++)
01245     if (merger[i]->crop)
01246       merger[i]->crop->whole_stream = 0;
01247   if (merger[0]->crop) {
01248     merger[0]->crop->whole_stream = 1;
01249     for (i = 1; i < nmerger; i++)
01250       if (merger[i]->crop != merger[0]->crop)
01251         merger[0]->crop->whole_stream = 0;
01252   }
01253   
01254   /* copy stream-wide information from output_data */
01255   if (output_data->loopcount > -2)
01256     dest->loopcount = output_data->loopcount;
01257   dest->screen_width = dest->screen_height = 0;
01258   
01259   /** ACTUALLY MERGE FRAMES INTO THE NEW STREAM **/
01260   for (i = 0; i < nmerger; i++) {
01261     Gt_Frame *fr = merger[i];
01262     Gif_Image *srci;
01263     Gif_Image *desti;
01264     int old_transparent;
01265     
01266     /* First, check for extensions */
01267     {
01268       int j;
01269       Gif_Extension *gfex = fr->stream->extensions;
01270       for (j = 0; fr->stream->images[j] != fr->image; j++) ;
01271       while (gfex && gfex->position < j)
01272         gfex = gfex->next;
01273       while (!fr->no_extensions && gfex && gfex->position == j) {
01274         Gif_AddExtension(dest, copy_extension(gfex), i);
01275         gfex = gfex->next;
01276       }
01277       gfex = fr->extensions;
01278       while (gfex) {
01279         Gif_Extension *next = gfex->next;
01280         Gif_AddExtension(dest, gfex, i);
01281         gfex = next;
01282       }
01283     }
01284     
01285     /* Make a copy of the image and crop it if we're cropping */
01286     if (fr->crop) {
01287       srci = Gif_CopyImage(fr->image);
01288       Gif_UncompressImage(srci);
01289       if (!crop_image(srci, fr->crop)) {
01290         /* We cropped the image out of existence! Be careful not to make 0x0
01291            frames. */
01292         fix_total_crop(dest, srci, i);
01293         goto merge_frame_done;
01294       }
01295     } else {
01296       srci = fr->image;
01297       Gif_UncompressImage(srci);
01298     }
01299     
01300     /* It was pretty stupid to remove this code, which I did between 1.2b6 and
01301        1.2 */
01302     old_transparent = srci->transparent;
01303     if (fr->transparent.haspixel == 255)
01304       srci->transparent = -1;
01305     else if (fr->transparent.haspixel)
01306       srci->transparent =
01307         find_color_or_error(&fr->transparent, fr->stream, srci, "transparent");
01308     
01309     desti = merge_image(dest, fr->stream, srci);
01310     
01311     srci->transparent = old_transparent; /* restore real transparent value */
01312     
01313     /* Flipping and rotating, and also setting the screen size */
01314     if (fr->flip_horizontal || fr->flip_vertical || fr->rotation)
01315       handle_flip_and_screen(dest, desti, fr, i == 0);
01316     else
01317       handle_screen(dest, fr->stream->screen_width, fr->stream->screen_height);
01318     
01319     /* Names and comments */
01320     if (fr->name || fr->no_name) {
01321       Gif_DeleteArray(desti->identifier);
01322       desti->identifier = Gif_CopyString(fr->name);
01323     }
01324     if (fr->no_comments && desti->comment) {
01325       Gif_DeleteComment(desti->comment);
01326       desti->comment = 0;
01327     }
01328     if (fr->comment) {
01329       if (!desti->comment) desti->comment = Gif_NewComment();
01330       merge_comments(desti->comment, fr->comment);
01331       /* delete the comment early to help with memory; set field to 0 so we
01332          don't re-free it later */
01333       Gif_DeleteComment(fr->comment);
01334       fr->comment = 0;
01335     }
01336     
01337     if (fr->interlacing >= 0)
01338       desti->interlace = fr->interlacing;
01339     if (fr->left >= 0)
01340       desti->left = fr->left + (fr->position_is_offset ? desti->left : 0);
01341     if (fr->top >= 0)
01342       desti->top = fr->top + (fr->position_is_offset ? desti->top : 0);
01343     
01344     if (fr->delay >= 0)
01345       desti->delay = fr->delay;
01346     if (fr->disposal >= 0)
01347       desti->disposal = fr->disposal;
01348     
01349     /* compress immediately if possible to save on memory */
01350     if (compress_immediately) {
01351       Gif_FullCompressImage(dest, desti, gif_write_flags);
01352       Gif_ReleaseUncompressedImage(desti);
01353     }
01354     
01355    merge_frame_done:
01356     /* Destroy the copied, cropped image if necessary */
01357     if (fr->crop)
01358       Gif_DeleteImage(srci);
01359     
01360     /* if we can, delete the image's data right now to save memory */
01361     srci = fr->image;
01362     assert(srci->refcount > 1);
01363     if (--srci->refcount == 1) {
01364       /* only 1 reference ==> the reference is from the input stream itself */
01365       Gif_ReleaseUncompressedImage(srci);
01366       Gif_ReleaseCompressedImage(srci);
01367       fr->image = 0;
01368     }
01369     
01370     /* 5/26/98 Destroy the stream now to help with memory. Assumes that
01371        all frames are added with add_frame() which properly increments the
01372        stream's refcount. Set field to 0 so we don't redelete */
01373     Gif_DeleteStream(fr->stream);
01374     fr->stream = 0;
01375   }
01376   /** END MERGE LOOP **/
01377 
01378   /* Cropping the whole output? Clear the logical screen */
01379   if (merger[0]->crop && merger[0]->crop == merger[nmerger-1]->crop)
01380     dest->screen_width = dest->screen_height = 0;
01381   /* Set the logical screen from the user's preferences */
01382   if (output_data->screen_width >= 0)
01383     dest->screen_width = output_data->screen_width;
01384   if (output_data->screen_height >= 0)
01385     dest->screen_height = output_data->screen_height;
01386   
01387   /* Find the background color in the colormap, or add it if we can */
01388   {
01389     int bg = find_color_or_error(&dest_background, dest, 0, 0);
01390     if (bg < 0 && dest->images[0]->transparent >= 0)
01391       dest->background = dest->images[0]->transparent;
01392     else if (bg < 0 && global->ncol < 256) {
01393       dest->background = global->ncol;
01394       global->col[ global->ncol ] = dest_background;
01395       global->ncol++;
01396     } else
01397       dest->background = bg;
01398   }
01399 
01400   return dest;
01401 }

void merger_add Gt_Frame   fp [static]
 

Definition at line 977 of file support.c.

References Gif_NewArray, Gif_ReArray, mergercap, and nmerger.

Referenced by merger_flatten().

00978 {
00979   while (nmerger >= mergercap)
00980     if (mergercap) {
00981       mergercap *= 2;
00982       Gif_ReArray(merger, Gt_Frame *, mergercap);
00983     } else {
00984       mergercap = 16;
00985       merger = Gif_NewArray(Gt_Frame *, mergercap);
00986     }
00987   merger[ nmerger++ ] = fp;
00988 }

void merger_flatten Gt_Frameset   fset,
int    f1,
int    f2
[static]
 

Definition at line 992 of file support.c.

References Gt_Frameset::count, FRAME, Gif_CopyString(), i, and merger_add().

Referenced by merge_frame_interval().

00993 {
00994   int i;
00995   assert(f1 >= 0 && f2 < fset->count);
00996   for (i = f1; i <= f2; i++) {
00997     Gt_Frameset *nest = FRAME(fset, i).nest;
00998     
00999     if (nest && nest->count > 0) {
01000       if (FRAME(fset, i).use < 0 && nest->count == 1) {
01001         /* use < 0 means use the frame's delay, disposal and name (if not
01002            explicitly overridden), but not the frame itself. */
01003         if (FRAME(nest, 0).delay < 0)
01004           FRAME(nest, 0).delay = FRAME(fset, i).image->delay;
01005         if (FRAME(nest, 0).disposal < 0)
01006           FRAME(nest, 0).disposal = FRAME(fset, i).image->disposal;
01007         if (FRAME(nest, 0).name == 0 && FRAME(nest, 0).no_name == 0)
01008           FRAME(nest, 0).name =
01009             Gif_CopyString(FRAME(fset, i).image->identifier);
01010       }
01011       merger_flatten(nest, 0, nest->count - 1);
01012     }
01013     
01014     if (FRAME(fset, i).use > 0)
01015       merger_add(&FRAME(fset, i));
01016   }
01017 }

Gt_Frameset* new_frameset int    initial_cap
 

Definition at line 894 of file support.c.

References Gt_Frameset::cap, Gt_Frameset::count, Gt_Frameset::f, Gif_New, and Gif_NewArray.

Referenced by main(), and set_frame_change().

00895 {
00896   Gt_Frameset *fs = Gif_New(Gt_Frameset);
00897   if (initial_cap < 0) initial_cap = 0;
00898   fs->cap = initial_cap;
00899   fs->count = 0;
00900   fs->f = Gif_NewArray(Gt_Frame, initial_cap);
00901   return fs;
00902 }

int parse_color Clp_Parser   clp,
const char *    arg,
int    complain,
void *    thunk
 

Definition at line 698 of file support.c.

References arg, Gif_Color::blue, Clp_OptionError(), error(), Gif_Color::green, Gif_Color::haspixel, parse_hex_color_channel(), Gif_Color::pixel, and Gif_Color::red.

Referenced by parse_two_colors().

00699 {
00700   const char *input_arg = arg;
00701   char *str;
00702   int red, green, blue;
00703   
00704   if (*arg == '#') {
00705     int len = strlen(++arg);
00706     if (!len || len % 3 != 0 || strspn(arg, "0123456789ABCDEFabcdef") != len) {
00707       if (complain)
00708         Clp_OptionError(clp, "invalid color `%s' (want `#RGB' or `#RRGGBB')",
00709                         input_arg);
00710       return 0;
00711     }
00712     
00713     len /= 3;
00714     red   = parse_hex_color_channel(&arg[ 0 * len ], len);
00715     green = parse_hex_color_channel(&arg[ 1 * len ], len);
00716     blue  = parse_hex_color_channel(&arg[ 2 * len ], len);
00717     goto gotrgb;
00718     
00719   } else if (!isdigit(*arg))
00720     goto error;
00721   
00722   red = strtol(arg, &str, 10);
00723   if (*str == 0) {
00724     if (red < 0 || red > 255)
00725       goto error;
00726     parsed_color.haspixel = 1;
00727     parsed_color.pixel = red;
00728     return 1;
00729     
00730   } else if (*str != ',' && *str != '/')
00731     goto error;
00732   
00733   if (*++str == 0) goto error;
00734   green = strtol(str, &str, 10);
00735   if (*str != ',' && *str != '/') goto error;
00736   
00737   if (*++str == 0) goto error;
00738   blue = strtol(str, &str, 10);
00739   if (*str != 0) goto error;
00740   
00741  gotrgb:
00742   if (red < 0 || green < 0 || blue < 0
00743       || red > 255 || green > 255 || blue > 255)
00744     goto error;
00745   parsed_color.red = red;
00746   parsed_color.green = green;
00747   parsed_color.blue = blue;
00748   parsed_color.haspixel = 0;
00749   return 1;
00750   
00751  error:
00752   if (complain)
00753     return Clp_OptionError(clp, "invalid color `%s'", input_arg);
00754   else
00755     return 0;
00756 }

int parse_dimensions Clp_Parser   clp,
const char *    arg,
int    complain,
void *    thunk
 

Definition at line 569 of file support.c.

References arg, Clp_OptionError(), dimensions_x, and dimensions_y.

Referenced by parse_rectangle().

00570 {
00571   char *val;
00572 
00573   if (*arg == '_' && arg[1] == 'x') {
00574     dimensions_x = 0;
00575     val = (char *)(arg + 1);
00576   } else
00577     dimensions_x = strtol(arg, &val, 10);
00578   if (*val == 'x') {
00579     if (val[1] == '_' && val[2] == 0) {
00580       dimensions_y = 0;
00581       val = val + 2;
00582     } else
00583       dimensions_y = strtol(val + 1, &val, 10);
00584     if (*val == 0)
00585       return 1;
00586   }
00587   
00588   if (complain)
00589     return Clp_OptionError(clp, "invalid dimensions `%s' (want WxH)", arg);
00590   else
00591     return 0;
00592 }

int parse_frame_spec Clp_Parser   clp,
const char *    arg,
int    complain,
void *    thunk
 

Definition at line 488 of file support.c.

References arg, c, Clp_OptionError(), frame_spec_1, frame_spec_2, frame_spec_name, Gif_GetNamedImage(), Gif_ImageCount, Gif_ImageNumber(), and input_stream().

Referenced by frame_argument().

00489 {
00490   char *c;
00491   
00492   frame_spec_1 = 0;
00493   frame_spec_2 = -1;
00494   frame_spec_name = 0;
00495   
00496   if (!input && !input_name)
00497     input_stream(0);
00498   if (!input)
00499     return 0;
00500   
00501   if (arg[0] != '#') {
00502     if (complain)
00503       return Clp_OptionError(clp, "frame specifications must start with #");
00504     else
00505       return 0;
00506   }
00507   arg++;
00508   c = (char *)arg;
00509   
00510   /* Get a number range (#x, #x-y, or #x-). First, read x. */
00511   if (isdigit(c[0]))
00512     frame_spec_1 = frame_spec_2 = strtol(c, &c, 10);
00513   else if (c[0] == '-' && isdigit(c[1])) {
00514     frame_spec_1 = frame_spec_2 = Gif_ImageCount(input) + strtol(c, &c, 10);
00515     if (frame_spec_1 < 0)
00516       return complain ? Clp_OptionError(clp, "there are only %d frames",
00517                                         Gif_ImageCount(input)) : 0;
00518   }
00519   
00520   /* Then, if the next character is a dash, read y. Be careful to prevent
00521      #- from being interpreted as a frame range. */
00522   if (c[0] == '-' && (frame_spec_2 > 0 || c[1] != 0)) {
00523     c++;
00524     if (isdigit(c[0]))
00525       frame_spec_2 = strtol(c, &c, 10);
00526     else if (c[0] == '-' && isdigit(c[1]))
00527       frame_spec_2 = Gif_ImageCount(input) + strtol(c, &c, 10);
00528     else
00529       frame_spec_2 = Gif_ImageCount(input) - 1;
00530   }
00531   
00532   /* It really was a number range (and not a frame name)
00533      only if c is now at the end of the argument. */
00534   if (c[0] != 0) {
00535     Gif_Image *gfi = Gif_GetNamedImage(input, arg);
00536     if (gfi) {
00537       frame_spec_name = (char *)arg;
00538       frame_spec_1 = frame_spec_2 = Gif_ImageNumber(input, gfi);
00539       return 1;
00540     } else if (complain < 0)    /* -1 is special value meaning `don't complain
00541                                    about frame NAMES, but do complain about
00542                                    frame numbers.' */
00543       return -97;               /* Return -97 on bad frame name. */
00544     else if (complain)
00545       return Clp_OptionError(clp, "no frame named `#%s'", arg);
00546     else
00547       return 0;
00548     
00549   } else {
00550     if (frame_spec_1 >= 0 && frame_spec_1 <= frame_spec_2
00551         && frame_spec_2 < Gif_ImageCount(input))
00552       return 1;
00553     else if (!complain)
00554       return 0;
00555     
00556     if (frame_spec_1 == frame_spec_2)
00557       return Clp_OptionError(clp, "no frame number #%d", frame_spec_1);
00558     else if (frame_spec_1 < 0)
00559       return Clp_OptionError(clp, "frame numbers can't be negative");
00560     else if (frame_spec_1 > frame_spec_2)
00561       return Clp_OptionError(clp, "empty frame range");
00562     else
00563       return Clp_OptionError(clp, "there are only %d frames",
00564                              Gif_ImageCount(input));
00565   }
00566 }

int parse_hex_color_channel const char *    s,
int    ndigits
[static]
 

Definition at line 684 of file support.c.

References xvalue().

Referenced by parse_color().

00685 {
00686   int val1 = xvalue(s[0]);
00687   if (val1 < 0) return -1;
00688   if (ndigits == 1)
00689     return val1 * 16 + val1;
00690   else {
00691     int val2 = xvalue(s[1]);
00692     if (val2 < 0) return -1;
00693     return val1 * 16 + val2;
00694   }
00695 }

int parse_position Clp_Parser   clp,
const char *    arg,
int    complain,
void *    thunk
 

Definition at line 595 of file support.c.

References arg, Clp_OptionError(), position_x, and position_y.

Referenced by parse_rectangle().

00596 {
00597   char *val;
00598   
00599   position_x = strtol(arg, &val, 10);
00600   if (*val == ',') {
00601     position_y = strtol(val + 1, &val, 10);
00602     if (*val == 0)
00603       return 1;
00604   }
00605   
00606   if (complain)
00607     return Clp_OptionError(clp, "invalid position `%s' (want `X,Y')", arg);
00608   else
00609     return 0;
00610 }

int parse_rectangle Clp_Parser   clp,
const char *    arg,
int    complain,
void *    thunk
 

Definition at line 634 of file support.c.

References arg, Clp_OptionError(), dimensions_x, dimensions_y, parse_dimensions(), parse_position(), position_x, and position_y.

00635 {
00636   const char *input_arg = arg;
00637   char *val;
00638   
00639   int x = position_x = strtol(arg, &val, 10);
00640   if (*val == ',') {
00641     int y = position_y = strtol(val + 1, &val, 10);
00642     if (*val == '-' && parse_position(clp, val + 1, 0, 0)) {
00643       if (x >= 0 && y >= 0 && x < position_x && y < position_y) {
00644         dimensions_x = position_x - x;
00645         dimensions_y = position_y - y;
00646         position_x = x;
00647         position_y = y;
00648         return 1;
00649       }
00650     } else if (*val == '+' && parse_dimensions(clp, val + 1, 0, 0))
00651       return 1;
00652   } else if (*val == 'x') {
00653     dimensions_x = position_x;
00654     dimensions_y = strtol(val + 1, &val, 10);
00655     if (*val == 0) {
00656       position_x = position_y = 0;
00657       return 1;
00658     }
00659   }
00660   
00661   if (complain)
00662     return Clp_OptionError(clp, "invalid rectangle `%s' (want `X1,Y1-X2,Y2' or `X1,Y1+WxH'", input_arg);
00663   else
00664     return 0;
00665 }

int parse_scale_factor Clp_Parser   clp,
const char *    arg,
int    complain,
void *    thunk
 

Definition at line 613 of file support.c.

References arg, Clp_OptionError(), parsed_scale_factor_x, parsed_scale_factor_y, and strtod().

00614 {
00615   char *val;
00616   
00617   parsed_scale_factor_x = strtod(arg, &val);
00618   if (*val == 'x') {
00619     parsed_scale_factor_y = strtod(val + 1, &val);
00620     if (*val == 0)
00621       return 1;
00622   } else if (*val == 0) {
00623     parsed_scale_factor_y = parsed_scale_factor_x;
00624     return 1;
00625   }
00626   
00627   if (complain)
00628     return Clp_OptionError(clp, "invalid scale factor `%s' (want XxY)", arg);
00629   else
00630     return 0;
00631 }

int parse_two_colors Clp_Parser   clp,
const char *    arg,
int    complain,
void *    thunk
 

Definition at line 759 of file support.c.

References arg, Clp_OptionError(), Clp_Shift(), and parse_color().

00760 {
00761   Gif_Color old_color;
00762   if (parse_color(clp, arg, complain, thunk) <= 0)
00763     return 0;
00764   old_color = parsed_color;
00765   
00766   arg = Clp_Shift(clp, 0);
00767   if (!arg && complain)
00768     return Clp_OptionError(clp, "`%O' takes two color arguments");
00769   else if (!arg)
00770     return 0;
00771   
00772   if (parse_color(clp, arg, complain, thunk) <= 0)
00773     return 0;
00774   
00775   parsed_color2 = parsed_color;
00776   parsed_color = old_color;
00777   return 1;
00778 }

Gif_Colormap* read_colormap_file char *    name,
FILE *    f
 

Definition at line 841 of file support.c.

References c, error(), Gif_Stream::errors, Gif_CopyColormap(), Gif_DeleteStream(), Gif_ReadFile, Gif_Stream::global, name, read_text_colormap(), strerror(), ungetc(), verbose_close(), verbose_open(), and warning().

Referenced by pipe_color_transformer(), and set_new_fixed_colormap().

00842 {
00843   Gif_Colormap *cm = 0;
00844   int c;
00845   int my_file = 0;
00846   
00847   if (name && strcmp(name, "-") == 0)
00848     name = 0;
00849   if (!f) {
00850     my_file = 1;
00851     if (!name)
00852       f = stdin;
00853     else
00854       f = fopen(name, "rb");
00855     if (!f) {
00856       error("%s: %s", name, strerror(errno));
00857       return 0;
00858     }
00859   }
00860   
00861   name = name ? name : "<stdin>";
00862   if (verbosing) verbose_open('<', name);
00863   
00864   c = getc(f);
00865   ungetc(c, f);
00866   if (c == 'G') {
00867     Gif_Stream *gfs = Gif_ReadFile(f);
00868     if (!gfs)
00869       error("`%s' doesn't seem to contain a GIF", name);
00870     else if (!gfs->global)
00871       error("can't use `%s' as a palette (no global color table)", name);
00872     else {
00873       if (gfs->errors)
00874         warning("there were errors reading `%s'", name);
00875       cm = Gif_CopyColormap(gfs->global);
00876     }
00877     
00878     Gif_DeleteStream(gfs);
00879   } else
00880     cm = read_text_colormap(f, name);
00881   
00882   if (my_file) fclose(f);
00883   if (verbosing) verbose_close('>');
00884   return cm;
00885 }

Gif_Colormap* read_text_colormap FILE *    f,
char *    name
[static]
 

Definition at line 786 of file support.c.

References c, Gif_Colormap::col, error(), Gif_DeleteColormap(), Gif_NewFullColormap(), name, Gif_Colormap::ncol, and ncol.

Referenced by read_colormap_file().

00787 {
00788   char buf[BUFSIZ];
00789   Gif_Colormap *cm = Gif_NewFullColormap(0, 256);
00790   Gif_Color *col = cm->col;
00791   int ncol = 0;
00792   unsigned red, green, blue;
00793   float fred, fgreen, fblue;
00794   
00795   while (fgets(buf, BUFSIZ, f)) {
00796     
00797     if (sscanf(buf, "%g %g %g", &fred, &fgreen, &fblue) == 3) {
00798       if (fred < 0) fred = 0;
00799       if (fgreen < 0) fgreen = 0;
00800       if (fblue < 0) fblue = 0;
00801       red = (unsigned)(fred + .5);
00802       green = (unsigned)(fgreen + .5);
00803       blue = (unsigned)(fblue + .5);
00804       goto found;
00805       
00806     } else if (sscanf(buf, "#%2x%2x%2x", &red, &green, &blue) == 3) {
00807      found:
00808       if (red > 255) red = 255;
00809       if (green > 255) green = 255;
00810       if (blue > 255) blue = 255;
00811       if (ncol >= 256) {
00812         error("%s: maximum 256 colors allowed in colormap", name);
00813         break;
00814       } else {
00815         col[ncol].red = red;
00816         col[ncol].green = green;
00817         col[ncol].blue = blue;
00818         ncol++;
00819       }
00820     }
00821     
00822     /* handle too-long lines gracefully */
00823     if (strchr(buf, '\n') == 0) {
00824       int c;
00825       for (c = getc(f); c != '\n' && c != EOF; c = getc(f))
00826         ;
00827     }
00828   }
00829   
00830   if (ncol == 0) {
00831     error("`%s' doesn't seem to contain a colormap", name);
00832     Gif_DeleteColormap(cm);
00833     return 0;
00834   } else {
00835     cm->ncol = ncol;
00836     return cm;
00837   }
00838 }

void safe_puts const char *    s,
u_int32_t    len,
FILE *    f
[static]
 

Definition at line 246 of file support.c.

References u_int32_t.

Referenced by comment_info(), and extension_info().

00247 {
00248   const char *last_safe = s;
00249   for (; len > 0; len--, s++)
00250     if (*s < ' ' || *s >= 0x7F || *s == '\\') {
00251       if (last_safe != s)
00252         fwrite(last_safe, 1, s - last_safe, f);
00253       last_safe = s + 1;
00254       switch (*s) {
00255        case '\a': fputs("\\a", f); break;
00256        case '\b': fputs("\\b", f); break;
00257        case '\f': fputs("\\f", f); break;
00258        case '\n': fputs("\\n", f); break;
00259        case '\r': fputs("\\r", f); break;
00260        case '\t': fputs("\\t", f); break;
00261        case '\v': fputs("\\v", f); break;
00262        case '\\': fputs("\\\\", f); break;
00263        case 0:    if (len > 1) fputs("\\000", f); break;
00264        default:   fprintf(f, "\\%03o", *s); break;
00265       }
00266     }
00267   if (last_safe != s)
00268     fwrite(last_safe, 1, s - last_safe, f);
00269 }

void short_usage void   
 

Definition at line 103 of file support.c.

References program_name.

00104 {
00105   fprintf(stderr, "Usage: %s [OPTION | FILE | FRAME]...\n\
00106 Try `%s --help' for more information.\n",
00107           program_name, program_name);
00108 }

void stream_info FILE *    where,
Gif_Stream   gfs,
const char *    filename,
int    colormaps,
int    extensions
 

Definition at line 356 of file support.c.

References Gif_Stream::background, colormap_info(), Gif_Stream::comment, comment_info(), extension_info(), Gif_Stream::extensions, Gif_Stream::global, Gif_Stream::loopcount, Gif_Colormap::ncol, Gif_Extension::next, Gif_Stream::nimages, Gif_Stream::screen_height, Gif_Stream::screen_width, and verbose_endline().

Referenced by output_information().

00358 {
00359   Gif_Extension *gfex;
00360   int n;
00361   
00362   if (!gfs) return;
00363   
00364   verbose_endline();
00365   fprintf(where, "* %s %d image%s\n", (filename ? filename : "<stdin>"),
00366           gfs->nimages, gfs->nimages == 1 ? "" : "s");
00367   fprintf(where, "  logical screen %dx%d\n",
00368           gfs->screen_width, gfs->screen_height);
00369   
00370   if (gfs->global) {
00371     fprintf(where, "  global color table [%d]\n", gfs->global->ncol);
00372     if (colormaps) colormap_info(where, gfs->global, "  |");
00373     fprintf(where, "  background %d\n", gfs->background);
00374   }
00375   
00376   if (gfs->comment)
00377     comment_info(where, gfs->comment, "  end comment ");
00378   
00379   if (gfs->loopcount == 0)
00380     fprintf(where, "  loop forever\n");
00381   else if (gfs->loopcount > 0)
00382     fprintf(where, "  loop count %u\n", (unsigned)gfs->loopcount);
00383   
00384   for (n = 0, gfex = gfs->extensions; gfex; gfex = gfex->next, n++)
00385     if (extensions)
00386       extension_info(where, gfs, gfex, n);
00387   if (n && !extensions)
00388     fprintf(where, "  extensions %d\n", n);
00389 }

void usage void   
 

Definition at line 112 of file support.c.

References program_name.

00113 {
00114   printf("\
00115 `Gifsicle' manipulates GIF images. Its most common uses include combining\n\
00116 single images into animations, adding transparency, optimizing animations for\n\
00117 space, and printing information about GIFs.\n\
00118 \n\
00119 Usage: %s [OPTION | FILE | FRAME]...\n\
00120 \n\
00121 Mode options: at most one, before any filenames.\n\
00122   -m, --merge                   Merge mode: combine inputs, write stdout.\n\
00123   -b, --batch                   Batch mode: modify inputs, write back to\n\
00124                                 same filenames.\n\
00125   -e, --explode                 Explode mode: write N files for each input,\n\
00126                                 one per frame, to `input.frame-number'.\n\
00127   -E, --explode-by-name         Explode mode, but write `input.name'.\n\
00128 \n\
00129 General options: Also --no-OPTION for info and verbose.\n\
00130   -I, --info                    Print info about input GIFs. Two -I's means\n\
00131                                 normal output is not suppressed.\n\
00132       --color-info, --cinfo     --info plus colormap details.\n\
00133       --extension-info, --xinfo --info plus extension details.\n\
00134   -v, --verbose                 Prints progress information.\n\
00135   -h, --help                    Print this message and exit.\n\
00136       --version                 Print version number and exit.\n\
00137   -o, --output FILE             Write output to FILE.\n\
00138   -w, --no-warnings             Don't report warnings.\n\
00139 \n", program_name);
00140   printf("\
00141 Frame selections:               #num, #num1-num2, #num1-, #name\n\
00142 \n\
00143 Frame change options:\n\
00144   --delete FRAMES               Delete FRAMES from input.\n\
00145   --insert-before FRAME GIFS    Insert GIFS before FRAMES in input.\n\
00146   --append GIFS                 Append GIFS to input.\n\
00147   --replace FRAMES GIFS         Replace FRAMES with GIFS in input.\n\
00148   --done                        Done with frame changes.\n\
00149 \n\
00150 Image options: Also --no-OPTION and --same-OPTION.\n\
00151   -B, --background COL          Makes COL the background color.\n\
00152       --crop X,Y+WxH, --crop X,Y-X2,Y2\n\
00153                                 Crops the image.\n\
00154       --flip-horizontal, --flip-vertical\n\
00155                                 Flips the image.\n\
00156   -i, --interlace               Turns on interlacing.\n\
00157   -S, --logical-screen WxH      Sets logical screen to WxH.\n\
00158   -p, --position X,Y            Sets frame position to (X,Y).\n\
00159       --rotate-90, --rotate-180, --rotate-270, --no-rotate\n\
00160                                 Rotates the image.\n\
00161   -t, --transparent COL         Makes COL transparent.\n\
00162 \n");
00163   printf("\
00164 Extension options: Also --no-OPTION and --same-OPTION.\n\
00165   -x, --app-extension N D       Adds an app extension named N with data D.\n\
00166   -c, --comment TEXT            Adds a comment before the next frame.\n\
00167       --extension N D           Adds an extension number N with data D.\n\
00168   -n, --name TEXT               Sets next frame's name.\n\
00169 \n\
00170 Animation options: Also --no-OPTION and --same-OPTION.\n\
00171   -d, --delay TIME              Sets frame delay to TIME (in 1/100sec).\n\
00172   -D, --disposal METHOD         Sets frame disposal to METHOD.\n\
00173   -l, --loopcount[=N]           Sets loop extension to N (default forever).\n\
00174   -O, --optimize[=LEV]          Optimize output GIFs.\n\
00175   -U, --unoptimize              Unoptimize input GIFs.\n\
00176 \n");
00177   printf("\
00178 Whole-GIF options: Also --no-OPTION.\n\
00179       --careful                 Write larger GIFs that avoid bugs in other\n\
00180                                 programs.\n\
00181       --change-color COL1 COL2  Changes COL1 to COL2 throughout.\n\
00182   -k, --colors N                Reduces the number of colors to N.\n\
00183       --color-method METHOD     Set method for choosing reduced colors.\n\
00184   -f, --dither                  Dither image after changing colormap.\n\
00185       --resize WxH              Resizes the output GIF to WxH.\n\
00186       --resize-width W          Resizes to width W and proportional height.\n\
00187       --resize-height H         Resizes to height H and proportional width.\n\
00188       --scale XFACTOR[xYFACTOR] Scales the output GIF by XFACTORxYFACTOR.\n\
00189       --transform-colormap CMD  Transform each output colormap by shell CMD.\n\
00190       --use-colormap CMAP       Set output GIF's colormap to CMAP, which can\n\
00191                                 be `web', `gray', `bw', or a GIF file.\n\
00192 \n\
00193 Report bugs to <eddietwo@lcs.mit.edu>.\n\
00194 Too much information? Try `%s --help | more'.\n", program_name);
00195 #ifdef GIF_UNGIF
00196   printf("\
00197 This version of Gifsicle writes uncompressed GIFs, which can be far larger\n\
00198 than compressed GIFs. See http://www.lcdf.org/gifsicle for more information.\n");
00199 #endif
00200 }

void verbose_close char    close
 

Definition at line 222 of file support.c.

References close(), and verbose_pos.

Referenced by input_done(), input_stream(), merge_and_write_frames(), and read_colormap_file().

00223 {
00224   fputc(close, stderr);
00225   verbose_pos++;
00226 }

void verbose_endline void   
 

Definition at line 230 of file support.c.

References verbose_pos.

Referenced by clp_error_handler(), image_info(), main(), stream_info(), and verror().

00231 {
00232   if (verbose_pos) {
00233     fputc('\n', stderr);
00234     fflush(stderr);
00235     verbose_pos = 0;
00236   }
00237 }

void verbose_open char    open,
const char *    name
 

Definition at line 204 of file support.c.

References l, name, and verbose_pos.

Referenced by input_stream(), merge_and_write_frames(), and read_colormap_file().

00205 {
00206   int l = strlen(name);
00207   if (verbose_pos && verbose_pos + 3 + l > 79) {
00208     fputc('\n', stderr);
00209     verbose_pos = 0;
00210   }
00211   if (verbose_pos) {
00212     fputc(' ', stderr);
00213     verbose_pos++;
00214   }
00215   fputc(open, stderr);
00216   fputs(name, stderr);
00217   verbose_pos += 1 + l;
00218 }

void verror int    seriousness,
char *    message,
va_list    val
[static]
 

Definition at line 26 of file support.c.

References error_count, program_name, and verbose_endline().

Referenced by error(), fatal_error(), warncontext(), and warning().

00027 {
00028   char pattern[BUFSIZ];
00029   char buffer[BUFSIZ];
00030   verbose_endline();
00031   
00032   if (seriousness > 2)
00033     sprintf(pattern, "%s: fatal error: %%s\n", program_name);
00034   else if (seriousness == 1)
00035     sprintf(pattern, "%s: warning: %%s\n", program_name);
00036   else
00037     sprintf(pattern, "%s: %%s\n", program_name);
00038   
00039   if (seriousness > 1)
00040     error_count++;
00041   else if (no_warnings)
00042     return;
00043   
00044   /* try and keep error messages together (no interleaving of error messages
00045      from two gifsicle processes in the same command line) by calling fprintf
00046      only once */
00047   if (strlen(message) + strlen(pattern) < BUFSIZ) {
00048     sprintf(buffer, pattern, message);
00049     vfprintf(stderr, buffer, val);
00050   } else {
00051     fwrite(pattern, 1, strlen(pattern) - 3, stderr);
00052     vfprintf(stderr, message, val);
00053     putc('\n', stderr);
00054   }
00055 }

void warncontext char *    message,
...   
 

Definition at line 86 of file support.c.

References verror().

Referenced by do_colormap_change(), find_background(), input_stream(), merge_colormap_if_possible(), print_useless_options(), and redundant_option_warning().

00087 {
00088   va_list val;
00089   va_start(val, message);
00090   verror(0, message, val);
00091   va_end(val);
00092 }

void warning char *    message,
...   
 

Definition at line 77 of file support.c.

References verror().

Referenced by colormap_diversity(), colormap_median_cut(), find_background(), input_stream(), merge_colormap_if_possible(), new_viewer(), parse_geometry(), pipe_color_transformer(), print_useless_options(), read_colormap_file(), and redundant_option_warning().

00078 {
00079   va_list val;
00080   va_start(val, message);
00081   verror(1, message, val);
00082   va_end(val);
00083 }

int xvalue char    c [static]
 

Definition at line 668 of file support.c.

References c.

Referenced by parse_hex_color_channel().

00669 {
00670   switch (c) {
00671    case '0': case '1': case '2': case '3': case '4':
00672    case '5': case '6': case '7': case '8': case '9':
00673     return c - '0';
00674    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
00675     return c - 'A' + 10;
00676    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
00677     return c - 'a' + 10;
00678    default:
00679     return -1;
00680   }
00681 }

Variable Documentation

int dimensions_x
 

Definition at line 478 of file support.c.

Referenced by parse_dimensions(), and parse_rectangle().

int dimensions_y
 

Definition at line 479 of file support.c.

Referenced by parse_dimensions(), and parse_rectangle().

char* disposal_names[] [static]
 

Initial value:

 {
  "none", "asis", "background", "previous", "4", "5", "6", "7"
}

Definition at line 392 of file support.c.

Referenced by image_info().

int error_count = 0
 

Definition at line 21 of file support.c.

Referenced by verror().

int frame_spec_1
 

Definition at line 475 of file support.c.

Referenced by parse_frame_spec().

int frame_spec_2
 

Definition at line 476 of file support.c.

Referenced by parse_frame_spec().

char* frame_spec_name
 

Definition at line 477 of file support.c.

Referenced by parse_frame_spec().

Gt_Frame** merger = 0 [static]
 

Definition at line 972 of file support.c.

int mergercap = 0 [static]
 

Definition at line 974 of file support.c.

Referenced by merger_add().

int nmerger = 0 [static]
 

Definition at line 973 of file support.c.

Referenced by find_background(), fix_total_crop(), merge_frame_interval(), and merger_add().

int no_warnings = 0
 

Definition at line 22 of file support.c.

Gif_Color parsed_color
 

Definition at line 482 of file support.c.

Gif_Color parsed_color2
 

Definition at line 483 of file support.c.

double parsed_scale_factor_x
 

Definition at line 484 of file support.c.

Referenced by parse_scale_factor().

double parsed_scale_factor_y
 

Definition at line 485 of file support.c.

Referenced by parse_scale_factor().

int position_x
 

Definition at line 480 of file support.c.

Referenced by parse_position(), and parse_rectangle().

int position_y
 

Definition at line 481 of file support.c.

Referenced by parse_position(), and parse_rectangle().

const char* program_name = "gifsicle"
 

Definition at line 19 of file support.c.

Referenced by short_usage(), usage(), and verror().

int verbose_pos = 0 [static]
 

Definition at line 20 of file support.c.

Referenced by verbose_close(), verbose_endline(), and verbose_open().

 

Powered by Plone

This site conforms to the following standards: