/****************************************************************************** * Handle last GIF error. Try to close the file and free all allocated memory. * ******************************************************************************/ static int HandleGifError(GifFileType *GifFile) { int i = GifLastError(); if (EGifCloseFile(GifFile) == GIF_ERROR) { GifLastError(); } return i; }
static int gif_err(GifFileType *gf) { #if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5 return gf->Error; #else (void) gf; return GifLastError(); #endif }
void GIFInput::report_last_error (void) { // N.B. Only GIFLIB_MAJOR >= 5 looks properly thread-safe, in that the // error is guaranteed to be specific to this open file. We use a spin // mutex to prevent a thread clash for older versions, but it still // appears to be a global call, so we can't be absolutely sure that the // error was for *this* file. So if you're using giflib prior to // version 5, beware. #if GIFLIB_MAJOR >= 5 error ("%s", GifErrorString (m_gif_file->Error)); #elif GIFLIB_MAJOR == 4 && GIFLIB_MINOR >= 2 spin_lock lock (gif_error_mutex); error ("%s", GifErrorString()); #else spin_lock lock (gif_error_mutex); error ("GIF error %d", GifLastError()); #endif }
/****************************************************************************** * Interpret the command line, prepar global data and call the Gif routines. * ******************************************************************************/ void main(int argc, char **argv) { int Error, NumFiles, ImageWidth, ImageHeight, Dummy, Red, Green, Blue, ColorMapSize, InFileHandle, ImageSizeFlag = FALSE, ColorMapFlag = FALSE, HelpFlag = FALSE; char **FileName = NULL, *ColorMapFile; GifColorType *ColorMap; FILE *InColorMapFile; if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifQuitePrint, &ImageSizeFlag, &ImageWidth, &ImageHeight, &ColorMapFlag, &ColorMapFile, &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(1); } if (HelpFlag) { fprintf(stderr, VersionStr); GAPrintHowTo(CtrlStr); exit(0); } if (ColorMapFlag) { /* Read color map from given file: */ if ((InColorMapFile = fopen(ColorMapFile, "rt")) == NULL) { GIF_MESSAGE("Failed to open COLOR MAP file (not exists!?)."); exit(2); } if ((ColorMap = (GifColorType *) malloc(sizeof(GifColorType) * 255)) /* Biggest map. */ == NULL) { GIF_MESSAGE("Failed to allocate bitmap, aborted."); exit(3); } for (ColorMapSize = 0; ColorMapSize < 256 && !feof(InColorMapFile); ColorMapSize++) { fscanf(InColorMapFile, "%3d %3d %3d %3d\n", &Dummy, &Red, &Green, &Blue); ColorMap[ColorMapSize].Red = Red; ColorMap[ColorMapSize].Green = Green; ColorMap[ColorMapSize].Blue = Blue; } } else { ColorMap = EGAPallete; ColorMapSize = EGA_PALLETE_SIZE; } if (NumFiles == 1) { #ifdef __MSDOS__ if ((InFileHandle = open(*FileName, O_RDONLY | O_BINARY)) == -1) { #else if ((InFileHandle = open(*FileName, O_RDONLY)) == -1) { #endif /* __MSDOS__ */ GIF_MESSAGE("Failed to open RAW image file (not exists!?)."); exit(2); } dup2(InFileHandle, 0); /* Make stdin from this file. */ } else { #ifdef __MSDOS__ setmode(0, O_BINARY); /* Make sure it is in binary mode. */ #endif /* __MSDOS__ */ } #ifdef __MSDOS__ setvbuf(stdin, NULL, _IOFBF, GIF_FILE_BUFFER_SIZE); #endif /* __MSDOS__ */ /* Conver Raw image from stdin to Gif file in stdout: */ Raw2Gif(ImageWidth, ImageHeight, ColorMap, ColorMapSize); } /****************************************************************************** * 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. * ******************************************************************************/ int Raw2Gif(int ImageWidth, int ImageHeight, GifColorType *ColorMap, int ColorMapSize) { static int BitsPerPixelArray[] = { 2, 4 ,8, 16, 32, 64, 128, 256 }; int i, j, BitsPerPixel; static GifPixelType *ScanLine; GifFileType *GifFile; for (BitsPerPixel = 0; BitsPerPixel < 8 && BitsPerPixelArray[BitsPerPixel] != ColorMapSize; BitsPerPixel++); if (++BitsPerPixel > 8) { GIF_MESSAGE("Number of color map is NOT power of 2 up to 256."); exit(3); } if ((ScanLine = (GifPixelType *) malloc(sizeof(GifPixelType) * ImageWidth)) == NULL) { GIF_MESSAGE("Failed to allocate scan line, aborted."); exit(3); } if ((GifFile = EGifOpenFileHandle(1)) == NULL) { /* Gif to stdout. */ free((char *) ScanLine); return HandleGifError(GifFile); } if (EGifPutScreenDesc(GifFile, ImageWidth, ImageHeight, BitsPerPixel, 0, BitsPerPixel, ColorMap) == GIF_ERROR) { free((char *) ScanLine); return HandleGifError(GifFile); } if (EGifPutImageDesc(GifFile, 0, 0, ImageWidth, ImageHeight, FALSE, 1, NULL) == GIF_ERROR) { free((char *) ScanLine); return HandleGifError(GifFile); } /* 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) != ImageWidth) { GIF_MESSAGE("RAW input file ended prematurely."); exit(3); } for (j = 0; j < ImageWidth; j++) if (ScanLine[j] >= ColorMapSize) GIF_MESSAGE("Warning: RAW data color > maximum color map entry."); if (EGifPutLine(GifFile, ScanLine, ImageWidth) == GIF_ERROR) { free((char *) ScanLine); return HandleGifError(GifFile); } GifQprintf("\b\b\b\b%-4d", i); } if (EGifCloseFile(GifFile) == GIF_ERROR) { free((char *) ScanLine); return HandleGifError(GifFile); } free((char *) ScanLine); return 0; } /****************************************************************************** * Handle last GIF error. Try to close the file and free all allocated memory. * ******************************************************************************/ static int HandleGifError(GifFileType *GifFile) { int i = GifLastError(); if (EGifCloseFile(GifFile) == GIF_ERROR) { GifLastError(); } return i; }
/* * Partially based on code in gif2rgb from giflib, by Gershon Elber. */ RImage *RLoadGIF(const char *file, int index) { RImage *image = NULL; unsigned char *cptr; GifFileType *gif = NULL; GifPixelType *buffer = NULL; int i, j, k; int width, height; GifRecordType recType; ColorMapObject *colormap; unsigned char rmap[256]; unsigned char gmap[256]; unsigned char bmap[256]; if (index < 0) index = 0; /* default error message */ RErrorCode = RERR_BADINDEX; gif = DGifOpenFileName(file); if (!gif) { switch (GifLastError()) { case D_GIF_ERR_OPEN_FAILED: RErrorCode = RERR_OPEN; break; case D_GIF_ERR_READ_FAILED: RErrorCode = RERR_READ; break; default: RErrorCode = RERR_BADIMAGEFILE; break; } return NULL; } if (gif->SWidth < 1 || gif->SHeight < 1) { DGifCloseFile(gif); RErrorCode = RERR_BADIMAGEFILE; return NULL; } colormap = gif->SColorMap; i = 0; do { int extCode; GifByteType *extension; if (DGifGetRecordType(gif, &recType) == GIF_ERROR) { goto giferr; } switch (recType) { case IMAGE_DESC_RECORD_TYPE: if (i++ != index) break; if (DGifGetImageDesc(gif) == GIF_ERROR) { goto giferr; } width = gif->Image.Width; height = gif->Image.Height; if (gif->Image.ColorMap) colormap = gif->Image.ColorMap; /* the gif specs talk about a default colormap, but it * doesnt say what the heck is this default colormap */ if (!colormap) { /* * Well, since the spec says the colormap can be anything, * lets just render it with whatever garbage the stack * has :) * goto bye; */ } else { for (j = 0; j < colormap->ColorCount; j++) { rmap[j] = colormap->Colors[j].Red; gmap[j] = colormap->Colors[j].Green; bmap[j] = colormap->Colors[j].Blue; } } buffer = malloc(width * sizeof(GifColorType)); if (!buffer) { RErrorCode = RERR_NOMEMORY; goto bye; } image = RCreateImage(width, height, False); if (!image) { goto bye; } if (gif->Image.Interlace) { int l; int pelsPerLine; if (RRGBAFormat == image->format) pelsPerLine = width * 4; else pelsPerLine = width * 3; for (j = 0; j < 4; j++) { for (k = InterlacedOffset[j]; k < height; k += InterlacedJumps[j]) { if (DGifGetLine(gif, buffer, width) == GIF_ERROR) { goto giferr; } cptr = image->data + (k * pelsPerLine); for (l = 0; l < width; l++) { int pixel = buffer[l]; *cptr++ = rmap[pixel]; *cptr++ = gmap[pixel]; *cptr++ = bmap[pixel]; } } } } else { cptr = image->data; for (j = 0; j < height; j++) { if (DGifGetLine(gif, buffer, width) == GIF_ERROR) { goto giferr; } for (k = 0; k < width; k++) { int pixel = buffer[k]; *cptr++ = rmap[pixel]; *cptr++ = gmap[pixel]; *cptr++ = bmap[pixel]; if (RRGBAFormat == image->format) cptr++; } } } break; case EXTENSION_RECORD_TYPE: /* skip all extension blocks */ if (DGifGetExtension(gif, &extCode, &extension) == GIF_ERROR) { goto giferr; } while (extension) { if (DGifGetExtensionNext(gif, &extension) == GIF_ERROR) { goto giferr; } } break; default: break; } } while (recType != TERMINATE_RECORD_TYPE && i <= index); /* yuck! */ goto did_not_get_any_errors; giferr: switch (GifLastError()) { case D_GIF_ERR_OPEN_FAILED: RErrorCode = RERR_OPEN; break; case D_GIF_ERR_READ_FAILED: RErrorCode = RERR_READ; break; default: RErrorCode = RERR_BADIMAGEFILE; break; } bye: if (image) RReleaseImage(image); image = NULL; did_not_get_any_errors: if (buffer) free(buffer); if (gif) DGifCloseFile(gif); return image; }
GifException::GifException() : runtime_error("Gif Error: " + GifLastError()), code_(GifLastError()) { }