From c51091c2501c74eb101d1d58795807c5ba5ec64f Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Thu, 9 Jul 2009 15:03:22 -0500 Subject: [PATCH] oleaut32: use WIC to decode gif files --- dlls/oleaut32/Makefile.in | 3 +- dlls/oleaut32/olepicture.c | 395 ++++++++---------- dlls/oleaut32/regsvr.c | 1 + dlls/oleaut32/ungif.c | 999 -------------------------------------------- dlls/oleaut32/ungif.h | 169 -------- 5 files changed, 180 insertions(+), 1387 deletions(-) delete mode 100644 dlls/oleaut32/ungif.c delete mode 100644 dlls/oleaut32/ungif.h diff --git a/dlls/oleaut32/Makefile.in b/dlls/oleaut32/Makefile.in index 0f2be7f..59b4b91 100644 --- a/dlls/oleaut32/Makefile.in +++ b/dlls/oleaut32/Makefile.in @@ -5,7 +5,7 @@ VPATH = @srcdir@ MODULE = oleaut32.dll IMPORTLIB = oleaut32 IMPORTS = uuid ole32 rpcrt4 user32 gdi32 advapi32 kernel32 ntdll -DELAYIMPORTS = comctl32 urlmon +DELAYIMPORTS = comctl32 urlmon windowscodecs EXTRADEFS = -D_OLEAUT32_ -DCOM_NO_WINDOWS_H \ -DENTRY_PREFIX=OLEAUTPS_ -DPROXY_CLSID=CLSID_PSDispatch -DPROXY_DELEGATION -DREGISTER_PROXY_DLL EXTRAINCL = @PNGINCL@ @@ -24,7 +24,6 @@ C_SRCS = \ tmarshal.c \ typelib.c \ typelib2.c \ - ungif.c \ usrmarshal.c \ varformat.c \ variant.c \ diff --git a/dlls/oleaut32/olepicture.c b/dlls/oleaut32/olepicture.c index 54baf12..83e5349 100644 --- a/dlls/oleaut32/olepicture.c +++ b/dlls/oleaut32/olepicture.c @@ -82,12 +82,11 @@ #include "oleauto.h" #include "connpt.h" #include "urlmon.h" +#include "wincodec.h" #include "wine/debug.h" #include "wine/unicode.h" #include "wine/library.h" -#include "ungif.h" - WINE_DEFAULT_DEBUG_CHANNEL(ole); #include "pshpack1.h" @@ -1059,220 +1058,6 @@ static jpeg_boolean _jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired) static void _jpeg_term_source(j_decompress_ptr cinfo) { } #endif /* SONAME_LIBJPEG */ -struct gifdata { - unsigned char *data; - unsigned int curoff; - unsigned int len; -}; - -static int _gif_inputfunc(GifFileType *gif, GifByteType *data, int len) { - struct gifdata *gd = gif->UserData; - - if (len+gd->curoff > gd->len) { - ERR("Trying to read %d bytes, but only %d available.\n",len, gd->len-gd->curoff); - len = gd->len - gd->curoff; - } - memcpy(data, gd->data+gd->curoff, len); - gd->curoff += len; - return len; -} - - -static HRESULT OLEPictureImpl_LoadGif(OLEPictureImpl *This, BYTE *xbuf, ULONG xread) -{ - struct gifdata gd; - GifFileType *gif; - BITMAPINFO *bmi; - HDC hdcref; - LPBYTE bytes; - int i,j,ret; - GifImageDesc *gid; - SavedImage *si; - ColorMapObject *cm; - int transparent = -1; - ExtensionBlock *eb; - int padding; - - gd.data = xbuf; - gd.curoff = 0; - gd.len = xread; - gif = DGifOpen((void*)&gd, _gif_inputfunc); - ret = DGifSlurp(gif); - if (ret == GIF_ERROR) { - ERR("Failed reading GIF using libgif.\n"); - return E_FAIL; - } - TRACE("screen height %d, width %d\n", gif->SWidth, gif->SHeight); - TRACE("color res %d, backgcolor %d\n", gif->SColorResolution, gif->SBackGroundColor); - TRACE("imgcnt %d\n", gif->ImageCount); - if (gif->ImageCount<1) { - ERR("GIF stream does not have images inside?\n"); - return E_FAIL; - } - TRACE("curimage: %d x %d, on %dx%d, interlace %d\n", - gif->Image.Width, gif->Image.Height, - gif->Image.Left, gif->Image.Top, - gif->Image.Interlace - ); - /* */ - padding = (gif->SWidth+3) & ~3; - si = gif->SavedImages+0; - gid = &(si->ImageDesc); - cm = gid->ColorMap; - if (!cm) cm = gif->SColorMap; - bmi = HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER)+(cm->ColorCount)*sizeof(RGBQUAD)); - bytes= HeapAlloc(GetProcessHeap(),0,padding*gif->SHeight); - - /* look for the transparent color extension */ - for (i = 0; i < si->ExtensionBlockCount; ++i) { - eb = si->ExtensionBlocks + i; - if (eb->Function == 0xF9 && eb->ByteCount == 4) { - if ((eb->Bytes[0] & 1) == 1) { - transparent = (unsigned char)eb->Bytes[3]; - } - } - } - - for (i = 0; i < cm->ColorCount; i++) { - bmi->bmiColors[i].rgbRed = cm->Colors[i].Red; - bmi->bmiColors[i].rgbGreen = cm->Colors[i].Green; - bmi->bmiColors[i].rgbBlue = cm->Colors[i].Blue; - if (i == transparent) { - This->rgbTrans = RGB(bmi->bmiColors[i].rgbRed, - bmi->bmiColors[i].rgbGreen, - bmi->bmiColors[i].rgbBlue); - } - } - - /* Map to in picture coordinates */ - for (i = 0, j = 0; i < gid->Height; i++) { - if (gif->Image.Interlace) { - memcpy( - bytes + (gid->Top + j) * padding + gid->Left, - si->RasterBits + i * gid->Width, - gid->Width); - - /* Lower bits of interlaced counter encode current interlace */ - if (j & 1) j += 2; /* Currently filling odd rows */ - else if (j & 2) j += 4; /* Currently filling even rows not multiples of 4 */ - else j += 8; /* Currently filling every 8th row or 4th row in-between */ - - if (j >= gid->Height && i < gid->Height && (j & 1) == 0) { - /* End of current interlace, go to next interlace */ - if (j & 2) j = 1; /* Next iteration fills odd rows */ - else if (j & 4) j = 2; /* Next iteration fills even rows not mod 4 and not mod 8 */ - else j = 4; /* Next iteration fills rows in-between rows mod 6 */ - } - } else { - memcpy( - bytes + (gid->Top + i) * padding + gid->Left, - si->RasterBits + i * gid->Width, - gid->Width); - } - } - - bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi->bmiHeader.biWidth = gif->SWidth; - bmi->bmiHeader.biHeight = -gif->SHeight; - bmi->bmiHeader.biPlanes = 1; - bmi->bmiHeader.biBitCount = 8; - bmi->bmiHeader.biCompression = BI_RGB; - bmi->bmiHeader.biSizeImage = padding*gif->SHeight; - bmi->bmiHeader.biXPelsPerMeter = 0; - bmi->bmiHeader.biYPelsPerMeter = 0; - bmi->bmiHeader.biClrUsed = cm->ColorCount; - bmi->bmiHeader.biClrImportant = 0; - - hdcref = GetDC(0); - This->desc.u.bmp.hbitmap=CreateDIBitmap( - hdcref, - &bmi->bmiHeader, - CBM_INIT, - bytes, - bmi, - DIB_RGB_COLORS - ); - - if (transparent > -1) { - /* Create the Mask */ - HDC hdc = CreateCompatibleDC(0); - HDC hdcMask = CreateCompatibleDC(0); - HBITMAP hOldbitmap; - HBITMAP hOldbitmapmask; - - unsigned int monopadding = (((unsigned)(gif->SWidth + 31)) >> 5) << 2; - HBITMAP hTempMask; - - This->hbmXor = CreateDIBitmap( - hdcref, - &bmi->bmiHeader, - CBM_INIT, - bytes, - bmi, - DIB_RGB_COLORS - ); - - bmi->bmiColors[0].rgbRed = 0; - bmi->bmiColors[0].rgbGreen = 0; - bmi->bmiColors[0].rgbBlue = 0; - bmi->bmiColors[1].rgbRed = 255; - bmi->bmiColors[1].rgbGreen = 255; - bmi->bmiColors[1].rgbBlue = 255; - - bmi->bmiHeader.biBitCount = 1; - bmi->bmiHeader.biSizeImage = monopadding*gif->SHeight; - bmi->bmiHeader.biClrUsed = 2; - - for (i = 0; i < gif->SHeight; i++) { - unsigned char * colorPointer = bytes + padding * i; - unsigned char * monoPointer = bytes + monopadding * i; - for (j = 0; j < gif->SWidth; j++) { - unsigned char pixel = colorPointer[j]; - if ((j & 7) == 0) monoPointer[j >> 3] = 0; - if (pixel == (transparent & 0x000000FFU)) monoPointer[j >> 3] |= 1 << (7 - (j & 7)); - } - } - hTempMask = CreateDIBitmap( - hdcref, - &bmi->bmiHeader, - CBM_INIT, - bytes, - bmi, - DIB_RGB_COLORS - ); - - bmi->bmiHeader.biHeight = -bmi->bmiHeader.biHeight; - This->hbmMask = CreateBitmap(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 1, 1, NULL); - hOldbitmap = SelectObject(hdc, hTempMask); - hOldbitmapmask = SelectObject(hdcMask, This->hbmMask); - - SetBkColor(hdc, RGB(255, 255, 255)); - BitBlt(hdcMask, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, hdc, 0, 0, SRCCOPY); - - /* We no longer need the original bitmap, so we apply the first - transformation with the mask to speed up the rendering */ - SelectObject(hdc, This->hbmXor); - SetBkColor(hdc, RGB(0,0,0)); - SetTextColor(hdc, RGB(255,255,255)); - BitBlt(hdc, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, - hdcMask, 0, 0, SRCAND); - - SelectObject(hdc, hOldbitmap); - SelectObject(hdcMask, hOldbitmapmask); - DeleteDC(hdcMask); - DeleteDC(hdc); - DeleteObject(hTempMask); - } - - ReleaseDC(0, hdcref); - This->desc.picType = PICTYPE_BITMAP; - OLEPictureImpl_SetBitmap(This); - DGifCloseFile(gif); - HeapFree(GetProcessHeap(),0,bmi); - HeapFree(GetProcessHeap(),0,bytes); - return S_OK; -} - static HRESULT OLEPictureImpl_LoadJpeg(OLEPictureImpl *This, BYTE *xbuf, ULONG xread) { #ifdef SONAME_LIBJPEG @@ -1404,6 +1189,182 @@ static HRESULT OLEPictureImpl_LoadDIB(OLEPictureImpl *This, BYTE *xbuf, ULONG xr return S_OK; } +static HRESULT OLEPictureImpl_LoadWICSource(OLEPictureImpl *This, IWICBitmapSource *src) +{ + HRESULT hr; + BITMAPINFOHEADER bih; + HDC hdcref; + UINT width, height; + UINT stride, buffersize; + LPBYTE bits=NULL; + WICRect rc; + IWICBitmapSource *real_source; + UINT x, y; + COLORREF white = RGB(255, 255, 255), black = RGB(0, 0, 0); + BOOL has_alpha=FALSE; + + hr = WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA, src, &real_source); + if (FAILED(hr)) return hr; + + hr = IWICBitmapSource_GetSize(real_source, &width, &height); + if (FAILED(hr)) goto end; + + bih.biSize = sizeof(bih); + bih.biWidth = width; + bih.biHeight = -height; + bih.biPlanes = 1; + bih.biBitCount = 32; + bih.biCompression = BI_RGB; + bih.biSizeImage = 0; + bih.biXPelsPerMeter = 4085; /* olepicture ignores the stored resolution */ + bih.biYPelsPerMeter = 4085; + bih.biClrUsed = 0; + bih.biClrImportant = 0; + + stride = 4 * width; + buffersize = stride * height; + + bits = HeapAlloc(GetProcessHeap(), 0, buffersize); + if (!bits) + { + hr = E_OUTOFMEMORY; + goto end; + } + + rc.X = 0; + rc.Y = 0; + rc.Width = width; + rc.Height = height; + hr = IWICBitmapSource_CopyPixels(real_source, &rc, stride, buffersize, bits); + if (FAILED(hr)) + goto end; + + hdcref = GetDC(0); + This->desc.u.bmp.hbitmap = CreateDIBitmap( + hdcref, + &bih, + CBM_INIT, + bits, + (BITMAPINFO*)&bih, + DIB_RGB_COLORS); + + if (This->desc.u.bmp.hbitmap == 0) + { + hr = E_FAIL; + ReleaseDC(0, hdcref); + goto end; + } + + This->desc.picType = PICTYPE_BITMAP; + OLEPictureImpl_SetBitmap(This); + + /* set transparent pixels to black, all others to white */ + for(y = 0; y < height; y++){ + for(x = 0; x < width; x++){ + DWORD *pixel = (DWORD*)(bits + stride*y + 4*x); + if((*pixel & 0x80000000) == 0) + { + has_alpha = TRUE; + *pixel = black; + } + else + *pixel = white; + } + } + + if (has_alpha) + { + HDC hdcBmp, hdcXor, hdcMask; + HBITMAP hbmoldBmp, hbmoldXor, hbmoldMask; + + This->hbmXor = CreateDIBitmap( + hdcref, + &bih, + CBM_INIT, + bits, + (BITMAPINFO*)&bih, + DIB_RGB_COLORS + ); + + This->hbmMask = CreateBitmap(width,-height,1,1,NULL); + hdcBmp = CreateCompatibleDC(NULL); + hdcXor = CreateCompatibleDC(NULL); + hdcMask = CreateCompatibleDC(NULL); + + hbmoldBmp = SelectObject(hdcBmp,This->desc.u.bmp.hbitmap); + hbmoldXor = SelectObject(hdcXor,This->hbmXor); + hbmoldMask = SelectObject(hdcMask,This->hbmMask); + + SetBkColor(hdcXor,black); + BitBlt(hdcMask,0,0,width,height,hdcXor,0,0,SRCCOPY); + BitBlt(hdcXor,0,0,width,height,hdcBmp,0,0,SRCAND); + + SelectObject(hdcBmp,hbmoldBmp); + SelectObject(hdcXor,hbmoldXor); + SelectObject(hdcMask,hbmoldMask); + + DeleteDC(hdcBmp); + DeleteDC(hdcXor); + DeleteDC(hdcMask); + } + + ReleaseDC(0, hdcref); + +end: + HeapFree(GetProcessHeap(), 0, bits); + IWICBitmapSource_Release(real_source); + return hr; +} + +static HRESULT OLEPictureImpl_LoadWICDecoder(OLEPictureImpl *This, REFCLSID decoder_clsid, BYTE *xbuf, ULONG xread) +{ + HRESULT hr; + IWICBitmapDecoder *decoder; + IWICBitmapFrameDecode *framedecode; + HRESULT initresult; + HGLOBAL hdata; + BYTE *data; + IStream *stream; + + hdata = GlobalAlloc(GMEM_MOVEABLE, xread); + if (!hdata) return E_OUTOFMEMORY; + + data = GlobalLock(hdata); + memcpy(data, xbuf, xread); + GlobalUnlock(hdata); + + hr = CreateStreamOnHGlobal(hdata, TRUE, &stream); + if (FAILED(hr)) + { + GlobalFree(hdata); + return hr; + } + + initresult = CoInitialize(NULL); + + hr = CoCreateInstance(decoder_clsid, NULL, CLSCTX_INPROC_SERVER, + &IID_IWICBitmapDecoder, (void**)&decoder); + if (FAILED(hr)) goto end; + + hr = IWICBitmapDecoder_Initialize(decoder, stream, WICDecodeMetadataCacheOnLoad); + if (SUCCEEDED(hr)) + { + hr = IWICBitmapDecoder_GetFrame(decoder, 0, &framedecode); + if (SUCCEEDED(hr)) + { + hr = OLEPictureImpl_LoadWICSource(This, (IWICBitmapSource*)framedecode); + IWICBitmapFrameDecode_Release(framedecode); + } + } + + IWICBitmapDecoder_Release(decoder); + +end: + IStream_Release(stream); + if (SUCCEEDED(initresult)) CoUninitialize(); + return hr; +} + /***************************************************** * start of PNG-specific code * currently only supports colortype PNG_COLOR_TYPE_RGB @@ -1925,7 +1886,7 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { switch (magic) { case BITMAP_FORMAT_GIF: /* GIF */ - hr = OLEPictureImpl_LoadGif(This, xbuf, xread); + hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICGifDecoder, xbuf, xread); break; case BITMAP_FORMAT_JPEG: /* JPEG */ hr = OLEPictureImpl_LoadJpeg(This, xbuf, xread); diff --git a/dlls/oleaut32/regsvr.c b/dlls/oleaut32/regsvr.c index 9ee36b5..3c5fabc 100644 --- a/dlls/oleaut32/regsvr.c +++ b/dlls/oleaut32/regsvr.c @@ -32,6 +32,7 @@ #include "oleauto.h" #include "initguid.h" #include "typelib.h" +#include "wincodec.h" #include "wine/debug.h" #include "wine/unicode.h" diff --git a/dlls/oleaut32/ungif.c b/dlls/oleaut32/ungif.c deleted file mode 100644 index c24f387..0000000 --- a/dlls/oleaut32/ungif.c +++ /dev/null @@ -1,999 +0,0 @@ -/* - * Gif extracting routines - derived from libungif - * - * Portions Copyright 2006 Mike McCormack - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -/* - * Original copyright notice: - * - * The GIFLIB distribution is Copyright (c) 1997 Eric S. Raymond - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - */ - - -/****************************************************************************** - * "Gif-Lib" - Yet another gif library. - * - * Written by: Gershon Elber IBM PC Ver 1.1, Aug. 1990 - ****************************************************************************** - * The kernel of the GIF Decoding process can be found here. - ****************************************************************************** - * History: - * 16 Jun 89 - Version 1.0 by Gershon Elber. - * 3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names). - *****************************************************************************/ - -#include -#include -#include "ungif.h" - -#include -#include "windef.h" -#include "winbase.h" - -static void *ungif_alloc( size_t sz ) -{ - return HeapAlloc( GetProcessHeap(), 0, sz ); -} - -static void *ungif_calloc( size_t num, size_t sz ) -{ - return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, num*sz ); -} - -static void *ungif_realloc( void *ptr, size_t sz ) -{ - return HeapReAlloc( GetProcessHeap(), 0, ptr, sz ); -} - -static void ungif_free( void *ptr ) -{ - HeapFree( GetProcessHeap(), 0, ptr ); -} - -#define LZ_MAX_CODE 4095 /* Biggest code possible in 12 bits. */ -#define LZ_BITS 12 - -#define NO_SUCH_CODE 4098 /* Impossible code, to signal empty. */ - -typedef struct GifFilePrivateType { - GifWord BitsPerPixel, /* Bits per pixel (Codes uses at least this + 1). */ - ClearCode, /* The CLEAR LZ code. */ - EOFCode, /* The EOF LZ code. */ - RunningCode, /* The next code algorithm can generate. */ - RunningBits, /* The number of bits required to represent RunningCode. */ - MaxCode1, /* 1 bigger than max. possible code, in RunningBits bits. */ - LastCode, /* The code before the current code. */ - CrntCode, /* Current algorithm code. */ - StackPtr, /* For character stack (see below). */ - CrntShiftState; /* Number of bits in CrntShiftDWord. */ - unsigned long CrntShiftDWord; /* For bytes decomposition into codes. */ - unsigned long PixelCount; /* Number of pixels in image. */ - InputFunc Read; /* function to read gif input (TVT) */ - GifByteType Buf[256]; /* Compressed input is buffered here. */ - GifByteType Stack[LZ_MAX_CODE]; /* Decoded pixels are stacked here. */ - GifByteType Suffix[LZ_MAX_CODE + 1]; /* So we can trace the codes. */ - GifPrefixType Prefix[LZ_MAX_CODE + 1]; -} GifFilePrivateType; - -/* avoid extra function call in case we use fread (TVT) */ -#define READ(_gif,_buf,_len) \ - ((GifFilePrivateType*)_gif->Private)->Read(_gif,_buf,_len) - -static int DGifGetWord(GifFileType *GifFile, GifWord *Word); -static int DGifSetupDecompress(GifFileType *GifFile); -static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen); -static int DGifGetPrefixChar(const GifPrefixType *Prefix, int Code, int ClearCode); -static int DGifDecompressInput(GifFileType *GifFile, int *Code); -static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, - GifByteType *NextByte); - -static int DGifGetExtensionNext(GifFileType * GifFile, GifByteType ** GifExtension); -static int DGifGetCodeNext(GifFileType * GifFile, GifByteType ** GifCodeBlock); - -/****************************************************************************** - * Miscellaneous utility functions - *****************************************************************************/ - -/* return smallest bitfield size n will fit in */ -static int -BitSize(int n) { - - register int i; - - for (i = 1; i <= 8; i++) - if ((1 << i) >= n) - break; - return (i); -} - -/****************************************************************************** - * Color map object functions - *****************************************************************************/ - -/* - * Allocate a color map of given size; initialize with contents of - * ColorMap if that pointer is non-NULL. - */ -static ColorMapObject * -MakeMapObject(int ColorCount, - const GifColorType * ColorMap) { - - ColorMapObject *Object; - - /*** FIXME: Our ColorCount has to be a power of two. Is it necessary to - * make the user know that or should we automatically round up instead? */ - if (ColorCount != (1 << BitSize(ColorCount))) { - return NULL; - } - - Object = ungif_alloc(sizeof(ColorMapObject)); - if (Object == NULL) { - return NULL; - } - - Object->Colors = ungif_calloc(ColorCount, sizeof(GifColorType)); - if (Object->Colors == NULL) { - return NULL; - } - - Object->ColorCount = ColorCount; - Object->BitsPerPixel = BitSize(ColorCount); - - if (ColorMap) { - memcpy(Object->Colors, ColorMap, ColorCount * sizeof(GifColorType)); - } - - return (Object); -} - -/* - * Free a color map object - */ -static void -FreeMapObject(ColorMapObject * Object) { - - if (Object != NULL) { - ungif_free(Object->Colors); - ungif_free(Object); - /*** FIXME: - * When we are willing to break API we need to make this function - * FreeMapObject(ColorMapObject **Object) - * and do this assignment to NULL here: - * *Object = NULL; - */ - } -} - -static int -AddExtensionBlock(SavedImage * New, - int Len, - const unsigned char ExtData[]) { - - ExtensionBlock *ep; - - if (New->ExtensionBlocks == NULL) - New->ExtensionBlocks = ungif_alloc(sizeof(ExtensionBlock)); - else - New->ExtensionBlocks = ungif_realloc(New->ExtensionBlocks, - sizeof(ExtensionBlock) * - (New->ExtensionBlockCount + 1)); - - if (New->ExtensionBlocks == NULL) - return (GIF_ERROR); - - ep = &New->ExtensionBlocks[New->ExtensionBlockCount++]; - - ep->ByteCount=Len; - ep->Bytes = ungif_alloc(ep->ByteCount); - if (ep->Bytes == NULL) - return (GIF_ERROR); - - if (ExtData) { - memcpy(ep->Bytes, ExtData, Len); - ep->Function = New->Function; - } - - return (GIF_OK); -} - -static void -FreeExtension(SavedImage * Image) -{ - ExtensionBlock *ep; - - if ((Image == NULL) || (Image->ExtensionBlocks == NULL)) { - return; - } - for (ep = Image->ExtensionBlocks; - ep < (Image->ExtensionBlocks + Image->ExtensionBlockCount); ep++) - ungif_free(ep->Bytes); - ungif_free(Image->ExtensionBlocks); - Image->ExtensionBlocks = NULL; -} - -/****************************************************************************** - * Image block allocation functions -******************************************************************************/ - -static void -FreeSavedImages(GifFileType * GifFile) { - - SavedImage *sp; - - if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) { - return; - } - for (sp = GifFile->SavedImages; - sp < GifFile->SavedImages + GifFile->ImageCount; sp++) { - if (sp->ImageDesc.ColorMap) { - FreeMapObject(sp->ImageDesc.ColorMap); - sp->ImageDesc.ColorMap = NULL; - } - - ungif_free(sp->RasterBits); - - if (sp->ExtensionBlocks) - FreeExtension(sp); - } - ungif_free(GifFile->SavedImages); - GifFile->SavedImages=NULL; -} - -/****************************************************************************** - * This routine should be called before any other DGif calls. Note that - * this routine is called automatically from DGif file open routines. - *****************************************************************************/ -static int -DGifGetScreenDesc(GifFileType * GifFile) { - - int i, BitsPerPixel; - GifByteType Buf[3]; - - /* Put the screen descriptor into the file: */ - if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR || - DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR) - return GIF_ERROR; - - if (READ(GifFile, Buf, 3) != 3) { - return GIF_ERROR; - } - GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1; - BitsPerPixel = (Buf[0] & 0x07) + 1; - GifFile->SBackGroundColor = Buf[1]; - if (Buf[0] & 0x80) { /* Do we have global color map? */ - - GifFile->SColorMap = MakeMapObject(1 << BitsPerPixel, NULL); - if (GifFile->SColorMap == NULL) { - return GIF_ERROR; - } - - /* Get the global color map: */ - for (i = 0; i < GifFile->SColorMap->ColorCount; i++) { - if (READ(GifFile, Buf, 3) != 3) { - FreeMapObject(GifFile->SColorMap); - GifFile->SColorMap = NULL; - return GIF_ERROR; - } - GifFile->SColorMap->Colors[i].Red = Buf[0]; - GifFile->SColorMap->Colors[i].Green = Buf[1]; - GifFile->SColorMap->Colors[i].Blue = Buf[2]; - } - } else { - GifFile->SColorMap = NULL; - } - - return GIF_OK; -} - -/****************************************************************************** - * This routine should be called before any attempt to read an image. - *****************************************************************************/ -static int -DGifGetRecordType(GifFileType * GifFile, - GifRecordType * Type) { - - GifByteType Buf; - - if (READ(GifFile, &Buf, 1) != 1) { - return GIF_ERROR; - } - - switch (Buf) { - case ',': - *Type = IMAGE_DESC_RECORD_TYPE; - break; - case '!': - *Type = EXTENSION_RECORD_TYPE; - break; - case ';': - *Type = TERMINATE_RECORD_TYPE; - break; - default: - *Type = UNDEFINED_RECORD_TYPE; - return GIF_ERROR; - } - - return GIF_OK; -} - -/****************************************************************************** - * This routine should be called before any attempt to read an image. - * Note it is assumed the Image desc. header (',') has been read. - *****************************************************************************/ -static int -DGifGetImageDesc(GifFileType * GifFile) { - - int i, BitsPerPixel; - GifByteType Buf[3]; - GifFilePrivateType *Private = GifFile->Private; - SavedImage *sp; - - if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR || - DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR || - DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR || - DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR) - return GIF_ERROR; - if (READ(GifFile, Buf, 1) != 1) { - return GIF_ERROR; - } - BitsPerPixel = (Buf[0] & 0x07) + 1; - GifFile->Image.Interlace = (Buf[0] & 0x40); - if (Buf[0] & 0x80) { /* Does this image have local color map? */ - - /*** FIXME: Why do we check both of these in order to do this? - * Why do we have both Image and SavedImages? */ - if (GifFile->Image.ColorMap && GifFile->SavedImages == NULL) - FreeMapObject(GifFile->Image.ColorMap); - - GifFile->Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL); - if (GifFile->Image.ColorMap == NULL) { - return GIF_ERROR; - } - - /* Get the image local color map: */ - for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) { - if (READ(GifFile, Buf, 3) != 3) { - FreeMapObject(GifFile->Image.ColorMap); - GifFile->Image.ColorMap = NULL; - return GIF_ERROR; - } - GifFile->Image.ColorMap->Colors[i].Red = Buf[0]; - GifFile->Image.ColorMap->Colors[i].Green = Buf[1]; - GifFile->Image.ColorMap->Colors[i].Blue = Buf[2]; - } - } else if (GifFile->Image.ColorMap) { - FreeMapObject(GifFile->Image.ColorMap); - GifFile->Image.ColorMap = NULL; - } - - if (GifFile->SavedImages) { - if ((GifFile->SavedImages = ungif_realloc(GifFile->SavedImages, - sizeof(SavedImage) * - (GifFile->ImageCount + 1))) == NULL) { - return GIF_ERROR; - } - } else { - if ((GifFile->SavedImages = ungif_alloc(sizeof(SavedImage))) == NULL) { - return GIF_ERROR; - } - } - - sp = &GifFile->SavedImages[GifFile->ImageCount]; - sp->ImageDesc = GifFile->Image; - if (GifFile->Image.ColorMap != NULL) { - sp->ImageDesc.ColorMap = MakeMapObject( - GifFile->Image.ColorMap->ColorCount, - GifFile->Image.ColorMap->Colors); - if (sp->ImageDesc.ColorMap == NULL) { - return GIF_ERROR; - } - } - sp->RasterBits = NULL; - sp->ExtensionBlockCount = 0; - sp->ExtensionBlocks = NULL; - - GifFile->ImageCount++; - - Private->PixelCount = (long)GifFile->Image.Width * - (long)GifFile->Image.Height; - - DGifSetupDecompress(GifFile); /* Reset decompress algorithm parameters. */ - - return GIF_OK; -} - -/****************************************************************************** - * Get one full scanned line (Line) of length LineLen from GIF file. - *****************************************************************************/ -static int -DGifGetLine(GifFileType * GifFile, - GifPixelType * Line, - int LineLen) { - - GifByteType *Dummy; - GifFilePrivateType *Private = GifFile->Private; - - if (!LineLen) - LineLen = GifFile->Image.Width; - - if ((Private->PixelCount -= LineLen) > 0xffff0000UL) { - return GIF_ERROR; - } - - if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) { - if (Private->PixelCount == 0) { - /* We probably would not be called any more, so lets clean - * everything before we return: need to flush out all rest of - * image until empty block (size 0) detected. We use GetCodeNext. */ - do - if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR) - return GIF_ERROR; - while (Dummy != NULL) ; - } - return GIF_OK; - } else - return GIF_ERROR; -} - -/****************************************************************************** - * Get an extension block (see GIF manual) from gif file. This routine only - * returns the first data block, and DGifGetExtensionNext should be called - * after this one until NULL extension is returned. - * The Extension should NOT be freed by the user (not dynamically allocated). - * Note it is assumed the Extension desc. header ('!') has been read. - *****************************************************************************/ -static int -DGifGetExtension(GifFileType * GifFile, - int *ExtCode, - GifByteType ** Extension) { - - GifByteType Buf; - - if (READ(GifFile, &Buf, 1) != 1) { - return GIF_ERROR; - } - *ExtCode = Buf; - - return DGifGetExtensionNext(GifFile, Extension); -} - -/****************************************************************************** - * Get a following extension block (see GIF manual) from gif file. This - * routine should be called until NULL Extension is returned. - * The Extension should NOT be freed by the user (not dynamically allocated). - *****************************************************************************/ -static int -DGifGetExtensionNext(GifFileType * GifFile, - GifByteType ** Extension) { - - GifByteType Buf; - GifFilePrivateType *Private = GifFile->Private; - - if (READ(GifFile, &Buf, 1) != 1) { - return GIF_ERROR; - } - if (Buf > 0) { - *Extension = Private->Buf; /* Use private unused buffer. */ - (*Extension)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */ - if (READ(GifFile, &((*Extension)[1]), Buf) != Buf) { - return GIF_ERROR; - } - } else - *Extension = NULL; - - return GIF_OK; -} - -/****************************************************************************** - * Get 2 bytes (word) from the given file: - *****************************************************************************/ -static int -DGifGetWord(GifFileType * GifFile, - GifWord *Word) { - - unsigned char c[2]; - - if (READ(GifFile, c, 2) != 2) { - return GIF_ERROR; - } - - *Word = (((unsigned int)c[1]) << 8) + c[0]; - return GIF_OK; -} - -/****************************************************************************** - * Continue to get the image code in compressed form. This routine should be - * called until NULL block is returned. - * The block should NOT be freed by the user (not dynamically allocated). - *****************************************************************************/ -static int -DGifGetCodeNext(GifFileType * GifFile, - GifByteType ** CodeBlock) { - - GifByteType Buf; - GifFilePrivateType *Private = GifFile->Private; - - if (READ(GifFile, &Buf, 1) != 1) { - return GIF_ERROR; - } - - if (Buf > 0) { - *CodeBlock = Private->Buf; /* Use private unused buffer. */ - (*CodeBlock)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */ - if (READ(GifFile, &((*CodeBlock)[1]), Buf) != Buf) { - return GIF_ERROR; - } - } else { - *CodeBlock = NULL; - Private->Buf[0] = 0; /* Make sure the buffer is empty! */ - Private->PixelCount = 0; /* And local info. indicate image read. */ - } - - return GIF_OK; -} - -/****************************************************************************** - * Setup the LZ decompression for this image: - *****************************************************************************/ -static int -DGifSetupDecompress(GifFileType * GifFile) { - - int i, BitsPerPixel; - GifByteType CodeSize; - GifPrefixType *Prefix; - GifFilePrivateType *Private = GifFile->Private; - - READ(GifFile, &CodeSize, 1); /* Read Code size from file. */ - BitsPerPixel = CodeSize; - - Private->Buf[0] = 0; /* Input Buffer empty. */ - Private->BitsPerPixel = BitsPerPixel; - Private->ClearCode = (1 << BitsPerPixel); - Private->EOFCode = Private->ClearCode + 1; - Private->RunningCode = Private->EOFCode + 1; - Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */ - Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */ - Private->StackPtr = 0; /* No pixels on the pixel stack. */ - Private->LastCode = NO_SUCH_CODE; - Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */ - Private->CrntShiftDWord = 0; - - Prefix = Private->Prefix; - for (i = 0; i <= LZ_MAX_CODE; i++) - Prefix[i] = NO_SUCH_CODE; - - return GIF_OK; -} - -/****************************************************************************** - * The LZ decompression routine: - * This version decompress the given gif file into Line of length LineLen. - * This routine can be called few times (one per scan line, for example), in - * order the complete the whole image. - *****************************************************************************/ -static int -DGifDecompressLine(GifFileType * GifFile, - GifPixelType * Line, - int LineLen) { - - int i = 0; - int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr; - GifByteType *Stack, *Suffix; - GifPrefixType *Prefix; - GifFilePrivateType *Private = GifFile->Private; - - StackPtr = Private->StackPtr; - Prefix = Private->Prefix; - Suffix = Private->Suffix; - Stack = Private->Stack; - EOFCode = Private->EOFCode; - ClearCode = Private->ClearCode; - LastCode = Private->LastCode; - - if (StackPtr != 0) { - /* Let pop the stack off before continuing to read the gif file: */ - while (StackPtr != 0 && i < LineLen) - Line[i++] = Stack[--StackPtr]; - } - - while (i < LineLen) { /* Decode LineLen items. */ - if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR) - return GIF_ERROR; - - if (CrntCode == EOFCode) { - /* Note, however, that usually we will not be here as we will stop - * decoding as soon as we got all the pixel, or EOF code will - * not be read at all, and DGifGetLine/Pixel clean everything. */ - if (i != LineLen - 1 || Private->PixelCount != 0) { - return GIF_ERROR; - } - i++; - } else if (CrntCode == ClearCode) { - /* We need to start over again: */ - for (j = 0; j <= LZ_MAX_CODE; j++) - Prefix[j] = NO_SUCH_CODE; - Private->RunningCode = Private->EOFCode + 1; - Private->RunningBits = Private->BitsPerPixel + 1; - Private->MaxCode1 = 1 << Private->RunningBits; - LastCode = Private->LastCode = NO_SUCH_CODE; - } else { - /* It's a regular code - if in pixel range simply add it to output - * stream, otherwise trace to codes linked list until the prefix - * is in pixel range: */ - if (CrntCode < ClearCode) { - /* This is simple - its pixel scalar, so add it to output: */ - Line[i++] = CrntCode; - } else { - /* It's a code to be traced: trace the linked list - * until the prefix is a pixel, while pushing the suffix - * pixels on our stack. If we done, pop the stack in reverse - * order (that's what stack is good for!) for output. */ - if (Prefix[CrntCode] == NO_SUCH_CODE) { - /* Only allowed if CrntCode is exactly the running code: - * In that case CrntCode = XXXCode, CrntCode or the - * prefix code is last code and the suffix char is - * exactly the prefix of last code! */ - if (CrntCode == Private->RunningCode - 2) { - CrntPrefix = LastCode; - Suffix[Private->RunningCode - 2] = - Stack[StackPtr++] = DGifGetPrefixChar(Prefix, - LastCode, - ClearCode); - } else { - return GIF_ERROR; - } - } else - CrntPrefix = CrntCode; - - /* Now (if image is O.K.) we should not get a NO_SUCH_CODE - * during the trace. As we might loop forever, in case of - * defective image, we count the number of loops we trace - * and stop if we got LZ_MAX_CODE. Obviously we cannot - * loop more than that. */ - j = 0; - while (j++ <= LZ_MAX_CODE && - CrntPrefix > ClearCode && CrntPrefix <= LZ_MAX_CODE) { - Stack[StackPtr++] = Suffix[CrntPrefix]; - CrntPrefix = Prefix[CrntPrefix]; - } - if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) { - return GIF_ERROR; - } - /* Push the last character on stack: */ - Stack[StackPtr++] = CrntPrefix; - - /* Now lets pop all the stack into output: */ - while (StackPtr != 0 && i < LineLen) - Line[i++] = Stack[--StackPtr]; - } - if (LastCode != NO_SUCH_CODE) { - Prefix[Private->RunningCode - 2] = LastCode; - - if (CrntCode == Private->RunningCode - 2) { - /* Only allowed if CrntCode is exactly the running code: - * In that case CrntCode = XXXCode, CrntCode or the - * prefix code is last code and the suffix char is - * exactly the prefix of last code! */ - Suffix[Private->RunningCode - 2] = - DGifGetPrefixChar(Prefix, LastCode, ClearCode); - } else { - Suffix[Private->RunningCode - 2] = - DGifGetPrefixChar(Prefix, CrntCode, ClearCode); - } - } - LastCode = CrntCode; - } - } - - Private->LastCode = LastCode; - Private->StackPtr = StackPtr; - - return GIF_OK; -} - -/****************************************************************************** - * Routine to trace the Prefixes linked list until we get a prefix which is - * not code, but a pixel value (less than ClearCode). Returns that pixel value. - * If image is defective, we might loop here forever, so we limit the loops to - * the maximum possible if image O.k. - LZ_MAX_CODE times. - *****************************************************************************/ -static int -DGifGetPrefixChar(const GifPrefixType *Prefix, - int Code, - int ClearCode) { - - int i = 0; - - while (Code > ClearCode && i++ <= LZ_MAX_CODE) - Code = Prefix[Code]; - return Code; -} - -/****************************************************************************** - * The LZ decompression input routine: - * This routine is responsible for the decompression of the bit stream from - * 8 bits (bytes) packets, into the real codes. - * Returns GIF_OK if read successfully. - *****************************************************************************/ -static int -DGifDecompressInput(GifFileType * GifFile, - int *Code) { - - GifFilePrivateType *Private = GifFile->Private; - - GifByteType NextByte; - static const unsigned short CodeMasks[] = { - 0x0000, 0x0001, 0x0003, 0x0007, - 0x000f, 0x001f, 0x003f, 0x007f, - 0x00ff, 0x01ff, 0x03ff, 0x07ff, - 0x0fff - }; - /* The image can't contain more than LZ_BITS per code. */ - if (Private->RunningBits > LZ_BITS) { - return GIF_ERROR; - } - - while (Private->CrntShiftState < Private->RunningBits) { - /* Needs to get more bytes from input stream for next code: */ - if (DGifBufferedInput(GifFile, Private->Buf, &NextByte) == GIF_ERROR) { - return GIF_ERROR; - } - Private->CrntShiftDWord |= - ((unsigned long)NextByte) << Private->CrntShiftState; - Private->CrntShiftState += 8; - } - *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits]; - - Private->CrntShiftDWord >>= Private->RunningBits; - Private->CrntShiftState -= Private->RunningBits; - - /* If code cannot fit into RunningBits bits, must raise its size. Note - * however that codes above 4095 are used for special signaling. - * If we're using LZ_BITS bits already and we're at the max code, just - * keep using the table as it is, don't increment Private->RunningCode. - */ - if (Private->RunningCode < LZ_MAX_CODE + 2 && - ++Private->RunningCode > Private->MaxCode1 && - Private->RunningBits < LZ_BITS) { - Private->MaxCode1 <<= 1; - Private->RunningBits++; - } - return GIF_OK; -} - -/****************************************************************************** - * This routines read one gif data block at a time and buffers it internally - * so that the decompression routine could access it. - * The routine returns the next byte from its internal buffer (or read next - * block in if buffer empty) and returns GIF_OK if successful. - *****************************************************************************/ -static int -DGifBufferedInput(GifFileType * GifFile, - GifByteType * Buf, - GifByteType * NextByte) { - - if (Buf[0] == 0) { - /* Needs to read the next buffer - this one is empty: */ - if (READ(GifFile, Buf, 1) != 1) { - return GIF_ERROR; - } - /* There shouldn't be any empty data blocks here as the LZW spec - * says the LZW termination code should come first. Therefore we - * shouldn't be inside this routine at that point. - */ - if (Buf[0] == 0) { - return GIF_ERROR; - } - if (READ(GifFile, &Buf[1], Buf[0]) != Buf[0]) { - return GIF_ERROR; - } - *NextByte = Buf[1]; - Buf[1] = 2; /* We use now the second place as last char read! */ - Buf[0]--; - } else { - *NextByte = Buf[Buf[1]++]; - Buf[0]--; - } - - return GIF_OK; -} - -/****************************************************************************** - * This routine reads an entire GIF into core, hanging all its state info off - * the GifFileType pointer. Call DGifOpenFileName() or DGifOpenFileHandle() - * first to initialize I/O. Its inverse is EGifSpew(). - ******************************************************************************/ -int -DGifSlurp(GifFileType * GifFile) { - - int ImageSize; - GifRecordType RecordType; - SavedImage *sp; - GifByteType *ExtData; - SavedImage temp_save; - - temp_save.ExtensionBlocks = NULL; - temp_save.ExtensionBlockCount = 0; - - do { - if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) - return (GIF_ERROR); - - switch (RecordType) { - case IMAGE_DESC_RECORD_TYPE: - if (DGifGetImageDesc(GifFile) == GIF_ERROR) - return (GIF_ERROR); - - sp = &GifFile->SavedImages[GifFile->ImageCount - 1]; - ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height; - - sp->RasterBits = ungif_alloc(ImageSize * sizeof(GifPixelType)); - if (sp->RasterBits == NULL) { - return GIF_ERROR; - } - if (DGifGetLine(GifFile, sp->RasterBits, ImageSize) == - GIF_ERROR) - return (GIF_ERROR); - if (temp_save.ExtensionBlocks) { - sp->ExtensionBlocks = temp_save.ExtensionBlocks; - sp->ExtensionBlockCount = temp_save.ExtensionBlockCount; - - temp_save.ExtensionBlocks = NULL; - temp_save.ExtensionBlockCount = 0; - - /* FIXME: The following is wrong. It is left in only for - * backwards compatibility. Someday it should go away. Use - * the sp->ExtensionBlocks->Function variable instead. */ - sp->Function = sp->ExtensionBlocks[0].Function; - } - break; - - case EXTENSION_RECORD_TYPE: - if (DGifGetExtension(GifFile, &temp_save.Function, &ExtData) == - GIF_ERROR) - return (GIF_ERROR); - while (ExtData != NULL) { - - /* Create an extension block with our data */ - if (AddExtensionBlock(&temp_save, ExtData[0], &ExtData[1]) - == GIF_ERROR) - return (GIF_ERROR); - - if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR) - return (GIF_ERROR); - temp_save.Function = 0; - } - break; - - case TERMINATE_RECORD_TYPE: - break; - - default: /* Should be trapped by DGifGetRecordType */ - break; - } - } while (RecordType != TERMINATE_RECORD_TYPE); - - /* Just in case the Gif has an extension block without an associated - * image... (Should we save this into a savefile structure with no image - * instead? Have to check if the present writing code can handle that as - * well.... */ - if (temp_save.ExtensionBlocks) - FreeExtension(&temp_save); - - return (GIF_OK); -} - -/****************************************************************************** - * GifFileType constructor with user supplied input function (TVT) - *****************************************************************************/ -GifFileType * -DGifOpen(void *userData, - InputFunc readFunc) { - - unsigned char Buf[GIF_STAMP_LEN + 1]; - GifFileType *GifFile; - GifFilePrivateType *Private; - - GifFile = ungif_alloc(sizeof(GifFileType)); - if (GifFile == NULL) { - return NULL; - } - - memset(GifFile, '\0', sizeof(GifFileType)); - - Private = ungif_alloc(sizeof(GifFilePrivateType)); - if (!Private) { - ungif_free(GifFile); - return NULL; - } - - GifFile->Private = (void*)Private; - - Private->Read = readFunc; /* TVT */ - GifFile->UserData = userData; /* TVT */ - - /* Lets see if this is a GIF file: */ - if (READ(GifFile, Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) { - ungif_free(Private); - ungif_free(GifFile); - return NULL; - } - - /* The GIF Version number is ignored at this time. Maybe we should do - * something more useful with it. */ - Buf[GIF_STAMP_LEN] = 0; - if (memcmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) { - ungif_free(Private); - ungif_free(GifFile); - return NULL; - } - - if (DGifGetScreenDesc(GifFile) == GIF_ERROR) { - ungif_free(Private); - ungif_free(GifFile); - return NULL; - } - - return GifFile; -} - -/****************************************************************************** - * This routine should be called last, to close the GIF file. - *****************************************************************************/ -int -DGifCloseFile(GifFileType * GifFile) { - - GifFilePrivateType *Private; - - if (GifFile == NULL) - return GIF_ERROR; - - Private = GifFile->Private; - - if (GifFile->Image.ColorMap) { - FreeMapObject(GifFile->Image.ColorMap); - GifFile->Image.ColorMap = NULL; - } - - if (GifFile->SColorMap) { - FreeMapObject(GifFile->SColorMap); - GifFile->SColorMap = NULL; - } - - ungif_free(Private); - Private = NULL; - - if (GifFile->SavedImages) { - FreeSavedImages(GifFile); - GifFile->SavedImages = NULL; - } - - ungif_free(GifFile); - - return GIF_OK; -} diff --git a/dlls/oleaut32/ungif.h b/dlls/oleaut32/ungif.h deleted file mode 100644 index e71dad8..0000000 --- a/dlls/oleaut32/ungif.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Gif extracting routines - derived from libungif - * - * Portions Copyright 2006 Mike McCormack - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -/* - * Original copyright notice: - * - * The GIFLIB distribution is Copyright (c) 1997 Eric S. Raymond - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - */ - -/****************************************************************************** - * In order to make life a little bit easier when using the GIF file format, - * this library was written, and which does all the dirty work... - * - * Written by Gershon Elber, Jun. 1989 - * Hacks by Eric S. Raymond, Sep. 1992 - ****************************************************************************** - * History: - * 14 Jun 89 - Version 1.0 by Gershon Elber. - * 3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names) - * 15 Sep 90 - Version 2.0 by Eric S. Raymond (Changes to support GIF slurp) - * 26 Jun 96 - Version 3.0 by Eric S. Raymond (Full GIF89 support) - * 17 Dec 98 - Version 4.0 by Toshio Kuratomi (Fix extension writing code) - *****************************************************************************/ - -#ifndef _UNGIF_H_ -#define _UNGIF_H_ 1 - -#define GIF_ERROR 0 -#define GIF_OK 1 - -#ifndef TRUE -#define TRUE 1 -#endif /* TRUE */ -#ifndef FALSE -#define FALSE 0 -#endif /* FALSE */ - -#ifndef NULL -#define NULL 0 -#endif /* NULL */ - -#define GIF_STAMP "GIFVER" /* First chars in file - GIF stamp. */ -#define GIF_STAMP_LEN sizeof(GIF_STAMP) - 1 -#define GIF_VERSION_POS 3 /* Version first character in stamp. */ -#define GIF87_STAMP "GIF87a" /* First chars in file - GIF stamp. */ -#define GIF89_STAMP "GIF89a" /* First chars in file - GIF stamp. */ - -#define GIF_FILE_BUFFER_SIZE 16384 /* Files uses bigger buffers than usual. */ - -typedef int GifBooleanType; -typedef unsigned char GifPixelType; -typedef unsigned char *GifRowType; -typedef unsigned char GifByteType; -typedef unsigned int GifPrefixType; -typedef int GifWord; - -typedef struct GifColorType { - GifByteType Red, Green, Blue; -} GifColorType; - -typedef struct ColorMapObject { - int ColorCount; - int BitsPerPixel; - GifColorType *Colors; -} ColorMapObject; - -typedef struct GifImageDesc { - GifWord Left, Top, Width, Height, /* Current image dimensions. */ - Interlace; /* Sequential/Interlaced lines. */ - ColorMapObject *ColorMap; /* The local color map */ -} GifImageDesc; - -typedef struct GifFileType { - GifWord SWidth, SHeight, /* Screen dimensions. */ - SColorResolution, /* How many colors can we generate? */ - SBackGroundColor; /* I hope you understand this one... */ - ColorMapObject *SColorMap; /* NULL if not exists. */ - int ImageCount; /* Number of current image */ - GifImageDesc Image; /* Block describing current image */ - struct SavedImage *SavedImages; /* Use this to accumulate file state */ - void *UserData; /* hook to attach user data (TVT) */ - void *Private; /* Don't mess with this! */ -} GifFileType; - -typedef enum { - UNDEFINED_RECORD_TYPE, - SCREEN_DESC_RECORD_TYPE, - IMAGE_DESC_RECORD_TYPE, /* Begin with ',' */ - EXTENSION_RECORD_TYPE, /* Begin with '!' */ - TERMINATE_RECORD_TYPE /* Begin with ';' */ -} GifRecordType; - -/* func type to read gif data from arbitrary sources (TVT) */ -typedef int (*InputFunc) (GifFileType *, GifByteType *, int); - -/* GIF89 extension function codes */ - -#define COMMENT_EXT_FUNC_CODE 0xfe /* comment */ -#define GRAPHICS_EXT_FUNC_CODE 0xf9 /* graphics control */ -#define PLAINTEXT_EXT_FUNC_CODE 0x01 /* plaintext */ -#define APPLICATION_EXT_FUNC_CODE 0xff /* application block */ - -/* public interface to ungif.c */ -int DGifSlurp(GifFileType * GifFile); -GifFileType *DGifOpen(void *userPtr, InputFunc readFunc); -int DGifCloseFile(GifFileType * GifFile); - -#define D_GIF_ERR_OPEN_FAILED 101 /* And DGif possible errors. */ -#define D_GIF_ERR_READ_FAILED 102 -#define D_GIF_ERR_NOT_GIF_FILE 103 -#define D_GIF_ERR_NO_SCRN_DSCR 104 -#define D_GIF_ERR_NO_IMAG_DSCR 105 -#define D_GIF_ERR_NO_COLOR_MAP 106 -#define D_GIF_ERR_WRONG_RECORD 107 -#define D_GIF_ERR_DATA_TOO_BIG 108 -#define D_GIF_ERR_NOT_ENOUGH_MEM 109 -#define D_GIF_ERR_CLOSE_FAILED 110 -#define D_GIF_ERR_NOT_READABLE 111 -#define D_GIF_ERR_IMAGE_DEFECT 112 -#define D_GIF_ERR_EOF_TOO_SOON 113 - -/****************************************************************************** - * Support for the in-core structures allocation (slurp mode). - *****************************************************************************/ - -/* This is the in-core version of an extension record */ -typedef struct { - int ByteCount; - char *Bytes; - int Function; /* Holds the type of the Extension block. */ -} ExtensionBlock; - -/* This holds an image header, its unpacked raster bits, and extensions */ -typedef struct SavedImage { - GifImageDesc ImageDesc; - unsigned char *RasterBits; - int Function; /* DEPRECATED: Use ExtensionBlocks[x].Function instead */ - int ExtensionBlockCount; - ExtensionBlock *ExtensionBlocks; -} SavedImage; - -#endif /* _UNGIF_H_ */ -- 1.5.4.3