Dmitry Timoshkov : windowscodecs: Implement CreateBitmapFromHBITMAP.

Alexandre Julliard julliard at winehq.org
Wed Sep 18 15:49:59 CDT 2013


Module: wine
Branch: master
Commit: c6d62ff081410eed07b3e788c8c4539f0fc36b92
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=c6d62ff081410eed07b3e788c8c4539f0fc36b92

Author: Dmitry Timoshkov <dmitry at baikal.ru>
Date:   Mon Sep 16 17:28:07 2013 +0900

windowscodecs: Implement CreateBitmapFromHBITMAP.

---

 dlls/windowscodecs/imgfactory.c   |  149 ++++++++++++++++++++++++++++++++++++-
 dlls/windowscodecs/tests/bitmap.c |   14 ++-
 2 files changed, 154 insertions(+), 9 deletions(-)

diff --git a/dlls/windowscodecs/imgfactory.c b/dlls/windowscodecs/imgfactory.c
index e5f2125..bb4cf67 100644
--- a/dlls/windowscodecs/imgfactory.c
+++ b/dlls/windowscodecs/imgfactory.c
@@ -603,12 +603,153 @@ static HRESULT WINAPI ComponentFactory_CreateBitmapFromMemory(IWICComponentFacto
     return BitmapImpl_Create(width, height, stride, size, buffer, format, WICBitmapCacheOnLoad, bitmap);
 }
 
+static BOOL get_16bpp_format(HBITMAP hbm, WICPixelFormatGUID *format)
+{
+    BOOL ret = TRUE;
+    BITMAPV4HEADER bmh;
+    HDC hdc;
+
+    hdc = CreateCompatibleDC(0);
+
+    memset(&bmh, 0, sizeof(bmh));
+    bmh.bV4Size = sizeof(bmh);
+    bmh.bV4Width = 1;
+    bmh.bV4Height = 1;
+    bmh.bV4V4Compression = BI_BITFIELDS;
+    bmh.bV4BitCount = 16;
+
+    GetDIBits(hdc, hbm, 0, 0, NULL, (BITMAPINFO *)&bmh, DIB_RGB_COLORS);
+
+    if (bmh.bV4RedMask == 0x7c00 &&
+        bmh.bV4GreenMask == 0x3e0 &&
+        bmh.bV4BlueMask == 0x1f)
+    {
+        *format = GUID_WICPixelFormat16bppBGR555;
+    }
+    else if (bmh.bV4RedMask == 0xf800 &&
+        bmh.bV4GreenMask == 0x7e0 &&
+        bmh.bV4BlueMask == 0x1f)
+    {
+        *format = GUID_WICPixelFormat16bppBGR565;
+    }
+    else
+    {
+        FIXME("unrecognized bitfields %x,%x,%x\n", bmh.bV4RedMask,
+            bmh.bV4GreenMask, bmh.bV4BlueMask);
+        ret = FALSE;
+    }
+
+    DeleteDC(hdc);
+    return ret;
+}
+
 static HRESULT WINAPI ComponentFactory_CreateBitmapFromHBITMAP(IWICComponentFactory *iface,
-    HBITMAP hBitmap, HPALETTE hPalette, WICBitmapAlphaChannelOption options,
-    IWICBitmap **ppIBitmap)
+    HBITMAP hbm, HPALETTE hpal, WICBitmapAlphaChannelOption option, IWICBitmap **bitmap)
 {
-    FIXME("(%p,%p,%p,%u,%p): stub\n", iface, hBitmap, hPalette, options, ppIBitmap);
-    return E_NOTIMPL;
+    BITMAP bm;
+    HRESULT hr;
+    WICPixelFormatGUID format;
+    IWICBitmapLock *lock;
+    UINT size, num_palette_entries = 0;
+    PALETTEENTRY entry[256];
+
+    TRACE("(%p,%p,%p,%u,%p)\n", iface, hbm, hpal, option, bitmap);
+
+    if (!bitmap) return E_INVALIDARG;
+
+    if (GetObjectW(hbm, sizeof(bm), &bm) != sizeof(bm))
+        return WINCODEC_ERR_WIN32ERROR;
+
+    if (hpal)
+    {
+        num_palette_entries = GetPaletteEntries(hpal, 0, 256, entry);
+        if (!num_palette_entries)
+            return WINCODEC_ERR_WIN32ERROR;
+    }
+
+    /* TODO: Figure out the correct format for 16, 32, 64 bpp */
+    switch(bm.bmBitsPixel)
+    {
+    case 1:
+        format = GUID_WICPixelFormat1bppIndexed;
+        break;
+    case 4:
+        format = GUID_WICPixelFormat4bppIndexed;
+        break;
+    case 8:
+        format = GUID_WICPixelFormat8bppIndexed;
+        break;
+    case 16:
+        if (!get_16bpp_format(hbm, &format))
+            return E_INVALIDARG;
+        break;
+    case 24:
+        format = GUID_WICPixelFormat24bppBGR;
+        break;
+    case 32:
+        format = GUID_WICPixelFormat32bppBGR;
+        break;
+    case 48:
+        format = GUID_WICPixelFormat48bppRGB;
+        break;
+    default:
+        FIXME("unsupported %d bpp\n", bm.bmBitsPixel);
+        return E_INVALIDARG;
+    }
+
+    hr = BitmapImpl_Create(bm.bmWidth, bm.bmHeight, bm.bmWidthBytes, 0, NULL, &format, option, bitmap);
+    if (hr != S_OK) return hr;
+
+    hr = IWICBitmap_Lock(*bitmap, NULL, WICBitmapLockWrite, &lock);
+    if (hr == S_OK)
+    {
+        BYTE *buffer;
+        HDC hdc;
+        char bmibuf[FIELD_OFFSET(BITMAPINFO, bmiColors[256])];
+        BITMAPINFO *bmi = (BITMAPINFO *)bmibuf;
+
+        IWICBitmapLock_GetDataPointer(lock, &size, &buffer);
+
+        hdc = CreateCompatibleDC(0);
+
+        bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+        bmi->bmiHeader.biBitCount = 0;
+        GetDIBits(hdc, hbm, 0, 0, NULL, bmi, DIB_RGB_COLORS);
+        bmi->bmiHeader.biHeight = -bm.bmHeight;
+        GetDIBits(hdc, hbm, 0, bm.bmHeight, buffer, bmi, DIB_RGB_COLORS);
+
+        DeleteDC(hdc);
+        IWICBitmapLock_Release(lock);
+
+        if (num_palette_entries)
+        {
+            IWICPalette *palette;
+            WICColor colors[256];
+            UINT i;
+
+            hr = PaletteImpl_Create(&palette);
+            if (hr == S_OK)
+            {
+                for (i = 0; i < num_palette_entries; i++)
+                    colors[i] = 0xff000000 | entry[i].peRed << 16 |
+                                entry[i].peGreen << 8 | entry[i].peBlue;
+
+                hr = IWICPalette_InitializeCustom(palette, colors, num_palette_entries);
+                if (hr == S_OK)
+                    hr = IWICBitmap_SetPalette(*bitmap, palette);
+
+                IWICPalette_Release(palette);
+            }
+        }
+    }
+
+    if (hr != S_OK)
+    {
+        IWICBitmap_Release(*bitmap);
+        *bitmap = NULL;
+    }
+
+    return hr;
 }
 
 static HRESULT WINAPI ComponentFactory_CreateBitmapFromHICON(IWICComponentFactory *iface,
diff --git a/dlls/windowscodecs/tests/bitmap.c b/dlls/windowscodecs/tests/bitmap.c
index 8795048..3c79ce8 100644
--- a/dlls/windowscodecs/tests/bitmap.c
+++ b/dlls/windowscodecs/tests/bitmap.c
@@ -727,17 +727,13 @@ static void test_CreateBitmapFromHBITMAP(void)
     ok(hbmp != 0, "failed to create bitmap\n");
 
     hr = IWICImagingFactory_CreateBitmapFromHBITMAP(factory, 0, 0, WICBitmapIgnoreAlpha, &bitmap);
-todo_wine
     ok(hr == WINCODEC_ERR_WIN32ERROR || hr == 0x88980003 /*XP*/, "expected WINCODEC_ERR_WIN32ERROR, got %#x\n", hr);
 
     hr = IWICImagingFactory_CreateBitmapFromHBITMAP(factory, hbmp, 0, WICBitmapIgnoreAlpha, NULL);
-todo_wine
     ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr);
 
     hr = IWICImagingFactory_CreateBitmapFromHBITMAP(factory, hbmp, 0, WICBitmapIgnoreAlpha, &bitmap);
