1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: SWIG interface for wxBitmap and wxMask
7 // Created: 7-July-1997
9 // Copyright: (c) 2003 by Total Control Software
10 // Licence: wxWindows license
11 /////////////////////////////////////////////////////////////////////////////
16 #include <wx/rawbmp.h>
20 // Turn off the aquisition of the Global Interpreter Lock for the classes and
21 // functions in this file
24 //---------------------------------------------------------------------------
29 static char** ConvertListOfStrings(PyObject* listOfStrings) {
33 if (!PyList_Check(listOfStrings)) {
34 PyErr_SetString(PyExc_TypeError, "Expected a list of strings.");
37 count = PyList_Size(listOfStrings);
38 cArray = new char*[count];
40 for(int x=0; x<count; x++) {
41 // TODO: Need some validation and error checking here
42 cArray[x] = PyString_AsString(PyList_GET_ITEM(listOfStrings, x));
49 //---------------------------------------------------------------------------
51 // TODO: When the API stabalizes and is available on other platforms, add
52 // wrappers for the new wxBitmap, wxRawBitmap, wxDIB stuff...
55 "The wx.Bitmap class encapsulates the concept of a platform-dependent
56 bitmap. It can be either monochrome or colour, and either loaded from
57 a file or created dynamically. A bitmap can be selected into a memory
58 device context (instance of `wx.MemoryDC`). This enables the bitmap to
59 be copied to a window or memory device context using `wx.DC.Blit`, or
60 to be used as a drawing surface.", "
62 The BMP and XMP image file formats are supported on all platforms by
63 wx.Bitmap. Other formats are automatically loaded by `wx.Image` and
64 converted to a wx.Bitmap, so any image file format supported by
65 `wx.Image` can be used.
67 :todo: Add wrappers and support for raw bitmap data access. Can this
68 be be put into Python without losing the speed benefits of the
69 teplates and iterators in rawbmp.h?
71 :todo: Find a way to do very efficient PIL Image <--> wx.Bitmap
74 :see: `wx.EmptyBitmap`, `wx.BitmapFromIcon`, `wx.BitmapFromImage`,
75 `wx.BitmapFromXPMData`, `wx.BitmapFromBits`, `wx.BitmapFromBuffer`,
76 `wx.BitmapFromBufferRGBA`, `wx.Image`
80 MustHaveApp(wxBitmap);
82 class wxBitmap : public wxGDIObject
86 wxBitmap(const wxString& name, wxBitmapType type=wxBITMAP_TYPE_ANY),
87 "Loads a bitmap from a file.",
89 :param name: Name of the file to load the bitmap from.
90 :param type: The type of image to expect. Can be one of the following
91 constants (assuming that the neccessary `wx.Image` handlers are
103 * wx.BITMAP_TYPE_JPEG
106 * wx.BITMAP_TYPE_PICT
107 * wx.BITMAP_TYPE_ICON
111 :see: Alternate constructors `wx.EmptyBitmap`, `wx.BitmapFromIcon`,
112 `wx.BitmapFromImage`, `wx.BitmapFromXPMData`, `wx.BitmapFromBits`,
113 `wx.BitmapFromBuffer`, `wx.BitmapFromBufferRGBA`,
119 wxBitmap(int width, int height, int depth=-1),
120 "Creates a new bitmap of the given size. A depth of -1 indicates the
121 depth of the current screen or visual. Some platforms only support 1
122 for monochrome and -1 for the current display depth.", "",
126 wxBitmap(const wxIcon& icon),
127 "Create a new bitmap from a `wx.Icon` object.", "",
131 wxBitmap(const wxImage& image, int depth=-1),
132 "Creates bitmap object from a `wx.Image`. This has to be done to
133 actually display a `wx.Image` as you cannot draw an image directly on
134 a window. The resulting bitmap will use the provided colour depth (or
135 that of the current screen colour depth if depth is -1) which entails
136 that a colour reduction may have to take place.", "",
143 "Construct a Bitmap from a list of strings formatted as XPM data.", "",
144 wxBitmap(PyObject* listOfStrings))
146 char** cArray = NULL;
149 cArray = ConvertListOfStrings(listOfStrings);
152 bmp = new wxBitmap(cArray);
160 "Creates a bitmap from an array of bits. You should only use this
161 function for monochrome bitmaps (depth 1) in portable programs: in
162 this case the bits parameter should contain an XBM image. For other
163 bit depths, the behaviour is platform dependent.", "",
164 wxBitmap(PyObject* bits, int width, int height, int depth=1 ))
168 PyString_AsStringAndSize(bits, &buf, &length);
169 return new wxBitmap(buf, width, height, depth);
174 // wxGDIImage methods
178 void SetHandle(long handle) { self->SetHandle((WXHANDLE)handle); }
183 %pythoncode { Ok = IsOk }
187 "Gets the width of the bitmap in pixels.", "");
192 "Gets the height of the bitmap in pixels.", "");
197 "Gets the colour depth of the bitmap. A value of 1 indicates a
198 monochrome bitmap.", "");
203 DocStr(GetSize, "Get the size of the bitmap.", "");
205 wxSize size(self->GetWidth(), self->GetHeight());
212 virtual wxImage , ConvertToImage() const,
213 "Creates a platform-independent image from a platform-dependent
214 bitmap. This preserves mask information so that bitmaps and images can
215 be converted back and forth without loss in that respect.", "");
219 virtual wxMask* , GetMask() const,
220 "Gets the associated mask (if any) which may have been loaded from a
221 file or explpicitly set for the bitmap.
223 :see: `SetMask`, `wx.Mask`
226 // MSW only? wxBitmap GetMaskBitmap() const;
230 virtual void , SetMask(wxMask* mask),
231 "Sets the mask for this bitmap.
233 :see: `GetMask`, `wx.Mask`
235 %cleardisown(wxMask*);
238 DocStr(SetMaskColour,
239 "Create a Mask based on a specified colour in the Bitmap.", "");
240 void SetMaskColour(const wxColour& colour) {
241 wxMask *mask = new wxMask(*self, colour);
248 virtual wxBitmap , GetSubBitmap(const wxRect& rect) const,
249 "Returns a sub-bitmap of the current one as long as the rect belongs
250 entirely to the bitmap. This function preserves bit depth and mask
255 virtual bool , SaveFile(const wxString &name, wxBitmapType type,
256 wxPalette *palette = NULL),
257 "Saves a bitmap in the named file. See `__init__` for a description of
258 the ``type`` parameter.", "");
262 virtual bool , LoadFile(const wxString &name, wxBitmapType type),
263 "Loads a bitmap from a file. See `__init__` for a description of the
264 ``type`` parameter.", "");
268 virtual wxPalette *GetPalette() const;
270 virtual void SetPalette(const wxPalette& palette);
274 virtual bool CopyFromIcon(const wxIcon& icon);
277 virtual void , SetHeight(int height),
278 "Set the height property (does not affect the existing bitmap data).", "");
282 virtual void , SetWidth(int width),
283 "Set the width property (does not affect the existing bitmap data).", "");
287 virtual void , SetDepth(int depth),
288 "Set the depth property (does not affect the existing bitmap data).", "");
292 DocStr(SetSize, "Set the bitmap size (does not affect the existing bitmap data).", "");
293 void SetSize(const wxSize& size) {
294 self->SetWidth(size.x);
295 self->SetHeight(size.y);
300 bool CopyFromCursor(const wxCursor& cursor);
302 // WXWIN_COMPATIBILITY_2_4
305 void SetQuality(int q);
306 %pythoncode { GetQuality = wx._deprecated(GetQuality) }
307 %pythoncode { SetQuality = wx._deprecated(SetQuality) }
311 %pythoncode { def __nonzero__(self): return self.IsOk() }
314 bool __eq__(const wxBitmap* other) { return other ? (*self == *other) : false; }
315 bool __ne__(const wxBitmap* other) { return other ? (*self != *other) : true; }
318 %property(Depth, GetDepth, SetDepth, doc="See `GetDepth` and `SetDepth`");
319 %property(Height, GetHeight, SetHeight, doc="See `GetHeight` and `SetHeight`");
320 %property(Mask, GetMask, SetMask, doc="See `GetMask` and `SetMask`");
321 %property(Palette, GetPalette, doc="See `GetPalette`");
322 %property(Size, GetSize, SetSize, doc="See `GetSize` and `SetSize`");
323 %property(SubBitmap, GetSubBitmap, doc="See `GetSubBitmap`");
324 %property(Width, GetWidth, SetWidth, doc="See `GetWidth` and `SetWidth`");
329 //---------------------------------------------------------------------------
330 // Factory functions for creating wxBitmaps from Python buffer objects. They
331 // use the Abstract Pixel API to be able to set RGB and A bytes directly into
332 // the wxBitmap's pixel buffer.
335 // See http://tinyurl.com/e5adr for what premultiplying alpha means. It
336 // appears to me that the other platforms are already doing it, so I'll just
337 // automatically do it for wxMSW here.
339 #define wxPy_premultiply(p, a) ((p) * (a) / 0xff)
340 #define wxPy_unpremultiply(p, a) ((a) ? ((p) * 0xff / (a)) : (p))
342 #define wxPy_premultiply(p, a) (p)
343 #define wxPy_unpremultiply(p, a) (p)
348 %newobject _BitmapFromBufferAlpha;
349 %newobject _BitmapFromBuffer;
351 wxBitmap* _BitmapFromBufferAlpha(int width, int height,
352 buffer data, int DATASIZE,
353 buffer alpha, int ALPHASIZE)
355 if (DATASIZE != width*height*3) {
356 wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size.");
360 if (ALPHASIZE != width*height) {
361 wxPyErr_SetString(PyExc_ValueError, "Invalid alpha buffer size.");
365 wxBitmap* bmp = new wxBitmap(width, height, 32);
366 wxAlphaPixelData pixData(*bmp, wxPoint(0,0), wxSize(width,height));
368 // raise an exception...
369 wxPyErr_SetString(PyExc_RuntimeError,
370 "Failed to gain raw access to bitmap data.");
375 wxAlphaPixelData::Iterator p(pixData);
376 for (int y=0; y<height; y++) {
377 wxAlphaPixelData::Iterator rowStart = p;
378 for (int x=0; x<width; x++) {
380 p.Red() = wxPy_premultiply(*(data++), a);
381 p.Green() = wxPy_premultiply(*(data++), a);
382 p.Blue() = wxPy_premultiply(*(data++), a);
387 p.OffsetY(pixData, 1);
392 wxBitmap* _BitmapFromBuffer(int width, int height, buffer data, int DATASIZE)
394 if (DATASIZE != width*height*3) {
395 wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size.");
399 wxBitmap* bmp = new wxBitmap(width, height, 24);
400 wxNativePixelData pixData(*bmp, wxPoint(0,0), wxSize(width,height));
402 // raise an exception...
403 wxPyErr_SetString(PyExc_RuntimeError,
404 "Failed to gain raw access to bitmap data.");
408 wxNativePixelData::Iterator p(pixData);
409 for (int y=0; y<height; y++) {
410 wxNativePixelData::Iterator rowStart = p;
411 for (int x=0; x<width; x++) {
413 p.Green() = *(data++);
414 p.Blue() = *(data++);
418 p.OffsetY(pixData, 1);
426 def BitmapFromBuffer(width, height, dataBuffer, alphaBuffer=None):
428 Creates a `wx.Bitmap` from the data in dataBuffer. The dataBuffer
429 parameter must be a Python object that implements the buffer
430 interface, such as a string, array, etc. The dataBuffer object is
431 expected to contain a series of RGB bytes and be width*height*3
432 bytes long. A buffer object can optionally be supplied for the
433 image's alpha channel data, and it is expected to be width*height
434 bytes long. On Windows the RGB values are 'premultiplied' by the
435 alpha values. (The other platforms do the multiplication
438 Unlike `wx.ImageFromBuffer` the bitmap created with this function
439 does not share the memory buffer with the buffer object. This is
440 because the native pixel buffer format varies on different
441 platforms, and so instead an efficient as possible copy of the
442 data is made from the buffer objects to the bitmap's native pixel
443 buffer. For direct access to a bitmap's pixel buffer see
444 `wx.NativePixelData` and `wx.AlphaPixelData`.
446 :see: `wx.Bitmap`, `wx.BitmapFromBufferRGBA`, `wx.NativePixelData`,
447 `wx.AlphaPixelData`, `wx.ImageFromBuffer`
449 if alphaBuffer is not None:
450 return _gdi_._BitmapFromBufferAlpha(width, height, dataBuffer, alphaBuffer)
452 return _gdi_._BitmapFromBuffer(width, height, dataBuffer)
457 %newobject _BitmapFromBufferRGBA;
459 wxBitmap* _BitmapFromBufferRGBA(int width, int height, buffer data, int DATASIZE)
461 if (DATASIZE != width*height*4) {
462 wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size.");
466 wxBitmap* bmp = new wxBitmap(width, height, 32);
467 wxAlphaPixelData pixData(*bmp, wxPoint(0,0), wxSize(width,height));
469 // raise an exception...
470 wxPyErr_SetString(PyExc_RuntimeError,
471 "Failed to gain raw access to bitmap data.");
476 wxAlphaPixelData::Iterator p(pixData);
477 for (int y=0; y<height; y++) {
478 wxAlphaPixelData::Iterator rowStart = p;
479 for (int x=0; x<width; x++) {
481 p.Red() = wxPy_premultiply(*(data++), a);
482 p.Green() = wxPy_premultiply(*(data++), a);
483 p.Blue() = wxPy_premultiply(*(data++), a);
484 p.Alpha() = a; data++;
488 p.OffsetY(pixData, 1);
495 def BitmapFromBufferRGBA(width, height, dataBuffer):
497 Creates a `wx.Bitmap` from the data in dataBuffer. The dataBuffer
498 parameter must be a Python object that implements the buffer
499 interface, such as a string, array, etc. The dataBuffer object is
500 expected to contain a series of RGBA bytes (red, green, blue and
501 alpha) and be width*height*4 bytes long. On Windows the RGB
502 values are 'premultiplied' by the alpha values. (The other
503 platforms do the multiplication themselves.)
505 Unlike `wx.ImageFromBuffer` the bitmap created with this function
506 does not share the memory buffer with the buffer object. This is
507 because the native pixel buffer format varies on different
508 platforms, and so instead an efficient as possible copy of the
509 data is made from the buffer object to the bitmap's native pixel
510 buffer. For direct access to a bitmap's pixel buffer see
511 `wx.NativePixelData` and `wx.AlphaPixelData`.
513 :see: `wx.Bitmap`, `wx.BitmapFromBuffer`, `wx.NativePixelData`,
514 `wx.AlphaPixelData`, `wx.ImageFromBuffer`
516 return _gdi_._BitmapFromBufferRGBA(width, height, dataBuffer)
520 //---------------------------------------------------------------------------
522 class wxPixelDataBase
525 // origin of the rectangular region we represent
526 wxPoint GetOrigin() const { return m_ptOrigin; }
528 // width and height of the region we represent
529 int GetWidth() const { return m_width; }
530 int GetHeight() const { return m_height; }
532 wxSize GetSize() const { return wxSize(m_width, m_height); }
534 // the distance between two rows
535 int GetRowStride() const { return m_stride; }
537 %property(Height, GetHeight, doc="See `GetHeight`");
538 %property(Origin, GetOrigin, doc="See `GetOrigin`");
539 %property(RowStride, GetRowStride, doc="See `GetRowStride`");
540 %property(Size, GetSize, doc="See `GetSize`");
541 %property(Width, GetWidth, doc="See `GetWidth`");
545 // Both wxNativePixelData and wxAlphaPixelData have the same interface, so
546 // make a macro to declare them both.
548 %define PIXELDATA(PixelData)
550 typedef PixelData##::Iterator PixelData##_Accessor;
552 class PixelData##_Accessor;
553 class PixelData : public wxPixelDataBase
558 PixelData(wxBitmap& bmp);
559 PixelData(wxBitmap& bmp, const wxRect& rect);
560 PixelData(wxBitmap& bmp, const wxPoint& pt, const wxSize& sz);
564 PixelData##_Accessor GetPixels() const;
568 bool __nonzero__() { return self->operator bool(); }
574 Create and return an iterator object for this pixel data
575 object. (It's really a generator but I won't tell if you
578 width = self.GetWidth()
579 height = self.GetHeight()
580 pixels = self.GetPixels()
582 # This class is a facade over the pixels object (using the one
583 # in the enclosing scope) that only allows Get() and Set() to
585 class PixelFacade(object):
588 def Set(self, *args, **kw):
589 return pixels.Set(*args, **kw)
591 return str(self.Get())
593 return 'pixel(%d,%d): %s' % (x,y,self.Get())
594 X = property(lambda self: x)
595 Y = property(lambda self: y)
598 for y in xrange(height):
599 for x in xrange(width):
600 # We always generate the same pf instance, but it
601 # accesses the pixels object which we use to iterate
602 # over the pixel buffer.
605 pixels.MoveTo(self, 0, y)
608 %property(Pixels, GetPixels, doc="See `GetPixels`");
613 class PixelData##_Accessor
616 %nokwargs PixelData##_Accessor;
618 PixelData##_Accessor(PixelData& data);
619 PixelData##_Accessor(wxBitmap& bmp, PixelData& data);
620 PixelData##_Accessor();
622 ~PixelData##_Accessor();
624 void Reset(const PixelData& data);
628 // PixelData##_Accessor& nextPixel() { return ++(*self); }
629 void nextPixel() { ++(*self); }
632 void Offset(const PixelData& data, int x, int y);
633 void OffsetX(const PixelData& data, int x);
634 void OffsetY(const PixelData& data, int y);
635 void MoveTo(const PixelData& data, int x, int y);
637 // NOTE: For now I'm not wrapping the Red, Green, Blue and Alpha
638 // functions because I can't hide the premultiplying needed on wxMSW
639 // if only the individual components are wrapped, plus it would mean 3
640 // or 4 trips per pixel from Python to C++ instead of just one.
641 // Instead I've added the Set and Get functions and put the
642 // premultiplying in there.
645 // byte _get_Red() { return self->Red(); }
646 // byte _get_Green() { return self->Green(); }
647 // byte _get_Blue() { return self->Blue(); }
649 // void _set_Red(byte val) { self->Red() = val; }
650 // void _set_Green(byte val) { self->Green() = val; }
651 // void _set_Blue(byte val) { self->Blue() = val; }
655 // Red = property(_get_Red, _set_Red)
656 // Green = property(_get_Green, _set_Green)
657 // Blue = property(_get_Blue, _set_Blue)
663 %pythonAppend wxAlphaPixelData::wxAlphaPixelData "self.UseAlpha()"
666 PIXELDATA(wxNativePixelData)
667 PIXELDATA(wxAlphaPixelData)
670 // Add in a few things that are different between the wxNativePixelData and
671 // wxAlphaPixelData and the iterator classes and so are not included in our
674 %extend wxNativePixelData_Accessor {
675 void Set(byte red, byte green, byte blue) {
677 self->Green() = green;
682 PyObject* rv = PyTuple_New(3);
683 PyTuple_SetItem(rv, 0, PyInt_FromLong(self->Red()));
684 PyTuple_SetItem(rv, 1, PyInt_FromLong(self->Green()));
685 PyTuple_SetItem(rv, 2, PyInt_FromLong(self->Blue()));
690 %extend wxAlphaPixelData_Accessor {
691 // byte _get_Alpha() { return self->Alpha(); }
692 // void _set_Alpha(byte val) { self->Alpha() = val; }
695 // Alpha = property(_get_Alpha, _set_Alpha)
698 void Set(byte red, byte green, byte blue, byte alpha) {
699 self->Red() = wxPy_premultiply(red, alpha);
700 self->Green() = wxPy_premultiply(green, alpha);
701 self->Blue() = wxPy_premultiply(blue, alpha);
702 self->Alpha() = alpha;
706 PyObject* rv = PyTuple_New(4);
707 int red = self->Red();
708 int green = self->Green();
709 int blue = self->Blue();
710 int alpha = self->Alpha();
712 PyTuple_SetItem(rv, 0, PyInt_FromLong( wxPy_unpremultiply(red, alpha) ));
713 PyTuple_SetItem(rv, 1, PyInt_FromLong( wxPy_unpremultiply(green, alpha) ));
714 PyTuple_SetItem(rv, 2, PyInt_FromLong( wxPy_unpremultiply(blue, alpha) ));
715 PyTuple_SetItem(rv, 3, PyInt_FromLong( alpha ));
721 //---------------------------------------------------------------------------
724 "This class encapsulates a monochrome mask bitmap, where the masked
725 area is black and the unmasked area is white. When associated with a
726 bitmap and drawn in a device context, the unmasked area of the bitmap
727 will be drawn, and the masked area will not be drawn.
729 A mask may be associated with a `wx.Bitmap`. It is used in
730 `wx.DC.DrawBitmap` or `wx.DC.Blit` when the source device context is a
731 `wx.MemoryDC` with a `wx.Bitmap` selected into it that contains a
736 class wxMask : public wxObject {
740 "Constructs a mask from a `wx.Bitmap` and a `wx.Colour` in that bitmap
741 that indicates the transparent portions of the mask. In other words,
742 the pixels in ``bitmap`` that match ``colour`` will be the transparent
743 portions of the mask. If no ``colour`` or an invalid ``colour`` is
744 passed then BLACK is used.
746 :see: `wx.Bitmap`, `wx.Colour`", "");
749 wxMask(const wxBitmap& bitmap, const wxColour& colour = wxNullColour) {
750 if ( !colour.IsOk() )
751 return new wxMask(bitmap, *wxBLACK);
753 return new wxMask(bitmap, colour);
760 %pythoncode { MaskColour = wx._deprecated(Mask, "wx.MaskColour is deprecated, use `wx.Mask` instead.") }
762 //---------------------------------------------------------------------------
763 //---------------------------------------------------------------------------
765 // Turn GIL acquisition back on.