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 this file
23 //---------------------------------------------------------------------------
28 static char** ConvertListOfStrings(PyObject* listOfStrings) {
32 if (!PyList_Check(listOfStrings)) {
33 PyErr_SetString(PyExc_TypeError, "Expected a list of strings.");
36 count = PyList_Size(listOfStrings);
37 cArray = new char*[count];
39 for(int x=0; x<count; x++) {
40 // TODO: Need some validation and error checking here
41 cArray[x] = PyString_AsString(PyList_GET_ITEM(listOfStrings, x));
48 //---------------------------------------------------------------------------
50 // TODO: When the API stabalizes and is available on other platforms, add
51 // wrappers for the new wxBitmap, wxRawBitmap, wxDIB stuff...
54 "The wx.Bitmap class encapsulates the concept of a platform-dependent
55 bitmap. It can be either monochrome or colour, and either loaded from
56 a file or created dynamically. A bitmap can be selected into a memory
57 device context (instance of `wx.MemoryDC`). This enables the bitmap to
58 be copied to a window or memory device context using `wx.DC.Blit`, or
59 to be used as a drawing surface.", "
61 The BMP and XMP image file formats are supported on all platforms by
62 wx.Bitmap. Other formats are automatically loaded by `wx.Image` and
63 converted to a wx.Bitmap, so any image file format supported by
64 `wx.Image` can be used.
66 :todo: Add wrappers and support for raw bitmap data access. Can this
67 be be put into Python without losing the speed benefits of the
68 teplates and iterators in rawbmp.h?
70 :todo: Find a way to do very efficient PIL Image <--> wx.Bitmap
73 :see: `wx.EmptyBitmap`, `wx.BitmapFromIcon`, `wx.BitmapFromImage`,
74 `wx.BitmapFromXPMData`, `wx.BitmapFromBits`, `wx.BitmapFromBuffer`,
75 `wx.BitmapFromBufferRGBA`, `wx.Image`
79 MustHaveApp(wxBitmap);
81 class wxBitmap : public wxGDIObject
85 wxBitmap(const wxString& name, wxBitmapType type=wxBITMAP_TYPE_ANY),
86 "Loads a bitmap from a file.",
88 :param name: Name of the file to load the bitmap from.
89 :param type: The type of image to expect. Can be one of the following
90 constants (assuming that the neccessary `wx.Image` handlers are
102 * wx.BITMAP_TYPE_JPEG
105 * wx.BITMAP_TYPE_PICT
106 * wx.BITMAP_TYPE_ICON
110 :see: Alternate constructors `wx.EmptyBitmap`, `wx.BitmapFromIcon`,
111 `wx.BitmapFromImage`, `wx.BitmapFromXPMData`, `wx.BitmapFromBits`,
112 `wx.BitmapFromBuffer`, `wx.BitmapFromBufferRGBA`,
118 wxBitmap(int width, int height, int depth=-1),
119 "Creates a new bitmap of the given size. A depth of -1 indicates the
120 depth of the current screen or visual. Some platforms only support 1
121 for monochrome and -1 for the current display depth.", "",
125 wxBitmap(const wxIcon& icon),
126 "Create a new bitmap from a `wx.Icon` object.", "",
130 wxBitmap(const wxImage& image, int depth=-1),
131 "Creates bitmap object from a `wx.Image`. This has to be done to
132 actually display a `wx.Image` as you cannot draw an image directly on
133 a window. The resulting bitmap will use the provided colour depth (or
134 that of the current screen colour depth if depth is -1) which entails
135 that a colour reduction may have to take place.", "",
142 "Construct a Bitmap from a list of strings formatted as XPM data.", "",
143 wxBitmap(PyObject* listOfStrings))
145 char** cArray = NULL;
148 cArray = ConvertListOfStrings(listOfStrings);
151 bmp = new wxBitmap(cArray);
159 "Creates a bitmap from an array of bits. You should only use this
160 function for monochrome bitmaps (depth 1) in portable programs: in
161 this case the bits parameter should contain an XBM image. For other
162 bit depths, the behaviour is platform dependent.", "",
163 wxBitmap(PyObject* bits, int width, int height, int depth=1 ))
167 PyString_AsStringAndSize(bits, &buf, &length);
168 return new wxBitmap(buf, width, height, depth);
173 // wxGDIImage methods
177 void SetHandle(long handle) { self->SetHandle((WXHANDLE)handle); }
185 "Gets the width of the bitmap in pixels.", "");
190 "Gets the height of the bitmap in pixels.", "");
195 "Gets the colour depth of the bitmap. A value of 1 indicates a
196 monochrome bitmap.", "");
201 DocStr(GetSize, "Get the size of the bitmap.", "");
203 wxSize size(self->GetWidth(), self->GetHeight());
210 virtual wxImage , ConvertToImage() const,
211 "Creates a platform-independent image from a platform-dependent
212 bitmap. This preserves mask information so that bitmaps and images can
213 be converted back and forth without loss in that respect.", "");
217 virtual wxMask* , GetMask() const,
218 "Gets the associated mask (if any) which may have been loaded from a
219 file or explpicitly set for the bitmap.
221 :see: `SetMask`, `wx.Mask`
224 // MSW only? wxBitmap GetMaskBitmap() const;
228 virtual void , SetMask(wxMask* mask),
229 "Sets the mask for this bitmap.
231 :see: `GetMask`, `wx.Mask`
233 %cleardisown(wxMask*);
236 DocStr(SetMaskColour,
237 "Create a Mask based on a specified colour in the Bitmap.", "");
238 void SetMaskColour(const wxColour& colour) {
239 wxMask *mask = new wxMask(*self, colour);
246 virtual wxBitmap , GetSubBitmap(const wxRect& rect) const,
247 "Returns a sub-bitmap of the current one as long as the rect belongs
248 entirely to the bitmap. This function preserves bit depth and mask
253 virtual bool , SaveFile(const wxString &name, wxBitmapType type,
254 wxPalette *palette = NULL),
255 "Saves a bitmap in the named file. See `__init__` for a description of
256 the ``type`` parameter.", "");
260 virtual bool , LoadFile(const wxString &name, wxBitmapType type),
261 "Loads a bitmap from a file. See `__init__` for a description of the
262 ``type`` parameter.", "");
266 virtual wxPalette *GetPalette() const;
268 virtual void SetPalette(const wxPalette& palette);
272 virtual bool CopyFromIcon(const wxIcon& icon);
275 virtual void , SetHeight(int height),
276 "Set the height property (does not affect the existing bitmap data).", "");
280 virtual void , SetWidth(int width),
281 "Set the width property (does not affect the existing bitmap data).", "");
285 virtual void , SetDepth(int depth),
286 "Set the depth property (does not affect the existing bitmap data).", "");
290 DocStr(SetSize, "Set the bitmap size (does not affect the existing bitmap data).", "");
291 void SetSize(const wxSize& size) {
292 self->SetWidth(size.x);
293 self->SetHeight(size.y);
298 bool CopyFromCursor(const wxCursor& cursor);
300 // WXWIN_COMPATIBILITY_2_4
303 void SetQuality(int q);
304 %pythoncode { GetQuality = wx._deprecated(GetQuality) }
305 %pythoncode { SetQuality = wx._deprecated(SetQuality) }
309 %pythoncode { def __nonzero__(self): return self.Ok() }
312 bool __eq__(const wxBitmap* other) { return other ? (*self == *other) : false; }
313 bool __ne__(const wxBitmap* other) { return other ? (*self != *other) : true; }
316 %property(Depth, GetDepth, SetDepth, doc="See `GetDepth` and `SetDepth`");
317 %property(Height, GetHeight, SetHeight, doc="See `GetHeight` and `SetHeight`");
318 %property(Mask, GetMask, SetMask, doc="See `GetMask` and `SetMask`");
319 %property(Palette, GetPalette, doc="See `GetPalette`");
320 %property(Size, GetSize, SetSize, doc="See `GetSize` and `SetSize`");
321 %property(SubBitmap, GetSubBitmap, doc="See `GetSubBitmap`");
322 %property(Width, GetWidth, SetWidth, doc="See `GetWidth` and `SetWidth`");
327 //---------------------------------------------------------------------------
328 // Factory functions for creating wxBitmaps from Python buffer objects. They
329 // use the Abstract Pixel API to be able to set RGB and A bytes directly into
330 // the wxBitmap's pixel buffer.
333 // See http://tinyurl.com/e5adr for what premultiplying alpha means. It
334 // appears to me that the other platforms are already doing it, so I'll just
335 // automatically do it for wxMSW here.
337 #define wxPy_premultiply(p, a) ((p) * (a) / 0xff)
338 #define wxPy_unpremultiply(p, a) ((a) ? ((p) * 0xff / (a)) : (p))
340 #define wxPy_premultiply(p, a) (p)
341 #define wxPy_unpremultiply(p, a) (p)
346 %newobject _BitmapFromBufferAlpha;
347 %newobject _BitmapFromBuffer;
349 wxBitmap* _BitmapFromBufferAlpha(int width, int height,
350 buffer data, int DATASIZE,
351 buffer alpha, int ALPHASIZE)
353 if (DATASIZE != width*height*3) {
354 wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size.");
358 if (ALPHASIZE != width*height) {
359 wxPyErr_SetString(PyExc_ValueError, "Invalid alpha buffer size.");
363 wxBitmap* bmp = new wxBitmap(width, height, 32);
364 wxAlphaPixelData pixData(*bmp, wxPoint(0,0), wxSize(width,height));
366 // raise an exception...
367 wxPyErr_SetString(PyExc_RuntimeError,
368 "Failed to gain raw access to bitmap data.");
373 wxAlphaPixelData::Iterator p(pixData);
374 for (int y=0; y<height; y++) {
375 wxAlphaPixelData::Iterator rowStart = p;
376 for (int x=0; x<width; x++) {
378 p.Red() = wxPy_premultiply(*(data++), a);
379 p.Green() = wxPy_premultiply(*(data++), a);
380 p.Blue() = wxPy_premultiply(*(data++), a);
385 p.OffsetY(pixData, 1);
390 wxBitmap* _BitmapFromBuffer(int width, int height, buffer data, int DATASIZE)
392 if (DATASIZE != width*height*3) {
393 wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size.");
397 wxBitmap* bmp = new wxBitmap(width, height, 24);
398 wxNativePixelData pixData(*bmp, wxPoint(0,0), wxSize(width,height));
400 // raise an exception...
401 wxPyErr_SetString(PyExc_RuntimeError,
402 "Failed to gain raw access to bitmap data.");
406 wxNativePixelData::Iterator p(pixData);
407 for (int y=0; y<height; y++) {
408 wxNativePixelData::Iterator rowStart = p;
409 for (int x=0; x<width; x++) {
411 p.Green() = *(data++);
412 p.Blue() = *(data++);
416 p.OffsetY(pixData, 1);
424 def BitmapFromBuffer(width, height, dataBuffer, alphaBuffer=None):
426 Creates a `wx.Bitmap` from the data in dataBuffer. The dataBuffer
427 parameter must be a Python object that implements the buffer
428 interface, such as a string, array, etc. The dataBuffer object is
429 expected to contain a series of RGB bytes and be width*height*3
430 bytes long. A buffer object can optionally be supplied for the
431 image's alpha channel data, and it is expected to be width*height
432 bytes long. On Windows the RGB values are 'premultiplied' by the
433 alpha values. (The other platforms do the multiplication
436 Unlike `wx.ImageFromBuffer` the bitmap created with this function
437 does not share the memory buffer with the buffer object. This is
438 because the native pixel buffer format varies on different
439 platforms, and so instead an efficient as possible copy of the
440 data is made from the buffer objects to the bitmap's native pixel
441 buffer. For direct access to a bitmap's pixel buffer see
442 `wx.NativePixelData` and `wx.AlphaPixelData`.
444 :see: `wx.Bitmap`, `wx.BitmapFromBufferRGBA`, `wx.NativePixelData`,
445 `wx.AlphaPixelData`, `wx.ImageFromBuffer`
447 if alphaBuffer is not None:
448 return _gdi_._BitmapFromBufferAlpha(width, height, dataBuffer, alphaBuffer)
450 return _gdi_._BitmapFromBuffer(width, height, dataBuffer)
455 %newobject _BitmapFromBufferRGBA;
457 wxBitmap* _BitmapFromBufferRGBA(int width, int height, buffer data, int DATASIZE)
459 if (DATASIZE != width*height*4) {
460 wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size.");
464 wxBitmap* bmp = new wxBitmap(width, height, 32);
465 wxAlphaPixelData pixData(*bmp, wxPoint(0,0), wxSize(width,height));
467 // raise an exception...
468 wxPyErr_SetString(PyExc_RuntimeError,
469 "Failed to gain raw access to bitmap data.");
474 wxAlphaPixelData::Iterator p(pixData);
475 for (int y=0; y<height; y++) {
476 wxAlphaPixelData::Iterator rowStart = p;
477 for (int x=0; x<width; x++) {
479 p.Red() = wxPy_premultiply(*(data++), a);
480 p.Green() = wxPy_premultiply(*(data++), a);
481 p.Blue() = wxPy_premultiply(*(data++), a);
482 p.Alpha() = a; data++;
486 p.OffsetY(pixData, 1);
493 def BitmapFromBufferRGBA(width, height, dataBuffer):
495 Creates a `wx.Bitmap` from the data in dataBuffer. The dataBuffer
496 parameter must be a Python object that implements the buffer
497 interface, such as a string, array, etc. The dataBuffer object is
498 expected to contain a series of RGBA bytes (red, green, blue and
499 alpha) and be width*height*4 bytes long. On Windows the RGB
500 values are 'premultiplied' by the alpha values. (The other
501 platforms do the multiplication themselves.)
503 Unlike `wx.ImageFromBuffer` the bitmap created with this function
504 does not share the memory buffer with the buffer object. This is
505 because the native pixel buffer format varies on different
506 platforms, and so instead an efficient as possible copy of the
507 data is made from the buffer object to the bitmap's native pixel
508 buffer. For direct access to a bitmap's pixel buffer see
509 `wx.NativePixelData` and `wx.AlphaPixelData`.
511 :see: `wx.Bitmap`, `wx.BitmapFromBuffer`, `wx.NativePixelData`,
512 `wx.AlphaPixelData`, `wx.ImageFromBuffer`
514 return _gdi_._BitmapFromBufferRGBA(width, height, dataBuffer)
518 //---------------------------------------------------------------------------
520 class wxPixelDataBase
523 // origin of the rectangular region we represent
524 wxPoint GetOrigin() const { return m_ptOrigin; }
526 // width and height of the region we represent
527 int GetWidth() const { return m_width; }
528 int GetHeight() const { return m_height; }
530 wxSize GetSize() const { return wxSize(m_width, m_height); }
532 // the distance between two rows
533 int GetRowStride() const { return m_stride; }
538 // Both wxNativePixelData and wxAlphaPixelData have the same interface, so
539 // make a macro to declare them both.
541 %define PIXELDATA(PixelData)
543 typedef PixelData##::Iterator PixelData##_Accessor;
545 class PixelData##_Accessor;
546 class PixelData : public wxPixelDataBase
551 PixelData(wxBitmap& bmp);
552 PixelData(wxBitmap& bmp, const wxRect& rect);
553 PixelData(wxBitmap& bmp, const wxPoint& pt, const wxSize& sz);
557 PixelData##_Accessor GetPixels() const;
561 bool __nonzero__() { return self->operator bool(); }
567 Create and return an iterator object for this pixel data
568 object. (It's really a generator but I won't tell if you
571 width = self.GetWidth()
572 height = self.GetHeight()
573 pixels = self.GetPixels()
575 # This class is a facade over the pixels object (using the one
576 # in the enclosing scope) that only allows Get() and Set() to
578 class PixelFacade(object):
581 def Set(self, *args, **kw):
582 return pixels.Set(*args, **kw)
584 return str(self.Get())
586 return 'pixel(%d,%d): %s' % (x,y,self.Get())
587 X = property(lambda self: x)
588 Y = property(lambda self: y)
591 for y in xrange(height):
592 for x in xrange(width):
593 # We always generate the same pf instance, but it
594 # accesses the pixels object which we use to iterate
595 # over the pixel buffer.
598 pixels.MoveTo(self, 0, y)
601 %property(Pixels, GetPixels, doc="See `GetPixels`");
606 class PixelData##_Accessor
609 %nokwargs PixelData##_Accessor;
611 PixelData##_Accessor(PixelData& data);
612 PixelData##_Accessor(wxBitmap& bmp, PixelData& data);
613 PixelData##_Accessor();
615 ~PixelData##_Accessor();
617 void Reset(const PixelData& data);
621 // PixelData##_Accessor& nextPixel() { return ++(*self); }
622 void nextPixel() { ++(*self); }
625 void Offset(const PixelData& data, int x, int y);
626 void OffsetX(const PixelData& data, int x);
627 void OffsetY(const PixelData& data, int y);
628 void MoveTo(const PixelData& data, int x, int y);
630 // NOTE: For now I'm not wrapping the Red, Green, Blue and Alpha
631 // functions because I can't hide the premultiplying needed on wxMSW
632 // if only the individual components are wrapped, plus it would mean 3
633 // or 4 trips per pixel from Python to C++ instead of just one.
634 // Instead I've added the Set and Get functions and put the
635 // premultiplying in there.
638 // byte _get_Red() { return self->Red(); }
639 // byte _get_Green() { return self->Green(); }
640 // byte _get_Blue() { return self->Blue(); }
642 // void _set_Red(byte val) { self->Red() = val; }
643 // void _set_Green(byte val) { self->Green() = val; }
644 // void _set_Blue(byte val) { self->Blue() = val; }
648 // Red = property(_get_Red, _set_Red)
649 // Green = property(_get_Green, _set_Green)
650 // Blue = property(_get_Blue, _set_Blue)
656 %pythonAppend wxAlphaPixelData::wxAlphaPixelData "self.UseAlpha()"
659 PIXELDATA(wxNativePixelData)
660 PIXELDATA(wxAlphaPixelData)
663 // Add in a few things that are different between the wxNativePixelData and
664 // wxAlphaPixelData and the iterator classes and so are not included in our
667 %extend wxNativePixelData_Accessor {
668 void Set(byte red, byte green, byte blue) {
670 self->Green() = green;
675 PyObject* rv = PyTuple_New(3);
676 PyTuple_SetItem(rv, 0, PyInt_FromLong(self->Red()));
677 PyTuple_SetItem(rv, 1, PyInt_FromLong(self->Green()));
678 PyTuple_SetItem(rv, 2, PyInt_FromLong(self->Blue()));
683 %extend wxAlphaPixelData_Accessor {
684 // byte _get_Alpha() { return self->Alpha(); }
685 // void _set_Alpha(byte val) { self->Alpha() = val; }
688 // Alpha = property(_get_Alpha, _set_Alpha)
691 void Set(byte red, byte green, byte blue, byte alpha) {
692 self->Red() = wxPy_premultiply(red, alpha);
693 self->Green() = wxPy_premultiply(green, alpha);
694 self->Blue() = wxPy_premultiply(blue, alpha);
695 self->Alpha() = alpha;
699 PyObject* rv = PyTuple_New(4);
700 int red = self->Red();
701 int green = self->Green();
702 int blue = self->Blue();
703 int alpha = self->Alpha();
705 PyTuple_SetItem(rv, 0, PyInt_FromLong( wxPy_unpremultiply(red, alpha) ));
706 PyTuple_SetItem(rv, 1, PyInt_FromLong( wxPy_unpremultiply(green, alpha) ));
707 PyTuple_SetItem(rv, 2, PyInt_FromLong( wxPy_unpremultiply(blue, alpha) ));
708 PyTuple_SetItem(rv, 3, PyInt_FromLong( alpha ));
714 //---------------------------------------------------------------------------
717 "This class encapsulates a monochrome mask bitmap, where the masked
718 area is black and the unmasked area is white. When associated with a
719 bitmap and drawn in a device context, the unmasked area of the bitmap
720 will be drawn, and the masked area will not be drawn.
722 A mask may be associated with a `wx.Bitmap`. It is used in
723 `wx.DC.DrawBitmap` or `wx.DC.Blit` when the source device context is a
724 `wx.MemoryDC` with a `wx.Bitmap` selected into it that contains a
729 class wxMask : public wxObject {
733 "Constructs a mask from a `wx.Bitmap` and a `wx.Colour` in that bitmap
734 that indicates the transparent portions of the mask. In other words,
735 the pixels in ``bitmap`` that match ``colour`` will be the transparent
736 portions of the mask. If no ``colour`` or an invalid ``colour`` is
737 passed then BLACK is used.
739 :see: `wx.Bitmap`, `wx.Colour`", "");
742 wxMask(const wxBitmap& bitmap, const wxColour& colour = wxNullColour) {
744 return new wxMask(bitmap, *wxBLACK);
746 return new wxMask(bitmap, colour);
753 %pythoncode { MaskColour = wx._deprecated(Mask, "wx.MaskColour is deprecated, use `wx.Mask` instead.") }
755 //---------------------------------------------------------------------------
756 //---------------------------------------------------------------------------