From: Jeff Smith whydoubt@gmail.com
Any time CanConvert returns FALSE for the output parameter, also return an appropriate failing result code.
This also adds tests for CanConvert. --- dlls/windowscodecs/converter.c | 40 +++++-- dlls/windowscodecs/tests/converter.c | 167 ++++++++++++++++++++++++++- 2 files changed, 199 insertions(+), 8 deletions(-)
diff --git a/dlls/windowscodecs/converter.c b/dlls/windowscodecs/converter.c index 39fcce61dd8..b5e253c98ea 100644 --- a/dlls/windowscodecs/converter.c +++ b/dlls/windowscodecs/converter.c @@ -59,6 +59,18 @@ enum pixelformat { format_48bppRGB, format_64bppRGBA, format_32bppCMYK, + format_8bppAlpha, + format_48bppBGR, + format_64bppRGB, + format_64bppBGRA, + format_64bppPRGBA, + format_64bppPBGRA, + format_32bppBGR101010, + format_96bppRGBFloat, + format_128bppRGBAFloat, + format_128bppPRGBAFloat, + format_128bppRGBFloat, + format_32bppR10G10B10A2, };
typedef HRESULT (*copyfunc)(struct FormatConverter *This, const WICRect *prc, @@ -1640,6 +1652,18 @@ static const struct pixelformatinfo supported_formats[] = { {format_48bppRGB, &GUID_WICPixelFormat48bppRGB, NULL}, {format_64bppRGBA, &GUID_WICPixelFormat64bppRGBA, copypixels_to_64bppRGBA}, {format_32bppCMYK, &GUID_WICPixelFormat32bppCMYK, NULL}, + {format_8bppAlpha, &GUID_WICPixelFormat8bppAlpha, NULL}, + {format_48bppBGR, &GUID_WICPixelFormat48bppBGR, NULL}, + {format_64bppRGB, &GUID_WICPixelFormat64bppRGB, NULL}, + {format_64bppBGRA, &GUID_WICPixelFormat64bppBGRA, NULL}, + {format_64bppPRGBA, &GUID_WICPixelFormat64bppPRGBA, NULL}, + {format_64bppPBGRA, &GUID_WICPixelFormat64bppPBGRA, NULL}, + {format_32bppBGR101010, &GUID_WICPixelFormat32bppBGR101010, NULL}, + {format_96bppRGBFloat, &GUID_WICPixelFormat96bppRGBFloat, NULL}, + {format_128bppRGBAFloat, &GUID_WICPixelFormat128bppRGBAFloat, NULL}, + {format_128bppPRGBAFloat, &GUID_WICPixelFormat128bppPRGBAFloat, NULL}, + {format_128bppRGBFloat, &GUID_WICPixelFormat128bppRGBFloat, NULL}, + {format_32bppR10G10B10A2, &GUID_WICPixelFormat32bppR10G10B10A2, NULL}, {0} };
@@ -1914,26 +1938,28 @@ static HRESULT WINAPI FormatConverter_CanConvert(IWICFormatConverter *iface, srcinfo = get_formatinfo(srcPixelFormat); if (!srcinfo) { - FIXME("Unsupported source format %s\n", debugstr_guid(srcPixelFormat)); + *pfCanConvert = FALSE; return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT; }
dstinfo = get_formatinfo(dstPixelFormat); if (!dstinfo) { - FIXME("Unsupported destination format %s\n", debugstr_guid(dstPixelFormat)); + *pfCanConvert = FALSE; return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT; }
- if (dstinfo->copy_function && - SUCCEEDED(dstinfo->copy_function(This, NULL, 0, 0, NULL, dstinfo->format))) - *pfCanConvert = TRUE; - else + if (!dstinfo->copy_function || + FAILED(dstinfo->copy_function(This, NULL, 0, 0, NULL, srcinfo->format))) { - FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(srcPixelFormat), debugstr_guid(dstPixelFormat)); + if (dstinfo->format != format_32bppR10G10B10A2 && + srcinfo->format != format_32bppCMYK && dstinfo->format != format_32bppCMYK) + FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(srcPixelFormat), debugstr_guid(dstPixelFormat)); *pfCanConvert = FALSE; + return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT; }
+ *pfCanConvert = TRUE; return S_OK; }
diff --git a/dlls/windowscodecs/tests/converter.c b/dlls/windowscodecs/tests/converter.c index f6cef841d56..82bfee47161 100644 --- a/dlls/windowscodecs/tests/converter.c +++ b/dlls/windowscodecs/tests/converter.c @@ -707,6 +707,170 @@ static void test_default_converter(void) DeleteTestBitmap(src_obj); }
+static void test_can_convert(void) +{ +#define WIC_PIXEL_FORMAT(fmt) #fmt, &GUID_WICPixelFormat ## fmt + static const struct test_data + { + const char *name; + const WICPixelFormatGUID *format; + BOOL src_valid; + BOOL dst_valid; + BOOL src_todo; + BOOL dst_todo; + BOOL src_broken; + } + td[] = + { + {WIC_PIXEL_FORMAT(Undefined)}, + {WIC_PIXEL_FORMAT(1bppIndexed), TRUE, TRUE, FALSE, TRUE}, + {WIC_PIXEL_FORMAT(2bppIndexed), TRUE, TRUE, FALSE, TRUE}, + {WIC_PIXEL_FORMAT(4bppIndexed), TRUE, TRUE, FALSE, TRUE}, + {WIC_PIXEL_FORMAT(8bppIndexed), TRUE, TRUE}, + {WIC_PIXEL_FORMAT(BlackWhite), TRUE, TRUE, FALSE, TRUE}, + {WIC_PIXEL_FORMAT(2bppGray), TRUE, TRUE, FALSE, TRUE}, + {WIC_PIXEL_FORMAT(4bppGray), TRUE, TRUE, FALSE, TRUE}, + {WIC_PIXEL_FORMAT(8bppGray), TRUE, TRUE}, + {WIC_PIXEL_FORMAT(16bppGray), TRUE, TRUE, FALSE, TRUE}, + + {WIC_PIXEL_FORMAT(8bppAlpha), TRUE, TRUE, TRUE, TRUE}, + + {WIC_PIXEL_FORMAT(16bppBGR555), TRUE, TRUE, FALSE, TRUE}, + {WIC_PIXEL_FORMAT(16bppBGR565), TRUE, TRUE, FALSE, TRUE}, + {WIC_PIXEL_FORMAT(16bppBGRA5551), TRUE, TRUE}, + {WIC_PIXEL_FORMAT(24bppBGR), TRUE, TRUE}, + {WIC_PIXEL_FORMAT(24bppRGB), TRUE, TRUE}, + {WIC_PIXEL_FORMAT(32bppBGR), TRUE, TRUE}, + {WIC_PIXEL_FORMAT(32bppBGRA), TRUE, TRUE}, + {WIC_PIXEL_FORMAT(32bppPBGRA), TRUE, TRUE}, + {WIC_PIXEL_FORMAT(32bppRGB), TRUE, TRUE}, + {WIC_PIXEL_FORMAT(32bppRGBA), TRUE, TRUE}, + {WIC_PIXEL_FORMAT(32bppPRGBA), TRUE, TRUE}, + {WIC_PIXEL_FORMAT(32bppGrayFloat), TRUE, TRUE}, + + {WIC_PIXEL_FORMAT(48bppRGB), TRUE, TRUE, FALSE, TRUE}, + {WIC_PIXEL_FORMAT(48bppBGR), TRUE, TRUE, TRUE, TRUE}, + {WIC_PIXEL_FORMAT(64bppRGB), TRUE, TRUE, TRUE, TRUE}, + {WIC_PIXEL_FORMAT(64bppRGBA), TRUE, TRUE}, + {WIC_PIXEL_FORMAT(64bppBGRA), TRUE, TRUE, TRUE, TRUE}, + {WIC_PIXEL_FORMAT(64bppPRGBA), TRUE, TRUE, TRUE, TRUE}, + {WIC_PIXEL_FORMAT(64bppPBGRA), TRUE, TRUE, TRUE, TRUE}, + + {WIC_PIXEL_FORMAT(16bppGrayFixedPoint)}, + {WIC_PIXEL_FORMAT(32bppBGR101010), TRUE, TRUE, TRUE, TRUE}, + {WIC_PIXEL_FORMAT(48bppRGBFixedPoint)}, + {WIC_PIXEL_FORMAT(48bppBGRFixedPoint)}, + {WIC_PIXEL_FORMAT(96bppRGBFixedPoint)}, + {WIC_PIXEL_FORMAT(96bppRGBFloat), TRUE, TRUE, TRUE, TRUE}, + {WIC_PIXEL_FORMAT(128bppRGBAFloat), TRUE, TRUE, TRUE, TRUE}, + {WIC_PIXEL_FORMAT(128bppPRGBAFloat), TRUE, TRUE, TRUE, TRUE}, + {WIC_PIXEL_FORMAT(128bppRGBFloat), TRUE, TRUE, TRUE, TRUE}, + + /* Not actually TODO, but it succeeds where Windows fails */ + {WIC_PIXEL_FORMAT(32bppCMYK), FALSE, FALSE, TRUE}, + + {WIC_PIXEL_FORMAT(64bppRGBAFixedPoint)}, + {WIC_PIXEL_FORMAT(64bppBGRAFixedPoint)}, + {WIC_PIXEL_FORMAT(64bppRGBFixedPoint)}, + {WIC_PIXEL_FORMAT(128bppRGBAFixedPoint)}, + {WIC_PIXEL_FORMAT(128bppRGBFixedPoint)}, + + {WIC_PIXEL_FORMAT(64bppRGBAHalf)}, + {WIC_PIXEL_FORMAT(64bppPRGBAHalf)}, + {WIC_PIXEL_FORMAT(64bppRGBHalf)}, + {WIC_PIXEL_FORMAT(48bppRGBHalf)}, + + {WIC_PIXEL_FORMAT(32bppRGBE)}, + + {WIC_PIXEL_FORMAT(16bppGrayHalf)}, + {WIC_PIXEL_FORMAT(32bppGrayFixedPoint)}, + + {WIC_PIXEL_FORMAT(32bppRGBA1010102)}, + {WIC_PIXEL_FORMAT(32bppRGBA1010102XR)}, + + /* Starting with Windows 10 v1809, this works as a source format */ + {WIC_PIXEL_FORMAT(32bppR10G10B10A2), TRUE, FALSE, TRUE, FALSE, TRUE}, + + {WIC_PIXEL_FORMAT(32bppR10G10B10A2HDR10)}, + + {WIC_PIXEL_FORMAT(64bppCMYK)}, + + {WIC_PIXEL_FORMAT(24bpp3Channels)}, + {WIC_PIXEL_FORMAT(32bpp4Channels)}, + {WIC_PIXEL_FORMAT(40bpp5Channels)}, + {WIC_PIXEL_FORMAT(48bpp6Channels)}, + {WIC_PIXEL_FORMAT(56bpp7Channels)}, + {WIC_PIXEL_FORMAT(64bpp8Channels)}, + + {WIC_PIXEL_FORMAT(48bpp3Channels)}, + {WIC_PIXEL_FORMAT(64bpp4Channels)}, + {WIC_PIXEL_FORMAT(80bpp5Channels)}, + {WIC_PIXEL_FORMAT(96bpp6Channels)}, + {WIC_PIXEL_FORMAT(112bpp7Channels)}, + {WIC_PIXEL_FORMAT(128bpp8Channels)}, + + {WIC_PIXEL_FORMAT(40bppCMYKAlpha)}, + {WIC_PIXEL_FORMAT(80bppCMYKAlpha)}, + + {WIC_PIXEL_FORMAT(32bpp3ChannelsAlpha)}, + {WIC_PIXEL_FORMAT(40bpp4ChannelsAlpha)}, + {WIC_PIXEL_FORMAT(48bpp5ChannelsAlpha)}, + {WIC_PIXEL_FORMAT(56bpp6ChannelsAlpha)}, + {WIC_PIXEL_FORMAT(64bpp7ChannelsAlpha)}, + {WIC_PIXEL_FORMAT(72bpp8ChannelsAlpha)}, + + {WIC_PIXEL_FORMAT(64bpp3ChannelsAlpha)}, + {WIC_PIXEL_FORMAT(80bpp4ChannelsAlpha)}, + {WIC_PIXEL_FORMAT(96bpp5ChannelsAlpha)}, + {WIC_PIXEL_FORMAT(112bpp6ChannelsAlpha)}, + {WIC_PIXEL_FORMAT(128bpp7ChannelsAlpha)}, + {WIC_PIXEL_FORMAT(144bpp8ChannelsAlpha)}, + + {WIC_PIXEL_FORMAT(8bppY)}, + {WIC_PIXEL_FORMAT(8bppCb)}, + {WIC_PIXEL_FORMAT(8bppCr)}, + {WIC_PIXEL_FORMAT(16bppCbCr)}, + + {WIC_PIXEL_FORMAT(16bppYQuantizedDctCoefficients)}, + {WIC_PIXEL_FORMAT(16bppCbQuantizedDctCoefficients)}, + {WIC_PIXEL_FORMAT(16bppCrQuantizedDctCoefficients)}, + }; +#undef WIC_PIXEL_FORMAT + BOOL can_convert, can_native, can_broken, can_wine; + HRESULT hr, expect_hr, broken_hr; + IWICFormatConverter *converter; + UINT i, j; + + hr = CoCreateInstance(&CLSID_WICDefaultFormatConverter, NULL, CLSCTX_INPROC_SERVER, + &IID_IWICFormatConverter, (void**)&converter); + ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%lx\n", hr); + if (FAILED(hr)) + return; + + for (i = 0; i < ARRAY_SIZE(td); i++) + { + for (j = 0; j < ARRAY_SIZE(td); j++) + { + can_native = td[i].src_valid && td[j].dst_valid; + can_broken = (td[i].src_valid ^ td[i].src_broken) && td[j].dst_valid; + can_wine = (td[i].src_valid ^ td[i].src_todo) && (td[j].dst_valid ^ td[j].dst_todo); + expect_hr = can_native ? S_OK : WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT; + broken_hr = can_broken ? S_OK : WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT; + + can_convert = -1; + hr = IWICFormatConverter_CanConvert(converter, td[i].format, td[j].format, &can_convert); + todo_wine_if (can_native != can_wine) { + ok(hr == expect_hr || broken(hr == broken_hr), + "CanConvert (%s -> %s) returned %lx\n", td[i].name, td[j].name, hr); + ok(can_convert == can_native || broken(can_convert == can_broken), + "expected %i, got %i \n", can_native, can_convert); + } + } + } + + IWICFormatConverter_Release(converter); +} + static void test_converter_4bppGray(void) { BitmapTestSrc *src_obj; @@ -723,7 +887,7 @@ static void test_converter_4bppGray(void) { hr = IWICFormatConverter_CanConvert(converter, &GUID_WICPixelFormat32bppBGRA, &GUID_WICPixelFormat4bppGray, &can_convert); - ok(SUCCEEDED(hr), "CanConvert returned %lx\n", hr); + todo_wine ok(SUCCEEDED(hr), "CanConvert returned %lx\n", hr); todo_wine ok(can_convert, "expected TRUE, got %i\n", can_convert);
hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface, @@ -2088,6 +2252,7 @@ START_TEST(converter)
test_invalid_conversion(); test_default_converter(); + test_can_convert(); test_converter_4bppGray(); test_converter_8bppGray(); test_converter_8bppIndexed();