Use Python's buffer interface API for all image data and alpha Set/Get

methods and the ImageFromData* constructors.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@33251 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2005-04-02 03:43:52 +00:00
parent 4013de1217
commit d8194e5dd4
2 changed files with 190 additions and 104 deletions

View File

@@ -259,6 +259,20 @@ typedef unsigned long wxUIntPtr;
%enddef %enddef
#endif #endif
#ifdef _DO_FULL_DOCS
%define RenameDocCtorStr(newname, docstr, details, decl)
%feature("docstring") decl docstr details;
%rename(newname) decl;
decl
%enddef
#else
%define RenameDocCtorStr(newname, docstr, details, decl)
%feature("docstring") decl docstr;
%rename(newname) decl;
decl
%enddef
#endif
// Set the autodoc string for a constructor decl and then define the decl too. // Set the autodoc string for a constructor decl and then define the decl too.
@@ -333,6 +347,19 @@ typedef unsigned long wxUIntPtr;
decl decl
%enddef %enddef
#ifdef _DO_FULL_DOCS
%define %RenameDocCtor(newname, docstr, details, decl)
%feature("docstring") decl docstr details;
%rename(newname) decl;
decl
%enddef
#else
%define %RenameDocCtor(newname, docstr, details, decl)
%feature("docstring") decl docstr;
%rename(newname) decl;
decl
%enddef
#endif
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Forward declarations and %renames for some classes, so the autodoc strings // Forward declarations and %renames for some classes, so the autodoc strings

View File

