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 ) if ( data.m_hBitmap )
{ {
wxDIB dib((HBITMAP)(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); CopyFromDIB(dib);
BITMAP bm; if ( m_depth != dib.GetDepth() )
if ( ::GetObject(m_hBitmap, sizeof(bm), &bm) != sizeof(bm) )
{ {
wxLogLastError(wxT("GetObject(hBitmap@wxBitmapRefData)")); // We got DDB with a different colour depth than we wanted, so we
}
else if ( m_depth != bm.bmBitsPixel )
{
// We got DDB with a different colour depth then we wanted, so we
// can't use it and need to continue using the DIB instead. // 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() ) if ( dibDst.IsOk() )
{ {
m_depth = dib.GetDepth();
memcpy(dibDst.GetData(), dib.GetData(), memcpy(dibDst.GetData(), dib.GetData(),
wxDIB::GetLineSize(m_width, m_depth)*m_height); wxDIB::GetLineSize(m_width, m_depth)*m_height);
AssignDIB(dibDst); AssignDIB(dibDst);
@@ -260,7 +258,6 @@ wxBitmapRefData::wxBitmapRefData(const wxBitmapRefData& data)
else else
{ {
// Nothing else left to do... // 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 #endif // SOMETIMES_USE_DIB/ALWAYS_USE_DIB
InitFromDIB(dib, hbitmap); 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) 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 else // we need to convert DIB to DDB
{ {
hbitmap = dib.CreateDDB((HDC)hdc); 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 #endif // !ALWAYS_USE_DIB