void colormap_combine(Gif_Colormap *dst, Gif_Colormap *src) { Gif_Color *src_col, *dst_col; int i, j; /* expand dst->col if necessary. This might change dst->col */ if (dst->ncol + src->ncol >= dst->capacity) { dst->capacity *= 2; Gif_ReArray(dst->col, Gif_Color, dst->capacity); } src_col = src->col; dst_col = dst->col; for (i = 0; i < src->ncol; i++, src_col++) { for (j = 1; j < dst->ncol; j++) { if (GIF_COLOREQ(src_col, &dst_col[j])) goto found; } dst_col[j] = *src_col; dst_col[j].pixel = 0; dst->ncol++; found: src_col->pixel = j; } }
static int create_image_data(Gif_Stream *gfs, Gif_Image *gfi, uint16_t *screen, uint8_t *new_data, int *used_transparent) { int have[257]; int transparent = -1; unsigned pos, size = gfs->screen_width * gfs->screen_height; uint16_t *move; int i; /* mark colors used opaquely in the image */ assert(TRANSPARENT == 256); for (i = 0; i < 257; i++) have[i] = 0; for (pos = 0, move = screen; pos != size; ++pos, move++) have[*move] = 1; /* the new transparent color is a color unused in either */ if (have[TRANSPARENT]) { for (i = 0; i < 256 && transparent < 0; i++) if (!have[i]) transparent = i; if (transparent < 0) goto error; if (transparent >= gfs->global->ncol) { Gif_ReArray(gfs->global->col, Gif_Color, 256); if (!gfs->global->col) goto error; gfs->global->ncol = transparent + 1; } } /* map the wide image onto the new data */ *used_transparent = 0; for (pos = 0, move = screen; pos != size; ++pos, move++, new_data++) if (*move == TRANSPARENT) { *new_data = transparent; *used_transparent = 1; } else *new_data = *move; gfi->transparent = transparent; return 1; error: return 0; }
static void all_colormap_add(const Gif_Colormap* src) { int i; /* expand dst->col if necessary. This might change dst->col */ if (all_colormap->ncol + src->ncol >= all_colormap->capacity) { all_colormap->capacity *= 2; Gif_ReArray(all_colormap->col, Gif_Color, all_colormap->capacity); } for (i = 0; i < src->ncol; ++i) { kchistitem* khi = kchist_add(&all_colormap_hist, kc_makegfcng(&src->col[i]), 0); if (!khi->count) { all_colormap->col[all_colormap->ncol] = src->col[i]; all_colormap->col[all_colormap->ncol].pixel = 0; khi->count = all_colormap->ncol; ++all_colormap->ncol; } src->col[i].pixel = khi->count; } }
static int read_compressed_image(Gif_Image *gfi, Gif_Reader *grr, int read_flags) { if (grr->is_record) { const uint8_t *first = grr->v; uint32_t pos; /* scan over image */ pos = 1; /* skip min code size */ while (pos < grr->w) { int amt = grr->v[pos]; pos += amt + 1; if (amt == 0) break; } if (pos > grr->w) pos = grr->w; gfi->compressed_len = pos; if (read_flags & GIF_READ_CONST_RECORD) { gfi->compressed = (uint8_t *)first; gfi->free_compressed = 0; } else { gfi->compressed = Gif_NewArray(uint8_t, gfi->compressed_len); gfi->free_compressed = Gif_Free; if (!gfi->compressed) return 0; memcpy(gfi->compressed, first, gfi->compressed_len); } /* move reader over that image */ grr->v += pos; grr->w -= pos; } else { /* non-record; have to read it block by block. */ uint32_t comp_cap = 1024; uint32_t comp_len; uint8_t *comp = Gif_NewArray(uint8_t, comp_cap); int i; if (!comp) return 0; /* min code size */ i = gifgetbyte(grr); comp[0] = i; comp_len = 1; i = gifgetbyte(grr); while (i > 0) { /* add 2 before check so we don't have to check after loop when appending 0 block */ if (comp_len + i + 2 > comp_cap) { comp_cap *= 2; Gif_ReArray(comp, uint8_t, comp_cap); if (!comp) return 0; } comp[comp_len] = i; gifgetblock(comp + comp_len + 1, i, grr); comp_len += i + 1; i = gifgetbyte(grr); } comp[comp_len++] = 0; gfi->compressed = comp; gfi->compressed_len = comp_len; gfi->free_compressed = Gif_Free; } return 1; }