Maybe the format for 32-bit bitmaps should be determined by the alpha channel options?

On Monday, September 16, 2013, Dmitry Timoshkov <dmitry@baikal.ru> wrote:
> Based on a gdiplus implementation.
> ---
>  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 *)&ji, 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);
> --
> 1.8.3.4
>
>
>
>