/****************************************************************************** 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); }
/****************************************************************************** This routine should be called before any other DGif calls. Note that this routine is called automatically from DGif file open routines. ******************************************************************************/ int DGifGetScreenDesc(GifFileType *GifFile) { int BitsPerPixel; bool SortFlag; GifByteType Buf[3]; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } /* Put the screen descriptor into the file: */ if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR) return GIF_ERROR; if (READ(GifFile, Buf, 3) != 3) { GifFile->Error = D_GIF_ERR_READ_FAILED; GifFreeMapObject(GifFile->SColorMap); GifFile->SColorMap = NULL; return GIF_ERROR; } GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1; SortFlag = (Buf[0] & 0x08) != 0; BitsPerPixel = (Buf[0] & 0x07) + 1; GifFile->SBackGroundColor = Buf[1]; GifFile->AspectByte = Buf[2]; if (Buf[0] & 0x80) { /* Do we have global color map? */ int i; GifFile->SColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL); if (GifFile->SColorMap == NULL) { GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } /* Get the global color map: */ GifFile->SColorMap->SortFlag = SortFlag; for (i = 0; i < GifFile->SColorMap->ColorCount; i++) { /* coverity[check_return] */ if (READ(GifFile, Buf, 3) != 3) { GifFreeMapObject(GifFile->SColorMap); GifFile->SColorMap = NULL; GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } GifFile->SColorMap->Colors[i].Red = Buf[0]; GifFile->SColorMap->Colors[i].Green = Buf[1]; GifFile->SColorMap->Colors[i].Blue = Buf[2]; } } else { GifFile->SColorMap = NULL; } return GIF_OK; }
static ColorMapObject* genDefColorMap() { ColorMapObject* cmap = GifMakeMapObject(256, NULL); if (cmap != NULL) { int iColor; for (iColor = 0; iColor < 256; iColor++) { cmap->Colors[iColor].Red = (GifByteType) iColor; cmap->Colors[iColor].Green = (GifByteType) iColor; cmap->Colors[iColor].Blue = (GifByteType) iColor; } } return cmap; }
int main(int argc, char **argv) { int i, ErrorCode; GifFileType *GifFileIn, *GifFileOut = (GifFileType *)NULL; if ((GifFileIn = DGifOpenFileHandle(0, &ErrorCode)) == NULL) { PrintGifError(ErrorCode); exit(EXIT_FAILURE); } if (DGifSlurp(GifFileIn) == GIF_ERROR) { PrintGifError(GifFileIn->Error); exit(EXIT_FAILURE); } if ((GifFileOut = EGifOpenFileHandle(1, &ErrorCode)) == NULL) { PrintGifError(ErrorCode); exit(EXIT_FAILURE); } /* * Your operations on in-core structures go here. * This code just copies the header and each image from the incoming file. */ GifFileOut->SWidth = GifFileIn->SWidth; GifFileOut->SHeight = GifFileIn->SHeight; GifFileOut->SColorResolution = GifFileIn->SColorResolution; GifFileOut->SBackGroundColor = GifFileIn->SBackGroundColor; GifFileOut->SColorMap = GifMakeMapObject( GifFileIn->SColorMap->ColorCount, GifFileIn->SColorMap->Colors); for (i = 0; i < GifFileIn->ImageCount; i++) (void) GifMakeSavedImage(GifFileOut, &GifFileIn->SavedImages[i]); /* * Note: don't do DGifCloseFile early, as this will * deallocate all the memory containing the GIF data! * * Further note: EGifSpew() doesn't try to validity-check any of this * data; it's *your* responsibility to keep your changes consistent. * Caveat hacker! */ if (EGifSpew(GifFileOut) == GIF_ERROR) PrintGifError(GifFileOut->Error); if (DGifCloseFile(GifFileIn, &ErrorCode) == GIF_ERROR) PrintGifError(ErrorCode); if (EGifCloseFile(GifFileOut, &ErrorCode) == GIF_ERROR) PrintGifError(ErrorCode); return 0; }
bool CMakeGifDoc::addImagesToGif() { const PixRectArray &prArray = getQuantizedPrArray(); if(prArray.size() == 0) { return false; } if(!hasGifFile()) { const CSize size = prArray.getMaxSize(); m_gif = allocateGifFile(size.cx, size.cy); } const SavedImageArray images(prArray, m_imageSettings.m_colorCount); for(size_t i = 0; i < images.size(); i++) { GifMakeSavedImage(m_gif, images[i]); } const SavedImage *image0 = images[0]; const ColorMapObject *colorMap = image0->ImageDesc.ColorMap; m_gif->SColorMap = GifMakeMapObject(colorMap->ColorCount, colorMap->Colors); updateTimestamp(); return true; }
static void saveGif(ByteOutputStream &out, GifFileType *gf) { int error; GifFileType *gifOut = NULL; try { gifOut = EGifOpen(&out, writeGifStreamFunction, &error); if(gifOut == NULL) { THROWGIFERROR(error); } gifOut->SWidth = gf->SWidth; gifOut->SHeight = gf->SHeight; gifOut->SColorResolution = gf->SColorResolution; gifOut->SBackGroundColor = gf->SBackGroundColor; gifOut->SColorMap = GifMakeMapObject(gf->SColorMap->ColorCount ,gf->SColorMap->Colors); for(int i = 0; i < gf->ImageCount; i++) { GifMakeSavedImage(gifOut, &gf->SavedImages[i]); } if(gifOut->ImageCount > 0) { SavedImage *image0 = gifOut->SavedImages; addNetscapeBlock(image0); } EGifSetGifVersion(gifOut, true); if(EGifSpew(gifOut) != GIF_OK) { THROWGIFERROR(gifOut->Error); } } catch(Exception e) { if(gifOut != NULL) { EGifCloseFile(gifOut, &error); } throw e; } catch(...) { if(gifOut != NULL) { EGifCloseFile(gifOut, &error); } throw; } }
void AnimatedGifEncoder::new_frame(unsigned char *data, int delay) { if (!gif_file) { if (write_func != NULL) { int nError; gif_file = EGifOpen(write_user_data, write_func, &nError); if (!gif_file) throw "EGifOpen in AnimatedGifEncoder::new_frame failed"; } else if (file_name.empty()) { // memory writer int nError; gif_file = EGifOpen(&gif, gif_writer, &nError); if (!gif_file) throw "EGifOpen in AnimatedGifEncoder::new_frame failed"; } else { int nError; gif_file = EGifOpenFileName(file_name.c_str(), FALSE, &nError); if (!gif_file) throw "EGifOpenFileName in AnimatedGifEncoder::new_frame failed"; } output_color_map = GifMakeMapObject(color_map_size, ext_web_safe_palette); if (!output_color_map) throw "MakeMapObject in AnimatedGifEncoder::new_frame failed"; gif_buf = (GifByteType *)malloc(sizeof(GifByteType)*width*height); if (!gif_buf) throw "malloc in AnimatedGifEncoder::new_frame failed"; } RGBator rgb(data, width, height, buf_type); if (web_safe_quantize(width, height, rgb.red, rgb.green, rgb.blue, gif_buf) == GIF_ERROR) throw "web_safe_quantize in AnimatedGifEncoder::new_frame failed"; /* if (QuantizeBuffer(width, height, &color_map_size, rgb.red, rgb.green, rgb.blue, gif_buf, output_color_map->Colors) == GIF_ERROR) { throw "QuantizeBuffer in AnimatedGifEncoder::new_frame failed"; } */ if (!headers_set) { if (EGifPutScreenDesc(gif_file, width, height, color_map_size, 0, output_color_map) == GIF_ERROR) { throw "EGifPutScreenDesc in AnimatedGifEncoder::new_frame failed"; } char netscape_extension[] = "NETSCAPE2.0"; EGifPutExtension(gif_file, APPLICATION_EXT_FUNC_CODE, 11, netscape_extension); char animation_extension[] = { 1, 1, 0 }; // repeat one time EGifPutExtension(gif_file, APPLICATION_EXT_FUNC_CODE, 3, animation_extension); headers_set = true; } char frame_flags = 1 << 2; char transp_color_idx = 0; if (transparency_color.color_present) { int i = find_color_index(output_color_map, color_map_size, transparency_color); if (i>=0) { frame_flags |= 1; transp_color_idx = i; } } char extension[] = { frame_flags, delay%256, delay/256, transp_color_idx }; EGifPutExtension(gif_file, GRAPHICS_EXT_FUNC_CODE, 4, extension); if (EGifPutImageDesc(gif_file, 0, 0, width, height, FALSE, NULL) == GIF_ERROR) { throw "EGifPutImageDesc in AnimatedGifEncoder::new_frame failed"; } GifByteType *gif_bufp = gif_buf; for (int i = 0; i < height; i++) { if (EGifPutLine(gif_file, gif_bufp, width) == GIF_ERROR) { throw "EGifPutLine in AnimatedGifEncoder::new_frame failed"; } gif_bufp += width; } }
bool MCImageEncodeGIF(MCImageIndexedBitmap *p_indexed, IO_handle p_stream, uindex_t &r_bytes_written) { bool t_success = true; int32_t t_transparent = -1; uindex_t t_palette_size; uindex_t t_depth; t_depth = GifBitSize(p_indexed->palette_size); // GIF requires palette size to be 2^depth t_palette_size = 1 << t_depth; int t_err = 0; GifFileType *t_gif = nil; ColorMapObject *t_colormap = nil; MCGIFWriteContext t_context; t_context.stream = p_stream; t_context.byte_count = 0; t_success = nil != (t_gif = EGifOpen(&t_context, gif_writeFunc, &t_err)); if (t_success) t_success = nil != (t_colormap = GifMakeMapObject(t_palette_size, nil)); if (t_success) { for (uindex_t i = 0; i < p_indexed->palette_size; i++) { t_colormap->Colors[i].Red = p_indexed->palette[i].red; t_colormap->Colors[i].Green = p_indexed->palette[i].green; t_colormap->Colors[i].Blue = p_indexed->palette[i].blue; } for (uindex_t i = p_indexed->palette_size; i < t_palette_size; i++) { t_colormap->Colors[i].Red = t_colormap->Colors[i].Green = t_colormap->Colors[i].Blue = 0; } if (MCImageIndexedBitmapHasTransparency(p_indexed)) { t_transparent = p_indexed->transparent_index; t_colormap->Colors[t_transparent].Red = t_colormap->Colors[t_transparent].Green = t_colormap->Colors[t_transparent].Blue = 0xFF; } t_success = GIF_OK == EGifPutScreenDesc(t_gif, p_indexed->width, p_indexed->height, t_depth, 0, t_colormap); } if (t_success) { if (t_transparent != -1) { GraphicsControlBlock t_gcb; MCMemoryClear(&t_gcb, sizeof(t_gcb)); t_gcb.TransparentColor = t_transparent; GifByteType t_extension[4]; uindex_t t_extension_size; t_extension_size = EGifGCBToExtension(&t_gcb, t_extension); // Should always be 4 bytes MCAssert(t_extension_size == sizeof(t_extension)); t_success = GIF_OK == EGifPutExtension(t_gif, GRAPHICS_EXT_FUNC_CODE, sizeof(t_extension), t_extension); } } if (t_success) t_success = GIF_OK == EGifPutImageDesc(t_gif, 0, 0, p_indexed->width, p_indexed->height, false, nil); for (uindex_t y = 0; t_success && y < p_indexed->height; y++) t_success = GIF_OK == EGifPutLine(t_gif, (uint8_t*)p_indexed->data + y * p_indexed->stride, p_indexed->width); int t_error_code; if (GIF_ERROR == EGifCloseFile(t_gif, &t_error_code)) t_success = false; GifFreeMapObject(t_colormap); if (t_success) r_bytes_written = t_context.byte_count; return t_success; }
bool Graphics::toGif(QImage &img, QString &path) { int errcode; if(QFile(path).exists()) // Remove old file QFile::remove(path); GifFileType *t = EGifOpenFileName(path.toStdString().c_str(), true, &errcode); if(!t) { EGifCloseFile(t, &errcode); std::cout << "Can't open\n"; return false; } EGifSetGifVersion(t, true); std::vector<GifColorType>colorArr; colorArr.resize(256); ColorMapObject *cmo = GifMakeMapObject(256, colorArr.data()); bool unfinished = false; QImage tarQImg(img.width(), img.height(), QImage::Format_Indexed8); QVector<QRgb> table; for(int y = 0; y < img.height(); y++) { for(int x = 0; x < img.width(); x++) { if(table.size() >= 256) { unfinished = true; break; } QRgb pix; if(!table.contains(pix = img.pixel(x, y))) { table.push_back(pix); tarQImg.setColor(tarQImg.colorCount(), pix); } tarQImg.setPixel(x, y, static_cast<uint>(table.indexOf(pix))); } if(table.size() >= 256) { unfinished = true; break; } } if(unfinished) { GifFreeMapObject(cmo); EGifCloseFile(t, &errcode); std::cout << "Unfinished\n"; return false; } for(int l = tarQImg.colorCount(); l < 256; l++) tarQImg.setColor(l, 0); if(tarQImg.colorTable().size() != 256) { GifFreeMapObject(cmo); EGifCloseFile(t, &errcode); std::cout << "A lot of colors\n"; return false; } std::vector<QRgb> clTab = tarQImg.colorTable().toStdVector(); for(size_t i = 0; i < 255; i++) { QRgb rgb = clTab[i]; colorArr[i].Red = static_cast<unsigned char>(qRed(rgb)); colorArr[i].Green = static_cast<unsigned char>(qGreen(rgb)); colorArr[i].Blue = static_cast<unsigned char>(qBlue(rgb)); } cmo->Colors = colorArr.data(); errcode = EGifPutScreenDesc(t, img.width(), img.height(), 256, 0, cmo); if(errcode != GIF_OK) { GifFreeMapObject(cmo); EGifCloseFile(t, &errcode); std::cout << "EGifPutScreenDesc error 1\n"; return false; } errcode = EGifPutImageDesc(t, 0, 0, img.width(), img.height(), false, 0); if(errcode != GIF_OK) { GifFreeMapObject(cmo); EGifCloseFile(t, &errcode); std::cout << "EGifPutImageDesc error 2\n"; return false; } //gen byte array GifByteType *byteArr = tarQImg.bits(); for(int h = 0; h < tarQImg.height(); h++) { errcode = EGifPutLine(t, byteArr, tarQImg.width()); if(errcode != GIF_OK) { GifFreeMapObject(cmo); EGifCloseFile(t, &errcode); std::cout << "EGifPutLine error 3\n"; return false; } byteArr += tarQImg.width(); byteArr += ((tarQImg.width() % 4) != 0 ? 4 - (tarQImg.width() % 4) : 0); } GifFreeMapObject(cmo); EGifCloseFile(t, &errcode); return true; }
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 GifEncoder::encode() { RGBator rgb(data, width, height, buf_type); int color_map_size = 256; ColorMapObject *output_color_map = GifMakeMapObject(256, ext_web_safe_palette); LOKI_ON_BLOCK_EXIT(GifFreeMapObject, output_color_map); if (!output_color_map) throw "MakeMapObject in GifEncoder::encode failed"; GifByteType *gif_buf = (GifByteType *)malloc(sizeof(GifByteType)*width*height); LOKI_ON_BLOCK_EXIT(free, gif_buf); if (!gif_buf) throw "malloc in GifEncoder::encode failed"; if (web_safe_quantize(width, height, rgb.red, rgb.green, rgb.blue, gif_buf) == GIF_ERROR) throw "web_safe_quantize in GifEncoder::encode failed"; /* if (QuantizeBuffer(width, height, &color_map_size, rgb.red, rgb.green, rgb.blue, gif_buf, output_color_map->Colors) == GIF_ERROR) { throw "QuantizeBuffer in GifEncoder::encode failed"; } */ int nError; GifFileType *gif_file = EGifOpen(&gif, gif_writer, &nError); LOKI_ON_BLOCK_EXIT(EGifCloseFile, gif_file); if (!gif_file) throw "EGifOpen in GifEncoder::encode failed"; if (EGifPutScreenDesc(gif_file, width, height, color_map_size, 0, output_color_map) == GIF_ERROR) { throw "EGifPutScreenDesc in GifEncoder::encode failed"; } if (transparency_color.color_present) { int i = find_color_index(output_color_map, color_map_size, transparency_color); if (i) { char extension[] = { 1, // enable transparency 0, 0, // no time delay i // transparency color index }; EGifPutExtension(gif_file, GRAPHICS_EXT_FUNC_CODE, 4, extension); } } if (EGifPutImageDesc(gif_file, 0, 0, width, height, FALSE, NULL) == GIF_ERROR) { throw "EGifPutImageDesc in GifEncoder::encode failed"; } GifByteType *gif_bufp = gif_buf; for (int i = 0; i < height; i++) { if (EGifPutLine(gif_file, gif_bufp, width) == GIF_ERROR) throw "EGifPutLine in GifEncoder::encode failed"; gif_bufp += width; } }
/****************************************************************************** Interpret the command line and scan the given GIF file. ******************************************************************************/ int main(int argc, char **argv) { int i, j, l, c, LevelStep, LogNumLevels, ErrorCode, Count = 0; bool Error, LevelsFlag = false, SizeFlag = false, HelpFlag = false; GifRowType Line; ColorMapObject *ColorMap; GifFileType *GifFile; if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifNoisyPrint, &LevelsFlag, &NumLevels, &SizeFlag, &ImageWidth, &ImageHeight, &HelpFlag)) != false) { GAPrintErrMsg(Error); GAPrintHowTo(CtrlStr); exit(EXIT_FAILURE); } if (HelpFlag) { (void)fprintf(stderr, VersionStr, GIFLIB_MAJOR, GIFLIB_MINOR); GAPrintHowTo(CtrlStr); exit(EXIT_SUCCESS); } /* Make sure the number of levels is power of 2 (up to 32 levels.). */ for (i = 1; i < 6; i++) if (NumLevels == (1 << i)) break; if (i == 6) GIF_EXIT("#Lvls (-l option) is not power of 2 up to 32."); LogNumLevels = i + 3; /* Multiple by 8 (see below). */ LevelStep = 256 / NumLevels; /* Make sure the image dimension is a multiple of NumLevels horizontally */ /* and 7 (White, Red, Green, Blue and Yellow Cyan Magenta) vertically. */ ImageWidth = (ImageWidth / NumLevels) * NumLevels; ImageHeight = (ImageHeight / 7) * 7; /* Open stdout for the output file: */ if ((GifFile = EGifOpenFileHandle(1, &ErrorCode)) == NULL) { PrintGifError(ErrorCode); exit(EXIT_FAILURE); } /* Dump out screen description with given size and generated color map: */ /* The color map has 7 NumLevels colors for White, Red, Green and then */ /* The secondary colors Yellow Cyan and magenta. */ if ((ColorMap = GifMakeMapObject(8 * NumLevels, NULL)) == NULL) GIF_EXIT("Failed to allocate memory required, aborted."); for (i = 0; i < 8; i++) /* Set color map. */ for (j = 0; j < NumLevels; j++) { l = LevelStep * j; c = i * NumLevels + j; ColorMap->Colors[c].Red = (i == 0 || i == 1 || i == 4 || i == 6) * l; ColorMap->Colors[c].Green = (i == 0 || i == 2 || i == 4 || i == 5) * l; ColorMap->Colors[c].Blue = (i == 0 || i == 3 || i == 5 || i == 6) * l; } if (EGifPutScreenDesc(GifFile, ImageWidth, ImageHeight, LogNumLevels, 0, ColorMap) == GIF_ERROR) { PrintGifError(GifFile->Error); } /* Dump out the image descriptor: */ if (EGifPutImageDesc(GifFile, 0, 0, ImageWidth, ImageHeight, false, NULL) == GIF_ERROR) { PrintGifError(GifFile->Error); exit(EXIT_FAILURE); } GifQprintf("\n%s: Image 1 at (%d, %d) [%dx%d]: ", PROGRAM_NAME, GifFile->Image.Left, GifFile->Image.Top, GifFile->Image.Width, GifFile->Image.Height); /* Allocate one scan line to be used for all image. */ if ((Line = (GifRowType) malloc(sizeof(GifPixelType) * ImageWidth)) == NULL) GIF_EXIT("Failed to allocate memory required, aborted."); /* Dump the pixels: */ for (c = 0; c < 7; c++) { for (i = 0, l = 0; i < NumLevels; i++) for (j = 0; j < ImageWidth / NumLevels; j++) Line[l++] = i + NumLevels * c; for (i = 0; i < ImageHeight / 7; i++) { if (EGifPutLine(GifFile, Line, ImageWidth) == GIF_ERROR) { PrintGifError(GifFile->Error); exit(EXIT_FAILURE); } GifQprintf("\b\b\b\b%-4d", Count++); } } if (EGifCloseFile(GifFile, &ErrorCode) == GIF_ERROR) { PrintGifError(ErrorCode); exit(EXIT_FAILURE); } return 0; }
/****************************************************************************** This routine should be called before any attempt to dump an image - any call to any of the pixel dump routines. ******************************************************************************/ int EGifPutImageDesc(GifFileType *GifFile, const int Left, const int Top, const int Width, const int Height, const bool Interlace, const ColorMapObject *ColorMap) { GifByteType Buf[3]; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (Private->FileState & FILE_STATE_IMAGE && Private->PixelCount > 0xffff0000UL) { /* If already has active image descriptor - something is wrong! */ GifFile->Error = E_GIF_ERR_HAS_IMAG_DSCR; return GIF_ERROR; } if (!IS_WRITEABLE(Private)) { /* This file was NOT open for writing: */ GifFile->Error = E_GIF_ERR_NOT_WRITEABLE; return GIF_ERROR; } GifFile->Image.Left = Left; GifFile->Image.Top = Top; GifFile->Image.Width = Width; GifFile->Image.Height = Height; GifFile->Image.Interlace = Interlace; if (ColorMap) { if (GifFile->Image.ColorMap != NULL) { GifFreeMapObject(GifFile->Image.ColorMap); GifFile->Image.ColorMap = NULL; } GifFile->Image.ColorMap = GifMakeMapObject(ColorMap->ColorCount, ColorMap->Colors); if (GifFile->Image.ColorMap == NULL) { GifFile->Error = E_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } } else { GifFile->Image.ColorMap = NULL; } /* Put the image descriptor into the file: */ Buf[0] = DESCRIPTOR_INTRODUCER; /* Image separator character. */ InternalWrite(GifFile, Buf, 1); (void)EGifPutWord(Left, GifFile); (void)EGifPutWord(Top, GifFile); (void)EGifPutWord(Width, GifFile); (void)EGifPutWord(Height, GifFile); Buf[0] = (ColorMap ? 0x80 : 0x00) | (Interlace ? 0x40 : 0x00) | (ColorMap ? ColorMap->BitsPerPixel - 1 : 0); InternalWrite(GifFile, Buf, 1); /* If we have Global color map - dump it also: */ if (ColorMap != NULL) { int i; for (i = 0; i < ColorMap->ColorCount; i++) { /* Put the ColorMap out also: */ Buf[0] = ColorMap->Colors[i].Red; Buf[1] = ColorMap->Colors[i].Green; Buf[2] = ColorMap->Colors[i].Blue; if (InternalWrite(GifFile, Buf, 3) != 3) { GifFile->Error = E_GIF_ERR_WRITE_FAILED; return GIF_ERROR; } } } if (GifFile->SColorMap == NULL && GifFile->Image.ColorMap == NULL) { GifFile->Error = E_GIF_ERR_NO_COLOR_MAP; return GIF_ERROR; } /* Mark this file as has screen descriptor: */ Private->FileState |= FILE_STATE_IMAGE; Private->PixelCount = (long)Width *(long)Height; /* Reset compress algorithm parameters. */ (void)EGifSetupCompress(GifFile); return GIF_OK; }
/* * Append an image block to the SavedImages array */ SavedImage * GifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom) { if (GifFile->SavedImages == NULL) GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage)); else GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages, sizeof(SavedImage) * (GifFile->ImageCount + 1)); if (GifFile->SavedImages == NULL) return ((SavedImage *)NULL); else { SavedImage *sp = &GifFile->SavedImages[GifFile->ImageCount++]; memset((char *)sp, '\0', sizeof(SavedImage)); if (CopyFrom != NULL) { memcpy((char *)sp, CopyFrom, sizeof(SavedImage)); /* * Make our own allocated copies of the heap fields in the * copied record. This guards against potential aliasing * problems. */ /* first, the local color map */ if (sp->ImageDesc.ColorMap != NULL) { sp->ImageDesc.ColorMap = GifMakeMapObject( CopyFrom->ImageDesc.ColorMap->ColorCount, CopyFrom->ImageDesc.ColorMap->Colors); if (sp->ImageDesc.ColorMap == NULL) { FreeLastSavedImage(GifFile); return (SavedImage *)(NULL); } } /* next, the raster */ sp->RasterBits = (unsigned char *)malloc(sizeof(GifPixelType) * CopyFrom->ImageDesc.Height * CopyFrom->ImageDesc.Width); if (sp->RasterBits == NULL) { FreeLastSavedImage(GifFile); return (SavedImage *)(NULL); } memcpy(sp->RasterBits, CopyFrom->RasterBits, sizeof(GifPixelType) * CopyFrom->ImageDesc.Height * CopyFrom->ImageDesc.Width); /* finally, the extension blocks */ if (sp->ExtensionBlocks != NULL) { sp->ExtensionBlocks = (ExtensionBlock *)malloc( sizeof(ExtensionBlock) * CopyFrom->ExtensionBlockCount); if (sp->ExtensionBlocks == NULL) { FreeLastSavedImage(GifFile); return (SavedImage *)(NULL); } memcpy(sp->ExtensionBlocks, CopyFrom->ExtensionBlocks, sizeof(ExtensionBlock) * CopyFrom->ExtensionBlockCount); } } return (sp); } }
/******************************************************************************* Compute the union of two given color maps and return it. If result can't fit into 256 colors, NULL is returned, the allocated union otherwise. ColorIn1 is copied as is to ColorUnion, while colors from ColorIn2 are copied iff they didn't exist before. ColorTransIn2 maps the old ColorIn2 into the ColorUnion color map table./ *******************************************************************************/ ColorMapObject * GifUnionColorMap(const ColorMapObject *ColorIn1, const ColorMapObject *ColorIn2, GifPixelType ColorTransIn2[]) { int i, j, CrntSlot, RoundUpTo, NewGifBitSize; ColorMapObject *ColorUnion; /* * We don't worry about duplicates within either color map; if * the caller wants to resolve those, he can perform unions * with an empty color map. */ /* Allocate table which will hold the result for sure. */ ColorUnion = GifMakeMapObject(MAX(ColorIn1->ColorCount, ColorIn2->ColorCount) * 2, NULL); if (ColorUnion == NULL) return (NULL); /* * Copy ColorIn1 to ColorUnion. */ for (i = 0; i < ColorIn1->ColorCount; i++) ColorUnion->Colors[i] = ColorIn1->Colors[i]; CrntSlot = ColorIn1->ColorCount; /* * Potentially obnoxious hack: * * Back CrntSlot down past all contiguous {0, 0, 0} slots at the end * of table 1. This is very useful if your display is limited to * 16 colors. */ while (ColorIn1->Colors[CrntSlot - 1].Red == 0 && ColorIn1->Colors[CrntSlot - 1].Green == 0 && ColorIn1->Colors[CrntSlot - 1].Blue == 0) CrntSlot--; /* Copy ColorIn2 to ColorUnion (use old colors if they exist): */ for (i = 0; i < ColorIn2->ColorCount && CrntSlot <= 256; i++) { /* Let's see if this color already exists: */ for (j = 0; j < ColorIn1->ColorCount; j++) if (memcmp (&ColorIn1->Colors[j], &ColorIn2->Colors[i], sizeof(GifColorType)) == 0) break; if (j < ColorIn1->ColorCount) ColorTransIn2[i] = j; /* color exists in Color1 */ else { /* Color is new - copy it to a new slot: */ ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i]; ColorTransIn2[i] = CrntSlot++; } } if (CrntSlot > 256) { GifFreeMapObject(ColorUnion); return ((ColorMapObject *) NULL); } NewGifBitSize = GifBitSize(CrntSlot); RoundUpTo = (1 << NewGifBitSize); if (RoundUpTo != ColorUnion->ColorCount) { register GifColorType *Map = ColorUnion->Colors; /* * Zero out slots up to next power of 2. * We know these slots exist because of the way ColorUnion's * start dimension was computed. */ for (j = CrntSlot; j < RoundUpTo; j++) Map[j].Red = Map[j].Green = Map[j].Blue = 0; /* perhaps we can shrink the map? */ if (RoundUpTo < ColorUnion->ColorCount) { GifColorType *new_map = (GifColorType *)realloc(Map, sizeof(GifColorType) * RoundUpTo); if( new_map == NULL ) { GifFreeMapObject(ColorUnion); return ((ColorMapObject *) NULL); } ColorUnion->Colors = new_map; } } ColorUnion->ColorCount = RoundUpTo; ColorUnion->BitsPerPixel = NewGifBitSize; return (ColorUnion); }
/****************************************************************************** Modify the given colormap according to global variables setting. ******************************************************************************/ static ColorMapObject *ModifyColorMap(ColorMapObject *ColorMap) { int i, Dummy, Red, Green, Blue; if (SaveFlag) { /* Save this color map to ColorFile: */ for (i = 0; i < ColorMap->ColorCount; i++) fprintf(ColorFile, "%3d %3d %3d %3d\n", i, ColorMap->Colors[i].Red, ColorMap->Colors[i].Green, ColorMap->Colors[i].Blue); return(ColorMap); } else if (LoadFlag) { /* Read the color map in ColorFile into this color map: */ for (i = 0; i < ColorMap->ColorCount; i++) { if (feof(ColorFile)) GIF_EXIT("Color file to load color map from, too small."); if (fscanf(ColorFile, "%3d %3d %3d %3d\n", &Dummy, &Red, &Green, &Blue) == 4) { ColorMap->Colors[i].Red = Red; ColorMap->Colors[i].Green = Green; ColorMap->Colors[i].Blue = Blue; } } return(ColorMap); } else if (GammaFlag) { /* Apply gamma correction to this color map: */ double Gamma1 = 1.0 / Gamma; for (i = 0; i < ColorMap->ColorCount; i++) { ColorMap->Colors[i].Red = ((int) (255 * pow(ColorMap->Colors[i].Red / 255.0, Gamma1))); ColorMap->Colors[i].Green = ((int) (255 * pow(ColorMap->Colors[i].Green / 255.0, Gamma1))); ColorMap->Colors[i].Blue = ((int) (255 * pow(ColorMap->Colors[i].Blue / 255.0, Gamma1))); } return(ColorMap); } else if (TranslateFlag) { ColorMapObject *NewMap; int Max = 0; /* Read the translation table in TranslateFile: */ for (i = 0; i < ColorMap->ColorCount; i++) { int tmp; if (feof(TranslateFile)) GIF_EXIT("Color file to load color map from, too small."); if (fscanf(TranslateFile, "%3d %3d\n", &Dummy, &tmp) == 2) { Translation[i] = tmp & 0xff; if (Translation[i] > Max) Max = Translation[i]; } } if ((NewMap = GifMakeMapObject(1 << GifBitSize(Max+1), NULL)) == NULL) GIF_EXIT("Out of memory while allocating color map!"); /* Apply the translation; we'll do it to the pixels, too */ for (i = 0; i < ColorMap->ColorCount; i++) { NewMap->Colors[i] = ColorMap->Colors[Translation[i]]; } return(NewMap); } else { GIF_EXIT("Nothing to do!"); return(ColorMap); } }
/****************************************************************************** Interpret the command line, prepar global data and call the Gif routines. ******************************************************************************/ int main(int argc, char **argv) { int NumFiles, ImageWidth, ImageHeight, Dummy, Red, Green, Blue, ErrorCode; static bool Error, ImageSizeFlag = false, ColorMapFlag = false, HelpFlag = false, TextifyFlag = false; char **FileName = NULL, *ColorMapFile; ColorMapObject *ColorMap; FILE *InColorMapFile; if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifNoisyPrint, &ImageSizeFlag, &ImageWidth, &ImageHeight, &ColorMapFlag, &ColorMapFile, &TextifyFlag, &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) { (void)fprintf(stderr, VersionStr, GIFLIB_MAJOR, GIFLIB_MINOR); GAPrintHowTo(CtrlStr); exit(EXIT_SUCCESS); } if (ImageSizeFlag) { if (ColorMapFlag) { int ColorMapSize; /* Read color map from given file: */ if ((InColorMapFile = fopen(ColorMapFile, "rt")) == NULL) { GIF_MESSAGE("Failed to open COLOR MAP file (not exists!?)."); exit(EXIT_FAILURE); } if ((ColorMap = GifMakeMapObject(256, NULL)) == NULL) { GIF_MESSAGE("Failed to allocate bitmap, aborted."); exit(EXIT_FAILURE); } for (ColorMapSize = 0; ColorMapSize < 256 && !feof(InColorMapFile); ColorMapSize++) { if (fscanf(InColorMapFile, "%3d %3d %3d %3d\n", &Dummy, &Red, &Green, &Blue) == 4) { ColorMap->Colors[ColorMapSize].Red = Red; ColorMap->Colors[ColorMapSize].Green = Green; ColorMap->Colors[ColorMapSize].Blue = Blue; } } } else { ColorMap = GifMakeMapObject(EGA_PALETTE_SIZE, EGAPalette); } if (NumFiles == 1) { int InFileHandle; #ifdef _WIN32 if ((InFileHandle = open(*FileName, O_RDONLY | O_BINARY)) == -1) { #else if ((InFileHandle = open(*FileName, O_RDONLY)) == -1) { #endif /* _WIN32 */ GIF_MESSAGE("Failed to open RAW image file (not exists!?)."); exit(EXIT_FAILURE); } dup2(InFileHandle, 0); /* Make stdin from this file. */ } else { #ifdef _WIN32 _setmode(0, O_BINARY); /* Make sure it is in binary mode. */ #endif /* _WIN32 */ } /* Convert Raw image from stdin to GIF file in stdout: */ Raw2Gif(ImageWidth, ImageHeight, ColorMap); } else { GifFileType *GifFile; if (NumFiles == 1) { if ((GifFile = DGifOpenFileName(*FileName, &ErrorCode)) == NULL) { PrintGifError(ErrorCode); exit(EXIT_FAILURE); } } else { /* Use stdin instead: */ if ((GifFile = DGifOpenFileHandle(0, &ErrorCode)) == NULL) { PrintGifError(ErrorCode); exit(EXIT_FAILURE); } } Gif2Raw(GifFile, TextifyFlag); } return 0; // cppcheck-suppress resourceLeak } /****************************************************************************** Convert raw image (One byte per pixel) into GIF file. Raw data is read from stdin, and GIF is dumped to stdout. ImagwWidth times ImageHeight bytes are read. Color map is dumped from ColorMap. ******************************************************************************/ void Raw2Gif(int ImageWidth, int ImageHeight, ColorMapObject *ColorMap) { int i, j, ErrorCode; static GifPixelType *ScanLine; GifFileType *GifFile; if ((ScanLine = (GifPixelType *) malloc(sizeof(GifPixelType) * ImageWidth)) == NULL) { GIF_MESSAGE("Failed to allocate scan line, aborted."); exit(EXIT_FAILURE); } if ((GifFile = EGifOpenFileHandle(1, &ErrorCode)) == NULL) { /* Gif to stdout. */ free((char *) ScanLine); PrintGifError(ErrorCode); exit(EXIT_FAILURE); } if (EGifPutScreenDesc(GifFile, ImageWidth, ImageHeight, ColorMap->BitsPerPixel, 0, ColorMap) == GIF_ERROR) { free((char *) ScanLine); PrintGifError(GifFile->Error); exit(EXIT_FAILURE); } if (EGifPutImageDesc(GifFile, 0, 0, ImageWidth, ImageHeight, false, NULL) == GIF_ERROR) { free((char *) ScanLine); PrintGifError(GifFile->Error); exit(EXIT_FAILURE); } /* Here it is - get one raw line from stdin, and dump to stdout Gif: */ GifQprintf("\n%s: Image 1 at (0, 0) [%dx%d]: ", PROGRAM_NAME, ImageWidth, ImageHeight); for (i = 0; i < ImageHeight; i++) { /* Note we assume here PixelSize == Byte, which is not necessarily */ /* so. If not - must read one byte at a time, and coerce to pixel. */ if (fread(ScanLine, 1, ImageWidth, stdin) != (unsigned)ImageWidth) { GIF_MESSAGE("RAW input file ended prematurely."); exit(EXIT_FAILURE); } for (j = 0; j < ImageWidth; j++) if (ScanLine[j] >= ColorMap->ColorCount) GIF_MESSAGE("Warning: RAW data color > maximum color map entry."); if (EGifPutLine(GifFile, ScanLine, ImageWidth) == GIF_ERROR) { free((char *) ScanLine); PrintGifError(GifFile->Error); exit(EXIT_FAILURE); } GifQprintf("\b\b\b\b%-4d", i); } if (EGifCloseFile(GifFile) == GIF_ERROR) { free((char *) ScanLine); PrintGifError(GifFile->Error); exit(EXIT_FAILURE); } free((char *) ScanLine); }
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; }
int main(int argc, char **argv) { FILE *input_file; float arg,size,rx,ry,rz; float f,fmin=1e10,fmax=-1e10; uint16_t i; uint64_t count; int xi,yi,zi,xo,yo,zo,nx,ny,nz,dx,dy,dz,x0,y0,z0,h; int **image; char format,type,comment[256]; GifFileType *GIFfile; ColorMapObject *GIFcmap; GifPixelType *GIFline; // // command line args // if (!((argc == 6) || (argc == 7) || (argc == 8) || (argc == 9) || (argc == 10) || (argc == 13) || (argc == 16) || (argc == 19))) { printf("command line: vol_gif in.vol out.gif nx ny nz [format [type [arg [size [dx dy dz [x0 y0 z0 [rx ry rz]]]]]]]\n"); printf(" in.vol = input volume file\n"); printf(" out.gif = output GIF file\n"); printf(" nx,ny,nz = x,y,z input voxel number\n"); printf(" format = 'f' for float 32, 'i' for uint16_t (default 'f')\n"); printf(" type = 's' for section, 'h' for height (default 's')\n"); printf(" arg = gamma for 's', threshold for 'h' (default 1)\n"); printf(" size = mm per voxel (default 1)\n"); printf(" dx,dy,dz = x,y,z output voxel number (default all)\n"); printf(" x0,y0,z0 = x,y,z output voxel origin (default 0)\n"); printf(" to be implemented: rx,ry,rz = view rotation angles (degrees; default 0)\n"); exit(-1); } format = 'f'; type = 's'; arg = 1; size = 1.0; rx = ry = rz = 0; sscanf(argv[3],"%d",&nx); sscanf(argv[4],"%d",&ny); sscanf(argv[5],"%d",&nz); dx = nx; dy = ny; dz = nz; x0 = y0 = z0 = 0; if (argc >= 7) { sscanf(argv[6],"%c",&format); if (!((format == 'f') || (format == 'i'))) { printf("vol_gif: oops -- format must be 'f' or 'i'\n"); exit(-1); } } if (argc >= 8) { sscanf(argv[7],"%c",&type); if (!((type == 's') || (type == 'h'))) { printf("vol_gif: oops -- type must be 's' or 'h'\n"); exit(-1); } } if (argc >= 9) { sscanf(argv[8],"%f",&arg); } if (argc >= 10) { sscanf(argv[9],"%f",&size); } if (argc >= 13) { sscanf(argv[10],"%d",&x0); sscanf(argv[11],"%d",&y0); sscanf(argv[12],"%d",&z0); } if (argc >= 16) { sscanf(argv[13],"%d",&dx); sscanf(argv[14],"%d",&dy); sscanf(argv[15],"%d",&dz); } if (argc >= 19) { sscanf(argv[16],"%f",&rx); sscanf(argv[17],"%f",&ry); sscanf(argv[18],"%f",&rz); } // // check and find limits // input_file = fopen(argv[1],"rb"); if (input_file == NULL) { printf("vol_gif: oops -- can not open %s\n",argv[1]); exit(-1); } if (((x0 + dx) > nx) || ((y0 + dy) > ny) || ((z0 + dz) > nz)) { printf("vol_gif: oops -- region too large\n"); exit(-1); } printf("read %s\n",argv[1]); if (format == 'f') { count = 0; while (fread(&f,sizeof(f),1,input_file) != 0) { if (f > fmax) fmax = f; if (f < fmin) fmin = f; count += 1; } } else if (format == 'i') { count = 0; while (fread(&i,sizeof(i),1,input_file) != 0) { if (i > fmax) fmax = i; if (i < fmin) fmin = i; count += 1; } } printf(" %" PRIu64 " points, min %f, max %f\n",count,fmin,fmax); printf(" nx ny nz: %d %d %d\n",nx,ny,nz); rewind(input_file); // // set up color map // #if GIFLIB_MAJOR >= 5 GIFcmap = GifMakeMapObject(256, NULL); #else GIFcmap = MakeMapObject(256, NULL); #endif for (i = 0; i < 256; i++) { GIFcmap->Colors[i].Red = i; GIFcmap->Colors[i].Green = i; GIFcmap->Colors[i].Blue = i; } // // open GIF file // printf("write %s\n",argv[2]); EGifPutScreenDesc(GIFfile,dx,dy,8,0,GIFcmap); unsigned char loop_count[] = {1,0,0}; #if GIFLIB_MAJOR >= 5 GIFfile = EGifOpenFileName(argv[2], 0, NULL); EGifPutExtension(GIFfile, APPLICATION_EXT_FUNC_CODE, 11, "NETSCAPE2.0"); EGifPutExtension(GIFfile, APPLICATION_EXT_FUNC_CODE, 3, loop_count); #else GIFfile = EGifOpenFileName(argv[2], 0); EGifPutExtensionFirst(GIFfile, APPLICATION_EXT_FUNC_CODE, 11, "NETSCAPE2.0"); EGifPutExtensionLast(GIFfile, APPLICATION_EXT_FUNC_CODE, 3, loop_count); #endif unsigned char delay_count[5] = { 0, // no transparency 0, // delay time 0, // delay time 0 // transparent index not used }; // // allocate image // image = malloc(dy*sizeof(int *)); for (yo = 0; yo < dy; ++yo) { image[yo] = malloc(dx*sizeof(int)); for (xo = 0; xo < dx; ++xo) image[yo][xo] = 0; } GIFline = malloc(dx*sizeof(GifPixelType)); // // scan file // xi = yi = zi = 0; for (zo = 0; zo < dz; ++zo) { printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b layer = %d",zo); EGifPutExtension(GIFfile,GRAPHICS_EXT_FUNC_CODE,4,delay_count); EGifPutImageDesc(GIFfile,0,0,dx,dy,0,NULL); // // read layer // for (yo = 0; yo < dy; ++yo) { for (xo = 0; xo < dx; ++xo) { if (format == 'f') { read_voxel_f(input_file,&f,xo+x0,yo+y0,zo+z0,&xi,&yi,&zi,nx,ny,nz); if (type == 'h') { h = 255*zo/(nz-1.0); if ((h > image[yo][xo]) && (f > arg)) image[yo][xo] = h; GIFline[xo] = image[yo][xo]*(nz-1.0)/zo; } else if (type == 's') { GIFline[xo] = 255*pow((f-fmin)/(fmax-fmin),arg); } } else if (format == 'i') { read_voxel_i(input_file,&i,xo+x0,yo+y0,zo+z0,&xi,&yi,&zi,nx,ny,nz); if (type == 'h') { h = 255*zo/(nz-1.0); if ((h > image[yo][xo]) && (i > arg)) image[yo][xo] = h; GIFline[xo] = image[yo][xo]*(nz-1.0)/zo; } else if (type == 's') { GIFline[xo] = 255*pow((i-fmin)/(fmax-fmin),arg); } } } EGifPutLine(GIFfile,GIFline,dx); } } printf("\n"); // // put mm per pixel in comment // sprintf(comment,"mm per pixel: %f;",size); EGifPutComment(GIFfile,comment); // // exit // fclose(input_file); EGifCloseFile(GIFfile); exit(0); }
GDALDataset * GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS, int bStrict, char ** papszOptions, GDALProgressFunc pfnProgress, void * pProgressData ) { int nBands = poSrcDS->GetRasterCount(); int nXSize = poSrcDS->GetRasterXSize(); int nYSize = poSrcDS->GetRasterYSize(); int bInterlace = FALSE; /* -------------------------------------------------------------------- */ /* Check for interlaced option. */ /* -------------------------------------------------------------------- */ bInterlace = CSLFetchBoolean(papszOptions, "INTERLACING", FALSE); /* -------------------------------------------------------------------- */ /* Some some rudimentary checks */ /* -------------------------------------------------------------------- */ if( nBands != 1 ) { CPLError( CE_Failure, CPLE_NotSupported, "GIF driver only supports one band images.\n" ); return NULL; } if (nXSize > 65535 || nYSize > 65535) { CPLError( CE_Failure, CPLE_NotSupported, "GIF driver only supports datasets up to 65535x65535 size.\n" ); return NULL; } if( poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte && bStrict ) { CPLError( CE_Failure, CPLE_NotSupported, "GIF driver doesn't support data type %s. " "Only eight bit bands supported.\n", GDALGetDataTypeName( poSrcDS->GetRasterBand(1)->GetRasterDataType()) ); return NULL; } /* -------------------------------------------------------------------- */ /* Open the output file. */ /* -------------------------------------------------------------------- */ GifFileType *hGifFile; VSILFILE *fp; fp = VSIFOpenL( pszFilename, "wb" ); if( fp == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Failed to create %s:\n%s", pszFilename, VSIStrerror( errno ) ); return NULL; } #if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5 int nError; hGifFile = EGifOpen( fp, VSIGIFWriteFunc, &nError ); #else hGifFile = EGifOpen( fp, VSIGIFWriteFunc ); #endif if( hGifFile == NULL ) { VSIFCloseL( fp ); CPLError( CE_Failure, CPLE_OpenFailed, "EGifOpenFilename(%s) failed. Does file already exist?", pszFilename ); return NULL; } /* -------------------------------------------------------------------- */ /* Prepare colortable. */ /* -------------------------------------------------------------------- */ GDALRasterBand *poBand = poSrcDS->GetRasterBand(1); ColorMapObject *psGifCT; int iColor; if( poBand->GetColorTable() == NULL ) { psGifCT = GifMakeMapObject( 256, NULL ); for( iColor = 0; iColor < 256; iColor++ ) { psGifCT->Colors[iColor].Red = (GifByteType) iColor; psGifCT->Colors[iColor].Green = (GifByteType) iColor; psGifCT->Colors[iColor].Blue = (GifByteType) iColor; } } else { GDALColorTable *poCT = poBand->GetColorTable(); int nFullCount = 1; while( nFullCount < poCT->GetColorEntryCount() ) nFullCount = nFullCount * 2; psGifCT = GifMakeMapObject( nFullCount, NULL ); for( iColor = 0; iColor < poCT->GetColorEntryCount(); iColor++ ) { GDALColorEntry sEntry; poCT->GetColorEntryAsRGB( iColor, &sEntry ); psGifCT->Colors[iColor].Red = (GifByteType) sEntry.c1; psGifCT->Colors[iColor].Green = (GifByteType) sEntry.c2; psGifCT->Colors[iColor].Blue = (GifByteType) sEntry.c3; } for( ; iColor < nFullCount; iColor++ ) { psGifCT->Colors[iColor].Red = 0; psGifCT->Colors[iColor].Green = 0; psGifCT->Colors[iColor].Blue = 0; } } /* -------------------------------------------------------------------- */ /* Setup parameters. */ /* -------------------------------------------------------------------- */ if (EGifPutScreenDesc(hGifFile, nXSize, nYSize, psGifCT->ColorCount, 255, psGifCT) == GIF_ERROR) { GifFreeMapObject(psGifCT); GDALPrintGifError(hGifFile, "Error writing gif file."); GIFAbstractDataset::myEGifCloseFile(hGifFile); VSIFCloseL( fp ); return NULL; } GifFreeMapObject(psGifCT); psGifCT = NULL; /* Support for transparency */ int bNoDataValue; double noDataValue = poBand->GetNoDataValue(&bNoDataValue); if (bNoDataValue && noDataValue >= 0 && noDataValue <= 255) { unsigned char extensionData[4]; extensionData[0] = 1; /* Transparent Color Flag */ extensionData[1] = 0; extensionData[2] = 0; extensionData[3] = (unsigned char)noDataValue; EGifPutExtension(hGifFile, 0xf9, 4, extensionData); } if (EGifPutImageDesc(hGifFile, 0, 0, nXSize, nYSize, bInterlace, NULL) == GIF_ERROR ) { GDALPrintGifError(hGifFile, "Error writing gif file."); GIFAbstractDataset::myEGifCloseFile(hGifFile); VSIFCloseL( fp ); return NULL; } /* -------------------------------------------------------------------- */ /* Loop over image, copying image data. */ /* -------------------------------------------------------------------- */ CPLErr eErr; GDALPamDataset *poDS; GByte *pabyScanline; pabyScanline = (GByte *) CPLMalloc( nXSize ); if( !pfnProgress( 0.0, NULL, pProgressData ) ) eErr = CE_Failure; if( !bInterlace ) { for( int iLine = 0; iLine < nYSize; iLine++ ) { eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, pabyScanline, nXSize, 1, GDT_Byte, nBands, nBands * nXSize ); if( eErr != CE_None || EGifPutLine( hGifFile, pabyScanline, nXSize ) == GIF_ERROR ) { CPLError( CE_Failure, CPLE_AppDefined, "Error writing gif file." ); goto error; } if( !pfnProgress( (iLine + 1) * 1.0 / nYSize, NULL, pProgressData ) ) { goto error; } } } else { int i, j; int nLinesRead = 0; int nLinesToRead = 0; for ( i = 0; i < 4; i++) { for (j = InterlacedOffset[i]; j < nYSize; j += InterlacedJumps[i]) { nLinesToRead ++; } } /* Need to perform 4 passes on the images: */ for ( i = 0; i < 4; i++) { for (j = InterlacedOffset[i]; j < nYSize; j += InterlacedJumps[i]) { eErr= poBand->RasterIO( GF_Read, 0, j, nXSize, 1, pabyScanline, nXSize, 1, GDT_Byte, 1, nXSize ); if (eErr != CE_None || EGifPutLine(hGifFile, pabyScanline, nXSize) == GIF_ERROR) { CPLError( CE_Failure, CPLE_AppDefined, "Error writing gif file." ); goto error; } nLinesRead ++; if( !pfnProgress( nLinesRead * 1.0 / nYSize, NULL, pProgressData ) ) { goto error; } } } } CPLFree( pabyScanline ); pabyScanline = NULL; /* -------------------------------------------------------------------- */ /* cleanup */ /* -------------------------------------------------------------------- */ if (GIFAbstractDataset::myEGifCloseFile(hGifFile) == GIF_ERROR) { CPLError( CE_Failure, CPLE_AppDefined, "EGifCloseFile() failed.\n" ); hGifFile = NULL; goto error; } hGifFile = NULL; VSIFCloseL( fp ); fp = NULL; /* -------------------------------------------------------------------- */ /* Do we need a world file? */ /* -------------------------------------------------------------------- */ if( CSLFetchBoolean( papszOptions, "WORLDFILE", FALSE ) ) { double adfGeoTransform[6]; if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None ) GDALWriteWorldFile( pszFilename, "wld", adfGeoTransform ); } /* -------------------------------------------------------------------- */ /* Re-open dataset, and copy any auxilary pam information. */ /* -------------------------------------------------------------------- */ /* If outputing to stdout, we can't reopen it, so we'll return */ /* a fake dataset to make the caller happy */ CPLPushErrorHandler(CPLQuietErrorHandler); poDS = (GDALPamDataset*) GDALOpen(pszFilename, GA_ReadOnly); CPLPopErrorHandler(); if (poDS) { poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT ); return poDS; } else { CPLErrorReset(); GIFDataset* poGIF_DS = new GIFDataset(); poGIF_DS->nRasterXSize = nXSize; poGIF_DS->nRasterYSize = nYSize; for(int i=0;i<nBands;i++) poGIF_DS->SetBand( i+1, new GIFRasterBand( poGIF_DS, i+1, NULL, 0 ) ); return poGIF_DS; } error: if (hGifFile) GIFAbstractDataset::myEGifCloseFile(hGifFile); if (fp) VSIFCloseL( fp ); if (pabyScanline) CPLFree( pabyScanline ); return NULL; }
/****************************************************************************** This routine should be called before any attempt to read an image. Note it is assumed the Image desc. header has been read. ******************************************************************************/ int DGifGetImageDesc(GifFileType *GifFile) { unsigned int BitsPerPixel; GifByteType Buf[3]; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; SavedImage *sp; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR) return GIF_ERROR; if (READ(GifFile, Buf, 1) != 1) { GifFile->Error = D_GIF_ERR_READ_FAILED; GifFreeMapObject(GifFile->Image.ColorMap); GifFile->Image.ColorMap = NULL; return GIF_ERROR; } BitsPerPixel = (Buf[0] & 0x07) + 1; GifFile->Image.Interlace = (Buf[0] & 0x40) ? giftrue : giffalse; /* Setup the colormap */ if (GifFile->Image.ColorMap) { GifFreeMapObject(GifFile->Image.ColorMap); GifFile->Image.ColorMap = NULL; } /* Does this image have local color map? */ if (Buf[0] & 0x80) { unsigned int i; GifFile->Image.ColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL); if (GifFile->Image.ColorMap == NULL) { GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } /* Get the image local color map: */ for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) { if (READ(GifFile, Buf, 3) != 3) { GifFreeMapObject(GifFile->Image.ColorMap); GifFile->Error = D_GIF_ERR_READ_FAILED; GifFile->Image.ColorMap = NULL; return GIF_ERROR; } GifFile->Image.ColorMap->Colors[i].Red = Buf[0]; GifFile->Image.ColorMap->Colors[i].Green = Buf[1]; GifFile->Image.ColorMap->Colors[i].Blue = Buf[2]; } } if (GifFile->SavedImages) { if ((GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages, sizeof(SavedImage) * (GifFile->ImageCount + 1))) == NULL) { GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } } else { if ((GifFile->SavedImages = (SavedImage *) malloc(sizeof(SavedImage))) == NULL) { GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } } sp = &GifFile->SavedImages[GifFile->ImageCount]; memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc)); if (GifFile->Image.ColorMap != NULL) { sp->ImageDesc.ColorMap = GifMakeMapObject( GifFile->Image.ColorMap->ColorCount, GifFile->Image.ColorMap->Colors); if (sp->ImageDesc.ColorMap == NULL) { GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } } sp->RasterBits = (unsigned char *)NULL; sp->ExtensionBlockCount = 0; sp->ExtensionBlocks = (ExtensionBlock *) NULL; GifFile->ImageCount++; Private->PixelCount = (long)GifFile->Image.Width * (long)GifFile->Image.Height; /* Reset decompress algorithm parameters. */ (void)DGifSetupDecompress(GifFile); return GIF_OK; }
/****************************************************************************** This routine should be called before any other EGif calls, immediately following the GIF file opening. ******************************************************************************/ int EGifPutScreenDesc(GifFileType *GifFile, const int Width, const int Height, const int ColorRes, const int BackGround, const ColorMapObject *ColorMap) { GifByteType Buf[3]; GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; const char *write_version; if (Private->FileState & FILE_STATE_SCREEN) { /* If already has screen descriptor - something is wrong! */ GifFile->Error = E_GIF_ERR_HAS_SCRN_DSCR; return GIF_ERROR; } if (!IS_WRITEABLE(Private)) { /* This file was NOT open for writing: */ GifFile->Error = E_GIF_ERR_NOT_WRITEABLE; return GIF_ERROR; } write_version = EGifGetGifVersion(GifFile); /* First write the version prefix into the file. */ if ((unsigned int)InternalWrite(GifFile, (unsigned char *)write_version, strlen(write_version)) != strlen(write_version)) { GifFile->Error = E_GIF_ERR_WRITE_FAILED; return GIF_ERROR; } GifFile->SWidth = Width; GifFile->SHeight = Height; GifFile->SColorResolution = ColorRes; GifFile->SBackGroundColor = BackGround; if (ColorMap) { GifFile->SColorMap = GifMakeMapObject(ColorMap->ColorCount, ColorMap->Colors); if (GifFile->SColorMap == NULL) { GifFile->Error = E_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } } else GifFile->SColorMap = NULL; /* * Put the logical screen descriptor into the file: */ /* Logical Screen Descriptor: Dimensions */ (void)EGifPutWord(Width, GifFile); (void)EGifPutWord(Height, GifFile); /* Logical Screen Descriptor: Packed Fields */ /* Note: We have actual size of the color table default to the largest * possible size (7+1 == 8 bits) because the decoder can use it to decide * how to display the files. */ Buf[0] = (ColorMap ? 0x80 : 0x00) | /* Yes/no global colormap */ ((ColorRes - 1) << 4) | /* Bits allocated to each primary color */ (ColorMap ? ColorMap->BitsPerPixel - 1 : 0x07 ); /* Actual size of the color table. */ if (ColorMap != NULL && ColorMap->SortFlag) Buf[0] |= 0x08; Buf[1] = BackGround; /* Index into the ColorTable for background color */ Buf[2] = GifFile->AspectByte; /* Pixel Aspect Ratio */ InternalWrite(GifFile, Buf, 3); /* If we have Global color map - dump it also: */ if (ColorMap != NULL) { int i; for (i = 0; i < ColorMap->ColorCount; i++) { /* Put the ColorMap out also: */ Buf[0] = ColorMap->Colors[i].Red; Buf[1] = ColorMap->Colors[i].Green; Buf[2] = ColorMap->Colors[i].Blue; if (InternalWrite(GifFile, Buf, 3) != 3) { GifFile->Error = E_GIF_ERR_WRITE_FAILED; return GIF_ERROR; } } } /* Mark this file as has screen descriptor, and no pixel written yet: */ Private->FileState |= FILE_STATE_SCREEN; return GIF_OK; }
/****************************************************************************** Interpret the command line and generate the given GIF file. ******************************************************************************/ int main(int argc, char **argv) { int i, j, l, GifNoisyPrint, ColorMapSize, ErrorCode; bool Error, BackGroundFlag = false, HelpFlag = false; char Line[LINE_LEN]; GifRowType RasterBuffer[GIF_FONT_HEIGHT]; ColorMapObject *ColorMap; GifFileType *GifFile; GifColorType ScratchMap[256]; int red, green, blue; if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifNoisyPrint, &BackGroundFlag, &BackGround, &HelpFlag)) != false) { GAPrintErrMsg(Error); GAPrintHowTo(CtrlStr); exit(EXIT_FAILURE); } if (HelpFlag) { (void)fprintf(stderr, VersionStr, GIFLIB_MAJOR, GIFLIB_MINOR); GAPrintHowTo(CtrlStr); exit(EXIT_SUCCESS); } /* Allocate the raster buffer for GIF_FONT_HEIGHT scan lines. */ for (i = 0; i < GIF_FONT_HEIGHT; i++) { if ((RasterBuffer[i] = (GifRowType) malloc(sizeof(GifPixelType) * IMAGEWIDTH)) == NULL) GIF_EXIT("Failed to allocate memory required, aborted."); } /* Open stdout for the output file: */ if ((GifFile = EGifOpenFileHandle(1, &ErrorCode)) == NULL) { PrintGifError(ErrorCode); exit(EXIT_FAILURE); } /* Read the color map in ColorFile into this color map: */ ColorMapSize = 0; while (fscanf(stdin, "%*3d %3d %3d %3d\n", &red, &green, &blue) == 3) { ScratchMap[ColorMapSize].Red = red; ScratchMap[ColorMapSize].Green = green; ScratchMap[ColorMapSize].Blue = blue; ColorMapSize++; } if ((ColorMap = GifMakeMapObject(1 << GifBitSize(ColorMapSize), ScratchMap)) == NULL) GIF_EXIT("Failed to allocate memory required, aborted."); if (EGifPutScreenDesc(GifFile, IMAGEWIDTH, ColorMapSize * GIF_FONT_HEIGHT, GifBitSize(ColorMapSize), BackGround, ColorMap) == GIF_ERROR) QuitGifError(GifFile); /* Dump out the image descriptor: */ if (EGifPutImageDesc(GifFile, 0, 0, IMAGEWIDTH, ColorMapSize * GIF_FONT_HEIGHT, false, NULL) == GIF_ERROR) QuitGifError(GifFile); GifQprintf("\n%s: Image 1 at (%d, %d) [%dx%d]: ", PROGRAM_NAME, GifFile->Image.Left, GifFile->Image.Top, GifFile->Image.Width, GifFile->Image.Height); for (i = l = 0; i < ColorMap->ColorCount; i++) { (void)snprintf(Line, sizeof(Line), "Color %-3d: [%-3d, %-3d, %-3d] ", i, ColorMap->Colors[i].Red, ColorMap->Colors[i].Green, ColorMap->Colors[i].Blue); GenRasterTextLine(RasterBuffer, Line, IMAGEWIDTH, i); for (j = 0; j < GIF_FONT_HEIGHT; j++) { if (EGifPutLine(GifFile, RasterBuffer[j], IMAGEWIDTH) == GIF_ERROR) QuitGifError(GifFile); GifQprintf("\b\b\b\b%-4d", l++); } } if (EGifCloseFile(GifFile, &ErrorCode) == GIF_ERROR) { PrintGifError(ErrorCode); if (GifFile != NULL) { EGifCloseFile(GifFile, NULL); } exit(EXIT_FAILURE); } return 0; }
bool toGif(QImage& img, QString& path) { int errcode; if(QFile(path).exists()) // Remove old file QFile::remove(path); GifFileType* t = EGifOpenFileName(path.toLocal8Bit().data(),true, &errcode); if(!t){ EGifCloseFile(t, &errcode); QTextStream(stdout) << "Can't open\n"; return false; } EGifSetGifVersion(t, true); GifColorType* colorArr = new GifColorType[256]; ColorMapObject* cmo = GifMakeMapObject(256, colorArr); bool unfinished = false; QImage tarQImg(img.width(), img.height(), QImage::Format_Indexed8); QVector<QRgb> table; for(int y = 0; y < img.height(); y++){ for(int x = 0; x < img.width(); x++){ if(table.size() >= 256){ unfinished = true; break; } QRgb pix; if(!table.contains(pix = img.pixel(x,y))){ table.push_back(pix); tarQImg.setColor(tarQImg.colorCount(), pix); } tarQImg.setPixel(x,y,table.indexOf(pix)); } if(table.size() >= 256){ unfinished = true; break; } } if(unfinished){ EGifCloseFile(t, &errcode); QTextStream(stdout) << "Unfinished\n"; return false; } for(int l = tarQImg.colorCount(); l < 256; l++){ tarQImg.setColor(l,0); } if(tarQImg.colorTable().size() != 256){ EGifCloseFile(t, &errcode); QTextStream(stdout) << "A lot of colors\n"; return false; } QVector<QRgb> clTab = tarQImg.colorTable(); for(int i = 0; i < 255; i++){ QRgb rgb = clTab[i]; colorArr[i].Red = qRed(rgb); colorArr[i].Green = qGreen(rgb); colorArr[i].Blue = qBlue(rgb); } cmo->Colors = colorArr; errcode = EGifPutScreenDesc(t, img.width(), img.height(), 256, 0, cmo); if(errcode != GIF_OK){ EGifCloseFile(t, &errcode); QTextStream(stdout) << "EGifPutScreenDesc error 1\n"; return false; } errcode = EGifPutImageDesc(t, 0, 0, img.width(), img.height(), false, 0); if(errcode != GIF_OK){ EGifCloseFile(t, &errcode); QTextStream(stdout) << "EGifPutImageDesc error 2\n"; return false; } //gen byte array GifByteType* byteArr = tarQImg.bits(); for(int h = 0; h < tarQImg.height(); h++){ errcode = EGifPutLine(t, byteArr, tarQImg.width()); if(errcode != GIF_OK){ EGifCloseFile(t, &errcode); QTextStream(stdout) << "EGifPutLine error 3\n"; return false; } byteArr += tarQImg.width(); byteArr += ((tarQImg.width() % 4)!=0 ? 4 - (tarQImg.width() % 4) : 0); } if(errcode != GIF_OK){ QTextStream(stdout) << "GIF error 4\n"; return false; } EGifCloseFile(t, &errcode); return true; }
//读取单个帧的图片信息(图片的上下左右坐标,帧的局部颜色空间等) int DGifGetImageDesc(GifFileType *GifFile) { unsigned int BitsPerPixel; GifByteType Buf[3]; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; SavedImage *sp; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } //读取当前帧的上下左右坐标 if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR) return GIF_ERROR; //读取长度1字节的信息(即当前帧的Packed Field) if (READ(GifFile, Buf, 1) != 1) { GifFile->Error = D_GIF_ERR_READ_FAILED; GifFreeMapObject(GifFile->Image.ColorMap); GifFile->Image.ColorMap = NULL; return GIF_ERROR; } //局部颜色空间的大小 BitsPerPixel = (Buf[0] & 0x07) + 1; //判断当前帧是否交错模式 GifFile->Image.Interlace = (Buf[0] & 0x40) ? true : false; /* Setup the colormap */ if (GifFile->Image.ColorMap) { GifFreeMapObject(GifFile->Image.ColorMap); GifFile->Image.ColorMap = NULL; } //判断当前帧是否使用局部的颜色空间 if (Buf[0] & 0x80) { unsigned int i; GifFile->Image.ColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL); if (GifFile->Image.ColorMap == NULL) { GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } //获取局部颜色空间 并储存到临时的帧描述内 for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) { /* coverity[check_return] */ if (READ(GifFile, Buf, 3) != 3) { GifFreeMapObject(GifFile->Image.ColorMap); GifFile->Error = D_GIF_ERR_READ_FAILED; GifFile->Image.ColorMap = NULL; return GIF_ERROR; } GifFile->Image.ColorMap->Colors[i].Red = Buf[0]; GifFile->Image.ColorMap->Colors[i].Green = Buf[1]; GifFile->Image.ColorMap->Colors[i].Blue = Buf[2]; } } //判断之前是否已经有储存帧图像 if (GifFile->SavedImages) { //如果有已经储存的帧图像 需要重新分配空间 SavedImage* new_saved_images = (SavedImage *)realloc(GifFile->SavedImages, sizeof(SavedImage) * (GifFile->ImageCount + 1)); if (new_saved_images == NULL) { GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } GifFile->SavedImages = new_saved_images; } else { if ((GifFile->SavedImages = (SavedImage *) malloc(sizeof(SavedImage))) == NULL) { GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } } //指向新的SavedImage sp = &GifFile->SavedImages[GifFile->ImageCount]; //写入之前获取的帧图像描述 memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc)); //写入局部颜色空间 if (GifFile->Image.ColorMap != NULL) { sp->ImageDesc.ColorMap = GifMakeMapObject( GifFile->Image.ColorMap->ColorCount, GifFile->Image.ColorMap->Colors); if (sp->ImageDesc.ColorMap == NULL) { GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } } sp->RasterBits = (unsigned char *)NULL; sp->ExtensionBlockCount = 0; sp->ExtensionBlocks = (ExtensionBlock *) NULL; GifFile->ImageCount++; Private->PixelCount = (long)GifFile->Image.Width * (long)GifFile->Image.Height; /* Reset decompress algorithm parameters. */ //DGifSetupDecompress return DGifSetupDecompress(GifFile); }
/*! * \brief pixToGif() * * \param[in] pix 1, 2, 4, 8, 16 or 32 bpp * \param[in] gif opened gif stream * \return 0 if OK, 1 on error * * <pre> * Notes: * (1) This encodes the pix to the gif stream. The stream is not * closes by this function. * (2) It is static to make this function private. * </pre> */ static l_int32 pixToGif(PIX *pix, GifFileType *gif) { char *text; l_int32 wpl, i, j, w, h, d, ncolor, rval, gval, bval; l_int32 gif_ncolor = 0; l_uint32 *data, *line; PIX *pixd; PIXCMAP *cmap; ColorMapObject *gif_cmap; GifByteType *gif_line; #if (GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1) || GIFLIB_MAJOR > 5 int giferr; #endif /* 5.1 and beyond */ PROCNAME("pixToGif"); if (!pix) return ERROR_INT("pix not defined", procName, 1); if (!gif) return ERROR_INT("gif not defined", procName, 1); d = pixGetDepth(pix); if (d == 32) { pixd = pixConvertRGBToColormap(pix, 1); } else if (d > 1) { pixd = pixConvertTo8(pix, TRUE); } else { /* d == 1; make sure there's a colormap */ pixd = pixClone(pix); if (!pixGetColormap(pixd)) { cmap = pixcmapCreate(1); pixcmapAddColor(cmap, 255, 255, 255); pixcmapAddColor(cmap, 0, 0, 0); pixSetColormap(pixd, cmap); } } if (!pixd) return ERROR_INT("failed to convert image to indexed", procName, 1); d = pixGetDepth(pixd); if ((cmap = pixGetColormap(pixd)) == NULL) { pixDestroy(&pixd); return ERROR_INT("cmap is missing", procName, 1); } /* 'Round' the number of gif colors up to a power of 2 */ ncolor = pixcmapGetCount(cmap); for (i = 0; i <= 8; i++) { if ((1 << i) >= ncolor) { gif_ncolor = (1 << i); break; } } if (gif_ncolor < 1) { pixDestroy(&pixd); return ERROR_INT("number of colors is invalid", procName, 1); } /* Save the cmap colors in a gif_cmap */ if ((gif_cmap = GifMakeMapObject(gif_ncolor, NULL)) == NULL) { pixDestroy(&pixd); return ERROR_INT("failed to create GIF color map", procName, 1); } for (i = 0; i < gif_ncolor; i++) { rval = gval = bval = 0; if (ncolor > 0) { if (pixcmapGetColor(cmap, i, &rval, &gval, &bval) != 0) { pixDestroy(&pixd); GifFreeMapObject(gif_cmap); return ERROR_INT("failed to get color from color map", procName, 1); } ncolor--; } gif_cmap->Colors[i].Red = rval; gif_cmap->Colors[i].Green = gval; gif_cmap->Colors[i].Blue = bval; } pixGetDimensions(pixd, &w, &h, NULL); if (EGifPutScreenDesc(gif, w, h, gif_cmap->BitsPerPixel, 0, gif_cmap) != GIF_OK) { pixDestroy(&pixd); GifFreeMapObject(gif_cmap); return ERROR_INT("failed to write screen description", procName, 1); } GifFreeMapObject(gif_cmap); /* not needed after this point */ if (EGifPutImageDesc(gif, 0, 0, w, h, FALSE, NULL) != GIF_OK) { pixDestroy(&pixd); return ERROR_INT("failed to image screen description", procName, 1); } data = pixGetData(pixd); wpl = pixGetWpl(pixd); if (d != 1 && d != 2 && d != 4 && d != 8) { pixDestroy(&pixd); return ERROR_INT("image depth is not in {1, 2, 4, 8}", procName, 1); } if ((gif_line = (GifByteType *)LEPT_CALLOC(sizeof(GifByteType), w)) == NULL) { pixDestroy(&pixd); return ERROR_INT("mem alloc fail for data line", procName, 1); } for (i = 0; i < h; i++) { line = data + i * wpl; /* Gif's way of setting the raster line up for compression */ for (j = 0; j < w; j++) { switch(d) { case 8: gif_line[j] = GET_DATA_BYTE(line, j); break; case 4: gif_line[j] = GET_DATA_QBIT(line, j); break; case 2: gif_line[j] = GET_DATA_DIBIT(line, j); break; case 1: gif_line[j] = GET_DATA_BIT(line, j); break; } } /* Compress and save the line */ if (EGifPutLine(gif, gif_line, w) != GIF_OK) { LEPT_FREE(gif_line); pixDestroy(&pixd); return ERROR_INT("failed to write data line into GIF", procName, 1); } } /* Write a text comment. This must be placed after writing the * data (!!) Note that because libgif does not provide a function * for reading comments from file, you will need another way * to read comments. */ if ((text = pixGetText(pix)) != NULL) { if (EGifPutComment(gif, text) != GIF_OK) L_WARNING("gif comment not written\n", procName); } LEPT_FREE(gif_line); pixDestroy(&pixd); return 0; }
/****************************************************************************** Interpret the command line and scan the given GIF file. ******************************************************************************/ int main(int argc, char **argv) { unsigned int Ratio; int i, l, LevelWidth, LogNumLevels, ErrorCode, Count = 0; bool Error, FlipDir, DoAllMaximum = false, DirectionFlag = false, LevelsFlag = false, ColorFlag = false, MinFlag = false, MaxFlag = false, SizeFlag = false, HelpFlag = false; GifPixelType Color; char *DirectionStr = DEFAULT_DIR; GifRowType Line; ColorMapObject *ColorMap; GifFileType *GifFile; if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifNoisyPrint, &DirectionFlag, &DirectionStr, &LevelsFlag, &NumLevels, &ColorFlag, &RedColor, &GreenColor, &BlueColor, &MinFlag, &MinimumIntensity, &MaxFlag, &MaximumIntensity, &SizeFlag, &ImageWidth, &ImageHeight, &HelpFlag)) != false) { GAPrintErrMsg(Error); GAPrintHowTo(CtrlStr); exit(EXIT_FAILURE); } if (HelpFlag) { (void)fprintf(stderr, VersionStr, GIFLIB_MAJOR, GIFLIB_MINOR); GAPrintHowTo(CtrlStr); exit(EXIT_SUCCESS); } /* Make sure intensities are in the right range: */ if (MinimumIntensity < 0 || MinimumIntensity > 100 || MaximumIntensity < 0 || MaximumIntensity > 100) GIF_EXIT("Intensities (-m or -M options) are not in [0..100] range (percent)."); /* Convert DirectionStr to our local representation: */ Direction = DIR_NONE; FlipDir = false; /* Make sure it's upper case. */ for (i = 0; i < (int)strlen(DirectionStr); i++) if (islower(DirectionStr[i])) DirectionStr[i] = toupper(DirectionStr[i]); switch(DirectionStr[0]) { case 'T': /* Top or North */ case 'N': if (strlen(DirectionStr) < 2) Direction = DIR_TOP; else switch(DirectionStr[1]) { case 'R': case 'E': Direction = DIR_TOP_RIGHT; break; case 'L': case 'W': Direction = DIR_TOP_LEFT; FlipDir = true; break; } break; case 'R': /* Right or East */ case 'E': Direction = DIR_RIGHT; break; case 'B': /* Bottom or South */ case 'S': if (strlen(DirectionStr) < 2) { Direction = DIR_BOT; FlipDir = true; } else switch(DirectionStr[1]) { case 'R': case 'E': Direction = DIR_BOT_RIGHT; break; case 'L': case 'W': Direction = DIR_BOT_LEFT; FlipDir = true; break; } break; case 'L': /* Left or West */ case 'W': Direction = DIR_LEFT; FlipDir = true; break; } if (Direction == DIR_NONE) GIF_EXIT("Direction requested (-d option) is weird!"); /* We are going to handle only TOP, TOP_RIGHT, RIGHT, BOT_RIGHT so flip */ /* the complement cases (TOP <-> BOT for example) by flipping the */ /* Color i with color (NumLevels - i - 1). */ if (FlipDir) { switch (Direction) { case DIR_BOT: Direction = DIR_TOP; break; case DIR_BOT_LEFT: Direction = DIR_TOP_RIGHT; break; case DIR_LEFT: Direction = DIR_RIGHT; break; case DIR_TOP_LEFT: Direction = DIR_BOT_RIGHT; break; } } /* If binary mask is requested (special case): */ if (MinimumIntensity == 100 && MaximumIntensity == 100 && NumLevels == 2) { MinimumIntensity = 0; DoAllMaximum = true; Direction = DIR_RIGHT; } /* Make sure colors are in the right range: */ if (RedColor > 255 || GreenColor > 255 || BlueColor > 255) GIF_EXIT("Colors are not in the ragne [0..255]."); /* Make sure number of levels is power of 2 (up to 8 bits per pixel). */ for (i = 1; i < 8; i++) if (NumLevels == (1 << i)) break; if (i == 8) GIF_EXIT("#Lvls (-l option) is not power of 2."); LogNumLevels = i; /* Open stdout for the output file: */ if ((GifFile = EGifOpenFileHandle(1, &ErrorCode)) == NULL) { PrintGifError(ErrorCode); exit(EXIT_FAILURE); } /* Dump out screen description with given size and generated color map: */ if ((ColorMap = GifMakeMapObject(NumLevels, NULL)) == NULL) GIF_EXIT("Failed to allocate memory required, aborted."); for (i = 1; i <= NumLevels; i++) { /* Ratio will be in the range of 0..100 for required intensity: */ Ratio = (MaximumIntensity * (i * (256 / NumLevels)) + MinimumIntensity * ((NumLevels - i) * (256 / NumLevels))) / 256; ColorMap->Colors[i-1].Red = (RedColor * Ratio) / 100; ColorMap->Colors[i-1].Green = (GreenColor * Ratio) / 100; ColorMap->Colors[i-1].Blue = (BlueColor * Ratio) / 100; } if (EGifPutScreenDesc(GifFile, ImageWidth, ImageHeight, LogNumLevels, 0, ColorMap) == GIF_ERROR) QuitGifError(GifFile); /* Dump out the image descriptor: */ if (EGifPutImageDesc(GifFile, 0, 0, ImageWidth, ImageHeight, false, NULL) == GIF_ERROR) QuitGifError(GifFile); GifQprintf("\n%s: Image 1 at (%d, %d) [%dx%d]: ", PROGRAM_NAME, GifFile->Image.Left, GifFile->Image.Top, GifFile->Image.Width, GifFile->Image.Height); /* Allocate one scan line twice as big as image is, as we are going to */ /* shift along it, while we dump the scan lines: */ if ((Line = (GifRowType) malloc(sizeof(GifPixelType) * ImageWidth * 2)) == NULL) GIF_EXIT("Failed to allocate memory required, aborted."); if (Direction == DIR_TOP) { int LevelHeight; /* We must evaluate the line each time level is changing: */ LevelHeight = ImageHeight / NumLevels; for (Color = NumLevels, i = l = 0; i < ImageHeight; i++) { if (i == l) { int j; /* Time to update the line to next color level: */ if (Color != 0) Color--; for (j = 0; j < ImageWidth; j++) Line[j] = (FlipDir ? NumLevels - Color - 1 : Color); l += LevelHeight; } if (EGifPutLine(GifFile, Line, ImageWidth) == GIF_ERROR) QuitGifError(GifFile); GifQprintf("\b\b\b\b%-4d", Count++); } } else if (Direction == DIR_RIGHT) { /* We pre-prepare the scan lines as going from color zero to maximum */ /* color and dump the same scan line Height times: */ /* Note this case should handle the Boolean Mask special case. */ LevelWidth = ImageWidth / NumLevels; if (DoAllMaximum) { /* Special case - do all in maximum color: */ for (i = 0; i < ImageWidth; i++) Line[i] = 1; } else { for (Color = i = 0, l = LevelWidth; i < ImageWidth; i++, l--) { if (l == 0) { l = LevelWidth; if (Color < NumLevels - 1) Color++; } Line[i] = (FlipDir ? NumLevels - Color - 1 : Color); } } for (i = 0; i < ImageHeight; i++) { /* coverity[uninit_use_in_call] */ if (EGifPutLine(GifFile, Line, ImageWidth) == GIF_ERROR) QuitGifError(GifFile); GifQprintf("\b\b\b\b%-4d", Count++); } } else { int Accumulator, StartX, StepX; /* We are in one of the TOP_RIGHT, BOT_RIGHT cases: we will */ /* initialize the Line with its double ImageWidth length from the */ /* minimum intensity to the maximum intensity and shift along it */ /* while we go along the image height. */ LevelWidth = ImageWidth * 2 / NumLevels; for (Color = i = 0, l = LevelWidth; i < ImageWidth * 2; i++, l--) { if (l == 0) { l = LevelWidth; if (Color < NumLevels - 1) Color++; } Line[i] = (FlipDir ? NumLevels - Color - 1 : Color); } /* We need to implement a DDA to know how much to shift Line while */ /* we go down along image height. we set the parameters for it now: */ Accumulator = 0; switch(Direction) { case DIR_TOP_RIGHT: StartX = ImageWidth; StepX = -1; break; case DIR_BOT_RIGHT: default: StartX = 0; StepX = 1; break; } /* Time to dump information out: */ for (i = 0; i < ImageHeight; i++) { if (EGifPutLine(GifFile, &Line[StartX], ImageWidth) == GIF_ERROR) QuitGifError(GifFile); GifQprintf("\b\b\b\b%-4d", Count++); if ((Accumulator += ImageWidth) > ImageHeight) { while (Accumulator > ImageHeight) { Accumulator -= ImageHeight; StartX += StepX; } if (Direction < 0) Direction = 0; if (Direction > ImageWidth) Direction = ImageWidth; } } } if (EGifCloseFile(GifFile, &ErrorCode) == GIF_ERROR) { PrintGifError(ErrorCode); exit(EXIT_FAILURE); } return 0; }
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; }
/****************************************************************************** Interpret the command line and generate the given GIF file. ******************************************************************************/ int main(int argc, char **argv) { int i, j, l, ImageWidth, ImageHeight, NumOfLines, LogNumLevels, ErrorCode, NumLevels, ColorMapSize = 1, ForeGroundIndex = DEFAULT_FG_INDEX; bool Error, ClrMapSizeFlag = false, ForeGroundFlag = false, TextLineFlag = false, HelpFlag = false, ColorFlag = false; char *TextLines[MAX_NUM_TEXT_LINES], Line[LINE_LEN]; GifRowType RasterBuffer[GIF_FONT_HEIGHT]; ColorMapObject *ColorMap; GifFileType *GifFile; if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifNoisyPrint, &ClrMapSizeFlag, &ColorMapSize, &ForeGroundFlag, &ForeGroundIndex, &ColorFlag, &RedColor, &GreenColor, &BlueColor, &TextLineFlag, &TextLines[0], &HelpFlag)) != false) { GAPrintErrMsg(Error); GAPrintHowTo(CtrlStr); exit(EXIT_FAILURE); } if (HelpFlag) { (void)fprintf(stderr, VersionStr, GIFLIB_MAJOR, GIFLIB_MINOR); GAPrintHowTo(CtrlStr); exit(EXIT_SUCCESS); } if (ForeGroundIndex > 255 || ForeGroundIndex < 1) GIF_EXIT("Foregound (-f) should be in the range 1..255, aborted."); if (ColorMapSize > 8 || ColorMapSize < 1) GIF_EXIT("ColorMapSize (-s) should be in the range 1..8, aborted."); if (TextLineFlag) { NumOfLines = 1; ImageHeight = GIF_FONT_HEIGHT; ImageWidth = GIF_FONT_WIDTH * strlen(TextLines[0]); } else { NumOfLines = l = 0; while (fgets(Line, LINE_LEN - 1, stdin)) { for (i = strlen(Line); i > 0 && Line[i-1] <= ' '; i--); Line[i] = 0; if (l < i) l = i; TextLines[NumOfLines++] = strdup(Line); if (NumOfLines == MAX_NUM_TEXT_LINES) GIF_EXIT("Input file has too many lines, aborted."); } if (NumOfLines == 0) GIF_EXIT("No input text, aborted."); ImageHeight = GIF_FONT_HEIGHT * NumOfLines; ImageWidth = GIF_FONT_WIDTH * l; } /* Allocate the raster buffer for GIF_FONT_HEIGHT scan lines (one text line). */ for (i = 0; i < GIF_FONT_HEIGHT; i++) if ((RasterBuffer[i] = (GifRowType) malloc(sizeof(GifPixelType) * ImageWidth)) == NULL) GIF_EXIT("Failed to allocate memory required, aborted."); /* Open stdout for the output file: */ if ((GifFile = EGifOpenFileHandle(1, &ErrorCode)) == NULL) { PrintGifError(ErrorCode); exit(EXIT_FAILURE); } /* Dump out screen description with given size and generated color map: */ for (LogNumLevels = 1, NumLevels = 2; NumLevels < ForeGroundIndex; LogNumLevels++, NumLevels <<= 1); if (NumLevels < (1 << ColorMapSize)) { NumLevels = (1 << ColorMapSize); LogNumLevels = ColorMapSize; } if ((ColorMap = GifMakeMapObject(NumLevels, NULL)) == NULL) GIF_EXIT("Failed to allocate memory required, aborted."); for (i = 0; i < NumLevels; i++) ColorMap->Colors[i].Red = ColorMap->Colors[i].Green = ColorMap->Colors[i].Blue = 0; ColorMap->Colors[ForeGroundIndex].Red = RedColor; ColorMap->Colors[ForeGroundIndex].Green = GreenColor; ColorMap->Colors[ForeGroundIndex].Blue = BlueColor; if (EGifPutScreenDesc(GifFile, ImageWidth, ImageHeight, LogNumLevels, 0, ColorMap) == GIF_ERROR) QuitGifError(GifFile); /* Dump out the image descriptor: */ if (EGifPutImageDesc(GifFile, 0, 0, ImageWidth, ImageHeight, false, NULL) == GIF_ERROR) QuitGifError(GifFile); GifQprintf("\n%s: Image 1 at (%d, %d) [%dx%d]: ", PROGRAM_NAME, GifFile->Image.Left, GifFile->Image.Top, GifFile->Image.Width, GifFile->Image.Height); for (i = l = 0; i < NumOfLines; i++) { GenRasterTextLine(RasterBuffer, TextLines[i], ImageWidth, ForeGroundIndex); for (j = 0; j < GIF_FONT_HEIGHT; j++) { if (EGifPutLine(GifFile, RasterBuffer[j], ImageWidth) == GIF_ERROR) QuitGifError(GifFile); GifQprintf("\b\b\b\b%-4d", l++); } } if (EGifCloseFile(GifFile) == GIF_ERROR) QuitGifError(GifFile); return 0; }