Commit 9d149e60 authored by Vincent Povirk's avatar Vincent Povirk Committed by Alexandre Julliard

gdiplus: Use WIC to decode ICO files.

parent ae51d05d
...@@ -5,6 +5,7 @@ VPATH = @srcdir@ ...@@ -5,6 +5,7 @@ VPATH = @srcdir@
MODULE = gdiplus.dll MODULE = gdiplus.dll
IMPORTLIB = gdiplus IMPORTLIB = gdiplus
IMPORTS = uuid shlwapi oleaut32 ole32 user32 gdi32 kernel32 IMPORTS = uuid shlwapi oleaut32 ole32 user32 gdi32 kernel32
DELAYIMPORTS = windowscodecs
C_SRCS = \ C_SRCS = \
brush.c \ brush.c \
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "ole2.h" #include "ole2.h"
#include "initguid.h" #include "initguid.h"
#include "wincodec.h"
#include "gdiplus.h" #include "gdiplus.h"
#include "gdiplus_private.h" #include "gdiplus_private.h"
#include "wine/debug.h" #include "wine/debug.h"
...@@ -1381,28 +1382,129 @@ GpStatus WINGDIPAPI GdipLoadImageFromFileICM(GDIPCONST WCHAR* filename,GpImage * ...@@ -1381,28 +1382,129 @@ GpStatus WINGDIPAPI GdipLoadImageFromFileICM(GDIPCONST WCHAR* filename,GpImage *
return GdipLoadImageFromFile(filename, image); 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) hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER,
return InvalidParameter; &IID_IWICBitmapDecoder, (void**)&decoder);
if (FAILED(hr)) goto end;
if(OleLoadPicture(stream, 0, FALSE, &IID_IPicture, hr = IWICBitmapDecoder_Initialize(decoder, (IStream*)stream, WICDecodeMetadataCacheOnLoad);
(LPVOID*) &pic) != S_OK){ if (SUCCEEDED(hr))
TRACE("Could not load picture\n"); hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
return GenericError;
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)); IWICBitmapDecoder_Release(decoder);
if(!*image) return OutOfMemory;
(*image)->type = ImageTypeUnknown;
(*image)->picture = pic;
(*image)->flags = ImageFlagsNone;
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) static GpStatus decode_image_olepicture_bitmap(IStream* stream, REFCLSID clsid, GpImage **image)
...@@ -2012,7 +2114,7 @@ static const struct image_codec codecs[NUM_CODECS] = { ...@@ -2012,7 +2114,7 @@ static const struct image_codec codecs[NUM_CODECS] = {
/* SigMask */ ico_sig_mask, /* SigMask */ ico_sig_mask,
}, },
NULL, NULL,
decode_image_olepicture_icon decode_image_icon
}, },
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment