X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/2b254edf9cb508b48bfd3f9cf76d46f7cf1e1f5b..a6c811617b84695050e16f09b4fee518c89665a7:/src/msw/dib.cpp diff --git a/src/msw/dib.cpp b/src/msw/dib.cpp index fe4136e2a3..3b42e9c0f7 100644 --- a/src/msw/dib.cpp +++ b/src/msw/dib.cpp @@ -12,8 +12,7 @@ /* TODO: support for palettes is very incomplete, several functions simply ignore them (we should select and realize the palette, if any, before - caling GetDIBits() in the DC we use with it and we shouldn't use - GetBitmapBits() at all because we can't do it with it) + caling GetDIBits() in the DC we use with it. */ // ============================================================================ @@ -36,6 +35,8 @@ #include "wx/log.h" #endif //WX_PRECOMP +#if wxUSE_WXDIB + #include "wx/bitmap.h" #include "wx/intl.h" #include "wx/file.h" @@ -60,13 +61,24 @@ // calculate the number of palette entries needed for the bitmap with this // number of bits per pixel -static WORD wxGetNumOfBitmapColors(WORD bitsPerPixel) +static inline WORD wxGetNumOfBitmapColors(WORD bitsPerPixel) { // only 1, 4 and 8bpp bitmaps use palettes (well, they could be used with // 24bpp ones too but we don't support this as I think it's quite uncommon) return bitsPerPixel <= 8 ? 1 << bitsPerPixel : 0; } +// wrapper around ::GetObject() for DIB sections +static inline bool GetDIBSection(HBITMAP hbmp, DIBSECTION *ds) +{ + // note that at least under Win9x (this doesn't seem to happen under Win2K + // but this doesn't mean anything, of course), GetObject() may return + // sizeof(DIBSECTION) for a bitmap which is *not* a DIB section and the way + // to check for it is by looking at the bits pointer + return ::GetObject(hbmp, sizeof(DIBSECTION), ds) == sizeof(DIBSECTION) && + ds->dsBm.bmBits; +} + // ============================================================================ // implementation // ============================================================================ @@ -84,7 +96,7 @@ bool wxDIB::Create(int width, int height, int depth) static const int infosize = sizeof(BITMAPINFOHEADER); BITMAPINFO *info = (BITMAPINFO *)malloc(infosize); - wxCHECK_MSG( info, NULL, _T("malloc(BITMAPINFO) failed") ); + wxCHECK_MSG( info, false, _T("malloc(BITMAPINFO) failed") ); memset(info, 0, infosize); @@ -132,26 +144,59 @@ bool wxDIB::Create(const wxBitmap& bmp) { wxCHECK_MSG( bmp.Ok(), false, _T("wxDIB::Create(): invalid bitmap") ); - const int w = bmp.GetWidth(); - const int h = bmp.GetHeight(); - int d = bmp.GetDepth(); - if ( d == -1 ) - d = wxDisplayDepth(); + // this bitmap could already be a DIB section in which case we don't need + // to convert it to DIB + HBITMAP hbmp = GetHbitmapOf(bmp); - if ( !Create(w, h, d) ) - return false; + DIBSECTION ds; + if ( GetDIBSection(hbmp, &ds) ) + { + m_handle = hbmp; - // we could have used GetDIBits() too but GetBitmapBits() is simpler - if ( !::GetBitmapBits - ( - GetHbitmapOf(bmp), // the source DDB - GetLineSize(w, d)*h, // the number of bytes to copy - m_data // the pixels will be copied here - ) ) + // wxBitmap will free it, not we + m_ownsHandle = false; + + // copy all the bitmap parameters too as we have them now anyhow + m_width = ds.dsBm.bmWidth; + m_height = ds.dsBm.bmHeight; + m_depth = ds.dsBm.bmBitsPixel; + + m_data = ds.dsBm.bmBits; + } + else // no, it's a DDB -- convert it to DIB { - wxLogLastError(wxT("GetDIBits()")); + const int w = bmp.GetWidth(); + const int h = bmp.GetHeight(); + int d = bmp.GetDepth(); + if ( d == -1 ) + d = wxDisplayDepth(); - return 0; + if ( !Create(w, h, d) ) + return false; + + if ( !GetDIBSection(m_handle, &ds) ) + { + // we've just created a new DIB section, why should this fail? + wxFAIL_MSG( _T("GetObject(DIBSECTION) unexpectedly failed") ); + + return false; + } + + if ( !::GetDIBits + ( + ScreenHDC(), // the DC to use + hbmp, // the source DDB + 0, // first scan line + h, // number of lines to copy + ds.dsBm.bmBits, // pointer to the buffer + (BITMAPINFO *)&ds.dsBmih, // bitmap header + DIB_RGB_COLORS // and not DIB_PAL_COLORS + ) ) + { + wxLogLastError(wxT("GetDIBits()")); + + return 0; + } } return true; @@ -190,7 +235,7 @@ bool wxDIB::Save(const wxString& filename) if ( ok ) { DIBSECTION ds; - if ( !::GetObject(m_handle, sizeof(ds), &ds) ) + if ( !GetDIBSection(m_handle, &ds) ) { wxLogLastError(_T("GetObject(hDIB)")); } @@ -239,7 +284,7 @@ void wxDIB::DoGetObject() const // check for this now rather than trying to find out why it doesn't // work later DIBSECTION ds; - if ( !::GetObject(m_handle, sizeof(ds), &ds) ) + if ( !GetDIBSection(m_handle, &ds) ) { wxLogLastError(_T("GetObject(hDIB)")); return; @@ -263,7 +308,7 @@ HBITMAP wxDIB::CreateDDB(HDC hdc) const wxCHECK_MSG( m_handle, 0, _T("wxDIB::CreateDDB(): invalid object") ); DIBSECTION ds; - if ( !::GetObject(m_handle, sizeof(ds), &ds) ) + if ( !GetDIBSection(m_handle, &ds) ) { wxLogLastError(_T("GetObject(hDIB)")); @@ -288,13 +333,31 @@ HBITMAP wxDIB::ConvertToBitmap(const BITMAPINFO *pbmi, HDC hdc, void *bits) if ( !bits ) { // we must skip over the colour table to get to the image data - - // biClrUsed has the number of colors but it may be not initialized at - // all - int numColors = pbmih->biClrUsed; - if ( !numColors ) + // + // colour table either has the real colour data in which case its + // number of entries is given by biClrUsed or is used for masks to be + // used for extracting colour information from true colour bitmaps in + // which case it always have exactly 3 DWORDs + int numColors; + switch ( pbmih->biCompression ) { - numColors = wxGetNumOfBitmapColors(pbmih->biBitCount); + case BI_BITFIELDS: + numColors = 3; + break; + + case BI_RGB: + // biClrUsed has the number of colors but it may be not initialized at + // all + numColors = pbmih->biClrUsed; + if ( !numColors ) + { + numColors = wxGetNumOfBitmapColors(pbmih->biBitCount); + } + break; + + default: + // no idea how it should be calculated for the other cases + numColors = 0; } bits = (char *)pbmih + sizeof(*pbmih) + numColors*sizeof(RGBQUAD); @@ -303,7 +366,7 @@ HBITMAP wxDIB::ConvertToBitmap(const BITMAPINFO *pbmi, HDC hdc, void *bits) HBITMAP hbmp = ::CreateDIBitmap ( hdc ? hdc // create bitmap compatible - : ScreenHDC(), // with this DC + : (HDC) ScreenHDC(), // with this DC pbmih, // used to get size &c CBM_INIT, // initialize bitmap bits too bits, // ... using this data @@ -400,7 +463,7 @@ HGLOBAL wxDIB::ConvertFromBitmap(HBITMAP hbmp) return NULL; } - if ( !ConvertFromBitmap((BITMAPINFO *)GlobalHandle(hDIB), hbmp) ) + if ( !ConvertFromBitmap((BITMAPINFO *)(void *)GlobalPtr(hDIB), hbmp) ) { // this really shouldn't happen... it worked the first time, why not // now? @@ -423,7 +486,7 @@ wxPalette *wxDIB::CreatePalette() const wxCHECK_MSG( m_handle, NULL, _T("wxDIB::CreatePalette(): invalid object") ); DIBSECTION ds; - if ( !::GetObject(m_handle, sizeof(ds), &ds) ) + if ( !GetDIBSection(m_handle, &ds) ) { wxLogLastError(_T("GetObject(hDIB)")); @@ -545,3 +608,6 @@ bool wxDIB::Create(const wxImage& image) #endif // wxUSE_IMAGE +#endif + // wxUSE_WXDIB +