Module: wine Branch: master Commit: 9d149e606b153c72df6945596c003d4ec453026a URL: http://source.winehq.org/git/wine.git/?a=commit;h=9d149e606b153c72df6945596c...
Author: Vincent Povirk vincent@codeweavers.com Date: Mon Aug 31 16:56:47 2009 -0500
gdiplus: Use WIC to decode ICO files.
---
dlls/gdiplus/Makefile.in | 1 + dlls/gdiplus/image.c | 134 ++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 119 insertions(+), 16 deletions(-)
diff --git a/dlls/gdiplus/Makefile.in b/dlls/gdiplus/Makefile.in index de88d5e..87f8b6a 100644 --- a/dlls/gdiplus/Makefile.in +++ b/dlls/gdiplus/Makefile.in @@ -5,6 +5,7 @@ VPATH = @srcdir@ MODULE = gdiplus.dll IMPORTLIB = gdiplus IMPORTS = uuid shlwapi oleaut32 ole32 user32 gdi32 kernel32 +DELAYIMPORTS = windowscodecs
C_SRCS = \ brush.c \ diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c index 730d981..6c48663 100644 --- a/dlls/gdiplus/image.c +++ b/dlls/gdiplus/image.c @@ -31,6 +31,7 @@ #include "ole2.h"
#include "initguid.h" +#include "wincodec.h" #include "gdiplus.h" #include "gdiplus_private.h" #include "wine/debug.h" @@ -1381,28 +1382,129 @@ GpStatus WINGDIPAPI GdipLoadImageFromFileICM(GDIPCONST WCHAR* filename,GpImage * return GdipLoadImageFromFile(filename, image); }
-static GpStatus decode_image_olepicture_icon(IStream* stream, REFCLSID clsid, GpImage **image) +static const WICPixelFormatGUID *wic_pixel_formats[] = { + &GUID_WICPixelFormat16bppBGR555, + &GUID_WICPixelFormat24bppBGR, + &GUID_WICPixelFormat32bppBGR, + &GUID_WICPixelFormat32bppBGRA, + &GUID_WICPixelFormat32bppPBGRA, + NULL +}; + +static const PixelFormat wic_gdip_formats[] = { + PixelFormat16bppRGB555, + PixelFormat24bppRGB, + PixelFormat32bppRGB, + PixelFormat32bppARGB, + PixelFormat32bppPARGB, +}; + +static GpStatus decode_image_wic(IStream* stream, REFCLSID clsid, GpImage **image) { - IPicture *pic; + GpStatus status=Ok; + GpBitmap *bitmap; + HRESULT hr; + IWICBitmapDecoder *decoder; + IWICBitmapFrameDecode *frame; + IWICBitmapSource *source=NULL; + WICPixelFormatGUID wic_format; + PixelFormat gdip_format=0; + int i; + UINT width, height; + BitmapData lockeddata; + WICRect wrc; + HRESULT initresult;
- TRACE("%p %p\n", stream, image); + initresult = CoInitialize(NULL);
- if(!stream || !image) - return InvalidParameter; + hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, + &IID_IWICBitmapDecoder, (void**)&decoder); + if (FAILED(hr)) goto end;
- if(OleLoadPicture(stream, 0, FALSE, &IID_IPicture, - (LPVOID*) &pic) != S_OK){ - TRACE("Could not load picture\n"); - return GenericError; + hr = IWICBitmapDecoder_Initialize(decoder, (IStream*)stream, WICDecodeMetadataCacheOnLoad); + if (SUCCEEDED(hr)) + hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame); + + if (SUCCEEDED(hr)) /* got frame */ + { + hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &wic_format); + + if (SUCCEEDED(hr)) + { + for (i=0; wic_pixel_formats[i]; i++) + { + if (IsEqualGUID(&wic_format, wic_pixel_formats[i])) + { + source = (IWICBitmapSource*)frame; + IWICBitmapSource_AddRef(source); + gdip_format = wic_gdip_formats[i]; + break; + } + } + if (!source) + { + /* unknown format; fall back on 32bppARGB */ + hr = WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA, (IWICBitmapSource*)frame, &source); + gdip_format = PixelFormat32bppARGB; + } + } + + if (SUCCEEDED(hr)) /* got source */ + { + hr = IWICBitmapSource_GetSize(source, &width, &height); + + if (SUCCEEDED(hr)) + status = GdipCreateBitmapFromScan0(width, height, 0, gdip_format, + NULL, &bitmap); + + if (SUCCEEDED(hr) && status == Ok) /* created bitmap */ + { + status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeWrite, + gdip_format, &lockeddata); + if (status == Ok) /* locked bitmap */ + { + wrc.X = 0; + wrc.Width = width; + wrc.Height = 1; + for (i=0; i<height; i++) + { + wrc.Y = i; + hr = IWICBitmapSource_CopyPixels(source, &wrc, abs(lockeddata.Stride), + abs(lockeddata.Stride), (BYTE*)lockeddata.Scan0+lockeddata.Stride*i); + if (FAILED(hr)) break; + } + + GdipBitmapUnlockBits(bitmap, &lockeddata); + } + + if (SUCCEEDED(hr) && status == Ok) + *image = (GpImage*)bitmap; + else + { + *image = NULL; + GdipDisposeImage((GpImage*)bitmap); + } + } + + IWICBitmapSource_Release(source); + } + + IWICBitmapFrameDecode_Release(frame); }
- *image = GdipAlloc(sizeof(GpImage)); - if(!*image) return OutOfMemory; - (*image)->type = ImageTypeUnknown; - (*image)->picture = pic; - (*image)->flags = ImageFlagsNone; + IWICBitmapDecoder_Release(decoder);
- return Ok; +end: + if (SUCCEEDED(initresult)) CoUninitialize(); + + if (FAILED(hr) && status == Ok) status = hresult_to_status(hr); + + return status; +} + +static GpStatus decode_image_icon(IStream* stream, REFCLSID clsid, GpImage **image) +{ + return decode_image_wic(stream, &CLSID_WICIcoDecoder, image); }
static GpStatus decode_image_olepicture_bitmap(IStream* stream, REFCLSID clsid, GpImage **image) @@ -2012,7 +2114,7 @@ static const struct image_codec codecs[NUM_CODECS] = { /* SigMask */ ico_sig_mask, }, NULL, - decode_image_olepicture_icon + decode_image_icon }, };