[PATCH 0/1] MR9816: windowscodecs: Add support for converting 8bpp indexed to 24bpp format.
From: Dmitry Timoshkov <dmitry@baikal.ru> Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=59155 Signed-off-by: Dmitry Timoshkov <dmitry@baikal.ru> --- dlls/windowscodecs/converter.c | 119 ++++++++++++++++++++++++++- dlls/windowscodecs/tests/converter.c | 13 +-- 2 files changed, 125 insertions(+), 7 deletions(-) diff --git a/dlls/windowscodecs/converter.c b/dlls/windowscodecs/converter.c index d6be5920ea2..9ad3fe14f66 100644 --- a/dlls/windowscodecs/converter.c +++ b/dlls/windowscodecs/converter.c @@ -1314,6 +1314,64 @@ static HRESULT copypixels_to_24bppBGR(struct FormatConverter *This, const WICRec return res; } return S_OK; + + case format_8bppIndexed: + if (prc) + { + HRESULT res; + INT x, y; + BYTE *srcdata; + UINT srcstride, srcdatasize; + const BYTE *srcrow; + const BYTE *srcbyte; + BYTE *dstrow; + BYTE *dstpixel; + WICColor colors[256]; + IWICPalette *palette; + UINT actualcolors; + + res = PaletteImpl_Create(&palette); + if (FAILED(res)) return res; + + res = IWICBitmapSource_CopyPalette(This->source, palette); + if (SUCCEEDED(res)) + res = IWICPalette_GetColors(palette, 256, colors, &actualcolors); + + IWICPalette_Release(palette); + + if (FAILED(res)) return res; + + srcstride = prc->Width; + srcdatasize = srcstride * prc->Height; + + srcdata = malloc(srcdatasize); + if (!srcdata) return E_OUTOFMEMORY; + + res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); + if (SUCCEEDED(res)) + { + srcrow = srcdata; + dstrow = pbBuffer; + for (y=0; y<prc->Height; y++) { + srcbyte = srcrow; + dstpixel = dstrow; + for (x=0; x<prc->Width; x++) + { + DWORD argb = colors[*srcbyte++]; + *dstpixel++ = argb & 0xff; + *dstpixel++ = (argb >> 8) & 0xff; + *dstpixel++ = (argb >> 16) & 0xff; + } + srcrow += srcstride; + dstrow += cbStride; + } + } + + free(srcdata); + return res; + } + return S_OK; + case format_24bppBGR: case format_24bppRGB: if (prc) @@ -1477,7 +1535,7 @@ static HRESULT copypixels_to_24bppBGR(struct FormatConverter *This, const WICRec return S_OK; default: - FIXME("Unimplemented conversion path!\n"); + FIXME("Unimplemented conversion path! (%d)\n", source_format); return WINCODEC_ERR_UNSUPPORTEDOPERATION; } } @@ -1489,6 +1547,63 @@ static HRESULT copypixels_to_24bppRGB(struct FormatConverter *This, const WICRec switch (source_format) { + case format_8bppIndexed: + if (prc) + { + HRESULT res; + INT x, y; + BYTE *srcdata; + UINT srcstride, srcdatasize; + const BYTE *srcrow; + const BYTE *srcbyte; + BYTE *dstrow; + BYTE *dstpixel; + WICColor colors[256]; + IWICPalette *palette; + UINT actualcolors; + + res = PaletteImpl_Create(&palette); + if (FAILED(res)) return res; + + res = IWICBitmapSource_CopyPalette(This->source, palette); + if (SUCCEEDED(res)) + res = IWICPalette_GetColors(palette, 256, colors, &actualcolors); + + IWICPalette_Release(palette); + + if (FAILED(res)) return res; + + srcstride = prc->Width; + srcdatasize = srcstride * prc->Height; + + srcdata = malloc(srcdatasize); + if (!srcdata) return E_OUTOFMEMORY; + + res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); + if (SUCCEEDED(res)) + { + srcrow = srcdata; + dstrow = pbBuffer; + for (y=0; y<prc->Height; y++) { + srcbyte = srcrow; + dstpixel = dstrow; + for (x=0; x<prc->Width; x++) + { + DWORD argb = colors[*srcbyte++]; + *dstpixel++ = (argb >> 16) & 0xff; + *dstpixel++ = (argb >> 8) & 0xff; + *dstpixel++ = argb & 0xff; + } + srcrow += srcstride; + dstrow += cbStride; + } + } + + free(srcdata); + return res; + } + return S_OK; + case format_24bppBGR: case format_24bppRGB: if (prc) @@ -1550,7 +1665,7 @@ static HRESULT copypixels_to_24bppRGB(struct FormatConverter *This, const WICRec } return S_OK; default: - FIXME("Unimplemented conversion path!\n"); + FIXME("Unimplemented conversion path! (%d)\n", source_format); return WINCODEC_ERR_UNSUPPORTEDOPERATION; } } diff --git a/dlls/windowscodecs/tests/converter.c b/dlls/windowscodecs/tests/converter.c index bce0cbb189b..3b71d517456 100644 --- a/dlls/windowscodecs/tests/converter.c +++ b/dlls/windowscodecs/tests/converter.c @@ -382,7 +382,7 @@ static void compare_bitmap_data(const struct bitmap_data *src, const struct bitm * optimized palette generation implementation. We either need to * assign our own palette, or just skip the comparison. */ - if (!(!is_indexed_format(src->format) && is_indexed_format(expect->format))) + if (is_indexed_format(src->format) == is_indexed_format(expect->format)) ok(compare_bits(expect, buffersize, converted_bits), "unexpected pixel data (%s)\n", name); /* Test with NULL rectangle - should copy the whole bitmap */ @@ -390,7 +390,7 @@ static void compare_bitmap_data(const struct bitmap_data *src, const struct bitm hr = IWICBitmapSource_CopyPixels(source, NULL, stride, buffersize, converted_bits); ok(SUCCEEDED(hr), "CopyPixels(%s,rc=NULL) failed, hr=%lx\n", name, hr); /* see comment above */ - if (!(!is_indexed_format(src->format) && is_indexed_format(expect->format))) + if (is_indexed_format(src->format) == is_indexed_format(expect->format)) ok(compare_bits(expect, buffersize, converted_bits), "unexpected pixel data (%s)\n", name); HeapFree(GetProcessHeap(), 0, converted_bits); @@ -837,7 +837,7 @@ static void test_can_convert(void) {WIC_PIXEL_FORMAT(BlackWhite), TRUE, TRUE, 35}, {WIC_PIXEL_FORMAT(2bppGray), TRUE, TRUE, 35}, {WIC_PIXEL_FORMAT(4bppGray), TRUE, TRUE, 35}, - {WIC_PIXEL_FORMAT(8bppGray), TRUE, TRUE, 26}, + {WIC_PIXEL_FORMAT(8bppGray), TRUE, TRUE, 25}, {WIC_PIXEL_FORMAT(16bppGray), TRUE, TRUE, 35}, {WIC_PIXEL_FORMAT(8bppAlpha), TRUE, TRUE, 35, TRUE}, @@ -845,8 +845,8 @@ static void test_can_convert(void) {WIC_PIXEL_FORMAT(16bppBGR555), TRUE, TRUE, 35}, {WIC_PIXEL_FORMAT(16bppBGR565), TRUE, TRUE, 35}, {WIC_PIXEL_FORMAT(16bppBGRA5551), TRUE, TRUE, 33, TRUE}, - {WIC_PIXEL_FORMAT(24bppBGR), TRUE, TRUE, 27}, - {WIC_PIXEL_FORMAT(24bppRGB), TRUE, TRUE, 30}, + {WIC_PIXEL_FORMAT(24bppBGR), TRUE, TRUE, 26}, + {WIC_PIXEL_FORMAT(24bppRGB), TRUE, TRUE, 29}, {WIC_PIXEL_FORMAT(32bppBGR), TRUE, TRUE, 13}, {WIC_PIXEL_FORMAT(32bppBGRA), TRUE, TRUE, 13}, {WIC_PIXEL_FORMAT(32bppPBGRA), TRUE, TRUE, 13}, @@ -2329,6 +2329,9 @@ START_TEST(converter) test_conversion(&testdata_2bppIndexed, &testdata_8bppIndexed_4colors, "2bppIndexed -> 8bppIndexed", TRUE); test_conversion(&testdata_4bppIndexed, &testdata_8bppIndexed, "4bppIndexed -> 8bppIndexed", TRUE); + test_conversion(&testdata_8bppIndexed, &testdata_24bppRGB, "8bppIndexed -> 24bppRGB", FALSE); + test_conversion(&testdata_8bppIndexed, &testdata_24bppBGR, "8bppIndexed -> 24bppBGR", FALSE); + 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); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9816
I don't understand why we don't have fallback paths that go through 32bppBGRA -> 24bpp. Most formats should have a default case like this so we don't have to implement every single format pair. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9816#note_126007
On Mon Dec 22 17:27:08 2025 +0000, Esme Povirk wrote:
I don't understand why we don't have fallback paths that go through 32bppBGRA -> 24bpp. Most formats should have a default case like this so we don't have to implement every single format pair. Probably the only reason is performance, but I tend to agree that it's much easier to have a fallback code path, and add individual converters when really needed.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/9816#note_126008
This merge request was approved by Esme Povirk. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9816
On Mon Dec 22 17:27:08 2025 +0000, Dmitry Timoshkov wrote:
Probably the only reason is performance, but I tend to agree that it's much easier to have a fallback code path, and add individual converters when really needed. I think it's fine to add another path, it should have better performance, but feel free to add fallbacks if you get tired of doing this.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/9816#note_126010
participants (3)
-
Dmitry Timoshkov -
Dmitry Timoshkov (@dmitry) -
Esme Povirk (@madewokherd)