Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygengifformat.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
1.7.6.1
|