From 22be0335df28fd3e638c40fe525b6ff323e73c15 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 23 Mar 2003 15:51:37 +0000 Subject: [PATCH] got rid of more duplicated code for working with DIBs git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@19730 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/msw/dib.h | 42 ++++++----- src/msw/dib.cpp | 155 ++++++++++++++++++++++++++++++++-------- src/msw/ole/dataobj.cpp | 154 ++++----------------------------------- 3 files changed, 158 insertions(+), 193 deletions(-) diff --git a/include/wx/msw/dib.h b/include/wx/msw/dib.h index a72122254a..1bade8910c 100644 --- a/include/wx/msw/dib.h +++ b/include/wx/msw/dib.h @@ -55,7 +55,7 @@ public: // 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) @@ -89,6 +89,25 @@ public: 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 // ------------------ @@ -180,32 +199,11 @@ inline wxDIB::~wxDIB() 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); diff --git a/src/msw/dib.cpp b/src/msw/dib.cpp index 6b676935ee..8722427148 100644 --- a/src/msw/dib.cpp +++ b/src/msw/dib.cpp @@ -46,6 +46,19 @@ #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 // ============================================================================ @@ -79,11 +92,8 @@ bool wxDIB::Create(int width, int height, int depth) 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) @@ -165,6 +175,10 @@ void wxDIB::DoGetObject() const } } +// ---------------------------------------------------------------------------- +// DDB <-> DIB conversions +// ---------------------------------------------------------------------------- + HBITMAP wxDIB::CreateDDB(HDC hdc) const { wxCHECK_MSG( m_handle, 0, _T("wxDIB::CreateDDB(): invalid object") ); @@ -177,45 +191,126 @@ HBITMAP wxDIB::CreateDDB(HDC hdc) const 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 diff --git a/src/msw/ole/dataobj.cpp b/src/msw/ole/dataobj.cpp index a4375d010e..0a594fd69f 100644 --- a/src/msw/ole/dataobj.cpp +++ b/src/msw/ole/dataobj.cpp @@ -757,23 +757,29 @@ const wxChar *wxDataObject::GetFormatName(wxDataFormat format) 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); @@ -1157,140 +1163,6 @@ void wxURLDataObject::SetURL(const wxString& url) // 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) -- 2.45.2