windowscodecs: Implement CreateBitmapFromHICON. Take 2.
Dmitry Timoshkov
dmitry at baikal.ru
Sun Jan 13 22:45:24 CST 2013
This version of the patch doesn't use the same logic for allocating memory
for a bitmap as the gdiplus implementation and fixes a IWICBitmapLock leak.
---
dlls/windowscodecs/Makefile.in | 2 +-
dlls/windowscodecs/imgfactory.c | 138 +++++++++++++++++++++++++++++++++++++-
dlls/windowscodecs/tests/bitmap.c | 4 --
3 files changed, 136 insertions(+), 8 deletions(-)
diff --git a/dlls/windowscodecs/Makefile.in b/dlls/windowscodecs/Makefile.in
index d031daa..07c04fd 100644
--- a/dlls/windowscodecs/Makefile.in
+++ b/dlls/windowscodecs/Makefile.in
@@ -1,6 +1,6 @@
MODULE = windowscodecs.dll
IMPORTLIB = windowscodecs
-IMPORTS = uuid ole32 oleaut32 shlwapi advapi32 rpcrt4
+IMPORTS = gdi32 user32 uuid ole32 oleaut32 shlwapi advapi32 rpcrt4
EXTRAINCL = @PNGINCL@
EXTRADEFS = -DENTRY_PREFIX=WIC_ -DPROXY_DELEGATION -DWINE_REGISTER_DLL
EXTRALIBS = @APPLICATIONSERVICESLIB@
diff --git a/dlls/windowscodecs/imgfactory.c b/dlls/windowscodecs/imgfactory.c
index 1d05ef5..8762c81 100644
--- a/dlls/windowscodecs/imgfactory.c
+++ b/dlls/windowscodecs/imgfactory.c
@@ -597,10 +597,142 @@ static HRESULT WINAPI ComponentFactory_CreateBitmapFromHBITMAP(IWICComponentFact
}
static HRESULT WINAPI ComponentFactory_CreateBitmapFromHICON(IWICComponentFactory *iface,
- HICON hIcon, IWICBitmap **ppIBitmap)
+ HICON hicon, IWICBitmap **bitmap)
{
- FIXME("(%p,%p,%p): stub\n", iface, hIcon, ppIBitmap);
- return E_NOTIMPL;
+ IWICBitmapLock *lock;
+ ICONINFO info;
+ BITMAP bm;
+ int width, height, x, y;
+ UINT stride, size;
+ BYTE *buffer;
+ DWORD *bits;
+ BITMAPINFO bi;
+ HDC hdc;
+ BOOL has_alpha;
+ HRESULT hr;
+
+ TRACE("(%p,%p,%p)\n", iface, hicon, bitmap);
+
+ if (!bitmap) return E_INVALIDARG;
+
+ if (!GetIconInfo(hicon, &info))
+ return HRESULT_FROM_WIN32(GetLastError());
+
+ GetObjectW(info.hbmColor ? info.hbmColor : info.hbmMask, sizeof(bm), &bm);
+
+ width = bm.bmWidth;
+ height = info.hbmColor ? abs(bm.bmHeight) : abs(bm.bmHeight) / 2;
+ stride = width * 4;
+ size = stride * height;
+
+ hr = BitmapImpl_Create(width, height, stride, size, NULL,
+ &GUID_WICPixelFormat32bppBGRA, WICBitmapCacheOnLoad, bitmap);
+ if (hr != S_OK) goto failed;
+
+ hr = IWICBitmap_Lock(*bitmap, NULL, WICBitmapLockWrite, &lock);
+ if (hr != S_OK)
+ {
+ IWICBitmap_Release(*bitmap);
+ goto failed;
+ }
+ IWICBitmapLock_GetDataPointer(lock, &size, &buffer);
+
+ hdc = CreateCompatibleDC(0);
+
+ memset(&bi, 0, sizeof(bi));
+ bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
+ bi.bmiHeader.biWidth = width;
+ bi.bmiHeader.biHeight = -height;
+ bi.bmiHeader.biPlanes = 1;
+ bi.bmiHeader.biBitCount = 32;
+ bi.bmiHeader.biCompression = BI_RGB;
+
+ has_alpha = FALSE;
+
+ if (info.hbmColor)
+ {
+ GetDIBits(hdc, info.hbmColor, 0, height, buffer, &bi, DIB_RGB_COLORS);
+
+ if (bm.bmBitsPixel == 32)
+ {
+ /* If any pixel has a non-zero alpha, ignore hbmMask */
+ bits = (DWORD *)buffer;
+ for (x = 0; x < width && !has_alpha; x++, bits++)
+ {
+ for (y = 0; y < height; y++)
+ {
+ if (*bits & 0xff000000)
+ {
+ has_alpha = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ GetDIBits(hdc, info.hbmMask, 0, height, buffer, &bi, DIB_RGB_COLORS);
+
+ if (!has_alpha)
+ {
+ DWORD *rgba;
+
+ if (info.hbmMask)
+ {
+ BYTE *mask;
+
+ mask = HeapAlloc(GetProcessHeap(), 0, size);
+ if (!mask)
+ {
+ IWICBitmapLock_Release(lock);
+ IWICBitmap_Release(*bitmap);
+ DeleteDC(hdc);
+ hr = E_OUTOFMEMORY;
+ goto failed;
+ }
+
+ /* read alpha data from the mask */
+ GetDIBits(hdc, info.hbmMask, info.hbmColor ? 0 : height, height, mask, &bi, DIB_RGB_COLORS);
+
+ for (y = 0; y < height; y++)
+ {
+ rgba = (DWORD *)(buffer + y * stride);
+ bits = (DWORD *)(mask + y * stride);
+
+ for (x = 0; x < width; x++, rgba++, bits++)
+ {
+ if (!info.hbmColor) *rgba = ~*rgba;
+
+ if (*bits)
+ *rgba = 0;
+ else
+ *rgba |= 0xff000000;
+ }
+ }
+
+ HeapFree(GetProcessHeap(), 0, mask);
+ }
+ else
+ {
+ /* set constant alpha of 255 */
+ for (y = 0; y < height; y++)
+ {
+ rgba = (DWORD *)(buffer + y * stride);
+ for (x = 0; x < width; x++, rgba++)
+ *rgba |= 0xff000000;
+ }
+ }
+
+ }
+
+ IWICBitmapLock_Release(lock);
+ DeleteDC(hdc);
+
+failed:
+ DeleteObject(info.hbmColor);
+ DeleteObject(info.hbmMask);
+
+ return hr;
}
static HRESULT WINAPI ComponentFactory_CreateComponentEnumerator(IWICComponentFactory *iface,
diff --git a/dlls/windowscodecs/tests/bitmap.c b/dlls/windowscodecs/tests/bitmap.c
index 40b8ce6..fb7183b 100644
--- a/dlls/windowscodecs/tests/bitmap.c
+++ b/dlls/windowscodecs/tests/bitmap.c
@@ -529,19 +529,15 @@ static void test_CreateBitmapFromHICON(void)
DeleteObject(info.hbmMask);
hr = IWICImagingFactory_CreateBitmapFromHICON(factory, 0, NULL);
-todo_wine
ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr);
hr = IWICImagingFactory_CreateBitmapFromHICON(factory, 0, &bitmap);
-todo_wine
ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_CURSOR_HANDLE), "expected ERROR_INVALID_CURSOR_HANDLE, got %#x\n", hr);
hr = IWICImagingFactory_CreateBitmapFromHICON(factory, icon, NULL);
-todo_wine
ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr);
hr = IWICImagingFactory_CreateBitmapFromHICON(factory, icon, &bitmap);
-todo_wine
ok(hr == S_OK, "CreateBitmapFromHICON error %#x\n", hr);
DestroyIcon(icon);
if (hr != S_OK) return;
--
1.8.0.2
More information about the wine-patches
mailing list