Add support for loading old V1 bitmap files to wxBMPHandler.

Such files are apparently still seen in the wild, even though this format has
been superseded since Windows 3.0 (!).

Closes #3433.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@76144 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2014-03-14 01:36:54 +00:00
parent ffeba70599
commit 371928415a
3 changed files with 99 additions and 27 deletions

View File

@@ -39,6 +39,7 @@ All (GUI):
- Added on-demand image loading option to wxRTC. - Added on-demand image loading option to wxRTC.
- Add wxFont::GetBaseFont() (Melroy Tellis). - Add wxFont::GetBaseFont() (Melroy Tellis).
- Update included Scintilla to version 3.3.9 (Christian Walther). - Update included Scintilla to version 3.3.9 (Christian Walther).
- Add support for loading old V1 BMP files to wxImage (Artur Wieczorek).
wxGTK: wxGTK:

View File

@@ -60,7 +60,7 @@ protected:
bool IsBmp, bool IsMask); bool IsBmp, bool IsMask);
bool DoLoadDib(wxImage *image, int width, int height, int bpp, int ncolors, bool DoLoadDib(wxImage *image, int width, int height, int bpp, int ncolors,
int comp, wxFileOffset bmpOffset, wxInputStream& stream, int comp, wxFileOffset bmpOffset, wxInputStream& stream,
bool verbose, bool IsBmp, bool hasPalette); bool verbose, bool IsBmp, bool hasPalette, int colEntrySize = 4);
bool LoadDib(wxImage *image, wxInputStream& stream, bool verbose, bool IsBmp); bool LoadDib(wxImage *image, wxInputStream& stream, bool verbose, bool IsBmp);
#endif // wxUSE_STREAMS #endif // wxUSE_STREAMS

View File

