Fix value returned by wxBitmap::GetDepth() in wxMSW

Some operations on wxBitmap involve converting the internal representation
from DIB to DDB, and when this is done it can happen that the resulting DDB
will have different colour depth than source DIB because CreateDIBitmap()
Windows API which is used for conversion purposes can create DDB with
"whatever bit depth your reference DC is".

Therefore after every operation which directly or indirectly employs
CreateDIBitmap() it is necessary to update respective data member with the
actual color depth of the obtained DDB.

Closes #17479.
Closes https://github.com/wxWidgets/wxWidgets/pull/265
This commit is contained in:
Artur Wieczorek 2016-04-03 12:51:03 +02:00 committed by Vadim Zeitlin
parent 8006c4fed1
commit ae1a332d1f

View File

@ -240,19 +240,17 @@ wxBitmapRefData::wxBitmapRefData(const wxBitmapRefData& data)
if ( data.m_hBitmap )
{
wxDIB dib((HBITMAP)(data.m_hBitmap));
// DDB obtained from CopyFromDIB() can have different
// colour depth than source DIB so we need to check it.
CopyFromDIB(dib);
BITMAP bm;
if ( ::GetObject(m_hBitmap, sizeof(bm), &bm) != sizeof(bm) )
if ( m_depth != dib.GetDepth() )
{
wxLogLastError(wxT("GetObject(hBitmap@wxBitmapRefData)"));
}
else if ( m_depth != bm.bmBitsPixel )
{
// We got DDB with a different colour depth then we wanted, so we
// We got DDB with a different colour depth than we wanted, so we
// can't use it and need to continue using the DIB instead.
wxDIB dibDst(m_width, m_height, m_depth);
wxDIB dibDst(m_width, m_height, dib.GetDepth());
if ( dibDst.IsOk() )
{
m_depth = dib.GetDepth();
memcpy(dibDst.GetData(), dib.GetData(),
wxDIB::GetLineSize(m_width, m_depth)*m_height);
AssignDIB(dibDst);
@ -260,7 +258,6 @@ wxBitmapRefData::wxBitmapRefData(const wxBitmapRefData& data)
else
{
// Nothing else left to do...
m_depth = bm.bmBitsPixel;
}
}
}
@ -337,6 +334,21 @@ void wxBitmapRefData::CopyFromDIB(const wxDIB& dib)
#endif // SOMETIMES_USE_DIB/ALWAYS_USE_DIB
InitFromDIB(dib, hbitmap);
if ( hbitmap )
{
// DDB obtained from CreatedDDB() can have different colour depth
// than source DIB and we have to adjust respective data member
// accordingly.
BITMAP bm;
if ( ::GetObject(hbitmap, sizeof(bm), &bm) != sizeof(bm) )
{
wxLogLastError(wxS("GetObject (@wxBitmapRefData::CopyFromDIB)"));
}
else
{
m_depth = bm.bmBitsPixel;
}
}
}
bool wxBitmapRefData::AssignDIB(wxDIB& dib)
@ -871,6 +883,18 @@ bool wxBitmap::CreateFromImage(const wxImage& image, int depth, WXHDC hdc)
else // we need to convert DIB to DDB
{
hbitmap = dib.CreateDDB((HDC)hdc);
// DDB obtained from CreatedDDB() can have different colour depth
// than source DIB and we have to adjust respective data member
// accordingly.
BITMAP bm;
if ( ::GetObject(hbitmap, sizeof(bm), &bm) != sizeof(bm) )
{
wxLogLastError(wxS("GetObject (@wxBitmap::CreateFromImage)"));
}
else
{
refData->m_depth = bm.bmBitsPixel;
}
}
#endif // !ALWAYS_USE_DIB