Doxygen Source Code Documentation
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_t * | data1 |
u_int16_t * | data2 |
u_int16_t * | last1 |
u_int16_t * | last2 |
int | brief |
int | was_different |
int | gifread_error_count |
Define Documentation
|
|
|
Definition at line 19 of file gifdiff.c. Referenced by main(). |
|
Definition at line 18 of file gifdiff.c. Referenced by main(). |
|
Definition at line 125 of file gifdiff.c. Referenced by compare(). |
|
Definition at line 34 of file gifdiff.c. Referenced by apply_image(), compare(), and name_color(). |
|
Definition at line 20 of file gifdiff.c. Referenced by main(). |
Function Documentation
|
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 } |
|
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 } |
|
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().
|
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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().
|
|
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 } |
|
Definition at line 144 of file gifdiff.c. References loopcount. Referenced by compare().
|
|
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 } |
|
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 } |
|
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
|
Definition at line 41 of file gifdiff.c. Referenced by different(), and main(). |
|
Definition at line 36 of file gifdiff.c. Referenced by apply_image(), apply_image_disposal(), and compare(). |
|
Definition at line 37 of file gifdiff.c. Referenced by apply_image(), apply_image_disposal(), and compare(). |
|
Definition at line 30 of file gifdiff.c. Referenced by main(). |
|
Definition at line 31 of file gifdiff.c. Referenced by main(). |
|
Definition at line 342 of file gifdiff.c. Referenced by gifread_error(), and main(). |
|
Definition at line 38 of file gifdiff.c. Referenced by apply_image(), apply_image_disposal(), and compare(). |
|
Definition at line 39 of file gifdiff.c. Referenced by apply_image(), apply_image_disposal(), and compare(). |
|
Initial value: { { "help", 'h', HELP_OPT, 0, 0 }, { "brief", 'q', QUIET_OPT, 0, Clp_Negate }, { "version", 'v', VERSION_OPT, 0, 0 }, } |
|
Definition at line 28 of file gifdiff.c. Referenced by error(), fatal_error(), main(), short_usage(), usage(), and warning(). |
|
Definition at line 33 of file gifdiff.c. Referenced by apply_image(), and compare(). |
|
Definition at line 33 of file gifdiff.c. Referenced by apply_image(), apply_image_disposal(), compare(), and fill_area(). |
|
Definition at line 127 of file gifdiff.c. Referenced by compare(), and different(). |