]> git.saurik.com Git - wxWidgets.git/commitdiff
modifications for raw bitmap support and for using DIBs
authorVadim Zeitlin <vadim@wxwidgets.org>
Sat, 22 Mar 2003 19:02:05 +0000 (19:02 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sat, 22 Mar 2003 19:02:05 +0000 (19:02 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@19710 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/msw/bitmap.h
src/msw/bitmap.cpp

index 75b41e7521930d21d40a56840994faf4a2c3ba0e..f834ebba857097dd382b4507ea1c605fe326d9db 100644 (file)
@@ -31,6 +31,7 @@ class WXDLLEXPORT wxCursor;
 class WXDLLEXPORT wxControl;
 class WXDLLEXPORT wxImage;
 class WXDLLEXPORT wxPalette;
+class WXDLLEXPORT wxRawBitmapData;
 
 // ----------------------------------------------------------------------------
 // wxBitmap: a mono or colour bitmap
@@ -58,13 +59,24 @@ public:
     // New constructor for generalised creation from data
     wxBitmap(void *data, long type, int width, int height, int depth = 1);
 
-    // If depth is omitted, will create a bitmap compatible with the display
+    // Create a new, uninitialized bitmap of the given size and depth (if it
+    // is omitted, will create a bitmap compatible with the display)
+    //
+    // NB: this ctor will create a DIB for 24 and 32bpp bitmaps, use ctor
+    //     taking a DC argument if you want to force using DDB in this case
     wxBitmap(int width, int height, int depth = -1);
 
+    // Create a bitmap compatible with the given DC
+    wxBitmap(int width, int height, const wxDC& dc);
+
 #if wxUSE_IMAGE
-    // Convert from wxImage:
+    // Convert from wxImage
     wxBitmap(const wxImage& image, int depth = -1)
         { (void)CreateFromImage(image, depth); }
+
+    // Create a DDB compatible with the given DC from wxImage
+    wxBitmap(const wxImage& image, const wxDC& dc)
+        { (void)CreateFromImage(image, dc); }
 #endif // wxUSE_IMAGE
 
     // we must have this, otherwise icons are silently copied into bitmaps using
@@ -108,6 +120,7 @@ public:
     bool CopyFromCursor(const wxCursor& cursor);
 
     virtual bool Create(int width, int height, int depth = -1);
+    virtual bool Create(int width, int height, const wxDC& dc);
     virtual bool Create(void *data, long type, int width, int height, int depth = 1);
     virtual bool LoadFile(const wxString& name, long type = wxBITMAP_TYPE_BMP_RESOURCE);
     virtual bool SaveFile(const wxString& name, int type, const wxPalette *cmap = NULL);
@@ -115,6 +128,10 @@ public:
     wxBitmapRefData *GetBitmapData() const
         { return (wxBitmapRefData *)m_refData; }
 
+    // raw bitmap access support functions
+    bool GetRawData(wxRawBitmapData *data);
+    void UngetRawData(wxRawBitmapData *) { /* nothing to do here */ }
+
 #if wxUSE_PALETTE
     wxPalette* GetPalette() const;
     void SetPalette(const wxPalette& palette);
@@ -140,14 +157,16 @@ public:
     void SetOk(bool isOk);
 #endif // WXWIN_COMPATIBILITY_2
 
-#if wxUSE_PALETTE
 #if WXWIN_COMPATIBILITY
+#if wxUSE_PALETTE
     wxPalette *GetColourMap() const { return GetPalette(); }
     void SetColourMap(wxPalette *cmap) { SetPalette(*cmap); };
-#endif // WXWIN_COMPATIBILITY
 #endif // wxUSE_PALETTE
+#endif // WXWIN_COMPATIBILITY
+
+    // implementation only from now on
+    // -------------------------------
 
-    // Implementation
 public:
     void SetHBITMAP(WXHBITMAP bmp) { SetHandle((WXHANDLE)bmp); }
     WXHBITMAP GetHBITMAP() const { return (WXHBITMAP)GetHandle(); }
@@ -180,16 +199,19 @@ protected:
     // creates the bitmap from XPM data, supposed to be called from ctor
     bool CreateFromXpm(const char **bits);
 
+    // creates an uninitialized bitmap, called from Create()s above
+    bool DoCreate(int w, int h, int depth, WXHDC hdc);
+
 #if wxUSE_IMAGE
     // creates the bitmap from wxImage, supposed to be called from ctor
     bool CreateFromImage(const wxImage& image, int depth);
-#endif // wxUSE_IMAGE
 
-#if wxUSE_DIB_FOR_BITMAP
-    void *CreateDIB(int width, int height, int depth);
+    // creates a DDB from wxImage, supposed to be called from ctor
+    bool CreateFromImage(const wxImage& image, const wxDC& dc);
 
-    void CopyDIBLine(void* src, void* dest, int count) const;
-#endif // wxUSE_DIB_FOR_BITMAP
+    // common part of the 2 methods above (hdc may be 0)
+    bool CreateFromImage(const wxImage& image, int depth, WXHDC hdc);
+#endif // wxUSE_IMAGE
 
 private:
 #ifdef __WIN32__
index 3215a98445d78b6fa0dc892bb16f42eb63b30273..6a80f162c8746088af2942b34e00a5e9646278c0 100644 (file)
@@ -50,6 +50,8 @@
 #include "wx/image.h"
 #include "wx/xpmdecod.h"
 
+#include "wx/rawbmp.h"
+
 // missing from mingw32 header
 #ifndef CLR_INVALID
     #define CLR_INVALID ((COLORREF)-1)
@@ -122,6 +124,34 @@ IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
 // implementation
 // ============================================================================
 
+// ----------------------------------------------------------------------------
+// helper functions
+// ----------------------------------------------------------------------------
+
+// decide whether we should create a DIB or a DDB for the given parameters
+static bool wxShouldCreateDIB(int w, int h, int d, WXHDC hdc)
+{
+    // here is the logic:
+    //
+    //  (a) if hdc is specified, the caller explicitly wants DDB
+    //  (b) otherwise, create a DIB if depth >= 24 (we don't support 16bpp or
+    //      less DIBs anyhow)
+    //  (c) finally, create DIBs under Win9x even if the depth hasn't been
+    //      explicitly specified but the current display depth is 24 or more
+    //      and the image is "big", i.e. > 16Mb which is the theoretical limit
+    //      for DDBs under Win9x
+    //
+    // consequences (all of which seem to make sense):
+    //
+    //  (i)     by default, DDBs are created (depth == -1 usually)
+    //  (ii)    DIBs can be created by explicitly specifying the depth
+    //  (iii)   using a DC always forces creating a DDB
+    return !hdc &&
+            (d >= 24 ||
+                (d == -1 &&
+                    wxDIB::GetLineSize(w, wxDisplayDepth())*h > 16*1024*1024));
+}
+
 // ----------------------------------------------------------------------------
 // wxBitmapRefData
 // ----------------------------------------------------------------------------
@@ -161,7 +191,6 @@ void wxBitmapRefData::Free()
 void wxBitmap::Init()
 {
     // m_refData = NULL; done in the base class ctor
-
 }
 
 wxGDIImageRefData *wxBitmap::CreateData() const
@@ -387,26 +416,54 @@ wxBitmap::wxBitmap(const wxString& filename, wxBitmapType type)
     LoadFile(filename, (int)type);
 }
 
-bool wxBitmap::Create(int w, int h, int d)
+bool wxBitmap::Create(int width, int height, int depth)
+{
+    return DoCreate(width, height, depth, 0);
+}
+
+bool wxBitmap::Create(int width, int height, const wxDC& dc)
+{
+    wxCHECK_MSG( dc.Ok(), FALSE, _T("invalid HDC in wxBitmap::Create()") );
+
+    return DoCreate(width, height, -1, dc.GetHDC());
+}
+
+bool wxBitmap::DoCreate(int w, int h, int d, WXHDC hdc)
 {
     UnRef();
 
     m_refData = new wxBitmapRefData;
 
-#if wxUSE_DIB_FOR_BITMAP
-    if ( w && h && d >= 16 )
+    GetBitmapData()->m_width = w;
+    GetBitmapData()->m_height = h;
+
+    HBITMAP hbmp;
+
+    if ( wxShouldCreateDIB(w, h, d, hdc) )
     {
-        if ( !CreateDIB(w, h, d) )
+        if ( d == -1 )
+        {
+            // create DIBs without alpha channel by default
+            d = 24;
+        }
+
+        wxDIB dib(w, h, d);
+        if ( !dib.IsOk() )
            return FALSE;
+
+        // don't delete the DIB section in dib object dtor
+        hbmp = dib.Detach();
+
+        GetBitmapData()->m_depth = d;
+        GetBitmapData()->m_hasAlpha = d == 32; // 32bpp DIBs have alpha channel
     }
-    else
-#endif // wxUSE_DIB_FOR_BITMAP
+    else // create a DDB
     {
-        GetBitmapData()->m_width = w;
-        GetBitmapData()->m_height = h;
+        if ( d == -1 )
+            d = wxDisplayDepth();
+
         GetBitmapData()->m_depth = d;
 
-        HBITMAP hbmp;
 #ifndef __WXMICROWIN__
         if ( d > 0 )
         {
@@ -428,13 +485,13 @@ bool wxBitmap::Create(int w, int h, int d)
 
             GetBitmapData()->m_depth = wxDisplayDepth();
         }
+    }
 
-        SetHBITMAP((WXHBITMAP)hbmp);
+    SetHBITMAP((WXHBITMAP)hbmp);
 
 #if WXWIN_COMPATIBILITY_2
-        GetBitmapData()->m_ok = hbmp != 0;
+    GetBitmapData()->m_ok = hbmp != 0;
 #endif // WXWIN_COMPATIBILITY_2
-    }
 
     return Ok();
 }
