diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index a2ea6e12..e48ed114 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -350,6 +350,7 @@ patch_enable_all () enable_widl_SLTG_Typelib_Support="$1" enable_windowscodecs_32bppGrayFloat="$1" enable_windowscodecs_IMILBitmapSource="$1" + enable_windowscodecs_IWICPalette_InitializeFromBitmap="$1" enable_windowscodecs_WICCreateBitmapFromSection="$1" enable_windowscodecs_copypixels_to_24bppRGB="$1" enable_wine_inf_Directory_ContextMenuHandlers="$1" @@ -1229,6 +1230,9 @@ patch_enable () windowscodecs-IMILBitmapSource) enable_windowscodecs_IMILBitmapSource="$2" ;; + windowscodecs-IWICPalette_InitializeFromBitmap) + enable_windowscodecs_IWICPalette_InitializeFromBitmap="$2" + ;; windowscodecs-WICCreateBitmapFromSection) enable_windowscodecs_WICCreateBitmapFromSection="$2" ;; @@ -2032,6 +2036,13 @@ if test "$enable_wined3d_CSMT_Helper" -eq 1; then enable_wined3d_Silence_FIXMEs=1 fi +if test "$enable_windowscodecs_IWICPalette_InitializeFromBitmap" -eq 1; then + if test "$enable_gdiplus_Grayscale_PNG" -gt 1; then + abort "Patchset gdiplus-Grayscale_PNG disabled, but windowscodecs-IWICPalette_InitializeFromBitmap depends on that." + fi + enable_gdiplus_Grayscale_PNG=1 +fi + if test "$enable_windowscodecs_32bppGrayFloat" -eq 1; then if test "$enable_windowscodecs_copypixels_to_24bppRGB" -gt 1; then abort "Patchset windowscodecs-copypixels_to_24bppRGB disabled, but windowscodecs-32bppGrayFloat depends on that." @@ -7198,6 +7209,33 @@ if test "$enable_windowscodecs_IMILBitmapSource" -eq 1; then ) >> "$patchlist" fi +# Patchset windowscodecs-IWICPalette_InitializeFromBitmap +# | +# | This patchset has the following (direct or indirect) dependencies: +# | * gdiplus-Grayscale_PNG +# | +# | This patchset fixes the following Wine bugs: +# | * [#39890] Implement IWICPalette::InitializeFromBitmap +# | +# | Modified files: +# | * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/image.c, dlls/gdiplus/tests/image.c, dlls/windowscodecs/palette.c, +# | dlls/windowscodecs/pngformat.c, dlls/windowscodecs/tests/palette.c, include/gdiplusflat.h +# | +if test "$enable_windowscodecs_IWICPalette_InitializeFromBitmap" -eq 1; then + patch_apply windowscodecs-IWICPalette_InitializeFromBitmap/0001-windowscodecs-tests-Add-some-tests-for-IWICPalette-I.patch + patch_apply windowscodecs-IWICPalette_InitializeFromBitmap/0002-windowscodecs-Implement-IWICPalette-InitializeFromBi.patch + patch_apply windowscodecs-IWICPalette_InitializeFromBitmap/0003-gdiplus-Implement-GdipInitializePalette.-v2.patch + patch_apply windowscodecs-IWICPalette_InitializeFromBitmap/0004-gdiplus-tests-Add-some-tests-for-GdipInitializePalet.patch + patch_apply windowscodecs-IWICPalette_InitializeFromBitmap/0005-windowscodecs-Return-S_OK-from-PngFrameEncode_SetPal.patch + ( + echo '+ { "Dmitry Timoshkov", "windowscodecs/tests: Add some tests for IWICPalette::InitializeFromBitmap.", 2 },'; + echo '+ { "Dmitry Timoshkov", "windowscodecs: Implement IWICPalette::InitializeFromBitmap.", 5 },'; + echo '+ { "Dmitry Timoshkov", "gdiplus: Implement GdipInitializePalette.", 2 },'; + echo '+ { "Dmitry Timoshkov", "gdiplus/tests: Add some tests for GdipInitializePalette.", 2 },'; + echo '+ { "Dmitry Timoshkov", "windowscodecs: Return S_OK from PngFrameEncode_SetPalette.", 1 },'; + ) >> "$patchlist" +fi + # Patchset windowscodecs-WICCreateBitmapFromSection # | # | This patchset fixes the following Wine bugs: diff --git a/patches/windowscodecs-IWICPalette_InitializeFromBitmap/0001-windowscodecs-tests-Add-some-tests-for-IWICPalette-I.patch b/patches/windowscodecs-IWICPalette_InitializeFromBitmap/0001-windowscodecs-tests-Add-some-tests-for-IWICPalette-I.patch new file mode 100644 index 00000000..4fe6e978 --- /dev/null +++ b/patches/windowscodecs-IWICPalette_InitializeFromBitmap/0001-windowscodecs-tests-Add-some-tests-for-IWICPalette-I.patch @@ -0,0 +1,234 @@ +From 65360656ee18c1bdcc50d8a81b41a691958903ab Mon Sep 17 00:00:00 2001 +From: Dmitry Timoshkov +Date: Wed, 20 Jul 2016 11:43:19 +0800 +Subject: windowscodecs/tests: Add some tests for + IWICPalette::InitializeFromBitmap. (v2) + +--- + dlls/windowscodecs/tests/palette.c | 158 +++++++++++++++++++++++++++++++++---- + 1 file changed, 143 insertions(+), 15 deletions(-) + +diff --git a/dlls/windowscodecs/tests/palette.c b/dlls/windowscodecs/tests/palette.c +index e3b9a31..193e621 100644 +--- a/dlls/windowscodecs/tests/palette.c ++++ b/dlls/windowscodecs/tests/palette.c +@@ -1,6 +1,6 @@ + /* + * Copyright 2009 Vincent Povirk for CodeWeavers +- * Copyright 2012 Dmitry Timoshkov ++ * Copyright 2012,2016 Dmitry Timoshkov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -27,9 +27,10 @@ + #include "wincodec.h" + #include "wine/test.h" + ++static IWICImagingFactory *factory; ++ + static void test_custom_palette(void) + { +- IWICImagingFactory *factory; + IWICPalette *palette, *palette2; + HRESULT hr; + WICBitmapPaletteType type=0xffffffff; +@@ -38,11 +39,6 @@ static void test_custom_palette(void) + WICColor colors[4]; + BOOL boolresult; + +- hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, +- &IID_IWICImagingFactory, (void**)&factory); +- ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr); +- if (FAILED(hr)) return; +- + hr = IWICImagingFactory_CreatePalette(factory, &palette); + ok(SUCCEEDED(hr), "CreatePalette failed, hr=%x\n", hr); + if (SUCCEEDED(hr)) +@@ -207,8 +203,6 @@ static void test_custom_palette(void) + IWICPalette_Release(palette2); + IWICPalette_Release(palette); + } +- +- IWICImagingFactory_Release(factory); + } + + static void generate_gray16_palette(DWORD *entries, UINT count) +@@ -451,7 +445,6 @@ static void test_predefined_palette(void) + { WICBitmapPaletteTypeFixedHalftone256, 0, 0, 256, { 0 } }, + { WICBitmapPaletteTypeFixedHalftone256, 0, 0, 256, { 0 }, 1 } + }; +- IWICImagingFactory *factory; + IWICPalette *palette; + HRESULT hr; + WICBitmapPaletteType type; +@@ -459,10 +452,6 @@ static void test_predefined_palette(void) + BOOL bret; + WICColor color[256]; + +- hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, +- &IID_IWICImagingFactory, (void **)&factory); +- ok(hr == S_OK, "CoCreateInstance error %#x\n", hr); +- + hr = IWICImagingFactory_CreatePalette(factory, &palette); + ok(hr == S_OK, "CreatePalette error %#x\n", hr); + hr = IWICPalette_InitializePredefined(palette, WICBitmapPaletteTypeCustom, FALSE); +@@ -538,16 +527,155 @@ static void test_predefined_palette(void) + + IWICPalette_Release(palette); + } ++} + +- IWICImagingFactory_Release(factory); ++static BYTE *init_bitmap(UINT *width, UINT *height, UINT *stride) ++{ ++ BYTE *src; ++ UINT i, j, scale; ++ ++ *width = 256; ++ *height = 256; ++ *stride = (*width * 3 + 3) & ~3; ++ trace("width %d, height %d, stride %d\n", *width, *height, *stride); ++ ++ src = HeapAlloc(GetProcessHeap(), 0, *stride * *height); ++ ++ scale = 256 / *width; ++ if (!scale) scale = 1; ++ ++ for (i = 0; i < *height; i++) ++ { ++ for (j = 0; j < *width; j++) ++ { ++ src[i * *stride + j*3 + 0] = scale * i; ++ src[i * *stride + j*3 + 1] = scale * (255 - (i+j)/2); ++ src[i * *stride + j*3 + 2] = scale * j; ++ } ++ } ++ ++ return src; ++} ++ ++static void test_palette_from_bitmap(void) ++{ ++ HRESULT hr; ++ BYTE *data; ++ IWICBitmap *bitmap; ++ IWICPalette *palette; ++ WICBitmapPaletteType type; ++ UINT width, height, stride, count, ret; ++ WICColor color[257]; ++ ++ data = init_bitmap(&width, &height, &stride); ++ ++ hr = IWICImagingFactory_CreateBitmapFromMemory(factory, width, height, &GUID_WICPixelFormat24bppRGB, ++ stride, stride * height, data, &bitmap); ++ ok(hr == S_OK, "CreateBitmapFromMemory error %#x\n", hr); ++ ++ hr = IWICImagingFactory_CreatePalette(factory, &palette); ++ ok(hr == S_OK, "CreatePalette error %#x\n", hr); ++ ++ hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 0, FALSE); ++todo_wine ++ ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr); ++ ++ hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 1, FALSE); ++todo_wine ++ ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr); ++ ++ hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 257, FALSE); ++todo_wine ++ ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr); ++ ++ hr = IWICPalette_InitializeFromBitmap(palette, NULL, 16, FALSE); ++todo_wine ++ ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr); ++ ++ hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 2, FALSE); ++todo_wine ++ ok(hr == S_OK, "InitializeFromBitmap error %#x\n", hr); ++if (hr == S_OK) ++{ ++ hr = IWICPalette_GetColorCount(palette, &count); ++ ok(hr == S_OK, "GetColorCount error %#x\n", hr); ++ ok(count == 2, "expected 2, got %u\n", count); ++} ++ ++ hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 2, TRUE); ++todo_wine ++ ok(hr == S_OK, "InitializeFromBitmap error %#x\n", hr); ++if (hr == S_OK) ++{ ++ count = 0; ++ hr = IWICPalette_GetColorCount(palette, &count); ++ ok(hr == S_OK, "GetColorCount error %#x\n", hr); ++ ok(count == 2, "expected 2, got %u\n", count); ++} ++ ++ /* without trasparent color */ ++ hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 16, FALSE); ++todo_wine ++ ok(hr == S_OK, "InitializeFromBitmap error %#x\n", hr); ++if (hr == S_OK) ++{ ++ type = -1; ++ hr = IWICPalette_GetType(palette, &type); ++ ok(hr == S_OK, "GetType error %#x\n", hr); ++ ok(type == WICBitmapPaletteTypeCustom, "expected WICBitmapPaletteTypeCustom, got %#x\n", type); ++ count = 0; ++ hr = IWICPalette_GetColorCount(palette, &count); ++ ok(hr == S_OK, "GetColorCount error %#x\n", hr); ++ ok(count == 16, "expected 16, got %u\n", count); ++ memset(color, 0, sizeof(color)); ++ hr = IWICPalette_GetColors(palette, count, color, &ret); ++ ok(hr == S_OK, "GetColors error %#x\n", hr); ++ ok(ret == count, "expected %u, got %u\n", count, ret); ++ ok(color[count - 1] != 0, "expected !0, got %08x\n", color[count - 1]); ++} ++ ++ /* with trasparent color */ ++ hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 16, TRUE); ++todo_wine ++ ok(hr == S_OK, "InitializeFromBitmap error %#x\n", hr); ++if (hr == S_OK) ++{ ++ type = -1; ++ hr = IWICPalette_GetType(palette, &type); ++ ok(hr == S_OK, "GetType error %#x\n", hr); ++ ok(type == WICBitmapPaletteTypeCustom, "expected WICBitmapPaletteTypeCustom, got %#x\n", type); ++ count = 0; ++ hr = IWICPalette_GetColorCount(palette, &count); ++ ok(hr == S_OK, "GetColorCount error %#x\n", hr); ++ ok(count == 16, "expected 16, got %u\n", count); ++ memset(color, 0xff, sizeof(color)); ++ hr = IWICPalette_GetColors(palette, count, color, &ret); ++ ok(hr == S_OK, "GetColors error %#x\n", hr); ++ ok(ret == count, "expected %u, got %u\n", count, ret); ++ ok(color[count - 1] == 0, "expected 0, got %08x\n", color[count - 1]); ++} ++ ++ IWICPalette_Release(palette); ++ IWICBitmap_Release(bitmap); ++ ++ HeapFree(GetProcessHeap(), 0, data); + } + + START_TEST(palette) + { ++ HRESULT hr; ++ + CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + ++ hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, ++ &IID_IWICImagingFactory, (void **)&factory); ++ ok(hr == S_OK, "CoCreateInstance error %#x\n", hr); ++ + test_custom_palette(); + test_predefined_palette(); ++ test_palette_from_bitmap(); ++ ++ IWICImagingFactory_Release(factory); + + CoUninitialize(); + } +-- +2.9.0 + diff --git a/patches/windowscodecs-IWICPalette_InitializeFromBitmap/0002-windowscodecs-Implement-IWICPalette-InitializeFromBi.patch b/patches/windowscodecs-IWICPalette_InitializeFromBitmap/0002-windowscodecs-Implement-IWICPalette-InitializeFromBi.patch new file mode 100644 index 00000000..8f0da421 --- /dev/null +++ b/patches/windowscodecs-IWICPalette_InitializeFromBitmap/0002-windowscodecs-Implement-IWICPalette-InitializeFromBi.patch @@ -0,0 +1,388 @@ +From 9c1a5dadc2eee5c9b54fe9f9646036521509e342 Mon Sep 17 00:00:00 2001 +From: Dmitry Timoshkov +Date: Thu, 21 Jul 2016 14:41:41 +0800 +Subject: windowscodecs: Implement IWICPalette::InitializeFromBitmap. (v5) + +Based on median cut implementation created by Sebastian Lackner. +--- + dlls/windowscodecs/palette.c | 279 ++++++++++++++++++++++++++++++++++++- + dlls/windowscodecs/tests/palette.c | 21 +-- + 2 files changed, 275 insertions(+), 25 deletions(-) + +diff --git a/dlls/windowscodecs/palette.c b/dlls/windowscodecs/palette.c +index 89ec9ea..a8370ff 100644 +--- a/dlls/windowscodecs/palette.c ++++ b/dlls/windowscodecs/palette.c +@@ -1,6 +1,7 @@ + /* + * Copyright 2009 Vincent Povirk for CodeWeavers +- * Copyright 2012 Dmitry Timoshkov ++ * Copyright 2012,2016 Dmitry Timoshkov ++ * Copyright 2016 Sebastian Lackner + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -446,11 +447,279 @@ static HRESULT WINAPI PaletteImpl_InitializeCustom(IWICPalette *iface, + return S_OK; + } + +-static HRESULT WINAPI PaletteImpl_InitializeFromBitmap(IWICPalette *iface, +- IWICBitmapSource *pISurface, UINT colorCount, BOOL fAddTransparentColor) ++#define R_COUNT (1 << 5) ++#define R_SHIFT (8 - 5) ++#define R_SCALE 2 ++ ++#define G_COUNT (1 << 6) ++#define G_SHIFT (8 - 6) ++#define G_SCALE 3 ++ ++#define B_COUNT (1 << 5) ++#define B_SHIFT (8 - 5) ++#define B_SCALE 1 ++ ++struct histogram ++{ ++ unsigned int data[R_COUNT][G_COUNT][B_COUNT]; ++}; ++ ++struct box ++{ ++ int r_min, r_max; ++ int g_min, g_max; ++ int b_min, b_max; ++ unsigned int count; ++ unsigned int score; ++}; ++ ++/* count nonzero elements in the histogram range [r_min, r_max] x [g_min, g_max] x [b_min, b_max] */ ++static inline unsigned int histogram_count(struct histogram *h, int r_min, int r_max, ++ int g_min, int g_max, int b_min, int b_max) ++{ ++ unsigned int count = 0; ++ int r, g, b; ++ for (r = r_min; r <= r_max; r++) ++ for (g = g_min; g <= g_max; g++) ++ for (b = b_min; b <= b_max; b++) ++ if (h->data[r][g][b] != 0) count++; ++ return count; ++} ++ ++/* compute weighted average color in the range [r_min, r_max] x [g_min, g_max] x [b_min, b_max] */ ++static unsigned int histogram_color(struct histogram *h, int r_min, int r_max, ++ int g_min, int g_max, int b_min, int b_max) ++{ ++ unsigned long long r_sum = 0, g_sum = 0, b_sum = 0; ++ unsigned int tmp, count = 0; ++ int r, g, b; ++ ++ for (r = r_min; r <= r_max; r++) ++ for (g = g_min; g <= g_max; g++) ++ for (b = b_min; b <= b_max; b++) ++ { ++ if (!(tmp = h->data[r][g][b])) continue; ++ r_sum += ((r << R_SHIFT) + ((1 << R_SHIFT) / 2)) * tmp; ++ g_sum += ((g << G_SHIFT) + ((1 << G_SHIFT) / 2)) * tmp; ++ b_sum += ((b << B_SHIFT) + ((1 << B_SHIFT) / 2)) * tmp; ++ count += tmp; ++ } ++ ++ return ((b_sum + (count / 2)) / count) | ++ ((g_sum + (count / 2)) / count) << 8 | ++ ((r_sum + (count / 2)) / count) << 16 | 0xff000000; ++} ++ ++/* same as histogram_count */ ++static inline unsigned int box_count(struct histogram *h, struct box *b) ++{ ++ return histogram_count(h, b->r_min, b->r_max, b->g_min, b->g_max, b->b_min, b->b_max); ++} ++ ++/* same as histogram_color */ ++static inline unsigned int box_color(struct histogram *h, struct box *b) ++{ ++ return histogram_color(h, b->r_min, b->r_max, b->g_min, b->g_max, b->b_min, b->b_max); ++} ++ ++/* compute score used to determine best split (also called "volume") */ ++static inline unsigned int box_score(struct box *b) ++{ ++ unsigned int tmp, sum = 0; ++ tmp = ((b->r_max - b->r_min) << R_SHIFT) * R_SCALE; sum += tmp * tmp; ++ tmp = ((b->g_max - b->g_min) << G_SHIFT) * G_SCALE; sum += tmp * tmp; ++ tmp = ((b->b_max - b->b_min) << B_SHIFT) * B_SCALE; sum += tmp * tmp; ++ return sum; ++} ++ ++/* attempt to shrink a box */ ++static void shrink_box(struct histogram *h, struct box *b) ++{ ++ int i; ++ for (i = b->r_min; i <= b->r_max; i++) ++ if (histogram_count(h, i, i, b->g_min, b->g_max, b->b_min, b->b_max)) { b->r_min = i; break; } ++ for (i = b->r_max; i >= b->r_min; i--) ++ if (histogram_count(h, i, i, b->g_min, b->g_max, b->b_min, b->b_max)) { b->r_max = i; break; } ++ for (i = b->g_min; i <= b->g_max; i++) ++ if (histogram_count(h, b->r_min, b->r_max, i, i, b->b_min, b->b_max)) { b->g_min = i; break; } ++ for (i = b->g_max; i >= b->g_min; i--) ++ if (histogram_count(h, b->r_min, b->r_max, i, i, b->b_min, b->b_max)) { b->g_max = i; break; } ++ for (i = b->b_min; i <= b->b_max; i++) ++ if (histogram_count(h, b->r_min, b->r_max, b->g_min, b->g_max, i, i)) { b->b_min = i; break; } ++ for (i = b->b_max; i >= b->b_min; i--) ++ if (histogram_count(h, b->r_min, b->r_max, b->g_min, b->g_max, i, i)) { b->b_max = i; break; } ++ b->count = box_count(h, b); ++ b->score = box_score(b); ++} ++ ++/* helper for split_box */ ++static inline void set_avg(int *min, int *max) ++{ ++ int avg = (*min + *max) / 2; ++ *min = avg + 1; ++ *max = avg; ++} ++ ++/* split a box based on the best axis */ ++static void split_box(struct histogram *h, struct box *b1, struct box *b2) ++{ ++ int r = ((b1->r_max - b1->r_min) << R_SHIFT) * R_SCALE; ++ int g = ((b1->g_max - b1->g_min) << G_SHIFT) * G_SCALE; ++ int b = ((b1->b_max - b1->b_min) << B_SHIFT) * B_SCALE; ++ ++ *b2 = *b1; ++ ++ if (r > g) ++ { ++ if (b > r) set_avg(&b1->b_min, &b2->b_max); ++ else set_avg(&b1->r_min, &b2->r_max); ++ } ++ else ++ { ++ if (b > g) set_avg(&b1->b_min, &b2->b_max); ++ else set_avg(&b1->g_min, &b2->g_max); ++ } ++ ++ shrink_box(h, b1); ++ shrink_box(h, b2); ++} ++ ++/* find box suitable for split based on count */ ++static struct box *find_box_max_count(struct box *b, int count) ++{ ++ struct box *best = NULL; ++ for (; count--; b++) ++ if (b->score && (!best || b->count > best->count)) best = b; ++ return best; ++} ++ ++/* find box suitable for split based on score */ ++static struct box *find_box_max_score(struct box *b, int count) ++{ ++ struct box *best = NULL; ++ for (; count--; b++) ++ if (b->score && (!best || b->score > best->score)) best = b; ++ return best; ++} ++ ++/* compute color map with at most 'desired' colors ++ * image must be in 24bpp BGR format and colors are returned in 0xAARRGGBB format */ ++static int median_cut(unsigned char *image, unsigned int width, unsigned int height, ++ unsigned int stride, int desired, unsigned int *colors) ++{ ++ struct box boxes[256]; ++ struct histogram *h; ++ unsigned int x, y; ++ unsigned char *p; ++ struct box *b1, *b2; ++ int numboxes, i; ++ ++ if (!(h = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*h)))) ++ return 0; ++ ++ for (y = 0; y < height; y++) ++ for (x = 0, p = image + y * stride; x < width; x++, p += 3) ++ h->data[p[2] >> R_SHIFT][p[1] >> G_SHIFT][p[0] >> B_SHIFT]++; ++ ++ numboxes = 1; ++ boxes[0].r_min = 0; boxes[0].r_max = R_COUNT - 1; ++ boxes[0].g_min = 0; boxes[0].g_max = G_COUNT - 1; ++ boxes[0].b_min = 0; boxes[0].b_max = B_COUNT - 1; ++ shrink_box(h, &boxes[0]); ++ ++ while (numboxes <= desired / 2) ++ { ++ if (!(b1 = find_box_max_count(boxes, numboxes))) break; ++ b2 = &boxes[numboxes++]; ++ split_box(h, b1, b2); ++ } ++ while (numboxes < desired) ++ { ++ if (!(b1 = find_box_max_score(boxes, numboxes))) break; ++ b2 = &boxes[numboxes++]; ++ split_box(h, b1, b2); ++ } ++ ++ for (i = 0; i < numboxes; i++) ++ colors[i] = box_color(h, &boxes[i]); ++ ++ HeapFree(GetProcessHeap(), 0, h); ++ return numboxes; ++} ++ ++ ++static HRESULT WINAPI PaletteImpl_InitializeFromBitmap(IWICPalette *palette, ++ IWICBitmapSource *source, UINT desired, BOOL add_transparent) + { +- FIXME("(%p,%p,%u,%i): stub\n", iface, pISurface, colorCount, fAddTransparentColor); +- return E_NOTIMPL; ++ IWICImagingFactory *factory = NULL; ++ IWICBitmap *rgb24_bitmap = NULL; ++ IWICBitmapSource *rgb24_source; ++ IWICBitmapLock *lock = NULL; ++ WICPixelFormatGUID format; ++ HRESULT hr; ++ UINT width, height, stride, size, actual_number_of_colors; ++ BYTE *src; ++ WICColor colors[256]; ++ ++ TRACE("(%p,%p,%u,%d)\n", palette, source, desired, add_transparent); ++ ++ if (!source || desired < 2 || desired > 256) ++ return E_INVALIDARG; ++ ++ hr = IWICBitmapSource_GetPixelFormat(source, &format); ++ if (hr != S_OK) return hr; ++ ++ /* For interoperability with gdiplus where PixelFormat24bppRGB actully stored ++ * as BGR (and there is no a corresponding RGB format) we have to use 24bppBGR ++ * to avoid format conversions. ++ */ ++ if (!IsEqualGUID(&format, &GUID_WICPixelFormat24bppBGR)) ++ { ++ hr = WICConvertBitmapSource(&GUID_WICPixelFormat24bppBGR, source, &rgb24_source); ++ if (hr != S_OK) return hr; ++ } ++ else ++ rgb24_source = source; ++ ++ hr = ComponentFactory_CreateInstance(&IID_IWICImagingFactory, (void **)&factory); ++ if (hr != S_OK) goto fail; ++ ++ hr = IWICImagingFactory_CreateBitmapFromSource(factory, rgb24_source, WICBitmapCacheOnLoad, &rgb24_bitmap); ++ if (hr != S_OK) goto fail; ++ ++ hr = IWICBitmap_Lock(rgb24_bitmap, NULL, WICBitmapLockRead, &lock); ++ if (hr != S_OK) goto fail; ++ ++ IWICBitmapLock_GetSize(lock, &width, &height); ++ IWICBitmapLock_GetStride(lock, &stride); ++ IWICBitmapLock_GetDataPointer(lock, &size, &src); ++ ++ actual_number_of_colors = median_cut(src, width, height, stride, add_transparent ? desired - 1 : desired, colors); ++ TRACE("actual number of colors: %u\n", actual_number_of_colors); ++ ++ if (actual_number_of_colors) ++ { ++ if (add_transparent) colors[actual_number_of_colors++] = 0; ++ ++ hr = IWICPalette_InitializeCustom(palette, colors, actual_number_of_colors); ++ } ++ else ++ hr = E_OUTOFMEMORY; ++ ++fail: ++ if (lock) ++ IWICBitmapLock_Release(lock); ++ ++ if (rgb24_bitmap) ++ IWICBitmap_Release(rgb24_bitmap); ++ ++ if (factory) ++ IWICImagingFactory_Release(factory); ++ ++ if (rgb24_source != source) ++ IWICBitmapSource_Release(rgb24_source); ++ ++ return hr; + } + + static HRESULT WINAPI PaletteImpl_InitializeFromPalette(IWICPalette *iface, +diff --git a/dlls/windowscodecs/tests/palette.c b/dlls/windowscodecs/tests/palette.c +index 193e621..33fd119 100644 +--- a/dlls/windowscodecs/tests/palette.c ++++ b/dlls/windowscodecs/tests/palette.c +@@ -577,48 +577,34 @@ static void test_palette_from_bitmap(void) + ok(hr == S_OK, "CreatePalette error %#x\n", hr); + + hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 0, FALSE); +-todo_wine + ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr); + + hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 1, FALSE); +-todo_wine + ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr); + + hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 257, FALSE); +-todo_wine + ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr); + + hr = IWICPalette_InitializeFromBitmap(palette, NULL, 16, FALSE); +-todo_wine + ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr); + + hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 2, FALSE); +-todo_wine + ok(hr == S_OK, "InitializeFromBitmap error %#x\n", hr); +-if (hr == S_OK) +-{ ++ count = 0; + hr = IWICPalette_GetColorCount(palette, &count); + ok(hr == S_OK, "GetColorCount error %#x\n", hr); + ok(count == 2, "expected 2, got %u\n", count); +-} + + hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 2, TRUE); +-todo_wine + ok(hr == S_OK, "InitializeFromBitmap error %#x\n", hr); +-if (hr == S_OK) +-{ + count = 0; + hr = IWICPalette_GetColorCount(palette, &count); + ok(hr == S_OK, "GetColorCount error %#x\n", hr); + ok(count == 2, "expected 2, got %u\n", count); +-} + + /* without trasparent color */ + hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 16, FALSE); +-todo_wine + ok(hr == S_OK, "InitializeFromBitmap error %#x\n", hr); +-if (hr == S_OK) +-{ + type = -1; + hr = IWICPalette_GetType(palette, &type); + ok(hr == S_OK, "GetType error %#x\n", hr); +@@ -632,14 +618,10 @@ if (hr == S_OK) + ok(hr == S_OK, "GetColors error %#x\n", hr); + ok(ret == count, "expected %u, got %u\n", count, ret); + ok(color[count - 1] != 0, "expected !0, got %08x\n", color[count - 1]); +-} + + /* with trasparent color */ + hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 16, TRUE); +-todo_wine + ok(hr == S_OK, "InitializeFromBitmap error %#x\n", hr); +-if (hr == S_OK) +-{ + type = -1; + hr = IWICPalette_GetType(palette, &type); + ok(hr == S_OK, "GetType error %#x\n", hr); +@@ -653,7 +635,6 @@ if (hr == S_OK) + ok(hr == S_OK, "GetColors error %#x\n", hr); + ok(ret == count, "expected %u, got %u\n", count, ret); + ok(color[count - 1] == 0, "expected 0, got %08x\n", color[count - 1]); +-} + + IWICPalette_Release(palette); + IWICBitmap_Release(bitmap); +-- +2.9.0 + diff --git a/patches/windowscodecs-IWICPalette_InitializeFromBitmap/0003-gdiplus-Implement-GdipInitializePalette.-v2.patch b/patches/windowscodecs-IWICPalette_InitializeFromBitmap/0003-gdiplus-Implement-GdipInitializePalette.-v2.patch new file mode 100644 index 00000000..d366be55 --- /dev/null +++ b/patches/windowscodecs-IWICPalette_InitializeFromBitmap/0003-gdiplus-Implement-GdipInitializePalette.-v2.patch @@ -0,0 +1,155 @@ +From f6f04f14bb73690b6a45299469c52391699a6e88 Mon Sep 17 00:00:00 2001 +From: Dmitry Timoshkov +Date: Wed, 20 Jul 2016 14:30:09 +0800 +Subject: gdiplus: Implement GdipInitializePalette. (v2) + +--- + dlls/gdiplus/gdiplus.spec | 2 +- + dlls/gdiplus/image.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++ + include/gdiplusflat.h | 1 + + 3 files changed, 110 insertions(+), 1 deletion(-) + +diff --git a/dlls/gdiplus/gdiplus.spec b/dlls/gdiplus/gdiplus.spec +index c163ef9..d380146 100644 +--- a/dlls/gdiplus/gdiplus.spec ++++ b/dlls/gdiplus/gdiplus.spec +@@ -615,7 +615,7 @@ + 615 stub GdipGetEffectParameterSize + 616 stub GdipGetEffectParameters + 617 stdcall GdipSetEffectParameters(ptr ptr long) +-618 stub GdipInitializePalette ++618 stdcall GdipInitializePalette(ptr long long long ptr) + 619 stdcall GdipBitmapCreateApplyEffect(ptr long ptr ptr ptr ptr long ptr ptr) + 620 stdcall GdipBitmapApplyEffect(ptr ptr ptr long ptr ptr) + 621 stub GdipBitmapGetHistogram +diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c +index 1cee84b..7135eb4 100644 +--- a/dlls/gdiplus/image.c ++++ b/dlls/gdiplus/image.c +@@ -5423,3 +5423,111 @@ GpStatus WINGDIPAPI GdipBitmapConvertFormat(GpBitmap *bitmap, PixelFormat format + FIXME("(%p, 0x%08x, %d, %d, %p, %f): stub\n", bitmap, format, dithertype, palettetype, palette, alphathreshold); + return NotImplemented; + } ++ ++static GpStatus create_optimal_palette(ColorPalette *palette, INT desired, ++ BOOL transparent, GpBitmap *bitmap) ++{ ++ GpStatus status; ++ BitmapData data; ++ HRESULT hr; ++ IWICImagingFactory *factory; ++ IWICPalette *wic_palette; ++ ++ if (!bitmap) return InvalidParameter; ++ if (palette->Count < desired) return GenericError; ++ ++ status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data); ++ if (status != Ok) return status; ++ ++ hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory); ++ if (hr != S_OK) ++ { ++ GdipBitmapUnlockBits(bitmap, &data); ++ return hresult_to_status(hr); ++ } ++ ++ hr = IWICImagingFactory_CreatePalette(factory, &wic_palette); ++ if (hr == S_OK) ++ { ++ IWICBitmap *bitmap; ++ ++ /* PixelFormat24bppRGB actually stores the bitmap bits as BGR. */ ++ hr = IWICImagingFactory_CreateBitmapFromMemory(factory, data.Width, data.Height, ++ &GUID_WICPixelFormat24bppBGR, data.Stride, data.Stride * data.Width, data.Scan0, &bitmap); ++ if (hr == S_OK) ++ { ++ hr = IWICPalette_InitializeFromBitmap(wic_palette, (IWICBitmapSource *)bitmap, desired, transparent); ++ if (hr == S_OK) ++ { ++ palette->Flags = 0; ++ IWICPalette_GetColorCount(wic_palette, &palette->Count); ++ IWICPalette_GetColors(wic_palette, palette->Count, palette->Entries, &palette->Count); ++ } ++ ++ IWICBitmap_Release(bitmap); ++ } ++ ++ IWICPalette_Release(wic_palette); ++ } ++ ++ IWICImagingFactory_Release(factory); ++ GdipBitmapUnlockBits(bitmap, &data); ++ ++ return hresult_to_status(hr); ++} ++ ++/***************************************************************************** ++ * GdipInitializePalette [GDIPLUS.@] ++ */ ++GpStatus WINGDIPAPI GdipInitializePalette(ColorPalette *palette, ++ PaletteType type, INT desired, BOOL transparent, GpBitmap *bitmap) ++{ ++ TRACE("(%p,%d,%d,%d,%p)\n", palette, type, desired, transparent, bitmap); ++ ++ if (!palette) return InvalidParameter; ++ ++ switch (type) ++ { ++ case PaletteTypeCustom: ++ return Ok; ++ ++ case PaletteTypeOptimal: ++ return create_optimal_palette(palette, desired, transparent, bitmap); ++ ++ /* WIC palette type enumeration matches these gdiplus enums */ ++ case PaletteTypeFixedBW: ++ case PaletteTypeFixedHalftone8: ++ case PaletteTypeFixedHalftone27: ++ case PaletteTypeFixedHalftone64: ++ case PaletteTypeFixedHalftone125: ++ case PaletteTypeFixedHalftone216: ++ case PaletteTypeFixedHalftone252: ++ case PaletteTypeFixedHalftone256: ++ { ++ ColorPalette *wic_palette; ++ GpStatus status = Ok; ++ ++ wic_palette = get_palette(NULL, type); ++ if (!wic_palette) return OutOfMemory; ++ ++ if (palette->Count >= wic_palette->Count) ++ { ++ palette->Flags = wic_palette->Flags; ++ palette->Count = wic_palette->Count; ++ memcpy(palette->Entries, wic_palette->Entries, wic_palette->Count * sizeof(wic_palette->Entries[0])); ++ } ++ else ++ status = GenericError; ++ ++ heap_free(wic_palette); ++ ++ return status; ++ } ++ ++ default: ++ FIXME("unknown palette type %d\n", type); ++ break; ++ } ++ ++ return InvalidParameter; ++} +diff --git a/include/gdiplusflat.h b/include/gdiplusflat.h +index c6f16c4..4849104 100644 +--- a/include/gdiplusflat.h ++++ b/include/gdiplusflat.h +@@ -262,6 +262,7 @@ GpStatus WINGDIPAPI GdipGetWorldTransform(GpGraphics*,GpMatrix*); + GpStatus WINGDIPAPI GdipGraphicsClear(GpGraphics*,ARGB); + GpStatus WINGDIPAPI GdipGetVisibleClipBounds(GpGraphics*,GpRectF*); + GpStatus WINGDIPAPI GdipGetVisibleClipBoundsI(GpGraphics*,GpRect*); ++GpStatus WINGDIPAPI GdipInitializePalette(ColorPalette*,PaletteType,INT,BOOL,GpBitmap*); + GpStatus WINGDIPAPI GdipIsClipEmpty(GpGraphics*, BOOL*); + GpStatus WINGDIPAPI GdipIsVisiblePoint(GpGraphics*,REAL,REAL,BOOL*); + GpStatus WINGDIPAPI GdipIsVisiblePointI(GpGraphics*,INT,INT,BOOL*); +-- +2.9.0 + diff --git a/patches/windowscodecs-IWICPalette_InitializeFromBitmap/0004-gdiplus-tests-Add-some-tests-for-GdipInitializePalet.patch b/patches/windowscodecs-IWICPalette_InitializeFromBitmap/0004-gdiplus-tests-Add-some-tests-for-GdipInitializePalet.patch new file mode 100644 index 00000000..2da9d106 --- /dev/null +++ b/patches/windowscodecs-IWICPalette_InitializeFromBitmap/0004-gdiplus-tests-Add-some-tests-for-GdipInitializePalet.patch @@ -0,0 +1,183 @@ +From baced9170457ba5c85df39c3c30ae60923a86488 Mon Sep 17 00:00:00 2001 +From: Dmitry Timoshkov +Date: Wed, 20 Jul 2016 14:30:53 +0800 +Subject: gdiplus/tests: Add some tests for GdipInitializePalette. (v2) + +--- + dlls/gdiplus/tests/image.c | 146 +++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 146 insertions(+) + +diff --git a/dlls/gdiplus/tests/image.c b/dlls/gdiplus/tests/image.c +index 28fd1a7..b74cb50 100644 +--- a/dlls/gdiplus/tests/image.c ++++ b/dlls/gdiplus/tests/image.c +@@ -30,6 +30,8 @@ + #include "gdiplus.h" + #include "wine/test.h" + ++static GpStatus (WINGDIPAPI *pGdipInitializePalette)(ColorPalette*,PaletteType,INT,BOOL,GpBitmap*); ++ + #define expect(expected, got) ok((got) == (expected), "Expected %d, got %d\n", (UINT)(expected), (UINT)(got)) + #define expectf(expected, got) ok(fabs((expected) - (got)) < 0.0001, "Expected %f, got %f\n", (expected), (got)) + +@@ -4849,6 +4851,149 @@ static void test_png_color_formats(void) + } + } + ++static BYTE *init_bitmap(UINT *width, UINT *height, UINT *stride) ++{ ++ BYTE *src; ++ UINT i, j, scale; ++ ++ *width = 256; ++ *height = 256; ++ *stride = (*width * 3 + 3) & ~3; ++ trace("width %d, height %d, stride %d\n", *width, *height, *stride); ++ ++ src = HeapAlloc(GetProcessHeap(), 0, *stride * *height); ++ ++ scale = 256 / *width; ++ if (!scale) scale = 1; ++ ++ for (i = 0; i < *height; i++) ++ { ++ for (j = 0; j < *width; j++) ++ { ++ src[i * *stride + j*3 + 0] = scale * i; ++ src[i * *stride + j*3 + 1] = scale * (255 - (i+j)/2); ++ src[i * *stride + j*3 + 2] = scale * j; ++ } ++ } ++ ++ return src; ++} ++ ++static void test_GdipInitializePalette(void) ++{ ++ GpStatus status; ++ BYTE *data; ++ GpBitmap *bitmap; ++ ColorPalette *palette; ++ UINT width, height, stride; ++ ++ pGdipInitializePalette = (void *)GetProcAddress(GetModuleHandleA("gdiplus.dll"), "GdipInitializePalette"); ++ if (!pGdipInitializePalette) ++ { ++ win_skip("GdipInitializePalette is not supported on this platform\n"); ++ return; ++ } ++ ++ data = init_bitmap(&width, &height, &stride); ++ ++ status = GdipCreateBitmapFromScan0(width, height, stride, PixelFormat24bppRGB, data, &bitmap); ++ expect(Ok, status); ++ ++ palette = GdipAlloc(sizeof(*palette) + sizeof(ARGB) * 255); ++ ++ palette->Flags = 0; ++ palette->Count = 15; ++ status = pGdipInitializePalette(palette, PaletteTypeOptimal, 16, FALSE, bitmap); ++ expect(GenericError, status); ++ ++ palette->Flags = 0; ++ palette->Count = 256; ++ status = pGdipInitializePalette(palette, PaletteTypeOptimal, 16, FALSE, NULL); ++ expect(InvalidParameter, status); ++ ++ memset(palette->Entries, 0x11, sizeof(ARGB) * 256); ++ palette->Flags = 0; ++ palette->Count = 256; ++ status = pGdipInitializePalette(palette, PaletteTypeCustom, 16, FALSE, NULL); ++ expect(Ok, status); ++ expect(0, palette->Flags); ++ expect(256, palette->Count); ++ expect(0x11111111, palette->Entries[0]); ++ expect(0x11111111, palette->Entries[128]); ++ expect(0x11111111, palette->Entries[255]); ++ ++ memset(palette->Entries, 0x11, sizeof(ARGB) * 256); ++ palette->Flags = 0; ++ palette->Count = 256; ++ status = pGdipInitializePalette(palette, PaletteTypeFixedBW, 0, FALSE, bitmap); ++ expect(Ok, status); ++todo_wine ++ expect(0x200, palette->Flags); ++ expect(2, palette->Count); ++ expect(0xff000000, palette->Entries[0]); ++ expect(0xffffffff, palette->Entries[1]); ++ ++ memset(palette->Entries, 0x11, sizeof(ARGB) * 256); ++ palette->Flags = 0; ++ palette->Count = 256; ++ status = pGdipInitializePalette(palette, PaletteTypeFixedHalftone8, 1, FALSE, NULL); ++ expect(Ok, status); ++todo_wine ++ expect(0x300, palette->Flags); ++ expect(16, palette->Count); ++ expect(0xff000000, palette->Entries[0]); ++ expect(0xffc0c0c0, palette->Entries[8]); ++ expect(0xff008080, palette->Entries[15]); ++ ++ memset(palette->Entries, 0x11, sizeof(ARGB) * 256); ++ palette->Flags = 0; ++ palette->Count = 256; ++ status = pGdipInitializePalette(palette, PaletteTypeFixedHalftone8, 1, FALSE, bitmap); ++ expect(Ok, status); ++todo_wine ++ expect(0x300, palette->Flags); ++ expect(16, palette->Count); ++ expect(0xff000000, palette->Entries[0]); ++ expect(0xffc0c0c0, palette->Entries[8]); ++ expect(0xff008080, palette->Entries[15]); ++ ++ memset(palette->Entries, 0x11, sizeof(ARGB) * 256); ++ palette->Flags = 0; ++ palette->Count = 256; ++ status = pGdipInitializePalette(palette, PaletteTypeFixedHalftone252, 1, FALSE, bitmap); ++ expect(Ok, status); ++todo_wine ++ expect(0x800, palette->Flags); ++ expect(252, palette->Count); ++ expect(0xff000000, palette->Entries[0]); ++ expect(0xff990066, palette->Entries[128]); ++ expect(0xffffffff, palette->Entries[251]); ++ ++ palette->Flags = 0; ++ palette->Count = 256; ++ status = pGdipInitializePalette(palette, PaletteTypeOptimal, 1, FALSE, bitmap); ++ expect(InvalidParameter, status); ++ ++ palette->Flags = 0; ++ palette->Count = 256; ++ status = pGdipInitializePalette(palette, PaletteTypeOptimal, 2, FALSE, bitmap); ++ expect(Ok, status); ++ expect(0, palette->Flags); ++ expect(2, palette->Count); ++ ++ palette->Flags = 0; ++ palette->Count = 256; ++ status = pGdipInitializePalette(palette, PaletteTypeOptimal, 16, FALSE, bitmap); ++ expect(Ok, status); ++ expect(0, palette->Flags); ++ expect(16, palette->Count); ++ ++ /* passing invalid enumeration palette type crashes under most Windows versions */ ++ ++ GdipFree(palette); ++ GdipDisposeImage((GpImage *)bitmap); ++} ++ + START_TEST(image) + { + struct GdiplusStartupInput gdiplusStartupInput; +@@ -4861,6 +5006,7 @@ START_TEST(image) + + GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); + ++ test_GdipInitializePalette(); + test_png_color_formats(); + test_supported_encoders(); + test_CloneBitmapArea(); +-- +2.9.0 + diff --git a/patches/windowscodecs-IWICPalette_InitializeFromBitmap/0005-windowscodecs-Return-S_OK-from-PngFrameEncode_SetPal.patch b/patches/windowscodecs-IWICPalette_InitializeFromBitmap/0005-windowscodecs-Return-S_OK-from-PngFrameEncode_SetPal.patch new file mode 100644 index 00000000..80d48056 --- /dev/null +++ b/patches/windowscodecs-IWICPalette_InitializeFromBitmap/0005-windowscodecs-Return-S_OK-from-PngFrameEncode_SetPal.patch @@ -0,0 +1,25 @@ +From 611e1f496ee05a60f29088df17289ae6de9fded0 Mon Sep 17 00:00:00 2001 +From: Dmitry Timoshkov +Date: Tue, 26 Jul 2016 16:28:08 +0800 +Subject: windowscodecs: Return S_OK from PngFrameEncode_SetPalette. + +--- + dlls/windowscodecs/pngformat.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c +index bb2aef9..b84e1e6 100644 +--- a/dlls/windowscodecs/pngformat.c ++++ b/dlls/windowscodecs/pngformat.c +@@ -1539,7 +1539,7 @@ static HRESULT WINAPI PngFrameEncode_SetPalette(IWICBitmapFrameEncode *iface, + IWICPalette *pIPalette) + { + FIXME("(%p,%p): stub\n", iface, pIPalette); +- return WINCODEC_ERR_UNSUPPORTEDOPERATION; ++ return S_OK; + } + + static HRESULT WINAPI PngFrameEncode_SetThumbnail(IWICBitmapFrameEncode *iface, +-- +2.9.0 + diff --git a/patches/windowscodecs-IWICPalette_InitializeFromBitmap/definition b/patches/windowscodecs-IWICPalette_InitializeFromBitmap/definition new file mode 100644 index 00000000..330f9c64 --- /dev/null +++ b/patches/windowscodecs-IWICPalette_InitializeFromBitmap/definition @@ -0,0 +1,3 @@ +Fixes: [39890] Implement IWICPalette::InitializeFromBitmap +Fixes: Implement gdiplus.GdipInitializePalette +Depends: gdiplus-Grayscale_PNG