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  

gifdiff.c File Reference

#include "config.h"
#include "gif.h"
#include "clp.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

Go to the source code of this file.


Defines

#define QUIET_OPT   300
#define HELP_OPT   301
#define VERSION_OPT   302
#define TRANSP   (0)
#define SAME   0
#define DIFFERENT   1

Functions

void combine_colormaps (Gif_Colormap *gfcm, Gif_Colormap *newcm)
void fill_area (u_int16_t *data, int l, int t, int w, int h, u_int16_t val)
void apply_image (int is_second, Gif_Stream *gfs, Gif_Image *gfi)
void apply_image_disposal (int is_second, Gif_Stream *gfs, Gif_Image *gfi, u_int16_t background)
void different (const char *format,...)
void name_loopcount (int loopcount, char *buf)
void name_delay (int delay, char *buf)
void name_color (int color, Gif_Colormap *gfcm, char *buf)
int compare (Gif_Stream *s1, Gif_Stream *s2)
void short_usage (void)
void usage (void)
void fatal_error (char *message,...)
void error (char *message,...)
void warning (char *message,...)
void gifread_error (const char *message, int which_image, void *thunk)
int main (int argc, char **argv)

Variables

Clp_Option options []
const char * program_name
const char * filename1
const char * filename2
int screen_width
int screen_height
u_int16_tdata1
u_int16_tdata2
u_int16_tlast1
u_int16_tlast2
int brief
int was_different
int gifread_error_count

Define Documentation

#define DIFFERENT   1
 

Definition at line 126 of file gifdiff.c.

Referenced by compare(), and main().

#define HELP_OPT   301
 

Definition at line 19 of file gifdiff.c.

Referenced by main().

#define QUIET_OPT   300
 

Definition at line 18 of file gifdiff.c.

Referenced by main().

#define SAME   0
 

Definition at line 125 of file gifdiff.c.

Referenced by compare().

#define TRANSP   (0)
 

Definition at line 34 of file gifdiff.c.

Referenced by apply_image(), compare(), and name_color().

#define VERSION_OPT   302
 

Definition at line 20 of file gifdiff.c.

Referenced by main().


Function Documentation

void apply_image int    is_second,
Gif_Stream   gfs,
Gif_Image   gfi
[static]
 

Definition at line 68 of file gifdiff.c.

References Gif_Colormap::col, data1, data2, Gif_Image::disposal, Gif_ClipImage(), GIF_DISPOSAL_PREVIOUS, Gif_ReleaseCompressedImage(), Gif_ReleaseUncompressedImage(), Gif_UncompressImage, Gif_Stream::global, Gif_Image::height, i, Gif_Image::img, ind, last1, last2, Gif_Image::left, Gif_Image::local, Gif_Colormap::ncol, screen_height, screen_width, Gif_Image::top, TRANSP, Gif_Image::transparent, u_int16_t, and Gif_Image::width.

Referenced by compare().

00069 {
00070   int i, x, y;
00071   int width = gfi->width;
00072   u_int16_t map[256];
00073   u_int16_t *data = (is_second ? data2 : data1);
00074   u_int16_t *last = (is_second ? last2 : last1);
00075   Gif_Colormap *gfcm = gfi->local ? gfi->local : gfs->global;
00076   
00077   /* set up colormap */
00078   for (i = 0; i < 256; i++)
00079     map[i] = 1;
00080   if (gfs)
00081     for (i = 0; i < gfcm->ncol; i++)
00082       map[i] = gfcm->col[i].pixel;
00083   if (gfi->transparent >= 0 && gfi->transparent < 256)
00084     map[gfi->transparent] = TRANSP;
00085   
00086   /* copy image over */
00087   Gif_UncompressImage(gfi);
00088   Gif_ClipImage(gfi, 0, 0, screen_width, screen_height);
00089   for (y = 0; y < gfi->height; y++) {
00090     u_int16_t *outd = data + screen_width * (y + gfi->top) + gfi->left;
00091     byte *ind = gfi->img[y];
00092     if (gfi->disposal == GIF_DISPOSAL_PREVIOUS)
00093       memcpy(last + screen_width * y + gfi->left, outd,
00094              sizeof(u_int16_t) * width);
00095     for (x = 0; x < width; x++, outd++, ind++)
00096       if (map[*ind] != TRANSP)
00097         *outd = map[*ind];
00098   }
00099   Gif_ReleaseUncompressedImage(gfi);
00100   Gif_ReleaseCompressedImage(gfi);
00101 }

