From: Robin Dunn <robin@alldunn.com> Date: Tue, 22 Aug 2006 17:27:42 +0000 (+0000) Subject: Added wx.BitmapFromBuffer and wx.BitmapFromBufferRGBA factory functions. X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/238ba802f1a9f79cde6e3ebd44e5c4ab78af2055 Added wx.BitmapFromBuffer and wx.BitmapFromBufferRGBA factory functions. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@40748 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/wxPython/docs/CHANGES.txt b/wxPython/docs/CHANGES.txt index 991c9a76b8..3704a9283a 100644 --- a/wxPython/docs/CHANGES.txt +++ b/wxPython/docs/CHANGES.txt @@ -190,6 +190,11 @@ IDs. Added wx.lib.combotreebox from Frank Niessink +Added wx.ImageFromBuffer, wx.BitmapFromBuffer and +wx.BitmapFromBufferRGBA factory functions. They enable loading of am +image or bitmap directly from a Python object that implements the +buffer interface, such as strings, arrays, etc. + diff --git a/wxPython/include/wx/wxPython/wxPython_int.h b/wxPython/include/wx/wxPython/wxPython_int.h index 4ca0e75196..4af26ea1fc 100644 --- a/wxPython/include/wx/wxPython/wxPython_int.h +++ b/wxPython/include/wx/wxPython/wxPython_int.h @@ -103,7 +103,9 @@ public: #endif //--------------------------------------------------------------------------- -typedef unsigned char byte; +typedef unsigned char byte; +typedef unsigned char* buffer; + typedef wxPoint2DDouble wxPoint2D; #ifndef SWIG_TYPE_TABLE diff --git a/wxPython/src/_bitmap.i b/wxPython/src/_bitmap.i index 93fa2a2b93..8aa329e133 100644 --- a/wxPython/src/_bitmap.i +++ b/wxPython/src/_bitmap.i @@ -12,6 +12,9 @@ // Not a %module +%{ +#include <wx/rawbmp.h> +%} //--------------------------------------------------------------------------- @@ -62,6 +65,10 @@ converted to a wx.Bitmap, so any image file format supported by :todo: Find a way to do very efficient PIL Image <--> wx.Bitmap converstions. + +:see: `wx.EmptyBitmap`, `wx.BitmapFromIcon`, `wx.BitmapFromImage`, + `wx.BitmapFromXPMData`, `wx.BitmapFromBits`, `wx.BitmapFromBuffer`, + `wx.BitmapFromBufferRGBA`, `wx.Image` "); @@ -126,35 +133,36 @@ that a colour reduction may have to take place.", "", %extend { - DocStr(wxBitmap(PyObject* listOfStrings), - "Construct a Bitmap from a list of strings formatted as XPM data.", ""); - - %RenameCtor(BitmapFromXPMData, wxBitmap(PyObject* listOfStrings)) - { - char** cArray = NULL; - wxBitmap* bmp; - - cArray = ConvertListOfStrings(listOfStrings); - if (! cArray) - return NULL; - bmp = new wxBitmap(cArray); - delete [] cArray; - return bmp; - } - - DocStr(wxBitmap(PyObject* bits, int width, int height, int depth=1 ), - "Creates a bitmap from an array of bits. You should only use this + %RenameDocCtor( + BitmapFromXPMData, + "Construct a Bitmap from a list of strings formatted as XPM data.", "", + wxBitmap(PyObject* listOfStrings)) + { + char** cArray = NULL; + wxBitmap* bmp; + + cArray = ConvertListOfStrings(listOfStrings); + if (! cArray) + return NULL; + bmp = new wxBitmap(cArray); + delete [] cArray; + return bmp; + } + + + %RenameDocCtor( + BitmapFromBits, + "Creates a bitmap from an array of bits. You should only use this function for monochrome bitmaps (depth 1) in portable programs: in this case the bits parameter should contain an XBM image. For other -bit depths, the behaviour is platform dependent.", ""); - - %RenameCtor(BitmapFromBits, wxBitmap(PyObject* bits, int width, int height, int depth=1 )) - { - char* buf; - Py_ssize_t length; - PyString_AsStringAndSize(bits, &buf, &length); - return new wxBitmap(buf, width, height, depth); - } +bit depths, the behaviour is platform dependent.", "", + wxBitmap(PyObject* bits, int width, int height, int depth=1 )) + { + char* buf; + Py_ssize_t length; + PyString_AsStringAndSize(bits, &buf, &length); + return new wxBitmap(buf, width, height, depth); + } } @@ -304,6 +312,181 @@ the ``type`` parameter.", ""); }; +//--------------------------------------------------------------------------- +// Factory functions for creating wxBitmaps from Python buffer objects. They +// use the Abstract Pixel API to be able to set RGB and A bytes directly into +// the wxBitmap's pixel buffer. + +%newobject _BitmapFromBufferAlpha; +%newobject _BitmapFromBuffer; +%inline %{ + wxBitmap* _BitmapFromBufferAlpha(int width, int height, + buffer data, int DATASIZE, + buffer alpha, int ALPHASIZE) + { + if (DATASIZE != width*height*3) { + wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size."); + return NULL; + } + + if (ALPHASIZE != width*height) { + wxPyErr_SetString(PyExc_ValueError, "Invalid alpha buffer size."); + return NULL; + } + + wxBitmap* bmp = new wxBitmap(width, height, 32); + wxAlphaPixelData pixels(*bmp, wxPoint(0,0), wxSize(width,height)); + if (! pixels) { + // raise an exception... + wxPyErr_SetString(PyExc_RuntimeError, + "Failed to gain raw access to bitmap data."); + return NULL; + } + + pixels.UseAlpha(); + wxAlphaPixelData::Iterator p(pixels); + for (int y=0; y<height; y++) { + wxAlphaPixelData::Iterator rowStart = p; + for (int x=0; x<width; x++) { + p.Red() = *(data++); + p.Green() = *(data++); + p.Blue() = *(data++); + p.Alpha() = *(alpha++); + ++p; + } + p = rowStart; + p.OffsetY(pixels, 1); + } + return bmp; + } + + wxBitmap* _BitmapFromBuffer(int width, int height, buffer data, int DATASIZE) + { + if (DATASIZE != width*height*3) { + wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size."); + return NULL; + } + + wxBitmap* bmp = new wxBitmap(width, height, 24); + wxNativePixelData pixels(*bmp, wxPoint(0,0), wxSize(width,height)); + if (! pixels) { + // raise an exception... + wxPyErr_SetString(PyExc_RuntimeError, + "Failed to gain raw access to bitmap data."); + return NULL; + } + + wxNativePixelData::Iterator p(pixels); + for (int y=0; y<height; y++) { + wxNativePixelData::Iterator rowStart = p; + for (int x=0; x<width; x++) { + p.Red() = *(data++); + p.Green() = *(data++); + p.Blue() = *(data++); + ++p; + } + p = rowStart; + p.OffsetY(pixels, 1); + } + return bmp; + } +%} + + +%pythoncode { +def BitmapFromBuffer(width, height, dataBuffer, alphaBuffer=None): + """ + Creates a `wx.Bitmap` from the data in dataBuffer. The dataBuffer + parameter must be a Python object that implements the buffer interface, or + is convertable to a buffer object, such as a string, array, etc. The + dataBuffer object is expected to contain a series of RGB bytes and be + width*height*3 bytes long. A buffer object can optionally be supplied for + the image's alpha channel data, and it is expected to be width*height + bytes long. + + Unlike `wx.ImageFromBuffer` the bitmap created with this function does not + share the memory buffer with the buffer object. This is because the + native pixel buffer format varies on different platforms, and so instead + an efficient as possible copy of the data is made from the buffer objects + to the bitmap's native pixel buffer. For direct access to a bitmap's + pixel buffer see `wx.NativePixelData` and `wx.AlphaPixelData`. + + :see: `wx.Bitmap`, `wx.BitmapFromBufferRGBA`, `wx.NativePixelData`, + `wx.AlphaPixelData`, `wx.ImageFromBuffer` + """ + if not isinstance(dataBuffer, buffer): + dataBuffer = buffer(dataBuffer) + if alphaBuffer is not None and not isinstance(alphaBuffer, buffer): + alphaBuffer = buffer(alphaBuffer) + if alphaBuffer is not None: + return _gdi_._BitmapFromBufferAlpha(width, height, dataBuffer, alphaBuffer) + else: + return _gdi_._BitmapFromBuffer(width, height, dataBuffer) +} + + + +%newobject _BitmapFromBufferRGBA; +%inline %{ + wxBitmap* _BitmapFromBufferRGBA(int width, int height, buffer data, int DATASIZE) + { + if (DATASIZE != width*height*4) { + wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size."); + return NULL; + } + + wxBitmap* bmp = new wxBitmap(width, height, 32); + wxAlphaPixelData pixels(*bmp, wxPoint(0,0), wxSize(width,height)); + if (! pixels) { + // raise an exception... + wxPyErr_SetString(PyExc_RuntimeError, + "Failed to gain raw access to bitmap data."); + return NULL; + } + + pixels.UseAlpha(); + wxAlphaPixelData::Iterator p(pixels); + for (int y=0; y<height; y++) { + wxAlphaPixelData::Iterator rowStart = p; + for (int x=0; x<width; x++) { + p.Red() = *(data++); + p.Green() = *(data++); + p.Blue() = *(data++); + p.Alpha() = *(data++); + ++p; + } + p = rowStart; + p.OffsetY(pixels, 1); + } + return bmp; + } +%} + +%pythoncode { +def BitmapFromBufferRGBA(width, height, dataBuffer): + """ + Creates a `wx.Bitmap` from the data in dataBuffer. The dataBuffer + parameter must be a Python object that implements the buffer interface, or + is convertable to a buffer object, such as a string, array, etc. The + dataBuffer object is expected to contain a series of RGBA bytes (red, + gree, blue and alpha) and be width*height*4 bytes long. + + Unlike `wx.ImageFromBuffer` the bitmap created with this function does not + share the memory buffer with the buffer object. This is because the + native pixel buffer format varies on different platforms, and so instead + an efficient as possible copy of the data is made from the buffer object + to the bitmap's native pixel buffer. For direct access to a bitmap's + pixel buffer see `wx.NativePixelData` and `wx.AlphaPixelData`. + + :see: `wx.Bitmap`, `wx.BitmapFromBuffer`, `wx.NativePixelData`, + `wx.AlphaPixelData`, `wx.ImageFromBuffer` + """ + if not isinstance(dataBuffer, buffer): + dataBuffer = buffer(dataBuffer) + return _gdi_._BitmapFromBufferRGBA(width, height, dataBuffer) +} + + //--------------------------------------------------------------------------- DocStr(wxMask, diff --git a/wxPython/src/my_typemaps.i b/wxPython/src/my_typemaps.i index 08a2c9c09b..5c8474ef2b 100644 --- a/wxPython/src/my_typemaps.i +++ b/wxPython/src/my_typemaps.i @@ -315,6 +315,21 @@ MAKE_INT_ARRAY_TYPEMAPS(styles, styles_field) } +//--------------------------------------------------------------------------- +// Typemaps for loading a image or bitmap from an object that implements the +// buffer interface + + +%typemap(in) (buffer data, int DATASIZE) +{ if ($input != Py_None) { + if (!PyArg_Parse($input, "t#", &$1, &$2)) SWIG_fail; +}} + +%typemap(in) (buffer alpha, int ALPHASIZE) +{ if ($input != Py_None) { + if (!PyArg_Parse($input, "t#", &$1, &$2)) SWIG_fail; +}} + //--------------------------------------------------------------------------- // Typemaps to convert return values that are base class pointers // to the real derived type, if possible. See wxPyMake_wxObject in