@@ -449,7 +506,7 @@ bool wxBitmap::Create(int w, int h, int d)
 // make sense to use #ifdefs inside the function bodies
 #ifdef __WXMICROWIN__
 
-bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
+bool wxBitmap::CreateFromImage(const wxImage& image, int depth, const wxDC& dc)
 {
     // Set this to 1 to experiment with mask code,
     // which currently doesn't work
@@ -637,7 +694,20 @@ wxImage wxBitmap::ConvertToImage() const
 // wxImage to/from conversions
 // ----------------------------------------------------------------------------
 
-bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
+bool wxBitmap::CreateFromImage(const wxImage& image, int depth)
+{
+    return CreateFromImage(image, depth, 0);
+}
+
+bool wxBitmap::CreateFromImage(const wxImage& image, const wxDC& dc)
+{
+    wxCHECK_MSG( dc.Ok(), FALSE,
+                    _T("invalid HDC in wxBitmap::CreateFromImage()") );
+
+    return CreateFromImage(image, -1, dc.GetHDC());
+}
+
+bool wxBitmap::CreateFromImage(const wxImage& image, int depth, WXHDC hdc )
 {
     wxCHECK_MSG( image.Ok(), FALSE, wxT("invalid image") );
 
@@ -656,7 +726,6 @@ bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
     wxBitmapRefData *refData = new wxBitmapRefData;
     refData->m_width = w;
     refData->m_height = h;
-    refData->m_depth = dib.GetDepth();
     refData->m_hasAlpha = image.HasAlpha();
 
     m_refData = refData;
@@ -665,16 +734,21 @@ bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
     // next either store DIB as is or create a DDB from it
     HBITMAP hbitmap;
 
-    // TODO: if we're ready to use DIB as is, we can just do this:
-    // if ( ... )
-    //  hbitmap = dib.Detach();
-    // else
+    // are we going to use DIB?
+    if ( wxShouldCreateDIB(w, h, depth, hdc) )
+    {
+        // don't delete the DIB section in dib object dtor
+        hbitmap = dib.Detach();
+
+        refData->m_depth = dib.GetDepth();
+    }
+    else // we need to convert DIB to DDB
     {
         // create and set the device-dependent bitmap
         //
         // VZ: why don't we just use SetDIBits() instead? because of the
         //     palette or is there some other reason?
-        hbitmap = ::CreateCompatibleBitmap(ScreenHDC(), w, h);
+        hbitmap = ::CreateCompatibleBitmap(hdc ? (HDC)hdc : ScreenHDC(), w, h);
         if ( !hbitmap )
         {
             wxLogLastError(_T("CreateCompatibleBitmap()"));
@@ -745,6 +819,8 @@ bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
             ::SelectPalette(hdcMem, hOldPalette, FALSE);
         }
 #endif // wxUSE_PALETTE
+
+        refData->m_depth = depth == -1 ? wxDisplayDepth() : depth;
     }
 
     // validate this object
@@ -1119,6 +1195,46 @@ void wxBitmap::SetQuality(int WXUNUSED(quality))
 
 #endif // WXWIN_COMPATIBILITY_2_4
 
+// ----------------------------------------------------------------------------
+// raw bitmap access support
+// ----------------------------------------------------------------------------
+
+bool wxBitmap::GetRawData(wxRawBitmapData *data)
+{
+    wxCHECK_MSG( data, FALSE, _T("NULL pointer in wxBitmap::GetRawData") );
+
+    if ( !Ok() )
+    {
+        // no bitmap, no data (raw or otherwise)
+        return FALSE;
+    }
+
+    // we only support raw access to the DIBs, so check if we have one
+    DIBSECTION ds;
+    if ( !::GetObject(GetHbitmap(), sizeof(ds), &ds) )
+    {
+        return FALSE;
+    }
+
+    // ok, store the relevant info in wxRawBitmapData
+    const LONG h = ds.dsBm.bmHeight;
+
+    data->m_width = ds.dsBm.bmWidth;
+    data->m_height = h;
+    data->m_bypp = ds.dsBm.bmBitsPixel / 8;
+
+    // remember that DIBs are stored in top to bottom order!
+    const LONG bytesPerRow = ds.dsBm.bmWidthBytes;
+    data->m_stride = -bytesPerRow;
+    data->m_pixels = (unsigned char *)ds.dsBm.bmBits;
+    if ( h > 1 )
+    {
+        data->m_pixels += (h - 1)*bytesPerRow;
+    }
+
+    return TRUE;
+}
+
 // ----------------------------------------------------------------------------
 // TODO: to be replaced by something better
 // ----------------------------------------------------------------------------