[USER32] Fix resource display of MSVC BI_BITFIELD 32-bit bitmaps. (#5942)

This specifically fixes Wordpad's Open and SaveAs dialog toolbars.

* Fix 16 bpp BI_BITFIELDS like 32 bpp was done.
* Add BI_BITFIELDS byte count into bitmap_info_size return value.
* Account for GCC's windres.exe incorrect omission for BI_BITFIELDS DWORD's when processing 32-bpp bitmaps.
* Account for GCC's windres.exe failing with bitmaps with BI_BITFIELDS and bits per plane is 16
* Fix WARN message to show error on either 16-bpp or 32-bpp
* Correct comment regarding GCC compiled bitmaps with compression of BI_BITFIELD's to add 16 bits per plane

CORE-17005
This commit is contained in:
Doug Lyons 2024-04-27 14:38:06 -05:00 committed by GitHub
parent ff12fc9fb9
commit 116c0cd9a5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -152,6 +152,8 @@ static BOOL is_dib_monochrome( const BITMAPINFO* info )
} }
} }
/* Return the size of the bitmap info structure including color table and
* the bytes required for 3 DWORDS if this is a BI_BITFIELDS bmp. */
static int bitmap_info_size( const BITMAPINFO * info, WORD coloruse ) static int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
{ {
unsigned int colors, size, masks = 0; unsigned int colors, size, masks = 0;
@ -170,8 +172,21 @@ static int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
colors = 256; colors = 256;
if (!colors && (info->bmiHeader.biBitCount <= 8)) if (!colors && (info->bmiHeader.biBitCount <= 8))
colors = 1 << info->bmiHeader.biBitCount; colors = 1 << info->bmiHeader.biBitCount;
/* Account for BI_BITFIELDS in BITMAPINFOHEADER(v1-v3) bmp's. The
* 'max' selection using biSize below will exclude v4 & v5's. */
if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3; if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) ); size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
/* Test for BI_BITFIELDS format and either 16 or 32 bpp.
* If so, account for the 3 DWORD masks (RGB Order).
* BITMAPCOREHEADER tested above has no 16 or 32 bpp types.
* See table "All of the possible pixel formats in a DIB"
* at https://en.wikipedia.org/wiki/BMP_file_format. */
if (info->bmiHeader.biSize >= sizeof(BITMAPV4HEADER) &&
info->bmiHeader.biCompression == BI_BITFIELDS &&
(info->bmiHeader.biBitCount == 16 || info->bmiHeader.biBitCount == 32))
{
size += 3 * sizeof(DWORD); // BI_BITFIELDS
}
return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD)); return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
} }
} }
@ -1099,7 +1114,7 @@ BITMAP_LoadImageW(
HBITMAP hbmpOld, hbmpRet = NULL; HBITMAP hbmpOld, hbmpRet = NULL;
LONG width, height; LONG width, height;
WORD bpp; WORD bpp;
DWORD compr; DWORD compr, ResSize = 0;
/* Map the bitmap info */ /* Map the bitmap info */
if(fuLoad & LR_LOADFROMFILE) if(fuLoad & LR_LOADFROMFILE)
@ -1137,6 +1152,7 @@ BITMAP_LoadImageW(
pbmi = LockResource(hgRsrc); pbmi = LockResource(hgRsrc);
if(!pbmi) if(!pbmi)
return NULL; return NULL;
ResSize = SizeofResource(hinst, hrsrc);
} }
/* Fix up values */ /* Fix up values */
@ -1162,6 +1178,21 @@ BITMAP_LoadImageW(
goto end; goto end;
CopyMemory(pbmiCopy, pbmi, iBMISize); CopyMemory(pbmiCopy, pbmi, iBMISize);
TRACE("Size Image %d, Size Header %d, ResSize %d\n",
pbmiCopy->bmiHeader.biSizeImage, pbmiCopy->bmiHeader.biSize, ResSize);
/* HACK: If this is a binutils' windres.exe compiled 16 or 32 bpp bitmap
* using BI_BITFIELDS, then a bug causes it to fail to include
* the bytes for the bitfields. So, we have to substract out the
* size of the bitfields previously included from bitmap_info_size. */
if (compr == BI_BITFIELDS && (bpp == 16 || bpp == 32) &&
pbmiCopy->bmiHeader.biSizeImage + pbmiCopy->bmiHeader.biSize == ResSize)
{
/* GCC pointer to the image data has 12 less bytes than MSVC */
pvBits = (char*)pvBits - 12;
WARN("Found GCC Resource Compiled 16-bpp or 32-bpp error\n");
}
/* Fix it up, if needed */ /* Fix it up, if needed */
if(fuLoad & (LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS)) if(fuLoad & (LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS))
{ {