[PATCH v3] windowscodecs: Correctly handle 8bpp custom conversions

Alistair Leslie-Hughes leslie_alistair at hotmail.com
Fri Feb 25 00:53:01 CST 2022


Signed-off-by: Alistair Leslie-Hughes <leslie_alistair at hotmail.com>
---
 dlls/windowscodecs/converter.c       |  40 ++++-----
 dlls/windowscodecs/tests/converter.c | 128 +++++++++++++++++++++++++++
 2 files changed, 147 insertions(+), 21 deletions(-)

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,
-- 
2.34.1




More information about the wine-devel mailing list