ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

gifformat.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 2009 Vincent Povirk for CodeWeavers
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00017  */
00018 
00019 #include "config.h"
00020 
00021 #include <stdarg.h>
00022 
00023 #define COBJMACROS
00024 
00025 #include "windef.h"
00026 #include "winbase.h"
00027 #include "objbase.h"
00028 #include "wincodec.h"
00029 
00030 #include "ungif.h"
00031 
00032 #include "wincodecs_private.h"
00033 
00034 #include "wine/debug.h"
00035 
00036 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
00037 
00038 typedef struct {
00039     const IWICBitmapDecoderVtbl *lpVtbl;
00040     LONG ref;
00041     BOOL initialized;
00042     GifFileType *gif;
00043     CRITICAL_SECTION lock;
00044 } GifDecoder;
00045 
00046 typedef struct {
00047     const IWICBitmapFrameDecodeVtbl *lpVtbl;
00048     LONG ref;
00049     SavedImage *frame;
00050     GifDecoder *parent;
00051 } GifFrameDecode;
00052 
00053 static HRESULT WINAPI GifFrameDecode_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid,
00054     void **ppv)
00055 {
00056     GifFrameDecode *This = (GifFrameDecode*)iface;
00057     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
00058 
00059     if (!ppv) return E_INVALIDARG;
00060 
00061     if (IsEqualIID(&IID_IUnknown, iid) ||
00062         IsEqualIID(&IID_IWICBitmapSource, iid) ||
00063         IsEqualIID(&IID_IWICBitmapFrameDecode, iid))
00064     {
00065         *ppv = This;
00066     }
00067     else
00068     {
00069         *ppv = NULL;
00070         return E_NOINTERFACE;
00071     }
00072 
00073     IUnknown_AddRef((IUnknown*)*ppv);
00074     return S_OK;
00075 }
00076 
00077 static ULONG WINAPI GifFrameDecode_AddRef(IWICBitmapFrameDecode *iface)
00078 {
00079     GifFrameDecode *This = (GifFrameDecode*)iface;
00080     ULONG ref = InterlockedIncrement(&This->ref);
00081 
00082     TRACE("(%p) refcount=%u\n", iface, ref);
00083 
00084     return ref;
00085 }
00086 
00087 static ULONG WINAPI GifFrameDecode_Release(IWICBitmapFrameDecode *iface)
00088 {
00089     GifFrameDecode *This = (GifFrameDecode*)iface;
00090     ULONG ref = InterlockedDecrement(&This->ref);
00091 
00092     TRACE("(%p) refcount=%u\n", iface, ref);
00093 
00094     if (ref == 0)
00095     {
00096         IUnknown_Release((IUnknown*)This->parent);
00097         HeapFree(GetProcessHeap(), 0, This);
00098     }
00099 
00100     return ref;
00101 }
00102 
00103 static HRESULT WINAPI GifFrameDecode_GetSize(IWICBitmapFrameDecode *iface,
00104     UINT *puiWidth, UINT *puiHeight)
00105 {
00106     GifFrameDecode *This = (GifFrameDecode*)iface;
00107     TRACE("(%p,%p,%p)\n", iface, puiWidth, puiHeight);
00108 
00109     *puiWidth = This->frame->ImageDesc.Width;
00110     *puiHeight = This->frame->ImageDesc.Height;
00111 
00112     return S_OK;
00113 }
00114 
00115 static HRESULT WINAPI GifFrameDecode_GetPixelFormat(IWICBitmapFrameDecode *iface,
00116     WICPixelFormatGUID *pPixelFormat)
00117 {
00118     memcpy(pPixelFormat, &GUID_WICPixelFormat8bppIndexed, sizeof(GUID));
00119 
00120     return S_OK;
00121 }
00122 
00123 static HRESULT WINAPI GifFrameDecode_GetResolution(IWICBitmapFrameDecode *iface,
00124     double *pDpiX, double *pDpiY)
00125 {
00126     FIXME("(%p,%p,%p): stub\n", iface, pDpiX, pDpiY);
00127     return E_NOTIMPL;
00128 }
00129 
00130 static HRESULT WINAPI GifFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface,
00131     IWICPalette *pIPalette)
00132 {
00133     GifFrameDecode *This = (GifFrameDecode*)iface;
00134     WICColor colors[256];
00135     ColorMapObject *cm = This->frame->ImageDesc.ColorMap;
00136     int i, trans;
00137     ExtensionBlock *eb;
00138     TRACE("(%p,%p)\n", iface, pIPalette);
00139 
00140     if (!cm) cm = This->parent->gif->SColorMap;
00141 
00142     if (cm->ColorCount > 256)
00143     {
00144         ERR("GIF contains %i colors???\n", cm->ColorCount);
00145         return E_FAIL;
00146     }
00147 
00148     for (i = 0; i < cm->ColorCount; i++) {
00149         colors[i] = 0xff000000| /* alpha */
00150                     cm->Colors[i].Red << 16|
00151                     cm->Colors[i].Green << 8|
00152                     cm->Colors[i].Blue;
00153     }
00154 
00155     /* look for the transparent color extension */
00156     for (i = 0; i < This->frame->ExtensionBlockCount; ++i) {
00157     eb = This->frame->ExtensionBlocks + i;
00158     if (eb->Function == 0xF9 && eb->ByteCount == 4) {
00159         if ((eb->Bytes[0] & 1) == 1) {
00160             trans = (unsigned char)eb->Bytes[3];
00161             colors[trans] &= 0xffffff; /* set alpha to 0 */
00162             break;
00163         }
00164     }
00165     }
00166 
00167     IWICPalette_InitializeCustom(pIPalette, colors, cm->ColorCount);
00168 
00169     return S_OK;
00170 }
00171 
00172 static HRESULT copy_interlaced_pixels(const BYTE *srcbuffer,
00173     UINT srcwidth, UINT srcheight, INT srcstride, const WICRect *rc,
00174     UINT dststride, UINT dstbuffersize, BYTE *dstbuffer)
00175 {
00176     UINT row_offset; /* number of bytes into the source rows where the data starts */
00177     const BYTE *src;
00178     BYTE *dst;
00179     UINT y;
00180 
00181     if (rc->X < 0 || rc->Y < 0 || rc->X+rc->Width > srcwidth || rc->Y+rc->Height > srcheight)
00182         return E_INVALIDARG;
00183 
00184     if (dststride < rc->Width)
00185         return E_INVALIDARG;
00186 
00187     if ((dststride * rc->Height) > dstbuffersize)
00188         return E_INVALIDARG;
00189 
00190     row_offset = rc->X;
00191 
00192     dst = dstbuffer;
00193     for (y=rc->Y; y-rc->Y < rc->Height; y++)
00194     {
00195         if (y%8 == 0)
00196             src = srcbuffer + srcstride * (y/8);
00197         else if (y%4 == 0)
00198             src = srcbuffer + srcstride * ((srcheight+7)/8 + y/8);
00199         else if (y%2 == 0)
00200             src = srcbuffer + srcstride * ((srcheight+3)/4 + y/4);
00201         else /* y%2 == 1 */
00202             src = srcbuffer + srcstride * ((srcheight+1)/2 + y/2);
00203         src += row_offset;
00204         memcpy(dst, src, rc->Width);
00205         dst += dststride;
00206     }
00207     return S_OK;
00208 }
00209 
00210 static HRESULT WINAPI GifFrameDecode_CopyPixels(IWICBitmapFrameDecode *iface,
00211     const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
00212 {
00213     GifFrameDecode *This = (GifFrameDecode*)iface;
00214     TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer);
00215 
00216     if (This->frame->ImageDesc.Interlace)
00217     {
00218         return copy_interlaced_pixels(This->frame->RasterBits, This->frame->ImageDesc.Width,
00219             This->frame->ImageDesc.Height, This->frame->ImageDesc.Width,
00220             prc, cbStride, cbBufferSize, pbBuffer);
00221     }
00222     else
00223     {
00224         return copy_pixels(8, This->frame->RasterBits, This->frame->ImageDesc.Width,
00225             This->frame->ImageDesc.Height, This->frame->ImageDesc.Width,
00226             prc, cbStride, cbBufferSize, pbBuffer);
00227     }
00228 }
00229 
00230 static HRESULT WINAPI GifFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode *iface,
00231     IWICMetadataQueryReader **ppIMetadataQueryReader)
00232 {
00233     TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader);
00234     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
00235 }
00236 
00237 static HRESULT WINAPI GifFrameDecode_GetColorContexts(IWICBitmapFrameDecode *iface,
00238     UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
00239 {
00240     TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
00241     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
00242 }
00243 
00244 static HRESULT WINAPI GifFrameDecode_GetThumbnail(IWICBitmapFrameDecode *iface,
00245     IWICBitmapSource **ppIThumbnail)
00246 {
00247     TRACE("(%p,%p)\n", iface, ppIThumbnail);
00248     return WINCODEC_ERR_CODECNOTHUMBNAIL;
00249 }
00250 
00251 static const IWICBitmapFrameDecodeVtbl GifFrameDecode_Vtbl = {
00252     GifFrameDecode_QueryInterface,
00253     GifFrameDecode_AddRef,
00254     GifFrameDecode_Release,
00255     GifFrameDecode_GetSize,
00256     GifFrameDecode_GetPixelFormat,
00257     GifFrameDecode_GetResolution,
00258     GifFrameDecode_CopyPalette,
00259     GifFrameDecode_CopyPixels,
00260     GifFrameDecode_GetMetadataQueryReader,
00261     GifFrameDecode_GetColorContexts,
00262     GifFrameDecode_GetThumbnail
00263 };
00264 
00265 static HRESULT WINAPI GifDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid,
00266     void **ppv)
00267 {
00268     GifDecoder *This = (GifDecoder*)iface;
00269     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
00270 
00271     if (!ppv) return E_INVALIDARG;
00272 
00273     if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICBitmapDecoder, iid))
00274     {
00275         *ppv = This;
00276     }
00277     else
00278     {
00279         *ppv = NULL;
00280         return E_NOINTERFACE;
00281     }
00282 
00283     IUnknown_AddRef((IUnknown*)*ppv);
00284     return S_OK;
00285 }
00286 
00287 static ULONG WINAPI GifDecoder_AddRef(IWICBitmapDecoder *iface)
00288 {
00289     GifDecoder *This = (GifDecoder*)iface;
00290     ULONG ref = InterlockedIncrement(&This->ref);
00291 
00292     TRACE("(%p) refcount=%u\n", iface, ref);
00293 
00294     return ref;
00295 }
00296 
00297 static ULONG WINAPI GifDecoder_Release(IWICBitmapDecoder *iface)
00298 {
00299     GifDecoder *This = (GifDecoder*)iface;
00300     ULONG ref = InterlockedDecrement(&This->ref);
00301 
00302     TRACE("(%p) refcount=%u\n", iface, ref);
00303 
00304     if (ref == 0)
00305     {
00306         This->lock.DebugInfo->Spare[0] = 0;
00307         DeleteCriticalSection(&This->lock);
00308         DGifCloseFile(This->gif);
00309         HeapFree(GetProcessHeap(), 0, This);
00310     }
00311 
00312     return ref;
00313 }
00314 
00315 static HRESULT WINAPI GifDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *pIStream,
00316     DWORD *pdwCapability)
00317 {
00318     FIXME("(%p,%p,%p): stub\n", iface, pIStream, pdwCapability);
00319     return E_NOTIMPL;
00320 }
00321 
00322 static int _gif_inputfunc(GifFileType *gif, GifByteType *data, int len) {
00323     IStream *stream = gif->UserData;
00324     ULONG bytesread;
00325     HRESULT hr;
00326 
00327     if (!stream)
00328     {
00329         ERR("attempting to read file after initialization\n");
00330         return 0;
00331     }
00332 
00333     hr = IStream_Read(stream, data, len, &bytesread);
00334     if (hr != S_OK) bytesread = 0;
00335     return bytesread;
00336 }
00337 
00338 static HRESULT WINAPI GifDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream,
00339     WICDecodeOptions cacheOptions)
00340 {
00341     GifDecoder *This = (GifDecoder*)iface;
00342     LARGE_INTEGER seek;
00343     int ret;
00344 
00345     TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions);
00346 
00347     EnterCriticalSection(&This->lock);
00348 
00349     if (This->initialized || This->gif)
00350     {
00351         WARN("already initialized\n");
00352         LeaveCriticalSection(&This->lock);
00353         return WINCODEC_ERR_WRONGSTATE;
00354     }
00355 
00356     /* seek to start of stream */
00357     seek.QuadPart = 0;
00358     IStream_Seek(pIStream, seek, STREAM_SEEK_SET, NULL);
00359 
00360     /* read all data from the stream */
00361     This->gif = DGifOpen((void*)pIStream, _gif_inputfunc);
00362     if (!This->gif)
00363     {
00364         LeaveCriticalSection(&This->lock);
00365         return E_FAIL;
00366     }
00367 
00368     ret = DGifSlurp(This->gif);
00369     if (ret == GIF_ERROR)
00370     {
00371         LeaveCriticalSection(&This->lock);
00372         return E_FAIL;
00373     }
00374 
00375     /* make sure we don't use the stream after this method returns */
00376     This->gif->UserData = NULL;
00377 
00378     This->initialized = TRUE;
00379 
00380     LeaveCriticalSection(&This->lock);
00381 
00382     return S_OK;
00383 }
00384 
00385 static HRESULT WINAPI GifDecoder_GetContainerFormat(IWICBitmapDecoder *iface,
00386     GUID *pguidContainerFormat)
00387 {
00388     memcpy(pguidContainerFormat, &GUID_ContainerFormatGif, sizeof(GUID));
00389     return S_OK;
00390 }
00391 
00392 static HRESULT WINAPI GifDecoder_GetDecoderInfo(IWICBitmapDecoder *iface,
00393     IWICBitmapDecoderInfo **ppIDecoderInfo)
00394 {
00395     HRESULT hr;
00396     IWICComponentInfo *compinfo;
00397 
00398     TRACE("(%p,%p)\n", iface, ppIDecoderInfo);
00399 
00400     hr = CreateComponentInfo(&CLSID_WICGifDecoder, &compinfo);
00401     if (FAILED(hr)) return hr;
00402 
00403     hr = IWICComponentInfo_QueryInterface(compinfo, &IID_IWICBitmapDecoderInfo,
00404         (void**)ppIDecoderInfo);
00405 
00406     IWICComponentInfo_Release(compinfo);
00407 
00408     return hr;
00409 }
00410 
00411 static HRESULT WINAPI GifDecoder_CopyPalette(IWICBitmapDecoder *iface,
00412     IWICPalette *pIPalette)
00413 {
00414     TRACE("(%p,%p)\n", iface, pIPalette);
00415     return WINCODEC_ERR_PALETTEUNAVAILABLE;
00416 }
00417 
00418 static HRESULT WINAPI GifDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface,
00419     IWICMetadataQueryReader **ppIMetadataQueryReader)
00420 {
00421     TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader);
00422     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
00423 }
00424 
00425 static HRESULT WINAPI GifDecoder_GetPreview(IWICBitmapDecoder *iface,
00426     IWICBitmapSource **ppIBitmapSource)
00427 {
00428     TRACE("(%p,%p)\n", iface, ppIBitmapSource);
00429     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
00430 }
00431 
00432 static HRESULT WINAPI GifDecoder_GetColorContexts(IWICBitmapDecoder *iface,
00433     UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
00434 {
00435     TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
00436     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
00437 }
00438 
00439 static HRESULT WINAPI GifDecoder_GetThumbnail(IWICBitmapDecoder *iface,
00440     IWICBitmapSource **ppIThumbnail)
00441 {
00442     TRACE("(%p,%p)\n", iface, ppIThumbnail);
00443     return WINCODEC_ERR_CODECNOTHUMBNAIL;
00444 }
00445 
00446 static HRESULT WINAPI GifDecoder_GetFrameCount(IWICBitmapDecoder *iface,
00447     UINT *pCount)
00448 {
00449     GifDecoder *This = (GifDecoder*)iface;
00450     TRACE("(%p,%p)\n", iface, pCount);
00451 
00452     if (!This->initialized) return WINCODEC_ERR_NOTINITIALIZED;
00453 
00454     *pCount = This->gif->ImageCount;
00455 
00456     TRACE("<- %u\n", *pCount);
00457 
00458     return S_OK;
00459 }
00460 
00461 static HRESULT WINAPI GifDecoder_GetFrame(IWICBitmapDecoder *iface,
00462     UINT index, IWICBitmapFrameDecode **ppIBitmapFrame)
00463 {
00464     GifDecoder *This = (GifDecoder*)iface;
00465     GifFrameDecode *result;
00466     TRACE("(%p,%u,%p)\n", iface, index, ppIBitmapFrame);
00467 
00468     if (!This->initialized) return WINCODEC_ERR_NOTINITIALIZED;
00469 
00470     if (index >= This->gif->ImageCount) return E_INVALIDARG;
00471 
00472     result = HeapAlloc(GetProcessHeap(), 0, sizeof(GifFrameDecode));
00473     if (!result) return E_OUTOFMEMORY;
00474 
00475     result->lpVtbl = &GifFrameDecode_Vtbl;
00476     result->ref = 1;
00477     result->frame = &This->gif->SavedImages[index];
00478     IWICBitmapDecoder_AddRef(iface);
00479     result->parent = This;
00480 
00481     *ppIBitmapFrame = (IWICBitmapFrameDecode*)result;
00482 
00483     return S_OK;
00484 }
00485 
00486 static const IWICBitmapDecoderVtbl GifDecoder_Vtbl = {
00487     GifDecoder_QueryInterface,
00488     GifDecoder_AddRef,
00489     GifDecoder_Release,
00490     GifDecoder_QueryCapability,
00491     GifDecoder_Initialize,
00492     GifDecoder_GetContainerFormat,
00493     GifDecoder_GetDecoderInfo,
00494     GifDecoder_CopyPalette,
00495     GifDecoder_GetMetadataQueryReader,
00496     GifDecoder_GetPreview,
00497     GifDecoder_GetColorContexts,
00498     GifDecoder_GetThumbnail,
00499     GifDecoder_GetFrameCount,
00500     GifDecoder_GetFrame
00501 };
00502 
00503 HRESULT GifDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
00504 {
00505     GifDecoder *This;
00506     HRESULT ret;
00507 
00508     TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppv);
00509 
00510     *ppv = NULL;
00511 
00512     if (pUnkOuter) return CLASS_E_NOAGGREGATION;
00513 
00514     This = HeapAlloc(GetProcessHeap(), 0, sizeof(GifDecoder));
00515     if (!This) return E_OUTOFMEMORY;
00516 
00517     This->lpVtbl = &GifDecoder_Vtbl;
00518     This->ref = 1;
00519     This->initialized = FALSE;
00520     This->gif = NULL;
00521     InitializeCriticalSection(&This->lock);
00522     This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": GifDecoder.lock");
00523 
00524     ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
00525     IUnknown_Release((IUnknown*)This);
00526 
00527     return ret;
00528 }

Generated on Wed May 23 2012 04:24:43 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.