windowscodecs: Correctly handle 8bpp custom conversions.

Signed-off-by: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Signed-off-by: Esme Povirk <esme@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alistair Leslie-Hughes 2022-02-25 17:53:01 +11:00 committed by Alexandre Julliard
parent 15a3864f4d
commit 950f3c08ce
2 changed files with 147 additions and 21 deletions

View File

@ -69,6 +69,7 @@ struct pixelformatinfo {
enum pixelformat format; enum pixelformat format;
const WICPixelFormatGUID *guid; const WICPixelFormatGUID *guid;
copyfunc copy_function; copyfunc copy_function;
BOOL is_indexed_format;
}; };
typedef struct FormatConverter { typedef struct FormatConverter {
@ -1493,10 +1494,10 @@ static HRESULT copypixels_to_8bppIndexed(struct FormatConverter *This, const WIC
} }
static const struct pixelformatinfo supported_formats[] = { static const struct pixelformatinfo supported_formats[] = {
{format_1bppIndexed, &GUID_WICPixelFormat1bppIndexed, NULL}, {format_1bppIndexed, &GUID_WICPixelFormat1bppIndexed, NULL, TRUE},
{format_2bppIndexed, &GUID_WICPixelFormat2bppIndexed, NULL}, {format_2bppIndexed, &GUID_WICPixelFormat2bppIndexed, NULL, TRUE},
{format_4bppIndexed, &GUID_WICPixelFormat4bppIndexed, NULL}, {format_4bppIndexed, &GUID_WICPixelFormat4bppIndexed, NULL, TRUE},
{format_8bppIndexed, &GUID_WICPixelFormat8bppIndexed, copypixels_to_8bppIndexed}, {format_8bppIndexed, &GUID_WICPixelFormat8bppIndexed, copypixels_to_8bppIndexed, TRUE},
{format_BlackWhite, &GUID_WICPixelFormatBlackWhite, NULL}, {format_BlackWhite, &GUID_WICPixelFormatBlackWhite, NULL},
{format_2bppGray, &GUID_WICPixelFormat2bppGray, NULL}, {format_2bppGray, &GUID_WICPixelFormat2bppGray, NULL},
{format_4bppGray, &GUID_WICPixelFormat4bppGray, NULL}, {format_4bppGray, &GUID_WICPixelFormat4bppGray, NULL},
@ -1636,12 +1637,7 @@ static HRESULT WINAPI FormatConverter_CopyPalette(IWICFormatConverter *iface,
if (!This->palette) if (!This->palette)
{ {
HRESULT hr; if (This->dst_format->is_indexed_format) return WINCODEC_ERR_WRONGSTATE;
UINT bpp;
hr = get_pixelformat_bpp(This->dst_format->guid, &bpp);
if (hr != S_OK) return hr;
if (bpp <= 8) return WINCODEC_ERR_WRONGSTATE;
return IWICBitmapSource_CopyPalette(This->source, palette); 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), TRACE("(%p,%p,%s,%u,%p,%0.3f,%u)\n", iface, source, debugstr_guid(dstFormat),
dither, palette, alpha_threshold, palette_type); 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) if (!palette)
{ {
UINT bpp; UINT bpp;
@ -1703,18 +1706,21 @@ static HRESULT WINAPI FormatConverter_Initialize(IWICFormatConverter *iface,
case WICBitmapPaletteTypeCustom: case WICBitmapPaletteTypeCustom:
IWICPalette_Release(palette); IWICPalette_Release(palette);
palette = NULL; palette = NULL;
if (bpp <= 8) return E_INVALIDARG;
/* Indexed types require a palette */
if (dstinfo->is_indexed_format)
return E_INVALIDARG;
break; break;
case WICBitmapPaletteTypeMedianCut: case WICBitmapPaletteTypeMedianCut:
{ {
if (bpp <= 8) if (dstinfo->is_indexed_format)
res = IWICPalette_InitializeFromBitmap(palette, source, 1 << bpp, FALSE); res = IWICPalette_InitializeFromBitmap(palette, source, 1 << bpp, FALSE);
break; break;
} }
default: default:
if (bpp <= 8) if (dstinfo->is_indexed_format)
res = IWICPalette_InitializePredefined(palette, palette_type, FALSE); res = IWICPalette_InitializePredefined(palette, palette_type, FALSE);
break; break;
} }
@ -1747,14 +1753,6 @@ static HRESULT WINAPI FormatConverter_Initialize(IWICFormatConverter *iface,
goto end; 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) if (dstinfo->copy_function)
{ {
IWICBitmapSource_AddRef(source); IWICBitmapSource_AddRef(source);

View File

@ -538,6 +538,18 @@ static const float bits_32bppGrayFloat[] = {
static const struct bitmap_data testdata_32bppGrayFloat = { static const struct bitmap_data testdata_32bppGrayFloat = {
&GUID_WICPixelFormat32bppGrayFloat, 32, (const BYTE *)bits_32bppGrayFloat, 32, 2, 96.0, 96.0, &testdata_32bppGrayFloat_xp}; &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[] = { 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,
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); 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 typedef struct property_opt_test_data
{ {
LPCOLESTR name; LPCOLESTR name;
@ -1736,6 +1814,54 @@ static void test_converter_8bppIndexed(void)
ok(hr == WINCODEC_ERR_WRONGSTATE, "unexpected error %#x\n", hr); ok(hr == WINCODEC_ERR_WRONGSTATE, "unexpected error %#x\n", hr);
IWICFormatConverter_Release(converter); 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 */ /* empty palette + Custom type */
hr = IWICImagingFactory_CreateFormatConverter(factory, &converter); hr = IWICImagingFactory_CreateFormatConverter(factory, &converter);
ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr); ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr);
@ -1906,6 +2032,8 @@ START_TEST(converter)
test_invalid_conversion(); test_invalid_conversion();
test_default_converter(); test_default_converter();
test_converter_4bppGray();
test_converter_8bppGray();
test_converter_8bppIndexed(); test_converter_8bppIndexed();
test_encoder(&testdata_8bppIndexed, &CLSID_WICGifEncoder, test_encoder(&testdata_8bppIndexed, &CLSID_WICGifEncoder,