[PATCH 0/1] MR9436: windowscodecs: Fix the bug when the input palette hpal is NULL in...
windowscodecs: Fix the bug when the input palette hpal is NULL in ImagingFactory_CreateBitmapFromHBITMAP. When the palette is given NULL and the format is 1/4/8bppIndexed, palette info is lost. It causes incorrect color calculation when the WIC interface is called later. Signed-off-by: yangkun <yangkun(a)uniontech.com> Change-Id: I851373e9186dc815488235f0fc219d8fbdd91658 -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9436
From: yangkun <yangkun(a)uniontech.com> When the palette is given NULL and the format is 1/4/8bppIndexed, palette info is lost. It causes incorrect color calculation when the WIC interface is called later. Signed-off-by: yangkun <yangkun(a)uniontech.com> Change-Id: I851373e9186dc815488235f0fc219d8fbdd91658 --- dlls/windowscodecs/imgfactory.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/dlls/windowscodecs/imgfactory.c b/dlls/windowscodecs/imgfactory.c index e2ffd6da3f4..62acc35f9da 100644 --- a/dlls/windowscodecs/imgfactory.c +++ b/dlls/windowscodecs/imgfactory.c @@ -769,6 +769,34 @@ static HRESULT WINAPI ImagingFactory_CreateBitmapFromHBITMAP(IWICImagingFactory2 return E_INVALIDARG; } + if (!hpal && + (IsEqualGUID(&format, &GUID_WICPixelFormat1bppIndexed) || + IsEqualGUID(&format, &GUID_WICPixelFormat4bppIndexed) || + IsEqualGUID(&format, &GUID_WICPixelFormat8bppIndexed))) + { + HDC hdc_palette = CreateCompatibleDC(0); + char bmibuf_palette[FIELD_OFFSET(BITMAPINFO, bmiColors[256])]; + BITMAPINFO *bmi_palette = (BITMAPINFO *)bmibuf_palette; + bmi_palette->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi_palette->bmiHeader.biBitCount = 0; + + if(GetDIBits(hdc_palette, hbm, 0, 0, NULL, bmi_palette, DIB_RGB_COLORS)) + { + num_palette_entries = bmi_palette->bmiHeader.biClrUsed ? bmi_palette->bmiHeader.biClrUsed : (UINT)(1 << bmi_palette->bmiHeader.biBitCount); + if (GetDIBits(hdc_palette, hbm, 0, 0, (LPVOID)entry, bmi_palette, DIB_RGB_COLORS)) + { + for (UINT i = 0; i < num_palette_entries; i++) + { + entry[i].peRed = bmi_palette->bmiColors[i].rgbRed; + entry[i].peGreen = bmi_palette->bmiColors[i].rgbGreen; + entry[i].peBlue = bmi_palette->bmiColors[i].rgbBlue; + entry[i].peFlags = 0; + } + } + } + DeleteDC(hdc_palette); + } + hr = BitmapImpl_Create(bm.bmWidth, bm.bmHeight, bm.bmWidthBytes, 0, NULL, 0, &format, WICBitmapCacheOnLoad, bitmap); if (hr != S_OK) return hr; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9436
In the function ImagingFactory_CreateBitmapFromHBITMAP, the hpal can be given NULL by application. In current wine, the color calculation is wrong for the format GUID_WICPixelFormat1bppIndexed, GUID_WICPixelFormat4bppIndexed and GUID_WICPixelFormat8bppIndexed if the application does not pass palette argument. WIC bitmap can not be used in the later WIC operation, such as FormatConverter_CopyPixels. After testing the code on the Windows system, I believe it should be handled as follows: If palette is NULL, and the format needs a palette to build color. It is necessary to obtain the bmiColors of the hbitmap at the time of its creation, such as CreateDIBSection. This is an 8bpp WIC program that does not run correctly under the current Wine. [wincodecs_test.c](/uploads/ad8051925814bb1d92d936134c8c3c9c/wincodecs_test.c) [wincodecs_test.exe](/uploads/53c8e520cfc415282c4221ac8789e7e6/wincodecs_test.exe) -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9436#note_121625
Esme Povirk (@madewokherd) commented about dlls/windowscodecs/imgfactory.c:
+ if (!hpal && + (IsEqualGUID(&format, &GUID_WICPixelFormat1bppIndexed) || + IsEqualGUID(&format, &GUID_WICPixelFormat4bppIndexed) || + IsEqualGUID(&format, &GUID_WICPixelFormat8bppIndexed))) + { + HDC hdc_palette = CreateCompatibleDC(0); + char bmibuf_palette[FIELD_OFFSET(BITMAPINFO, bmiColors[256])]; + BITMAPINFO *bmi_palette = (BITMAPINFO *)bmibuf_palette; + bmi_palette->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi_palette->bmiHeader.biBitCount = 0; + + if(GetDIBits(hdc_palette, hbm, 0, 0, NULL, bmi_palette, DIB_RGB_COLORS)) + { + num_palette_entries = bmi_palette->bmiHeader.biClrUsed ? bmi_palette->bmiHeader.biClrUsed : (UINT)(1 << bmi_palette->bmiHeader.biBitCount); + if (GetDIBits(hdc_palette, hbm, 0, 0, (LPVOID)entry, bmi_palette, DIB_RGB_COLORS))
I'm confused about the use of `entry` here. That argument is supposed to point to bitmap bits? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9436#note_121722
Esme Povirk (@madewokherd) commented about dlls/windowscodecs/imgfactory.c:
bmi->bmiHeader.biBitCount = 0; GetDIBits(hdc, hbm, 0, 0, NULL, bmi, DIB_RGB_COLORS); bmi->bmiHeader.biHeight = -bm.bmHeight; GetDIBits(hdc, hbm, 0, bm.bmHeight, buffer, bmi, DIB_RGB_COLORS);
I think this GetDIBits call will read the palette, and it would be simpler to use that. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9436#note_121723
On Wed Nov 12 21:41:42 2025 +0000, Esme Povirk wrote:
I think this GetDIBits call will read the palette, and it would be simpler to use that. Do you mean that I move the code which calculates num_palette_entries to line 819 and use the palette in GetDIBits in line 820? @madewokherd
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/9436#note_122522
On Mon Nov 17 09:39:46 2025 +0000, Kun Yang wrote:
Do you mean that I move the code which calculates num_palette_entries to line 819 and use the palette in GetDIBits in line 820? @madewokherd Yes.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/9436#note_122606
participants (3)
-
Esme Povirk (@madewokherd) -
Kun Yang (@yangkun) -
yangkun