@@ -499,7 +499,8 @@ struct BMPPalette
bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height,
int bpp, int ncolors, int comp, int bpp, int ncolors, int comp,
wxFileOffset bmpOffset, wxInputStream& stream, wxFileOffset bmpOffset, wxInputStream& stream,
bool verbose, bool IsBmp, bool hasPalette) bool verbose, bool IsBmp, bool hasPalette,
int colEntrySize)
{ {
wxInt32 aDword, rmask = 0, gmask = 0, bmask = 0, amask = 0; wxInt32 aDword, rmask = 0, gmask = 0, bmask = 0, amask = 0;
int rshift = 0, gshift = 0, bshift = 0, ashift = 0; int rshift = 0, gshift = 0, bshift = 0, ashift = 0;
@@ -585,7 +586,7 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height,
{ {
if (hasPalette) if (hasPalette)
{ {
if ( !stream.ReadAll(bbuf, 4) ) if ( !stream.ReadAll(bbuf, colEntrySize) )
return false; return false;
cmap[j].b = bbuf[0]; cmap[j].b = bbuf[0];
@@ -997,28 +998,57 @@ bool wxBMPHandler::LoadDib(wxImage *image, wxInputStream& stream,
wxInt32 dbuf[4]; wxInt32 dbuf[4];
wxInt8 bbuf[4]; wxInt8 bbuf[4];
// offset to bitmap data
wxFileOffset offset;
// DIB header size (used to distinguish different versions of DIB header)
wxInt32 hdrSize;
if ( IsBmp ) if ( IsBmp )
{ {
// read the header off the .BMP format file // read the header off the .BMP format file
if ( !stream.ReadAll(bbuf, 2) || if ( !stream.ReadAll(bbuf, 2) ||
!stream.ReadAll(dbuf, 16) ) !stream.ReadAll(dbuf, 16) )
return false; return false;
#if 0 // unused
wxInt32 size = wxINT32_SWAP_ON_BE(dbuf[0]);
#endif
offset = wxINT32_SWAP_ON_BE(dbuf[2]);
hdrSize = wxINT32_SWAP_ON_BE(dbuf[3]);
} }
else else
{ {
if ( !stream.ReadAll(dbuf, 4) ) if ( !stream.ReadAll(dbuf, 4) )
return false; return false;
}
#if 0 // unused
wxInt32 size = wxINT32_SWAP_ON_BE(dbuf[0]);
#endif
wxFileOffset offset = wxINT32_SWAP_ON_BE(dbuf[2]);
offset = wxInvalidOffset; // not used in loading ICO/CUR DIBs
hdrSize = wxINT32_SWAP_ON_BE(dbuf[0]);
}
// Bitmap files come in old v1 format using BITMAPCOREHEADER or a newer
// format (typically BITMAPV5HEADER, in use since Windows 98, but we don't
// really support any features specific to later formats such as gamma
// correction or ICC profiles, so it doesn't matter much to us).
const bool usesV1 = hdrSize == 12;
int width;
int height;
if ( usesV1 )
{
wxInt16 buf[2];
if ( !stream.ReadAll(buf, sizeof(buf)) )
return false;
width = wxINT16_SWAP_ON_BE((short)buf[0]);
height = wxINT16_SWAP_ON_BE((short)buf[1]);
}
else // We have at least BITMAPINFOHEADER
{
if ( !stream.ReadAll(dbuf, 4 * 2) ) if ( !stream.ReadAll(dbuf, 4 * 2) )
return false; return false;
int width = wxINT32_SWAP_ON_BE((int)dbuf[0]); width = wxINT32_SWAP_ON_BE((int)dbuf[0]);
int height = wxINT32_SWAP_ON_BE((int)dbuf[1]); height = wxINT32_SWAP_ON_BE((int)dbuf[1]);
}
if ( !IsBmp)height = height / 2; // for icons divide by 2 if ( !IsBmp)height = height / 2; // for icons divide by 2
if ( width > 32767 ) if ( width > 32767 )
@@ -1058,10 +1088,45 @@ bool wxBMPHandler::LoadDib(wxImage *image, wxInputStream& stream,
return false; return false;
} }
class Resolution
{
public:
Resolution()
{
m_valid = false;
}
void Init(int x, int y)
{
m_x = x;
m_y = y;
m_valid = false;
}
bool IsValid() const { return m_valid; }
int GetX() const { return m_x; }
int GetY() const { return m_y; }
private:
int m_x, m_y;
bool m_valid;
} res;
int comp;
int ncolors;
if ( usesV1 )
{
// The only possible format is BI_RGB and colours count is not used.
comp = BI_RGB;
ncolors = 0;
}
else // We have at least BITMAPINFOHEADER
{
if ( !stream.ReadAll(dbuf, 4 * 4) ) if ( !stream.ReadAll(dbuf, 4 * 4) )
return false; return false;
int comp = wxINT32_SWAP_ON_BE((int)dbuf[0]); comp = wxINT32_SWAP_ON_BE((int)dbuf[0]);
if ( comp != BI_RGB && comp != BI_RLE4 && comp != BI_RLE8 && if ( comp != BI_RGB && comp != BI_RLE4 && comp != BI_RLE8 &&
comp != BI_BITFIELDS ) comp != BI_BITFIELDS )
{ {
@@ -1075,7 +1140,9 @@ bool wxBMPHandler::LoadDib(wxImage *image, wxInputStream& stream,
if ( !stream.ReadAll(dbuf, 4 * 2) ) if ( !stream.ReadAll(dbuf, 4 * 2) )
return false; return false;
int ncolors = wxINT32_SWAP_ON_BE( (int)dbuf[0] ); ncolors = wxINT32_SWAP_ON_BE( (int)dbuf[0] );
res.Init(dbuf[2]/100, dbuf[3]/100);
}
if (ncolors == 0) if (ncolors == 0)
ncolors = 1 << bpp; ncolors = 1 << bpp;
/* some more sanity checks */ /* some more sanity checks */
@@ -1092,7 +1159,8 @@ bool wxBMPHandler::LoadDib(wxImage *image, wxInputStream& stream,
//read DIB; this is the BMP image or the XOR part of an icon image //read DIB; this is the BMP image or the XOR part of an icon image
if ( !DoLoadDib(image, width, height, bpp, ncolors, comp, offset, stream, if ( !DoLoadDib(image, width, height, bpp, ncolors, comp, offset, stream,
verbose, IsBmp, true) ) verbose, IsBmp, true,
usesV1 ? 3 : 4) )
{ {
if (verbose) if (verbose)
{ {
@@ -1120,9 +1188,12 @@ bool wxBMPHandler::LoadDib(wxImage *image, wxInputStream& stream,
} }
// the resolution in the bitmap header is in meters, convert to centimeters // the resolution in the bitmap header is in meters, convert to centimeters
if ( res.IsValid() )
{
image->SetOption(wxIMAGE_OPTION_RESOLUTIONUNIT, wxIMAGE_RESOLUTION_CM); image->SetOption(wxIMAGE_OPTION_RESOLUTIONUNIT, wxIMAGE_RESOLUTION_CM);
image->SetOption(wxIMAGE_OPTION_RESOLUTIONX, dbuf[2]/100); image->SetOption(wxIMAGE_OPTION_RESOLUTIONX, res.GetX());
image->SetOption(wxIMAGE_OPTION_RESOLUTIONY, dbuf[3]/100); image->SetOption(wxIMAGE_OPTION_RESOLUTIONY, res.GetY());
}
return true; return true;
} }