]> git.saurik.com Git - wxWidgets.git/blobdiff - wxPython/src/_bitmap.i
Use PyObject_AsReadBuffer in the typemap for getting buffer or buffer
[wxWidgets.git] / wxPython / src / _bitmap.i
index fcb37d0a417a6c1e7362599b1eb3067462a184d0..f6ee5a0c8d8623016940e2e3eac5f88284a814a6 100644 (file)
 #include <wx/rawbmp.h>
 %}
 
+
+// Turn off the aquisition of the Global Interpreter Lock for this file
+%threadWrapperOff
+
 //---------------------------------------------------------------------------
 
 %{
@@ -323,8 +327,10 @@ the ``type`` parameter.", "");
 // automatically do it for wxMSW here.
 #ifdef __WXMSW__
 #define wxPy_premultiply(p, a)   ((p) * (a) / 256)
+#define wxPy_unpremultiply(p, a) ((a) ? ((p) * 256 / (a)) : (p))    
 #else
 #define wxPy_premultiply(p, a)   (p)
+#define wxPy_unpremultiply(p, a) (p)    
 #endif
 %}
 
@@ -347,16 +353,16 @@ the ``type`` parameter.", "");
         }
 
         wxBitmap* bmp = new wxBitmap(width, height, 32);
-        wxAlphaPixelData pixels(*bmp, wxPoint(0,0), wxSize(width,height));
-        if (! pixels) {
+        wxAlphaPixelData pixData(*bmp, wxPoint(0,0), wxSize(width,height));
+        if (! pixData) {
             // raise an exception...
             wxPyErr_SetString(PyExc_RuntimeError,
                               "Failed to gain raw access to bitmap data.");
             return NULL;
         }
                 
-        pixels.UseAlpha();
-        wxAlphaPixelData::Iterator p(pixels);
+        pixData.UseAlpha();
+        wxAlphaPixelData::Iterator p(pixData);
         for (int y=0; y<height; y++) {
             wxAlphaPixelData::Iterator rowStart = p;
             for (int x=0; x<width; x++) {
@@ -368,7 +374,7 @@ the ``type`` parameter.", "");
                 ++p; 
             }
             p = rowStart;
-            p.OffsetY(pixels, 1);
+            p.OffsetY(pixData, 1);
         }
         return bmp;
     }        
@@ -381,15 +387,15 @@ the ``type`` parameter.", "");
         }
 
         wxBitmap* bmp = new wxBitmap(width, height, 24);
-        wxNativePixelData pixels(*bmp, wxPoint(0,0), wxSize(width,height));
-        if (! pixels) {
+        wxNativePixelData pixData(*bmp, wxPoint(0,0), wxSize(width,height));
+        if (! pixData) {
             // raise an exception...
             wxPyErr_SetString(PyExc_RuntimeError,
                               "Failed to gain raw access to bitmap data.");
             return NULL;
         }
                 
-        wxNativePixelData::Iterator p(pixels);
+        wxNativePixelData::Iterator p(pixData);
         for (int y=0; y<height; y++) {
             wxNativePixelData::Iterator rowStart = p;
             for (int x=0; x<width; x++) {
@@ -399,7 +405,7 @@ the ``type`` parameter.", "");
                 ++p; 
             }
             p = rowStart;
-            p.OffsetY(pixels, 1);
+            p.OffsetY(pixData, 1);
         }
         return bmp;
     }
