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()); } } }
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; }
JNIEXPORT jlong JNICALL Java_com_ly_widget_GifDrawable_loadGifFile(JNIEnv * env, jobject obj, jstring filepath, jarray size) { int error; const char *native_file_path = (*env)->GetStringUTFChars(env, filepath, 0); GifFileType* gif = DGifOpenFileName(native_file_path,&error); error = DGifSlurp(gif); (*env)->ReleaseStringUTFChars(env, filepath, native_file_path); return loadGif(env, gif, size); }
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 compress_custom(void* input_data, InputFunc input_func, void* output_data, OutputFunc output_func, int sample_size) { GifFileType* input_gif = NULL; GifFileType* output_gif = NULL; int result = GIF_ERROR; // Check sample if (sample_size <= 0) { return false; } input_gif = DGifOpen(input_data, input_func, &error_code); if (input_gif == NULL) { LOGE(EMSG("Can't open input gif")); return false; } DGifSlurp(input_gif); if (input_gif->ImageCount == 0) { LOGE(EMSG("Gif frame count is 0")); DGifCloseFile(input_gif, &error_code); return false; } // Save gif output_gif = EGifOpen(output_data, output_func, &error_code); if (output_gif == NULL) { LOGE(EMSG("Can't open output gif")); DGifCloseFile(input_gif, &error_code); return false; } if (do_compress(input_gif, output_gif, sample_size)) { result = EGifSpew(output_gif); } // Free GifFreeExtensions(&output_gif->ExtensionBlockCount, &output_gif->ExtensionBlocks); if (output_gif->SavedImages) { GifFreeSavedImages(output_gif); output_gif->SavedImages = NULL; } // Close gif DGifCloseFile(input_gif, &error_code); return result == GIF_OK; }
SkGIFMovie::SkGIFMovie(SkStream* stream) { fGIF = DGifOpen( stream, Decode ); if (NULL == fGIF) return; if (DGifSlurp(fGIF) != GIF_OK) { DGifCloseFile(fGIF); fGIF = NULL; } fCurrIndex = -1; fLastDrawIndex = -1; }
static GifFileType *loadGif(ByteInputStream &in) { int error; GifFileType *gf = DGifOpen(&in, readGifStreamFunction, &error); if(gf == NULL) { THROWGIFERROR(error); } try { if(DGifSlurp(gf) != GIF_OK) { THROWGIFERROR(gf->Error); } return gf; } catch(...) { DGifCloseFile(gf, &error); throw; } }
void AnimatedImage::load(CWnd *parent, ByteInputStream &in) { int error; GifFileType *gifFile = DGifOpen(&in, readGifStreamFunction, &error); if(gifFile == NULL) { THROWGIFERROR(error); } try { if(DGifSlurp(gifFile) != GIF_OK) { THROWGIFERROR(gifFile->Error); } createFromGifFile(parent, gifFile); DGifCloseFile(gifFile, &error); } catch(...) { DGifCloseFile(gifFile, &error); throw; } }
static HRESULT WINAPI GifDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream, WICDecodeOptions cacheOptions) { GifDecoder *This = (GifDecoder*)iface; LARGE_INTEGER seek; int ret; TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions); EnterCriticalSection(&This->lock); if (This->initialized || This->gif) { WARN("already initialized\n"); LeaveCriticalSection(&This->lock); return WINCODEC_ERR_WRONGSTATE; } /* seek to start of stream */ seek.QuadPart = 0; IStream_Seek(pIStream, seek, STREAM_SEEK_SET, NULL); /* read all data from the stream */ This->gif = DGifOpen((void*)pIStream, _gif_inputfunc); if (!This->gif) { LeaveCriticalSection(&This->lock); return E_FAIL; } ret = DGifSlurp(This->gif); if (ret == GIF_ERROR) { LeaveCriticalSection(&This->lock); return E_FAIL; } /* make sure we don't use the stream after this method returns */ This->gif->UserData = NULL; This->initialized = TRUE; LeaveCriticalSection(&This->lock); return S_OK; }
SkGIFMovie::SkGIFMovie(SkStream* stream) { #if GIFLIB_MAJOR < 5 fGIF = DGifOpen( stream, Decode ); #else fGIF = DGifOpen( stream, Decode, NULL ); #endif if (NULL == fGIF) return; if (DGifSlurp(fGIF) != GIF_OK) { DGifCloseFile(fGIF); fGIF = NULL; } fCurrIndex = -1; fLastDrawIndex = -1; }
static int read_gif_info(const ps_byte* data, size_t len, psx_image_header* header) { #if GIFLIB_MAJOR >= 5 int errorcode = 0; #endif struct gif_image_ctx* ctx = (struct gif_image_ctx*)calloc(1, sizeof(struct gif_image_ctx)); if (!ctx) { return -1; // out of memory. } ctx->buf = (uint8_t*)data; ctx->len = (uint32_t)len; ctx->pos = 0; #if GIFLIB_MAJOR >= 5 if ((ctx->gif = DGifOpen((void*)ctx, read_gif_from_memory, &errorcode)) == NULL) { free(ctx); return -1; } #else if ((ctx->gif = DGifOpen((void*)ctx, read_gif_from_memory)) == NULL) { free(ctx); return -1; } #endif if (GIF_OK != DGifSlurp(ctx->gif)) { GIF_CLOSE_DFILE(ctx->gif); free(ctx); return -1; } header->priv = ctx; header->width = ctx->gif->SWidth; header->height = ctx->gif->SHeight; header->pitch = ctx->gif->SWidth * 4; header->depth = 32; header->bpp = 4; header->format = 0; header->alpha = 1; header->frames = ctx->gif->ImageCount; return 0; }
void init_gifs(char *fileName, int sizex, int sizey) { if(gifFileIn==NULL) { gifFileIn = DGifOpenFileName("kaavyhdi.gif"); if(gifFileIn==NULL) {failExit;} printf("%i,%i: %i\n", gifFileIn->SWidth, gifFileIn->SHeight, gifFileIn->SColorResolution); if(DGifSlurp(gifFileIn) == GIF_ERROR) failExit; printf("slurp done\n"); } gifFileOut = EGifOpenFileName(fileName, FALSE); if(gifFileOut==NULL) failExit; printf("making output...\n"); if(EGifPutScreenDesc(gifFileOut, sizex, sizey, gifFileIn->SColorResolution, gifFileIn->SBackGroundColor, MakeMapObject(gifFileIn->SColorMap->ColorCount, gifFileIn->SColorMap->Colors)) == GIF_ERROR) failExit; if(EGifPutImageDesc(gifFileOut, 0, 0, sizex, sizey, FALSE, NULL) == GIF_ERROR) failExit; }
JNIEXPORT jlong JNICALL Java_com_ly_widget_GifDrawable_loadGifAsset(JNIEnv * env, jobject obj, jobject assetManager, jstring filepath, jarray size) { int error; AAssetManager *mgr = AAssetManager_fromJava(env, assetManager); const char *native_file_path = (*env)->GetStringUTFChars(env, filepath, 0); AAsset* asset = AAssetManager_open(mgr, native_file_path, AASSET_MODE_UNKNOWN); off_t start, length; fd = AAsset_openFileDescriptor(asset, &start, &length); bytesLeft = length; lseek(fd, start, SEEK_SET); if (fd < 0) { return 0; } GifFileType* gif = DGifOpen(NULL,&readFunc,&error); error = DGifSlurp(gif); (*env)->ReleaseStringUTFChars(env, filepath, native_file_path); AAsset_close(asset); return loadGif(env, gif, size); }
bool GIFMovie::init(FILE* file) { if(file == NULL) { return false; } int error = 0; fGIF = DGifOpen(file,&DecodeCallBackProc,&error); if (NULL == fGIF || DGifSlurp(fGIF) != GIF_OK) { GifUtils::closeFile(file); DGifCloseFile(fGIF); fGIF = NULL; return false; } GifUtils::closeFile(file); return true; }
int openStream(GifFileType* gifFileType,JNIEnv * env,jobject stream) { jclass streamCls = (jclass)env->NewGlobalRef(env->GetObjectClass(stream)); jmethodID mid = env->GetMethodID(streamCls, "mark", "(I)V"); jmethodID readMID = env->GetMethodID(streamCls, "read", "([BII)I"); jmethodID resetMID = env->GetMethodID(streamCls, "reset", "()V"); if (mid == 0 || readMID == 0 || resetMID == 0) { env->DeleteGlobalRef(streamCls); return (jint) NULL; } StreamContainer* container = (StreamContainer*)malloc(sizeof(StreamContainer)); if (container == NULL) { return (jint) NULL; } container->readMID = readMID; container->resetMID = resetMID; container->stream = env->NewGlobalRef(stream); container->streamCls = streamCls; container->buffer = NULL; container->env = env; int Error = 0; gifType = DGifOpen(container, &streamReadFun); if(gifType == NULL){ return GIF_ERROR; }else{ } if(DGifSlurp(gifType) == GIF_ERROR){ return GIF_ERROR; } return GIF_OK; }
GDALDataset *GIFDataset::Open( GDALOpenInfo * poOpenInfo ) { if( !Identify( poOpenInfo ) ) return NULL; if( poOpenInfo->eAccess == GA_Update ) { CPLError( CE_Failure, CPLE_NotSupported, "The GIF driver does not support update access to existing" " files.\n" ); return NULL; } /* -------------------------------------------------------------------- */ /* Open the file and ingest. */ /* -------------------------------------------------------------------- */ GifFileType *hGifFile; VSILFILE *fp; int nGifErr; fp = VSIFOpenL( poOpenInfo->pszFilename, "r" ); if( fp == NULL ) return NULL; hGifFile = GIFAbstractDataset::myDGifOpen( fp, VSIGIFReadFunc ); if( hGifFile == NULL ) { VSIFCloseL( fp ); CPLError( CE_Failure, CPLE_OpenFailed, "DGifOpen() failed for %s.\n" "Perhaps the gif file is corrupt?\n", poOpenInfo->pszFilename ); return NULL; } /* The following code enables us to detect GIF datasets eligible */ /* for BIGGIF driver even with an unpatched giflib */ /* -------------------------------------------------------------------- */ /* Find the first image record. */ /* -------------------------------------------------------------------- */ GifRecordType RecordType = TERMINATE_RECORD_TYPE; while( DGifGetRecordType(hGifFile, &RecordType) != GIF_ERROR && RecordType != TERMINATE_RECORD_TYPE && RecordType != IMAGE_DESC_RECORD_TYPE ) { /* Skip extension records found before IMAGE_DESC_RECORD_TYPE */ if (RecordType == EXTENSION_RECORD_TYPE) { int nFunction; GifByteType *pExtData; if (DGifGetExtension(hGifFile, &nFunction, &pExtData) == GIF_ERROR) break; while (pExtData != NULL) { if (DGifGetExtensionNext(hGifFile, &pExtData) == GIF_ERROR) break; } } } if( RecordType == IMAGE_DESC_RECORD_TYPE && DGifGetImageDesc(hGifFile) != GIF_ERROR) { int width = hGifFile->SavedImages[0].ImageDesc.Width; int height = hGifFile->SavedImages[0].ImageDesc.Height; if ((double) width * (double) height > 100000000.0 ) { CPLDebug( "GIF", "Due to limitations of the GDAL GIF driver we deliberately avoid\n" "opening large GIF files (larger than 100 megapixels)."); GIFAbstractDataset::myDGifCloseFile( hGifFile ); VSIFCloseL( fp ); return NULL; } } GIFAbstractDataset::myDGifCloseFile( hGifFile ); VSIFSeekL( fp, 0, SEEK_SET); hGifFile = GIFAbstractDataset::myDGifOpen( fp, VSIGIFReadFunc ); if( hGifFile == NULL ) { VSIFCloseL( fp ); CPLError( CE_Failure, CPLE_OpenFailed, "DGifOpen() failed for %s.\n" "Perhaps the gif file is corrupt?\n", poOpenInfo->pszFilename ); return NULL; } nGifErr = DGifSlurp( hGifFile ); if( nGifErr != GIF_OK || hGifFile->SavedImages == NULL ) { VSIFCloseL( fp ); GIFAbstractDataset::myDGifCloseFile(hGifFile); if( nGifErr == D_GIF_ERR_DATA_TOO_BIG ) { CPLDebug( "GIF", "DGifSlurp() failed for %s because it was too large.\n" "Due to limitations of the GDAL GIF driver we deliberately avoid\n" "opening large GIF files (larger than 100 megapixels).", poOpenInfo->pszFilename ); return NULL; } else CPLError( CE_Failure, CPLE_OpenFailed, "DGifSlurp() failed for %s.\n" "Perhaps the gif file is corrupt?\n", poOpenInfo->pszFilename ); return NULL; } /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ GIFDataset *poDS; poDS = new GIFDataset(); poDS->fp = fp; poDS->eAccess = GA_ReadOnly; poDS->hGifFile = hGifFile; /* -------------------------------------------------------------------- */ /* Capture some information from the file that is of interest. */ /* -------------------------------------------------------------------- */ poDS->nRasterXSize = hGifFile->SavedImages[0].ImageDesc.Width; poDS->nRasterYSize = hGifFile->SavedImages[0].ImageDesc.Height; /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ for( int iImage = 0; iImage < hGifFile->ImageCount; iImage++ ) { SavedImage *psImage = hGifFile->SavedImages + iImage; if( psImage->ImageDesc.Width != poDS->nRasterXSize || psImage->ImageDesc.Height != poDS->nRasterYSize ) continue; poDS->SetBand( poDS->nBands+1, new GIFRasterBand( poDS, poDS->nBands+1, psImage, hGifFile->SBackGroundColor )); } /* -------------------------------------------------------------------- */ /* Check for georeferencing. */ /* -------------------------------------------------------------------- */ poDS->DetectGeoreferencing(poOpenInfo); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( poOpenInfo->pszFilename ); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Support overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename ); return poDS; }
void * gifconv_gif2lossless(unsigned char *gif_data, unsigned long gif_data_len, int *tag_no, int *format, unsigned short *width, unsigned short *height, void **colormap, int *colormap_count) { GifFileType *GifFile = NULL; ColorMapObject *ColorMap = NULL; my_gif_buffer gif_buff; int bpp; gif_uint_32 gif_width = 0, gif_height = 0; gif_bytep gif_image_data_ref = NULL; gif_uint_32 x, y; void *image_data = NULL; int palette_num = 0; int trans_index = -1; SavedImage Image; int i, j; unsigned char *indices_data; gif_buff.data = gif_data; gif_buff.data_len = gif_data_len; gif_buff.data_offset = 0; #if GIFLIB_MAJOR >= 5 GifFile = DGifOpen(& gif_buff, gif_data_read_func, NULL); #else GifFile = DGifOpen(& gif_buff, gif_data_read_func); #endif if (GifFile == NULL) { fprintf(stderr, "gifconv_gif2lossless: can't open GIFFile\n"); return NULL; } if (DGifSlurp(GifFile) == GIF_ERROR) { fprintf(stderr, "gifconv_gif2lossless: DGifSlurp failed\n"); #if GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1 || GIFLIB_MAJOR > 5 DGifCloseFile(GifFile, NULL); #else DGifCloseFile(GifFile); #endif return NULL; } Image = GifFile->SavedImages[0]; ColorMap = GifFile->SColorMap; if (ColorMap == NULL) { ColorMap = Image.ImageDesc.ColorMap; } gif_width = GifFile->SWidth; gif_height = GifFile->SHeight; bpp = ColorMap->BitsPerPixel; if (bpp > 8) { fprintf(stderr, "gifconv_gif2lossless: bpp=%d not implemented. accept only bpp <= 8\n", bpp); #if GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1 || GIFLIB_MAJOR > 5 DGifCloseFile(GifFile, NULL); #else DGifCloseFile(GifFile); #endif return NULL; } palette_num = ColorMap->ColorCount; trans_index = getTransparentIndex(Image); *width = (unsigned short) gif_width; *height = (unsigned short) gif_height; *format = 3; if (trans_index != -1) { *tag_no = 36; // DefineBitsLossless2 } else { *tag_no = 20; // DefineBitsLossless } /* * image copy */ *colormap_count = palette_num; if (trans_index == -1) { // Lossless swf_rgb_t *result_colormap = malloc(sizeof(swf_rgb_t) * palette_num); for (i=0 ; i < palette_num ; i++) { result_colormap[i].red = ColorMap->Colors[i].Red; result_colormap[i].green = ColorMap->Colors[i].Green; result_colormap[i].blue = ColorMap->Colors[i].Blue; } *colormap = result_colormap; } else { // Lossless2 swf_rgba_t *result_colormap = malloc(sizeof(swf_rgba_t) * palette_num); for (i=0 ; i < palette_num ; i++) { if (i == trans_index) { result_colormap[i].red = 0x0; result_colormap[i].green = 0x0; result_colormap[i].blue = 0x0; result_colormap[i].alpha = 0x0; } else { result_colormap[i].red = ColorMap->Colors[i].Red; result_colormap[i].green = ColorMap->Colors[i].Green; result_colormap[i].blue = ColorMap->Colors[i].Blue; result_colormap[i].alpha = 0xff; } } *colormap = result_colormap; } indices_data = malloc(((gif_width+ 3) & -4) * gif_height); gif_image_data_ref = Image.RasterBits; i = 0; j = 0; for (y=0 ; y < gif_height ; y++) { for (x=0 ; x < gif_width ; x++) { indices_data[i] = gif_image_data_ref[j]; i++; j++; } while (i % 4) { i++; } // 4byte alignment } image_data = indices_data; /* * destruct */ if (GifFile) { #if GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1 || GIFLIB_MAJOR > 5 DGifCloseFile(GifFile, NULL); #else DGifCloseFile(GifFile); #endif } return image_data; }
//================================================================================= // bind_gif //================================================================================= static void bind_gif(struct QDRBindImage *b, const char *file) { GifFileType *gif; SavedImage g; ColorMapObject *colormap; unsigned char trans[256]; int i, j, s, t; gif = DGifOpenFileName(file); if(!gif) return; if(DGifSlurp(gif) == GIF_ERROR) return; //アニメーションGIFの場合でも、1枚目の画像のみ使う g = gif->SavedImages[0]; if(g.ImageDesc.Left + g.ImageDesc.Width > gif->SWidth || g.ImageDesc.Top + g.ImageDesc.Height > gif->SHeight){ DGifCloseFile(gif); return; } //カラーマップ colormap = g.ImageDesc.ColorMap; if(!colormap) colormap = gif->SColorMap; //透過情報の取得 memset(trans, 0, 256); if(g.ExtensionBlockCount!=0 && g.ExtensionBlocks){ ExtensionBlock *block; for(i=0; i<g.ExtensionBlockCount; i++){ block = &(g.ExtensionBlocks[i]); if(block->Function == GRAPHICS_EXT_FUNC_CODE){ if(block->Bytes[0] & 0x01) trans[(int)block->Bytes[3]] = 1; } } } //イメージを格納する領域 b->width = g.ImageDesc.Width; b->height = g.ImageDesc.Height; b->data = malloc(b->height * b->width * 4); if(g.ImageDesc.Interlace){ int ifset[4] = { 0, 4, 2, 1 }; //InterlacedOffset int jumps[4] = { 8, 8, 4, 2 }; //InterlacedJumps i=0; for(t=0; t<4; t++){ for(s=ifset[t]; s<b->height; s+=jumps[t]){ for(j=0; j<b->width; j++){ if(trans[g.RasterBits[i*b->width+j]]){ memset(&b->data[(s*b->width+j)*4], 0, 4); }else{ //RGB -> BGRA GifColorType *ColorMapEntry = &colormap->Colors[g.RasterBits[i*b->width+j]]; b->data[(s*b->width+j)*4 ] = ColorMapEntry->Blue; b->data[(s*b->width+j)*4+1] = ColorMapEntry->Green; b->data[(s*b->width+j)*4+2] = ColorMapEntry->Red; b->data[(s*b->width+j)*4+3] = 0xff; } } i++; } } }else{ for(i=0; i<b->height; i++){ for(j=0; j<b->width; j++){ if(trans[g.RasterBits[i*b->width+j]]){ memset(&b->data[(i*b->width+j)*4], 0, 4); }else{ //RGB -> BGRA GifColorType *ColorMapEntry = &colormap->Colors[g.RasterBits[i*b->width+j]]; b->data[(i*b->width+j)*4 ] = ColorMapEntry->Blue; b->data[(i*b->width+j)*4+1] = ColorMapEntry->Green; b->data[(i*b->width+j)*4+2] = ColorMapEntry->Red; b->data[(i*b->width+j)*4+3] = 0xff; } } } } DGifCloseFile(gif); }
bool MCGIFImageLoader::LoadFrames(MCBitmapFrame *&r_frames, uint32_t &r_count) { bool t_success; t_success = true; MCImageBitmap *t_canvas; t_canvas = nil; // restoration info MCImageBitmap *t_restore_image = nil; int t_disposal_mode = DISPOSAL_UNSPECIFIED; MCRectangle t_disposal_region = kMCEmptyRectangle; // The list of frames. MCBitmapFrame *t_frames = nil; t_success = GIF_OK == DGifSlurp(m_gif); // Fetch the width and height of the virtual canvas. int32_t t_width, t_height; if (t_success) { t_width = m_gif -> SWidth; t_height = m_gif -> SHeight; // create the canvas image t_success = MCImageBitmapCreate(t_width, t_height, t_canvas); } // The current frame count. The number of frames is the same as the // number of images in the GIF. uint32_t t_frame_count; t_frame_count = 0; // If true, the new image will be merged with the old - otherwise the mask // replaces it. bool t_overlay; t_overlay = false; // Loop through all the images, making frames as we go. for(uindex_t i = 0; t_success && i < m_gif -> ImageCount; i++) { // Process the disposal. switch (t_disposal_mode) { case DISPOSE_BACKGROUND: gif_fill_image_region(t_canvas, t_disposal_region, 0); break; case DISPOSE_PREVIOUS: if (t_restore_image != nil) gif_paste_image(t_canvas, t_restore_image, t_disposal_region.x, t_disposal_region.y); break; case DISPOSE_DO_NOT: t_overlay = true; break; default: t_overlay = false; break; } // Fetch the image information. GraphicsControlBlock t_image_gcb; MCRectangle t_image_region; ColorMapObject *t_image_colors = nil; int32_t t_image_transparency; int32_t t_image_delay; int32_t t_image_disposal; GifByteType *t_image_raster; // First the information from the image description. t_image_region.x = m_gif -> SavedImages[i] . ImageDesc . Left; t_image_region.y = m_gif -> SavedImages[i] . ImageDesc . Top; t_image_region.width = m_gif -> SavedImages[i] . ImageDesc . Width; t_image_region.height = m_gif -> SavedImages[i] . ImageDesc . Height; t_image_colors = m_gif -> SavedImages[i] . ImageDesc . ColorMap; t_image_raster = m_gif -> SavedImages[i] . RasterBits; if (t_image_colors == nil) t_image_colors = m_gif -> SColorMap; // Then the information from the GCB. if (GIF_OK == DGifSavedExtensionToGCB(m_gif, i, &t_image_gcb)) { t_image_transparency = t_image_gcb . TransparentColor; t_image_delay = t_image_gcb . DelayTime; t_image_disposal = t_image_gcb . DisposalMode; } else { t_image_transparency = -1; t_image_delay = 0; t_image_disposal = DISPOSAL_UNSPECIFIED; } // If disposal is 'previous' then cache the portion of the canvas we are // about to affect. if (t_image_disposal == DISPOSE_PREVIOUS) { if (t_restore_image != nil) { if (t_disposal_mode != DISPOSE_PREVIOUS || !MCU_equal_rect(t_disposal_region, t_image_region)) { MCImageFreeBitmap(t_restore_image); t_restore_image = nil; } } if (t_restore_image == nil) t_success = MCImageCopyBitmapRegion(t_canvas, t_image_region, t_restore_image); } if (t_success) { // Render the image into the canvas. gif_draw_image_into_canvas(t_canvas, t_image_raster, t_image_region.x, t_image_region.y, t_image_region.width, t_image_region.height, t_image_colors, t_image_transparency, t_overlay); // Generate our frame. t_success = MCMemoryResizeArray(t_frame_count + 1, t_frames, t_frame_count); } MCImageBitmap *t_frame_bitmap = nil; if (t_success) t_success = MCImageCopyBitmap(t_canvas, t_frame_bitmap); if (t_success) { MCImageBitmapCheckTransparency(t_frame_bitmap); t_frames[t_frame_count - 1].image = t_frame_bitmap; t_frames[t_frame_count - 1].duration = t_image_delay * 10; // convert 1/100 seconds to milliseconds t_frames[t_frame_count - 1].x_scale = t_frames[t_frame_count - 1].y_scale = 1.0; } t_disposal_region = t_image_region; t_disposal_mode = t_image_disposal; } MCImageFreeBitmap(t_canvas); MCImageFreeBitmap(t_restore_image); if (t_success) { r_frames = t_frames; r_count = t_frame_count; } else MCImageFreeFrames(t_frames, t_frame_count); return t_success; }
bool nglImageGIFCodec::Feed(nglIStream* pIStream) { GifFileType* pGIF = DGifOpen(pIStream, &GIFInputFunc); if (!pGIF) return false; if (DGifSlurp(pGIF) != GIF_OK) return false; nglImageInfo info(pGIF->SWidth, pGIF->SHeight, 32); if (!SendInfo(info)) { DGifCloseFile(pGIF); return false; } GifImageDesc* pImg = &pGIF->SavedImages[0].ImageDesc; // Local colormap has precedence over Global colormap ColorMapObject* pColormap = pImg->ColorMap ? pImg->ColorMap : pGIF->SColorMap; uint32 numcolors = pColormap->ColorCount; uint32 alphapalette = getTransparentColor(pGIF, 0); uint32 bgcolor = -1; // bgcolor is the background color to fill the bitmap if (pGIF->SColorMap) // There is a GlobalColorMap bgcolor = (uint8)pGIF->SBackGroundColor; // The SBGColor is meaningful else if (alphapalette >= 0) // There is a transparency color bgcolor = alphapalette; // set the bgcolor to tranparent else bgcolor = 0; // Don't know what to do here. // If this doesn't work, we could // create a new color and set the // alpha-channel to transparent // (unless we are using all the 256 // colors, in which case either we // give up, or move to 16-bits palette uint32 palette[256]; for (uint32 i = 0; i < numcolors; i++) { uint8 alpha = 255; if (i == bgcolor || i == alphapalette) alpha = 0; nuiColor c(pColormap->Colors[i].Red, pColormap->Colors[i].Green, pColormap->Colors[i].Blue, alpha); palette[i] = c.GetRGBA(); } uint32* pOutBuf = (uint32*)mpImage->GetBuffer(); uint8* pInBuf = (uint8*)(pGIF->SavedImages[0].RasterBits); for (uint32 i = 0; i < pGIF->SWidth * pGIF->SHeight; i++) *pOutBuf++ = palette[*pInBuf++]; SendData(1.0f); DGifCloseFile(pGIF); return true; }
static void Icon2Gif(char *FileName, FILE *txtin, int fdout) { unsigned int ExtCode, ColorMapSize = 0; GifColorType GlobalColorMap[256], LocalColorMap[256], *ColorMap = GlobalColorMap; char GlobalColorKeys[PRINTABLES], LocalColorKeys[PRINTABLES], *KeyTable = GlobalColorKeys; int red, green, blue; char buf[BUFSIZ * 2], InclusionFile[64]; GifFileType *GifFileOut; SavedImage *NewImage = NULL; int n, LineNum = 0; if ((GifFileOut = EGifOpenFileHandle(fdout)) == NULL) { (void) HandleGifError(GifFileOut); } /* OK, interpret directives */ while (fgets(buf, sizeof(buf), txtin) != (char *)NULL) { char *cp; ++LineNum; /* * Skip lines consisting only of whitespace and comments */ for (cp = buf; isspace((int)(*cp)); cp++) continue; if (*cp == '#' || *cp == '\0') continue; /* * If there's a trailing comment, nuke it and all preceding whitespace. * But preserve the EOL. */ if ((cp = strchr(buf, '#')) && (cp == strrchr(cp, '#'))) { while (isspace((int)(*--cp))) continue; *++cp = '\n'; *++cp = '\0'; } /* * Explicit header declarations */ if (sscanf(buf, "screen width %d\n", &GifFileOut->SWidth) == 1) continue; else if (sscanf(buf, "screen height %d\n", &GifFileOut->SHeight) == 1) continue; else if (sscanf(buf, "screen colors %d\n", &n) == 1) { int ResBits = BitSize(n); if (n > 256 || n < 0 || n != (1 << ResBits)) { PARSE_ERROR("Invalid color resolution value."); exit(EXIT_FAILURE); } GifFileOut->SColorResolution = ResBits; continue; } else if (sscanf(buf, "screen background %d\n", &GifFileOut->SBackGroundColor) == 1) continue; /* * Color table parsing */ else if (strcmp(buf, "screen map\n") == 0) { if (GifFileOut->SColorMap != NULL) { PARSE_ERROR("You've already declared a global color map."); exit(EXIT_FAILURE); } ColorMapSize = 0; ColorMap = GlobalColorMap; KeyTable = GlobalColorKeys; memset(GlobalColorKeys, '\0', sizeof(GlobalColorKeys)); } else if (strcmp(buf, "image map\n") == 0) { if (NewImage == NULL) { PARSE_ERROR("No previous image declaration."); exit(EXIT_FAILURE); } ColorMapSize = 0; ColorMap = LocalColorMap; KeyTable = LocalColorKeys; memset(LocalColorKeys, '\0', sizeof(LocalColorKeys)); } else if (sscanf(buf, " rgb %d %d %d is %c", &red, &green, &blue, &KeyTable[ColorMapSize]) == 4) { ColorMap[ColorMapSize].Red = red; ColorMap[ColorMapSize].Green = green; ColorMap[ColorMapSize].Blue = blue; ColorMapSize++; } else if (strcmp(buf, "end\n") == 0) { ColorMapObject *NewMap; NewMap = MakeMapObject(1 << BitSize(ColorMapSize), ColorMap); if (NewMap == (ColorMapObject *)NULL) { PARSE_ERROR("Out of memory while allocating new color map."); exit(EXIT_FAILURE); } if (NewImage) NewImage->ImageDesc.ColorMap = NewMap; else GifFileOut->SColorMap = NewMap; } /* GIF inclusion */ else if (sscanf(buf, "include %s", InclusionFile) == 1) { GifBooleanType DoTranslation; GifPixelType Translation[256]; GifFileType *Inclusion; SavedImage *NewImage, *CopyFrom; if ((Inclusion = DGifOpenFileName(InclusionFile)) == NULL || DGifSlurp(Inclusion) == GIF_ERROR) { PARSE_ERROR("Inclusion read failed."); QuitGifError(Inclusion, GifFileOut); } if ((DoTranslation = (GifFileOut->SColorMap!=(ColorMapObject*)NULL))) { ColorMapObject *UnionMap; UnionMap = UnionColorMap(GifFileOut->SColorMap, Inclusion->SColorMap, Translation); if (UnionMap == NULL) { PARSE_ERROR("Inclusion failed --- global map conflict."); QuitGifError(Inclusion, GifFileOut); } FreeMapObject(GifFileOut->SColorMap); GifFileOut->SColorMap = UnionMap; } for (CopyFrom = Inclusion->SavedImages; CopyFrom < Inclusion->SavedImages + Inclusion->ImageCount; CopyFrom++) { if ((NewImage = MakeSavedImage(GifFileOut, CopyFrom)) == NULL) { PARSE_ERROR("Inclusion failed --- out of memory."); QuitGifError(Inclusion, GifFileOut); } else if (DoTranslation) ApplyTranslation(NewImage, Translation); GifQprintf( "%s: Image %d at (%d, %d) [%dx%d]: from %s\n", PROGRAM_NAME, GifFileOut->ImageCount, NewImage->ImageDesc.Left, NewImage->ImageDesc.Top, NewImage->ImageDesc.Width, NewImage->ImageDesc.Height, InclusionFile); } (void) DGifCloseFile(Inclusion); } /* * Explicit image declarations */ else if (strcmp(buf, "image\n") == 0) { if ((NewImage = MakeSavedImage(GifFileOut, NULL)) == (SavedImage *)NULL) { PARSE_ERROR("Out of memory while allocating image block."); exit(EXIT_FAILURE); } /* use global table unless user specifies a local one */ ColorMap = GlobalColorMap; KeyTable = GlobalColorKeys; } /* * Nothing past this point is valid unless we've seen a previous * image declaration. */ else if (NewImage == (SavedImage *)NULL) { (void) fputs(buf, stderr); PARSE_ERROR("Syntax error in header block."); exit(EXIT_FAILURE); } /* * Accept image attributes */ else if (sscanf(buf, "image top %d\n", &NewImage->ImageDesc.Top) == 1) continue; else if (sscanf(buf, "image left %d\n", &NewImage->ImageDesc.Left)== 1) continue; else if (strcmp(buf, "image interlaced\n") == 0) { NewImage->ImageDesc.Interlace = TRUE; continue; } else if (sscanf(buf, "image bits %d by %d\n", &NewImage->ImageDesc.Width, &NewImage->ImageDesc.Height) == 2) { int i, j; static GifPixelType *Raster, *cp; int c; if ((Raster = (GifPixelType *) malloc(sizeof(GifPixelType) * NewImage->ImageDesc.Width * NewImage->ImageDesc.Height)) == NULL) { PARSE_ERROR("Failed to allocate raster block, aborted."); exit(EXIT_FAILURE); } if (!GifQuietPrint) fprintf(stderr, "%s: Image %d at (%d, %d) [%dx%d]: ", PROGRAM_NAME, GifFileOut->ImageCount, NewImage->ImageDesc.Left, NewImage->ImageDesc.Top, NewImage->ImageDesc.Width, NewImage->ImageDesc.Height); cp = Raster; for (i = 0; i < NewImage->ImageDesc.Height; i++) { char *dp; for (j = 0; j < NewImage->ImageDesc.Width; j++) if ((c = fgetc(txtin)) == EOF) { PARSE_ERROR("input file ended prematurely."); exit(EXIT_FAILURE); } else if (c == '\n') { --j; ++LineNum; } else if (isspace(c)) --j; else if ((dp = strchr(KeyTable, c))) *cp++ = (dp - KeyTable); else { PARSE_ERROR("Invalid pixel value."); exit(EXIT_FAILURE); } if (!GifQuietPrint) fprintf(stderr, "\b\b\b\b%-4d", i); } if (!GifQuietPrint) putc('\n', stderr); NewImage->RasterBits = (unsigned char *) Raster; } else if (sscanf(buf, "comment")) { MakeExtension(NewImage, COMMENT_EXT_FUNC_CODE); while (fgets(buf, sizeof(buf), txtin) != (char *)NULL) if (strcmp(buf, "end\n") == 0) break; else { int Len; buf[strlen(buf) - 1] = '\0'; Len = EscapeString(buf, buf); if (AddExtensionBlock(NewImage, Len, (unsigned char *)buf) == GIF_ERROR) { PARSE_ERROR("out of memory while adding comment block."); exit(EXIT_FAILURE); } } } else if (sscanf(buf, "plaintext")) { MakeExtension(NewImage, PLAINTEXT_EXT_FUNC_CODE); while (fgets(buf, sizeof(buf), txtin) != (char *)NULL) if (strcmp(buf, "end\n") == 0) break; else { int Len; buf[strlen(buf) - 1] = '\0'; Len = EscapeString(buf, buf); if (AddExtensionBlock(NewImage, Len, (unsigned char *)buf) == GIF_ERROR) { PARSE_ERROR("out of memory while adding plaintext block."); exit(EXIT_FAILURE); } } } else if (sscanf(buf, "extension %02x", &ExtCode)) { MakeExtension(NewImage, ExtCode); while (fgets(buf, sizeof(buf), txtin) != (char *)NULL) if (strcmp(buf, "end\n") == 0) break; else { int Len; buf[strlen(buf) - 1] = '\0'; Len = EscapeString(buf, buf); if (AddExtensionBlock(NewImage, Len, (unsigned char *)buf) == GIF_ERROR) { PARSE_ERROR("out of memory while adding extension block."); exit(EXIT_FAILURE); } } } else { (void) fputs(buf, stderr); PARSE_ERROR("Syntax error in image description."); exit(EXIT_FAILURE); } } if (EGifSpew(GifFileOut) == GIF_ERROR) HandleGifError(GifFileOut); }
int main (int argc, char **argv) { // inverse flag int rflag = 0, mflag = 0, cflag = 0, ch; while ((ch = getopt (argc, argv, "rmc")) != -1) { switch (ch) { case 'r': rflag = 1; break; case 'm': mflag = 1; break; case 'c': cflag = 1; break; default: // print error and exit usage (); return 1; } } // adjust args array post-getopt argc -= optind; argv += optind; if (argv[0] == NULL) { // print error and exit fputs ("File name missing\n", stderr); usage (); return 1; } char *fname = argv[0]; // open the GIF file GifFileType *SpriteGif; SpriteGif = DGifOpenFileName (fname); // check for error if (SpriteGif == NULL) { // print error and exit PrintGifError (); exit (1); } if (DGifSlurp (SpriteGif) == GIF_ERROR) { // print error and exit PrintGifError (); exit (1); } int rc; // return code if (cflag && mflag) { rc = DecodeMultiColorCharacterGraphics (SpriteGif); } else if (cflag) { rc = DecodeHiResCharacterGraphics (SpriteGif); } else if (mflag) { rc = DecodeMultiColorSpriteGraphics (SpriteGif); } else { rc = DecodeHiResSpriteGraphics (SpriteGif, rflag); } // close the file object if (DGifCloseFile (SpriteGif) == GIF_ERROR) { // print error and exit PrintGifError (); return 1; } return rc; }
/*! * \brief gifToPix() * * \param[in] gif opened gif stream * \return pix, or NULL on error * * <pre> * Notes: * (1) This decodes the pix from the compressed gif stream and * closes the stream. * (2) It is static so that the stream is not exposed to clients. * </pre> */ static PIX * gifToPix(GifFileType *gif) { l_int32 wpl, i, j, w, h, d, cindex, ncolors; l_int32 rval, gval, bval; l_uint32 *data, *line; PIX *pixd, *pixdi; PIXCMAP *cmap; ColorMapObject *gif_cmap; SavedImage si; #if (GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1) || GIFLIB_MAJOR > 5 int giferr; #endif /* 5.1 and beyond */ PROCNAME("gifToPix"); /* Read all the data, but use only the first image found */ if (DGifSlurp(gif) != GIF_OK) { DGifCloseFile(gif, &giferr); return (PIX *)ERROR_PTR("failed to read GIF data", procName, NULL); } if (gif->SavedImages == NULL) { DGifCloseFile(gif, &giferr); return (PIX *)ERROR_PTR("no images found in GIF", procName, NULL); } si = gif->SavedImages[0]; w = si.ImageDesc.Width; h = si.ImageDesc.Height; if (w <= 0 || h <= 0) { DGifCloseFile(gif, &giferr); return (PIX *)ERROR_PTR("invalid image dimensions", procName, NULL); } if (si.RasterBits == NULL) { DGifCloseFile(gif, &giferr); return (PIX *)ERROR_PTR("no raster data in GIF", procName, NULL); } if (si.ImageDesc.ColorMap) { /* private cmap for this image */ gif_cmap = si.ImageDesc.ColorMap; } else if (gif->SColorMap) { /* global cmap for whole picture */ gif_cmap = gif->SColorMap; } else { /* don't know where to take cmap from */ DGifCloseFile(gif, &giferr); return (PIX *)ERROR_PTR("color map is missing", procName, NULL); } ncolors = gif_cmap->ColorCount; if (ncolors <= 2) d = 1; else if (ncolors <= 4) d = 2; else if (ncolors <= 16) d = 4; else d = 8; if ((cmap = pixcmapCreate(d)) == NULL) { DGifCloseFile(gif, &giferr); return (PIX *)ERROR_PTR("cmap creation failed", procName, NULL); } for (cindex = 0; cindex < ncolors; cindex++) { rval = gif_cmap->Colors[cindex].Red; gval = gif_cmap->Colors[cindex].Green; bval = gif_cmap->Colors[cindex].Blue; pixcmapAddColor(cmap, rval, gval, bval); } if ((pixd = pixCreate(w, h, d)) == NULL) { DGifCloseFile(gif, &giferr); pixcmapDestroy(&cmap); return (PIX *)ERROR_PTR("failed to allocate pixd", procName, NULL); } pixSetInputFormat(pixd, IFF_GIF); pixSetColormap(pixd, cmap); wpl = pixGetWpl(pixd); data = pixGetData(pixd); for (i = 0; i < h; i++) { line = data + i * wpl; if (d == 1) { for (j = 0; j < w; j++) { if (si.RasterBits[i * w + j]) SET_DATA_BIT(line, j); } } else if (d == 2) { for (j = 0; j < w; j++) SET_DATA_DIBIT(line, j, si.RasterBits[i * w + j]); } else if (d == 4) { for (j = 0; j < w; j++) SET_DATA_QBIT(line, j, si.RasterBits[i * w + j]); } else { /* d == 8 */ for (j = 0; j < w; j++) SET_DATA_BYTE(line, j, si.RasterBits[i * w + j]); } } /* If the image has been interlaced (for viewing in a browser), * this restores the raster lines to normal order. */ if (gif->Image.Interlace) { pixdi = pixUninterlaceGIF(pixd); pixTransferAllData(pixd, &pixdi, 0, 0); } DGifCloseFile(gif, &giferr); return pixd; }
/* gif_load_img: * Load GIF image. */ int gif_load_img(img I) { GifFileType *g = I->us; struct SavedImage *si; int ret = 0; unsigned char *p, *end; GifColorType *pal; pel *q; if (DGifSlurp(g) == GIF_ERROR) { I->err = IE_IMGFORMAT; return 0; } /* Now allocate memory and copy the image into it. */ img_alloc(I); /* Retrieve only the first image. */ if (g->ImageCount < 1) { I->err = IE_IMGFORMAT; goto fail; } si = g->SavedImages; if (si->ImageDesc.Width != I->width || si->ImageDesc.Height != I->height) { I->err = IE_IMGFORMAT; goto fail; } if (si->ImageDesc.ColorMap) pal = si->ImageDesc.ColorMap->Colors; else pal = g->SColorMap->Colors; if (si->ImageDesc.Interlace) { int i; unsigned char *gifsrc = si->RasterBits; /* Deal with deranged interlaced GIF file. */ #define COPYROW(src, dest) for (p = (src), q = (dest); p < (src) + I->width; ++p, ++q) \ *q = PELA(pal[*p].Red, pal[*p].Green, pal[*p].Blue, *p == g->SBackGroundColor ? 255 : 0); /* Pass 1: every 8th row, starting at row 0. */ for (i = 0; i < I->height; i += 8) { COPYROW(gifsrc, I->data[i]); gifsrc += I->width; } /* Pass 2: every 8th row, starting at row 4. */ for (i = 4; i < I->height; i += 8) { COPYROW(gifsrc, I->data[i]); gifsrc += I->width; } /* Pass 3: every 4th row, starting at row 2. */ for (i = 2; i < I->height; i += 4) { COPYROW(gifsrc, I->data[i]); gifsrc += I->width; } /* Pass 4: every 2nd row, starting at row 1. */ for (i = 1; i < I->height; i += 2) { COPYROW(gifsrc, I->data[i]); gifsrc += I->width; } } else for (p = (unsigned char*)si->RasterBits, end = p + I->width * I->height, q = I->flat; p < end; ++p, ++q) *q = PELA(pal[*p].Red, pal[*p].Green, pal[*p].Blue, *p == g->SBackGroundColor ? 255 : 0); ret = 1; fail: DGifCloseFile(g); return ret; }
bool ZLWin32ImageManager::gifConvert(const std::string &stringData, ZLWin32ImageData &data, bool &result) const { result = false; GifReader reader(stringData); GifFileType *gif = DGifOpen(&reader, GifReader::inputFunction); if (gif == 0) { return false; } if (DGifSlurp(gif) != GIF_OK) { DGifCloseFile(gif); return false; } ColorMapObject* colormap = gif->SColorMap; if ((colormap == 0) || (gif->ImageCount < 1) || (colormap->ColorCount != (1 << colormap->BitsPerPixel))) { DGifCloseFile(gif); return false; } SavedImage* gif_image = gif->SavedImages; const int width = gif->SWidth; const int height = gif->SHeight; int transparent = -1; for (int i = 0; i < gif_image->ExtensionBlockCount; ++i) { ExtensionBlock* eb = gif_image->ExtensionBlocks + i; if (eb->Function == 0xF9 && eb->ByteCount == 4) { if ((eb->Bytes[0] & 1) == 1) { transparent = (unsigned char)eb->Bytes[3]; } } } data.init(width, height, (transparent != -1), 0); byte *ptr = gif_image->RasterBits; if (gif->Image.Interlace) { for (int i = 0; i < height; i += 8) { data.setPosition(0, i); copyLine(*colormap, ptr, data, width, transparent); } for (int i = 4; i < height; i += 8) { data.setPosition(0, i); copyLine(*colormap, ptr, data, width, transparent); } for (int i = 2; i < height; i += 4) { data.setPosition(0, i); copyLine(*colormap, ptr, data, width, transparent); } for (int i = 1; i < height; i += 2) { data.setPosition(0, i); copyLine(*colormap, ptr, data, width, transparent); } } else { for (int i = 0; i < height; ++i) { data.setPosition(0, i); copyLine(*colormap, ptr, data, width, transparent); } } DGifCloseFile(gif); result = true; return true; }
/* * GIFの最初の1枚を読む */ static int load_gif_sub(RefImage *image, Value r, int info_only) { int err = 0; int rowbytes; GifFileType *gif = DGifOpen(&r, gif_read_callback, &err); if (gif == NULL) { fs->throw_errorf(mod_image, "ImageError", "Failed to read GIF image"); return FALSE; } if (gif->SWidth > MAX_IMAGE_SIZE || gif->SHeight > MAX_IMAGE_SIZE) { fs->throw_errorf(mod_image, "ImageError", "Image size too large (max:%d)", MAX_IMAGE_SIZE); DGifCloseFile(gif); return FALSE; } image->bands = BAND_P; image->width = gif->SWidth; image->height = gif->SHeight; rowbytes = image->width; image->pitch = rowbytes; if (!info_only) { const ColorMapObject *cmap; const SavedImage *si; if (DGifSlurp(gif) == GIF_ERROR || gif->ImageCount <= 0) { fs->throw_errorf(mod_image, "ImageError", "Failed to read GIF image"); return FALSE; } si = &gif->SavedImages[0]; // パレット読み込み if (si->ImageDesc.ColorMap != NULL) { cmap = si->ImageDesc.ColorMap; } else { cmap = gif->SColorMap; } if (cmap != NULL) { int i; int color_key; uint32_t *col = malloc(sizeof(uint32_t) * PALETTE_NUM); for (i = 0; i < PALETTE_NUM; i++) { col[i] = COLOR_A_MASK; } for (i = 0; i < cmap->ColorCount; i++) { const GifColorType *c = &cmap->Colors[i]; col[i] = (c->Red << COLOR_R_SHIFT) | (c->Green << COLOR_G_SHIFT) | (c->Blue << COLOR_B_SHIFT) | COLOR_A_MASK; } color_key = get_transparent_index(si); if (color_key >= 0) { col[color_key] &= ~COLOR_A_MASK; } image->palette = col; } else { // Illigal image->bands = BAND_L; } if (si->RasterBits != NULL) { int y; int size_alloc = rowbytes * image->height; const GifImageDesc *id = &si->ImageDesc; uint8_t *data; if (size_alloc > fs->max_alloc) { fs->throw_error_select(THROW_MAX_ALLOC_OVER__INT, fs->max_alloc); DGifCloseFile(gif); return FALSE; } if (id->Left < 0 || id->Left + id->Width > image->width || id->Top < 0 || id->Top + id->Height > image->height) { fs->throw_errorf(mod_image, "ImageError", "Invalid GIF format"); DGifCloseFile(gif); return FALSE; } data = malloc(size_alloc); memset(data, gif->SBackGroundColor, size_alloc); for (y = 0; y < id->Height; y++) { memcpy(data + rowbytes * (y + id->Top) + id->Left, si->RasterBits + id->Width * y, id->Width); } image->data = data; } } DGifCloseFile(gif); return TRUE; }
int readGif(GifFileType *file, dblData result) { ColorMapObject *colorMap; unsigned char *bits; unsigned char *data; unsigned char *p; int i, nColors, size, alpha, bgColor, alignedWidth, bytesPerColor; unsigned long outsize; if(DGifSlurp(file) != GIF_OK) // error("Error slurping file"); return 0; /* data should now be available */ /* Local colormap has precedence over Global colormap */ colorMap = file->Image.ColorMap ? file->Image.ColorMap : file->SColorMap; nColors = colorMap->ColorCount; alpha = getTransparentColor(file); /* bgColor is the background color to fill the bitmap with * if an image is smaller than screen coordinates */ if (file->SColorMap) /* There is a GlobalColorMap */ bgColor = file->SBackGroundColor; /* The BackGroundColor is meaningful */ else if (alpha >= 0) /* There is a transparency color */ bgColor = alpha; /* set the bgColor to tranparent */ else bgColor = 0; /* Don't know what to do here. * If this doesn't work, we could * create a new color and set the * alpha-channel to transparent * (unless we are using all the 256 * colors, in which case either we * give up, or move to 16-bits palette */ result->hasalpha = 0; bytesPerColor = 3; if (alpha >= 0) { bytesPerColor += 1; /* if tranparent color, use the alpha * channel (RGBA instead of RGB) */ result->hasalpha = 1; } /* Ah! The Flash specs says scanlines must be DWORD ALIGNED! * (but image width is the correct number of pixels) */ alignedWidth = (file->SWidth + 3) & ~3; /* size = size-of-colormap + size-of-bitmap */ size = (nColors * bytesPerColor) + (alignedWidth * file->SHeight); data = malloc(size); result->format = 3; result->width = file->SWidth; result->height = file->SHeight; result->format2 = nColors-1; /* size(colorMap) - 1 */ p = data; /* create ColorMap */ for(i=0; i<nColors; ++i) { GifColorType c = colorMap->Colors[i]; if (bytesPerColor == 3) { /* RGB */ *p++ = c.Red; *p++ = c.Green; *p++ = c.Blue; } else { /* RGBA */ #if 1 /* You would think that an alpha value of 0 * would mean fully transparent, but Flash * player doesn't seem to think so. * So, we just set the transparency color * as 0,0,0,0 */ if (i != alpha) { *p++ = c.Red; *p++ = c.Green; *p++ = c.Blue; *p++ = 255; /* Fully opaque */ } else { *p++ = 0; /* red */ *p++ = 0; /* green */ *p++ = 0; /* blue */ *p++ = 0; /* Fully transparent */ } #else *p++ = c.Red; *p++ = c.Green; *p++ = c.Blue; *p++ = (i != alpha) ? 255 : 0; /* set alpha to 0 for transparent color */ #endif } } bits = file->SavedImages[0].RasterBits; if (alignedWidth == file->SWidth && file->Image.Width == file->SWidth && file->Image.Height == file->SHeight) { /* we are all nicely aligned and don't need to move the bitmap around. * Just copy the bits into the output buffer. */ memcpy(p, bits, file->SWidth * file->SHeight); } else { /* here we need to pad the scanline or to move the bitmap around * (if the image is not at 0,0 in the logical screen) */ int screenWidth = file->SWidth; int screenHeight = file->SHeight; int imageTop = file->Image.Top; int imageBottom = file->Image.Top + file->Image.Height; int imageLeft = file->Image.Left; int imageWidth = file->Image.Width; for (i=0; i < screenHeight; i++, p += alignedWidth) { /* the image is smaller than the logical "screen": * Fill the reminder with the background color. */ if (imageWidth != screenWidth) memset(p, bgColor, screenWidth); /* finally, copy scanline */ if (i >= imageTop && i < imageBottom) { memcpy(p + imageLeft, bits, imageWidth); bits += imageWidth; } } } /* Done! */ #if GIFLIB_MAJOR >= 5 && GIFLIB_MINOR >= 1 if (DGifCloseFile(file, NULL) != GIF_OK) return 0; #else DGifCloseFile(file); #endif result->data = malloc(outsize = (int)floor(size*1.01+12)); /* zlib-compress the gif data */ compress2(result->data, &outsize, data, size, 9); result->length = outsize; free(data); return 1; }
// Read animated GIF bitstream from 'filename' into 'AnimatedImage' struct. static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image, int dump_frames, const char dump_folder[]) { uint32_t frame_count; uint32_t canvas_width, canvas_height; uint32_t i; int gif_error; GifFileType* gif; gif = DGifOpenFileName(filename, NULL); if (gif == NULL) { fprintf(stderr, "Could not read file: %s.\n", filename); return 0; } gif_error = DGifSlurp(gif); if (gif_error != GIF_OK) { fprintf(stderr, "Could not parse image: %s.\n", filename); GIFDisplayError(gif, gif_error); DGifCloseFile(gif, NULL); return 0; } // Animation properties. image->canvas_width = (uint32_t)gif->SWidth; image->canvas_height = (uint32_t)gif->SHeight; if (image->canvas_width > MAX_CANVAS_SIZE || image->canvas_height > MAX_CANVAS_SIZE) { fprintf(stderr, "Invalid canvas dimension: %d x %d\n", image->canvas_width, image->canvas_height); DGifCloseFile(gif, NULL); return 0; } image->loop_count = GetLoopCountGIF(gif); image->bgcolor = GetBackgroundColorGIF(gif); frame_count = (uint32_t)gif->ImageCount; if (frame_count == 0) { DGifCloseFile(gif, NULL); return 0; } if (image->canvas_width == 0 || image->canvas_height == 0) { image->canvas_width = gif->SavedImages[0].ImageDesc.Width; image->canvas_height = gif->SavedImages[0].ImageDesc.Height; gif->SavedImages[0].ImageDesc.Left = 0; gif->SavedImages[0].ImageDesc.Top = 0; if (image->canvas_width == 0 || image->canvas_height == 0) { fprintf(stderr, "Invalid canvas size in GIF.\n"); DGifCloseFile(gif, NULL); return 0; } } // Allocate frames. AllocateFrames(image, frame_count); canvas_width = image->canvas_width; canvas_height = image->canvas_height; // Decode and reconstruct frames. for (i = 0; i < frame_count; ++i) { const int canvas_width_in_bytes = canvas_width * kNumChannels; const SavedImage* const curr_gif_image = &gif->SavedImages[i]; GraphicsControlBlock curr_gcb; DecodedFrame* curr_frame; uint8_t* curr_rgba; memset(&curr_gcb, 0, sizeof(curr_gcb)); DGifSavedExtensionToGCB(gif, i, &curr_gcb); curr_frame = &image->frames[i]; curr_rgba = curr_frame->rgba; curr_frame->duration = GetFrameDurationGIF(gif, i); if (i == 0) { // Initialize as transparent. curr_frame->is_key_frame = 1; ZeroFillCanvas(curr_rgba, canvas_width, canvas_height); } else { DecodedFrame* const prev_frame = &image->frames[i - 1]; const GifImageDesc* const prev_desc = &gif->SavedImages[i - 1].ImageDesc; GraphicsControlBlock prev_gcb; memset(&prev_gcb, 0, sizeof(prev_gcb)); DGifSavedExtensionToGCB(gif, i - 1, &prev_gcb); curr_frame->is_key_frame = IsKeyFrameGIF(prev_desc, prev_gcb.DisposalMode, prev_frame, canvas_width, canvas_height); if (curr_frame->is_key_frame) { // Initialize as transparent. ZeroFillCanvas(curr_rgba, canvas_width, canvas_height); } else { int prev_frame_disposed, curr_frame_opaque; int prev_frame_completely_covered; // Initialize with previous canvas. uint8_t* const prev_rgba = image->frames[i - 1].rgba; CopyCanvas(prev_rgba, curr_rgba, canvas_width, canvas_height); // Dispose previous frame rectangle. prev_frame_disposed = (prev_gcb.DisposalMode == DISPOSE_BACKGROUND || prev_gcb.DisposalMode == DISPOSE_PREVIOUS); curr_frame_opaque = (curr_gcb.TransparentColor == NO_TRANSPARENT_COLOR); prev_frame_completely_covered = curr_frame_opaque && CoversFrameGIF(&curr_gif_image->ImageDesc, prev_desc); if (prev_frame_disposed && !prev_frame_completely_covered) { switch (prev_gcb.DisposalMode) { case DISPOSE_BACKGROUND: { ZeroFillFrameRect(curr_rgba, canvas_width_in_bytes, prev_desc->Left, prev_desc->Top, prev_desc->Width, prev_desc->Height); break; } case DISPOSE_PREVIOUS: { int src_frame_num = i - 2; while (src_frame_num >= 0) { GraphicsControlBlock src_frame_gcb; memset(&src_frame_gcb, 0, sizeof(src_frame_gcb)); DGifSavedExtensionToGCB(gif, src_frame_num, &src_frame_gcb); if (src_frame_gcb.DisposalMode != DISPOSE_PREVIOUS) break; --src_frame_num; } if (src_frame_num >= 0) { // Restore pixels inside previous frame rectangle to // corresponding pixels in source canvas. uint8_t* const src_frame_rgba = image->frames[src_frame_num].rgba; CopyFrameRectangle(src_frame_rgba, curr_rgba, canvas_width_in_bytes, prev_desc->Left, prev_desc->Top, prev_desc->Width, prev_desc->Height); } else { // Source canvas doesn't exist. So clear previous frame // rectangle to background. ZeroFillFrameRect(curr_rgba, canvas_width_in_bytes, prev_desc->Left, prev_desc->Top, prev_desc->Width, prev_desc->Height); } break; } default: break; // Nothing to do. } } } } // Decode current frame. if (!ReadFrameGIF(curr_gif_image, gif->SColorMap, curr_gcb.TransparentColor, canvas_width_in_bytes, curr_rgba)) { DGifCloseFile(gif, NULL); return 0; } if (dump_frames) { if (!DumpFrame(filename, dump_folder, i, curr_rgba, canvas_width, canvas_height)) { DGifCloseFile(gif, NULL); return 0; } } } DGifCloseFile(gif, NULL); return 1; }
/*! * pixReadStreamGif() * * Input: stream * Return: pix, or null on error */ PIX * pixReadStreamGif(FILE *fp) { l_int32 fd, wpl, i, j, w, h, d, cindex, ncolors; l_int32 rval, gval, bval; l_uint32 *data, *line; GifFileType *gif; PIX *pixd, *pixdi; PIXCMAP *cmap; ColorMapObject *gif_cmap; SavedImage si; PROCNAME("pixReadStreamGif"); if ((fd = fileno(fp)) < 0) return (PIX *)ERROR_PTR("invalid file descriptor", procName, NULL); #ifndef _MSC_VER lseek(fd, 0, SEEK_SET); #else _lseek(fd, 0, SEEK_SET); #endif /* _MSC_VER */ if ((gif = DGifOpenFileHandle(fd)) == NULL) return (PIX *)ERROR_PTR("invalid file or file not found", procName, NULL); /* Read all the data, but use only the first image found */ if (DGifSlurp(gif) != GIF_OK) { DGifCloseFile(gif); return (PIX *)ERROR_PTR("failed to read GIF data", procName, NULL); } if (gif->SavedImages == NULL) { DGifCloseFile(gif); return (PIX *)ERROR_PTR("no images found in GIF", procName, NULL); } si = gif->SavedImages[0]; w = si.ImageDesc.Width; h = si.ImageDesc.Height; if (w <= 0 || h <= 0) { DGifCloseFile(gif); return (PIX *)ERROR_PTR("invalid image dimensions", procName, NULL); } if (si.RasterBits == NULL) { DGifCloseFile(gif); return (PIX *)ERROR_PTR("no raster data in GIF", procName, NULL); } if (si.ImageDesc.ColorMap) { /* private cmap for this image */ gif_cmap = si.ImageDesc.ColorMap; } else if (gif->SColorMap) { /* global cmap for whole picture */ gif_cmap = gif->SColorMap; } else { /* don't know where to take cmap from */ DGifCloseFile(gif); return (PIX *)ERROR_PTR("color map is missing", procName, NULL); } ncolors = gif_cmap->ColorCount; if (ncolors <= 2) d = 1; else if (ncolors <= 4) d = 2; else if (ncolors <= 16) d = 4; else d = 8; if ((cmap = pixcmapCreate(d)) == NULL) return (PIX *)ERROR_PTR("cmap creation failed", procName, NULL); for (cindex = 0; cindex < ncolors; cindex++) { rval = gif_cmap->Colors[cindex].Red; gval = gif_cmap->Colors[cindex].Green; bval = gif_cmap->Colors[cindex].Blue; pixcmapAddColor(cmap, rval, gval, bval); } if ((pixd = pixCreate(w, h, d)) == NULL) { DGifCloseFile(gif); pixcmapDestroy(&cmap); return (PIX *)ERROR_PTR("failed to allocate pixd", procName, NULL); } pixSetColormap(pixd, cmap); wpl = pixGetWpl(pixd); data = pixGetData(pixd); for (i = 0; i < h; i++) { line = data + i * wpl; if (d == 1) { for (j = 0; j < w; j++) { if (si.RasterBits[i * w + j]) SET_DATA_BIT(line, j); } } else if (d == 2) { for (j = 0; j < w; j++) SET_DATA_DIBIT(line, j, si.RasterBits[i * w + j]); } else if (d == 4) { for (j = 0; j < w; j++) SET_DATA_QBIT(line, j, si.RasterBits[i * w + j]); } else { /* d == 8 */ for (j = 0; j < w; j++) SET_DATA_BYTE(line, j, si.RasterBits[i * w + j]); } } if (gif->Image.Interlace) { pixdi = pixInterlaceGIF(pixd); pixTransferAllData(pixd, &pixdi, 0, 0); } DGifCloseFile(gif); return pixd; }
/************************************************************************ 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; } }