@@ -104,6 +104,18 @@ key value from a RGB tripple.", "");
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
%{
typedef unsigned char* buffer;
%}
%typemap(in) (buffer data, int DATASIZE)
{ if (!PyArg_Parse($input, "t#", &$1, &$2)) SWIG_fail; }
%typemap(in) (buffer alpha, int ALPHASIZE)
{ if (!PyArg_Parse($input, "t#", &$1, &$2)) SWIG_fail; }
//---------------------------------------------------------------------------
class wxImage : public wxObject { class wxImage : public wxObject {
public: public:
@@ -130,55 +142,85 @@ public:
ImageFromStreamMime); ImageFromStreamMime);
%extend { %extend {
%rename(EmptyImage) wxImage(int width=0, int height=0, bool clear = true); %RenameDocCtor(
wxImage(int width=0, int height=0, bool clear = true) EmptyImage,
{ "Construct an empty image of a given size, optionally setting all
if (width > 0 && height > 0) pixels to black.", "",
return new wxImage(width, height, clear); wxImage(int width=0, int height=0, bool clear = true))
else {
return new wxImage; if (width > 0 && height > 0)
} return new wxImage(width, height, clear);
else
MustHaveApp(wxImage(const wxBitmap &bitmap)); return new wxImage;
%rename(ImageFromBitmap) wxImage(const wxBitmap &bitmap);
wxImage(const wxBitmap &bitmap)
{
return new wxImage(bitmap.ConvertToImage());
}
%rename(ImageFromData) wxImage(int width, int height, unsigned char* data);
wxImage(int width, int height, unsigned char* data)
{
// Copy the source data so the wxImage can clean it up later
unsigned char* copy = (unsigned char*)malloc(width*height*3);
if (copy == NULL) {
PyErr_NoMemory();
return NULL;
} }
memcpy(copy, data, width*height*3);
return new wxImage(width, height, copy, false);
}
%rename(ImageFromDataWithAlpha) wxImage(int width, int height, unsigned char* data, unsigned char* alpha); MustHaveApp(wxImage(const wxBitmap &bitmap));
wxImage(int width, int height, unsigned char* data, unsigned char* alpha)
{ %RenameDocCtor(
// Copy the source data so the wxImage can clean it up later ImageFromBitmap,
unsigned char* dcopy = (unsigned char*)malloc(width*height*3); "Construct an Image from a `wx.Bitmap`.", "",
if (dcopy == NULL) { wxImage(const wxBitmap &bitmap))
PyErr_NoMemory(); {
return NULL; return new wxImage(bitmap.ConvertToImage());
} }
memcpy(dcopy, data, width*height*3);
unsigned char* acopy = (unsigned char*)malloc(width*height);
if (acopy == NULL) {
PyErr_NoMemory();
return NULL;
}
memcpy(acopy, alpha, width*height);
return new wxImage(width, height, dcopy, acopy, false); %RenameDocCtor(
} ImageFromData,
"Construct an Image from a buffer of RGB bytes. Accepts either a
string or a buffer object holding the data and the length of the data
must be width*height*3.", "",
wxImage(int width, int height, buffer data, int DATASIZE))
{
if (DATASIZE != width*height*3) {
wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size.");
return NULL;
}
// Copy the source data so the wxImage can clean it up later
buffer copy = (buffer)malloc(DATASIZE);
if (copy == NULL) {
wxPyBLOCK_THREADS(PyErr_NoMemory());
return NULL;
}
memcpy(copy, data, DATASIZE);
return new wxImage(width, height, copy, false);
}
%RenameDocCtor(
ImageFromDataWithAlpha,
"Construct an Image from a buffer of RGB bytes with an Alpha channel.
Accepts either a string or a buffer object holding the data and the
length of the data must be width*height*3.", "",
wxImage(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;
}
// Copy the source data so the wxImage can clean it up later
buffer dcopy = (buffer)malloc(DATASIZE);
if (dcopy == NULL) {
wxPyBLOCK_THREADS(PyErr_NoMemory());
return NULL;
}
memcpy(dcopy, data, DATASIZE);
buffer acopy = (buffer)malloc(ALPHASIZE);
if (acopy == NULL) {
wxPyBLOCK_THREADS(PyErr_NoMemory());
return NULL;
}
memcpy(acopy, alpha, ALPHASIZE);
return new wxImage(width, height, dcopy, acopy, false);
}
} }
// TODO: wxImage( char** xpmData ); // TODO: wxImage( char** xpmData );
@@ -301,59 +343,68 @@ The method will then fill up the whole image with the colour given.", "");
//void SetData( unsigned char *data ); //void SetData( unsigned char *data );
%extend { %extend {
PyObject* GetData() { DocStr(GetData,
unsigned char* data = self->GetData(); "Returns a string containing a copy of the RGB bytes of the image.", "");
PyObject* GetData()
{
buffer data = self->GetData();
int len = self->GetWidth() * self->GetHeight() * 3; int len = self->GetWidth() * self->GetHeight() * 3;
PyObject* rv; PyObject* rv;
wxPyBLOCK_THREADS( rv = PyString_FromStringAndSize((char*)data, len)); wxPyBLOCK_THREADS( rv = PyString_FromStringAndSize((char*)data, len));
return rv; return rv;
} }
void SetData(PyObject* data) { DocStr(SetData,
unsigned char* dataPtr; "Resets the Image's RGB data from a buffer of RGB bytes. Accepts
either a string or a buffer object holding the data and the length of
if (! PyString_Check(data)) { the data must be width*height*3.", "");
wxPyBLOCK_THREADS(PyErr_SetString(PyExc_TypeError, void SetData(buffer data, int DATASIZE)
"Expected string object")); {
return /* NULL */ ; if (DATASIZE != self->GetWidth() * self->GetHeight() * 3) {
wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size.");
return;
} }
buffer copy = (buffer)malloc(DATASIZE);
size_t len = self->GetWidth() * self->GetHeight() * 3; if (copy == NULL) {
dataPtr = (unsigned char*) malloc(len); wxPyBLOCK_THREADS(PyErr_NoMemory());
wxPyBLOCK_THREADS( memcpy(dataPtr, PyString_AsString(data), len) ); return;
self->SetData(dataPtr); }
// wxImage takes ownership of dataPtr... memcpy(copy, data, DATASIZE);
self->SetData(copy, false);
// wxImage takes ownership of copy...
} }
DocStr(GetDataBuffer,
PyObject* GetDataBuffer() { "Returns a writable Python buffer object that is pointing at the RGB
unsigned char* data = self->GetData(); image data buffer inside the wx.Image.", "");
PyObject* GetDataBuffer()
{
buffer data = self->GetData();
int len = self->GetWidth() * self->GetHeight() * 3; int len = self->GetWidth() * self->GetHeight() * 3;
PyObject* rv; PyObject* rv;
wxPyBLOCK_THREADS( rv = PyBuffer_FromReadWriteMemory(data, len) ); wxPyBLOCK_THREADS( rv = PyBuffer_FromReadWriteMemory(data, len) );
return rv; return rv;
} }
void SetDataBuffer(PyObject* data) {
unsigned char* buffer;
int size;
wxPyBlock_t blocked = wxPyBeginBlockThreads(); DocStr(SetDataBuffer,
if (!PyArg_Parse(data, "t#", &buffer, &size)) "Sets the internal image data pointer to point at a Python buffer
goto done; object. This can save a copy of the data but you must ensure that the
buffer object lives longer than the wx.Image does.", "");
if (size != self->GetWidth() * self->GetHeight() * 3) { void SetDataBuffer(buffer data, int DATASIZE)
PyErr_SetString(PyExc_TypeError, "Incorrect buffer size"); {
goto done; if (DATASIZE != self->GetWidth() * self->GetHeight() * 3) {
wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size.");
return;
} }
self->SetData(buffer); self->SetData(data, true);
done:
wxPyEndBlockThreads(blocked);
} }
DocStr(GetAlphaData,
"Returns a string containing a copy of the alpha bytes of the image.", "");
PyObject* GetAlphaData() { PyObject* GetAlphaData() {
unsigned char* data = self->GetAlpha(); buffer data = self->GetAlpha();
if (! data) { if (! data) {
RETURN_NONE(); RETURN_NONE();
} else { } else {
@@ -363,45 +414,53 @@ The method will then fill up the whole image with the colour given.", "");
return rv; return rv;
} }
} }
void SetAlphaData(PyObject* data) {
unsigned char* dataPtr;
if (! PyString_Check(data)) { DocStr(SetAlphaData,
PyErr_SetString(PyExc_TypeError, "Expected string object"); "Resets the Image's alpha data from a buffer of bytes. Accepts either
return /* NULL */ ; a string or a buffer object holding the data and the length of the
data must be width*height.", "");
void SetAlphaData(buffer alpha, int ALPHASIZE)
{
if (ALPHASIZE != self->GetWidth() * self->GetHeight()) {
wxPyErr_SetString(PyExc_ValueError, "Invalid alpha buffer size.");
return;
} }
buffer acopy = (buffer)malloc(ALPHASIZE);
size_t len = self->GetWidth() * self->GetHeight(); if (acopy == NULL) {
dataPtr = (unsigned char*) malloc(len); wxPyBLOCK_THREADS(PyErr_NoMemory());
wxPyBLOCK_THREADS( memcpy(dataPtr, PyString_AsString(data), len) ); return;
self->SetAlpha(dataPtr); }
// wxImage takes ownership of dataPtr... memcpy(acopy, alpha, ALPHASIZE);
self->SetAlpha(acopy, false);
// wxImage takes ownership of acopy...
} }
PyObject* GetAlphaBuffer() { DocStr(GetDataBuffer,
unsigned char* data = self->GetAlpha(); "Returns a writable Python buffer object that is pointing at the Alpha
data buffer inside the wx.Image.", "");
PyObject* GetAlphaBuffer()
{
buffer data = self->GetAlpha();
int len = self->GetWidth() * self->GetHeight(); int len = self->GetWidth() * self->GetHeight();
PyObject* rv; PyObject* rv;
wxPyBLOCK_THREADS( rv = PyBuffer_FromReadWriteMemory(data, len) ); wxPyBLOCK_THREADS( rv = PyBuffer_FromReadWriteMemory(data, len) );
return rv; return rv;
} }
void SetAlphaBuffer(PyObject* data) {
unsigned char* buffer;
int size;
wxPyBlock_t blocked = wxPyBeginBlockThreads();
if (!PyArg_Parse(data, "t#", &buffer, &size))
goto done;
if (size != self->GetWidth() * self->GetHeight()) { DocStr(SetDataBuffer,
PyErr_SetString(PyExc_TypeError, "Incorrect buffer size"); "Sets the internal image alpha pointer to point at a Python buffer
goto done; object. This can save a copy of the data but you must ensure that the
buffer object lives longer than the wx.Image does.", "");
void SetAlphaBuffer(buffer alpha, int ALPHASIZE)
{
if (ALPHASIZE != self->GetWidth() * self->GetHeight()) {
wxPyErr_SetString(PyExc_ValueError, "Invalid alpha buffer size.");
return;
} }
self->SetAlpha(buffer); self->SetAlpha(alpha, true);
done:
wxPyEndBlockThreads(blocked);
} }
} }