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:
@@ -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
|
||||||
|
@@ -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);
|
%RenameDocCtor(
|
||||||
if (acopy == NULL) {
|
ImageFromData,
|
||||||
PyErr_NoMemory();
|
"Construct an Image from a buffer of RGB bytes. Accepts either a
|
||||||
return NULL;
|
string or a buffer object holding the data and the length of the data
|
||||||
}
|
must be width*height*3.", "",
|
||||||
memcpy(acopy, alpha, width*height);
|
wxImage(int width, int height, buffer data, int DATASIZE))
|
||||||
|
{
|
||||||
|
if (DATASIZE != width*height*3) {
|
||||||
|
wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return new wxImage(width, height, dcopy, acopy, false);
|
// 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;
|
||||||
size_t len = self->GetWidth() * self->GetHeight() * 3;
|
}
|
||||||
dataPtr = (unsigned char*) malloc(len);
|
buffer copy = (buffer)malloc(DATASIZE);
|
||||||
wxPyBLOCK_THREADS( memcpy(dataPtr, PyString_AsString(data), len) );
|
if (copy == NULL) {
|
||||||
self->SetData(dataPtr);
|
wxPyBLOCK_THREADS(PyErr_NoMemory());
|
||||||
// wxImage takes ownership of dataPtr...
|
return;
|
||||||
|
}
|
||||||
|
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))
|
DocStr(SetDataBuffer,
|
||||||
goto done;
|
"Sets the internal image alpha pointer to point at a Python buffer
|
||||||
|
object. This can save a copy of the data but you must ensure that the
|
||||||
if (size != self->GetWidth() * self->GetHeight()) {
|
buffer object lives longer than the wx.Image does.", "");
|
||||||
PyErr_SetString(PyExc_TypeError, "Incorrect buffer size");
|
void SetAlphaBuffer(buffer alpha, int ALPHASIZE)
|
||||||
goto done;
|
{
|
||||||
|
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user