void apply_image_disposal int    is_second,
Gif_Stream   gfs,
Gif_Image   gfi,
u_int16_t    background
[static]
 

Definition at line 104 of file gifdiff.c.

References data1, data2, Gif_Image::disposal, GIF_DISPOSAL_BACKGROUND, GIF_DISPOSAL_PREVIOUS, Gif_Image::height, last1, last2, Gif_Image::left, screen_width, Gif_Image::top, u_int16_t, and Gif_Image::width.

Referenced by compare().

00106 {
00107   int x, y, width = gfi->width;
00108   u_int16_t *data = (is_second ? data2 : data1);
00109   u_int16_t *last = (is_second ? last2 : last1);
00110   
00111   if (gfi->disposal == GIF_DISPOSAL_PREVIOUS)
00112     for (y = gfi->top; y < gfi->top + gfi->height; y++)
00113       memcpy(data + screen_width * y + gfi->left,
00114              last + screen_width * y + gfi->left,
00115              sizeof(u_int16_t) * width);
00116   else if (gfi->disposal == GIF_DISPOSAL_BACKGROUND)
00117     for (y = gfi->top; y < gfi->top + gfi->height; y++) {
00118       u_int16_t *d = data + screen_width * y + gfi->left;
00119       for (x = 0; x < gfi->width; x++)
00120         *d++ = background;
00121     }
00122 }

void combine_colormaps Gif_Colormap   gfcm,
Gif_Colormap   newcm
[static]
 

Definition at line 45 of file gifdiff.c.

References c, Gif_Colormap::col, Gif_AddColor(), i, Gif_Colormap::ncol, and Gif_Color::pixel.

Referenced by compare().

00046 {
00047   int i;
00048   if (!gfcm) return;
00049   for (i = 0; i < gfcm->ncol; i++) {
00050     Gif_Color *c = &gfcm->col[i];
00051     c->pixel = Gif_AddColor(newcm, c, 1);
00052   }
00053 }

int compare Gif_Stream   s1,
Gif_Stream   s2
 

Definition at line 176 of file gifdiff.c.

References apply_image(), apply_image_disposal(), Gif_Stream::background, c, Gif_Colormap::col, combine_colormaps(), data1, data2, Gif_Image::delay, DIFFERENT, different(), fill_area(), Gif_CalculateScreenSize(), Gif_DeleteArray, Gif_DeleteColormap(), Gif_NewArray, Gif_NewFullColormap(), Gif_Stream::global, Gif_Stream::images, last1, last2, Gif_Image::local, Gif_Stream::loopcount, memcmp(), name_color(), name_delay(), name_loopcount(), Gif_Stream::nimages, s2, SAME, screen_height, Gif_Stream::screen_height, screen_width, Gif_Stream::screen_width, TRANSP, Gif_Image::transparent, u_int16_t, and was_different.

