]>
git.saurik.com Git - wxWidgets.git/blob - src/msw/bitmap.cpp
1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 #pragma implementation "bitmap.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
37 #include "wx/palette.h"
38 #include "wx/dcmemory.h"
39 #include "wx/bitmap.h"
43 #include "wx/msw/private.h"
46 #include "wx/msw/dib.h"
49 // ----------------------------------------------------------------------------
51 // ----------------------------------------------------------------------------
53 #if !USE_SHARED_LIBRARIES
54 IMPLEMENT_DYNAMIC_CLASS(wxBitmap
, wxGDIObject
)
55 IMPLEMENT_DYNAMIC_CLASS(wxMask
, wxObject
)
57 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler
, wxObject
)
60 // ============================================================================
62 // ============================================================================
64 // ----------------------------------------------------------------------------
66 // ----------------------------------------------------------------------------
68 wxBitmapRefData::wxBitmapRefData()
71 m_selectedInto
= NULL
;
76 void wxBitmapRefData::Free()
78 wxASSERT_MSG( !m_selectedInto
,
79 wxT("deleting bitmap still selected into wxMemoryDC") );
83 if ( !::DeleteObject((HBITMAP
)m_hBitmap
) )
85 wxLogLastError("DeleteObject(hbitmap)");
93 // ----------------------------------------------------------------------------
95 // ----------------------------------------------------------------------------
97 // this function should be called from all wxBitmap ctors
100 // m_refData = NULL; done in the base class ctor
102 if ( wxTheBitmapList
)
103 wxTheBitmapList
->AddBitmap(this);
108 bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage
& icon
)
110 // it may be either HICON or HCURSOR
111 HICON hicon
= (HICON
)icon
.GetHandle();
114 if ( !::GetIconInfo(hicon
, &iconInfo
) )
116 wxLogLastError("GetIconInfo");
121 wxBitmapRefData
*refData
= new wxBitmapRefData
;
124 refData
->m_width
= icon
.GetWidth();
125 refData
->m_height
= icon
.GetHeight();
126 refData
->m_depth
= wxDisplayDepth();
128 refData
->m_hBitmap
= (WXHBITMAP
)iconInfo
.hbmColor
;
129 refData
->m_bitmapMask
= new wxMask((WXHBITMAP
)iconInfo
.hbmMask
);
131 #if WXWIN_COMPATIBILITY_2
132 refData
->m_ok
= TRUE
;
133 #endif // WXWIN_COMPATIBILITY_2
140 bool wxBitmap::CopyFromCursor(const wxCursor
& cursor
)
148 wxFAIL_MSG( _T("don't know how to convert cursor to bitmap") );
153 return CopyFromIconOrCursor(cursor
);
156 bool wxBitmap::CopyFromIcon(const wxIcon
& icon
)
163 // GetIconInfo() doesn't exist under Win16 and I don't know any other way
164 // to create a bitmap from icon there - but using this way we won't have
167 int width
= icon
.GetWidth(),
168 height
= icon
.GetHeight();
170 // copy the icon to the bitmap
172 HDC hdc
= ::CreateCompatibleDC(hdcScreen
);
173 HBITMAP hbitmap
= ::CreateCompatibleBitmap(hdcScreen
, width
, height
);
174 HBITMAP hbmpOld
= (HBITMAP
)::SelectObject(hdc
, hbitmap
);
176 ::DrawIcon(hdc
, 0, 0, GetHiconOf(icon
));
178 ::SelectObject(hdc
, hbmpOld
);
181 wxBitmapRefData
*refData
= new wxBitmapRefData
;
184 refData
->m_width
= width
;
185 refData
->m_height
= height
;
186 refData
->m_depth
= wxDisplayDepth();
188 refData
->m_hBitmap
= (WXHBITMAP
)hbitmap
;
190 #if WXWIN_COMPATIBILITY_2
191 refData
->m_ok
= TRUE
;
192 #endif // WXWIN_COMPATIBILITY_2
196 return CopyFromIconOrCursor(icon
);
197 #endif // Win16/Win32
200 wxBitmap::~wxBitmap()
203 wxTheBitmapList
->DeleteObject(this);
206 wxBitmap::wxBitmap(const char bits
[], int the_width
, int the_height
, int no_bits
)
210 wxBitmapRefData
*refData
= new wxBitmapRefData
;
213 refData
->m_width
= the_width
;
214 refData
->m_height
= the_height
;
215 refData
->m_depth
= no_bits
;
216 refData
->m_numColors
= 0;
217 refData
->m_selectedInto
= NULL
;
219 HBITMAP hbmp
= ::CreateBitmap(the_width
, the_height
, 1, no_bits
, bits
);
222 wxLogLastError("CreateBitmap");
225 SetHBITMAP((WXHBITMAP
)hbmp
);
228 // Create from XPM data
229 wxBitmap::wxBitmap(char **data
, wxControl
*WXUNUSED(anItem
))
233 (void)Create((void *)data
, wxBITMAP_TYPE_XPM_DATA
, 0, 0, 0);
236 wxBitmap::wxBitmap(int w
, int h
, int d
)
240 (void)Create(w
, h
, d
);
243 wxBitmap::wxBitmap(void *data
, long type
, int width
, int height
, int depth
)
247 (void)Create(data
, type
, width
, height
, depth
);
250 wxBitmap::wxBitmap(const wxString
& filename
, long type
)
254 LoadFile(filename
, (int)type
);
257 bool wxBitmap::Create(int w
, int h
, int d
)
261 m_refData
= new wxBitmapRefData
;
263 GetBitmapData()->m_width
= w
;
264 GetBitmapData()->m_height
= h
;
265 GetBitmapData()->m_depth
= d
;
271 hbmp
= ::CreateBitmap(w
, h
, 1, d
, NULL
);
274 wxLogLastError("CreateBitmap");
280 hbmp
= ::CreateCompatibleBitmap(dc
, w
, h
);
283 wxLogLastError("CreateCompatibleBitmap");
286 GetBitmapData()->m_depth
= wxDisplayDepth();
289 SetHBITMAP((WXHBITMAP
)hbmp
);
291 #if WXWIN_COMPATIBILITY_2
292 GetBitmapData()->m_ok
= hbmp
!= 0;
293 #endif // WXWIN_COMPATIBILITY_2
298 bool wxBitmap::LoadFile(const wxString
& filename
, long type
)
302 wxBitmapHandler
*handler
= wxDynamicCast(FindHandler(type
), wxBitmapHandler
);
306 m_refData
= new wxBitmapRefData
;
308 return handler
->LoadFile(this, filename
, type
, -1, -1);
313 if ( !image
.LoadFile( filename
, type
) || !image
.Ok() )
316 *this = image
.ConvertToBitmap();
322 bool wxBitmap::Create(void *data
, long type
, int width
, int height
, int depth
)
326 wxBitmapHandler
*handler
= wxDynamicCast(FindHandler(type
), wxBitmapHandler
);
330 wxLogDebug(wxT("Failed to create bitmap: no bitmap handler for "
331 "type %d defined."), type
);
336 m_refData
= new wxBitmapRefData
;
338 return handler
->Create(this, data
, type
, width
, height
, depth
);
341 bool wxBitmap::SaveFile(const wxString
& filename
, int type
, const wxPalette
*palette
)
343 wxBitmapHandler
*handler
= wxDynamicCast(FindHandler(type
), wxBitmapHandler
);
347 return handler
->SaveFile(this, filename
, type
, palette
);
351 // FIXME what about palette? shouldn't we use it?
352 wxImage
image( *this );
356 return image
.SaveFile( filename
, type
);
360 // ----------------------------------------------------------------------------
361 // wxBitmap accessors
362 // ----------------------------------------------------------------------------
364 void wxBitmap::SetQuality(int q
)
368 GetBitmapData()->m_quality
= q
;
371 #if WXWIN_COMPATIBILITY_2
372 void wxBitmap::SetOk(bool isOk
)
376 GetBitmapData()->m_ok
= isOk
;
378 #endif // WXWIN_COMPATIBILITY_2
380 void wxBitmap::SetPalette(const wxPalette
& palette
)
384 GetBitmapData()->m_bitmapPalette
= palette
;
387 void wxBitmap::SetMask(wxMask
*mask
)
391 GetBitmapData()->m_bitmapMask
= mask
;
394 // Creates a bitmap that matches the device context, from
395 // an arbitray bitmap. At present, the original bitmap must have an
396 // associated palette. TODO: use a default palette if no palette exists.
397 // Contributed by Frederic Villeneuve <frederic.villeneuve@natinst.com>
398 wxBitmap
wxBitmap::GetBitmapForDC(wxDC
& dc
) const
401 wxBitmap
tmpBitmap(this->GetWidth(), this->GetHeight(), dc
.GetDepth());
402 HPALETTE hPal
= (HPALETTE
) NULL
;
404 void *lpBits
= (void*) NULL
;
406 if( GetPalette() && GetPalette()->Ok() )
408 tmpBitmap
.SetPalette(*GetPalette());
409 memDC
.SelectObject(tmpBitmap
);
410 memDC
.SetPalette(*GetPalette());
411 hPal
= (HPALETTE
)GetPalette()->GetHPALETTE();
415 hPal
= (HPALETTE
) ::GetStockObject(DEFAULT_PALETTE
);
417 palette
.SetHPALETTE( (WXHPALETTE
)hPal
);
418 tmpBitmap
.SetPalette( palette
);
419 memDC
.SelectObject(tmpBitmap
);
420 memDC
.SetPalette( palette
);
423 // set the height negative because in a DIB the order of the lines is
425 if ( !wxCreateDIB(GetWidth(), -GetHeight(), GetDepth(), hPal
, &lpDib
) )
430 lpBits
= malloc(lpDib
->bmiHeader
.biSizeImage
);
432 ::GetBitmapBits(GetHbitmap(), lpDib
->bmiHeader
.biSizeImage
, lpBits
);
434 ::SetDIBitsToDevice(GetHdcOf(memDC
), 0, 0,
435 GetWidth(), GetHeight(),
436 0, 0, 0, GetHeight(),
437 lpBits
, lpDib
, DIB_RGB_COLORS
);
446 // ----------------------------------------------------------------------------
448 // ----------------------------------------------------------------------------
455 // Construct a mask from a bitmap and a colour indicating
456 // the transparent area
457 wxMask::wxMask(const wxBitmap
& bitmap
, const wxColour
& colour
)
460 Create(bitmap
, colour
);
463 // Construct a mask from a bitmap and a palette index indicating
464 // the transparent area
465 wxMask::wxMask(const wxBitmap
& bitmap
, int paletteIndex
)
468 Create(bitmap
, paletteIndex
);
471 // Construct a mask from a mono bitmap (copies the bitmap).
472 wxMask::wxMask(const wxBitmap
& bitmap
)
481 ::DeleteObject((HBITMAP
) m_maskBitmap
);
484 // Create a mask from a mono bitmap (copies the bitmap).
485 bool wxMask::Create(const wxBitmap
& bitmap
)
489 ::DeleteObject((HBITMAP
) m_maskBitmap
);
492 if (!bitmap
.Ok() || bitmap
.GetDepth() != 1)
496 m_maskBitmap
= (WXHBITMAP
) CreateBitmap(
501 HDC srcDC
= CreateCompatibleDC(0);
502 SelectObject(srcDC
, (HBITMAP
) bitmap
.GetHBITMAP());
503 HDC destDC
= CreateCompatibleDC(0);
504 SelectObject(destDC
, (HBITMAP
) m_maskBitmap
);
505 BitBlt(destDC
, 0, 0, bitmap
.GetWidth(), bitmap
.GetHeight(), srcDC
, 0, 0, SRCCOPY
);
506 SelectObject(srcDC
, 0);
508 SelectObject(destDC
, 0);
513 // Create a mask from a bitmap and a palette index indicating
514 // the transparent area
515 bool wxMask::Create(const wxBitmap
& bitmap
, int paletteIndex
)
519 ::DeleteObject((HBITMAP
) m_maskBitmap
);
522 if (bitmap
.Ok() && bitmap
.GetPalette()->Ok())
524 unsigned char red
, green
, blue
;
525 if (bitmap
.GetPalette()->GetRGB(paletteIndex
, &red
, &green
, &blue
))
527 wxColour
transparentColour(red
, green
, blue
);
528 return Create(bitmap
, transparentColour
);
534 // Create a mask from a bitmap and a colour indicating
535 // the transparent area
536 bool wxMask::Create(const wxBitmap
& bitmap
, const wxColour
& colour
)
540 ::DeleteObject((HBITMAP
) m_maskBitmap
);
548 // scan the bitmap for the transparent colour and set
549 // the corresponding pixels in the mask to BLACK and
551 COLORREF maskColour
= RGB(colour
.Red(), colour
.Green(), colour
.Blue());
552 m_maskBitmap
= (WXHBITMAP
) ::CreateBitmap(
557 HDC srcDC
= ::CreateCompatibleDC(0);
558 ::SelectObject(srcDC
, (HBITMAP
) bitmap
.GetHBITMAP());
559 HDC destDC
= ::CreateCompatibleDC(0);
560 ::SelectObject(destDC
, (HBITMAP
) m_maskBitmap
);
562 // this is not very efficient, but I can't think
563 // of a better way of doing it
564 for (int w
= 0; w
< bitmap
.GetWidth(); w
++)
566 for (int h
= 0; h
< bitmap
.GetHeight(); h
++)
568 COLORREF col
= GetPixel(srcDC
, w
, h
);
569 if (col
== maskColour
)
571 ::SetPixel(destDC
, w
, h
, RGB(0, 0, 0));
575 ::SetPixel(destDC
, w
, h
, RGB(255, 255, 255));
579 ::SelectObject(srcDC
, 0);
581 ::SelectObject(destDC
, 0);
586 // ----------------------------------------------------------------------------
588 // ----------------------------------------------------------------------------
590 bool wxBitmapHandler::Create(wxGDIImage
*image
,
593 int width
, int height
, int depth
)
595 wxBitmap
*bitmap
= wxDynamicCast(image
, wxBitmap
);
597 return bitmap
? Create(bitmap
, data
, width
, height
, depth
) : FALSE
;
600 bool wxBitmapHandler::Load(wxGDIImage
*image
,
601 const wxString
& name
,
603 int width
, int height
)
605 wxBitmap
*bitmap
= wxDynamicCast(image
, wxBitmap
);
607 return bitmap
? LoadFile(bitmap
, name
, flags
, width
, height
) : FALSE
;
610 bool wxBitmapHandler::Save(wxGDIImage
*image
,
611 const wxString
& name
,
614 wxBitmap
*bitmap
= wxDynamicCast(image
, wxBitmap
);
616 return bitmap
? SaveFile(bitmap
, name
, type
) : FALSE
;
619 bool wxBitmapHandler::Create(wxBitmap
*WXUNUSED(bitmap
),
620 void *WXUNUSED(data
),
623 int WXUNUSED(height
),
629 bool wxBitmapHandler::LoadFile(wxBitmap
*WXUNUSED(bitmap
),
630 const wxString
& WXUNUSED(name
),
632 int WXUNUSED(desiredWidth
),
633 int WXUNUSED(desiredHeight
))
638 bool wxBitmapHandler::SaveFile(wxBitmap
*WXUNUSED(bitmap
),
639 const wxString
& WXUNUSED(name
),
641 const wxPalette
*WXUNUSED(palette
))
646 // ----------------------------------------------------------------------------
648 // ----------------------------------------------------------------------------
650 bool wxCreateDIB(long xSize
, long ySize
, long bitsPerPixel
,
651 HPALETTE hPal
, LPBITMAPINFO
* lpDIBHeader
)
653 unsigned long i
, headerSize
;
654 LPBITMAPINFO lpDIBheader
= NULL
;
655 LPPALETTEENTRY lpPe
= NULL
;
658 // Allocate space for a DIB header
659 headerSize
= (sizeof(BITMAPINFOHEADER
) + (256 * sizeof(PALETTEENTRY
)));
660 lpDIBheader
= (BITMAPINFO
*) malloc(headerSize
);
661 lpPe
= (PALETTEENTRY
*)((BYTE
*)lpDIBheader
+ sizeof(BITMAPINFOHEADER
));
663 GetPaletteEntries(hPal
, 0, 256, lpPe
);
665 memset(lpDIBheader
, 0x00, sizeof(BITMAPINFOHEADER
));
667 // Fill in the static parts of the DIB header
668 lpDIBheader
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
669 lpDIBheader
->bmiHeader
.biWidth
= xSize
;
670 lpDIBheader
->bmiHeader
.biHeight
= ySize
;
671 lpDIBheader
->bmiHeader
.biPlanes
= 1;
673 // this value must be 1, 4, 8 or 24 so PixelDepth can only be
674 lpDIBheader
->bmiHeader
.biBitCount
= (WORD
)(bitsPerPixel
);
675 lpDIBheader
->bmiHeader
.biCompression
= BI_RGB
;
676 lpDIBheader
->bmiHeader
.biSizeImage
= xSize
* abs(ySize
) * bitsPerPixel
>> 3;
677 lpDIBheader
->bmiHeader
.biClrUsed
= 256;
680 // Initialize the DIB palette
681 for (i
= 0; i
< 256; i
++) {
682 lpDIBheader
->bmiColors
[i
].rgbReserved
= lpPe
[i
].peFlags
;
683 lpDIBheader
->bmiColors
[i
].rgbRed
= lpPe
[i
].peRed
;
684 lpDIBheader
->bmiColors
[i
].rgbGreen
= lpPe
[i
].peGreen
;
685 lpDIBheader
->bmiColors
[i
].rgbBlue
= lpPe
[i
].peBlue
;
688 *lpDIBHeader
= lpDIBheader
;
693 void wxFreeDIB(LPBITMAPINFO lpDIBHeader
)