diff --git a/dlls/windowscodecs/converter.c b/dlls/windowscodecs/converter.c index a401d1cdc4a..8abba2dec52 100644 --- a/dlls/windowscodecs/converter.c +++ b/dlls/windowscodecs/converter.c @@ -69,6 +69,7 @@ struct pixelformatinfo { enum pixelformat format; const WICPixelFormatGUID *guid; copyfunc copy_function; + BOOL is_indexed_format; }; typedef struct FormatConverter { @@ -1493,10 +1494,10 @@ static HRESULT copypixels_to_8bppIndexed(struct FormatConverter *This, const WIC } static const struct pixelformatinfo supported_formats[] = { - {format_1bppIndexed, &GUID_WICPixelFormat1bppIndexed, NULL}, - {format_2bppIndexed, &GUID_WICPixelFormat2bppIndexed, NULL}, - {format_4bppIndexed, &GUID_WICPixelFormat4bppIndexed, NULL}, - {format_8bppIndexed, &GUID_WICPixelFormat8bppIndexed, copypixels_to_8bppIndexed}, + {format_1bppIndexed, &GUID_WICPixelFormat1bppIndexed, NULL, TRUE}, + {format_2bppIndexed, &GUID_WICPixelFormat2bppIndexed, NULL, TRUE}, + {format_4bppIndexed, &GUID_WICPixelFormat4bppIndexed, NULL, TRUE}, + {format_8bppIndexed, &GUID_WICPixelFormat8bppIndexed, copypixels_to_8bppIndexed, TRUE}, {format_BlackWhite, &GUID_WICPixelFormatBlackWhite, NULL}, {format_2bppGray, &GUID_WICPixelFormat2bppGray, NULL}, {format_4bppGray, &GUID_WICPixelFormat4bppGray, NULL}, @@ -1636,12 +1637,7 @@ static HRESULT WINAPI FormatConverter_CopyPalette(IWICFormatConverter *iface, if (!This->palette) { - HRESULT hr; - UINT bpp; - - hr = get_pixelformat_bpp(This->dst_format->guid, &bpp); - if (hr != S_OK) return hr; - if (bpp <= 8) return WINCODEC_ERR_WRONGSTATE; + if (This->dst_format->is_indexed_format) return WINCODEC_ERR_WRONGSTATE; return IWICBitmapSource_CopyPalette(This->source, palette); } @@ -1689,6 +1685,13 @@ static HRESULT WINAPI FormatConverter_Initialize(IWICFormatConverter *iface, TRACE("(%p,%p,%s,%u,%p,%0.3f,%u)\n", iface, source, debugstr_guid(dstFormat), dither, palette, alpha_threshold, palette_type); + dstinfo = get_formatinfo(dstFormat); + if (!dstinfo) + { + FIXME("Unsupported destination format %s\n", debugstr_guid(dstFormat)); + return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT; + } + if (!palette) { UINT bpp; @@ -1703,18 +1706,21 @@ static HRESULT WINAPI FormatConverter_Initialize(IWICFormatConverter *iface, case WICBitmapPaletteTypeCustom: IWICPalette_Release(palette); palette = NULL; - if (bpp <= 8) return E_INVALIDARG; + + /* Indexed types require a palette */ + if (dstinfo->is_indexed_format) + return E_INVALIDARG; break; case WICBitmapPaletteTypeMedianCut: { - if (bpp <= 8) + if (dstinfo->is_indexed_format) res = IWICPalette_InitializeFromBitmap(palette, source, 1 << bpp, FALSE); break; } default: - if (bpp <= 8) + if (dstinfo->is_indexed_format) res = IWICPalette_InitializePredefined(palette, palette_type, FALSE); break; } @@ -1747,14 +1753,6 @@ static HRESULT WINAPI FormatConverter_Initialize(IWICFormatConverter *iface, goto end; } - dstinfo = get_formatinfo(dstFormat); - if (!dstinfo) - { - res = WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT; - FIXME("Unsupported destination format %s\n", debugstr_guid(dstFormat)); - goto end; - } - if (dstinfo->copy_function) { IWICBitmapSource_AddRef(source); diff --git a/dlls/windowscodecs/tests/converter.c b/dlls/windowscodecs/tests/converter.c index f0672fceaf8..ca26b5204bc 100644 --- a/dlls/windowscodecs/tests/converter.c +++ b/dlls/windowscodecs/tests/converter.c @@ -538,6 +538,18 @@ static const float bits_32bppGrayFloat[] = { static const struct bitmap_data testdata_32bppGrayFloat = { &GUID_WICPixelFormat32bppGrayFloat, 32, (const BYTE *)bits_32bppGrayFloat, 32, 2, 96.0, 96.0, &testdata_32bppGrayFloat_xp}; +static const BYTE bits_4bppGray_xp[] = { + 77,112,77,112,77,112,77,112,77,112,77,112,77,112,77,112,249, + 239,249,239,249,239,249,239,249,239,249,239,249,239,249,239}; +static const struct bitmap_data testdata_4bppGray_xp = { + &GUID_WICPixelFormat4bppGray, 4, bits_4bppGray_xp, 32, 2, 96.0, 96.0}; + +static const BYTE bits_4bppGray[] = { + 77,112,77,112,77,112,77,112,77,112,77,112,77,112,77,112,249, + 239,249,239,249,239,249,239,249,239,249,239,249,239,249,239}; +static const struct bitmap_data testdata_4bppGray = { + &GUID_WICPixelFormat4bppGray, 4, bits_4bppGray, 32, 2, 96.0, 96.0, &testdata_4bppGray_xp}; + static const BYTE bits_8bppGray_xp[] = { 29,150,76,0,29,150,76,0,29,150,76,0,29,150,76,0, 29,150,76,0,29,150,76,0,29,150,76,0,29,150,76,0, @@ -637,6 +649,72 @@ static void test_default_converter(void) DeleteTestBitmap(src_obj); } +static void test_converter_4bppGray(void) +{ + BitmapTestSrc *src_obj; + IWICFormatConverter *converter; + BOOL can_convert = TRUE; + HRESULT hr; + + CreateTestBitmap(&testdata_32bppBGRA, &src_obj); + + hr = CoCreateInstance(&CLSID_WICDefaultFormatConverter, NULL, CLSCTX_INPROC_SERVER, + &IID_IWICFormatConverter, (void**)&converter); + ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr); + if (SUCCEEDED(hr)) + { + hr = IWICFormatConverter_CanConvert(converter, &GUID_WICPixelFormat32bppBGRA, + &GUID_WICPixelFormat4bppGray, &can_convert); + ok(SUCCEEDED(hr), "CanConvert returned %x\n", hr); + todo_wine ok(can_convert, "expected TRUE, got %i\n", can_convert); + + hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface, + &GUID_WICPixelFormat4bppGray, WICBitmapDitherTypeNone, NULL, 0.0, + WICBitmapPaletteTypeCustom); + todo_wine ok(SUCCEEDED(hr), "Initialize returned %x\n", hr); + + if (SUCCEEDED(hr)) + compare_bitmap_data(&testdata_32bppBGRA, &testdata_4bppGray, (IWICBitmapSource*)converter, "4bppGray converter"); + + IWICFormatConverter_Release(converter); + } + + DeleteTestBitmap(src_obj); +} + +static void test_converter_8bppGray(void) +{ + BitmapTestSrc *src_obj; + IWICFormatConverter *converter; + BOOL can_convert = TRUE; + HRESULT hr; + + CreateTestBitmap(&testdata_32bppBGRA, &src_obj); + + hr = CoCreateInstance(&CLSID_WICDefaultFormatConverter, NULL, CLSCTX_INPROC_SERVER, + &IID_IWICFormatConverter, (void**)&converter); + ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr); + if (SUCCEEDED(hr)) + { + hr = IWICFormatConverter_CanConvert(converter, &GUID_WICPixelFormat32bppBGRA, + &GUID_WICPixelFormat8bppGray, &can_convert); + ok(SUCCEEDED(hr), "CanConvert returned %x\n", hr); + ok(can_convert, "expected TRUE, got %i\n", can_convert); + + hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface, + &GUID_WICPixelFormat8bppGray, WICBitmapDitherTypeNone, NULL, 0.0, + WICBitmapPaletteTypeCustom); + ok(SUCCEEDED(hr), "Initialize returned %x\n", hr); + + if (SUCCEEDED(hr)) + compare_bitmap_data(&testdata_32bppBGRA, &testdata_8bppGray, (IWICBitmapSource*)converter, "8bppGray converter"); + + IWICFormatConverter_Release(converter); + } + + DeleteTestBitmap(src_obj); +} + typedef struct property_opt_test_data { LPCOLESTR name; @@ -1736,6 +1814,54 @@ static void test_converter_8bppIndexed(void) ok(hr == WINCODEC_ERR_WRONGSTATE, "unexpected error %#x\n", hr); IWICFormatConverter_Release(converter); + hr = IWICImagingFactory_CreateFormatConverter(factory, &converter); + ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr); + hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface, + &GUID_WICPixelFormat4bppIndexed, WICBitmapDitherTypeNone, + NULL, 0.0, WICBitmapPaletteTypeCustom); + ok(hr == E_INVALIDARG, "unexpected error %#x\n", hr); + IWICFormatConverter_Release(converter); + + hr = IWICImagingFactory_CreateFormatConverter(factory, &converter); + ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr); + hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface, + &GUID_WICPixelFormat2bppIndexed, WICBitmapDitherTypeNone, + NULL, 0.0, WICBitmapPaletteTypeCustom); + ok(hr == E_INVALIDARG, "unexpected error %#x\n", hr); + IWICFormatConverter_Release(converter); + + hr = IWICImagingFactory_CreateFormatConverter(factory, &converter); + ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr); + hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface, + &GUID_WICPixelFormat1bppIndexed, WICBitmapDitherTypeNone, + NULL, 0.0, WICBitmapPaletteTypeCustom); + ok(hr == E_INVALIDARG, "unexpected error %#x\n", hr); + IWICFormatConverter_Release(converter); + + hr = IWICImagingFactory_CreateFormatConverter(factory, &converter); + ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr); + hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface, + &GUID_WICPixelFormat1bppIndexed, WICBitmapDitherTypeNone, + NULL, 0.0, WICBitmapPaletteTypeMedianCut); + todo_wine ok(hr == S_OK, "unexpected error %#x\n", hr); + IWICFormatConverter_Release(converter); + + hr = IWICImagingFactory_CreateFormatConverter(factory, &converter); + ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr); + hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface, + &GUID_WICPixelFormat1bppIndexed, WICBitmapDitherTypeNone, + NULL, 0.0, WICBitmapPaletteTypeFixedBW); + todo_wine ok(hr == S_OK, "unexpected error %#x\n", hr); + IWICFormatConverter_Release(converter); + + hr = IWICImagingFactory_CreateFormatConverter(factory, &converter); + ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr); + hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface, + &GUID_WICPixelFormat1bppIndexed, WICBitmapDitherTypeNone, + NULL, 0.0, WICBitmapPaletteTypeFixedHalftone8); + todo_wine ok(hr == E_INVALIDARG, "unexpected error %#x\n", hr); + IWICFormatConverter_Release(converter); + /* empty palette + Custom type */ hr = IWICImagingFactory_CreateFormatConverter(factory, &converter); ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr); @@ -1906,6 +2032,8 @@ START_TEST(converter) test_invalid_conversion(); test_default_converter(); + test_converter_4bppGray(); + test_converter_8bppGray(); test_converter_8bppIndexed(); test_encoder(&testdata_8bppIndexed, &CLSID_WICGifEncoder,