// create a bitmap compatiblr with the given HDC (or screen by default) and
// return its handle, the caller is responsible for freeing it (using
// DeleteObject())
- HBITMAP CreateDDB(HDC hdc = NULL) const;
+ HBITMAP CreateDDB(HDC hdc = 0) const;
// get the handle from the DIB and reset it, i.e. this object won't destroy
// the DIB after this (but the caller should do it)
void *GetData() const { DoGetObject(); return m_data; }
+ // HBITMAP conversion
+ // ------------------
+
+ // these functions are only used by wxBitmapDataObject implementation in
+ // src/msw/ole/dataobj.cpp, don't use them directly if possible
+
+ // creates a DDB compatible with the given (or screen) DC from either
+ // a plain DIB or a DIB section (in which case the last parameter must be
+ // non NULL)
+ static HBITMAP ConvertToBitmap(const BITMAPINFO *pbi,
+ HDC hdc = 0,
+ void *bits = NULL);
+
+ // creates a DIB from the given DDB or calculates the space needed by it:
+ // if pbi is NULL, only the space is calculated, otherwise pbi is supposed
+ // to point at BITMAPINFO of the correct size which is filled by this
+ // function
+ static size_t ConvertFromBitmap(BITMAPINFO *pbi, HBITMAP hbmp);
+
// wxImage conversion
// ------------------
Free();
}
-// ----------------------------------------------------------------------------
-// Functions for working with DIBs
-// ----------------------------------------------------------------------------
-
-// WARNING: these functions are private to wxWindows and shouldn't be used
-// by the user code, they risk to disappear in the next versions!
-
-// VZ: we have 3 different sets of functions: from bitmap.cpp (wxCreateDIB and
-// wxFreeDIB), from dib.cpp and from dataobj.cpp - surely there is some
-// redundancy between them? (FIXME)
-
-// defined in ole/dataobj.cpp
-extern WXDLLEXPORT size_t wxConvertBitmapToDIB(LPBITMAPINFO pbi, const wxBitmap& bitmap);
-extern WXDLLEXPORT wxBitmap wxConvertDIBToBitmap(const LPBITMAPINFO pbi);
-
// the rest is defined in dib.cpp
// Save (device dependent) wxBitmap as a DIB
bool wxSaveBitmap(wxChar *filename, wxBitmap *bitmap, wxPalette *palette = NULL);
-// Load device independent bitmap into device dependent bitmap
-wxBitmap *wxLoadBitmap(wxChar *filename, wxPalette **palette = NULL);
-
-// Load into existing bitmap;
-bool wxLoadIntoBitmap(wxChar *filename, wxBitmap *bitmap, wxPalette **pal = NULL);
-
HANDLE wxBitmapToDIB (HBITMAP hBitmap, HPALETTE hPal);
bool wxReadDIB(LPTSTR lpFileName, HBITMAP *bitmap, HPALETTE *palette);
HANDLE wxReadDIB2(LPTSTR lpFileName);
#include "wx/image.h"
#include "wx/msw/dib.h"
+// ----------------------------------------------------------------------------
+// private functions
+// ----------------------------------------------------------------------------
+
+// calculate the number of palette entries needed for the bitmap with this
+// number of bits per pixel
+static 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;
+}
+
// ============================================================================
// implementation
// ============================================================================
info->bmiHeader.biPlanes = 1;
info->bmiHeader.biBitCount = depth;
- info->bmiHeader.biCompression = BI_RGB;
info->bmiHeader.biSizeImage = GetLineSize(width, depth)*height;
- // No need to report an error here. If it fails, we just won't use a
- // file mapping and CreateDIBSection will just allocate memory for us.
m_handle = ::CreateDIBSection
(
0, // hdc (unused with DIB_RGB_COLORS)
}
}
+// ----------------------------------------------------------------------------
+// DDB <-> DIB conversions
+// ----------------------------------------------------------------------------
+
HBITMAP wxDIB::CreateDDB(HDC hdc) const
{
wxCHECK_MSG( m_handle, 0, _T("wxDIB::CreateDDB(): invalid object") );
return 0;
}
- HBITMAP hbitmap = ::CreateCompatibleBitmap
- (
- hdc ? hdc : ScreenHDC(),
- ds.dsBm.bmWidth,
- ds.dsBm.bmHeight
- );
- if ( !hbitmap )
+ return ConvertToBitmap((BITMAPINFO *)&ds.dsBmih, hdc, ds.dsBm.bmBits);
+}
+
+/* static */
+HBITMAP wxDIB::ConvertToBitmap(const BITMAPINFO *pbmi, HDC hdc, void *bits)
+{
+ wxCHECK_MSG( pbmi, 0, _T("invalid DIB in ConvertToBitmap") );
+
+ // here we get BITMAPINFO struct followed by the actual bitmap bits and
+ // BITMAPINFO starts with BITMAPINFOHEADER followed by colour info
+ const BITMAPINFOHEADER *pbmih = &pbmi->bmiHeader;
+
+ // get the pointer to the start of the real image data if we have a plain
+ // DIB and not a DIB section (in the latter case the pointer must be passed
+ // to us by the caller)
+ if ( !bits )
{
- wxLogLastError(_T("CreateCompatibleBitmap()"));
+ // we must skip over the colour table to get to the image data
- return 0;
+ // biClrUsed has the number of colors but it may be not initialized at
+ // all
+ int numColors = pbmih->biClrUsed;
+ if ( !numColors )
+ {
+ numColors = wxGetNumOfBitmapColors(pbmih->biBitCount);
+ }
+
+ bits = (char *)pbmih + sizeof(*pbmih) + numColors*sizeof(RGBQUAD);
}
- MemoryHDC hdcMem;
- SelectInHDC select(hdcMem, hbitmap);
- if ( !select )
+ HBITMAP hbmp = ::CreateDIBitmap
+ (
+ hdc ? hdc // create bitmap compatible
+ : ScreenHDC(), // with this DC
+ pbmih, // used to get size &c
+ CBM_INIT, // initialize bitmap bits too
+ bits, // ... using this data
+ pbmi, // this is used for palette only
+ DIB_RGB_COLORS // direct or indexed palette?
+ );
+
+ if ( !hbmp )
{
- wxLogLastError(_T("SelectObjct(hBitmap)"));
- }
-
- if ( !::SetDIBits
- (
- hdcMem,
- hbitmap,
- 0,
- ds.dsBm.bmHeight,
- ds.dsBm.bmBits,
- (BITMAPINFO *)&ds.dsBmih,
- DIB_RGB_COLORS
- ) )
+ wxLogLastError(wxT("CreateDIBitmap"));
+ }
+
+ return hbmp;
+}
+
+/* static */
+size_t wxDIB::ConvertFromBitmap(BITMAPINFO *pbi, HBITMAP hbmp)
+{
+ wxASSERT_MSG( hbmp, wxT("invalid bmp can't be converted to DIB") );
+
+ // prepare all the info we need
+ BITMAP bm;
+ if ( !::GetObject(hbmp, sizeof(bm), &bm) )
+ {
+ wxLogLastError(wxT("GetObject(bitmap)"));
+
+ return 0;
+ }
+
+ // calculate the number of bits per pixel and the number of items in
+ // bmiColors array (whose meaning depends on the bitmap format)
+ WORD biBits = bm.bmPlanes * bm.bmBitsPixel;
+ WORD biColors = wxGetNumOfBitmapColors(biBits);
+
+ // we need a BITMAPINFO anyhow and if we're not given a pointer to it we
+ // use this one
+ BITMAPINFO bi2;
+
+ bool wantSizeOnly = pbi == NULL;
+ if ( wantSizeOnly )
+ pbi = &bi2;
+
+ // just for convenience
+ const int h = bm.bmHeight;
+
+ // init the header
+ BITMAPINFOHEADER& bi = pbi->bmiHeader;
+ wxZeroMemory(bi);
+ bi.biSize = sizeof(BITMAPINFOHEADER);
+ bi.biWidth = bm.bmWidth;
+ bi.biHeight = h;
+ bi.biPlanes = 1;
+ bi.biBitCount = biBits;
+
+ // memory we need for BITMAPINFO only
+ DWORD dwLen = bi.biSize + biColors * sizeof(RGBQUAD);
+
+ // first get the image size
+ ScreenHDC hdc;
+ if ( !::GetDIBits(hdc, hbmp, 0, h, NULL, pbi, DIB_RGB_COLORS) )
{
- wxLogLastError(_T("SetDIBits"));
+ wxLogLastError(wxT("GetDIBits(NULL)"));
return 0;
}
- return hbitmap;
+ if ( !wantSizeOnly )
+ {
+ // and now copy the bits
+ void *image = (char *)pbi + dwLen;
+ if ( !::GetDIBits(hdc, hbmp, 0, h, image, pbi, DIB_RGB_COLORS) )
+ {
+ wxLogLastError(wxT("GetDIBits"));
+
+ return 0;
+ }
+ }
+
+ // return the total size
+ return dwLen + bi.biSizeImage;
}
+// ----------------------------------------------------------------------------
+// palette support
+// ----------------------------------------------------------------------------
+
#if wxUSE_PALETTE
wxPalette *wxDIB::CreatePalette() const
size_t wxBitmapDataObject::GetDataSize() const
{
- return wxConvertBitmapToDIB(NULL, GetBitmap());
+ return wxDIB::ConvertFromBitmap(NULL, GetHbitmapOf(GetBitmap()));
}
bool wxBitmapDataObject::GetDataHere(void *buf) const
{
- return wxConvertBitmapToDIB((LPBITMAPINFO)buf, GetBitmap()) != 0;
+ BITMAPINFO * const pbi = (BITMAPINFO *)buf;
+
+ return wxDIB::ConvertFromBitmap(pbi, GetHbitmapOf(GetBitmap())) != 0;
}
bool wxBitmapDataObject::SetData(size_t WXUNUSED(len), const void *buf)
{
- wxBitmap bitmap(wxConvertDIBToBitmap((const LPBITMAPINFO)buf));
+ const BITMAPINFO * const pbmi = (const BITMAPINFO *)buf;
- if ( !bitmap.Ok() ) {
- wxFAIL_MSG(wxT("pasting/dropping invalid bitmap"));
+ HBITMAP hbmp = wxDIB::ConvertToBitmap(pbmi);
- return FALSE;
- }
+ wxCHECK_MSG( hbmp, FALSE, wxT("pasting/dropping invalid bitmap") );
+
+ const BITMAPINFOHEADER * const pbmih = &pbmi->bmiHeader;
+ wxBitmap bitmap(pbmih->biWidth, pbmih->biHeight, pbmih->biBitCount);
+ bitmap.SetHBITMAP((WXHBITMAP)hbmp);
+
+ // TODO: create wxPalette if the bitmap has any
SetBitmap(bitmap);
// private functions
// ----------------------------------------------------------------------------
-static size_t wxGetNumOfBitmapColors(size_t bitsPerPixel)
-{
- switch ( bitsPerPixel )
- {
- case 1:
- // monochrome bitmap, 2 entries
- return 2;
-
- case 4:
- return 16;
-
- case 8:
- return 256;
-
- case 24:
- // may be used with 24bit bitmaps, but we don't use it here - fall
- // through
-
- case 16:
- case 32:
- // bmiColors not used at all with these bitmaps
- return 0;
-
- default:
- wxFAIL_MSG( wxT("unknown bitmap format") );
- return 0;
- }
-}
-
-size_t wxConvertBitmapToDIB(LPBITMAPINFO pbi, const wxBitmap& bitmap)
-{
- wxASSERT_MSG( bitmap.Ok(), wxT("invalid bmp can't be converted to DIB") );
-
- // shouldn't be selected into a DC or GetDIBits() would fail
- wxASSERT_MSG( !bitmap.GetSelectedInto(),
- wxT("can't copy bitmap selected into wxMemoryDC") );
-
- // prepare all the info we need
- BITMAP bm;
- HBITMAP hbmp = (HBITMAP)bitmap.GetHBITMAP();
- if ( !GetObject(hbmp, sizeof(bm), &bm) )
- {
- wxLogLastError(wxT("GetObject(bitmap)"));
-
- return 0;
- }
-
- // calculate the number of bits per pixel and the number of items in
- // bmiColors array (whose meaning depends on the bitmap format)
- WORD biBits = bm.bmPlanes * bm.bmBitsPixel;
- WORD biColors = (WORD)wxGetNumOfBitmapColors(biBits);
-
- BITMAPINFO bi2;
-
- bool wantSizeOnly = pbi == NULL;
- if ( wantSizeOnly )
- pbi = &bi2;
-
- // just for convenience
- BITMAPINFOHEADER& bi = pbi->bmiHeader;
-
- bi.biSize = sizeof(BITMAPINFOHEADER);
- bi.biWidth = bm.bmWidth;
- bi.biHeight = bm.bmHeight;
- bi.biPlanes = 1;
- bi.biBitCount = biBits;
- bi.biCompression = BI_RGB;
- bi.biSizeImage = 0;
- bi.biXPelsPerMeter = 0;
- bi.biYPelsPerMeter = 0;
- bi.biClrUsed = 0;
- bi.biClrImportant = 0;
-
- // memory we need for BITMAPINFO only
- DWORD dwLen = bi.biSize + biColors * sizeof(RGBQUAD);
-
- // first get the image size
- ScreenHDC hdc;
- if ( !GetDIBits(hdc, hbmp, 0, bi.biHeight, NULL, pbi, DIB_RGB_COLORS) )
- {
- wxLogLastError(wxT("GetDIBits(NULL)"));
-
- return 0;
- }
-
- if ( wantSizeOnly )
- {
- // size of the header + size of the image
- return dwLen + bi.biSizeImage;
- }
-
- // and now copy the bits
- void *image = (char *)pbi + dwLen;
- if ( !GetDIBits(hdc, hbmp, 0, bi.biHeight, image, pbi, DIB_RGB_COLORS) )
- {
- wxLogLastError(wxT("GetDIBits"));
-
- return 0;
- }
-
- return dwLen + bi.biSizeImage;
-}
-
-wxBitmap wxConvertDIBToBitmap(const LPBITMAPINFO pbmi)
-{
- // here we get BITMAPINFO struct followed by the actual bitmap bits and
- // BITMAPINFO starts with BITMAPINFOHEADER followed by colour info
- const BITMAPINFOHEADER *pbmih = &pbmi->bmiHeader;
-
- // biClrUsed has the number of colors, unless it's 0
- int numColors = pbmih->biClrUsed;
- if (numColors==0)
- {
- numColors = wxGetNumOfBitmapColors(pbmih->biBitCount);
- }
-
- // offset of image from the beginning of the header
- DWORD ofs = numColors * sizeof(RGBQUAD);
- void *image = (char *)pbmih + sizeof(BITMAPINFOHEADER) + ofs;
-
- ScreenHDC hdc;
- HBITMAP hbmp = CreateDIBitmap(hdc, pbmih, CBM_INIT,
- image, pbmi, DIB_RGB_COLORS);
- if ( !hbmp )
- {
- wxLogLastError(wxT("CreateDIBitmap"));
- }
-
- wxBitmap bitmap(pbmih->biWidth, pbmih->biHeight, pbmih->biBitCount);
- bitmap.SetHBITMAP((WXHBITMAP)hbmp);
-
- return bitmap;
-}
-
#ifdef __WXDEBUG__
static const wxChar *GetTymedName(DWORD tymed)