1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "bitmap.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
29 #include "wx/palette.h"
30 #include "wx/bitmap.h"
34 #include "wx/msw/private.h"
39 #include "..\..\contrib\wxxpm\libxpm.34b\lib\xpm34.h"
42 #include "wx/msw/dib.h"
44 #if !USE_SHARED_LIBRARIES
45 IMPLEMENT_DYNAMIC_CLASS(wxBitmap
, wxGDIObject
)
46 IMPLEMENT_DYNAMIC_CLASS(wxMask
, wxObject
)
49 wxBitmapRefData::wxBitmapRefData(void)
57 m_selectedInto
= NULL
;
62 wxBitmapRefData::~wxBitmapRefData(void)
67 sprintf(buf
, "Bitmap was deleted without selecting out of wxMemoryDC %X.", (unsigned int) m_selectedInto
);
72 DeleteObject((HBITMAP
) m_hBitmap
);
81 wxList
wxBitmap::sm_handlers
;
83 wxBitmap::wxBitmap(void)
85 m_refData
= NULL
; // new wxBitmapRefData;
87 if ( wxTheBitmapList
)
88 wxTheBitmapList
->AddBitmap(this);
91 wxBitmap::~wxBitmap(void)
94 wxTheBitmapList
->DeleteObject(this);
97 bool wxBitmap::FreeResource(bool force
)
102 if (M_BITMAPDATA
->m_selectedInto
)
105 sprintf(buf
, "Bitmap %X was deleted without selecting out of wxMemoryDC %X.", (unsigned int) this, (unsigned int) M_BITMAPDATA
->m_selectedInto
);
108 if (M_BITMAPDATA
->m_hBitmap
)
110 DeleteObject((HBITMAP
) M_BITMAPDATA
->m_hBitmap
);
112 M_BITMAPDATA
->m_hBitmap
= 0 ;
115 if (M_BITMAPDATA->m_bitmapPalette)
116 delete M_BITMAPDATA->m_bitmapPalette;
118 M_BITMAPDATA->m_bitmapPalette = NULL ;
125 wxBitmap::wxBitmap(const char bits
[], const int the_width
, const int the_height
, const int no_bits
)
127 m_refData
= new wxBitmapRefData
;
129 M_BITMAPDATA
->m_width
= the_width
;
130 M_BITMAPDATA
->m_height
= the_height
;
131 M_BITMAPDATA
->m_depth
= no_bits
;
132 M_BITMAPDATA
->m_numColors
= 0;
134 M_BITMAPDATA
->m_hBitmap
= (WXHBITMAP
) CreateBitmap(the_width
, the_height
, no_bits
, 1, bits
);
136 if (M_BITMAPDATA
->m_hBitmap
)
137 M_BITMAPDATA
->m_ok
= TRUE
;
139 M_BITMAPDATA
->m_ok
= FALSE
;
141 M_BITMAPDATA
->m_selectedInto
= NULL
;
143 if ( wxTheBitmapList
)
144 wxTheBitmapList
->AddBitmap(this);
147 wxBitmap::wxBitmap(const int w
, const int h
, const int d
)
149 (void)Create(w
, h
, d
);
151 if ( wxTheBitmapList
)
152 wxTheBitmapList
->AddBitmap(this);
155 wxBitmap::wxBitmap(void *data
, const long type
, const int width
, const int height
, const int depth
)
157 (void) Create(data
, type
, width
, height
, depth
);
159 if ( wxTheBitmapList
)
160 wxTheBitmapList
->AddBitmap(this);
163 wxBitmap::wxBitmap(const wxString
& filename
, const long type
)
165 LoadFile(filename
, (int)type
);
167 if ( wxTheBitmapList
)
168 wxTheBitmapList
->AddBitmap(this);
173 wxBitmap::wxBitmap(const char **data
, wxItem
*WXUNUSED(anItem
))
175 (void) Create((void *)data
, wxBITMAP_TYPE_XPM_DATA
, 0, 0, 0);
179 bool wxBitmap::Create(const int w
, const int h
, const int d
)
183 m_refData
= new wxBitmapRefData
;
185 M_BITMAPDATA
->m_width
= w
;
186 M_BITMAPDATA
->m_height
= h
;
187 M_BITMAPDATA
->m_depth
= d
;
191 M_BITMAPDATA
->m_hBitmap
= (WXHBITMAP
) CreateBitmap(w
, h
, d
, 1, NULL
);
195 HDC dc
= GetDC(NULL
);
196 M_BITMAPDATA
->m_hBitmap
= (WXHBITMAP
) CreateCompatibleBitmap(dc
, w
, h
);
198 M_BITMAPDATA
->m_depth
= wxDisplayDepth();
200 if (M_BITMAPDATA
->m_hBitmap
)
201 M_BITMAPDATA
->m_ok
= TRUE
;
203 M_BITMAPDATA
->m_ok
= FALSE
;
204 return M_BITMAPDATA
->m_ok
;
207 bool wxBitmap::LoadFile(const wxString
& filename
, const long type
)
211 m_refData
= new wxBitmapRefData
;
213 wxBitmapHandler
*handler
= FindHandler(type
);
216 return handler
->LoadFile(this, filename
, type
, -1, -1);
221 bool wxBitmap::Create(void *data
, const long type
, const int width
, const int height
, const int depth
)
225 m_refData
= new wxBitmapRefData
;
227 wxBitmapHandler
*handler
= FindHandler(type
);
230 return handler
->Create(this, data
, type
, width
, height
, depth
);
235 bool wxBitmap::SaveFile(const wxString
& filename
, const int type
, const wxPalette
*palette
)
237 wxBitmapHandler
*handler
= FindHandler(type
);
240 return handler
->SaveFile(this, filename
, type
, palette
);
245 void wxBitmap::SetWidth(int w
)
248 m_refData
= new wxBitmapRefData
;
250 M_BITMAPDATA
->m_width
= w
;
253 void wxBitmap::SetHeight(int h
)
256 m_refData
= new wxBitmapRefData
;
258 M_BITMAPDATA
->m_height
= h
;
261 void wxBitmap::SetDepth(int d
)
264 m_refData
= new wxBitmapRefData
;
266 M_BITMAPDATA
->m_depth
= d
;
269 void wxBitmap::SetQuality(int q
)
272 m_refData
= new wxBitmapRefData
;
274 M_BITMAPDATA
->m_quality
= q
;
277 void wxBitmap::SetOk(bool isOk
)
280 m_refData
= new wxBitmapRefData
;
282 M_BITMAPDATA
->m_ok
= isOk
;
285 void wxBitmap::SetPalette(const wxPalette
& palette
)
288 m_refData
= new wxBitmapRefData
;
290 M_BITMAPDATA
->m_bitmapPalette
= palette
;
293 void wxBitmap::SetMask(wxMask
*mask
)
296 m_refData
= new wxBitmapRefData
;
298 M_BITMAPDATA
->m_bitmapMask
= mask
;
301 void wxBitmap::SetHBITMAP(WXHBITMAP bmp
)
304 m_refData
= new wxBitmapRefData
;
306 M_BITMAPDATA
->m_hBitmap
= bmp
;
309 void wxBitmap::AddHandler(wxBitmapHandler
*handler
)
311 sm_handlers
.Append(handler
);
314 void wxBitmap::InsertHandler(wxBitmapHandler
*handler
)
316 sm_handlers
.Insert(handler
);
319 bool wxBitmap::RemoveHandler(const wxString
& name
)
321 wxBitmapHandler
*handler
= FindHandler(name
);
324 sm_handlers
.DeleteObject(handler
);
331 wxBitmapHandler
*wxBitmap::FindHandler(const wxString
& name
)
333 wxNode
*node
= sm_handlers
.First();
336 wxBitmapHandler
*handler
= (wxBitmapHandler
*)node
->Data();
337 if ( handler
->GetName() == name
)
344 wxBitmapHandler
*wxBitmap::FindHandler(const wxString
& extension
, long bitmapType
)
346 wxNode
*node
= sm_handlers
.First();
349 wxBitmapHandler
*handler
= (wxBitmapHandler
*)node
->Data();
350 if ( handler
->GetExtension() == extension
&&
351 (bitmapType
== -1 || handler
->GetType() == bitmapType
) )
358 wxBitmapHandler
*wxBitmap::FindHandler(long bitmapType
)
360 wxNode
*node
= sm_handlers
.First();
363 wxBitmapHandler
*handler
= (wxBitmapHandler
*)node
->Data();
364 if (handler
->GetType() == bitmapType
)
380 // Construct a mask from a bitmap and a colour indicating
381 // the transparent area
382 wxMask::wxMask(const wxBitmap
& bitmap
, const wxColour
& colour
)
385 Create(bitmap
, colour
);
388 // Construct a mask from a bitmap and a palette index indicating
389 // the transparent area
390 wxMask::wxMask(const wxBitmap
& bitmap
, const int paletteIndex
)
393 Create(bitmap
, paletteIndex
);
396 // Construct a mask from a mono bitmap (copies the bitmap).
397 wxMask::wxMask(const wxBitmap
& bitmap
)
403 wxMask::~wxMask(void)
406 ::DeleteObject((HBITMAP
) m_maskBitmap
);
409 // Create a mask from a mono bitmap (copies the bitmap).
410 bool wxMask::Create(const wxBitmap
& bitmap
)
414 ::DeleteObject((HBITMAP
) m_maskBitmap
);
417 if (!bitmap
.Ok() || bitmap
.GetDepth() != 1)
421 m_maskBitmap
= (WXHBITMAP
) CreateBitmap(
426 HDC srcDC
= CreateCompatibleDC(0);
427 SelectObject(srcDC
, (HBITMAP
) bitmap
.GetHBITMAP());
428 HDC destDC
= CreateCompatibleDC(0);
429 SelectObject(destDC
, (HBITMAP
) m_maskBitmap
);
430 BitBlt(destDC
, 0, 0, bitmap
.GetWidth(), bitmap
.GetHeight(), srcDC
, 0, 0, SRCCOPY
);
431 SelectObject(srcDC
, 0);
433 SelectObject(destDC
, 0);
438 // Create a mask from a bitmap and a palette index indicating
439 // the transparent area
440 bool wxMask::Create(const wxBitmap
& bitmap
, const int paletteIndex
)
444 ::DeleteObject((HBITMAP
) m_maskBitmap
);
447 if (bitmap
.Ok() && bitmap
.GetPalette()->Ok())
449 unsigned char red
, green
, blue
;
450 if (bitmap
.GetPalette()->GetRGB(paletteIndex
, &red
, &green
, &blue
))
452 wxColour
transparentColour(red
, green
, blue
);
453 return Create(bitmap
, transparentColour
);
459 // Create a mask from a bitmap and a colour indicating
460 // the transparent area
461 bool wxMask::Create(const wxBitmap
& bitmap
, const wxColour
& colour
)
465 ::DeleteObject((HBITMAP
) m_maskBitmap
);
473 // scan the bitmap for the transparent colour and set
474 // the corresponding pixels in the mask to BLACK and
476 COLORREF maskColour
= RGB(colour
.Red(), colour
.Green(), colour
.Blue());
477 m_maskBitmap
= (WXHBITMAP
) ::CreateBitmap(
482 HDC srcDC
= ::CreateCompatibleDC(0);
483 ::SelectObject(srcDC
, (HBITMAP
) bitmap
.GetHBITMAP());
484 HDC destDC
= ::CreateCompatibleDC(0);
485 ::SelectObject(destDC
, (HBITMAP
) m_maskBitmap
);
487 // this is not very efficient, but I can't think
488 // of a better way of doing it
489 for (int w
= 0; w
< bitmap
.GetWidth(); w
++)
491 for (int h
= 0; h
< bitmap
.GetHeight(); h
++)
493 COLORREF col
= GetPixel(srcDC
, w
, h
);
494 if (col
== maskColour
)
496 ::SetPixel(destDC
, w
, h
, RGB(0, 0, 0));
500 ::SetPixel(destDC
, w
, h
, RGB(255, 255, 255));
504 ::SelectObject(srcDC
, 0);
506 ::SelectObject(destDC
, 0);
515 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler
, wxObject
)
517 bool wxBitmapHandler::Create(wxBitmap
*bitmap
, void *data
, const long type
, const int width
, const int height
, const int depth
)
522 bool wxBitmapHandler::LoadFile(wxBitmap
*bitmap
, const wxString
& name
, const long type
,
523 int desiredWidth
, int desiredHeight
)
528 bool wxBitmapHandler::SaveFile(wxBitmap
*bitmap
, const wxString
& name
, const int type
, const wxPalette
*palette
)
537 class WXDLLEXPORT wxBMPResourceHandler
: public wxBitmapHandler
539 DECLARE_DYNAMIC_CLASS(wxBMPResourceHandler
)
541 inline wxBMPResourceHandler(void)
543 m_name
= "Windows bitmap resource";
545 m_type
= wxBITMAP_TYPE_BMP_RESOURCE
;
548 virtual bool LoadFile(wxBitmap
*bitmap
, const wxString
& name
, const long flags
,
549 int desiredWidth
, int desiredHeight
);
551 IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler
, wxBitmapHandler
)
553 bool wxBMPResourceHandler::LoadFile(wxBitmap
*bitmap
, const wxString
& name
, const long flags
,
554 int desiredWidth
, int desiredHeight
)
556 // TODO: load colourmap.
557 M_BITMAPHANDLERDATA
->m_hBitmap
= (WXHBITMAP
) ::LoadBitmap(wxGetInstance(), name
);
558 if (M_BITMAPHANDLERDATA
->m_hBitmap
)
560 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
562 GetObject((HBITMAP
) M_BITMAPHANDLERDATA
->m_hBitmap
, sizeof(BITMAP
), (LPSTR
) &bm
);
563 M_BITMAPHANDLERDATA
->m_width
= bm
.bmWidth
;
564 M_BITMAPHANDLERDATA
->m_height
= bm
.bmHeight
;
565 M_BITMAPHANDLERDATA
->m_depth
= bm
.bmPlanes
;
571 class WXDLLEXPORT wxBMPFileHandler
: public wxBitmapHandler
573 DECLARE_DYNAMIC_CLASS(wxBMPFileHandler
)
575 inline wxBMPFileHandler(void)
577 m_name
= "Windows bitmap file";
579 m_type
= wxBITMAP_TYPE_BMP
;
582 virtual bool LoadFile(wxBitmap
*bitmap
, const wxString
& name
, const long flags
,
583 int desiredWidth
, int desiredHeight
);
584 virtual bool SaveFile(wxBitmap
*bitmap
, const wxString
& name
, const int type
, const wxPalette
*palette
= NULL
);
586 IMPLEMENT_DYNAMIC_CLASS(wxBMPFileHandler
, wxBitmapHandler
)
588 bool wxBMPFileHandler::LoadFile(wxBitmap
*bitmap
, const wxString
& name
, const long flags
,
589 int desiredWidth
, int desiredHeight
)
591 #if USE_IMAGE_LOADING_IN_MSW
592 wxPalette
*palette
= NULL
;
593 bool success
= FALSE
;
595 if (type & wxBITMAP_DISCARD_COLOURMAP)
596 success = wxLoadIntoBitmap(WXSTRINGCAST name, bitmap);
599 success
= (wxLoadIntoBitmap(WXSTRINGCAST name
, bitmap
, &palette
) != 0);
600 if (!success
&& palette
)
606 M_BITMAPHANDLERDATA
->m_bitmapPalette
= *palette
;
613 bool wxBMPFileHandler::SaveFile(wxBitmap
*bitmap
, const wxString
& name
, const int type
, const wxPalette
*pal
)
615 #if USE_IMAGE_LOADING_IN_MSW
616 wxPalette
*actualPalette
= (wxPalette
*)pal
;
617 if (!actualPalette
&& (!M_BITMAPHANDLERDATA
->m_bitmapPalette
.IsNull()))
618 actualPalette
= & (M_BITMAPHANDLERDATA
->m_bitmapPalette
);
619 return (wxSaveBitmap(WXSTRINGCAST name
, bitmap
, actualPalette
) != 0);
625 class WXDLLEXPORT wxXPMFileHandler
: public wxBitmapHandler
627 DECLARE_DYNAMIC_CLASS(wxXPMFileHandler
)
629 inline wxXPMFileHandler(void)
631 m_name
= "XPM bitmap file";
633 m_type
= wxBITMAP_TYPE_XPM
;
636 virtual bool LoadFile(wxBitmap
*bitmap
, const wxString
& name
, const long flags
,
637 int desiredWidth
= -1, int desiredHeight
= -1);
638 virtual bool SaveFile(wxBitmap
*bitmap
, const wxString
& name
, const int type
, const wxPalette
*palette
= NULL
);
640 IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler
, wxBitmapHandler
)
642 bool wxXPMFileHandler::LoadFile(wxBitmap
*bitmap
, const wxString
& name
, const long flags
,
643 int desiredWidth
, int desiredHeight
)
647 XpmAttributes xpmAttr
;
650 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
651 dc
= CreateCompatibleDC(NULL
);
654 xpmAttr
.valuemask
= XpmReturnPixels
;
655 int errorStatus
= XpmReadFileToImage(&dc
, WXSTRINGCAST name
, &ximage
, (XImage
**) NULL
, &xpmAttr
);
657 if (errorStatus
== XpmSuccess
)
659 M_BITMAPHANDLERDATA
->m_hBitmap
= (WXHBITMAP
) ximage
->bitmap
;
662 GetObject((HBITMAP
) m_hBitmap
, sizeof(bm
), (LPSTR
) & bm
);
664 M_BITMAPHANDLERDATA
->m_width
= (bm
.bmWidth
);
665 M_BITMAPHANDLERDATA
->m_height
= (bm
.bmHeight
);
666 M_BITMAPHANDLERDATA
->m_depth
= (bm
.bmPlanes
* bm
.bmBitsPixel
);
667 M_BITMAPHANDLERDATA
->m_numColors
= xpmAttr
.npixels
;
668 XpmFreeAttributes(&xpmAttr
);
671 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
676 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
685 bool wxXPMFileHandler::SaveFile(wxBitmap
*bitmap
, const wxString
& name
, const int type
, const wxPalette
*palette
)
690 Visual
*visual
= NULL
;
693 dc
= CreateCompatibleDC(NULL
);
696 if (SelectObject(dc
, (HBITMAP
) M_BITMAPHANDLERDATA
->m_hBitmap
))
697 { /* for following SetPixel */
698 /* fill the XImage struct 'by hand' */
699 ximage
.width
= M_BITMAPHANDLERDATA
->m_width
; ximage
.height
= M_BITMAPHANDLERDATA
->m_height
;
700 ximage
.depth
= M_BITMAPHANDLERDATA
->m_depth
; ximage
.bitmap
= M_BITMAPHANDLERDATA
->m_hBitmap
;
701 int errorStatus
= XpmWriteFileFromImage(&dc
, WXSTRINGCAST name
,
702 &ximage
, (XImage
*) NULL
, (XpmAttributes
*) NULL
);
707 if (errorStatus
== XpmSuccess
)
708 return TRUE
; /* no error */
718 class WXDLLEXPORT wxXPMDataHandler
: public wxBitmapHandler
720 DECLARE_DYNAMIC_CLASS(wxXPMDataHandler
)
722 inline wxXPMDataHandler(void)
724 m_name
= "XPM bitmap data";
726 m_type
= wxBITMAP_TYPE_XPM_DATA
;
729 virtual bool Create(wxBitmap
*bitmap
, void *data
, const long flags
, const int width
, const int height
, const int depth
= 1);
731 IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler
, wxBitmapHandler
)
733 bool wxXPMDataHandler::Create(wxBitmap
*bitmap
, void *data
, const long flags
, const int width
, const int height
, const int depth
)
738 XpmAttributes xpmAttr
;
741 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
742 M_BITMAPHANDLERDATA
->m_numColors
= 0;
744 dc
= CreateCompatibleDC(NULL
); /* memory DC */
748 xpmAttr
.valuemask
= XpmReturnInfos
; /* get infos back */
749 ErrorStatus
= XpmCreateImageFromData(&dc
, (char **)data
,
750 &ximage
, (XImage
**) NULL
, &xpmAttr
);
752 if (ErrorStatus
== XpmSuccess
)
754 /* ximage is malloced and contains bitmap and attributes */
755 M_BITMAPHANDLERDATA
->m_hBitmap
= (WXHBITMAP
) ximage
->bitmap
;
758 GetObject((HBITMAP
) M_BITMAPHANDLERDATA
->m_hBitmap
, sizeof(bm
), (LPSTR
) & bm
);
760 M_BITMAPHANDLERDATA
->m_width
= (bm
.bmWidth
);
761 M_BITMAPHANDLERDATA
->m_height
= (bm
.bmHeight
);
762 M_BITMAPHANDLERDATA
->m_depth
= (bm
.bmPlanes
* bm
.bmBitsPixel
);
763 M_BITMAPHANDLERDATA
->m_numColors
= xpmAttr
.npixels
;
764 XpmFreeAttributes(&xpmAttr
);
766 XImageFree(ximage
); // releases the malloc, but does not detroy
768 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
773 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
774 // XpmDebugError(ErrorStatus, NULL);
784 void wxBitmap::CleanUpHandlers(void)
786 wxNode
*node
= sm_handlers
.First();
789 wxBitmapHandler
*handler
= (wxBitmapHandler
*)node
->Data();
790 wxNode
*next
= node
->Next();
797 void wxBitmap::InitStandardHandlers(void)
799 AddHandler(new wxBMPResourceHandler
);
800 AddHandler(new wxBMPFileHandler
);
801 AddHandler(new wxXPMFileHandler
);
802 AddHandler(new wxXPMDataHandler
);
803 AddHandler(new wxICOResourceHandler
);
804 AddHandler(new wxICOFileHandler
);