%}
-// Turn off the aquisition of the Global Interpreter Lock for this file
+// Turn off the aquisition of the Global Interpreter Lock for the classes and
+// functions in this file
%threadWrapperOff
//---------------------------------------------------------------------------
+%{
+// See http://tinyurl.com/e5adr for what premultiplying alpha means. It
+// appears to me that the other platforms are already doing it, so I'll just
+// automatically do it for wxMSW here.
+#ifdef __WXMSW__
+#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
+%}
+
+//---------------------------------------------------------------------------
+
+
%{
#include <wx/image.h>
* wx.BITMAP_TYPE_IFF
:see: Alternate constructors `wx.EmptyBitmap`, `wx.BitmapFromIcon`,
- `wx.BitmapFromImage`, `wx.BitmapFromXPMData`,
- `wx.BitmapFromBits`
+ `wx.BitmapFromImage`, `wx.BitmapFromXPMData`, `wx.BitmapFromBits`,
+ `wx.BitmapFromBuffer`, `wx.BitmapFromBufferRGBA`,
");
~wxBitmap();
}
#endif
- bool Ok();
-
+ bool IsOk();
+ %pythoncode { Ok = IsOk }
+
DocDeclStr(
int , GetWidth(),
"Gets the width of the bitmap in pixels.", "");
be converted back and forth without loss in that respect.", "");
-
DocDeclStr(
virtual wxMask* , GetMask() const,
"Gets the associated mask (if any) which may have been loaded from a
#ifdef __WXMSW__
bool CopyFromCursor(const wxCursor& cursor);
-
-// WXWIN_COMPATIBILITY_2_4
- #if 0
- int GetQuality();
- void SetQuality(int q);
- %pythoncode { GetQuality = wx._deprecated(GetQuality) }
- %pythoncode { SetQuality = wx._deprecated(SetQuality) }
- #endif
#endif
- %pythoncode { def __nonzero__(self): return self.Ok() }
+ %extend {
+ DocStr(CopyFromBuffer,
+ "Copy data from a RGB buffer object to replace the bitmap pixel data.
+See `wx.BitmapFromBuffer` for more details.", "");
+ void CopyFromBuffer(buffer data, int DATASIZE)
+ {
+ int height=self->GetHeight();
+ int width=self->GetWidth();
+
+ if (DATASIZE != width * height * 3) {
+ wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size.");
+ }
+ wxNativePixelData pixData(*self, wxPoint(0,0), wxSize(width, height));
+ if (! pixData) {
+ // raise an exception...
+ 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);
+ }
+ }
+ DocStr(CopyFromBufferRGBA,
+ "Copy data from a RGBA buffer object to replace the bitmap pixel data.
+See `wx.BitmapFromBufferRGBA` for more details.", "");
+ void CopyFromBufferRGBA(buffer data, int DATASIZE)
+ {
+ int height=self->GetHeight();
+ int width=self->GetWidth();
+
+ if (DATASIZE != width * height * 4) {
+ wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size.");
+ }
+ wxAlphaPixelData pixData(*self, wxPoint(0,0), wxSize(width, height));
+ if (! pixData) {
+ // raise an exception...
+ wxPyErr_SetString(PyExc_RuntimeError,
+ "Failed to gain raw access to bitmap data.");
+ return;
+ }
+
+ pixData.UseAlpha();
+ 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);
+ }
+ }
+ }
+
+
+ %pythoncode { def __nonzero__(self): return self.IsOk() }
+
+ // TODO: Should these just be removed since the C++ operators are
+ // gone? Or is using IsSameAs for wxPython ok?
%extend {
- bool __eq__(const wxBitmap* other) { return other ? (*self == *other) : false; }
- bool __ne__(const wxBitmap* other) { return other ? (*self != *other) : true; }
+ bool __eq__(const wxBitmap* other) { return other ? self->IsSameAs(*other) : false; }
+ bool __ne__(const wxBitmap* other) { return other ? !self->IsSameAs(*other) : true; }
}
+
+ %property(Depth, GetDepth, SetDepth, doc="See `GetDepth` and `SetDepth`");
+ %property(Height, GetHeight, SetHeight, doc="See `GetHeight` and `SetHeight`");
+ %property(Mask, GetMask, SetMask, doc="See `GetMask` and `SetMask`");
+ %property(Palette, GetPalette, doc="See `GetPalette`");
+ %property(Size, GetSize, SetSize, doc="See `GetSize` and `SetSize`");
+ %property(SubBitmap, GetSubBitmap, doc="See `GetSubBitmap`");
+ %property(Width, GetWidth, SetWidth, doc="See `GetWidth` and `SetWidth`");
+
};
// use the Abstract Pixel API to be able to set RGB and A bytes directly into
// the wxBitmap's pixel buffer.
-%{
-// See http://tinyurl.com/e5adr for what premultiplying alpha means. It
-// appears to me that the other platforms are already doing it, so I'll just
-// automatically do it for wxMSW here.
-#ifdef __WXMSW__
-#define wxPy_premultiply(p, a) ((p) * (a) / 256)
-#else
-#define wxPy_premultiply(p, a) (p)
-#endif
-%}
-
%newobject _BitmapFromBufferAlpha;
%newobject _BitmapFromBuffer;
}
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++) {
++p;
}
p = rowStart;
- p.OffsetY(pixels, 1);
+ p.OffsetY(pixData, 1);
}
return bmp;
}
}
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++) {
++p;
}
p = rowStart;
- p.OffsetY(pixels, 1);
+ p.OffsetY(pixData, 1);
}
return bmp;
}
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. On Windows the RGB values are 'premultiplied' by the alpha
- values. (The other platforms appear to already be premultiplying the
- alpha.)
-
- 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`.
+ 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. On Windows the RGB values are '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 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:
}
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++) {
++p;
}
p = rowStart;
- p.OffsetY(pixels, 1);
+ p.OffsetY(pixData, 1);
}
return bmp;
}
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,
- green, blue and alpha) and be width*height*4 bytes long. On Windows the
- RGB values are 'premultiplied' by the alpha values. (The other platforms
- appear to already be premultiplying the alpha.)
-
- 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`.
+ 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 RGBA bytes (red, green, blue and
+ alpha) and be width*height*4 bytes long. On Windows the RGB
+ values are '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 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)
}
// the distance between two rows
int GetRowStride() const { return m_stride; }
+ %property(Height, GetHeight, doc="See `GetHeight`");
+ %property(Origin, GetOrigin, doc="See `GetOrigin`");
+ %property(RowStride, GetRowStride, doc="See `GetRowStride`");
+ %property(Size, GetSize, doc="See `GetSize`");
+ %property(Width, GetWidth, doc="See `GetWidth`");
};
+// Both wxNativePixelData and wxAlphaPixelData have the same interface, so
+// make a macro to declare them both.
%define PIXELDATA(PixelData)
%{
- typedef PixelData##::Iterator PixelData##_Iterator;
+ typedef PixelData##::Iterator PixelData##_Accessor;
%}
-class PixelData##_Iterator;
+class PixelData##_Accessor;
class PixelData : public wxPixelDataBase
{
public:
~PixelData();
+ PixelData##_Accessor GetPixels() const;
+ void UseAlpha();
+
%extend {
bool __nonzero__() { return self->operator bool(); }
}
- PixelData##_Iterator GetPixels() const;
- void UseAlpha();
+ %pythoncode {
+ def __iter__(self):
+ """
+ Create and return an iterator object for this pixel data
+ object. (It's really a generator but I won't tell if you
+ don't tell.)
+ """
+ width = self.GetWidth()
+ height = self.GetHeight()
+ pixels = self.GetPixels()
+
+ # This class is a facade over the pixels object (using the one
+ # in the enclosing scope) that only allows Get() and Set() to
+ # be called.
+ class PixelFacade(object):
+ def Get(self):
+ return pixels.Get()
+ def Set(self, *args, **kw):
+ return pixels.Set(*args, **kw)
+ def __str__(self):
+ return str(self.Get())
+ def __repr__(self):
+ return 'pixel(%d,%d): %s' % (x,y,self.Get())
+ X = property(lambda self: x)
+ Y = property(lambda self: y)
+
+ pf = PixelFacade()
+ for y in xrange(height):
+ for x in xrange(width):
+ # We always generate the same pf instance, but it
+ # accesses the pixels object which we use to iterate
+ # over the pixel buffer.
+ yield pf
+ pixels.nextPixel()
+ pixels.MoveTo(self, 0, y)
+ }
+
+ %property(Pixels, GetPixels, doc="See `GetPixels`");
};
-class PixelData##_Iterator
+
+class PixelData##_Accessor
{
public:
- %nokwargs PixelData##_Iterator;
+ %nokwargs PixelData##_Accessor;
- PixelData##_Iterator(PixelData& data);
- PixelData##_Iterator(wxBitmap& bmp, PixelData& data);
- PixelData##_Iterator();
+ PixelData##_Accessor(PixelData& data);
+ PixelData##_Accessor(wxBitmap& bmp, PixelData& data);
+ PixelData##_Accessor();
- ~PixelData##_Iterator();
+ ~PixelData##_Accessor();
void Reset(const PixelData& data);
bool IsOk() const;
%extend {
- // PixelData##_Iterator& nextPixel() { return ++(*self); }
+ // PixelData##_Accessor& nextPixel() { return ++(*self); }
void nextPixel() { ++(*self); }
}
void OffsetY(const PixelData& data, int y);
void MoveTo(const PixelData& data, int x, int y);
- %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)
- }
-
+// 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, plus it would mean 3
+// or 4 trips per pixel from Python to C++ instead of just one.
+// Instead I've added the Set and Get functions and put the
+// premultiplying 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 iterators and so are not included in our macro...
+// wxAlphaPixelData and the iterator classes and so are not included in our
+// macro...
-%extend wxNativePixelData_Iterator {
+%extend wxNativePixelData_Accessor {
void Set(byte red, byte green, byte blue) {
self->Red() = red;
self->Green() = green;
}
}
-%extend wxAlphaPixelData_Iterator {
- byte _get_Alpha() { return self->Alpha(); }
- void _set_Alpha(byte val) { self->Alpha() = val; }
+%extend wxAlphaPixelData_Accessor {
+// byte _get_Alpha() { return self->Alpha(); }
+// void _set_Alpha(byte val) { self->Alpha() = val; }
- %pythoncode {
- Alpha = property(_get_Alpha, _set_Alpha)
- }
+// %pythoncode {
+// Alpha = property(_get_Alpha, _set_Alpha)
+// }
void Set(byte red, byte green, byte blue, byte alpha) {
- self->Red() = red;
- self->Green() = green;
- self->Blue() = blue;
+ 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);
- PyTuple_SetItem(rv, 0, PyInt_FromLong(self->Red()));
- PyTuple_SetItem(rv, 1, PyInt_FromLong(self->Green()));
- PyTuple_SetItem(rv, 2, PyInt_FromLong(self->Blue()));
- PyTuple_SetItem(rv, 3, PyInt_FromLong(self->Alpha()));
+ 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,
%extend {
wxMask(const wxBitmap& bitmap, const wxColour& colour = wxNullColour) {
- if ( !colour.Ok() )
+ if ( !colour.IsOk() )
return new wxMask(bitmap, *wxBLACK);
else
return new wxMask(bitmap, colour);
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
+
+// Turn GIL acquisition back on.
%threadWrapperOn