[2/2] windowscodecs: Implement CreateBitmapFromHICON, based on a gdiplus implementation.

Dmitry Timoshkov dmitry at baikal.ru
Fri Jan 11 04:40:02 CST 2013


---
 dlls/windowscodecs/Makefile.in    |   2 +-
 dlls/windowscodecs/imgfactory.c   | 128 ++++++++++++++++++++++++++++++++++++--
 dlls/windowscodecs/tests/bitmap.c |   5 --
 3 files changed, 125 insertions(+), 10 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..3d126fb 100644
--- a/dlls/windowscodecs/imgfactory.c
+++ b/dlls/windowscodecs/imgfactory.c
@@ -597,10 +597,130 @@ static HRESULT WINAPI ComponentFactory_CreateBitmapFromHBITMAP(IWICComponentFact
 }
 
 static HRESULT WINAPI ComponentFactory_CreateBitmapFromHICON(IWICComponentFactory *iface,
-    HICON hIcon, IWICBitmap **ppIBitmap)
-{
-    FIXME("(%p,%p,%p): stub\n", iface, hIcon, ppIBitmap);
-    return E_NOTIMPL;
+    HICON hicon, IWICBitmap **bitmap)
+{
+    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;
+
+    buffer = HeapAlloc(GetProcessHeap(), 0, size);
+    if (!buffer)
+    {
+        DeleteObject(info.hbmColor);
+        DeleteObject(info.hbmMask);
+        return E_OUTOFMEMORY;
+    }
+
+    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);
+
+    hr = BitmapImpl_Create(width, height, stride, size, buffer,
+                           &GUID_WICPixelFormat32bppBGRA, WICBitmapCacheOnLoad, bitmap);
+    if (hr != S_OK) goto failed;
+
+    if (!has_alpha)
+    {
+        IWICBitmapLock *lock;
+        BYTE *data;
+        DWORD *rgba;
+
+        IWICBitmap_Lock(*bitmap, NULL, WICBitmapLockWrite, &lock);
+        IWICBitmapLock_GetDataPointer(lock, &size, &data);
+
+        if (info.hbmMask)
+        {
+            /* read alpha data from the mask */
+            GetDIBits(hdc, info.hbmMask, info.hbmColor ? 0 : height, height, buffer, &bi, DIB_RGB_COLORS);
+
+            for (y = 0; y < height; y++)
+            {
+                rgba = (DWORD *)(data + y * stride);
+                bits = (DWORD *)(buffer + y * stride);
+
+                for (x = 0; x < width; x++, rgba++, bits++)
+                {
+                    if (!info.hbmColor) *rgba = ~*rgba;
+
+                    if (*bits)
+                        *rgba = 0;
+                    else
+                        *rgba |= 0xff000000;
+                }
+            }
+        }
+        else
+        {
+            /* set constant alpha of 255 */
+            for (y = 0; y < height; y++)
+            {
+                rgba = (DWORD *)(data + y * stride);
+                for (x = 0; x < width; x++, rgba++)
+                    *rgba |= 0xff000000;
+            }
+        }
+    }
+
+failed:
+    HeapFree(GetProcessHeap(), 0, buffer);
+    DeleteDC(hdc);
+    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 f957b5a..0b2f9b2 100644
--- a/dlls/windowscodecs/tests/bitmap.c
+++ b/dlls/windowscodecs/tests/bitmap.c
@@ -529,21 +529,16 @@ 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);
-    if (hr != S_OK) return;
 
     IWICBitmap_GetPixelFormat(bitmap, &format);
     ok(IsEqualGUID(&format, &GUID_WICPixelFormat32bppBGRA),
-- 
1.8.0.2




More information about the wine-patches mailing list