int Gif_FullUnoptimize(Gif_Stream *gfs, int flags) { int ok = 1; int i; unsigned pos, size; uint16_t *screen; uint16_t background; Gif_Image *gfi; if (gfs->nimages < 1) return 1; for (i = 0; i < gfs->nimages; i++) if (gfs->images[i]->local) return 0; if (!gfs->global) return 0; Gif_CalculateScreenSize(gfs, 0); size = gfs->screen_width * gfs->screen_height; screen = Gif_NewArray(uint16_t, size); gfi = gfs->images[0]; if (gfi->transparent < 0 && gfs->global && gfs->background < gfs->global->ncol) background = gfs->background; else background = TRANSPARENT; for (pos = 0; pos != size; ++pos) screen[pos] = background; for (i = 0; i < gfs->nimages; i++) if (!unoptimize_image(gfs, gfs->images[i], screen)) ok = 0; if (ok) { if (flags & GIF_UNOPTIMIZE_SIMPLEST_DISPOSAL) { /* set disposal based on use of transparency. If (every transparent pixel in frame i is also transparent in frame i - 1), then frame i - 1 gets disposal ASIS; otherwise, disposal BACKGROUND. */ for (i = 0; i < gfs->nimages; ++i) if (i == gfs->nimages - 1 || no_more_transparency(gfs->images[i+1], gfs->images[i])) gfs->images[i]->disposal = GIF_DISPOSAL_NONE; else gfs->images[i]->disposal = GIF_DISPOSAL_BACKGROUND; } else for (i = 0; i < gfs->nimages; ++i) gfs->images[i]->disposal = GIF_DISPOSAL_BACKGROUND; } Gif_DeleteArray(screen); return ok; }
int compare(Gif_Stream *s1, Gif_Stream *s2) { Gif_Colormap *newcm; int imageno1, imageno2, background1, background2; char buf1[256], buf2[256], fbuf[256]; was_different = 0; /* Compare image counts and screen sizes. If either of these differs, quit early. */ Gif_CalculateScreenSize(s1, 0); Gif_CalculateScreenSize(s2, 0); if (s1->nimages != s2->nimages && (s1->nimages == 0 || s2->nimages == 0)) { different("frame counts differ: <#%d >#%d", s1->nimages, s2->nimages); return DIFFERENT; } if (s1->screen_width != s2->screen_width || s1->screen_height != s2->screen_height) { different("screen sizes differ: <%dx%d >%dx%d", s1->screen_width, s1->screen_height, s2->screen_width, s2->screen_height); return DIFFERENT; } if (s1->screen_width == 0 || s1->screen_height == 0 || s2->screen_width == 0 || s2->screen_height == 0) { /* paranoia -- don't think this can happen */ different("zero screen sizes"); return DIFFERENT; } /* Create arrays for the image data */ screen_width = s1->screen_width; screen_height = s1->screen_height; gdata[0] = Gif_NewArray(uint16_t, screen_width * screen_height); gdata[1] = Gif_NewArray(uint16_t, screen_width * screen_height); glast[0] = Gif_NewArray(uint16_t, screen_width * screen_height); glast[1] = Gif_NewArray(uint16_t, screen_width * screen_height); scratch = Gif_NewArray(uint16_t, screen_width * screen_height); line = Gif_NewArray(uint16_t, screen_width); /* Merge all distinct colors from the two images into one colormap, setting the 'pixel' slots in the images' colormaps to the corresponding values in the merged colormap. Don't forget transparency */ newcm = Gif_NewFullColormap(1, 256); combine_colormaps(s1->global, newcm); combine_colormaps(s2->global, newcm); for (imageno1 = 0; imageno1 < s1->nimages; ++imageno1) combine_colormaps(s1->images[imageno1]->local, newcm); for (imageno2 = 0; imageno2 < s2->nimages; ++imageno2) combine_colormaps(s2->images[imageno2]->local, newcm); /* Choose the background values and clear the image data arrays */ if (s1->images[0]->transparent >= 0 || !s1->global) background1 = TRANSP; else background1 = s1->global->col[ s1->background ].pixel; if (s2->images[0]->transparent >= 0 || !s2->global) background2 = TRANSP; else background2 = s2->global->col[ s2->background ].pixel; fill_area(gdata[0], 0, 0, screen_width, screen_height, background1); fill_area(gdata[1], 0, 0, screen_width, screen_height, background2); /* Loopcounts differ? */ if (s1->loopcount != s2->loopcount) { name_loopcount(s1->loopcount, buf1); name_loopcount(s2->loopcount, buf2); different("loop counts differ: <%s >%s", buf1, buf2); } /* Loop over frames, comparing image data and delays */ apply_image(0, s1, 0, background1); apply_image(1, s2, 0, background2); imageno1 = imageno2 = 0; while (imageno1 != s1->nimages && imageno2 != s2->nimages) { int fi1 = imageno1, fi2 = imageno2, delay1 = s1->images[fi1]->delay, delay2 = s2->images[fi2]->delay; /* get message right */ if (imageno1 == imageno2) sprintf(fbuf, "#%d", imageno1); else sprintf(fbuf, "<#%d >#%d", imageno1, imageno2); /* compare pixels */ if (memcmp(gdata[0], gdata[1], screen_width * screen_height * sizeof(uint16_t)) != 0) { unsigned d, c = screen_width * screen_height; uint16_t *d1 = gdata[0], *d2 = gdata[1]; for (d = 0; d < c; d++, d1++, d2++) if (*d1 != *d2) { name_color(*d1, newcm, buf1); name_color(*d2, newcm, buf2); different("frame %s pixels differ: %d,%d <%s >%s", fbuf, d % screen_width, d / screen_width, buf1, buf2); break; } } /* move to next images, skipping redundancy */ for (++imageno1; imageno1 < s1->nimages && !apply_image(0, s1, imageno1, background1); ++imageno1) delay1 += s1->images[imageno1]->delay; for (++imageno2; imageno2 < s2->nimages && !apply_image(1, s2, imageno2, background2); ++imageno2) delay2 += s2->images[imageno2]->delay; if (!ignore_redundancy) { fi1 = (imageno1 - fi1) - (imageno2 - fi2); for (; fi1 > 0; --fi1) different("extra redundant frame: <#%d", imageno1 - fi1); for (; fi1 < 0; ++fi1) different("extra redundant frame: >#%d", imageno2 + fi1); } if (delay1 != delay2) { name_delay(delay1, buf1); name_delay(delay2, buf2); different("frame %s delays differ: <%s >%s", fbuf, buf1, buf2); } } if (imageno1 != s1->nimages || imageno2 != s2->nimages) different("frame counts differ: <#%d >#%d", s1->nimages, s2->nimages); /* That's it! */ Gif_DeleteColormap(newcm); Gif_DeleteArray(gdata[0]); Gif_DeleteArray(gdata[1]); Gif_DeleteArray(glast[0]); Gif_DeleteArray(glast[1]); Gif_DeleteArray(scratch); Gif_DeleteArray(line); return was_different ? DIFFERENT : SAME; }
static int initialize_optimizer(Gif_Stream *gfs) { int i; if (gfs->nimages < 1) return 0; /* combine colormaps */ all_colormap = Gif_NewFullColormap(1, 384); all_colormap->col[0].gfc_red = 255; all_colormap->col[0].gfc_green = 255; all_colormap->col[0].gfc_blue = 255; in_global_map = gfs->global; if (!in_global_map) { Gif_Color *col; in_global_map = Gif_NewFullColormap(256, 256); col = in_global_map->col; for (i = 0; i < 256; i++, col++) col->gfc_red = col->gfc_green = col->gfc_blue = i; } { int any_globals = 0; int first_transparent = -1; kchist_init(&all_colormap_hist); for (i = 0; i < gfs->nimages; i++) { Gif_Image *gfi = gfs->images[i]; if (gfi->local) all_colormap_add(gfi->local); else any_globals = 1; if (gfi->transparent >= 0 && first_transparent < 0) first_transparent = i; } if (any_globals) all_colormap_add(in_global_map); kchist_cleanup(&all_colormap_hist); /* try and maintain transparency's pixel value */ if (first_transparent >= 0) { Gif_Image *gfi = gfs->images[first_transparent]; Gif_Colormap *gfcm = gfi->local ? gfi->local : gfs->global; all_colormap->col[TRANSP] = gfcm->col[gfi->transparent]; } } /* find screen_width and screen_height, and clip all images to screen */ Gif_CalculateScreenSize(gfs, 0); screen_width = gfs->screen_width; screen_height = gfs->screen_height; for (i = 0; i < gfs->nimages; i++) Gif_ClipImage(gfs->images[i], 0, 0, screen_width, screen_height); /* choose background */ if (gfs->images[0]->transparent < 0 && gfs->global && gfs->background < in_global_map->ncol) background = in_global_map->col[gfs->background].pixel; else background = TRANSP; return 1; }
static int initialize_optimizer(Gif_Stream *gfs) { int i; unsigned screen_size; if (gfs->nimages < 1) return 0; /* combine colormaps */ all_colormap = Gif_NewFullColormap(1, 384); all_colormap->col[0].gfc_red = 255; all_colormap->col[0].gfc_green = 255; all_colormap->col[0].gfc_blue = 255; in_global_map = gfs->global; if (!in_global_map) { Gif_Color *col; in_global_map = Gif_NewFullColormap(256, 256); col = in_global_map->col; for (i = 0; i < 256; i++, col++) col->gfc_red = col->gfc_green = col->gfc_blue = i; } { int any_globals = 0; int first_transparent = -1; for (i = 0; i < gfs->nimages; i++) { Gif_Image *gfi = gfs->images[i]; if (gfi->local) colormap_combine(all_colormap, gfi->local); else any_globals = 1; if (gfi->transparent >= 0 && first_transparent < 0) first_transparent = i; } if (any_globals) colormap_combine(all_colormap, in_global_map); /* try and maintain transparency's pixel value */ if (first_transparent >= 0) { Gif_Image *gfi = gfs->images[first_transparent]; Gif_Colormap *gfcm = gfi->local ? gfi->local : gfs->global; all_colormap->col[TRANSP] = gfcm->col[gfi->transparent]; } } /* find screen_width and screen_height, and clip all images to screen */ Gif_CalculateScreenSize(gfs, 0); screen_width = gfs->screen_width; screen_height = gfs->screen_height; for (i = 0; i < gfs->nimages; i++) Gif_ClipImage(gfs->images[i], 0, 0, screen_width, screen_height); /* create data arrays */ screen_size = (unsigned) screen_width * (unsigned) screen_height; last_data = Gif_NewArray(uint16_t, screen_size); this_data = Gif_NewArray(uint16_t, screen_size); /* set up colormaps */ gif_color_count = 2; while (gif_color_count < gfs->global->ncol && gif_color_count < 256) gif_color_count *= 2; /* choose background */ if (gfs->images[0]->transparent < 0 && gfs->background < in_global_map->ncol) background = in_global_map->col[gfs->background].pixel; else background = TRANSP; return 1; }