/****************************************************************************** * Interpret the command line and scan the given GIF file. * ******************************************************************************/ int main(int argc, char **argv) { int i, j, Error, NumFiles, Width, Height; char **FileName = NULL; GifByteType *RedBuffer = NULL, *GreenBuffer = NULL, *BlueBuffer = NULL, *OutputBuffer = NULL; ColorMapObject *OutputColorMap = NULL; if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifQuietPrint, &ColorFlag, &ExpNumOfColors, &HelpFlag, &NumFiles, &FileName)) != FALSE || (NumFiles > 1 && !HelpFlag)) { if (Error) GAPrintErrMsg(Error); else if (NumFiles > 1) GIF_MESSAGE("Error in command line parsing - one GIF file please."); GAPrintHowTo(CtrlStr); exit(EXIT_FAILURE); } if (HelpFlag) { fprintf(stderr, VersionStr); GAPrintHowTo(CtrlStr); exit(EXIT_SUCCESS); } ColorMapSize = 1 << ExpNumOfColors; if (NumFiles == 1) { LoadRle(*FileName, &RedBuffer, &GreenBuffer, &BlueBuffer, &Width, &Height); } else { LoadRle(NULL, &RedBuffer, &GreenBuffer, &BlueBuffer, &Width, &Height); } if ((OutputColorMap = MakeMapObject(ColorMapSize, NULL)) == NULL || (OutputBuffer = (GifByteType *) malloc(Width * Height * sizeof(GifByteType))) == NULL) GIF_EXIT("Failed to allocate memory required, aborted."); if (QuantizeBuffer(Width, Height, &ColorMapSize, RedBuffer, GreenBuffer, BlueBuffer, OutputBuffer, OutputColorMap->Colors) == GIF_ERROR) QuitGifError(NULL); free((char *) RedBuffer); free((char *) GreenBuffer); free((char *) BlueBuffer); SaveGif(OutputBuffer, OutputColorMap, ExpNumOfColors, Width, Height); return 0; }
int write_gif(const char *filename, int width, int height, char *rgb) { int i; int colormap_size = 256; GifByteType *red, *green, *blue, *buffer, *ptr; GifFileType *outfile; ColorMapObject *colormap; red = malloc(width * height * sizeof(GifByteType)); green = malloc(width * height * sizeof(GifByteType)); blue = malloc(width * height * sizeof(GifByteType)); buffer = malloc(width * height * sizeof(GifByteType)); if (red == NULL || green == NULL || blue == NULL || buffer == NULL) { fprintf(stderr, "Can't allocate memory for GIF file.\n"); return(0); } colormap = MakeMapObject(colormap_size, NULL); for (i = 0; i < width * height; i++) { red[i] = (GifByteType) rgb[3*i ]; green[i] = (GifByteType) rgb[3*i+1]; blue[i] = (GifByteType) rgb[3*i+2]; } if (QuantizeBuffer(width, height, &colormap_size, red, green, blue, buffer, colormap->Colors) == GIF_ERROR) { PrintGifError(); return(0); } free(red); free(green); free(blue); outfile = EGifOpenFileName((char *) filename, FALSE); if (outfile == NULL) { PrintGifError(); return(0); } if (EGifPutScreenDesc(outfile, width, height, colormap_size, 0, colormap) == GIF_ERROR) { PrintGifError(); return(0); } if (EGifPutImageDesc(outfile, 0, 0, width, height, FALSE, NULL) == GIF_ERROR) { PrintGifError(); return(0); } ptr = buffer; for (i = 0; i < height; i++) { if (EGifPutLine(outfile, ptr, width) == GIF_ERROR) { PrintGifError(); return(0); } ptr += width; } EGifSpew(outfile); if (EGifCloseFile(outfile) == GIF_ERROR) PrintGifError(); free(buffer); return(1); }
static int encode_gif_data(psx_image_header* header, psx_image_frame* frame, int idx, const ps_byte* buffer, size_t buffer_len, int* ret) { int x, y; ColorMapObject *output_map = NULL; int map_size = 256; struct gif_image_ctx* ctx = (struct gif_image_ctx*)header->priv; if ((output_map = MakeMapObject(map_size, NULL)) == NULL) { if (ret) *ret = S_FAILURE; return -1; } for (y = 0; y < header->height; y++) { ps_byte* row = (ps_byte*)(buffer + header->pitch * y); for (x = 0; x < header->width; x++) { uint32_t rgba[4] = {0}; // r, g, b, a gif_get_pixel_rgba_premultiply(header->format, row, x, rgba); ctx->red_buf[header->width * y + x] = rgba[0]; ctx->green_buf[header->width * y + x] = rgba[1]; ctx->blue_buf[header->width * y + x] = rgba[2]; } } if (QuantizeBuffer(header->width, header->height, &map_size, ctx->red_buf, ctx->green_buf, ctx->blue_buf, ctx->output_buffer, output_map->Colors) == GIF_ERROR) { FreeMapObject(output_map); if (ret) *ret = S_FAILURE; return -1; } if (frame->duration > 0) { GifByteType extension[4]; #if GIFLIB_MAJOR >= 5 GraphicsControlBlock gcb; gcb.DisposalMode = DISPOSAL_UNSPECIFIED; // FIXME: need specified ? gcb.UserInputFlag = false; gcb.DelayTime = frame->duration / 10; gcb.TransparentColor = -1; // FIXME: need specified ? EGifGCBToExtension(&gcb, extension); #else int delay = frame->duration / 10; extension[0] = 0; extension[1] = LOBYTE(delay); extension[2] = HIBYTE(delay); extension[3] = (char)-1; #endif if (EGifPutExtension(ctx->gif, GRAPHICS_EXT_FUNC_CODE, 4, extension) == GIF_ERROR) { FreeMapObject(output_map); if (ret) *ret = S_FAILURE; return -1; } } if (EGifPutImageDesc(ctx->gif, 0, 0, header->width, header->height, FALSE, output_map) == GIF_ERROR) { FreeMapObject(output_map); if (ret) *ret = S_FAILURE; return -1; } for (y = 0; y < header->height; y++) { EGifPutLine(ctx->gif, ctx->output_buffer + y * header->width, header->width); } FreeMapObject(output_map); return 0; }
void * gif_encode(Image *image, int single, int *size) { int width = image->columns; int height = image->rows; int total = width * height; GifByteType output[total]; GifByteType red[total]; GifByteType green[total]; GifByteType blue[total]; // Quantize the images using IM/GM first, to reduce // their number of colors to 256. int count = GetImageListLength(image); QuantizeInfo info; GetQuantizeInfo(&info); info.dither = 1; info.number_colors = NCOLORS; QuantizeImage(&info, image); if (count > 1) { #ifdef _MAGICK_USES_IM RemapImages(&info, image->next, image); #else MapImages(image->next, image, 0); #endif } if (!acquire_image_pixels(image, red, green, blue)) { return NULL; } Frame *frames = calloc(count, sizeof(*frames)); ColorMapObject *palette = MakeMapObject(NCOLORS, NULL); int palette_size = NCOLORS; // Quantize again using giflib, since it yields a palette which produces // better compression, reducing the file size by 20%. Note that this second // quantization is very fast, because the image already has 256 colors, so // its effect on performance is negligible. if (QuantizeBuffer(width, height, &palette_size, red, green, blue, output, palette->Colors) == GIF_ERROR) { FreeMapObject(palette); gif_frames_free(frames, count); return NULL; } frames[0].data = malloc(total); memcpy(frames[0].data, output, total); frames[0].width = width; frames[0].height = height; frames[0].duration = image->delay; GifColorType *colors = palette->Colors; Image *cur = image->next; PixelCache *cache = pixel_cache_new(); int ii; for (ii = 1; ii < count; ii++, cur = cur->next) { frames[ii].width = width; frames[ii].height = height; frames[ii].duration = cur->delay; GifPixelType *data = malloc(total); frames[ii].data = data; if (!aprox_image_pixels(cur, colors, palette_size, cache, data)) { FreeMapObject(palette); gif_frames_free(frames, count); pixel_cache_free(cache); return NULL; } } pixel_cache_free(cache); void *ret = gif_save(image, palette, frames, count, size); FreeMapObject(palette); gif_frames_free(frames, count); return ret; }