windowscodecs: Implement CreateBitmapFromHICON.

This commit is contained in:
Dmitry Timoshkov 2013-01-14 12:45:24 +08:00 committed by Alexandre Julliard
parent d7687bed6a
commit 4ba27f7930
3 changed files with 136 additions and 8 deletions

View file

@ -1,6 +1,6 @@
MODULE = windowscodecs.dll
IMPORTLIB = windowscodecs
IMPORTS = uuid ole32 oleaut32 shlwapi advapi32 rpcrt4
IMPORTS = uuid ole32 oleaut32 rpcrt4 shlwapi user32 gdi32 advapi32
EXTRAINCL = @PNGINCL@
EXTRADEFS = -DENTRY_PREFIX=WIC_ -DPROXY_DELEGATION -DWINE_REGISTER_DLL
EXTRALIBS = @APPLICATIONSERVICESLIB@

View file

@ -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,

View file

@ -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;