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 //---------------------------------------------------------------------------
27 // See http://tinyurl.com/e5adr for what premultiplying alpha means. wxMSW and
28 // wxMac want to have the values premultiplied by the alpha value, but the
29 // other platforms don't. These macros help keep the code clean.
30 #if defined(__WXMSW__) || (defined(__WXMAC__) && wxMAC_USE_CORE_GRAPHICS)
31 #define wxPy_premultiply(p, a) ((p) * (a) / 0xff)
32 #define wxPy_unpremultiply(p, a) ((a) ? ((p) * 0xff / (a)) : (p))
34 #define wxPy_premultiply(p, a) (p)
35 #define wxPy_unpremultiply(p, a) (p)
39 //---------------------------------------------------------------------------
45 static char** ConvertListOfStrings(PyObject* listOfStrings) {
49 if (!PyList_Check(listOfStrings)) {
50 PyErr_SetString(PyExc_TypeError, "Expected a list of strings.");
53 count = PyList_Size(listOfStrings);
54 cArray = new char*[count];
56 for(int x=0; x<count; x++) {
57 // TODO: Need some validation and error checking here
58 cArray[x] = PyString_AsString(PyList_GET_ITEM(listOfStrings, x));
65 //---------------------------------------------------------------------------
67 // TODO: When the API stabalizes and is available on other platforms, add
68 // wrappers for the new wxBitmap, wxRawBitmap, wxDIB stuff...
71 "The wx.Bitmap class encapsulates the concept of a platform-dependent
72 bitmap. It can be either monochrome or colour, and either loaded from
73 a file or created dynamically. A bitmap can be selected into a memory
74 device context (instance of `wx.MemoryDC`). This enables the bitmap to
75 be copied to a window or memory device context using `wx.DC.Blit`, or
76 to be used as a drawing surface.", "
78 The BMP and XMP image file formats are supported on all platforms by
79 wx.Bitmap. Other formats are automatically loaded by `wx.Image` and
80 converted to a wx.Bitmap, so any image file format supported by
81 `wx.Image` can be used.
83 :todo: Add wrappers and support for raw bitmap data access. Can this
84 be be put into Python without losing the speed benefits of the
85 teplates and iterators in rawbmp.h?
87 :todo: Find a way to do very efficient PIL Image <--> wx.Bitmap
90 :see: `wx.EmptyBitmap`, `wx.BitmapFromIcon`, `wx.BitmapFromImage`,
91 `wx.BitmapFromXPMData`, `wx.BitmapFromBits`, `wx.BitmapFromBuffer`,
92 `wx.BitmapFromBufferRGBA`, `wx.Image`
96 MustHaveApp(wxBitmap);
98 class wxBitmap : public wxGDIObject
102 wxBitmap(const wxString& name, wxBitmapType type=wxBITMAP_TYPE_ANY),
103 "Loads a bitmap from a file.",
105 :param name: Name of the file to load the bitmap from.
106 :param type: The type of image to expect. Can be one of the following
107 constants (assuming that the neccessary `wx.Image` handlers are
119 * wx.BITMAP_TYPE_JPEG
122 * wx.BITMAP_TYPE_PICT
123 * wx.BITMAP_TYPE_ICON
127 :see: Alternate constructors `wx.EmptyBitmap`, `wx.BitmapFromIcon`,
128 `wx.BitmapFromImage`, `wx.BitmapFromXPMData`, `wx.BitmapFromBits`,
129 `wx.BitmapFromBuffer`, `wx.BitmapFromBufferRGBA`,
135 wxBitmap(int width, int height, int depth=-1),
136 "Creates a new bitmap of the given size. A depth of -1 indicates the
137 depth of the current screen or visual. Some platforms only support 1
138 for monochrome and -1 for the current display depth.", "",
142 wxBitmap(const wxIcon& icon),
143 "Create a new bitmap from a `wx.Icon` object.", "",
147 wxBitmap(const wxImage& image, int depth=-1),
148 "Creates bitmap object from a `wx.Image`. This has to be done to
149 actually display a `wx.Image` as you cannot draw an image directly on
150 a window. The resulting bitmap will use the provided colour depth (or
151 that of the current screen colour depth if depth is -1) which entails
152 that a colour reduction may have to take place.", "",
159 "Construct a Bitmap from a list of strings formatted as XPM data.", "",
160 wxBitmap(PyObject* listOfStrings))
162 char** cArray = NULL;
165 cArray = ConvertListOfStrings(listOfStrings);
168 bmp = new wxBitmap(cArray);
176 "Creates a bitmap from an array of bits. You should only use this
177 function for monochrome bitmaps (depth 1) in portable programs: in
178 this case the bits parameter should contain an XBM image. For other
179 bit depths, the behaviour is platform dependent.", "",
180 wxBitmap(PyObject* bits, int width, int height, int depth=1 ))
184 PyString_AsStringAndSize(bits, &buf, &length);
185 return new wxBitmap(buf, width, height, depth);
190 // wxGDIImage methods
194 void SetHandle(long handle) { self->SetHandle((WXHANDLE)handle); }
199 %pythoncode { Ok = IsOk }
203 "Gets the width of the bitmap in pixels.", "");
208 "Gets the height of the bitmap in pixels.", "");
213 "Gets the colour depth of the bitmap. A value of 1 indicates a
214 monochrome bitmap.", "");
219 DocStr(GetSize, "Get the size of the bitmap.", "");
221 wxSize size(self->GetWidth(), self->GetHeight());
228 virtual wxImage , ConvertToImage() const,
229 "Creates a platform-independent image from a platform-dependent
230 bitmap. This preserves mask information so that bitmaps and images can
231 be converted back and forth without loss in that respect.", "");
235 virtual wxMask* , GetMask() const,
236 "Gets the associated mask (if any) which may have been loaded from a
237 file or explpicitly set for the bitmap.
239 :see: `SetMask`, `wx.Mask`
242 // MSW only? wxBitmap GetMaskBitmap() const;
246 virtual void , SetMask(wxMask* mask),
247 "Sets the mask for this bitmap.
249 :see: `GetMask`, `wx.Mask`
251 %cleardisown(wxMask*);
254 DocStr(SetMaskColour,
255 "Create a Mask based on a specified colour in the Bitmap.", "");
256 void SetMaskColour(const wxColour& colour) {
257 wxMask *mask = new wxMask(*self, colour);
264 virtual wxBitmap , GetSubBitmap(const wxRect& rect) const,
265 "Returns a sub-bitmap of the current one as long as the rect belongs
266 entirely to the bitmap. This function preserves bit depth and mask
271 virtual bool , SaveFile(const wxString &name, wxBitmapType type,
272 wxPalette *palette = NULL),
273 "Saves a bitmap in the named file. See `__init__` for a description of
274 the ``type`` parameter.", "");
278 virtual bool , LoadFile(const wxString &name, wxBitmapType type),
279 "Loads a bitmap from a file. See `__init__` for a description of the
280 ``type`` parameter.", "");
284 virtual wxPalette *GetPalette() const;
286 virtual void SetPalette(const wxPalette& palette);
290 virtual bool CopyFromIcon(const wxIcon& icon);
293 virtual void , SetHeight(int height),
294 "Set the height property (does not affect the existing bitmap data).", "");
298 virtual void , SetWidth(int width),
299 "Set the width property (does not affect the existing bitmap data).", "");
303 virtual void , SetDepth(int depth),
304 "Set the depth property (does not affect the existing bitmap data).", "");
308 DocStr(SetSize, "Set the bitmap size (does not affect the existing bitmap data).", "");
309 void SetSize(const wxSize& size) {
310 self->SetWidth(size.x);
311 self->SetHeight(size.y);
316 bool CopyFromCursor(const wxCursor& cursor);
320 DocStr(CopyFromBuffer,
321 "Copy data from a RGB buffer object to replace the bitmap pixel data.
322 See `wx.BitmapFromBuffer` for more details.", "");
323 void CopyFromBuffer(buffer data, int DATASIZE)
325 int height=self->GetHeight();
326 int width=self->GetWidth();
328 if (DATASIZE != width * height * 3) {
329 wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size.");
331 wxNativePixelData pixData(*self, wxPoint(0,0), wxSize(width, height));
333 // raise an exception...
334 wxPyErr_SetString(PyExc_RuntimeError,
335 "Failed to gain raw access to bitmap data.");
339 wxNativePixelData::Iterator p(pixData);
340 for (int y=0; y<height; y++) {
341 wxNativePixelData::Iterator rowStart = p;
342 for (int x=0; x<width; x++) {
344 p.Green() = *(data++);
345 p.Blue() = *(data++);
349 p.OffsetY(pixData, 1);
353 DocStr(CopyFromBufferRGBA,
354 "Copy data from a RGBA buffer object to replace the bitmap pixel data.
355 See `wx.BitmapFromBufferRGBA` for more details.", "");
356 void CopyFromBufferRGBA(buffer data, int DATASIZE)
358 int height=self->GetHeight();
359 int width=self->GetWidth();
361 if (DATASIZE != width * height * 4) {
362 wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size.");
364 wxAlphaPixelData pixData(*self, 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);
381 p.Alpha() = a; data++;
385 p.OffsetY(pixData, 1);
391 %pythoncode { def __nonzero__(self): return self.IsOk() }
393 // TODO: Should these just be removed since the C++ operators are
394 // gone? Or is using IsSameAs for wxPython ok?
396 bool __eq__(const wxBitmap* other) { return other ? self->IsSameAs(*other) : false; }
397 bool __ne__(const wxBitmap* other) { return other ? !self->IsSameAs(*other) : true; }
400 %property(Depth, GetDepth, SetDepth, doc="See `GetDepth` and `SetDepth`");
401 %property(Height, GetHeight, SetHeight, doc="See `GetHeight` and `SetHeight`");
402 %property(Mask, GetMask, SetMask, doc="See `GetMask` and `SetMask`");
403 %property(Palette, GetPalette, doc="See `GetPalette`");
404 %property(Size, GetSize, SetSize, doc="See `GetSize` and `SetSize`");
405 %property(SubBitmap, GetSubBitmap, doc="See `GetSubBitmap`");
406 %property(Width, GetWidth, SetWidth, doc="See `GetWidth` and `SetWidth`");
411 //---------------------------------------------------------------------------
412 // Factory functions for creating wxBitmaps from Python buffer objects. They
413 // use the Abstract Pixel API to be able to set RGB and A bytes directly into
414 // the wxBitmap's pixel buffer.
417 %newobject _BitmapFromBufferAlpha;
418 %newobject _BitmapFromBuffer;
420 wxBitmap* _BitmapFromBufferAlpha(int width, int height,
421 buffer data, int DATASIZE,
422 buffer alpha, int ALPHASIZE)
424 if (DATASIZE != width*height*3) {
425 wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size.");
429 if (ALPHASIZE != width*height) {
430 wxPyErr_SetString(PyExc_ValueError, "Invalid alpha buffer size.");
434 wxBitmap* bmp = new wxBitmap(width, height, 32);
435 wxAlphaPixelData pixData(*bmp, wxPoint(0,0), wxSize(width,height));
437 // raise an exception...
438 wxPyErr_SetString(PyExc_RuntimeError,
439 "Failed to gain raw access to bitmap data.");
444 wxAlphaPixelData::Iterator p(pixData);
445 for (int y=0; y<height; y++) {
446 wxAlphaPixelData::Iterator rowStart = p;
447 for (int x=0; x<width; x++) {
449 p.Red() = wxPy_premultiply(*(data++), a);
450 p.Green() = wxPy_premultiply(*(data++), a);
451 p.Blue() = wxPy_premultiply(*(data++), a);
456 p.OffsetY(pixData, 1);
461 wxBitmap* _BitmapFromBuffer(int width, int height, buffer data, int DATASIZE)
463 if (DATASIZE != width*height*3) {
464 wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size.");
468 wxBitmap* bmp = new wxBitmap(width, height, 24);
469 wxNativePixelData pixData(*bmp, wxPoint(0,0), wxSize(width,height));
471 // raise an exception...
472 wxPyErr_SetString(PyExc_RuntimeError,
473 "Failed to gain raw access to bitmap data.");
477 wxNativePixelData::Iterator p(pixData);
478 for (int y=0; y<height; y++) {
479 wxNativePixelData::Iterator rowStart = p;
480 for (int x=0; x<width; x++) {
482 p.Green() = *(data++);
483 p.Blue() = *(data++);
487 p.OffsetY(pixData, 1);
495 def BitmapFromBuffer(width, height, dataBuffer, alphaBuffer=None):
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 RGB bytes and be width*height*3
501 bytes long. A buffer object can optionally be supplied for the
502 image's alpha channel data, and it is expected to be width*height
503 bytes long. On Windows and Mac the RGB values are 'premultiplied'
504 by the alpha values. (The other platforms do the multiplication
507 Unlike `wx.ImageFromBuffer` the bitmap created with this function
508 does not share the memory buffer with the buffer object. This is
509 because the native pixel buffer format varies on different
510 platforms, and so instead an efficient as possible copy of the
511 data is made from the buffer objects to the bitmap's native pixel
512 buffer. For direct access to a bitmap's pixel buffer see
513 `wx.NativePixelData` and `wx.AlphaPixelData`.
515 :see: `wx.Bitmap`, `wx.BitmapFromBufferRGBA`, `wx.NativePixelData`,
516 `wx.AlphaPixelData`, `wx.ImageFromBuffer`
518 if alphaBuffer is not None:
519 return _gdi_._BitmapFromBufferAlpha(width, height, dataBuffer, alphaBuffer)
521 return _gdi_._BitmapFromBuffer(width, height, dataBuffer)
526 %newobject _BitmapFromBufferRGBA;
528 wxBitmap* _BitmapFromBufferRGBA(int width, int height, buffer data, int DATASIZE)
530 if (DATASIZE != width*height*4) {
531 wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size.");
535 wxBitmap* bmp = new wxBitmap(width, height, 32);
536 wxAlphaPixelData pixData(*bmp, wxPoint(0,0), wxSize(width,height));
538 // raise an exception...
539 wxPyErr_SetString(PyExc_RuntimeError,
540 "Failed to gain raw access to bitmap data.");
545 wxAlphaPixelData::Iterator p(pixData);
546 for (int y=0; y<height; y++) {
547 wxAlphaPixelData::Iterator rowStart = p;
548 for (int x=0; x<width; x++) {
550 p.Red() = wxPy_premultiply(*(data++), a);
551 p.Green() = wxPy_premultiply(*(data++), a);
552 p.Blue() = wxPy_premultiply(*(data++), a);
553 p.Alpha() = a; data++;
557 p.OffsetY(pixData, 1);
564 def BitmapFromBufferRGBA(width, height, dataBuffer):
566 Creates a `wx.Bitmap` from the data in dataBuffer. The dataBuffer
567 parameter must be a Python object that implements the buffer
568 interface, such as a string, array, etc. The dataBuffer object is
569 expected to contain a series of RGBA bytes (red, green, blue and
570 alpha) and be width*height*4 bytes long. On Windows and Mac the
571 RGB values are 'premultiplied' by the alpha values. (The other
572 platforms do the multiplication themselves.)
574 Unlike `wx.ImageFromBuffer` the bitmap created with this function
575 does not share the memory buffer with the buffer object. This is
576 because the native pixel buffer format varies on different
577 platforms, and so instead an efficient as possible copy of the
578 data is made from the buffer object to the bitmap's native pixel
579 buffer. For direct access to a bitmap's pixel buffer see
580 `wx.NativePixelData` and `wx.AlphaPixelData`.
582 :see: `wx.Bitmap`, `wx.BitmapFromBuffer`, `wx.NativePixelData`,
583 `wx.AlphaPixelData`, `wx.ImageFromBuffer`
585 return _gdi_._BitmapFromBufferRGBA(width, height, dataBuffer)
589 //---------------------------------------------------------------------------
591 class wxPixelDataBase
594 // origin of the rectangular region we represent
595 wxPoint GetOrigin() const { return m_ptOrigin; }
597 // width and height of the region we represent
598 int GetWidth() const { return m_width; }
599 int GetHeight() const { return m_height; }
601 wxSize GetSize() const { return wxSize(m_width, m_height); }
603 // the distance between two rows
604 int GetRowStride() const { return m_stride; }
606 %property(Height, GetHeight, doc="See `GetHeight`");
607 %property(Origin, GetOrigin, doc="See `GetOrigin`");
608 %property(RowStride, GetRowStride, doc="See `GetRowStride`");
609 %property(Size, GetSize, doc="See `GetSize`");
610 %property(Width, GetWidth, doc="See `GetWidth`");
614 // Both wxNativePixelData and wxAlphaPixelData have the same interface, so
615 // make a macro to declare them both.
617 %define PIXELDATA(PixelData)
619 typedef PixelData##::Iterator PixelData##_Accessor;
621 class PixelData##_Accessor;
622 class PixelData : public wxPixelDataBase
627 PixelData(wxBitmap& bmp);
628 PixelData(wxBitmap& bmp, const wxRect& rect);
629 PixelData(wxBitmap& bmp, const wxPoint& pt, const wxSize& sz);
633 PixelData##_Accessor GetPixels() const;
637 bool __nonzero__() { return self->operator bool(); }
643 Create and return an iterator object for this pixel data
644 object. (It's really a generator but I won't tell if you
647 width = self.GetWidth()
648 height = self.GetHeight()
649 pixels = self.GetPixels()
651 # This class is a facade over the pixels object (using the one
652 # in the enclosing scope) that only allows Get() and Set() to
654 class PixelFacade(object):
657 def Set(self, *args, **kw):
658 return pixels.Set(*args, **kw)
660 return str(self.Get())
662 return 'pixel(%d,%d): %s' % (x,y,self.Get())
663 X = property(lambda self: x)
664 Y = property(lambda self: y)
667 for y in xrange(height):
668 for x in xrange(width):
669 # We always generate the same pf instance, but it
670 # accesses the pixels object which we use to iterate
671 # over the pixel buffer.
674 pixels.MoveTo(self, 0, y)
677 %property(Pixels, GetPixels, doc="See `GetPixels`");
682 class PixelData##_Accessor
685 %nokwargs PixelData##_Accessor;
687 PixelData##_Accessor(PixelData& data);
688 PixelData##_Accessor(wxBitmap& bmp, PixelData& data);
689 PixelData##_Accessor();
691 ~PixelData##_Accessor();
693 void Reset(const PixelData& data);
697 // PixelData##_Accessor& nextPixel() { return ++(*self); }
698 void nextPixel() { ++(*self); }
701 void Offset(const PixelData& data, int x, int y);
702 void OffsetX(const PixelData& data, int x);
703 void OffsetY(const PixelData& data, int y);
704 void MoveTo(const PixelData& data, int x, int y);
706 // NOTE: For now I'm not wrapping the Red, Green, Blue and Alpha
707 // functions because I can't hide the premultiplying needed on wxMSW
708 // if only the individual components are wrapped, plus it would mean 3
709 // or 4 trips per pixel from Python to C++ instead of just one.
710 // Instead I've added the Set and Get functions and put the
711 // premultiplying in there.
714 // byte _get_Red() { return self->Red(); }
715 // byte _get_Green() { return self->Green(); }
716 // byte _get_Blue() { return self->Blue(); }
718 // void _set_Red(byte val) { self->Red() = val; }
719 // void _set_Green(byte val) { self->Green() = val; }
720 // void _set_Blue(byte val) { self->Blue() = val; }
724 // Red = property(_get_Red, _set_Red)
725 // Green = property(_get_Green, _set_Green)
726 // Blue = property(_get_Blue, _set_Blue)
732 %pythonAppend wxAlphaPixelData::wxAlphaPixelData "self.UseAlpha()"
735 PIXELDATA(wxNativePixelData)
736 PIXELDATA(wxAlphaPixelData)
739 // Add in a few things that are different between the wxNativePixelData and
740 // wxAlphaPixelData and the iterator classes and so are not included in our
743 %extend wxNativePixelData_Accessor {
744 void Set(byte red, byte green, byte blue) {
746 self->Green() = green;
751 PyObject* rv = PyTuple_New(3);
752 PyTuple_SetItem(rv, 0, PyInt_FromLong(self->Red()));
753 PyTuple_SetItem(rv, 1, PyInt_FromLong(self->Green()));
754 PyTuple_SetItem(rv, 2, PyInt_FromLong(self->Blue()));
759 %extend wxAlphaPixelData_Accessor {
760 // byte _get_Alpha() { return self->Alpha(); }
761 // void _set_Alpha(byte val) { self->Alpha() = val; }
764 // Alpha = property(_get_Alpha, _set_Alpha)
767 void Set(byte red, byte green, byte blue, byte alpha) {
768 self->Red() = wxPy_premultiply(red, alpha);
769 self->Green() = wxPy_premultiply(green, alpha);
770 self->Blue() = wxPy_premultiply(blue, alpha);
771 self->Alpha() = alpha;
775 PyObject* rv = PyTuple_New(4);
776 int red = self->Red();
777 int green = self->Green();
778 int blue = self->Blue();
779 int alpha = self->Alpha();
781 PyTuple_SetItem(rv, 0, PyInt_FromLong( wxPy_unpremultiply(red, alpha) ));
782 PyTuple_SetItem(rv, 1, PyInt_FromLong( wxPy_unpremultiply(green, alpha) ));
783 PyTuple_SetItem(rv, 2, PyInt_FromLong( wxPy_unpremultiply(blue, alpha) ));
784 PyTuple_SetItem(rv, 3, PyInt_FromLong( alpha ));
790 //---------------------------------------------------------------------------
793 "This class encapsulates a monochrome mask bitmap, where the masked
794 area is black and the unmasked area is white. When associated with a
795 bitmap and drawn in a device context, the unmasked area of the bitmap
796 will be drawn, and the masked area will not be drawn.
798 A mask may be associated with a `wx.Bitmap`. It is used in
799 `wx.DC.DrawBitmap` or `wx.DC.Blit` when the source device context is a
800 `wx.MemoryDC` with a `wx.Bitmap` selected into it that contains a
805 class wxMask : public wxObject {
809 "Constructs a mask from a `wx.Bitmap` and a `wx.Colour` in that bitmap
810 that indicates the transparent portions of the mask. In other words,
811 the pixels in ``bitmap`` that match ``colour`` will be the transparent
812 portions of the mask. If no ``colour`` or an invalid ``colour`` is
813 passed then BLACK is used.
815 :see: `wx.Bitmap`, `wx.Colour`", "");
818 wxMask(const wxBitmap& bitmap, const wxColour& colour = wxNullColour) {
819 if ( !colour.IsOk() )
820 return new wxMask(bitmap, *wxBLACK);
822 return new wxMask(bitmap, colour);
829 %pythoncode { MaskColour = wx._deprecated(Mask, "wx.MaskColour is deprecated, use `wx.Mask` instead.") }
831 //---------------------------------------------------------------------------
832 //---------------------------------------------------------------------------
834 // Turn GIL acquisition back on.