]> git.saurik.com Git - wxWidgets.git/commitdiff
got rid of more duplicated code for working with DIBs
authorVadim Zeitlin <vadim@wxwidgets.org>
Sun, 23 Mar 2003 15:51:37 +0000 (15:51 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sun, 23 Mar 2003 15:51:37 +0000 (15:51 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@19730 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/msw/dib.h
src/msw/dib.cpp
src/msw/ole/dataobj.cpp

index a72122254a3846ec0fe14f19c118ed10c5caa1df..1bade8910c33e8df1dff791d8eac6e5b3a14f96b 100644 (file)
@@ -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);
index 6b676935ee4fbb1edf313c422222db8e8c32d198..87224271483e6f9ed6de3b4160d5ff858c273ab1 100644 (file)
 #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
index a4375d010ee906513f3acdaed3a83f59f7a7de35..0a594fd69ff048fabd2e0854fd49d3596e28cd17 100644 (file)
@@ -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)