Module: wine Branch: master Commit: c6d62ff081410eed07b3e788c8c4539f0fc36b92 URL: http://source.winehq.org/git/wine.git/?a=commit;h=c6d62ff081410eed07b3e788c8...
Author: Dmitry Timoshkov dmitry@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);