00177 {
00178   Gif_Colormap *newcm;
00179   int imageno, background1, background2;
00180   char buf1[256], buf2[256];
00181   
00182   was_different = 0;
00183 
00184   /* Compare image counts and screen sizes. If either of these differs, quit
00185      early. */
00186   Gif_CalculateScreenSize(s1, 0);
00187   Gif_CalculateScreenSize(s2, 0);
00188   
00189   if (s1->nimages != s2->nimages)
00190     different("frame counts differ: <%d >%d", s1->nimages, s2->nimages);
00191   if (s1->screen_width != s2->screen_width
00192       || s1->screen_height != s2->screen_height)
00193     different("screen sizes differ: <%dx%d >%dx%d", s1->screen_width,
00194               s1->screen_height, s2->screen_width, s2->screen_height);
00195 
00196   if (was_different)
00197     return DIFFERENT;
00198   else if (s1->nimages == 0)
00199     return SAME;
00200 
00201   /* Create arrays for the image data */
00202   screen_width = s1->screen_width;
00203   screen_height = s1->screen_height;
00204   
00205   data1 = Gif_NewArray(u_int16_t, screen_width * screen_height);
00206   data2 = Gif_NewArray(u_int16_t, screen_width * screen_height);
00207   last1 = Gif_NewArray(u_int16_t, screen_width * screen_height);
00208   last2 = Gif_NewArray(u_int16_t, screen_width * screen_height);
00209 
00210   /* Merge all distinct colors from the two images into one colormap, setting
00211      the `pixel' slots in the images' colormaps to the corresponding values
00212      in the merged colormap. Don't forget transparency */
00213   newcm = Gif_NewFullColormap(1, 256);
00214   combine_colormaps(s1->global, newcm);
00215   combine_colormaps(s2->global, newcm);
00216   for (imageno = 0; imageno < s1->nimages; imageno++) {
00217     combine_colormaps(s1->images[imageno]->local, newcm);
00218     combine_colormaps(s2->images[imageno]->local, newcm);
00219   }
00220   
00221   /* Choose the background values and clear the image data arrays */
00222   if (s1->images[0]->transparent >= 0 || !s1->global)
00223     background1 = TRANSP;
00224   else
00225     background1 = s1->global->col[ s1->background ].pixel;
00226   
00227   if (s2->images[0]->transparent >= 0 || !s2->global)
00228     background2 = TRANSP;
00229   else
00230     background2 = s2->global->col[ s2->background ].pixel;
00231   
00232   fill_area(data1, 0, 0, screen_width, screen_height, background1);
00233   fill_area(data2, 0, 0, screen_width, screen_height, background2);
00234   
00235   /* Loopcounts differ? */
00236   if (s1->loopcount != s2->loopcount) {
00237     name_loopcount(s1->loopcount, buf1);
00238     name_loopcount(s2->loopcount, buf2);
00239     different("loop counts differ: <%s >%s", buf1, buf2);
00240   }
00241   
00242   /* Loop over frames, comparing image data and delays */
00243   for (imageno = 0; imageno < s1->nimages; imageno++) {
00244     Gif_Image *gfi1 = s1->images[imageno], *gfi2 = s2->images[imageno];
00245     apply_image(0, s1, gfi1);
00246     apply_image(1, s2, gfi2);
00247     
00248     if (memcmp(data1, data2, screen_width * screen_height * sizeof(u_int16_t))
00249         != 0) {
00250       int d, c = screen_width * screen_height;
00251       u_int16_t *d1 = data1, *d2 = data2;
00252       for (d = 0; d < c; d++, d1++, d2++)
00253         if (*d1 != *d2) {
00254           name_color(*d1, newcm, buf1);
00255           name_color(*d2, newcm, buf2);
00256           different("frame #%d pixels differ: %d,%d <%s >%s",
00257                     imageno, d % screen_width, d / screen_width, buf1, buf2);
00258           break;
00259         }
00260     }
00261     
00262     if (gfi1->delay != gfi2->delay) {
00263       name_delay(gfi1->delay, buf1);
00264       name_delay(gfi2->delay, buf2);
00265       different("frame #%d delays differ: <%s >%s", imageno, buf1, buf2);
00266     }
00267     
00268     apply_image_disposal(0, s1, gfi1, background1);
00269     apply_image_disposal(1, s2, gfi2, background2);
00270   }
00271 
00272   /* That's it! */
00273   Gif_DeleteColormap(newcm);
00274   Gif_DeleteArray(data1);
00275   Gif_DeleteArray(data2);
00276   Gif_DeleteArray(last1);
00277   Gif_DeleteArray(last2);
00278   
00279   return was_different ? DIFFERENT : SAME;
00280 }

void different const char *    format,
...   
[static]
 

Definition at line 130 of file gifdiff.c.