-todo_wine
     ok(hr == S_OK, "CreateBitmapFromHBITMAP error %#x\n", hr);
-    if (hr != S_OK) return;
 
     IWICBitmap_GetPixelFormat(bitmap, &format);
     ok(IsEqualGUID(&format, &GUID_WICPixelFormat8bppIndexed),
@@ -770,6 +766,7 @@ todo_wine
     ok(hr == S_OK, "CreateBitmapFromHBITMAP error %#x\n", hr);
 
     IWICBitmap_GetPixelFormat(bitmap, &format);
+todo_wine
     ok(IsEqualGUID(&format, &GUID_WICPixelFormat4bppIndexed),
        "unexpected pixel format %s\n", debugstr_guid(&format));
 
@@ -789,6 +786,7 @@ todo_wine
 
     hr = IWICPalette_GetColorCount(palette, &count);
     ok(hr == S_OK, "GetColorCount error %#x\n", hr);
+todo_wine
     ok(count == 16, "expected 16, got %u\n", count);
 
     IWICPalette_Release(palette);
@@ -837,7 +835,13 @@ todo_wine
     hr = IWICBitmap_CopyPixels(bitmap, NULL, 4, sizeof(data), data);
     ok(hr == S_OK, "IWICBitmap_CopyPixels error %#x\n", hr);
     for (i = 0; i < sizeof(data); i++)
-        ok(data[i] == data_8bpp_pal_wic[i], "%u: expected %#x, got %#x\n", i, data_8bpp_pal_wic[i], data[i]);
+    {
+        if (data[i] != data_8bpp_pal_wic[i])
+todo_wine
+            ok(data[i] == data_8bpp_pal_wic[i], "%u: expected %#x, got %#x\n", i, data_8bpp_pal_wic[i], data[i]);
+        else
+            ok(data[i] == data_8bpp_pal_wic[i], "%u: expected %#x, got %#x\n", i, data_8bpp_pal_wic[i], data[i]);
+    }
 
     IWICBitmap_Release(bitmap);
     DeleteObject(hbmp);




More information about the wine-cvs mailing list