Exemplo n.º 1
0
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());
    }
  }
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
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);
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
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;
}
Exemplo n.º 7
0
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;
  }
}
Exemplo n.º 8
0
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;
  }
}
Exemplo n.º 9
0
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;
}
Exemplo n.º 10
0
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;
}
Exemplo n.º 11
0
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;
}
Exemplo n.º 12
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;
}
Exemplo n.º 13
0
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);
}
Exemplo n.º 14
0
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;
}
Exemplo n.º 15
0
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;
}
Exemplo n.º 17
0
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;
}
Exemplo n.º 18
0
//=================================================================================
// 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);
}
Exemplo n.º 19
0
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;
}
Exemplo n.º 20
0
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;
}
Exemplo n.º 21
0
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);
}
Exemplo n.º 22
0
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;
}
Exemplo n.º 23
0
/*!
 * \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;
}
Exemplo n.º 24
0
/* 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;
}
Exemplo n.º 26
0
/*
 * 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;
}
Exemplo n.º 27
0
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;
}
Exemplo n.º 28
0
// 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;
}
Exemplo n.º 29
0
/*!
 *  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;
}
Exemplo n.º 30
0
/************************************************************************
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;
		}
	}