References brief, format, and was_different.

Referenced by compare().

00131 {
00132   va_list val;
00133   va_start(val, format);
00134   if (!brief) {
00135     vfprintf(stderr, format, val);
00136     fputc('\n', stderr);
00137   }
00138   va_end(val);
00139   was_different = 1;
00140 }

void error char *    message,
...   
 

Definition at line 323 of file gifdiff.c.

References program_name.

00324 {
00325   va_list val;
00326   va_start(val, message);
00327   fprintf(stderr, "%s: ", program_name);
00328   vfprintf(stderr, message, val);
00329   fputc('\n', stderr);
00330 }

void fatal_error char *    message,
...   
 

Definition at line 312 of file gifdiff.c.

References program_name.

00313 {
00314   va_list val;
00315   va_start(val, message);
00316   fprintf(stderr, "%s: ", program_name);
00317   vfprintf(stderr, message, val);
00318   fputc('\n', stderr);
00319   exit(2);                      /* exit(2) for trouble */
00320 }

void fill_area u_int16_t   data,
int    l,
int    t,
int    w,
int    h,
u_int16_t    val
[static]
 

Definition at line 56 of file gifdiff.c.

References l, screen_width, and u_int16_t.

Referenced by compare().

00057 {
00058   int x, y;
00059   for (y = t; y < t+h; y++) {
00060     u_int16_t *d = data + screen_width * y + l;
00061     for (x = 0; x < w; x++)
00062       *d++ = val;
00063   }
00064 }

void gifread_error const char *    message,
int    which_image,
void *    thunk
[static]
 

Definition at line 345 of file gifdiff.c.

References error(), and gifread_error_count.

Referenced by main().

00346 {
00347   static int last_which_image = 0;
00348   static const char *last_message = 0;
00349   static int different_error_count = 0;
00350   static int same_error_count = 0;
00351   const char *filename = (const char *)thunk;
00352   
00353   if (gifread_error_count == 0) {
00354     last_which_image = -1;
00355     different_error_count = 0;
00356   }
00357   
00358   gifread_error_count++;
00359   if (last_message && different_error_count <= 10
00360       && (message != last_message || last_which_image != which_image)) {
00361     if (same_error_count == 1)
00362       error("  %s", last_message);
00363     else if (same_error_count > 0)
00364       error("  %s (%d times)", last_message, same_error_count);
00365     same_error_count = 0;
00366   }
00367 
00368   if (message != last_message)
00369     different_error_count++;
00370   
00371   same_error_count++;
00372   last_message = message;
00373   if (last_which_image != which_image && different_error_count <= 10
00374       && message) {
00375     error("Error while reading `%s' frame #%d:", filename, which_image);
00376     last_which_image = which_image;
00377   }
00378   
00379   if (different_error_count == 11 && message)
00380     error("(more errors while reading `%s')", filename);
00381 }

int main int    argc,
char **    argv
 

Definition at line 385 of file gifdiff.c.

References Clp_Parser::arg, argc, brief, Clp_BadOption, Clp_Done, Clp_NewParser(), Clp_Next(), Clp_NotOption, Clp_ProgramName(), compare(), DIFFERENT, dmalloc_report(), error(), fatal_error(), filename1, filename2, Gif_DeleteStream(), Gif_FullReadFile(), GIF_READ_COMPRESSED, gifread_error(), gifread_error_count, HELP_OPT, Clp_Parser::negated, program_name, QUIET_OPT, short_usage(), strerror(), usage(), and VERSION_OPT.