@@ -443,7 +449,7 @@ def BitmapFromBuffer(width, height, dataBuffer, alphaBuffer=None):
 
 %newobject _BitmapFromBufferRGBA;
 %inline %{
-    wxBitmap* _BitmapFromBufferRGBA(int width, int height, buffer data, int DATASIZE)                                   
+    wxBitmap* _BitmapFromBufferRGBA(int width, int height, buffer data, int DATASIZE)
     {
         if (DATASIZE != width*height*4) {
             wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size.");
@@ -451,16 +457,16 @@ def BitmapFromBuffer(width, height, dataBuffer, alphaBuffer=None):
         }
 
         wxBitmap* bmp = new wxBitmap(width, height, 32);
-        wxAlphaPixelData pixels(*bmp, wxPoint(0,0), wxSize(width,height));
-        if (! pixels) {
+        wxAlphaPixelData pixData(*bmp, wxPoint(0,0), wxSize(width,height));
+        if (! pixData) {
             // raise an exception...
             wxPyErr_SetString(PyExc_RuntimeError,
                               "Failed to gain raw access to bitmap data.");
             return NULL;
         }
-                
-        pixels.UseAlpha();
-        wxAlphaPixelData::Iterator p(pixels);
+               
+        pixData.UseAlpha();
+        wxAlphaPixelData::Iterator p(pixData);
         for (int y=0; y<height; y++) {
             wxAlphaPixelData::Iterator rowStart = p;
             for (int x=0; x<width; x++) {
@@ -472,7 +478,7 @@ def BitmapFromBuffer(width, height, dataBuffer, alphaBuffer=None):
                 ++p; 
             }
             p = rowStart;
-            p.OffsetY(pixels, 1);
+            p.OffsetY(pixData, 1);
         }
         return bmp;
     }        
@@ -505,6 +511,211 @@ def BitmapFromBufferRGBA(width, height, dataBuffer):
 }
 
 
+//---------------------------------------------------------------------------
+
+class wxPixelDataBase
+{
+public:
+    // origin of the rectangular region we represent
+    wxPoint GetOrigin() const { return m_ptOrigin; }
+
+    // width and height of the region we represent
+    int GetWidth() const { return m_width; }
+    int GetHeight() const { return m_height; }
+
+    wxSize GetSize() const { return wxSize(m_width, m_height); }
+
+    // the distance between two rows
+    int GetRowStride() const { return m_stride; }
+
+};
+
+
+// Both wxNativePixelData and wxAlphaPixelData have the same interface, so
+// make a macro to declare them both.
+
+%define PIXELDATA(PixelData)
+%{
+    typedef PixelData##::Iterator PixelData##_Accessor;
+%}
+class PixelData##_Accessor;
+class PixelData : public wxPixelDataBase
+{
+public:
+    %nokwargs PixelData;
+    
+    PixelData(wxBitmap& bmp);
+    PixelData(wxBitmap& bmp, const wxRect& rect);
+    PixelData(wxBitmap& bmp, const wxPoint& pt, const wxSize& sz);
+
+    ~PixelData();
+
+    PixelData##_Accessor GetPixels() const;
+    void UseAlpha();
+
+    %extend {
+        bool __nonzero__() { return self->operator bool(); }
+    }
+
+    %pythoncode {
+    def __iter__(self):
+        """Create and return an iterator object for this pixel data object."""
+        return self.PixelIterator(self)
+
+    class PixelIterator(object):
+        """
+        Sequential iterator which returns pixel accessor objects starting at the
+        the top-left corner, and going row-by-row until the bottom-right
+        corner is reached.
+        """
+
+        class PixelAccessor(object):
+            """
+            This class is what is returned by the iterator and allows the pixel
+            to be Get or Set.
+            """
+            def __init__(self, data, pixels, x, y):
+                self.data = data
+                self.pixels = pixels
+                self.x = x
+                self.y = y
+            def Set(self, *args, **kw):
+                self.pixels.MoveTo(self.data, self.x, self.y)
+                return self.pixels.Set(*args, **kw)
+            def Get(self):
+                self.pixels.MoveTo(self.data, self.x, self.y)
+                return self.pixels.Get()
+
+        def __init__(self, pixelData):
+            self.x = self.y = 0
+            self.w = pixelData.GetWidth()
+            self.h = pixelData.GetHeight()
+            self.data = pixelData
+            self.pixels = pixelData.GetPixels()
+
+        def __iter__(self):
+            return self
+
+        def next(self):
+            if self.y >= self.h:
+                raise StopIteration
+            p = self.PixelAccessor(self.data, self.pixels, self.x, self.y)
+            self.x += 1
+            if self.x >= self.w:
+                self.x = 0
+                self.y += 1
+            return p
+    }
+};
+
+
+
+class PixelData##_Accessor
+{
+public:
+    %nokwargs PixelData##_Accessor;
+    
+    PixelData##_Accessor(PixelData& data);
+    PixelData##_Accessor(wxBitmap& bmp, PixelData& data);
+    PixelData##_Accessor();
+
+    ~PixelData##_Accessor();
+
+    void Reset(const PixelData& data);
+    bool IsOk() const;
+
+    %extend {
+        // PixelData##_Accessor& nextPixel() { return ++(*self); }
+        void nextPixel() { ++(*self); }
+    }
+
+    void Offset(const PixelData& data, int x, int y);
+    void OffsetX(const PixelData& data, int x);
+    void OffsetY(const PixelData& data, int y);
+    void MoveTo(const PixelData& data, int x, int y);
+
+// NOTE: For now I'm not wrapping the Red, Green, Blue and Alpha functions
+// because I can't hide the premultiplying needed on wxMSW if only the
+// individual components are wrapped.  Instead I've added the Set and Get
+// functions and put the puemultiplying in there.
+    
+//     %extend {
+//         byte _get_Red()   { return self->Red(); }
+//         byte _get_Green() { return self->Green(); }
+//         byte _get_Blue()  { return self->Blue(); }
+
+//         void _set_Red(byte val)   { self->Red() = val; }
+//         void _set_Green(byte val) { self->Green() = val; }
+//         void _set_Blue(byte val)  { self->Blue() = val; }
+//     }
+
+//     %pythoncode {
+//         Red   = property(_get_Red,   _set_Red)
+//         Green = property(_get_Green, _set_Green)
+//         Blue  = property(_get_Blue,  _set_Blue)
+//     }
+};
+%enddef
+
+
+%pythonAppend wxAlphaPixelData::wxAlphaPixelData "self.UseAlpha()"
+
+// Make the classes
+PIXELDATA(wxNativePixelData)
+PIXELDATA(wxAlphaPixelData)    
+
+
+// Add in a few things that are different between the wxNativePixelData and
+// wxAlphaPixelData and the iterator classes and so are not included in our
+// macro...
+
+%extend wxNativePixelData_Accessor {
+    void Set(byte red, byte green, byte blue) {
+        self->Red()   = red;
+        self->Green() = green;
+        self->Blue()  = blue;
+    }
+    
+    PyObject* Get() {
+        PyObject* rv = PyTuple_New(3);
+        PyTuple_SetItem(rv, 0, PyInt_FromLong(self->Red()));
+        PyTuple_SetItem(rv, 1, PyInt_FromLong(self->Green()));
+        PyTuple_SetItem(rv, 2, PyInt_FromLong(self->Blue()));
+        return rv;            
+    }    
+}
+
+%extend wxAlphaPixelData_Accessor {
+//     byte _get_Alpha()         { return self->Alpha(); }
+//     void _set_Alpha(byte val) { self->Alpha() = val; }
+    
+//     %pythoncode {
+//         Alpha = property(_get_Alpha, _set_Alpha)
+//     }
+
+    void Set(byte red, byte green, byte blue, byte alpha) {
+        self->Red()   = wxPy_premultiply(red,   alpha);
+        self->Green() = wxPy_premultiply(green, alpha);
+        self->Blue()  = wxPy_premultiply(blue,  alpha);
+        self->Alpha() = alpha;
+    }
+    
+    PyObject* Get() {
+        PyObject* rv = PyTuple_New(4);
+        int red   = self->Red();
+        int green = self->Green();
+        int blue  = self->Blue();
+        int alpha = self->Alpha();
+            
+        PyTuple_SetItem(rv, 0, PyInt_FromLong( wxPy_unpremultiply(red,   alpha) ));
+        PyTuple_SetItem(rv, 1, PyInt_FromLong( wxPy_unpremultiply(green, alpha) ));
+        PyTuple_SetItem(rv, 2, PyInt_FromLong( wxPy_unpremultiply(blue,  alpha) ));
+        PyTuple_SetItem(rv, 3, PyInt_FromLong( alpha ));
+        return rv;            
+    }
+}
+
+
 //---------------------------------------------------------------------------
 
 DocStr(wxMask,
@@ -548,3 +759,4 @@ passed then BLACK is used.
 
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
+%threadWrapperOn