/****************************************************************************** Close output file (if open), and exit. ******************************************************************************/ static void RGB2GIF(bool OneFileFlag, int NumFiles, char *FileName, int ExpNumOfColors, int Width, int Height) { int ColorMapSize; GifByteType *RedBuffer = NULL, *GreenBuffer = NULL, *BlueBuffer = NULL, *OutputBuffer = NULL; ColorMapObject *OutputColorMap = NULL; ColorMapSize = 1 << ExpNumOfColors; if (NumFiles == 1) { LoadRGB(FileName, OneFileFlag, &RedBuffer, &GreenBuffer, &BlueBuffer, Width, Height); } else { LoadRGB(NULL, OneFileFlag, &RedBuffer, &GreenBuffer, &BlueBuffer, Width, Height); } if ((OutputColorMap = GifMakeMapObject(ColorMapSize, NULL)) == NULL || (OutputBuffer = (GifByteType *) malloc(Width * Height * sizeof(GifByteType))) == NULL) GIF_EXIT("Failed to allocate memory required, aborted."); if (GifQuantizeBuffer(Width, Height, &ColorMapSize, RedBuffer, GreenBuffer, BlueBuffer, OutputBuffer, OutputColorMap->Colors) == GIF_ERROR) exit(EXIT_FAILURE); free((char *) RedBuffer); free((char *) GreenBuffer); free((char *) BlueBuffer); SaveGif(OutputBuffer, Width, Height, ExpNumOfColors, OutputColorMap); }
void * gif_encode(Image *image, int single, int *size) { int width = image->columns; int height = image->rows; int total = width * height; 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 = 0; 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; } size_t frame_size = sizeof(Frame) + total; Frame *frames = malloc(frame_size * count); ColorMapObject *palette = GifMakeMapObject(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 (GifQuantizeBuffer(width, height, &palette_size, red, green, blue, frames->data, palette->Colors) == GIF_ERROR) { GifFreeMapObject(palette); free(frames); return NULL; } frames->width = width; frames->height = height; frames->duration = image->delay; GifColorType *colors = palette->Colors; Image *cur = image->next; PixelCache *cache = pixel_cache_new(); unsigned char *p = (unsigned char*)frames; int ii; for (ii = 1; ii < count; ii++, cur = cur->next) { p += frame_size; Frame *frame = (Frame*)p; frame->width = width; frame->height = height; frame->duration = cur->delay; GifPixelType *data = frame->data; if (!aprox_image_pixels(cur, colors, palette_size, cache, data)) { GifFreeMapObject(palette); free(frames); pixel_cache_free(cache); return NULL; } } pixel_cache_free(cache); void *ret = gif_save(image, palette, frames, count, frame_size, size); GifFreeMapObject(palette); free(frames); return ret; }
void EncodeToGifBufferWorker::Execute () { GifByteType * redBuff = (GifByteType *) _pixbuf, * greenBuff = (GifByteType *) _pixbuf + _width * _height, * blueBuff = (GifByteType *) _pixbuf + 2 * _width * _height, * alphaBuff = (GifByteType *) _pixbuf + 3 * _width * _height, * gifimgbuf = (GifByteType *) malloc(_width * _height * sizeof(GifByteType)); // the indexed image ColorMapObject *cmap; SavedImage * simg; if (NULL == gifimgbuf){ SetErrorMessage("Out of memory"); return; } cmap = GifMakeMapObject(_cmapSize, NULL); if (NULL == cmap){ free(gifimgbuf); SetErrorMessage("Out of memory"); return; } if (GIF_ERROR == GifQuantizeBuffer( _width, _height, &_colors, redBuff, greenBuff, blueBuff, gifimgbuf, cmap->Colors )){ free(gifimgbuf); GifFreeMapObject(cmap); SetErrorMessage("Unable to quantize image"); return; } int errcode; gifWriteCbData buffinf = {NULL, 0}; GifFileType * gif; gif = EGifOpen((void *) &buffinf, gifWriteCB, &errcode); if (NULL == gif){ free(gifimgbuf); GifFreeMapObject(cmap); SetErrorMessage(GifErrorString(errcode)); return; } gif->SWidth = _width; gif->SHeight = _height; gif->SColorResolution = _cmapSize; simg = GifMakeSavedImage(gif, NULL); if (NULL == simg){ free(gifimgbuf); EGifCloseFile(gif, &errcode); // will also free cmap SetErrorMessage("Out of memory"); return; } simg->ImageDesc.Left = 0; simg->ImageDesc.Top = 0; simg->ImageDesc.Width = _width; simg->ImageDesc.Height = _height; simg->ImageDesc.Interlace = _interlaced; simg->ImageDesc.ColorMap = cmap; simg->RasterBits = gifimgbuf; // for some reason giflib sometimes creates an invalid file if the global // color table is not set as well gif->SColorMap = cmap; if (_trans){ ExtensionBlock ext; // 1. assign transparent color index in color table GraphicsControlBlock gcb = {0, false, 0, _colors++}; // 2. replace transparent pixels above threshold with this color remapTransparentPixels(gifimgbuf, alphaBuff, _width, _height, gcb.TransparentColor, _threshold); // 3. create a control block size_t extlen = EGifGCBToExtension(&gcb, (GifByteType *) &ext); if (GIF_ERROR == GifAddExtensionBlock( &(simg->ExtensionBlockCount), &(simg->ExtensionBlocks), GRAPHICS_EXT_FUNC_CODE, extlen, (unsigned char *) &ext) ) { EGifCloseFile(gif, &errcode); SetErrorMessage("Out of memory"); return; } } if (GIF_ERROR == EGifSpew(gif)){ EGifCloseFile(gif, &errcode); SetErrorMessage(GifErrorString(gif->Error)); return; } _gifbuf = (char *) buffinf.buff; _gifbufsize = buffinf.buffsize; return; }