static void GDALPrintGifError( #if GIFLIB_MAJOR < 5 CPL_UNUSED #endif GifFileType *hGifFile, const char* pszMsg) { /* GIFLIB_MAJOR is only defined in libgif >= 4.2.0 */ /* libgif 4.2.0 has retired PrintGifError() and added GifErrorString() */ #if defined(GIFLIB_MAJOR) && defined(GIFLIB_MINOR) && \ ((GIFLIB_MAJOR == 4 && GIFLIB_MINOR >= 2) || GIFLIB_MAJOR > 4) /* Static string actually, hence the const char* cast */ #if GIFLIB_MAJOR >= 5 const char* pszGIFLIBError = (const char*) GifErrorString(hGifFile->Error); #else const char* pszGIFLIBError = (const char*) GifErrorString(); #endif if (pszGIFLIBError == NULL) pszGIFLIBError = "Unknown error"; CPLError( CE_Failure, CPLE_AppDefined, "%s. GIFLib Error : %s", pszMsg, pszGIFLIBError ); #else PrintGifError(); CPLError( CE_Failure, CPLE_AppDefined, "%s", pszMsg ); #endif }
PixRectArray::PixRectArray(const StringArray &fileNames, StringArray &errors) { USES_CONVERSION; m_updateCounter = 0; for(size_t i = 0; i < fileNames.size(); i++) { const String &name = fileNames[i]; try { if(FileNameSplitter(name).getExtension().equalsIgnoreCase(_T(".gif"))) { int error; const char *namea = T2A(name.cstr()); GifFileType *gifFile = DGifOpenFileName(namea, &error); if(gifFile == NULL) { throwException(_T("%s"), GifErrorString(error)); } if(DGifSlurp(gifFile) != GIF_OK) { const String msg = GifErrorString(gifFile->Error); DGifCloseFile(gifFile, &error); throwException(_T("%s"), msg.cstr()); } const int imageCount = gifFile->ImageCount; for(int k = 0; k < imageCount; k++) { add(new GifPixRect(gifFile, k)); } DGifCloseFile(gifFile, &error); } else { add(GifPixRect::load(name)); } } catch(Exception e) { errors.add(e.what()); } } }
void checkGifError(const char *file, int line, int errorCode) { if(errorCode == GIF_OK) { return; } printf("Error in %s line %d:%s\n", file, line, GifErrorString(errorCode)); exit(-1); }
int main(int argc, char **argv) { argv++; if(!*argv) usage(); int errorCode; GifFileType *gifFile = DGifOpenFileName(*argv, &errorCode); if(gifFile == NULL) { printf("Error:%s\n", GifErrorString(errorCode)); exit(-1); } CHECKGIFOK(DGifSlurp(gifFile)); _tprintf(_T("GifFile:Size:(%d,%d)\n"), gifFile->SWidth, gifFile->SHeight); _tprintf(_T("GifFile:BackgroundColor:%d, AspectByte:%d, ColorResultion:%d\n"), gifFile->SBackGroundColor, gifFile->AspectByte, gifFile->SColorResolution); _tprintf(_T("GifFile ")); dumpImageDesc(gifFile->Image); _tprintf(_T("GifFile:")); dumpColorMap(gifFile->SColorMap); _tprintf(_T("GifFile.ExtentionBlocks:\n")); dumpExtensionBlocks(gifFile->ExtensionBlocks, gifFile->ExtensionBlockCount); for(int i = 0; i < gifFile->ImageCount; i++) { dumpSavedImage(i, gifFile->SavedImages[i]); } if(DGifCloseFile(gifFile, &errorCode) != GIF_OK) { CHECKGIFOK(errorCode); } return 0; }
ImageSet* process_gif(const char *buf, size_t len) { int error; GifFileType* gif = DGifOpen((char*)buf, &gif_readfunc, &error); if (error != GIF_OK) { printf("GIF reading error %d: %s\n", error, GifErrorString(error)); return NULL; } printf("gif read, now converting\n", error); ImageSet* imgset = (ImageSet*)malloc(sizeof(ImageSet)); imgset->width = gif->SWidth; imgset->height = gif->SHeight; ColorMapObject* gif_colormap = gif->SColorMap; if (gif_colormap != NULL) { gif_colormap->ColorCount; imgset->palette = (Color*)calloc(256, sizeof(Color)); int shift = 8 - gif_colormap->BitsPerPixel; if (shift < 1 || shift > 7) { fprintf(stderr, "Error opening gif: invalid palette BPP %d\n", gif_colormap->BitsPerPixel); } for (int i=0; i < 256; i++) { if (i <= gif_colormap->ColorCount) { imgset->palette[i].r = gif_colormap->Colors[i].Red >> shift; imgset->palette[i].g = gif_colormap->Colors[i].Green >> shift; imgset->palette[i].b = gif_colormap->Colors[i].Blue >> shift; } else { //gset->palette[i] = Color{0,0,0}; } } } else {
static String gifErrorCodeToString(int errorCode) { const char *errorMsg = GifErrorString(errorCode); if(errorMsg == NULL) { return _T("No error"); } else { return errorMsg; } }
void PrintGifError(int ErrorCode) { const char *Err = GifErrorString(ErrorCode); if (Err != NULL) fprintf(stderr, "GIF-LIB error: %s.\n", Err); else fprintf(stderr, "GIF-LIB undefined error %d.\n", ErrorCode); }
static inline void gif_error (const gchar *action, int err) { const char *str = GifErrorString (err); if (str != NULL) { g_message ("%s, error: '%s'", action, str); } else { g_message ("%s, undefined error %d", action, err); } }
static void GIFDisplayError(const GifFileType* const gif, int gif_error) { // libgif 4.2.0 has retired PrintGifError() and added GifErrorString(). #if LOCAL_GIF_PREREQ(4, 2) #if LOCAL_GIF_PREREQ(5, 0) const char* error_str = GifErrorString((gif == NULL) ? gif_error : gif->Error); #else const char* error_str = GifErrorString(); (void)gif; #endif if (error_str == NULL) error_str = "Unknown error"; fprintf(stderr, "GIFLib Error %d: %s\n", gif_error, error_str); #else (void)gif; fprintf(stderr, "GIFLib Error %d: ", gif_error); PrintGifError(); fprintf(stderr, "\n"); #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 }
static void DisplayGifError(const GifFileType* const gif, int gif_error) { // GIFLIB_MAJOR is only defined in libgif >= 4.2.0. // libgif 4.2.0 has retired PrintGifError() and added GifErrorString(). #if defined(GIFLIB_MAJOR) && defined(GIFLIB_MINOR) && \ ((GIFLIB_MAJOR == 4 && GIFLIB_MINOR >= 2) || GIFLIB_MAJOR > 4) #if GIFLIB_MAJOR >= 5 // Static string actually, hence the const char* cast. const char* error_str = (const char*)GifErrorString( (gif == NULL) ? gif_error : gif->Error); #else const char* error_str = (const char*)GifErrorString(); (void)gif; #endif if (error_str == NULL) error_str = "Unknown error"; fprintf(stderr, "GIFLib Error %d: %s\n", gif_error, error_str); #else (void)gif; fprintf(stderr, "GIFLib Error %d: ", gif_error); PrintGifError(); fprintf(stderr, "\n"); #endif }
/* * Copyright (C) 2006, Jamie McCracken <*****@*****.**> * Copyright (C) 2008, Nokia <*****@*****.**> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "config.h" #include <errno.h> #include <fcntl.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <gif_lib.h> #include <libtracker-common/tracker-common.h> #include <libtracker-extract/tracker-extract.h> #define XMP_MAGIC_TRAILER_LENGTH 256 #define EXTENSION_RECORD_COMMENT_BLOCK_CODE 0xFE typedef struct { const gchar *title; const gchar *date; const gchar *artist; } MergeData; typedef struct { gchar *width; gchar *height; gchar *comment; } GifData; typedef struct { unsigned int byteCount; char *bytes; } ExtBlock; static int ext_block_append(ExtBlock *extBlock, unsigned int len, unsigned char extData[]) { extBlock->bytes = realloc(extBlock->bytes,extBlock->byteCount+len); if (extBlock->bytes == NULL) { return (GIF_ERROR); } memcpy(&(extBlock->bytes[extBlock->byteCount]), &extData[0], len); extBlock->byteCount += len; return (GIF_OK); } #if GIFLIB_MAJOR >= 5 static inline void gif_error (const gchar *action, int err) { const char *str = GifErrorString (err); if (str != NULL) { g_message ("%s, error: '%s'", action, str); } else { g_message ("%s, undefined error %d", action, err); } } #else /* GIFLIB_MAJOR >= 5 */ static inline void print_gif_error() { #if defined(GIFLIB_MAJOR) && defined(GIFLIB_MINOR) && ((GIFLIB_MAJOR == 4 && GIFLIB_MINOR >= 2) || GIFLIB_MAJOR > 4) const char *str = GifErrorString (); if (str != NULL) { g_message ("GIF, error: '%s'", str); } else { g_message ("GIF, undefined error"); } #else PrintGifError(); #endif }
/************************************************************************ return NULL if error http://www.imagemagick.org/Usage/anim_basics/#dispose http://wwwcdf.pd.infn.it/libgif/gif89.txt http://wwwcdf.pd.infn.it/libgif/gif_lib.html ************************************************************************/ static anim_t * giflib_load(SDL_Renderer * render, const char * filename) { GifFileType * gif = NULL; int i = 0; int j = 0; int transparent = 0; unsigned char transparent_color = 0; int disposal = 0; int delay = 0; ColorMapObject * global_pal = NULL; ColorMapObject * pal = NULL; SDL_Surface* surf = NULL; SDL_Surface* prev_surf = NULL; int x = 0; int y = 0; int col = 0; int pix_index = 0; anim_t * anim = NULL; int render_width; int render_height; int frame_left = 0; int frame_top = 0; int frame_width = 0; int frame_height = 0; int allow_draw = 1; int error = 0; int ret; gif = DGifOpenFileName(filename,&error); if(gif == NULL) { #if 0 printf("%s: %s\n", filename,GifErrorString(error)); #endif return NULL; } ret = DGifSlurp(gif); if (ret != GIF_OK) { DGifCloseFile(gif,&error); return NULL; } if ( gif->Error != D_GIF_SUCCEEDED) { DGifCloseFile(gif,&error); return NULL; } anim = malloc(sizeof(anim_t)); memset(anim,0,sizeof(anim_t)); anim->num_frame = gif->ImageCount; anim->tex = malloc(sizeof(SDL_Texture *) * anim->num_frame); anim->w = gif->SWidth; anim->h = gif->SHeight; anim->delay = malloc(sizeof(Uint32) * anim->num_frame); render_width = gif->SWidth; render_height = gif->SHeight; //bg_color = gif->SBackGroundColor; surf = SDL_CreateRGBSurface(0,render_width,render_height,32,0xff000000,0x00ff0000,0x0000ff00,0x000000ff); prev_surf = SDL_CreateRGBSurface(0,render_width,render_height,32,0xff000000,0x00ff0000,0x0000ff00,0x000000ff); global_pal = gif->SColorMap; pal = global_pal; /* Init with transparent background */ memset(surf->pixels,0, render_height * render_width * 4 ); for(i=0; i<gif->ImageCount; i++) { frame_left = gif->SavedImages[i].ImageDesc.Left; frame_top = gif->SavedImages[i].ImageDesc.Top; frame_width = gif->SavedImages[i].ImageDesc.Width; frame_height = gif->SavedImages[i].ImageDesc.Height; /* select palette */ pal = global_pal; if( gif->SavedImages[i].ImageDesc.ColorMap ) { pal = gif->SavedImages[i].ImageDesc.ColorMap; } /* GCE */ for(j=0; j<gif->SavedImages[i].ExtensionBlockCount; j++) { if(gif->SavedImages[i].ExtensionBlocks[j].Function == GIF_GCE) { transparent = gif->SavedImages[i].ExtensionBlocks[j].Bytes[0] & 0x01; disposal = (gif->SavedImages[i].ExtensionBlocks[j].Bytes[0] & 28)>>2; delay = (gif->SavedImages[i].ExtensionBlocks[j].Bytes[1] + gif->SavedImages[i].ExtensionBlocks[j].Bytes[2] * 256)*10; if(delay==0) { delay = DEFAULT_DELAY; } if(transparent) { transparent_color = gif->SavedImages[i].ExtensionBlocks[j].Bytes[3]; } } } /* Save the current render if needed */ if( disposal == DISPOSE_PREVIOUS ) { memcpy(prev_surf->pixels,surf->pixels, render_height * render_width * 4); } /* Fill surface buffer with raster bytes */ if( allow_draw ) { // See DISPOSE_DO_NOT for(y=0; y<frame_height; y++) { for(x=0; x<frame_width; x++) { pix_index = ((x+frame_left) + ( (y+frame_top) *render_width))*4; col = gif->SavedImages[i].RasterBits[(x)+(y)*frame_width]; if( col == transparent_color && transparent) { /* Transparent color means do not touch the render */ } else { ((char*)surf->pixels)[pix_index+3] = pal->Colors[col].Red; ((char*)surf->pixels)[pix_index+2] = pal->Colors[col].Green; ((char*)surf->pixels)[pix_index+1] = pal->Colors[col].Blue; ((char*)surf->pixels)[pix_index+0] = 0xFF; } } } } anim->delay[i] = delay; anim->tex[i] = SDL_CreateTextureFromSurface(render,surf); /* Prepare next rendering depending of disposal */ allow_draw = 1; switch( disposal ) { /* Do not touch render for next frame */ case DISPOSE_DO_NOT: allow_draw = 0; break; case DISPOSE_BACKGROUND: /* Draw transparent color in frame */ for(y=0; y<frame_height; y++) { for(x=0; x<frame_width; x++) { pix_index = ((x+frame_left)+((y+frame_top)*render_width))*4; ((char*)surf->pixels)[pix_index+3] = 0; ((char*)surf->pixels)[pix_index+2] = 0; ((char*)surf->pixels)[pix_index+1] = 0; ((char*)surf->pixels)[pix_index+0] = 0; } } break; case DISPOSE_PREVIOUS: /* Restore previous render in frame*/ memcpy(surf->pixels,prev_surf->pixels, render_height * render_width * 4); break; default: break; } }
int FileGIF::read_frame(VFrame *output, VFrame *input) { data = input->get_data(); offset = 0; size = input->get_compressed_size(); GifFileType *gif_file; GifRowType *gif_buffer; gif_file = DGifOpen(this, input_func); if(gif_file == 0) { printf("FileGIF::read_frame %d: %s\n", __LINE__, GifErrorString()); return 1; } gif_buffer = (GifRowType*)malloc(sizeof(GifRowType) * gif_file->SHeight); int row_size = gif_file->SWidth * sizeof(GifPixelType); gif_buffer[0] = (GifRowType)malloc(row_size); for(int i = 0; i < gif_file->SWidth; i++) { gif_buffer[0][i] = gif_file->SBackGroundColor; } for(int i = 0; i < gif_file->SHeight; i++) { gif_buffer[i] = (GifRowType)malloc(row_size); memcpy(gif_buffer[i], gif_buffer[0], row_size); } GifRecordType record_type; do { if(DGifGetRecordType(gif_file, &record_type) == GIF_ERROR) { printf("FileGIF::read_frame %d: %s\n", __LINE__, GifErrorString()); break; } switch(record_type) { case IMAGE_DESC_RECORD_TYPE: { if(DGifGetImageDesc(gif_file) == GIF_ERROR) { printf("FileGIF::read_frame %d: %s\n", __LINE__, GifErrorString()); break; } int row = gif_file->Image.Top; int col = gif_file->Image.Left; int width = gif_file->Image.Width; int height = gif_file->Image.Height; if(gif_file->Image.Left + gif_file->Image.Width > gif_file->SWidth || gif_file->Image.Top + gif_file->Image.Height > gif_file->SHeight) { DGifCloseFile(gif_file); for(int k = 0; k < gif_file->SHeight; k++) { free(gif_buffer[k]); } free(gif_buffer); return 1; } if (gif_file->Image.Interlace) { static int InterlacedOffset[] = { 0, 4, 2, 1 }; static int InterlacedJumps[] = { 8, 8, 4, 2 }; /* Need to perform 4 passes on the images: */ for (int i = 0; i < 4; i++) { for (int j = row + InterlacedOffset[i]; j < row + height; j += InterlacedJumps[i]) { if (DGifGetLine(gif_file, &gif_buffer[j][col], width) == GIF_ERROR) { DGifCloseFile(gif_file); for(int k = 0; k < gif_file->SHeight; k++) { free(gif_buffer[k]); } free(gif_buffer); return 1; } } } } else { for (int i = 0; i < height; i++) { if (DGifGetLine(gif_file, &gif_buffer[row++][col], width) == GIF_ERROR) { DGifCloseFile(gif_file); for(int k = 0; k < gif_file->SHeight; k++) { free(gif_buffer[k]); } free(gif_buffer); return 1; } } } break; } } } while(record_type != TERMINATE_RECORD_TYPE); int background = gif_file->SBackGroundColor; ColorMapObject *color_map = (gif_file->Image.ColorMap ? gif_file->Image.ColorMap : gif_file->SColorMap); if(!color_map) { DGifCloseFile(gif_file); for(int k = 0; k < gif_file->SHeight; k++) { free(gif_buffer[k]); } free(gif_buffer); return 1; } int screen_width = gif_file->SWidth; int screen_height = gif_file->SHeight; for(int i = 0; i < screen_height; i++) { GifRowType gif_row = gif_buffer[i]; unsigned char *out_ptr = output->get_rows()[i]; for(int j = 0; j < screen_width; j++) { GifColorType *color_map_entry = &color_map->Colors[gif_row[j]]; *out_ptr++ = color_map_entry->Red; *out_ptr++ = color_map_entry->Green; *out_ptr++ = color_map_entry->Blue; } } for(int k = 0; k < gif_file->SHeight; k++) { free(gif_buffer[k]); } free(gif_buffer); DGifCloseFile(gif_file); return 0; }
static int load_image(char *filename, struct image_info *info, unsigned char *buf, ssize_t *buf_size) { int w, h; long time = 0; /* measured ticks */ struct gif_decoder *p_decoder = &decoder; unsigned char *memory, *memory_max; size_t memory_size, img_size, disp_size; /* align buffer */ memory = (unsigned char *)((intptr_t)(buf + 3) & ~3); memory_max = (unsigned char *)((intptr_t)(memory + *buf_size) & ~3); memory_size = memory_max - memory; #ifdef DISK_SPINDOWN if (iv->running_slideshow && iv->immediate_ata_off) { /* running slideshow and time is long enough: power down disk */ rb->storage_sleep(); } #endif /* initialize decoder context struct, set buffer decoder is free * to use. */ gif_decoder_init(p_decoder, memory, memory_size); /* populate internal data from gif file control structs */ gif_open(filename, p_decoder); if (!p_decoder->error) { if (!iv->running_slideshow) { rb->lcd_putsf(0, 2, "image %dx%d", p_decoder->width, p_decoder->height); rb->lcd_putsf(0, 3, "decoding %d*%d", p_decoder->width, p_decoder->height); rb->lcd_update(); } /* the actual decoding */ time = *rb->current_tick; #ifdef HAVE_ADJUSTABLE_CPU_FREQ rb->cpu_boost(true); #endif gif_decode(p_decoder, iv->cb_progress); #ifdef HAVE_ADJUSTABLE_CPU_FREQ rb->cpu_boost(false); #endif time = *rb->current_tick - time; } if (!iv->running_slideshow && !p_decoder->error) { rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ); rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */ rb->lcd_putsxy((LCD_WIDTH - w)/2, LCD_HEIGHT - h, print); rb->lcd_update(); } if (p_decoder->error) { rb->splashf(HZ, "%s", GifErrorString(p_decoder->error)); return PLUGIN_ERROR; } info->x_size = p_decoder->width; info->y_size = p_decoder->height; info->frames_count = p_decoder->frames_count; info->delay = p_decoder->delay; /* check mem constraints * each frame can have 4 scaled versions with ds = (1,2,4,8) */ img_size = (p_decoder->native_img_size*p_decoder->frames_count + 3) & ~3; disp_size = (sizeof(unsigned char *)*p_decoder->frames_count*4 + 3) & ~3; if (memory_size < img_size + disp_size) { /* No memory to allocate disp matrix */ rb->splashf(HZ, "%s", GifErrorString(D_GIF_ERR_NOT_ENOUGH_MEM)); return PLUGIN_ERROR; } disp = (unsigned char **)(p_decoder->mem + img_size); disp_buf = (unsigned char *)disp + disp_size; *buf_size = memory_max - disp_buf; /* set all pointers to NULL initially */ memset(disp, 0, sizeof(unsigned char *)*p_decoder->frames_count*4); return PLUGIN_OK; }
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; }
pictw_t * sgif_read(session_t *ps, const char *path) { assert(path); pictw_t *pictw = NULL; GifPixelType *data = NULL; unsigned char *tdata = NULL; GifRecordType rectype; int ret = 0, err = 0; const char *errstr = NULL; #ifdef SGIF_THREADSAFE GifFileType *f = DGifOpenFileName(path, &err); #else GifFileType *f = DGifOpenFileName(path); #endif if (unlikely(!f)) { #ifdef SGIF_HAS_ERROR err = GifError(); errstr = GifErrorString(); #endif #ifdef SGIF_THREADSAFE errstr = GifErrorString(err); #endif printfef("(\"%s\"): Failed to open file: %d (%s)", path, err, errstr); goto sgif_read_end; } int width = 0, height = 0, transp = -1; { int i = 0; while (GIF_OK == (ret = DGifGetRecordType(f, &rectype)) && TERMINATE_RECORD_TYPE != rectype) { ++i; switch (rectype) { case UNDEFINED_RECORD_TYPE: printfef("(\"%s\"): %d: Encountered a record of unknown type.", path, i); break; case SCREEN_DESC_RECORD_TYPE: printfef("(\"%s\"): %d: Encountered a record of " "ScreenDescRecordType. This shouldn't happen!", path, i); break; case IMAGE_DESC_RECORD_TYPE: if (data) { printfef("(\"%s\"): %d: Extra image section ignored.", path, i); break; } if (GIF_ERROR == DGifGetImageDesc(f)) { printfef("(\"%s\"): %d: Failed to read GIF image info.", path, i); break; } width = f->Image.Width; height = f->Image.Height; if (width <= 0 || height <= 0) { printfef("(\"%s\"): %d: Width/height invalid.", path, i); break; } assert(!data); data = allocchk(malloc(width * height * sizeof(GifPixelType))); // FIXME: Interlace images may need special treatments for (int j = 0; j < height; ++j) if (GIF_OK != DGifGetLine(f, &data[j * width], width)) { printfef("(\"%s\"): %d: Failed to read line %d.", path, i, j); goto sgif_read_end; } break; case EXTENSION_RECORD_TYPE: { int code = 0; GifByteType *pbytes = NULL; if (GIF_OK != DGifGetExtension(f, &code, &pbytes) || !pbytes) { printfef("(\"%s\"): %d: Failed to read extension block.", path, i); break; } do { // Transparency if (0xf9 == code && (pbytes[1] & 1)) transp = pbytes[4]; } while (GIF_OK == DGifGetExtensionNext(f, &pbytes) && pbytes); } break; case TERMINATE_RECORD_TYPE: assert(0); break; } } if (unlikely(!data)) { printfef("(\"%s\"): No valid data found.", path); goto sgif_read_end; } } // Colormap translation int depth = 32; { ColorMapObject *cmap = f->Image.ColorMap; if (!cmap) cmap = f->SColorMap; if (unlikely(!cmap)) { printfef("(\"%s\"): No colormap found.", path); goto sgif_read_end; } tdata = allocchk(malloc(width * height * depth / 8)); { GifPixelType *pd = data; unsigned char *end = tdata + width * height * depth / 8; for (unsigned char *p = tdata; p < end; p += depth / 8, ++pd) { // When the alpha is 0, X seemingly wants all color channels // to be 0 as well. if (transp >= 0 && transp == *pd) { p[0] = p[1] = p[2] = 0; if (32 == depth) p[3] = 0; continue; } p[0] = cmap->Colors[*pd].Blue; p[1] = cmap->Colors[*pd].Green; p[2] = cmap->Colors[*pd].Red; p[3] = 0xff; } } } if (unlikely(!(pictw = simg_data_to_pictw(ps, width, height, depth, tdata, 0)))) { printfef("(\"%s\"): Failed to create Picture.", path); goto sgif_read_end; } sgif_read_end: if (data) free(data); if (likely(f)) DGifCloseFile(f); return pictw; }
bool GIFInput::seek_subimage (int subimage, int miplevel, ImageSpec &newspec) { GifColorType *local_colormap = NULL; if (subimage < 0 || miplevel != 0) return false; if (m_subimage == subimage) { // We're already pointing to the right subimage newspec = m_spec; return true; } if (m_subimage > subimage) { // requested subimage is located before the current one // file needs to be reopened if (m_gif_file && ! close()) { return false; } } if (! m_gif_file) { #if GIFLIB_MAJOR >= 5 int giflib_error; if (! (m_gif_file = DGifOpenFileName (m_filename.c_str(), &giflib_error))) { error (GifErrorString (giflib_error)); return false; } #else if (! (m_gif_file = DGifOpenFileName (m_filename.c_str()))) { error ("Error trying to open the file."); return false; } #endif m_subimage = -1; // read global color table if (m_gif_file->SColorMap) { m_global_colormap = m_gif_file->SColorMap->Colors; } else { m_global_colormap = NULL; } } if (m_subimage < subimage) { // requested subimage is located after the current one // skip the preceding part of current image.. if (m_subimage != -1 && m_next_scanline < m_spec.height) { int remaining_size = m_spec.width * (m_spec.height - m_next_scanline); boost::scoped_array<unsigned char> buffer (new unsigned char[remaining_size]); if (DGifGetLine (m_gif_file, buffer.get(), remaining_size) == GIF_ERROR) { report_last_error (); return false; } } // ..and skip the rest of preceding subimages for (m_subimage += 1; m_subimage < subimage; m_subimage ++) { if (! read_subimage_metadata (newspec, &local_colormap)) { return false; } int image_size = newspec.width * newspec.height; boost::scoped_array<unsigned char> buffer (new unsigned char[image_size]); if (DGifGetLine (m_gif_file, buffer.get(), image_size) == GIF_ERROR) { report_last_error (); return false; } } } // read metadata of current subimage if (! read_subimage_metadata (newspec, &local_colormap)) { return false; } m_spec = newspec; m_subimage = subimage; m_next_scanline = 0; m_cached_data.clear (); m_local_colormap = local_colormap; return true; }