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`,
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.", "");
218 virtual wxMask* , GetMask() const,
219 "Gets the associated mask (if any) which may have been loaded from a
220 file or explpicitly set for the bitmap.
222 :see: `SetMask`, `wx.Mask`
225 // MSW only? wxBitmap GetMaskBitmap() const;
229 virtual void , SetMask(wxMask* mask),
230 "Sets the mask for this bitmap.
232 :see: `GetMask`, `wx.Mask`
234 %cleardisown(wxMask*);
237 DocStr(SetMaskColour,
238 "Create a Mask based on a specified colour in the Bitmap.", "");
239 void SetMaskColour(const wxColour& colour) {
240 wxMask *mask = new wxMask(*self, colour);
247 virtual wxBitmap , GetSubBitmap(const wxRect& rect) const,
248 "Returns a sub-bitmap of the current one as long as the rect belongs
249 entirely to the bitmap. This function preserves bit depth and mask
254 virtual bool , SaveFile(const wxString &name, wxBitmapType type,
255 wxPalette *palette = NULL),
256 "Saves a bitmap in the named file. See `__init__` for a description of
257 the ``type`` parameter.", "");
261 virtual bool , LoadFile(const wxString &name, wxBitmapType type),
262 "Loads a bitmap from a file. See `__init__` for a description of the
263 ``type`` parameter.", "");
267 virtual wxPalette *GetPalette() const;
269 virtual void SetPalette(const wxPalette& palette);
273 virtual bool CopyFromIcon(const wxIcon& icon);
276 virtual void , SetHeight(int height),
277 "Set the height property (does not affect the existing bitmap data).", "");
281 virtual void , SetWidth(int width),
282 "Set the width property (does not affect the existing bitmap data).", "");
286 virtual void , SetDepth(int depth),
287 "Set the depth property (does not affect the existing bitmap data).", "");
291 DocStr(SetSize, "Set the bitmap size (does not affect the existing bitmap data).", "");
292 void SetSize(const wxSize& size) {
293 self->SetWidth(size.x);
294 self->SetHeight(size.y);
299 bool CopyFromCursor(const wxCursor& cursor);
301 // WXWIN_COMPATIBILITY_2_4
304 void SetQuality(int q);
305 %pythoncode { GetQuality = wx._deprecated(GetQuality) }
306 %pythoncode { SetQuality = wx._deprecated(SetQuality) }
310 %pythoncode { def __nonzero__(self): return self.Ok() }
313 bool __eq__(const wxBitmap* other) { return other ? (*self == *other) : false; }
314 bool __ne__(const wxBitmap* other) { return other ? (*self != *other) : true; }
319 //---------------------------------------------------------------------------
320 // Factory functions for creating wxBitmaps from Python buffer objects. They
321 // use the Abstract Pixel API to be able to set RGB and A bytes directly into
322 // the wxBitmap's pixel buffer.
325 // See http://tinyurl.com/e5adr for what premultiplying alpha means. It
326 // appears to me that the other platforms are already doing it, so I'll just
327 // automatically do it for wxMSW here.
329 #define wxPy_premultiply(p, a) ((p) * (a) / 256)
330 #define wxPy_unpremultiply(p, a) ((a) ? ((p) * 256 / (a)) : (p))
332 #define wxPy_premultiply(p, a) (p)
333 #define wxPy_unpremultiply(p, a) (p)
338 %newobject _BitmapFromBufferAlpha;
339 %newobject _BitmapFromBuffer;
341 wxBitmap* _BitmapFromBufferAlpha(int width, int height,
342 buffer data, int DATASIZE,
343 buffer alpha, int ALPHASIZE)
345 if (DATASIZE != width*height*3) {
346 wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size.");
350 if (ALPHASIZE != width*height) {
351 wxPyErr_SetString(PyExc_ValueError, "Invalid alpha buffer size.");
355 wxBitmap* bmp = new wxBitmap(width, height, 32);
356 wxAlphaPixelData pixData(*bmp, wxPoint(0,0), wxSize(width,height));
358 // raise an exception...
359 wxPyErr_SetString(PyExc_RuntimeError,
360 "Failed to gain raw access to bitmap data.");
365 wxAlphaPixelData::Iterator p(pixData);
366 for (int y=0; y<height; y++) {
367 wxAlphaPixelData::Iterator rowStart = p;
368 for (int x=0; x<width; x++) {
370 p.Red() = wxPy_premultiply(*(data++), a);
371 p.Green() = wxPy_premultiply(*(data++), a);
372 p.Blue() = wxPy_premultiply(*(data++), a);
377 p.OffsetY(pixData, 1);
382 wxBitmap* _BitmapFromBuffer(int width, int height, buffer data, int DATASIZE)
384 if (DATASIZE != width*height*3) {
385 wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size.");
389 wxBitmap* bmp = new wxBitmap(width, height, 24);
390 wxNativePixelData pixData(*bmp, wxPoint(0,0), wxSize(width,height));
392 // raise an exception...
393 wxPyErr_SetString(PyExc_RuntimeError,
394 "Failed to gain raw access to bitmap data.");
398 wxNativePixelData::Iterator p(pixData);
399 for (int y=0; y<height; y++) {
400 wxNativePixelData::Iterator rowStart = p;
401 for (int x=0; x<width; x++) {
403 p.Green() = *(data++);
404 p.Blue() = *(data++);
408 p.OffsetY(pixData, 1);
416 def BitmapFromBuffer(width, height, dataBuffer, alphaBuffer=None):
418 Creates a `wx.Bitmap` from the data in dataBuffer. The dataBuffer
419 parameter must be a Python object that implements the buffer interface, or
420 is convertable to a buffer object, such as a string, array, etc. The
421 dataBuffer object is expected to contain a series of RGB bytes and be
422 width*height*3 bytes long. A buffer object can optionally be supplied for
423 the image's alpha channel data, and it is expected to be width*height
424 bytes long. On Windows the RGB values are 'premultiplied' by the alpha
425 values. (The other platforms appear to already be premultiplying the
428 Unlike `wx.ImageFromBuffer` the bitmap created with this function does not
429 share the memory buffer with the buffer object. This is because the
430 native pixel buffer format varies on different platforms, and so instead
431 an efficient as possible copy of the data is made from the buffer objects
432 to the bitmap's native pixel buffer. For direct access to a bitmap's
433 pixel buffer see `wx.NativePixelData` and `wx.AlphaPixelData`.
435 :see: `wx.Bitmap`, `wx.BitmapFromBufferRGBA`, `wx.NativePixelData`,
436 `wx.AlphaPixelData`, `wx.ImageFromBuffer`
438 if not isinstance(dataBuffer, buffer):
439 dataBuffer = buffer(dataBuffer)
440 if alphaBuffer is not None and not isinstance(alphaBuffer, buffer):
441 alphaBuffer = buffer(alphaBuffer)
442 if alphaBuffer is not None:
443 return _gdi_._BitmapFromBufferAlpha(width, height, dataBuffer, alphaBuffer)
445 return _gdi_._BitmapFromBuffer(width, height, dataBuffer)
450 %newobject _BitmapFromBufferRGBA;
452 wxBitmap* _BitmapFromBufferRGBA(int width, int height, buffer data, int DATASIZE)
454 if (DATASIZE != width*height*4) {
455 wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size.");
459 wxBitmap* bmp = new wxBitmap(width, height, 32);
460 wxAlphaPixelData pixData(*bmp, wxPoint(0,0), wxSize(width,height));
462 // raise an exception...
463 wxPyErr_SetString(PyExc_RuntimeError,
464 "Failed to gain raw access to bitmap data.");
469 wxAlphaPixelData::Iterator p(pixData);
470 for (int y=0; y<height; y++) {
471 wxAlphaPixelData::Iterator rowStart = p;
472 for (int x=0; x<width; x++) {
474 p.Red() = wxPy_premultiply(*(data++), a);
475 p.Green() = wxPy_premultiply(*(data++), a);
476 p.Blue() = wxPy_premultiply(*(data++), a);
477 p.Alpha() = a; data++;
481 p.OffsetY(pixData, 1);
488 def BitmapFromBufferRGBA(width, height, dataBuffer):
490 Creates a `wx.Bitmap` from the data in dataBuffer. The dataBuffer
491 parameter must be a Python object that implements the buffer interface, or
492 is convertable to a buffer object, such as a string, array, etc. The
493 dataBuffer object is expected to contain a series of RGBA bytes (red,
494 green, blue and alpha) and be width*height*4 bytes long. On Windows the
495 RGB values are 'premultiplied' by the alpha values. (The other platforms
496 appear to already be premultiplying the alpha.)
498 Unlike `wx.ImageFromBuffer` the bitmap created with this function does not
499 share the memory buffer with the buffer object. This is because the
500 native pixel buffer format varies on different platforms, and so instead
501 an efficient as possible copy of the data is made from the buffer object
502 to the bitmap's native pixel buffer. For direct access to a bitmap's
503 pixel buffer see `wx.NativePixelData` and `wx.AlphaPixelData`.
505 :see: `wx.Bitmap`, `wx.BitmapFromBuffer`, `wx.NativePixelData`,
506 `wx.AlphaPixelData`, `wx.ImageFromBuffer`
508 if not isinstance(dataBuffer, buffer):
509 dataBuffer = buffer(dataBuffer)
510 return _gdi_._BitmapFromBufferRGBA(width, height, dataBuffer)
514 //---------------------------------------------------------------------------
516 class wxPixelDataBase
519 // origin of the rectangular region we represent
520 wxPoint GetOrigin() const { return m_ptOrigin; }
522 // width and height of the region we represent
523 int GetWidth() const { return m_width; }
524 int GetHeight() const { return m_height; }
526 wxSize GetSize() const { return wxSize(m_width, m_height); }
528 // the distance between two rows
529 int GetRowStride() const { return m_stride; }
535 %define PIXELDATA(PixelData)
537 typedef PixelData##::Iterator PixelData##_Iterator;
539 class PixelData##_Iterator;
540 class PixelData : public wxPixelDataBase
545 PixelData(wxBitmap& bmp);
546 PixelData(wxBitmap& bmp, const wxRect& rect);
547 PixelData(wxBitmap& bmp, const wxPoint& pt, const wxSize& sz);
552 bool __nonzero__() { return self->operator bool(); }
555 PixelData##_Iterator GetPixels() const;
561 class PixelData##_Iterator
564 %nokwargs PixelData##_Iterator;
566 PixelData##_Iterator(PixelData& data);
567 PixelData##_Iterator(wxBitmap& bmp, PixelData& data);
568 PixelData##_Iterator();
570 ~PixelData##_Iterator();
572 void Reset(const PixelData& data);
576 // PixelData##_Iterator& nextPixel() { return ++(*self); }
577 void nextPixel() { ++(*self); }
580 void Offset(const PixelData& data, int x, int y);
581 void OffsetX(const PixelData& data, int x);
582 void OffsetY(const PixelData& data, int y);
583 void MoveTo(const PixelData& data, int x, int y);
585 // NOTE: For now I'm not wrapping the Red, Green, Blue and Alpha functions
586 // because I can't hide the premultiplying needed on wxMSW if only the
587 // individual components are wrapped. Instead I've added the Set and Get
588 // functions and put the puemultiplying in there.
591 // byte _get_Red() { return self->Red(); }
592 // byte _get_Green() { return self->Green(); }
593 // byte _get_Blue() { return self->Blue(); }
595 // void _set_Red(byte val) { self->Red() = val; }
596 // void _set_Green(byte val) { self->Green() = val; }
597 // void _set_Blue(byte val) { self->Blue() = val; }
601 // Red = property(_get_Red, _set_Red)
602 // Green = property(_get_Green, _set_Green)
603 // Blue = property(_get_Blue, _set_Blue)
609 PIXELDATA(wxNativePixelData)
610 PIXELDATA(wxAlphaPixelData)
613 // Add in a few things that are different between the wxNativePixelData and
614 // wxAlphaPixelData iterators and so are not included in our macro...
616 %extend wxNativePixelData_Iterator {
617 void Set(byte red, byte green, byte blue) {
619 self->Green() = green;
624 PyObject* rv = PyTuple_New(3);
625 PyTuple_SetItem(rv, 0, PyInt_FromLong(self->Red()));
626 PyTuple_SetItem(rv, 1, PyInt_FromLong(self->Green()));
627 PyTuple_SetItem(rv, 2, PyInt_FromLong(self->Blue()));
632 %extend wxAlphaPixelData_Iterator {
633 // byte _get_Alpha() { return self->Alpha(); }
634 // void _set_Alpha(byte val) { self->Alpha() = val; }
637 // Alpha = property(_get_Alpha, _set_Alpha)
640 void Set(byte red, byte green, byte blue, byte alpha) {
641 self->Red() = wxPy_premultiply(red, alpha);
642 self->Green() = wxPy_premultiply(green, alpha);
643 self->Blue() = wxPy_premultiply(blue, alpha);
644 self->Alpha() = alpha;
648 PyObject* rv = PyTuple_New(4);
649 int red = self->Red();
650 int green = self->Green();
651 int blue = self->Blue();
652 int alpha = self->Alpha();
654 PyTuple_SetItem(rv, 0, PyInt_FromLong( wxPy_unpremultiply(red, alpha) ));
655 PyTuple_SetItem(rv, 1, PyInt_FromLong( wxPy_unpremultiply(green, alpha) ));
656 PyTuple_SetItem(rv, 2, PyInt_FromLong( wxPy_unpremultiply(blue, alpha) ));
657 PyTuple_SetItem(rv, 3, PyInt_FromLong( alpha ));
662 //---------------------------------------------------------------------------
665 "This class encapsulates a monochrome mask bitmap, where the masked
666 area is black and the unmasked area is white. When associated with a
667 bitmap and drawn in a device context, the unmasked area of the bitmap
668 will be drawn, and the masked area will not be drawn.
670 A mask may be associated with a `wx.Bitmap`. It is used in
671 `wx.DC.DrawBitmap` or `wx.DC.Blit` when the source device context is a
672 `wx.MemoryDC` with a `wx.Bitmap` selected into it that contains a
677 class wxMask : public wxObject {
681 "Constructs a mask from a `wx.Bitmap` and a `wx.Colour` in that bitmap
682 that indicates the transparent portions of the mask. In other words,
683 the pixels in ``bitmap`` that match ``colour`` will be the transparent
684 portions of the mask. If no ``colour`` or an invalid ``colour`` is
685 passed then BLACK is used.
687 :see: `wx.Bitmap`, `wx.Colour`", "");
690 wxMask(const wxBitmap& bitmap, const wxColour& colour = wxNullColour) {
692 return new wxMask(bitmap, *wxBLACK);
694 return new wxMask(bitmap, colour);
701 %pythoncode { MaskColour = wx._deprecated(Mask, "wx.MaskColour is deprecated, use `wx.Mask` instead.") }
703 //---------------------------------------------------------------------------
704 //---------------------------------------------------------------------------