Correct loading of BI_BITFIELDS bitmaps
This fixes several minor bugs in the loading of `BI_BITFIELDS` bitmaps, related to handling different header sizes and the colour and alpha masks. Closes #23601.
This commit is contained in:
parent
6bba7055aa
commit
d78e9fb1cb
9 changed files with 57 additions and 17 deletions
|
|
@ -148,6 +148,7 @@ set(TEST_GUI_DATA
|
|||
horse.tif
|
||||
horse.xpm
|
||||
image/bitfields.bmp
|
||||
image/bitfields-alpha.bmp
|
||||
image/8bpp-colorsused-large.bmp
|
||||
image/8bpp-colorsused-negative.bmp
|
||||
image/rle4-delta-320x240.bmp
|
||||
|
|
|
|||
|
|
@ -510,7 +510,7 @@ struct BMPDesc
|
|||
|
||||
wxScopedArray<BMPPalette> paletteData;
|
||||
|
||||
int rmask, gmask, bmask, amask;
|
||||
int rmask, gmask, bmask;
|
||||
};
|
||||
|
||||
// Read the data in BMP format into the given image.
|
||||
|
|
@ -620,6 +620,18 @@ bool LoadBMPData(wxImage * image, const BMPDesc& desc,
|
|||
gmask = desc.gmask;
|
||||
bmask = desc.bmask;
|
||||
|
||||
// Mimic Windows behaviour: alpha is applied only in 32bpp
|
||||
// and if the colour masks are the same as for BI_RGB.
|
||||
// Any alpha mask in the header is ignored.
|
||||
if ( bpp == 32 &&
|
||||
rmask == 0x00FF0000 &&
|
||||
gmask == 0x0000FF00 &&
|
||||
bmask == 0x000000FF )
|
||||
{
|
||||
amask = 0xFF000000;
|
||||
ashift = 24;
|
||||
}
|
||||
|
||||
// find shift amount (Least significant bit of mask)
|
||||
for (bit = bpp-1; bit>=0; bit--)
|
||||
{
|
||||
|
|
@ -1207,15 +1219,18 @@ bool wxBMPHandler::LoadDib(wxImage *image, wxInputStream& stream,
|
|||
if ( desc.comp == BI_BITFIELDS )
|
||||
{
|
||||
// Read the mask values from the header.
|
||||
if ( !stream.ReadAll(dbuf, 4 * 4) )
|
||||
if ( !stream.ReadAll(dbuf, 4 * 3) )
|
||||
return false;
|
||||
|
||||
hdrBytesRead += 4 * 4;
|
||||
hdrBytesRead += 4 * 3;
|
||||
|
||||
desc.rmask = wxINT32_SWAP_ON_BE(dbuf[0]);
|
||||
desc.gmask = wxINT32_SWAP_ON_BE(dbuf[1]);
|
||||
desc.bmask = wxINT32_SWAP_ON_BE(dbuf[2]);
|
||||
desc.amask = wxINT32_SWAP_ON_BE(dbuf[3]);
|
||||
|
||||
// There will also be an alpha mask if (and only if) the header is
|
||||
// V4 or V5, so we mustn't try to read it if we don't have one of
|
||||
// those. But it's not used anywhere in any case.
|
||||
}
|
||||
|
||||
// Now that we've read everything we needed from the header, advance
|
||||
|
|
@ -1231,6 +1246,10 @@ bool wxBMPHandler::LoadDib(wxImage *image, wxInputStream& stream,
|
|||
// bytes preceding it: "BM" signature and 3 other DWORDs.
|
||||
wxFileOffset bytesRead = 14 + hdrSize;
|
||||
|
||||
// We might have read colour masks.
|
||||
if ( desc.comp == BI_BITFIELDS )
|
||||
bytesRead += 12;
|
||||
|
||||
// We must have a palette for 1bpp, 4bpp and 8bpp bitmaps.
|
||||
if (desc.ncolors == 0 && desc.bpp < 16)
|
||||
desc.ncolors = 1 << desc.bpp;
|
||||
|
|
|
|||
|
|
@ -416,7 +416,9 @@ HBITMAP wxDIB::ConvertToBitmap(const BITMAPINFO *pbmi, HDC hdc, const void *bits
|
|||
switch ( pbmih->biCompression )
|
||||
{
|
||||
case BI_BITFIELDS:
|
||||
numColors = 3;
|
||||
// with a classic BITMAPINFOHEADER, there are 3 colour-mask DWORDs
|
||||
// after the header. Otherwise the masks are part of the header
|
||||
numColors = pbmih->biSize == sizeof(BITMAPINFOHEADER) ? 3 : 0;
|
||||
break;
|
||||
|
||||
case BI_RGB:
|
||||
|
|
@ -436,7 +438,10 @@ HBITMAP wxDIB::ConvertToBitmap(const BITMAPINFO *pbmi, HDC hdc, const void *bits
|
|||
numColors = 0;
|
||||
}
|
||||
|
||||
bits = reinterpret_cast<const char*>(pbmih + 1) + numColors * sizeof(RGBQUAD);
|
||||
// pbmih->biSize might not be the same as sizeof(BITMAPINFOHEADER)
|
||||
// (such as in the case of a BITMAPV4HEADER or BITMAPV5HEADER);
|
||||
// we need to advance by the number of bytes actually present
|
||||
bits = reinterpret_cast<const char*>(pbmih) + pbmih->biSize + numColors * sizeof(RGBQUAD);
|
||||
}
|
||||
|
||||
HBITMAP hbmp = ::CreateDIBitmap
|
||||
|
|
|
|||
|
|
@ -582,7 +582,7 @@ data-image-sample:
|
|||
|
||||
data-images:
|
||||
@mkdir -p image
|
||||
@for f in bitfields.bmp 8bpp-colorsused-large.bmp 8bpp-colorsused-negative.bmp rle4-delta-320x240.bmp rle8-delta-320x240.bmp rle8-delta-320x240-expected.bmp horse_grey.bmp horse_grey_flipped.bmp horse_rle4.bmp horse_rle4_flipped.bmp horse_rle8.bmp horse_rle8_flipped.bmp horse_bicubic_50x50.png horse_bicubic_100x100.png horse_bicubic_150x150.png horse_bicubic_300x300.png horse_bilinear_50x50.png horse_bilinear_100x100.png horse_bilinear_150x150.png horse_bilinear_300x300.png horse_box_average_50x50.png horse_box_average_100x100.png horse_box_average_150x150.png horse_box_average_300x300.png cross_bicubic_256x256.png cross_bilinear_256x256.png cross_box_average_256x256.png cross_nearest_neighb_256x256.png paste_input_background.png paste_input_black.png paste_input_overlay_transparent_border_opaque_square.png paste_input_overlay_transparent_border_semitransparent_circle.png paste_input_overlay_transparent_border_semitransparent_square.png paste_result_background_plus_circle_plus_square.png paste_result_background_plus_overlay_transparent_border_opaque_square.png paste_result_background_plus_overlay_transparent_border_semitransparent_square.png paste_result_no_background_square_over_circle.png wx.png toucan.png toucan_hue_0.538.png toucan_sat_-0.41.png toucan_bright_-0.259.png toucan_hsv_0.538_-0.41_-0.259.png toucan_light_46.png toucan_dis_240.png toucan_grey.png toucan_mono_255_255_255.png width-times-height-overflow.bmp width_height_32_bit_overflow.pgm; do \
|
||||
@for f in bitfields.bmp bitfields-alpha.bmp 8bpp-colorsused-large.bmp 8bpp-colorsused-negative.bmp rle4-delta-320x240.bmp rle8-delta-320x240.bmp rle8-delta-320x240-expected.bmp horse_grey.bmp horse_grey_flipped.bmp horse_rle4.bmp horse_rle4_flipped.bmp horse_rle8.bmp horse_rle8_flipped.bmp horse_bicubic_50x50.png horse_bicubic_100x100.png horse_bicubic_150x150.png horse_bicubic_300x300.png horse_bilinear_50x50.png horse_bilinear_100x100.png horse_bilinear_150x150.png horse_bilinear_300x300.png horse_box_average_50x50.png horse_box_average_100x100.png horse_box_average_150x150.png horse_box_average_300x300.png cross_bicubic_256x256.png cross_bilinear_256x256.png cross_box_average_256x256.png cross_nearest_neighb_256x256.png paste_input_background.png paste_input_black.png paste_input_overlay_transparent_border_opaque_square.png paste_input_overlay_transparent_border_semitransparent_circle.png paste_input_overlay_transparent_border_semitransparent_square.png paste_result_background_plus_circle_plus_square.png paste_result_background_plus_overlay_transparent_border_opaque_square.png paste_result_background_plus_overlay_transparent_border_semitransparent_square.png paste_result_no_background_square_over_circle.png wx.png toucan.png toucan_hue_0.538.png toucan_sat_-0.41.png toucan_bright_-0.259.png toucan_hsv_0.538_-0.41_-0.259.png toucan_light_46.png toucan_dis_240.png toucan_grey.png toucan_mono_255_255_255.png width-times-height-overflow.bmp width_height_32_bit_overflow.pgm; do \
|
||||
if test ! -f image/$$f -a ! -d image/$$f ; \
|
||||
then x=yep ; \
|
||||
else x=`find $(srcdir)/image/$$f -newer image/$$f -print` ; \
|
||||
|
|
|
|||
BIN
tests/image/bitfields-alpha.bmp
Normal file
BIN
tests/image/bitfields-alpha.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.1 KiB |
|
|
@ -1331,12 +1331,20 @@ static wxImage ImageFromBMPFile(const wxString& filename)
|
|||
// wxDIB::ConvertToBitmap() about it because we need to test its
|
||||
// code path where bits==nullptr, so we just have to fail the test
|
||||
const BITMAPINFO* pbmi = reinterpret_cast<const BITMAPINFO*>(&buf[0]);
|
||||
wxUint32 nColors = pbmi->bmiHeader.biClrUsed
|
||||
? pbmi->bmiHeader.biClrUsed
|
||||
: (pbmi->bmiHeader.biBitCount <= 8
|
||||
? 1 << pbmi->bmiHeader.biBitCount
|
||||
: 0);
|
||||
wxUint32 cbColorTable = nColors * sizeof(RGBQUAD);
|
||||
wxUint32 numColors = 0;
|
||||
if ( pbmi->bmiHeader.biCompression == BI_BITFIELDS )
|
||||
{
|
||||
if ( pbmi->bmiHeader.biSize == sizeof(BITMAPINFOHEADER) )
|
||||
numColors = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( pbmi->bmiHeader.biClrUsed )
|
||||
numColors = pbmi->bmiHeader.biClrUsed;
|
||||
else if ( pbmi->bmiHeader.biBitCount <= 8 )
|
||||
numColors = 1 << pbmi->bmiHeader.biBitCount;
|
||||
}
|
||||
wxUint32 cbColorTable = numColors * sizeof(RGBQUAD);
|
||||
size_t ofstComputed = hdrLen + pbmi->bmiHeader.biSize + cbColorTable;
|
||||
REQUIRE(ofstComputed == ofstDeclared);
|
||||
|
||||
|
|
@ -1350,7 +1358,7 @@ static wxImage ImageFromBMPFile(const wxString& filename)
|
|||
|
||||
// Compare the results of loading a BMP via wxBMPHandler
|
||||
// and via Windows' own conversion (CreateDIBitmap())
|
||||
static void CompareBMPImageLoad(const wxString& filename)
|
||||
static void CompareBMPImageLoad(const wxString& filename, int properties = 0)
|
||||
{
|
||||
wxImage image1 = ImageFromBMPFile(filename);
|
||||
REQUIRE( image1.IsOk() );
|
||||
|
|
@ -1359,11 +1367,17 @@ static void CompareBMPImageLoad(const wxString& filename)
|
|||
REQUIRE( image2.IsOk() );
|
||||
|
||||
INFO("Comparing loading methods for " << filename);
|
||||
CompareImage(*wxImage::FindHandler(wxBITMAP_TYPE_BMP), image1, 0, &image2);
|
||||
CompareImage(*wxImage::FindHandler(wxBITMAP_TYPE_BMP),
|
||||
image1, properties, &image2);
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(ImageHandlersInit, "wxImage::BMPLoadMethod", "[image][bmp]")
|
||||
{
|
||||
CompareBMPImageLoad("image/bitfields.bmp");
|
||||
// We would check the alpha on this one, but at the moment it fails
|
||||
// because of the way CompareImage() saves and reloads images,
|
||||
// which for BMPs does not preserve the alpha channel
|
||||
CompareBMPImageLoad("image/bitfields-alpha.bmp"/*, wxIMAGE_HAVE_ALPHA*/);
|
||||
CompareBMPImageLoad("image/horse_grey.bmp");
|
||||
CompareBMPImageLoad("image/horse_rle8.bmp");
|
||||
CompareBMPImageLoad("image/horse_rle4.bmp");
|
||||
|
|
|
|||
|
|
@ -552,7 +552,7 @@ data-image-sample:
|
|||
|
||||
data-images:
|
||||
if not exist image mkdir image
|
||||
for %%f in (bitfields.bmp 8bpp-colorsused-large.bmp 8bpp-colorsused-negative.bmp rle4-delta-320x240.bmp rle8-delta-320x240.bmp rle8-delta-320x240-expected.bmp horse_grey.bmp horse_grey_flipped.bmp horse_rle4.bmp horse_rle4_flipped.bmp horse_rle8.bmp horse_rle8_flipped.bmp horse_bicubic_50x50.png horse_bicubic_100x100.png horse_bicubic_150x150.png horse_bicubic_300x300.png horse_bilinear_50x50.png horse_bilinear_100x100.png horse_bilinear_150x150.png horse_bilinear_300x300.png horse_box_average_50x50.png horse_box_average_100x100.png horse_box_average_150x150.png horse_box_average_300x300.png cross_bicubic_256x256.png cross_bilinear_256x256.png cross_box_average_256x256.png cross_nearest_neighb_256x256.png paste_input_background.png paste_input_black.png paste_input_overlay_transparent_border_opaque_square.png paste_input_overlay_transparent_border_semitransparent_circle.png paste_input_overlay_transparent_border_semitransparent_square.png paste_result_background_plus_circle_plus_square.png paste_result_background_plus_overlay_transparent_border_opaque_square.png paste_result_background_plus_overlay_transparent_border_semitransparent_square.png paste_result_no_background_square_over_circle.png wx.png toucan.png toucan_hue_0.538.png toucan_sat_-0.41.png toucan_bright_-0.259.png toucan_hsv_0.538_-0.41_-0.259.png toucan_light_46.png toucan_dis_240.png toucan_grey.png toucan_mono_255_255_255.png width-times-height-overflow.bmp width_height_32_bit_overflow.pgm) do if not exist image\%%f copy .\image\%%f image
|
||||
for %%f in (bitfields.bmp bitfields-alpha.bmp 8bpp-colorsused-large.bmp 8bpp-colorsused-negative.bmp rle4-delta-320x240.bmp rle8-delta-320x240.bmp rle8-delta-320x240-expected.bmp horse_grey.bmp horse_grey_flipped.bmp horse_rle4.bmp horse_rle4_flipped.bmp horse_rle8.bmp horse_rle8_flipped.bmp horse_bicubic_50x50.png horse_bicubic_100x100.png horse_bicubic_150x150.png horse_bicubic_300x300.png horse_bilinear_50x50.png horse_bilinear_100x100.png horse_bilinear_150x150.png horse_bilinear_300x300.png horse_box_average_50x50.png horse_box_average_100x100.png horse_box_average_150x150.png horse_box_average_300x300.png cross_bicubic_256x256.png cross_bilinear_256x256.png cross_box_average_256x256.png cross_nearest_neighb_256x256.png paste_input_background.png paste_input_black.png paste_input_overlay_transparent_border_opaque_square.png paste_input_overlay_transparent_border_semitransparent_circle.png paste_input_overlay_transparent_border_semitransparent_square.png paste_result_background_plus_circle_plus_square.png paste_result_background_plus_overlay_transparent_border_opaque_square.png paste_result_background_plus_overlay_transparent_border_semitransparent_square.png paste_result_no_background_square_over_circle.png wx.png toucan.png toucan_hue_0.538.png toucan_sat_-0.41.png toucan_bright_-0.259.png toucan_hsv_0.538_-0.41_-0.259.png toucan_light_46.png toucan_dis_240.png toucan_grey.png toucan_mono_255_255_255.png width-times-height-overflow.bmp width_height_32_bit_overflow.pgm) do if not exist image\%%f copy .\image\%%f image
|
||||
|
||||
fr:
|
||||
if not exist $(OBJS)\intl\fr mkdir $(OBJS)\intl\fr
|
||||
|
|
|
|||
|
|
@ -845,7 +845,7 @@ data-image-sample:
|
|||
|
||||
data-images:
|
||||
if not exist image mkdir image
|
||||
for %f in (bitfields.bmp 8bpp-colorsused-large.bmp 8bpp-colorsused-negative.bmp rle4-delta-320x240.bmp rle8-delta-320x240.bmp rle8-delta-320x240-expected.bmp horse_grey.bmp horse_grey_flipped.bmp horse_rle4.bmp horse_rle4_flipped.bmp horse_rle8.bmp horse_rle8_flipped.bmp horse_bicubic_50x50.png horse_bicubic_100x100.png horse_bicubic_150x150.png horse_bicubic_300x300.png horse_bilinear_50x50.png horse_bilinear_100x100.png horse_bilinear_150x150.png horse_bilinear_300x300.png horse_box_average_50x50.png horse_box_average_100x100.png horse_box_average_150x150.png horse_box_average_300x300.png cross_bicubic_256x256.png cross_bilinear_256x256.png cross_box_average_256x256.png cross_nearest_neighb_256x256.png paste_input_background.png paste_input_black.png paste_input_overlay_transparent_border_opaque_square.png paste_input_overlay_transparent_border_semitransparent_circle.png paste_input_overlay_transparent_border_semitransparent_square.png paste_result_background_plus_circle_plus_square.png paste_result_background_plus_overlay_transparent_border_opaque_square.png paste_result_background_plus_overlay_transparent_border_semitransparent_square.png paste_result_no_background_square_over_circle.png wx.png toucan.png toucan_hue_0.538.png toucan_sat_-0.41.png toucan_bright_-0.259.png toucan_hsv_0.538_-0.41_-0.259.png toucan_light_46.png toucan_dis_240.png toucan_grey.png toucan_mono_255_255_255.png width-times-height-overflow.bmp width_height_32_bit_overflow.pgm) do if not exist image\%f copy .\image\%f image
|
||||
for %f in (bitfields.bmp bitfields-alpha.bmp 8bpp-colorsused-large.bmp 8bpp-colorsused-negative.bmp rle4-delta-320x240.bmp rle8-delta-320x240.bmp rle8-delta-320x240-expected.bmp horse_grey.bmp horse_grey_flipped.bmp horse_rle4.bmp horse_rle4_flipped.bmp horse_rle8.bmp horse_rle8_flipped.bmp horse_bicubic_50x50.png horse_bicubic_100x100.png horse_bicubic_150x150.png horse_bicubic_300x300.png horse_bilinear_50x50.png horse_bilinear_100x100.png horse_bilinear_150x150.png horse_bilinear_300x300.png horse_box_average_50x50.png horse_box_average_100x100.png horse_box_average_150x150.png horse_box_average_300x300.png cross_bicubic_256x256.png cross_bilinear_256x256.png cross_box_average_256x256.png cross_nearest_neighb_256x256.png paste_input_background.png paste_input_black.png paste_input_overlay_transparent_border_opaque_square.png paste_input_overlay_transparent_border_semitransparent_circle.png paste_input_overlay_transparent_border_semitransparent_square.png paste_result_background_plus_circle_plus_square.png paste_result_background_plus_overlay_transparent_border_opaque_square.png paste_result_background_plus_overlay_transparent_border_semitransparent_square.png paste_result_no_background_square_over_circle.png wx.png toucan.png toucan_hue_0.538.png toucan_sat_-0.41.png toucan_bright_-0.259.png toucan_hsv_0.538_-0.41_-0.259.png toucan_light_46.png toucan_dis_240.png toucan_grey.png toucan_mono_255_255_255.png width-times-height-overflow.bmp width_height_32_bit_overflow.pgm) do if not exist image\%f copy .\image\%f image
|
||||
|
||||
fr:
|
||||
if not exist $(OBJS)\intl\fr mkdir $(OBJS)\intl\fr
|
||||
|
|
|
|||
|
|
@ -354,6 +354,7 @@
|
|||
<dstdir>image</dstdir>
|
||||
<files>
|
||||
bitfields.bmp
|
||||
bitfields-alpha.bmp
|
||||
8bpp-colorsused-large.bmp
|
||||
8bpp-colorsused-negative.bmp
|
||||
rle4-delta-320x240.bmp
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue