コード例 #1
0
ファイル: merge.c プロジェクト: Shenjiaqi/gifsicle
void
mark_used_colors(Gif_Stream *gfs, Gif_Image *gfi, Gt_Crop *crop,
                 int compress_immediately)
{
    Gif_Colormap *gfcm = gfi->local ? gfi->local : gfs->global;
    Gif_Color *col;
    int i, j, l, t, r, b, nleft, ncol, transp = gfi->transparent;

    /* There might not be a colormap. */
    if (!gfcm)
        return;
    col = gfcm->col;
    ncol = gfcm->ncol;

    /* Mark color used for transparency. */
    if (transp >= 0 && transp < ncol)
        col[transp].haspixel |= 2;

    /* Only mark colors until we've seen all of them. The left variable keeps
       track of how many are left. */
    for (i = nleft = 0; i < ncol; ++i)
        if (!(col[i].haspixel & 1) && i != transp)
            ++nleft;
    if (nleft == 0)
        return;

    if (gfi->img || Gif_UncompressImage(gfs, gfi) == 2)
        compress_immediately = 0;

    /* Loop over every pixel (until we've seen all colors) */
    if (crop) {
        Gt_Crop c;
        combine_crop(&c, crop, gfi);
        l = c.x;
        t = c.y;
        r = l + c.w;
        b = t + c.h;
    } else {
        l = t = 0;
        r = gfi->width;
        b = gfi->height;
    }

    for (j = t; j != b; ++j) {
        uint8_t *data = gfi->img[j] + l;
        for (i = l; i != r; ++i, ++data)
            if (*data < ncol && !(col[*data].haspixel & 1) && *data != transp) {
                col[*data].haspixel |= 1;
                --nleft;
                if (nleft == 0)
                    goto done;
            }
    }

  done:
    if (compress_immediately > 0)
        Gif_ReleaseUncompressedImage(gfi);
}
コード例 #2
0
ファイル: optimize.c プロジェクト: alexzhuustc/gifsicle
static void
apply_frame(uint16_t *dst, Gif_Stream* gfs, Gif_Image* gfi,
            int replace, int save_uncompressed)
{
  int i, y, was_compressed = 0;
  uint16_t map[256];
  Gif_Colormap *colormap = gfi->local ? gfi->local : in_global_map;
  Gif_OptBounds ob = safe_bounds(gfi);

  if (!gfi->img) {
    was_compressed = 1;
    Gif_UncompressImage(gfs, gfi);
  }

  /* make sure transparency maps to TRANSP */
  for (i = 0; i < colormap->ncol; i++)
    map[i] = colormap->col[i].pixel;
  /* out-of-bounds colors map to 0, for the sake of argument */
  for (i = colormap->ncol; i < 256; i++)
    map[i] = colormap->col[0].pixel;
  if (gfi->transparent >= 0 && gfi->transparent < 256)
    map[gfi->transparent] = TRANSP;
  else
    replace = 1;

  /* map the image */
  dst += ob.left + ob.top * (unsigned) screen_width;
  for (y = 0; y < ob.height; y++) {
    uint8_t *gfi_pointer = gfi->img[y];
    int x;

    if (replace)
      for (x = 0; x < ob.width; x++)
	dst[x] = map[gfi_pointer[x]];
    else
      for (x = 0; x < ob.width; x++) {
	uint16_t new_pixel = map[gfi_pointer[x]];
	if (new_pixel != TRANSP)
	    dst[x] = new_pixel;
      }

    dst += screen_width;
  }

  if (was_compressed && !save_uncompressed)
    Gif_ReleaseUncompressedImage(gfi);
}
コード例 #3
0
static void
finalize_optimizer(Gif_Stream *gfs, int optimize_flags)
{
  int i;

  if (background == TRANSP)
    gfs->background = (uint8_t)gfs->images[0]->transparent;

  /* 11.Mar.2010 - remove entirely transparent frames. */
  for (i = 1; i < gfs->nimages && !(optimize_flags & GT_OPT_KEEPEMPTY); ++i) {
    Gif_Image *gfi = gfs->images[i];
    if (gfi->width == 1 && gfi->height == 1 && gfi->transparent >= 0
	&& !gfi->identifier && !gfi->comment
	&& (gfi->disposal == GIF_DISPOSAL_ASIS
	    || gfi->disposal == GIF_DISPOSAL_NONE
	    || gfi->disposal == GIF_DISPOSAL_PREVIOUS)
	&& gfi->delay && gfs->images[i-1]->delay) {
      Gif_UncompressImage(gfi);
      if (gfi->img[0][0] == gfi->transparent
	  && (gfs->images[i-1]->disposal == GIF_DISPOSAL_ASIS
	      || gfs->images[i-1]->disposal == GIF_DISPOSAL_NONE)) {
	gfs->images[i-1]->delay += gfi->delay;
	Gif_DeleteImage(gfi);
	memmove(&gfs->images[i], &gfs->images[i+1], sizeof(Gif_Image *) * (gfs->nimages - i - 1));
	--gfs->nimages;
	--i;
      }
    }
  }

  /* 10.Dec.1998 - prefer GIF_DISPOSAL_NONE to GIF_DISPOSAL_ASIS. This is
     semantically "wrong" -- it's better to set the disposal explicitly than
     rely on default behavior -- but will result in smaller GIF files, since
     the graphic control extension can be left off in many cases. */
  for (i = 0; i < gfs->nimages; i++)
    if (gfs->images[i]->disposal == GIF_DISPOSAL_ASIS
	&& gfs->images[i]->delay == 0
	&& gfs->images[i]->transparent < 0)
      gfs->images[i]->disposal = GIF_DISPOSAL_NONE;

  Gif_DeleteColormap(in_global_map);
  Gif_DeleteColormap(all_colormap);

  Gif_DeleteArray(last_data);
  Gif_DeleteArray(this_data);
}
コード例 #4
0
ファイル: gifunopt.c プロジェクト: c0ns0le/nikkhokkho
static int
unoptimize_image(Gif_Stream *gfs, Gif_Image *gfi, uint16_t *screen)
{
    unsigned size = gfs->screen_width * gfs->screen_height;
    int used_transparent;
    uint8_t *new_data = Gif_NewArray(uint8_t, size);
    uint16_t *new_screen = screen;
    if (!new_data) return 0;

    /* Oops! May need to uncompress it */
    Gif_UncompressImage(gfs, gfi);
    Gif_ReleaseCompressedImage(gfi);

    if (gfi->disposal == GIF_DISPOSAL_PREVIOUS) {
        new_screen = Gif_NewArray(uint16_t, size);
        if (!new_screen) return 0;
        memcpy(new_screen, screen, size * sizeof(uint16_t));
    }

    put_image_in_screen(gfs, gfi, new_screen);
    if (!create_image_data(gfs, gfi, new_screen, new_data, &used_transparent)) {
        Gif_DeleteArray(new_data);
        return 0;
    }

    if (gfi->disposal == GIF_DISPOSAL_PREVIOUS)
        Gif_DeleteArray(new_screen);
    else if (gfi->disposal == GIF_DISPOSAL_BACKGROUND)
        put_background_in_screen(gfs, gfi, screen);

    gfi->left = 0;
    gfi->top = 0;
    gfi->width = gfs->screen_width;
    gfi->height = gfs->screen_height;
    gfi->disposal = used_transparent;
    Gif_SetUncompressedImage(gfi, new_data, Gif_Free, 0);

    return 1;
}
コード例 #5
0
ファイル: gifdiff.c プロジェクト: alexzhuustc/gifsicle
static int
apply_image(int is_second, Gif_Stream *gfs, int imageno, uint16_t background)
{
  int i, x, y, any_change;
  Gif_Image *gfi = gfs->images[imageno];
  Gif_Image *pgfi = imageno ? gfs->images[imageno - 1] : 0;
  int width = gfi->width;
  uint16_t map[256];
  uint16_t *data = gdata[is_second];
  uint16_t *last = glast[is_second];
  Gif_Colormap *gfcm = gfi->local ? gfi->local : gfs->global;

  /* set up colormap */
  for (i = 0; i < 256; i++)
    map[i] = 1;
  if (gfs)
    for (i = 0; i < gfcm->ncol; i++)
      map[i] = gfcm->col[i].pixel;
  if (gfi->transparent >= 0 && gfi->transparent < 256)
    map[gfi->transparent] = TRANSP;

  /* if this image's disposal is 'previous', save the post-disposal version in
     'scratch' */
  if (gfi->disposal == GIF_DISPOSAL_PREVIOUS) {
    copy_area(scratch, data, gfi->left, gfi->top, gfi->width, gfi->height);
    if (pgfi && pgfi->disposal == GIF_DISPOSAL_PREVIOUS)
      copy_area(scratch, last, pgfi->left, pgfi->top, pgfi->width, pgfi->height);
    else if (pgfi && pgfi->disposal == GIF_DISPOSAL_BACKGROUND)
      fill_area(scratch, pgfi->left, pgfi->top, pgfi->width, pgfi->height, background);
  }

  /* uncompress and clip */
  Gif_UncompressImage(gfs, gfi);
  Gif_ClipImage(gfi, 0, 0, screen_width, screen_height);

  any_change = imageno == 0;
  {
    int lf = 0, tp = 0, rt = 0, bt = 0;
    expand_bounds(&lf, &tp, &rt, &bt, gfi);
    if (pgfi && pgfi->disposal == GIF_DISPOSAL_PREVIOUS)
      expand_bounds(&lf, &tp, &rt, &bt, pgfi);
    else if (pgfi && pgfi->disposal == GIF_DISPOSAL_BACKGROUND) {
      expand_bounds(&lf, &tp, &rt, &bt, pgfi);
      fill_area(last, pgfi->left, pgfi->top, pgfi->width, pgfi->height, background);
    } else
      pgfi = 0;
    for (y = tp; y < bt; ++y) {
      uint16_t *outd = data + screen_width * y + lf;
      if (!any_change)
	memcpy(line, outd, (rt - lf) * sizeof(uint16_t));
      if (pgfi && y >= pgfi->top && y < pgfi->top + pgfi->height)
	memcpy(outd + pgfi->left - lf,
	       last + screen_width * y + pgfi->left,
	       pgfi->width * sizeof(uint16_t));
      if (y >= gfi->top && y < gfi->top + gfi->height) {
	uint16_t *xoutd = outd + gfi->left - lf;
	const uint8_t *ind = gfi->img[y - gfi->top];
	for (x = 0; x < width; ++x, ++ind, ++xoutd)
	  if (map[*ind] != TRANSP)
	    *xoutd = map[*ind];
      }
      if (!any_change && memcmp(line, outd, (rt - lf) * sizeof(uint16_t)) != 0)
	any_change = 1;
    }
  }

  Gif_ReleaseUncompressedImage(gfi);
  Gif_ReleaseCompressedImage(gfi);

  /* switch 'glast' with 'scratch' if necessary */
  if (gfi->disposal == GIF_DISPOSAL_PREVIOUS) {
    uint16_t *x = scratch;
    scratch = glast[is_second];
    glast[is_second] = x;
  }

  return any_change;
}