From: Dmitry Timoshkov Subject: [PATCH] windowscodecs: Add support for 32bppRGB, 32bppRGBA and 32bppPRGBA to format converter. Message-Id: <20190215101044.7ed2c8baed1ed264c17621f6@baikal.ru> Date: Fri, 15 Feb 2019 10:10:44 +0800 Signed-off-by: Dmitry Timoshkov --- dlls/windowscodecs/converter.c | 112 +++++++++++++++++++++++++++ dlls/windowscodecs/info.c | 2 + dlls/windowscodecs/regsvr.c | 36 +++++++++ dlls/windowscodecs/tests/converter.c | 45 ++++++++++- 4 files changed, 194 insertions(+), 1 deletion(-) diff --git a/dlls/windowscodecs/converter.c b/dlls/windowscodecs/converter.c index 83f1339d0c..9083aa04f7 100644 --- a/dlls/windowscodecs/converter.c +++ b/dlls/windowscodecs/converter.c @@ -53,8 +53,11 @@ enum pixelformat { format_24bppRGB, format_32bppGrayFloat, format_32bppBGR, + format_32bppRGB, format_32bppBGRA, + format_32bppRGBA, format_32bppPBGRA, + format_32bppPRGBA, format_48bppRGB, format_64bppRGBA, format_32bppCMYK, @@ -858,6 +861,63 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe } } +static HRESULT copypixels_to_32bppRGBA(struct FormatConverter *This, const WICRect *prc, + UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) +{ + HRESULT hr; + + switch (source_format) + { + case format_32bppRGB: + if (prc) + { + INT x, y; + + hr = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); + if (FAILED(hr)) return hr; + + /* set all alpha values to 255 */ + for (y=0; yHeight; y++) + for (x=0; xWidth; x++) + pbBuffer[cbStride*y+4*x+3] = 0xff; + } + return S_OK; + + case format_32bppRGBA: + if (prc) + return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); + return S_OK; + + case format_32bppPRGBA: + if (prc) + { + INT x, y; + + hr = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); + if (FAILED(hr)) return hr; + + for (y=0; yHeight; y++) + for (x=0; xWidth; x++) + { + BYTE alpha = pbBuffer[cbStride*y+4*x+3]; + if (alpha != 0 && alpha != 255) + { + pbBuffer[cbStride*y+4*x] = pbBuffer[cbStride*y+4*x] * 255 / alpha; + pbBuffer[cbStride*y+4*x+1] = pbBuffer[cbStride*y+4*x+1] * 255 / alpha; + pbBuffer[cbStride*y+4*x+2] = pbBuffer[cbStride*y+4*x+2] * 255 / alpha; + } + } + } + return S_OK; + + default: + hr = copypixels_to_32bppBGRA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format); + if (SUCCEEDED(hr) && prc) + reverse_bgr8(4, pbBuffer, prc->Width, prc->Height, cbStride); + return hr; + } +} + static HRESULT copypixels_to_32bppBGR(struct FormatConverter *This, const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) { @@ -874,6 +934,22 @@ static HRESULT copypixels_to_32bppBGR(struct FormatConverter *This, const WICRec } } +static HRESULT copypixels_to_32bppRGB(struct FormatConverter *This, const WICRect *prc, + UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) +{ + switch (source_format) + { + case format_32bppRGB: + case format_32bppRGBA: + case format_32bppPRGBA: + if (prc) + return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); + return S_OK; + default: + return copypixels_to_32bppRGBA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format); + } +} + static HRESULT copypixels_to_32bppPBGRA(struct FormatConverter *This, const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) { @@ -907,6 +983,39 @@ static HRESULT copypixels_to_32bppPBGRA(struct FormatConverter *This, const WICR } } +static HRESULT copypixels_to_32bppPRGBA(struct FormatConverter *This, const WICRect *prc, + UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) +{ + HRESULT hr; + + switch (source_format) + { + case format_32bppPRGBA: + if (prc) + return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); + return S_OK; + default: + hr = copypixels_to_32bppRGBA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format); + if (SUCCEEDED(hr) && prc) + { + INT x, y; + + for (y=0; yHeight; y++) + for (x=0; xWidth; x++) + { + BYTE alpha = pbBuffer[cbStride*y+4*x+3]; + if (alpha != 255) + { + pbBuffer[cbStride*y+4*x] = pbBuffer[cbStride*y+4*x] * alpha / 255; + pbBuffer[cbStride*y+4*x+1] = pbBuffer[cbStride*y+4*x+1] * alpha / 255; + pbBuffer[cbStride*y+4*x+2] = pbBuffer[cbStride*y+4*x+2] * alpha / 255; + } + } + } + return hr; + } +} + static HRESULT copypixels_to_24bppBGR(struct FormatConverter *This, const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) { @@ -1326,8 +1435,11 @@ static const struct pixelformatinfo supported_formats[] = { {format_24bppRGB, &GUID_WICPixelFormat24bppRGB, copypixels_to_24bppRGB}, {format_32bppGrayFloat, &GUID_WICPixelFormat32bppGrayFloat, copypixels_to_32bppGrayFloat}, {format_32bppBGR, &GUID_WICPixelFormat32bppBGR, copypixels_to_32bppBGR}, + {format_32bppRGB, &GUID_WICPixelFormat32bppRGB, copypixels_to_32bppRGB}, {format_32bppBGRA, &GUID_WICPixelFormat32bppBGRA, copypixels_to_32bppBGRA}, + {format_32bppRGBA, &GUID_WICPixelFormat32bppRGBA, copypixels_to_32bppRGBA}, {format_32bppPBGRA, &GUID_WICPixelFormat32bppPBGRA, copypixels_to_32bppPBGRA}, + {format_32bppPRGBA, &GUID_WICPixelFormat32bppPRGBA, copypixels_to_32bppPRGBA}, {format_48bppRGB, &GUID_WICPixelFormat48bppRGB, NULL}, {format_64bppRGBA, &GUID_WICPixelFormat64bppRGBA, NULL}, {format_32bppCMYK, &GUID_WICPixelFormat32bppCMYK, NULL}, diff --git a/dlls/windowscodecs/info.c b/dlls/windowscodecs/info.c index 9bec30fcea..0a86266396 100644 --- a/dlls/windowscodecs/info.c +++ b/dlls/windowscodecs/info.c @@ -2483,6 +2483,8 @@ HRESULT WINAPI WICConvertBitmapSource(REFWICPixelFormatGUID dstFormat, IWICBitma BOOL canconvert; ULONG num_fetched; + TRACE("%s,%p,%p\n", debugstr_guid(dstFormat), pISrc, ppIDst); + res = IWICBitmapSource_GetPixelFormat(pISrc, &srcFormat); if (FAILED(res)) return res; diff --git a/dlls/windowscodecs/regsvr.c b/dlls/windowscodecs/regsvr.c index 9a580c67c5..c8338f1bea 100644 --- a/dlls/windowscodecs/regsvr.c +++ b/dlls/windowscodecs/regsvr.c @@ -1463,8 +1463,11 @@ static GUID const * const converter_formats[] = { &GUID_WICPixelFormat24bppBGR, &GUID_WICPixelFormat24bppRGB, &GUID_WICPixelFormat32bppBGR, + &GUID_WICPixelFormat32bppRGB, &GUID_WICPixelFormat32bppBGRA, + &GUID_WICPixelFormat32bppRGBA, &GUID_WICPixelFormat32bppPBGRA, + &GUID_WICPixelFormat32bppPRGBA, &GUID_WICPixelFormat32bppGrayFloat, &GUID_WICPixelFormat48bppRGB, &GUID_WICPixelFormat64bppRGBA, @@ -1928,6 +1931,17 @@ static struct regsvr_pixelformat const pixelformat_list[] = { WICPixelFormatNumericRepresentationUnsignedInteger, 0 }, + { &GUID_WICPixelFormat32bppRGB, + "The Wine Project", + "32bpp RGB", + NULL, /* no version */ + &GUID_VendorMicrosoft, + 32, /* bitsperpixel */ + 3, /* channel count */ + channel_masks_8bit, + WICPixelFormatNumericRepresentationUnsignedInteger, + 0 + }, { &GUID_WICPixelFormat32bppBGRA, "The Wine Project", "32bpp BGRA", @@ -1939,6 +1953,17 @@ static struct regsvr_pixelformat const pixelformat_list[] = { WICPixelFormatNumericRepresentationUnsignedInteger, 1 }, + { &GUID_WICPixelFormat32bppRGBA, + "The Wine Project", + "32bpp RGBA", + NULL, /* no version */ + &GUID_VendorMicrosoft, + 32, /* bitsperpixel */ + 4, /* channel count */ + channel_masks_8bit, + WICPixelFormatNumericRepresentationUnsignedInteger, + 1 + }, { &GUID_WICPixelFormat32bppPBGRA, "The Wine Project", "32bpp PBGRA", @@ -1950,6 +1975,17 @@ static struct regsvr_pixelformat const pixelformat_list[] = { WICPixelFormatNumericRepresentationUnsignedInteger, 1 }, + { &GUID_WICPixelFormat32bppPRGBA, + "The Wine Project", + "32bpp PRGBA", + NULL, /* no version */ + &GUID_VendorMicrosoft, + 32, /* bitsperpixel */ + 4, /* channel count */ + channel_masks_8bit, + WICPixelFormatNumericRepresentationUnsignedInteger, + 1 + }, { &GUID_WICPixelFormat32bppGrayFloat, "The Wine Project", "32bpp GrayFloat", diff --git a/dlls/windowscodecs/tests/converter.c b/dlls/windowscodecs/tests/converter.c index 1cfa29b4df..455c6ae2e6 100644 --- a/dlls/windowscodecs/tests/converter.c +++ b/dlls/windowscodecs/tests/converter.c @@ -294,6 +294,21 @@ static BOOL compare_bits(const struct bitmap_data *expect, UINT buffersize, cons if (!equal && expect->alt_data) equal = compare_bits(expect->alt_data, buffersize, converted_bits); + if (!equal && winetest_debug > 1) + { + UINT i, bps; + bps = expect->bpp / 8; + if (!bps) bps = buffersize; + printf("converted_bits (%u bytes):\n ", buffersize); + for (i = 0; i < buffersize; i++) + { + printf("%u,", converted_bits[i]); + if (!((i + 1) % 32)) printf("\n "); + else if (!((i+1) % bps)) printf(" "); + } + printf("\n"); + } + return equal; } @@ -441,6 +456,10 @@ static const BYTE bits_32bppBGR[] = { 0,255,255,80, 255,0,255,80, 255,255,0,80, 255,255,255,80, 0,255,255,80, 255,0,255,80, 255,255,0,80, 255,255,255,80}; static const struct bitmap_data testdata_32bppBGR = { &GUID_WICPixelFormat32bppBGR, 32, bits_32bppBGR, 32, 2, 96.0, 96.0}; +static const struct bitmap_data testdata_32bppBGRA80 = { + &GUID_WICPixelFormat32bppBGRA, 32, bits_32bppBGR, 32, 2, 96.0, 96.0}; +static const struct bitmap_data testdata_32bppRGBA80 = { + &GUID_WICPixelFormat32bppRGBA, 32, bits_32bppBGR, 32, 2, 96.0, 96.0}; static const BYTE bits_32bppBGRA[] = { 255,0,0,255, 0,255,0,255, 0,0,255,255, 0,0,0,255, 255,0,0,255, 0,255,0,255, 0,0,255,255, 0,0,0,255, @@ -453,6 +472,24 @@ static const BYTE bits_32bppBGRA[] = { 0,255,255,255, 255,0,255,255, 255,255,0,255, 255,255,255,255, 0,255,255,255, 255,0,255,255, 255,255,0,255, 255,255,255,255}; static const struct bitmap_data testdata_32bppBGRA = { &GUID_WICPixelFormat32bppBGRA, 32, bits_32bppBGRA, 32, 2, 96.0, 96.0}; +static const struct bitmap_data testdata_32bppRGBA = { + &GUID_WICPixelFormat32bppRGBA, 32, bits_32bppBGRA, 32, 2, 96.0, 96.0}; +static const struct bitmap_data testdata_32bppRGB = { + &GUID_WICPixelFormat32bppRGB, 32, bits_32bppBGRA, 32, 2, 96.0, 96.0}; + +static const BYTE bits_32bppPBGRA[] = { + 80,0,0,80, 0,80,0,80, 0,0,80,80, 0,0,0,80, 80,0,0,80, 0,80,0,80, 0,0,80,80, 0,0,0,80, + 80,0,0,80, 0,80,0,80, 0,0,80,80, 0,0,0,80, 80,0,0,80, 0,80,0,80, 0,0,80,80, 0,0,0,80, + 80,0,0,80, 0,80,0,80, 0,0,80,80, 0,0,0,80, 80,0,0,80, 0,80,0,80, 0,0,80,80, 0,0,0,80, + 80,0,0,80, 0,80,0,80, 0,0,80,80, 0,0,0,80, 80,0,0,80, 0,80,0,80, 0,0,80,80, 0,0,0,80, + 0,80,80,80, 80,0,80,80, 80,80,0,80, 80,80,80,80, 0,80,80,80, 80,0,80,80, 80,80,0,80, 80,80,80,80, + 0,80,80,80, 80,0,80,80, 80,80,0,80, 80,80,80,80, 0,80,80,80, 80,0,80,80, 80,80,0,80, 80,80,80,80, + 0,80,80,80, 80,0,80,80, 80,80,0,80, 80,80,80,80, 0,80,80,80, 80,0,80,80, 80,80,0,80, 80,80,80,80, + 0,80,80,80, 80,0,80,80, 80,80,0,80, 80,80,80,80, 0,80,80,80, 80,0,80,80, 80,80,0,80, 80,80,80,80}; +static const struct bitmap_data testdata_32bppPBGRA = { + &GUID_WICPixelFormat32bppPBGRA, 32, bits_32bppPBGRA, 32, 2, 96.0, 96.0}; +static const struct bitmap_data testdata_32bppPRGBA = { + &GUID_WICPixelFormat32bppPRGBA, 32, bits_32bppPBGRA, 32, 2, 96.0, 96.0}; /* XP and 2003 use linear color conversion, later versions use sRGB gamma */ static const float bits_32bppGrayFloat_xp[] = { @@ -518,7 +555,7 @@ static void test_conversion(const struct bitmap_data *src, const struct bitmap_d hr = WICConvertBitmapSource(dst->format, &src_obj->IWICBitmapSource_iface, &dst_bitmap); todo_wine_if (todo) ok(hr == S_OK || - broken(hr == E_INVALIDARG) /* XP */, "WICConvertBitmapSource(%s) failed, hr=%x\n", name, hr); + broken(hr == E_INVALIDARG || hr == WINCODEC_ERR_COMPONENTNOTFOUND) /* XP */, "WICConvertBitmapSource(%s) failed, hr=%x\n", name, hr); if (hr == S_OK) { @@ -1751,6 +1788,12 @@ START_TEST(converter) test_conversion(&testdata_32bppBGRA, &testdata_32bppBGR, "BGRA -> BGR", FALSE); test_conversion(&testdata_32bppBGR, &testdata_32bppBGRA, "BGR -> BGRA", FALSE); test_conversion(&testdata_32bppBGRA, &testdata_32bppBGRA, "BGRA -> BGRA", FALSE); + test_conversion(&testdata_32bppBGRA80, &testdata_32bppPBGRA, "BGRA -> PBGRA", FALSE); + + test_conversion(&testdata_32bppRGBA, &testdata_32bppRGB, "RGBA -> RGB", FALSE); + test_conversion(&testdata_32bppRGB, &testdata_32bppRGBA, "RGB -> RGBA", FALSE); + test_conversion(&testdata_32bppRGBA, &testdata_32bppRGBA, "RGBA -> RGBA", FALSE); + test_conversion(&testdata_32bppRGBA80, &testdata_32bppPRGBA, "RGBA -> PRGBA", FALSE); test_conversion(&testdata_24bppBGR, &testdata_24bppBGR, "24bppBGR -> 24bppBGR", FALSE); test_conversion(&testdata_24bppBGR, &testdata_24bppRGB, "24bppBGR -> 24bppRGB", FALSE); -- 2.20.1