00386 {
00387   int how_many_inputs = 0;
00388   int status;
00389   const char **inputp;
00390   FILE *f1, *f2;
00391   Gif_Stream *gfs1, *gfs2;
00392   
00393   Clp_Parser *clp =
00394     Clp_NewParser(argc, argv, sizeof(options) / sizeof(options[0]), options);
00395   
00396   program_name = Clp_ProgramName(clp);
00397   brief = 0;
00398   
00399   while (1) {
00400     int opt = Clp_Next(clp);
00401     switch (opt) {
00402       
00403      case HELP_OPT:
00404       usage();
00405       exit(0);
00406       break;
00407       
00408      case VERSION_OPT:
00409       printf("gifdiff (LCDF Gifsicle) %s\n", VERSION);
00410       printf("Copyright (C) 1998-2001 Eddie Kohler\n\
00411 This is free software; see the source for copying conditions.\n\
00412 There is NO warranty, not even for merchantability or fitness for a\n\
00413 particular purpose.\n");
00414       exit(0);
00415       break;
00416       
00417      case QUIET_OPT:
00418       brief = !clp->negated;
00419       break;
00420       
00421      case Clp_NotOption:
00422       if (how_many_inputs == 2) {
00423         error("too many file arguments");
00424         goto bad_option;
00425       }
00426       inputp = (how_many_inputs == 0 ? &filename1 : &filename2);
00427       how_many_inputs++;
00428       if (strcmp(clp->arg, "-") == 0)
00429         *inputp = 0;
00430       else
00431         *inputp = clp->arg;
00432       break;
00433 
00434      bad_option:
00435      case Clp_BadOption:
00436       short_usage();
00437       exit(1);
00438       break;
00439       
00440      case Clp_Done:
00441       goto done;
00442       
00443     }
00444   }
00445   
00446  done:
00447   
00448   if (how_many_inputs < 2)
00449     fatal_error("need exactly 2 file arguments");
00450   if (filename1 == 0 && filename2 == 0)
00451     fatal_error("can't read both files from stdin");
00452   
00453   if (filename1 == 0) {
00454     f1 = stdin;
00455     filename1 = "<stdin>";
00456   } else {
00457     f1 = fopen(filename1, "rb");
00458     if (!f1)
00459       fatal_error("%s: %s", filename1, strerror(errno));
00460   }
00461   gifread_error_count = 0;
00462   gfs1 = Gif_FullReadFile(f1, GIF_READ_COMPRESSED, gifread_error, (void *)filename1);
00463   gifread_error(0, -1, (void *)filename1); /* print out last error message */
00464   if (!gfs1)
00465     fatal_error("`%s' doesn't seem to contain a GIF", filename1);
00466   
00467   if (filename2 == 0) {
00468     f2 = stdin;
00469     filename2 = "<stdin>";
00470   } else {
00471     f2 = fopen(filename2, "rb");
00472     if (!f2)
00473       fatal_error("%s: %s", filename2, strerror(errno));
00474   }
00475   gifread_error_count = 0;
00476   gfs2 = Gif_FullReadFile(f2, GIF_READ_COMPRESSED, gifread_error, (void *)filename2);
00477   gifread_error(0, -1, (void *)filename2); /* print out last error message */
00478   if (!gfs2) fatal_error("`%s' doesn't seem to contain a GIF", filename2);
00479   
00480   status = (compare(gfs1, gfs2) == DIFFERENT);
00481   if (status == 1 && brief)
00482     printf("GIF files %s and %s differ\n", filename1, filename2);
00483 
00484   Gif_DeleteStream(gfs1);
00485   Gif_DeleteStream(gfs2);
00486 #ifdef DMALLOC
00487   dmalloc_report();
00488 #endif
00489   return status;
00490 }

void name_color int    color,
Gif_Colormap   gfcm,
char *    buf
[static]
 

Definition at line 164 of file gifdiff.c.

References Gif_Color::blue, c, Gif_Colormap::col, color, Gif_Color::green, Gif_Color::red, and TRANSP.

Referenced by compare().

00165 {
00166   if (color == TRANSP)
00167     strcpy(buf, "transparent");
00168   else {
00169     Gif_Color *c = &gfcm->col[color];
00170     sprintf(buf, "#%02X%02X%02X", c->red, c->green, c->blue);
00171   }
00172 }

void name_delay int    delay,
char *    buf
[static]
 

Definition at line 155 of file gifdiff.c.

Referenced by compare().

00156 {
00157   if (delay == 0)
00158     strcpy(buf, "none");
00159   else
00160     sprintf(buf, "%d.%02ds", delay / 100, delay % 100);
00161 }

