From 12f73ed9d8518442c6cc79d24a56dd07fa8a7fa8 Mon Sep 17 00:00:00 2001 From: Piotr Caban Date: Fri, 19 Apr 2024 20:06:30 +0200 Subject: [PATCH] windowscodecs: Support 32-bit ABGR bitfields bitmaps. --- dlls/windowscodecs/bmpdecode.c | 34 +++++++ dlls/windowscodecs/tests/bmpformat.c | 137 +++++++++++++++++++++++++++ 2 files changed, 171 insertions(+) diff --git a/dlls/windowscodecs/bmpdecode.c b/dlls/windowscodecs/bmpdecode.c index e80f145c73c..9d4867447f0 100644 --- a/dlls/windowscodecs/bmpdecode.c +++ b/dlls/windowscodecs/bmpdecode.c @@ -415,6 +415,39 @@ fail: return hr; } +static HRESULT BmpFrameDecode_ReadABGRasBGR(BmpDecoder* This) +{ + UINT x, y, width, height; + BYTE *pixel; + HRESULT hr; + + hr = IWICBitmapFrameDecode_GetSize(&This->IWICBitmapFrameDecode_iface, &width, &height); + + if (SUCCEEDED(hr)) + { + hr = BmpFrameDecode_ReadUncompressed(This); + } + + if (SUCCEEDED(hr)) + { + for (y = 0; y < height; y++) + { + pixel = This->imagedatastart + This->stride * y; + + for (x = 0; x < width; x++) + { + pixel[0] = pixel[1]; + pixel[1] = pixel[2]; + pixel[2] = pixel[3]; + pixel[3] = 0; + pixel += 4; + } + } + } + + return hr; +} + static HRESULT BmpFrameDecode_ReadRGB8(BmpDecoder* This) { HRESULT hr; @@ -742,6 +775,7 @@ static const struct bitfields_format bitfields_formats[] = { {16,0xf800,0x7e0,0x1f,0,&GUID_WICPixelFormat16bppBGR565,BmpFrameDecode_ReadUncompressed}, {32,0xff0000,0xff00,0xff,0,&GUID_WICPixelFormat32bppBGR,BmpFrameDecode_ReadUncompressed}, {32,0xff0000,0xff00,0xff,0xff000000,&GUID_WICPixelFormat32bppBGRA,BmpFrameDecode_ReadUncompressed}, + {32,0xff000000,0xff0000,0xff00,0xff,&GUID_WICPixelFormat32bppBGR,BmpFrameDecode_ReadABGRasBGR}, {32,0xff,0xff00,0xff0000,0,&GUID_WICPixelFormat32bppBGR,BmpFrameDecode_ReadRGB8}, {0} }; diff --git a/dlls/windowscodecs/tests/bmpformat.c b/dlls/windowscodecs/tests/bmpformat.c index 39a576d6c69..1a6a8185156 100644 --- a/dlls/windowscodecs/tests/bmpformat.c +++ b/dlls/windowscodecs/tests/bmpformat.c @@ -910,6 +910,142 @@ static void test_decode_rle4(void) IWICBitmapDecoder_Release(decoder); } +static const char testbmp_bitfields_abgr[] = { + /* BITMAPFILEHEADER */ + 'B','M', /* "BM" */ + sizeof(BITMAPFILEHEADER)+sizeof(BITMAPV5HEADER)+8,0,0,0, /* file size */ + 0,0,0,0, /* reserved */ + sizeof(BITMAPFILEHEADER)+sizeof(BITMAPV5HEADER),0,0,0, /* offset to bits */ + /* BITMAPV5HEADER */ + sizeof(BITMAPV5HEADER),0,0,0, /* size */ + 2,0,0,0, /* width */ + 1,0,0,0, /* height */ + 1,0, /* planes */ + 32,0, /* bit count */ + BI_BITFIELDS,0,0,0, /* compression */ + 8,0,0,0, /* image size */ + 19,11,0,0, /* X pixels per meter */ + 19,11,0,0, /* Y pixels per meter */ + 0,0,0,0, /* colors used */ + 0,0,0,0, /* colors important */ + 0,0,0,255, /* red mask */ + 0,0,255,0, /* green mask */ + 0,255,0,0, /* blue mask */ + 255,0,0,0, /* alpha mask */ + 'B','G','R','s', /* color space */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0, /* gamma */ + LCS_GM_GRAPHICS,0,0,0, /* intent */ + 0,0,0,0,0,0,0,0,0,0,0,0, + /* bits */ + 0,255,0,0,255,0,255,0 +}; + +static void test_decode_bitfields(void) +{ + IWICBitmapDecoder *decoder; + IWICBitmapFrameDecode *framedecode; + HRESULT hr; + HGLOBAL hbmpdata; + char *bmpdata; + IStream *bmpstream; + GUID guidresult; + UINT count=0, width=0, height=0; + double dpiX, dpiY; + DWORD imagedata[2] = {1}; + const DWORD expected_imagedata[2] = { 0xff, 0xff00 }; + WICRect rc; + + hr = CoCreateInstance(&CLSID_WICBmpDecoder, NULL, CLSCTX_INPROC_SERVER, + &IID_IWICBitmapDecoder, (void**)&decoder); + ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%lx\n", hr); + if (FAILED(hr)) return; + + hbmpdata = GlobalAlloc(GMEM_MOVEABLE, sizeof(testbmp_bitfields_abgr)); + ok(hbmpdata != 0, "GlobalAlloc failed\n"); + if (hbmpdata) + { + bmpdata = GlobalLock(hbmpdata); + memcpy(bmpdata, testbmp_bitfields_abgr, sizeof(testbmp_bitfields_abgr)); + GlobalUnlock(hbmpdata); + + hr = CreateStreamOnHGlobal(hbmpdata, FALSE, &bmpstream); + ok(SUCCEEDED(hr), "CreateStreamOnHGlobal failed, hr=%lx\n", hr); + if (SUCCEEDED(hr)) + { + hr = IWICBitmapDecoder_Initialize(decoder, bmpstream, WICDecodeMetadataCacheOnLoad); + ok(hr == S_OK, "Initialize failed, hr=%lx\n", hr); + + hr = IWICBitmapDecoder_GetContainerFormat(decoder, &guidresult); + ok(SUCCEEDED(hr), "GetContainerFormat failed, hr=%lx\n", hr); + ok(IsEqualGUID(&guidresult, &GUID_ContainerFormatBmp), "unexpected container format\n"); + + hr = IWICBitmapDecoder_GetFrameCount(decoder, &count); + ok(SUCCEEDED(hr), "GetFrameCount failed, hr=%lx\n", hr); + ok(count == 1, "unexpected count %u\n", count); + + hr = IWICBitmapDecoder_GetFrame(decoder, 0, &framedecode); + ok(SUCCEEDED(hr), "GetFrame failed, hr=%lx\n", hr); + if (SUCCEEDED(hr)) + { + IWICImagingFactory *factory; + IWICPalette *palette; + + hr = IWICBitmapFrameDecode_GetSize(framedecode, &width, &height); + ok(SUCCEEDED(hr), "GetSize failed, hr=%lx\n", hr); + ok(width == 2, "expected width=2, got %u\n", width); + ok(height == 1, "expected height=1, got %u\n", height); + + hr = IWICBitmapFrameDecode_GetResolution(framedecode, &dpiX, &dpiY); + ok(SUCCEEDED(hr), "GetResolution failed, hr=%lx\n", hr); + ok(fabs(dpiX - 72.0) < 0.01, "expected dpiX=72.0, got %f\n", dpiX); + ok(fabs(dpiY - 72.0) < 0.01, "expected dpiY=72.0, got %f\n", dpiY); + + hr = IWICBitmapFrameDecode_GetPixelFormat(framedecode, &guidresult); + ok(SUCCEEDED(hr), "GetPixelFormat failed, hr=%lx\n", hr); + ok(IsEqualGUID(&guidresult, &GUID_WICPixelFormat32bppBGR), "unexpected pixel format\n"); + + hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, + &IID_IWICImagingFactory, (void**)&factory); + ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%lx\n", hr); + if (SUCCEEDED(hr)) + { + hr = IWICImagingFactory_CreatePalette(factory, &palette); + ok(SUCCEEDED(hr), "CreatePalette failed, hr=%lx\n", hr); + if (SUCCEEDED(hr)) + { + hr = IWICBitmapDecoder_CopyPalette(decoder, palette); + ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "expected WINCODEC_ERR_PALETTEUNAVAILABLE, got %lx\n", hr); + + hr = IWICBitmapFrameDecode_CopyPalette(framedecode, palette); + ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "expected WINCODEC_ERR_PALETTEUNAVAILABLE, got %lx\n", hr); + + IWICPalette_Release(palette); + } + + IWICImagingFactory_Release(factory); + } + + rc.X = 0; + rc.Y = 0; + rc.Width = 2; + rc.Height = 1; + hr = IWICBitmapFrameDecode_CopyPixels(framedecode, &rc, 32, sizeof(imagedata), (BYTE*)imagedata); + ok(SUCCEEDED(hr), "CopyPixels failed, hr=%lx\n", hr); + ok(!memcmp(imagedata, expected_imagedata, sizeof(imagedata)), "unexpected image data\n"); + + IWICBitmapFrameDecode_Release(framedecode); + } + + IStream_Release(bmpstream); + } + + GlobalFree(hbmpdata); + } + + IWICBitmapDecoder_Release(decoder); +} + static void test_componentinfo(void) { IWICImagingFactory *factory; @@ -1340,6 +1476,7 @@ START_TEST(bmpformat) test_decode_4bpp(); test_decode_rle8(); test_decode_rle4(); + test_decode_bitfields(); test_componentinfo(); test_createfromstream(); test_create_decoder();