mirror of
https://github.com/wxWidgets/Phoenix.git
synced 2026-01-04 19:10:09 +01:00
Add buffer related methods and helpers for wxBitmap
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxPython/Phoenix/trunk@71293 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
3
TODO.txt
3
TODO.txt
@@ -107,9 +107,6 @@ WAF Build
|
||||
other dev stuff
|
||||
---------------
|
||||
|
||||
* port all of the wx.Bitmap copy-to and copy-from buffer methods, and
|
||||
raw bitmap access routines from Classic.
|
||||
|
||||
* Come up with some way to implement the MustHaveApp check that
|
||||
Classic does. It should raise an exception when something is
|
||||
created/used that should not be done before there is an application
|
||||
|
||||
266
etg/bitmap.py
266
etg/bitmap.py
@@ -18,7 +18,13 @@ DOCSTRING = ""
|
||||
|
||||
# The classes and/or the basename of the Doxygen XML files to be processed by
|
||||
# this script.
|
||||
ITEMS = [ 'wxBitmap', 'wxBitmapHandler', 'wxMask' ]
|
||||
ITEMS = [ 'wxBitmap',
|
||||
'wxBitmapHandler',
|
||||
'wxMask' ]
|
||||
|
||||
OTHERDEPS = [ 'src/bitmap_ex.h',
|
||||
'src/bitmap_ex.cpp', ]
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
@@ -52,9 +58,36 @@ def run():
|
||||
return self->IsOk();
|
||||
""")
|
||||
|
||||
# On MSW the handler classes are different than what is documented, and
|
||||
# this causes compile errors. Nobody has needed them from Python thus far,
|
||||
# so just ignore them all for now.
|
||||
c.addCppMethod('long', 'GetHandle', '()',
|
||||
doc='MSW-only method to fetch the windows handle for the bitmap.',
|
||||
body="""\
|
||||
#ifdef __WXMSW__
|
||||
return self->GetHandle();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
""")
|
||||
|
||||
c.addCppMethod('void', 'SetHandle', '(long handle)',
|
||||
doc='MSW-only method to set the windows handle for the bitmap.',
|
||||
body="""\
|
||||
#ifdef __WXMSW__
|
||||
self->SetHandle((WXHANDLE)handle);
|
||||
#endif
|
||||
""")
|
||||
|
||||
c.addCppMethod('void', 'SetSize', '(const wxSize& size)',
|
||||
doc='Set the bitmap size (does not affect the existing bitmap data).',
|
||||
body="""\
|
||||
self->SetWidth(size->x);
|
||||
self->SetHeight(size->y);
|
||||
""")
|
||||
|
||||
|
||||
|
||||
# On MSW the bitmap handler classes are different than what is
|
||||
# documented, and this causes compile errors. Nobody has needed them from
|
||||
# Python thus far, so just ignore them all for now.
|
||||
for m in c.find('FindHandler').all():
|
||||
m.ignore()
|
||||
c.find('AddHandler').ignore()
|
||||
@@ -70,9 +103,230 @@ def run():
|
||||
module.find('wxBitmapHandler').ignore()
|
||||
#module.addItem(tools.wxListWrapperTemplate('wxList', 'wxBitmapHandler', module))
|
||||
|
||||
# TODO: The ctors and methods from Classic for converting to/from
|
||||
# buffer objects with raw bitmap access.
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Declarations, helpers and methods for converting to/from buffer objects
|
||||
# with raw bitmap access.
|
||||
|
||||
from etgtools import EnumDef, EnumValueDef
|
||||
e = EnumDef(name='wxBitmapBufferFormat')
|
||||
e.items.extend([ EnumValueDef(name='wxBitmapBufferFormat_RGB'),
|
||||
EnumValueDef(name='wxBitmapBufferFormat_RGBA'),
|
||||
EnumValueDef(name='wxBitmapBufferFormat_RGB32'),
|
||||
EnumValueDef(name='wxBitmapBufferFormat_ARGB32'),
|
||||
])
|
||||
module.insertItem(0, e)
|
||||
|
||||
c.includeCppCode('src/bitmap_ex.cpp')
|
||||
module.addHeaderCode('#include "bitmap_ex.h"')
|
||||
|
||||
|
||||
c.addCppMethod('void', 'CopyFromBuffer',
|
||||
'(wxPyBuffer* data, wxBitmapBufferFormat format=wxBitmapBufferFormat_RGB, int stride=-1)',
|
||||
doc="""\
|
||||
Copy data from a buffer object to replace the bitmap pixel data.
|
||||
Default format is plain RGB, but other formats are now supported as
|
||||
well. The following symbols are used to specify the format of the
|
||||
bytes in the buffer:
|
||||
|
||||
============================= ================================
|
||||
wx.BitmapBufferFormat_RGB A simple sequence of RGB bytes
|
||||
wx.BitmapBufferFormat_RGBA A simple sequence of RGBA bytes
|
||||
wx.BitmapBufferFormat_ARGB32 A sequence of 32-bit values in native
|
||||
endian order, with alpha in the upper
|
||||
8 bits, followed by red, green, and
|
||||
blue.
|
||||
wx.BitmapBufferFormat_RGB32 Same as above but the alpha byte
|
||||
is ignored.
|
||||
============================= ================================""",
|
||||
body="""\
|
||||
wxPyCopyBitmapFromBuffer(self, (byte*)data->m_ptr, data->m_len, format, stride);
|
||||
""")
|
||||
|
||||
|
||||
c.addCppMethod('void', 'CopyToBuffer',
|
||||
'(wxPyBuffer* data, wxBitmapBufferFormat format=wxBitmapBufferFormat_RGB, int stride=-1)',
|
||||
doc="""\
|
||||
Copy pixel data to a buffer object. See `CopyFromBuffer` for buffer
|
||||
format details.""",
|
||||
body="""\
|
||||
wxPyCopyBitmapToBuffer(self, (byte*)data->m_ptr, data->m_len, format, stride);
|
||||
""")
|
||||
|
||||
|
||||
# Some bitmap factories added as static methods
|
||||
|
||||
c.addCppMethod('wxBitmap*', 'FromBufferAndAlpha',
|
||||
'(int width, int height, wxPyBuffer* data, wxPyBuffer* alpha)',
|
||||
isStatic=True,
|
||||
factory=True,
|
||||
doc="""\
|
||||
Creates a `wx.Bitmap` from in-memory data. The data and alpha
|
||||
parameters must be a Python object that implements the buffer
|
||||
interface, such as a string, bytearray, etc. The data object
|
||||
is expected to contain a series of RGB bytes and be at least
|
||||
width*height*3 bytes long, while the alpha object is expected
|
||||
to be width*height bytes long and represents the image's alpha
|
||||
channel. On Windows and Mac the RGB values will be
|
||||
'premultiplied' by the alpha values. (The other platforms do
|
||||
the multiplication themselves.)
|
||||
|
||||
Unlike `wx.ImageFromBuffer` the bitmap created with this function
|
||||
does not share the memory block 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.
|
||||
""",
|
||||
body="""\
|
||||
if (!data->checkSize(width*height*3) || !alpha->checkSize(width*height))
|
||||
return NULL;
|
||||
|
||||
byte* ddata = (byte*)data->m_ptr;
|
||||
byte* adata = (byte*)alpha->m_ptr;
|
||||
wxBitmap* bmp = new wxBitmap(width, height, 32);
|
||||
|
||||
wxAlphaPixelData pixData(*bmp, wxPoint(0,0), wxSize(width,height));
|
||||
if (! pixData) {
|
||||
wxPyErr_SetString(PyExc_RuntimeError, "Failed to gain raw access to bitmap data.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wxAlphaPixelData::Iterator p(pixData);
|
||||
for (int y=0; y<height; y++) {
|
||||
wxAlphaPixelData::Iterator rowStart = p;
|
||||
for (int x=0; x<width; x++) {
|
||||
byte a = *(adata++);
|
||||
p.Red() = wxPy_premultiply(*(ddata++), a);
|
||||
p.Green() = wxPy_premultiply(*(ddata++), a);
|
||||
p.Blue() = wxPy_premultiply(*(ddata++), a);
|
||||
p.Alpha() = a;
|
||||
++p;
|
||||
}
|
||||
p = rowStart;
|
||||
p.OffsetY(pixData, 1);
|
||||
}
|
||||
return bmp;
|
||||
""")
|
||||
|
||||
c.addCppMethod('wxBitmap*', 'FromBuffer', '(int width, int height, wxPyBuffer* data)',
|
||||
isStatic=True,
|
||||
factory=True,
|
||||
doc="""\
|
||||
Creates a `wx.Bitmap` from in-memory data. The data parameter
|
||||
must be a Python object that implements the buffer interface, such
|
||||
as a string, bytearray, etc. The data object is expected to contain
|
||||
a series of RGB bytes and be at least width*height*3 bytes long.
|
||||
|
||||
Unlike `wx.ImageFromBuffer` the bitmap created with this function
|
||||
does not share the memory block 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.
|
||||
""",
|
||||
body="""\
|
||||
wxBitmap* bmp = new wxBitmap(width, height, 24);
|
||||
wxPyCopyBitmapFromBuffer(bmp, (byte*)data->m_ptr, data->m_len, wxBitmapBufferFormat_RGB);
|
||||
if (PyErr_Occurred()) {
|
||||
delete bmp;
|
||||
bmp = NULL;
|
||||
}
|
||||
return bmp;
|
||||
""")
|
||||
|
||||
module.addPyFunction('BitmapFromBuffer', '(width, height, dataBuffer, alphaBuffer=None)',
|
||||
deprecated=True,
|
||||
doc='A compatibility wrapper for Bitmap.FromBuffer and Bitmap.FromBufferAndAlpha',
|
||||
body="""\
|
||||
if alphaBuffer is not None:
|
||||
return Bitmap.FromBufferAndAlpha(width, height, dataBuffer, alphaBuffer)
|
||||
else:
|
||||
return Bitmap.FromBuffer(width, height, dataBuffer)
|
||||
""")
|
||||
|
||||
|
||||
|
||||
|
||||
c.addCppMethod('wxBitmap*', 'FromBufferRGBA', '(int width, int height, wxPyBuffer* data)',
|
||||
isStatic=True,
|
||||
factory=True,
|
||||
doc="""\
|
||||
Creates a `wx.Bitmap` from in-memory data. The data parameter
|
||||
must be a Python object that implements the buffer interface, such
|
||||
as a string, bytearray, etc. The data object is expected to contain
|
||||
a series of RGBA bytes and be at least width*height*4 bytes long.
|
||||
On Windows and Mac the RGB values will be 'premultiplied' by the
|
||||
alpha values. (The other platforms do the multiplication themselves.)
|
||||
|
||||
Unlike `wx.ImageFromBuffer` the bitmap created with this function
|
||||
does not share the memory block 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.
|
||||
""",
|
||||
body="""\
|
||||
wxBitmap* bmp = new wxBitmap(width, height, 32);
|
||||
wxPyCopyBitmapFromBuffer(bmp, (byte*)data->m_ptr, data->m_len, wxBitmapBufferFormat_RGBA);
|
||||
if (PyErr_Occurred()) {
|
||||
delete bmp;
|
||||
bmp = NULL;
|
||||
}
|
||||
return bmp;
|
||||
""")
|
||||
|
||||
module.addPyFunction('BitmapFromBufferRGBA', '(width, height, dataBuffer)',
|
||||
deprecated=True,
|
||||
doc='A compatibility wrapper for Bitmap.FromBufferRGBA',
|
||||
body='return Bitmap.FromBufferRGBA(width, height, dataBuffer)')
|
||||
|
||||
|
||||
|
||||
|
||||
c.addCppMethod('wxBitmap*', 'FromRGBA',
|
||||
'(int width, int height, byte red=0, byte green=0, byte blue=0, byte alpha=0)',
|
||||
isStatic=True,
|
||||
factory=True,
|
||||
doc="""\
|
||||
Creates a new empty 32-bit `wx.Bitmap` where every pixel has been
|
||||
initialized with the given RGBA values.
|
||||
""",
|
||||
body="""\
|
||||
if ( !(width > 0 && height > 0) ) {
|
||||
wxPyErr_SetString(PyExc_ValueError, "Width and height must be greater than zero");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wxBitmap* bmp = new wxBitmap(width, height, 32);
|
||||
wxAlphaPixelData pixData(*bmp, wxPoint(0,0), wxSize(width,height));
|
||||
if (! pixData) {
|
||||
wxPyErr_SetString(PyExc_RuntimeError, "Failed to gain raw access to bitmap data.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wxAlphaPixelData::Iterator p(pixData);
|
||||
for (int y=0; y<height; y++) {
|
||||
wxAlphaPixelData::Iterator rowStart = p;
|
||||
for (int x=0; x<width; x++) {
|
||||
p.Red() = wxPy_premultiply(red, alpha);
|
||||
p.Green() = wxPy_premultiply(green, alpha);
|
||||
p.Blue() = wxPy_premultiply(blue, alpha);
|
||||
p.Alpha() = alpha;
|
||||
++p;
|
||||
}
|
||||
p = rowStart;
|
||||
p.OffsetY(pixData, 1);
|
||||
}
|
||||
return bmp;
|
||||
""")
|
||||
|
||||
module.addPyFunction('EmptyBitmapRGBA', '(width, height, red=0, green=0, blue=0, alpha=0)',
|
||||
deprecated=True,
|
||||
doc='A compatibility wrapper for Bitmap.FromRGBA',
|
||||
body='return Bitmap.FromRGBA(width, height, red, green, blue, alpha)')
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# For compatibility:
|
||||
module.addPyFunction('EmptyBitmap', '(width, height, depth=BITMAP_SCREEN_DEPTH)',
|
||||
|
||||
@@ -56,6 +56,7 @@ def run():
|
||||
module.insertItemAfter(td, etgtools.TypedefDef(type='long', name='time_t'))
|
||||
module.insertItemAfter(td, etgtools.TypedefDef(type='long long', name='wxFileOffset'))
|
||||
module.insertItemAfter(td, etgtools.TypedefDef(type='SIP_SSIZE_T', name='ssize_t'))
|
||||
module.insertItemAfter(td, etgtools.TypedefDef(type='unsigned char', name='byte', pyInt=True))
|
||||
|
||||
|
||||
|
||||
|
||||
103
etg/image.py
103
etg/image.py
@@ -21,6 +21,8 @@ DOCSTRING = ""
|
||||
ITEMS = [ 'wxImage',
|
||||
'wxImageHistogram',
|
||||
'wxImageHandler',
|
||||
#'wxQuantize',
|
||||
#'wxPalette',
|
||||
]
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -58,7 +60,7 @@ def run():
|
||||
if (! copy)
|
||||
return NULL;
|
||||
sipCpp = new sipwxImage;
|
||||
sipCpp->Create(width, height, (unsigned char*)copy);
|
||||
sipCpp->Create(width, height, (byte*)copy);
|
||||
""")
|
||||
|
||||
c.addCppCtor_sip('(int width, int height, wxPyBuffer* data, wxPyBuffer* alpha)',
|
||||
@@ -70,7 +72,7 @@ def run():
|
||||
if ((dcopy = data->copy()) == NULL || (acopy = alpha->copy()) == NULL)
|
||||
return NULL;
|
||||
sipCpp = new sipwxImage;
|
||||
sipCpp->Create(width, height, (unsigned char*)dcopy, (unsigned char*)acopy, false);
|
||||
sipCpp->Create(width, height, (byte*)dcopy, (byte*)acopy, false);
|
||||
""")
|
||||
|
||||
c.addCppCtor_sip('(const wxSize& size, wxPyBuffer* data)',
|
||||
@@ -82,7 +84,7 @@ def run():
|
||||
if (! copy)
|
||||
return NULL;
|
||||
sipCpp = new sipwxImage;
|
||||
sipCpp->Create(size->x, size->y, (unsigned char*)copy, false);
|
||||
sipCpp->Create(size->x, size->y, (byte*)copy, false);
|
||||
""")
|
||||
|
||||
c.addCppCtor_sip('(const wxSize& size, wxPyBuffer* data, wxPyBuffer* alpha)',
|
||||
@@ -94,7 +96,7 @@ def run():
|
||||
if ((dcopy = data->copy()) == NULL || (acopy = alpha->copy()) == NULL)
|
||||
return NULL;
|
||||
sipCpp = new sipwxImage;
|
||||
sipCpp->Create(size->x, size->y, (unsigned char*)dcopy, (unsigned char*)acopy, false);
|
||||
sipCpp->Create(size->x, size->y, (byte*)dcopy, (byte*)acopy, false);
|
||||
""")
|
||||
|
||||
|
||||
@@ -112,7 +114,7 @@ def run():
|
||||
void* copy = data->copy();
|
||||
if (! copy)
|
||||
return false;
|
||||
return self->Create(width, height, (unsigned char*)copy);
|
||||
return self->Create(width, height, (byte*)copy);
|
||||
""")
|
||||
|
||||
c.addCppMethod('bool', 'Create', '(int width, int height, wxPyBuffer* data, wxPyBuffer* alpha)',
|
||||
@@ -123,7 +125,7 @@ def run():
|
||||
return false;
|
||||
if ((dcopy = data->copy()) == NULL || (acopy = alpha->copy()) == NULL)
|
||||
return false;
|
||||
return self->Create(width, height, (unsigned char*)dcopy, (unsigned char*)acopy);
|
||||
return self->Create(width, height, (byte*)dcopy, (byte*)acopy);
|
||||
""")
|
||||
|
||||
c.addCppMethod('bool', 'Create', '(const wxSize& size, wxPyBuffer* data)',
|
||||
@@ -134,7 +136,7 @@ def run():
|
||||
void* copy = data->copy();
|
||||
if (! copy)
|
||||
return false;
|
||||
return self->Create(size->x, size->y, (unsigned char*)copy);
|
||||
return self->Create(size->x, size->y, (byte*)copy);
|
||||
""")
|
||||
|
||||
c.addCppMethod('bool', 'Create', '(const wxSize& size, wxPyBuffer* data, wxPyBuffer* alpha)',
|
||||
@@ -145,7 +147,7 @@ def run():
|
||||
return false;
|
||||
if ((dcopy = data->copy()) == NULL || (acopy = alpha->copy()) == NULL)
|
||||
return false;
|
||||
return self->Create(size->x, size->y, (unsigned char*)dcopy, (unsigned char*)acopy);
|
||||
return self->Create(size->x, size->y, (byte*)dcopy, (byte*)acopy);
|
||||
""")
|
||||
|
||||
|
||||
@@ -160,7 +162,7 @@ def run():
|
||||
void* copy = data->copy();
|
||||
if (!copy)
|
||||
return;
|
||||
self->SetData((unsigned char*)copy, false);
|
||||
self->SetData((byte*)copy, false);
|
||||
""", briefDoc=bd, detailedDoc=dd)
|
||||
|
||||
c.find('SetData').findOverload('int new_width').ignore()
|
||||
@@ -171,7 +173,7 @@ def run():
|
||||
void* copy = data->copy();
|
||||
if (!copy)
|
||||
return;
|
||||
self->SetData((unsigned char*)copy, new_width, new_height, false);
|
||||
self->SetData((byte*)copy, new_width, new_height, false);
|
||||
""")
|
||||
|
||||
m = c.find('SetAlpha').findOverload('unsigned char *alpha')
|
||||
@@ -184,7 +186,7 @@ def run():
|
||||
void* copy = alpha->copy();
|
||||
if (!copy)
|
||||
return;
|
||||
self->SetAlpha((unsigned char*)copy, false);
|
||||
self->SetAlpha((byte*)copy, false);
|
||||
""")
|
||||
|
||||
|
||||
@@ -195,7 +197,7 @@ def run():
|
||||
c.addCppMethod('PyObject*', 'GetData', '()',
|
||||
doc="Returns a copy of the RGB bytes of the image.",
|
||||
body="""\
|
||||
unsigned char* data = self->GetData();
|
||||
byte* data = self->GetData();
|
||||
Py_ssize_t len = self->GetWidth() * self->GetHeight() * 3;
|
||||
PyObject* rv = NULL;
|
||||
wxPyBLOCK_THREADS( rv = PyByteArray_FromStringAndSize((const char*)data, len));
|
||||
@@ -206,7 +208,7 @@ def run():
|
||||
c.addCppMethod('PyObject*', 'GetAlpha', '()',
|
||||
doc="Returns a copy of the Alpha bytes of the image.",
|
||||
body="""\
|
||||
unsigned char* data = self->GetAlpha();
|
||||
byte* data = self->GetAlpha();
|
||||
Py_ssize_t len = self->GetWidth() * self->GetHeight();
|
||||
PyObject* rv = NULL;
|
||||
wxPyBLOCK_THREADS( rv = PyByteArray_FromStringAndSize((const char*)data, len));
|
||||
@@ -223,7 +225,7 @@ def run():
|
||||
image data buffer inside the wx.Image. You need to ensure that you do
|
||||
not use this buffer object after the image has been destroyed.""",
|
||||
body="""\
|
||||
unsigned char* data = self->GetData();
|
||||
byte* data = self->GetData();
|
||||
Py_ssize_t len = self->GetWidth() * self->GetHeight() * 3;
|
||||
PyObject* rv;
|
||||
Py_buffer view;
|
||||
@@ -240,7 +242,7 @@ def run():
|
||||
data buffer inside the wx.Image. You need to ensure that you do
|
||||
not use this buffer object after the image has been destroyed.""",
|
||||
body="""\
|
||||
unsigned char* data = self->GetAlpha();
|
||||
byte* data = self->GetAlpha();
|
||||
Py_ssize_t len = self->GetWidth() * self->GetHeight();
|
||||
PyObject* rv;
|
||||
Py_buffer view;
|
||||
@@ -263,7 +265,7 @@ def run():
|
||||
if (!data->checkSize(self->GetWidth() * self->GetHeight() * 3))
|
||||
return;
|
||||
// True means don't free() the pointer
|
||||
self->SetData((unsigned char*)data->m_ptr, true);
|
||||
self->SetData((byte*)data->m_ptr, true);
|
||||
""")
|
||||
c.addCppMethod('void', 'SetDataBuffer', '(wxPyBuffer* data, int new_width, int new_height)',
|
||||
doc="""\
|
||||
@@ -275,7 +277,7 @@ def run():
|
||||
if (!data->checkSize(new_width * new_height * 3))
|
||||
return;
|
||||
// True means don't free() the pointer
|
||||
self->SetData((unsigned char*)data->m_ptr, new_width, new_height, true);
|
||||
self->SetData((byte*)data->m_ptr, new_width, new_height, true);
|
||||
""")
|
||||
|
||||
|
||||
@@ -289,7 +291,7 @@ def run():
|
||||
if (!alpha->checkSize(self->GetWidth() * self->GetHeight()))
|
||||
return;
|
||||
// True means don't free() the pointer
|
||||
self->SetAlpha((unsigned char*)alpha->m_ptr, true);
|
||||
self->SetAlpha((byte*)alpha->m_ptr, true);
|
||||
""")
|
||||
|
||||
|
||||
@@ -387,10 +389,10 @@ def run():
|
||||
|
||||
unsigned rgblen = 3 * self->GetWidth() * self->GetHeight();
|
||||
unsigned alphalen = self->GetWidth() * self->GetHeight();
|
||||
unsigned char* src_data = self->GetData();
|
||||
unsigned char* src_alpha = self->GetAlpha();
|
||||
unsigned char* dst_data = dest->GetData();
|
||||
unsigned char* dst_alpha = NULL;
|
||||
byte* src_data = self->GetData();
|
||||
byte* src_alpha = self->GetAlpha();
|
||||
byte* dst_data = dest->GetData();
|
||||
byte* dst_alpha = NULL;
|
||||
|
||||
// adjust rgb
|
||||
if ( factor_red == 1.0 && factor_green == 1.0 && factor_blue == 1.0)
|
||||
@@ -403,18 +405,18 @@ def run():
|
||||
// rgb pixel for pixel
|
||||
for ( unsigned i = 0; i < rgblen; i= i + 3 )
|
||||
{
|
||||
dst_data[i] = (unsigned char) wxMin( 255, (int) (factor_red * src_data[i]) );
|
||||
dst_data[i + 1] = (unsigned char) wxMin( 255, (int) (factor_green * src_data[i + 1]) );
|
||||
dst_data[i + 2] = (unsigned char) wxMin( 255, (int) (factor_blue * src_data[i + 2]) );
|
||||
dst_data[i] = (byte) wxMin( 255, (int) (factor_red * src_data[i]) );
|
||||
dst_data[i + 1] = (byte) wxMin( 255, (int) (factor_green * src_data[i + 1]) );
|
||||
dst_data[i + 2] = (byte) wxMin( 255, (int) (factor_blue * src_data[i + 2]) );
|
||||
}
|
||||
}
|
||||
|
||||
// adjust the mask colour
|
||||
if ( self->HasMask() )
|
||||
{
|
||||
dest->SetMaskColour((unsigned char) wxMin( 255, (int) (factor_red * self->GetMaskRed() ) ),
|
||||
(unsigned char) wxMin( 255, (int) (factor_green * self->GetMaskGreen() ) ),
|
||||
(unsigned char) wxMin( 255, (int) (factor_blue * self->GetMaskBlue() ) ) );
|
||||
dest->SetMaskColour((byte) wxMin( 255, (int) (factor_red * self->GetMaskRed() ) ),
|
||||
(byte) wxMin( 255, (int) (factor_green * self->GetMaskGreen() ) ),
|
||||
(byte) wxMin( 255, (int) (factor_blue * self->GetMaskBlue() ) ) );
|
||||
}
|
||||
|
||||
// adjust the alpha channel
|
||||
@@ -436,7 +438,7 @@ def run():
|
||||
// alpha value for alpha value
|
||||
for ( unsigned i = 0; i < alphalen; ++i )
|
||||
{
|
||||
dst_alpha[i] = (unsigned char) wxMin( 255, (int) (factor_alpha * src_alpha[i]) );
|
||||
dst_alpha[i] = (byte) wxMin( 255, (int) (factor_alpha * src_alpha[i]) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -450,7 +452,7 @@ def run():
|
||||
|
||||
for ( unsigned i = 0; i < alphalen; ++i )
|
||||
{
|
||||
dst_alpha[i] = (unsigned char) wxMin( 255, (int) (factor_alpha * 255) );
|
||||
dst_alpha[i] = (byte) wxMin( 255, (int) (factor_alpha * 255) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -458,9 +460,9 @@ def run():
|
||||
if ( dst_alpha && dest->HasMask() )
|
||||
{
|
||||
// make the mask transparent honoring the alpha channel
|
||||
const unsigned char mr = dest->GetMaskRed();
|
||||
const unsigned char mg = dest->GetMaskGreen();
|
||||
const unsigned char mb = dest->GetMaskBlue();
|
||||
const byte mr = dest->GetMaskRed();
|
||||
const byte mg = dest->GetMaskGreen();
|
||||
const byte mb = dest->GetMaskBlue();
|
||||
|
||||
for ( unsigned i = 0; i < alphalen; ++i )
|
||||
{
|
||||
@@ -508,6 +510,41 @@ def run():
|
||||
|
||||
|
||||
|
||||
module.addPyFunction('ImageFromBuffer', '(width, height, dataBuffer, alphaBuffer=None)',
|
||||
doc="""\
|
||||
Creates a `wx.Image` from the data in dataBuffer. The dataBuffer
|
||||
parameter must be a Python object that implements the buffer interface,
|
||||
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.
|
||||
|
||||
The wx.Image will be created with its data and alpha pointers initialized
|
||||
to the memory address pointed to by the buffer objects, thus saving the
|
||||
time needed to copy the image data from the buffer object to the wx.Image.
|
||||
While this has advantages, it also has the shoot-yourself-in-the-foot
|
||||
risks associated with sharing a C pointer between two objects.
|
||||
|
||||
To help alleviate the risk a reference to the data and alpha buffer
|
||||
objects are kept with the wx.Image, so that they won't get deleted until
|
||||
after the wx.Image is deleted. However please be aware that it is not
|
||||
guaranteed that an object won't move its memory buffer to a new location
|
||||
when it needs to resize its contents. If that happens then the wx.Image
|
||||
will end up referring to an invalid memory location and could cause the
|
||||
application to crash. Therefore care should be taken to not manipulate
|
||||
the objects used for the data and alpha buffers in a way that would cause
|
||||
them to change size.
|
||||
""",
|
||||
body="""\
|
||||
img = Image(width, height)
|
||||
img.SetDataBuffer(dataBuffer)
|
||||
if alphaBuffer:
|
||||
img.SetAlphaBuffer(alphaBuffer)
|
||||
img._buffer = dataBuffer
|
||||
img._alpha = alphaBuffer
|
||||
return img
|
||||
""")
|
||||
|
||||
#-------------------------------------------------------
|
||||
c = module.find('wxImageHistogram')
|
||||
setParamsPyInt('MakeKey')
|
||||
|
||||
319
src/bitmap_ex.cpp
Normal file
319
src/bitmap_ex.cpp
Normal file
@@ -0,0 +1,319 @@
|
||||
//--------------------------------------------------------------------------
|
||||
// Name: src/bitmap_ex.h
|
||||
// Purpose: Helper functions and etc. for copying bitmap data to/from
|
||||
// buffer objects. This file is included in etg/bitmap.py and
|
||||
// used in the wxBitmap wrapper.
|
||||
//
|
||||
// Author: Robin Dunn
|
||||
//
|
||||
// Created: 27-Apr-2012
|
||||
// Copyright: (c) 2012 by Total Control Software
|
||||
// Licence: wxWindows license
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include <wx/rawbmp.h>
|
||||
|
||||
// TODO: Switch these APIs to use the new wxPyBuffer class
|
||||
|
||||
void wxPyCopyBitmapFromBuffer(wxBitmap* bmp,
|
||||
buffer data, Py_ssize_t DATASIZE,
|
||||
wxBitmapBufferFormat format, int stride)
|
||||
{
|
||||
int height = bmp->GetHeight();
|
||||
int width = bmp->GetWidth();
|
||||
|
||||
switch (format) {
|
||||
// A simple sequence of RGB bytes
|
||||
case wxBitmapBufferFormat_RGB:
|
||||
{
|
||||
if (DATASIZE < width * height * 3) {
|
||||
wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size.");
|
||||
return;
|
||||
}
|
||||
wxNativePixelData pixData(*bmp, wxPoint(0,0), wxSize(width, height));
|
||||
if (! pixData) {
|
||||
wxPyErr_SetString(PyExc_RuntimeError,
|
||||
"Failed to gain raw access to bitmap data.");
|
||||
return;
|
||||
}
|
||||
|
||||
wxNativePixelData::Iterator p(pixData);
|
||||
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(pixData, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// A simple sequence of RGBA bytes
|
||||
case wxBitmapBufferFormat_RGBA:
|
||||
{
|
||||
if (DATASIZE < width * height * 4) {
|
||||
wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size.");
|
||||
return;
|
||||
}
|
||||
wxAlphaPixelData pixData(*bmp, wxPoint(0,0), wxSize(width, height));
|
||||
if (! pixData) {
|
||||
wxPyErr_SetString(PyExc_RuntimeError,
|
||||
"Failed to gain raw access to bitmap data.");
|
||||
return;
|
||||
}
|
||||
wxAlphaPixelData::Iterator p(pixData);
|
||||
for (int y=0; y<height; y++) {
|
||||
wxAlphaPixelData::Iterator rowStart = p;
|
||||
for (int x=0; x<width; x++) {
|
||||
byte a = data[3];
|
||||
p.Red() = wxPy_premultiply(*(data++), a);
|
||||
p.Green() = wxPy_premultiply(*(data++), a);
|
||||
p.Blue() = wxPy_premultiply(*(data++), a);
|
||||
p.Alpha() = a; data++;
|
||||
++p;
|
||||
}
|
||||
p = rowStart;
|
||||
p.OffsetY(pixData, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// A sequence of 32-bit values in native endian order,
|
||||
// where the alpha is in the upper 8 bits, then red, then
|
||||
// green, then blue. The stride is the distance in bytes
|
||||
// from the beginning of one row of the image data to the
|
||||
// beginning of the next row. This may not be the same as
|
||||
// width*4 if alignment or platform specific optimizations
|
||||
// have been utilized.
|
||||
|
||||
// NOTE: This is normally used with Cairo, which seems to
|
||||
// already have the values premultiplied. Should we have
|
||||
// a way to optionally do it anyway?
|
||||
|
||||
case wxBitmapBufferFormat_RGB32:
|
||||
case wxBitmapBufferFormat_ARGB32:
|
||||
{
|
||||
bool useAlpha = (format == wxBitmapBufferFormat_ARGB32);
|
||||
byte* rowStart = data;
|
||||
wxUint32* bufptr;
|
||||
wxUint32 value;
|
||||
|
||||
if (stride == -1)
|
||||
stride = width * 4;
|
||||
|
||||
if (DATASIZE < stride * height) {
|
||||
wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size.");
|
||||
return;
|
||||
}
|
||||
|
||||
wxAlphaPixelData pixData(*bmp, wxPoint(0,0), wxSize(width,height));
|
||||
if (! pixData) {
|
||||
wxPyErr_SetString(PyExc_RuntimeError,
|
||||
"Failed to gain raw access to bitmap data.");
|
||||
return;
|
||||
}
|
||||
|
||||
wxAlphaPixelData::Iterator pix(pixData);
|
||||
for (int y=0; y<height; y++) {
|
||||
pix.MoveTo(pixData, 0, y);
|
||||
bufptr = (wxUint32*)rowStart;
|
||||
for (int x=0; x<width; x++) {
|
||||
value = *bufptr;
|
||||
pix.Alpha() = useAlpha ? (value >> 24) & 0xFF : 255;
|
||||
pix.Red() = (value >> 16) & 0xFF;
|
||||
pix.Green() = (value >> 8) & 0xFF;
|
||||
pix.Blue() = (value >> 0) & 0xFF;
|
||||
++pix;
|
||||
++bufptr;
|
||||
}
|
||||
rowStart += stride;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Some helper macros used below to help declutter the code
|
||||
#define MAKE_PIXDATA(type) \
|
||||
type pixData(*bmp, wxPoint(0,0), wxSize(width, height)); \
|
||||
if (! pixData) { \
|
||||
wxPyErr_SetString(PyExc_RuntimeError, "Failed to gain raw access to bitmap data."); \
|
||||
return; \
|
||||
} \
|
||||
type::Iterator p(pixData); \
|
||||
type::Iterator rowStart
|
||||
|
||||
#define CHECK_BUFFERSIZE(size_needed) \
|
||||
if (DATASIZE < size_needed) { \
|
||||
wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size."); \
|
||||
return; \
|
||||
}
|
||||
|
||||
|
||||
void wxPyCopyBitmapToBuffer(wxBitmap* bmp,
|
||||
buffer data, Py_ssize_t DATASIZE,
|
||||
wxBitmapBufferFormat format, int stride)
|
||||
{
|
||||
int height = bmp->GetHeight();
|
||||
int width = bmp->GetWidth();
|
||||
int depth = bmp->GetDepth();
|
||||
|
||||
// images loaded from a file may not have set the depth, at least on Mac...
|
||||
if (depth == -1) {
|
||||
if (bmp->HasAlpha())
|
||||
depth = 32;
|
||||
else
|
||||
depth = 24;
|
||||
}
|
||||
|
||||
switch (format) {
|
||||
// A simple sequence of RGB bytes
|
||||
case wxBitmapBufferFormat_RGB:
|
||||
{
|
||||
CHECK_BUFFERSIZE(width * height * 3);
|
||||
if (depth == 24) {
|
||||
MAKE_PIXDATA(wxNativePixelData);
|
||||
|
||||
for (int y=0; y<height; y++) {
|
||||
rowStart = p;
|
||||
for (int x=0; x<width; x++) {
|
||||
*(data++) = p.Red();
|
||||
*(data++) = p.Green();
|
||||
*(data++) = p.Blue();
|
||||
++p;
|
||||
}
|
||||
p = rowStart;
|
||||
p.OffsetY(pixData, 1);
|
||||
}
|
||||
}
|
||||
if (depth == 32) {
|
||||
// Source has alpha, but we won't be using it because the
|
||||
// destination buffer doesn't
|
||||
MAKE_PIXDATA(wxAlphaPixelData);
|
||||
|
||||
for (int y=0; y<height; y++) {
|
||||
rowStart = p;
|
||||
for (int x=0; x<width; x++) {
|
||||
*(data++) = p.Red();
|
||||
*(data++) = p.Green();
|
||||
*(data++) = p.Blue();
|
||||
++p;
|
||||
}
|
||||
p = rowStart;
|
||||
p.OffsetY(pixData, 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// A simple sequence of RGBA bytes
|
||||
case wxBitmapBufferFormat_RGBA:
|
||||
{
|
||||
CHECK_BUFFERSIZE(width * height * 4);
|
||||
if (depth == 24) {
|
||||
MAKE_PIXDATA(wxNativePixelData);
|
||||
for (int y=0; y<height; y++) {
|
||||
rowStart = p;
|
||||
for (int x=0; x<width; x++) {
|
||||
byte a = wxALPHA_OPAQUE;
|
||||
*(data++) = wxPy_unpremultiply(p.Red(), a);
|
||||
*(data++) = wxPy_unpremultiply(p.Green(), a);
|
||||
*(data++) = wxPy_unpremultiply(p.Blue(), a);
|
||||
*(data++) = a;
|
||||
}
|
||||
p = rowStart;
|
||||
p.OffsetY(pixData, 1);
|
||||
}
|
||||
}
|
||||
if (depth == 32) {
|
||||
MAKE_PIXDATA(wxAlphaPixelData);
|
||||
for (int y=0; y<height; y++) {
|
||||
rowStart = p;
|
||||
for (int x=0; x<width; x++) {
|
||||
byte a = p.Alpha();
|
||||
*(data++) = wxPy_unpremultiply(p.Red(), a);
|
||||
*(data++) = wxPy_unpremultiply(p.Green(), a);
|
||||
*(data++) = wxPy_unpremultiply(p.Blue(), a);
|
||||
*(data++) = a;
|
||||
}
|
||||
p = rowStart;
|
||||
p.OffsetY(pixData, 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// A sequence of 32-bit values in native endian order,
|
||||
// where the alpha is in the upper 8 bits, then red, then
|
||||
// green, then blue. The stride is the distance in bytes
|
||||
// from the beginning of one row of the image data to the
|
||||
// beginning of the next row. This may not be the same as
|
||||
// width*4 if alignment or platform specific optimizations
|
||||
// have been utilized.
|
||||
|
||||
// NOTE: This is normally used with Cairo, which seems to
|
||||
// already have the values premultiplied. Should we have
|
||||
// a way to optionally do it anyway?
|
||||
|
||||
case wxBitmapBufferFormat_RGB32:
|
||||
case wxBitmapBufferFormat_ARGB32:
|
||||
{
|
||||
bool useAlpha = (format == wxBitmapBufferFormat_ARGB32);
|
||||
byte* dataRow = data;
|
||||
wxUint32* bufptr;
|
||||
wxUint32 value;
|
||||
|
||||
if (stride == -1)
|
||||
stride = width * 4;
|
||||
|
||||
CHECK_BUFFERSIZE(stride * height);
|
||||
|
||||
if (useAlpha && depth == 32) {
|
||||
MAKE_PIXDATA(wxAlphaPixelData);
|
||||
for (int y=0; y<height; y++) {
|
||||
p.MoveTo(pixData, 0, y);
|
||||
bufptr = (wxUint32*)dataRow;
|
||||
for (int x=0; x<width; x++) {
|
||||
value =
|
||||
(p.Alpha() << 24) |
|
||||
(p.Red() << 16) |
|
||||
(p.Green() << 8) |
|
||||
(p.Blue());
|
||||
*bufptr = value;
|
||||
++p;
|
||||
++bufptr;
|
||||
}
|
||||
dataRow += stride;
|
||||
}
|
||||
}
|
||||
else // if (!useAlpha /*depth == 24*/)
|
||||
{
|
||||
MAKE_PIXDATA(wxNativePixelData);
|
||||
for (int y=0; y<height; y++) {
|
||||
p.MoveTo(pixData, 0, y);
|
||||
bufptr = (wxUint32*)dataRow;
|
||||
for (int x=0; x<width; x++) {
|
||||
value =
|
||||
(wxALPHA_OPAQUE << 24) |
|
||||
(p.Red() << 16) |
|
||||
(p.Green() << 8) |
|
||||
(p.Blue());
|
||||
*bufptr = value;
|
||||
++p;
|
||||
++bufptr;
|
||||
}
|
||||
dataRow += stride;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
46
src/bitmap_ex.h
Normal file
46
src/bitmap_ex.h
Normal file
@@ -0,0 +1,46 @@
|
||||
//--------------------------------------------------------------------------
|
||||
// Name: src/bitmap_ex.h
|
||||
// Purpose: Helper functions and etc. for copying bitmap data to/from
|
||||
// buffer objects.
|
||||
//
|
||||
// Author: Robin Dunn
|
||||
//
|
||||
// Created: 27-Apr-2012
|
||||
// Copyright: (c) 2012 by Total Control Software
|
||||
// Licence: wxWindows license
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef BITMAP_EX_H
|
||||
#define BITMAP_EX_H
|
||||
|
||||
|
||||
enum wxBitmapBufferFormat {
|
||||
wxBitmapBufferFormat_RGB,
|
||||
wxBitmapBufferFormat_RGBA,
|
||||
wxBitmapBufferFormat_RGB32,
|
||||
wxBitmapBufferFormat_ARGB32,
|
||||
};
|
||||
|
||||
|
||||
// See http://tinyurl.com/e5adr for what premultiplying alpha means. wxMSW and
|
||||
// wxMac want to have the values premultiplied by the alpha value, but the
|
||||
// other platforms don't. These macros help keep the code clean.
|
||||
#if defined(__WXMSW__) || defined(__WXMAC__)
|
||||
#define wxPy_premultiply(p, a) ((p) * (a) / 0xff)
|
||||
#define wxPy_unpremultiply(p, a) ((a) ? ((p) * 0xff / (a)) : (p))
|
||||
#else
|
||||
#define wxPy_premultiply(p, a) (p)
|
||||
#define wxPy_unpremultiply(p, a) (p)
|
||||
#endif
|
||||
|
||||
|
||||
void wxPyCopyBitmapFromBuffer(wxBitmap* bmp,
|
||||
buffer data, Py_ssize_t DATASIZE,
|
||||
wxBitmapBufferFormat format, int stride=-1);
|
||||
|
||||
void wxPyCopyBitmapToBuffer(wxBitmap* bmp,
|
||||
buffer data, Py_ssize_t DATASIZE,
|
||||
wxBitmapBufferFormat format, int stride=-1);
|
||||
|
||||
#endif
|
||||
@@ -46,6 +46,8 @@
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
typedef PyGILState_STATE wxPyBlock_t;
|
||||
typedef unsigned char byte;
|
||||
typedef unsigned char* buffer;
|
||||
|
||||
|
||||
// Convert a wxString to a Python string (actually a PyUnicode object).
|
||||
|
||||
@@ -7,19 +7,35 @@ pngFile = os.path.join(os.path.dirname(__file__), 'toucan.png')
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
def makeBuf(w, h, bpp=1, init=0):
|
||||
"Make a simple buffer for testing with"
|
||||
buf = bytearray([init] * (w*h*bpp))
|
||||
return buf
|
||||
|
||||
|
||||
class BitmapTests(wtc.WidgetTestCase):
|
||||
|
||||
def test_BitmapCtors(self):
|
||||
def test_BitmapCtor1(self):
|
||||
b1 = wx.Bitmap()
|
||||
self.assertTrue( not b1.IsOk() )
|
||||
|
||||
def test_BitmapCtor2(self):
|
||||
b2 = wx.Bitmap(5, 10, 32)
|
||||
self.assertTrue( b2.IsOk() )
|
||||
|
||||
def test_BitmapCtor3(self):
|
||||
b3 = wx.Bitmap(wx.Size(5,10), 32)
|
||||
self.assertTrue( b3.IsOk() )
|
||||
|
||||
def test_BitmapCtor4(self):
|
||||
b4 = wx.Bitmap((5,10), 32)
|
||||
self.assertTrue( b4.IsOk() )
|
||||
|
||||
def test_BitmapCtor5(self):
|
||||
b5 = wx.Bitmap(pngFile)
|
||||
self.assertTrue( b5.IsOk() )
|
||||
|
||||
def test_BitmapCtor6(self):
|
||||
img = wx.Image(pngFile)
|
||||
b6 = wx.Bitmap(img)
|
||||
self.assertTrue( b6.IsOk() )
|
||||
@@ -76,6 +92,96 @@ class BitmapTests(wtc.WidgetTestCase):
|
||||
m = wx.Mask(bmp, wx.Colour(1,2,3))
|
||||
|
||||
|
||||
def test_bitmapFormatConstants(self):
|
||||
wx.BitmapBufferFormat_RGB
|
||||
wx.BitmapBufferFormat_RGBA
|
||||
wx.BitmapBufferFormat_RGB32
|
||||
wx.BitmapBufferFormat_ARGB32
|
||||
|
||||
def test_bitmapSetSize(self):
|
||||
b1 = wx.Bitmap(1,1)
|
||||
b1.SetSize((20,30))
|
||||
self.assertTrue(b1.GetSize() == (20,30))
|
||||
self.assertTrue(b1.Size == (20,30))
|
||||
b1.Size = (25,35)
|
||||
self.assertTrue(b1.GetSize() == (25,35))
|
||||
|
||||
def test_bitmapHandle(self):
|
||||
b1 = wx.Bitmap(1,1)
|
||||
b1.Handle
|
||||
b1.GetHandle()
|
||||
|
||||
|
||||
def test_bitmapCopyFromBuffer1(self):
|
||||
w = h = 10
|
||||
buf = makeBuf(w,h,3)
|
||||
bmp = wx.Bitmap(w,h,24)
|
||||
bmp.CopyFromBuffer(buf, wx.BitmapBufferFormat_RGB)
|
||||
|
||||
def test_bitmapCopyFromBuffer2(self):
|
||||
w = h = 10
|
||||
buf = makeBuf(w,h,4)
|
||||
bmp = wx.Bitmap(w,h,32)
|
||||
bmp.CopyFromBuffer(buf, wx.BitmapBufferFormat_RGBA)
|
||||
|
||||
def test_bitmapCopyFromBuffer3(self):
|
||||
w = h = 10
|
||||
buf = makeBuf(w,h,4)
|
||||
bmp = wx.Bitmap(w,h,32)
|
||||
bmp.CopyFromBuffer(buf, wx.BitmapBufferFormat_ARGB32)
|
||||
|
||||
|
||||
def test_bitmapCopyToBuffer1(self):
|
||||
w = h = 10
|
||||
buf = makeBuf(w,h,3)
|
||||
bmp = wx.Bitmap(w,h,24)
|
||||
bmp.CopyToBuffer(buf, wx.BitmapBufferFormat_RGB)
|
||||
|
||||
def test_bitmapCopyToBuffer2(self):
|
||||
w = h = 10
|
||||
buf = makeBuf(w,h,4)
|
||||
bmp = wx.Bitmap(w,h,32)
|
||||
bmp.CopyToBuffer(buf, wx.BitmapBufferFormat_RGBA)
|
||||
|
||||
def test_bitmapCopyToBuffer3(self):
|
||||
w = h = 10
|
||||
buf = makeBuf(w,h,4)
|
||||
bmp = wx.Bitmap(w,h,32)
|
||||
bmp.CopyToBuffer(buf, wx.BitmapBufferFormat_ARGB32)
|
||||
|
||||
|
||||
def test_bitmapBufferFactory1(self):
|
||||
w = h = 10
|
||||
buf = makeBuf(w,h,3, 111)
|
||||
bmp = wx.Bitmap.FromBuffer(w, h, buf)
|
||||
self.assertTrue(bmp.IsOk())
|
||||
|
||||
def test_bitmapBufferFactory2(self):
|
||||
w = h = 10
|
||||
buf = makeBuf(w,h,3, 111)
|
||||
alpha = makeBuf(w,h,1)
|
||||
bmp = wx.Bitmap.FromBufferAndAlpha(w, h, buf, alpha)
|
||||
self.assertTrue(bmp.IsOk())
|
||||
|
||||
def test_bitmapBufferFactory3(self):
|
||||
w = h = 10
|
||||
buf = makeBuf(w,h,4, 111)
|
||||
bmp = wx.Bitmap.FromBufferRGBA(w, h, buf)
|
||||
self.assertTrue(bmp.IsOk())
|
||||
|
||||
|
||||
def test_bitmapEmptyFactory1(self):
|
||||
w = h = 10
|
||||
bmp = wx.Bitmap.FromRGBA(w, h)
|
||||
self.assertTrue(bmp.IsOk())
|
||||
|
||||
def test_bitmapEmptyFactory2(self):
|
||||
w = h = 10
|
||||
bmp = wx.Bitmap.FromRGBA(w, h, 1, 2, 3, 4)
|
||||
self.assertTrue(bmp.IsOk())
|
||||
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
@@ -9,11 +9,6 @@ pngFile = os.path.join(os.path.dirname(__file__), 'toucan.png')
|
||||
|
||||
def makeBuf(w, h, bpp=1, init=0):
|
||||
"Make a simple buffer for testing with"
|
||||
|
||||
# Apparently array objects do not implement the new buffer protocol...
|
||||
#import array
|
||||
#buf = array.array('B', [init] * (w*h*bpp))
|
||||
|
||||
buf = bytearray([init] * (w*h*bpp))
|
||||
return buf
|
||||
|
||||
|
||||
Reference in New Issue
Block a user