void name_loopcount int    loopcount,
char *    buf
[static]
 

Definition at line 144 of file gifdiff.c.

References loopcount.

Referenced by compare().

00145 {
00146   if (loopcount < 0)
00147     strcpy(buf, "none");
00148   else if (loopcount == 0)
00149     strcpy(buf, "forever");
00150   else
00151     sprintf(buf, "%d", loopcount);
00152 }

void short_usage void   
 

Definition at line 284 of file gifdiff.c.

References program_name.

Referenced by main().

00285 {
00286   fprintf(stderr, "Usage: %s [OPTION]... FILE1 FILE2\n\
00287 Try `%s --help' for more information.\n",
00288           program_name, program_name);
00289 }

void usage void   
 

Definition at line 292 of file gifdiff.c.

References program_name.

Referenced by get_options(), init_options(), main(), parse_switches(), select_file_type(), select_transform(), set_params(), and validate_options().

00293 {
00294   printf("\
00295 `Gifdiff' compares two GIF files (either images or animations) for identical\n\
00296 visual appearance. An animation and an optimized version of the same animation\n\
00297 should compare as the same. Gifdiff exits with status 0 if the images are\n\
00298 the same, 1 if they're different, and 2 if there was some error.\n\
00299 \n\
00300 Usage: %s [OPTION]... FILE1 FILE2\n\
00301 \n\
00302 Options:\n\
00303   -q, --brief                   Don't report detailed differences.\n\
00304   -h, --help                    Print this message and exit.\n\
00305   -v, --version                 Print version number and exit.\n\
00306 \n\
00307 Report bugs to <eddietwo@lcs.mit.edu>.\n", program_name);
00308 }

void warning char *    message,
...   
 

Definition at line 333 of file gifdiff.c.

References program_name.

00334 {
00335   va_list val;
00336   va_start(val, message);
00337   fprintf(stderr, "%s: warning: ", program_name);
00338   vfprintf(stderr, message, val);
00339   fputc('\n', stderr);
00340 }

Variable Documentation

int brief [static]
 

Definition at line 41 of file gifdiff.c.

Referenced by different(), and main().

u_int16_t* data1 [static]
 

Definition at line 36 of file gifdiff.c.

Referenced by apply_image(), apply_image_disposal(), and compare().

u_int16_t* data2 [static]
 

Definition at line 37 of file gifdiff.c.

Referenced by apply_image(), apply_image_disposal(), and compare().

const char* filename1 [static]
 

Definition at line 30 of file gifdiff.c.

Referenced by main().

const char* filename2 [static]
 

Definition at line 31 of file gifdiff.c.

Referenced by main().

int gifread_error_count [static]
 

Definition at line 342 of file gifdiff.c.

Referenced by gifread_error(), and main().

u_int16_t* last1 [static]
 

Definition at line 38 of file gifdiff.c.

Referenced by apply_image(), apply_image_disposal(), and compare().

u_int16_t* last2 [static]
 

Definition at line 39 of file gifdiff.c.

Referenced by apply_image(), apply_image_disposal(), and compare().

Clp_Option options[]
 

Initial value:

 {
  { "help", 'h', HELP_OPT, 0, 0 },
  { "brief", 'q', QUIET_OPT, 0, Clp_Negate },
  { "version", 'v', VERSION_OPT, 0, 0 },
}

Definition at line 22 of file gifdiff.c.

const char* program_name [static]
 

Definition at line 28 of file gifdiff.c.

Referenced by error(), fatal_error(), main(), short_usage(), usage(), and warning().

int screen_height [static]
 

Definition at line 33 of file gifdiff.c.

Referenced by apply_image(), and compare().

int screen_width [static]
 

Definition at line 33 of file gifdiff.c.

Referenced by apply_image(), apply_image_disposal(), compare(), and fill_area().

int was_different [static]
 

Definition at line 127 of file gifdiff.c.

Referenced by compare(), and different().

 

Powered by Plone

This site conforms to the following standards: