unsigned char * gifconv_lossless2gif(void *image_data, unsigned short width, unsigned short height, void *index_data, unsigned short index_data_count, int tag_no, int format, unsigned long *length) { GifFileType *GifFile = NULL; GifColorType *Colors = NULL; int ColorCount; my_gif_buffer gif_buff; gif_uint_32 gif_width = 0, gif_height = 0; int bpp; gif_bytep gif_image_data = NULL; gif_uint_32 x, y; gif_colorp gif_palette = NULL; // int trans_index = -1; int i; if (format != 3) { fprintf(stderr, "jpegconv_lossless2gif: format=%d not implemented yes.\n", format); return NULL; } bpp = 8; gif_width = width; gif_height = height; ColorCount = 256; Colors = calloc(sizeof(GifColorType), ColorCount); gif_buff.data = NULL; gif_buff.data_len = 0; gif_buff.data_offset = 0; #if GIFLIB_MAJOR >= 5 GifFile = EGifOpen(& gif_buff, gif_data_write_func, NULL); #else GifFile = EGifOpen(& gif_buff, gif_data_write_func); #endif if (GifFile == NULL) { fprintf(stderr, "gifconv_lossless2gif: can't open GIFFile\n"); return NULL; } GifFile->SWidth = gif_width; GifFile->SHeight = gif_height; GifFile->SColorResolution = bpp; gif_palette = (gif_colorp) malloc(sizeof(gif_color)*index_data_count); if (tag_no == 20) { swf_rgb_t *rgb_list = index_data; for (i=0 ; i < index_data_count ; i++) { Colors[i].Red = rgb_list[i].red; Colors[i].Green = rgb_list[i].green; Colors[i].Blue = rgb_list[i].blue; } } else { swf_rgba_t *rgba_list = index_data; for (i=0 ; i < index_data_count ; i++) { // if (rgba_list[i].alpha) Colors[i].Red = rgba_list[i].red; Colors[i].Green = rgba_list[i].green; Colors[i].Blue = rgba_list[i].blue; // gif_palette[i].alpha = ; } } GifFile->SBackGroundColor = 0; // XXX gif_image_data = (gif_bytep) calloc(sizeof(unsigned char), gif_width * gif_height); i = 0; for (y=0 ; y < gif_height ; y++) { for (x=0 ; x < gif_width ; x++) { unsigned char *data = image_data; gif_image_data[i] = data[x + y*((gif_width +3) & -4)]; i++; } } GifFile->SavedImages[0].RasterBits = gif_image_data; #if GIFLIB_MAJOR >= 5 GifFile->SColorMap = GifMakeMapObject(ColorCount, Colors); #else GifFile->SColorMap = MakeMapObject(ColorCount, Colors); #endif EGifSpew(GifFile); // XXX free(gif_image_data); if (GifFile) { #if GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1 || GIFLIB_MAJOR > 5 EGifCloseFile(GifFile, NULL); #else EGifCloseFile(GifFile); #endif } *length = gif_buff.data_offset; return gif_buff.data; }
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; }
static void Icon2Gif(char *FileName, FILE *txtin, int fdout) { unsigned int ExtCode, ColorMapSize = 0; GifColorType GlobalColorMap[256], LocalColorMap[256], *ColorMap = GlobalColorMap; char GlobalColorKeys[PRINTABLES], LocalColorKeys[PRINTABLES], *KeyTable = GlobalColorKeys; int red, green, blue; char buf[BUFSIZ * 2], InclusionFile[64]; GifFileType *GifFileOut; SavedImage *NewImage = NULL; int n, LineNum = 0; if ((GifFileOut = EGifOpenFileHandle(fdout)) == NULL) { (void) HandleGifError(GifFileOut); } /* OK, interpret directives */ while (fgets(buf, sizeof(buf), txtin) != (char *)NULL) { char *cp; ++LineNum; /* * Skip lines consisting only of whitespace and comments */ for (cp = buf; isspace((int)(*cp)); cp++) continue; if (*cp == '#' || *cp == '\0') continue; /* * If there's a trailing comment, nuke it and all preceding whitespace. * But preserve the EOL. */ if ((cp = strchr(buf, '#')) && (cp == strrchr(cp, '#'))) { while (isspace((int)(*--cp))) continue; *++cp = '\n'; *++cp = '\0'; } /* * Explicit header declarations */ if (sscanf(buf, "screen width %d\n", &GifFileOut->SWidth) == 1) continue; else if (sscanf(buf, "screen height %d\n", &GifFileOut->SHeight) == 1) continue; else if (sscanf(buf, "screen colors %d\n", &n) == 1) { int ResBits = BitSize(n); if (n > 256 || n < 0 || n != (1 << ResBits)) { PARSE_ERROR("Invalid color resolution value."); exit(EXIT_FAILURE); } GifFileOut->SColorResolution = ResBits; continue; } else if (sscanf(buf, "screen background %d\n", &GifFileOut->SBackGroundColor) == 1) continue; /* * Color table parsing */ else if (strcmp(buf, "screen map\n") == 0) { if (GifFileOut->SColorMap != NULL) { PARSE_ERROR("You've already declared a global color map."); exit(EXIT_FAILURE); } ColorMapSize = 0; ColorMap = GlobalColorMap; KeyTable = GlobalColorKeys; memset(GlobalColorKeys, '\0', sizeof(GlobalColorKeys)); } else if (strcmp(buf, "image map\n") == 0) { if (NewImage == NULL) { PARSE_ERROR("No previous image declaration."); exit(EXIT_FAILURE); } ColorMapSize = 0; ColorMap = LocalColorMap; KeyTable = LocalColorKeys; memset(LocalColorKeys, '\0', sizeof(LocalColorKeys)); } else if (sscanf(buf, " rgb %d %d %d is %c", &red, &green, &blue, &KeyTable[ColorMapSize]) == 4) { ColorMap[ColorMapSize].Red = red; ColorMap[ColorMapSize].Green = green; ColorMap[ColorMapSize].Blue = blue; ColorMapSize++; } else if (strcmp(buf, "end\n") == 0) { ColorMapObject *NewMap; NewMap = MakeMapObject(1 << BitSize(ColorMapSize), ColorMap); if (NewMap == (ColorMapObject *)NULL) { PARSE_ERROR("Out of memory while allocating new color map."); exit(EXIT_FAILURE); } if (NewImage) NewImage->ImageDesc.ColorMap = NewMap; else GifFileOut->SColorMap = NewMap; } /* GIF inclusion */ else if (sscanf(buf, "include %s", InclusionFile) == 1) { GifBooleanType DoTranslation; GifPixelType Translation[256]; GifFileType *Inclusion; SavedImage *NewImage, *CopyFrom; if ((Inclusion = DGifOpenFileName(InclusionFile)) == NULL || DGifSlurp(Inclusion) == GIF_ERROR) { PARSE_ERROR("Inclusion read failed."); QuitGifError(Inclusion, GifFileOut); } if ((DoTranslation = (GifFileOut->SColorMap!=(ColorMapObject*)NULL))) { ColorMapObject *UnionMap; UnionMap = UnionColorMap(GifFileOut->SColorMap, Inclusion->SColorMap, Translation); if (UnionMap == NULL) { PARSE_ERROR("Inclusion failed --- global map conflict."); QuitGifError(Inclusion, GifFileOut); } FreeMapObject(GifFileOut->SColorMap); GifFileOut->SColorMap = UnionMap; } for (CopyFrom = Inclusion->SavedImages; CopyFrom < Inclusion->SavedImages + Inclusion->ImageCount; CopyFrom++) { if ((NewImage = MakeSavedImage(GifFileOut, CopyFrom)) == NULL) { PARSE_ERROR("Inclusion failed --- out of memory."); QuitGifError(Inclusion, GifFileOut); } else if (DoTranslation) ApplyTranslation(NewImage, Translation); GifQprintf( "%s: Image %d at (%d, %d) [%dx%d]: from %s\n", PROGRAM_NAME, GifFileOut->ImageCount, NewImage->ImageDesc.Left, NewImage->ImageDesc.Top, NewImage->ImageDesc.Width, NewImage->ImageDesc.Height, InclusionFile); } (void) DGifCloseFile(Inclusion); } /* * Explicit image declarations */ else if (strcmp(buf, "image\n") == 0) { if ((NewImage = MakeSavedImage(GifFileOut, NULL)) == (SavedImage *)NULL) { PARSE_ERROR("Out of memory while allocating image block."); exit(EXIT_FAILURE); } /* use global table unless user specifies a local one */ ColorMap = GlobalColorMap; KeyTable = GlobalColorKeys; } /* * Nothing past this point is valid unless we've seen a previous * image declaration. */ else if (NewImage == (SavedImage *)NULL) { (void) fputs(buf, stderr); PARSE_ERROR("Syntax error in header block."); exit(EXIT_FAILURE); } /* * Accept image attributes */ else if (sscanf(buf, "image top %d\n", &NewImage->ImageDesc.Top) == 1) continue; else if (sscanf(buf, "image left %d\n", &NewImage->ImageDesc.Left)== 1) continue; else if (strcmp(buf, "image interlaced\n") == 0) { NewImage->ImageDesc.Interlace = TRUE; continue; } else if (sscanf(buf, "image bits %d by %d\n", &NewImage->ImageDesc.Width, &NewImage->ImageDesc.Height) == 2) { int i, j; static GifPixelType *Raster, *cp; int c; if ((Raster = (GifPixelType *) malloc(sizeof(GifPixelType) * NewImage->ImageDesc.Width * NewImage->ImageDesc.Height)) == NULL) { PARSE_ERROR("Failed to allocate raster block, aborted."); exit(EXIT_FAILURE); } if (!GifQuietPrint) fprintf(stderr, "%s: Image %d at (%d, %d) [%dx%d]: ", PROGRAM_NAME, GifFileOut->ImageCount, NewImage->ImageDesc.Left, NewImage->ImageDesc.Top, NewImage->ImageDesc.Width, NewImage->ImageDesc.Height); cp = Raster; for (i = 0; i < NewImage->ImageDesc.Height; i++) { char *dp; for (j = 0; j < NewImage->ImageDesc.Width; j++) if ((c = fgetc(txtin)) == EOF) { PARSE_ERROR("input file ended prematurely."); exit(EXIT_FAILURE); } else if (c == '\n') { --j; ++LineNum; } else if (isspace(c)) --j; else if ((dp = strchr(KeyTable, c))) *cp++ = (dp - KeyTable); else { PARSE_ERROR("Invalid pixel value."); exit(EXIT_FAILURE); } if (!GifQuietPrint) fprintf(stderr, "\b\b\b\b%-4d", i); } if (!GifQuietPrint) putc('\n', stderr); NewImage->RasterBits = (unsigned char *) Raster; } else if (sscanf(buf, "comment")) { MakeExtension(NewImage, COMMENT_EXT_FUNC_CODE); while (fgets(buf, sizeof(buf), txtin) != (char *)NULL) if (strcmp(buf, "end\n") == 0) break; else { int Len; buf[strlen(buf) - 1] = '\0'; Len = EscapeString(buf, buf); if (AddExtensionBlock(NewImage, Len, (unsigned char *)buf) == GIF_ERROR) { PARSE_ERROR("out of memory while adding comment block."); exit(EXIT_FAILURE); } } } else if (sscanf(buf, "plaintext")) { MakeExtension(NewImage, PLAINTEXT_EXT_FUNC_CODE); while (fgets(buf, sizeof(buf), txtin) != (char *)NULL) if (strcmp(buf, "end\n") == 0) break; else { int Len; buf[strlen(buf) - 1] = '\0'; Len = EscapeString(buf, buf); if (AddExtensionBlock(NewImage, Len, (unsigned char *)buf) == GIF_ERROR) { PARSE_ERROR("out of memory while adding plaintext block."); exit(EXIT_FAILURE); } } } else if (sscanf(buf, "extension %02x", &ExtCode)) { MakeExtension(NewImage, ExtCode); while (fgets(buf, sizeof(buf), txtin) != (char *)NULL) if (strcmp(buf, "end\n") == 0) break; else { int Len; buf[strlen(buf) - 1] = '\0'; Len = EscapeString(buf, buf); if (AddExtensionBlock(NewImage, Len, (unsigned char *)buf) == GIF_ERROR) { PARSE_ERROR("out of memory while adding extension block."); exit(EXIT_FAILURE); } } } else { (void) fputs(buf, stderr); PARSE_ERROR("Syntax error in image description."); exit(EXIT_FAILURE); } } if (EGifSpew(GifFileOut) == GIF_ERROR) HandleGifError(GifFileOut); }
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); }