Vincent Povirk : gdiplus: Use WIC to decode ICO files.
Alexandre Julliard
julliard at winehq.org
Tue Sep 1 11:05:40 CDT 2009
Module: wine
Branch: master
Commit: 9d149e606b153c72df6945596c003d4ec453026a
URL: http://source.winehq.org/git/wine.git/?a=commit;h=9d149e606b153c72df6945596c003d4ec453026a
Author: Vincent Povirk <vincent at 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
},
};
More information about the wine-cvs
mailing list