1 /////////////////////////////////////////////////////////////////////////////
4 // Author: David Webster
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
21 #include "wx/palette.h"
22 #include "wx/dcmemory.h"
23 #include "wx/bitmap.h"
27 #include "wx/os2/private.h"
30 //#include "wx/msw/dib.h"
33 // ----------------------------------------------------------------------------
35 // ----------------------------------------------------------------------------
37 #if !USE_SHARED_LIBRARIES
38 IMPLEMENT_DYNAMIC_CLASS(wxBitmap
, wxGDIObject
)
39 IMPLEMENT_DYNAMIC_CLASS(wxMask
, wxObject
)
41 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler
, wxObject
)
44 // ============================================================================
46 // ============================================================================
48 // ----------------------------------------------------------------------------
50 // ----------------------------------------------------------------------------
52 wxBitmapRefData
::wxBitmapRefData()
55 m_pSelectedInto
= NULL
;
60 void wxBitmapRefData
::Free()
62 wxASSERT_MSG( !m_pSelectedInto
,
63 wxT("deleting bitmap still selected into wxMemoryDC") );
67 if ( !::GpiDeleteBitmap((HBITMAP
)m_hBitmap
) )
69 wxLogLastError("GpiDeleteBitmap(hbitmap)");
77 // ----------------------------------------------------------------------------
79 // ----------------------------------------------------------------------------
81 // this function should be called from all wxBitmap ctors
84 // m_refData = NULL; done in the base class ctor
87 wxTheBitmapList
->AddBitmap(this);
90 bool wxBitmap
::CopyFromIconOrCursor(
91 const wxGDIImage
& rIcon
94 wxBitmapRefData
* pRefData
= new wxBitmapRefData
;
98 refData
->m_width
= rIcon
.GetWidth();
99 refData
->m_height
= rIcon
.GetHeight();
100 refData
->m_depth
= wxDisplayDepth();
102 refData
->m_hBitmap
= (WXHBITMAP
)rIcon
.GetHandle();
104 refData
->m_bitmapMask
= new wxMask();
106 #if WXWIN_COMPATIBILITY_2
107 refData
->m_ok
= TRUE
;
108 #endif // WXWIN_COMPATIBILITY_2
113 bool wxBitmap
::CopyFromCursor(
114 const wxCursor
& rCursor
121 return CopyFromIconOrCursor(wxGDIImage
)rCursor
);
124 bool wxBitmap
::CopyFromIcon(
133 #if WXWIN_COMPATIBILITY_2
134 refData
->m_ok
= TRUE
;
135 #endif // WXWIN_COMPATIBILITY_2
137 return CopyFromIconOrCursor(icon
);
140 wxBitmap
::~wxBitmap()
143 wxTheBitmapList
->DeleteObject(this);
155 wxBitmapRefData
* pRefData
= new wxBitmapRefData
;
156 BITMAPINFOHEADER2 vHeader
;
160 DEVOPENSTRUCT vDop
= { NULL
, "DISPLAY", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
161 SIZEL vSize
= {0, 0};
163 wxAssert(vHabmain
!= NULL
);
165 hDc
= ::DevOpenDC(vHabmain
, OD_MEMORY
, (PSZ
)"*", 1L, (PDEVOPENDATA
)&vDop
, 0L);
167 vHeader
.cbFix
= sizeof(vHeader
);
168 vHeader
.cx
= (USHORT
)nTheWidth
;
169 vHeader
.cy
= (USHORT
)nTheHeight
;
170 vHeader
.cPlanes
= 1L;
171 vHeader
.cBitCount
= nNoBits
;
172 vHeader
.ulCompression
= BCA_UNCOMP
;
173 vHeader
.cxResolution
= 0;
174 vHeader
.cyResolution
= 0;
175 vHeader
.cclrUsed
= 0;
176 vHeader
.cclrImportant
= 0;
177 vHeader
.usUnits
= BRU_METRIC
;
178 vHeader
.usRecording
= BRA_BOTTOMUP
;
179 vHeader
.usRendering
= BRH_NOTHALFTONED
;
182 vHeader
.ulColorEncoding
= 0;
183 vHeader
.ulIdentifier
= 0;
185 vhPs
= ::GpiCreatePS(habMain
, hdc
, &vSize
, GPIA_ASSOC
| PU_PELS
);
188 wxLogLastError("GpiCreatePS Failure");
191 m_refData
= pRefData
;
193 refData
->m_width
= nTheWidth
;
194 refData
->m_height
= nTheHeight
;
195 refData
->m_depth
= nNoBits
;
196 refData
->m_numColors
= 0;
197 refData
->m_selectedInto
= NULL
;
199 HBITMAP hBmp
= ::GpiCreateBitmap(hPs
, &vHeader
, 0L, NULL
, &vInfo
);
202 wxLogLastError("CreateBitmap");
204 SetHBITMAP((WXHBITMAP
)hbmp
);
207 // Create from XPM data
210 , wxControl
* WXUNUSED(pAnItem
))
214 F (void)Create( (void *)ppData
215 ,wxBITMAP_TYPE_XPM_DATA
255 const wxString
& rFilename
266 bool wxBitmap
::Create(
273 BITMAPINFOHEADER2 vHeader
;
277 DEVOPENSTRUCT vDop
= { NULL
, "DISPLAY", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
278 SIZEL vSize
= {0, 0};
280 wxAssert(vHabmain
!= NULL
);
282 hDc
= ::DevOpenDC(vHabmain
, OD_MEMORY
, (PSZ
)"*", 1L, (PDEVOPENDATA
)&vDop
, 0L);
284 vHeader
.cbFix
= sizeof(vHeader
);
285 vHeader
.cx
= (USHORT
)nW
;
286 vHeader
.cy
= (USHORT
)nH
;
287 vHeader
.cPlanes
= (USHORT
)nD
;
288 vHeader
.cBitCount
= 24;
289 vHeader
.ulCompression
= BCA_UNCOMP
;
290 vHeader
.cxResolution
= 0;
291 vHeader
.cyResolution
= 0;
292 vHeader
.cclrUsed
= 0;
293 vHeader
.cclrImportant
= 0;
294 vHeader
.usUnits
= BRU_METRIC
;
295 vHeader
.usRecording
= BRA_BOTTOMUP
;
296 vHeader
.usRendering
= BRH_NOTHALFTONED
;
299 vHeader
.ulColorEncoding
= 0;
300 vHeader
.ulIdentifier
= 0;
302 vhPs
= ::GpiCreatePS(habMain
, hdc
, &vSize
, GPIA_ASSOC
| PU_PELS
);
305 wxLogLastError("GpiCreatePS Failure");
310 m_refData
= new wxBitmapRefData
;
312 GetBitmapData()->m_width
= nW
;
313 GetBitmapData()->m_height
= nH
;
314 GetBitmapData()->m_depth
= nD
;
318 hBmp
= ::GpiCreateBitmap(hPs
, &vHeader
, 0L, NULL
, &vInfo
);
321 wxLogLastError("CreateBitmap");
327 hbmp
= ::CreateCompatibleBitmap(dc
, w
, h
);
330 wxLogLastError("CreateCompatibleBitmap");
333 GetBitmapData()->m_depth
= wxDisplayDepth();
336 SetHBITMAP((WXHBITMAP
)hbmp
);
338 #if WXWIN_COMPATIBILITY_2
339 GetBitmapData()->m_ok
= hbmp
!= 0;
340 #endif // WXWIN_COMPATIBILITY_2
345 bool wxBitmap
::LoadFile(const wxString
& filename
, long type
)
349 wxBitmapHandler
*handler
= wxDynamicCast(FindHandler(type
), wxBitmapHandler
);
353 m_refData
= new wxBitmapRefData
;
355 return handler
->LoadFile(this, filename
, type
, -1, -1);
360 if ( !image
.LoadFile( filename
, type
) || !image
.Ok() )
363 *this = image
.ConvertToBitmap();
369 bool wxBitmap
::Create(void *data
, long type
, int width
, int height
, int depth
)
373 wxBitmapHandler
*handler
= wxDynamicCast(FindHandler(type
), wxBitmapHandler
);
377 wxLogDebug(wxT("Failed to create bitmap: no bitmap handler for "
378 "type %d defined."), type
);
383 m_refData
= new wxBitmapRefData
;
385 return handler
->Create(this, data
, type
, width
, height
, depth
);
388 bool wxBitmap
::SaveFile(const wxString
& filename
, int type
, const wxPalette
*palette
)
390 wxBitmapHandler
*handler
= wxDynamicCast(FindHandler(type
), wxBitmapHandler
);
394 return handler
->SaveFile(this, filename
, type
, palette
);
398 // FIXME what about palette? shouldn't we use it?
399 wxImage
image( *this );
403 return image
.SaveFile( filename
, type
);
407 // ----------------------------------------------------------------------------
408 // wxBitmap accessors
409 // ----------------------------------------------------------------------------
411 void wxBitmap
::SetQuality(int q
)
415 GetBitmapData()->m_quality
= q
;
418 #if WXWIN_COMPATIBILITY_2
419 void wxBitmap
::SetOk(bool isOk
)
423 GetBitmapData()->m_ok
= isOk
;
425 #endif // WXWIN_COMPATIBILITY_2
427 void wxBitmap
::SetPalette(const wxPalette
& palette
)
431 GetBitmapData()->m_bitmapPalette
= palette
;
434 void wxBitmap
::SetMask(wxMask
*mask
)
438 GetBitmapData()->m_bitmapMask
= mask
;
441 // Creates a bitmap that matches the device context, from
442 // an arbitray bitmap. At present, the original bitmap must have an
443 // associated palette. TODO: use a default palette if no palette exists.
444 // Contributed by Frederic Villeneuve <frederic.villeneuve@natinst.com>
445 wxBitmap wxBitmap
::GetBitmapForDC(wxDC
& dc
) const
448 wxBitmap
tmpBitmap(this->GetWidth(), this->GetHeight(), dc
.GetDepth());
449 HPALETTE hPal
= (HPALETTE
) NULL
;
451 void *lpBits
= (void*) NULL
;
453 if( GetPalette() && GetPalette()->Ok() )
455 tmpBitmap
.SetPalette(*GetPalette());
456 memDC
.SelectObject(tmpBitmap
);
457 memDC
.SetPalette(*GetPalette());
458 hPal
= (HPALETTE
)GetPalette()->GetHPALETTE();
462 hPal
= (HPALETTE
) ::GetStockObject(DEFAULT_PALETTE
);
464 palette
.SetHPALETTE( (WXHPALETTE
)hPal
);
465 tmpBitmap
.SetPalette( palette
);
466 memDC
.SelectObject(tmpBitmap
);
467 memDC
.SetPalette( palette
);
470 // set the height negative because in a DIB the order of the lines is
472 if ( !wxCreateDIB(GetWidth(), -GetHeight(), GetDepth(), hPal
, &lpDib
) )
477 lpBits
= malloc(lpDib
->bmiHeader
.biSizeImage
);
479 ::GetBitmapBits(GetHbitmap(), lpDib
->bmiHeader
.biSizeImage
, lpBits
);
481 ::SetDIBitsToDevice(GetHdcOf(memDC
), 0, 0,
482 GetWidth(), GetHeight(),
483 0, 0, 0, GetHeight(),
484 lpBits
, lpDib
, DIB_RGB_COLORS
);
493 // ----------------------------------------------------------------------------
495 // ----------------------------------------------------------------------------
502 // Construct a mask from a bitmap and a colour indicating
503 // the transparent area
504 wxMask
::wxMask(const wxBitmap
& bitmap
, const wxColour
& colour
)
507 Create(bitmap
, colour
);
510 // Construct a mask from a bitmap and a palette index indicating
511 // the transparent area
512 wxMask
::wxMask(const wxBitmap
& bitmap
, int paletteIndex
)
515 Create(bitmap
, paletteIndex
);
518 // Construct a mask from a mono bitmap (copies the bitmap).
519 wxMask
::wxMask(const wxBitmap
& bitmap
)
528 ::DeleteObject((HBITMAP
) m_maskBitmap
);
531 // Create a mask from a mono bitmap (copies the bitmap).
532 bool wxMask
::Create(const wxBitmap
& bitmap
)
536 ::DeleteObject((HBITMAP
) m_maskBitmap
);
539 if (!bitmap
.Ok() || bitmap
.GetDepth() != 1)
543 m_maskBitmap
= (WXHBITMAP
) CreateBitmap(
548 HDC srcDC
= CreateCompatibleDC(0);
549 SelectObject(srcDC
, (HBITMAP
) bitmap
.GetHBITMAP());
550 HDC destDC
= CreateCompatibleDC(0);
551 SelectObject(destDC
, (HBITMAP
) m_maskBitmap
);
552 BitBlt(destDC
, 0, 0, bitmap
.GetWidth(), bitmap
.GetHeight(), srcDC
, 0, 0, SRCCOPY
);
553 SelectObject(srcDC
, 0);
555 SelectObject(destDC
, 0);
560 // Create a mask from a bitmap and a palette index indicating
561 // the transparent area
562 bool wxMask
::Create(const wxBitmap
& bitmap
, int paletteIndex
)
566 ::DeleteObject((HBITMAP
) m_maskBitmap
);
569 if (bitmap
.Ok() && bitmap
.GetPalette()->Ok())
571 unsigned char red
, green
, blue
;
572 if (bitmap
.GetPalette()->GetRGB(paletteIndex
, &red
, &green
, &blue
))
574 wxColour
transparentColour(red
, green
, blue
);
575 return Create(bitmap
, transparentColour
);
581 // Create a mask from a bitmap and a colour indicating
582 // the transparent area
583 bool wxMask
::Create(const wxBitmap
& bitmap
, const wxColour
& colour
)
587 ::DeleteObject((HBITMAP
) m_maskBitmap
);
595 // scan the bitmap for the transparent colour and set
596 // the corresponding pixels in the mask to BLACK and
598 COLORREF maskColour
= RGB(colour
.Red(), colour
.Green(), colour
.Blue());
599 m_maskBitmap
= (WXHBITMAP
) ::CreateBitmap(
604 HDC srcDC
= ::CreateCompatibleDC(0);
605 ::SelectObject(srcDC
, (HBITMAP
) bitmap
.GetHBITMAP());
606 HDC destDC
= ::CreateCompatibleDC(0);
607 ::SelectObject(destDC
, (HBITMAP
) m_maskBitmap
);
609 // this is not very efficient, but I can't think
610 // of a better way of doing it
611 for (int w
= 0; w
< bitmap
.GetWidth(); w
++)
613 for (int h
= 0; h
< bitmap
.GetHeight(); h
++)
615 COLORREF col
= GetPixel(srcDC
, w
, h
);
616 if (col
== maskColour
)
618 ::SetPixel(destDC
, w
, h
, RGB(0, 0, 0));
622 ::SetPixel(destDC
, w
, h
, RGB(255, 255, 255));
626 ::SelectObject(srcDC
, 0);
628 ::SelectObject(destDC
, 0);
633 // ----------------------------------------------------------------------------
635 // ----------------------------------------------------------------------------
637 bool wxBitmapHandler
::Create(wxGDIImage
*image
,
640 int width
, int height
, int depth
)
642 wxBitmap
*bitmap
= wxDynamicCast(image
, wxBitmap
);
644 return bitmap ?
Create(bitmap
, data
, width
, height
, depth
) : FALSE
;
647 bool wxBitmapHandler
::Load(wxGDIImage
*image
,
648 const wxString
& name
,
650 int width
, int height
)
652 wxBitmap
*bitmap
= wxDynamicCast(image
, wxBitmap
);
654 return bitmap ?
LoadFile(bitmap
, name
, flags
, width
, height
) : FALSE
;
657 bool wxBitmapHandler
::Save(wxGDIImage
*image
,
658 const wxString
& name
,
661 wxBitmap
*bitmap
= wxDynamicCast(image
, wxBitmap
);
663 return bitmap ?
SaveFile(bitmap
, name
, type
) : FALSE
;
666 bool wxBitmapHandler
::Create(wxBitmap
*WXUNUSED(bitmap
),
667 void *WXUNUSED(data
),
670 int WXUNUSED(height
),
676 bool wxBitmapHandler
::LoadFile(wxBitmap
*WXUNUSED(bitmap
),
677 const wxString
& WXUNUSED(name
),
679 int WXUNUSED(desiredWidth
),
680 int WXUNUSED(desiredHeight
))
685 bool wxBitmapHandler
::SaveFile(wxBitmap
*WXUNUSED(bitmap
),
686 const wxString
& WXUNUSED(name
),
688 const wxPalette
*WXUNUSED(palette
))
693 // ----------------------------------------------------------------------------
695 // ----------------------------------------------------------------------------
697 bool wxCreateDIB(long xSize
, long ySize
, long bitsPerPixel
,
698 HPALETTE hPal
, LPBITMAPINFO
* lpDIBHeader
)
700 unsigned long i
, headerSize
;
701 LPBITMAPINFO lpDIBheader
= NULL
;
702 LPPALETTEENTRY lpPe
= NULL
;
705 // Allocate space for a DIB header
706 headerSize
= (sizeof(BITMAPINFOHEADER
) + (256 * sizeof(PALETTEENTRY
)));
707 lpDIBheader
= (BITMAPINFO
*) malloc(headerSize
);
708 lpPe
= (PALETTEENTRY
*)((BYTE
*)lpDIBheader
+ sizeof(BITMAPINFOHEADER
));
710 GetPaletteEntries(hPal
, 0, 256, lpPe
);
712 memset(lpDIBheader
, 0x00, sizeof(BITMAPINFOHEADER
));
714 // Fill in the static parts of the DIB header
715 lpDIBheader
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
716 lpDIBheader
->bmiHeader
.biWidth
= xSize
;
717 lpDIBheader
->bmiHeader
.biHeight
= ySize
;
718 lpDIBheader
->bmiHeader
.biPlanes
= 1;
720 // this value must be 1, 4, 8 or 24 so PixelDepth can only be
721 lpDIBheader
->bmiHeader
.biBitCount
= (WORD
)(bitsPerPixel
);
722 lpDIBheader
->bmiHeader
.biCompression
= BI_RGB
;
723 lpDIBheader
->bmiHeader
.biSizeImage
= xSize
* abs(ySize
) * bitsPerPixel
>> 3;
724 lpDIBheader
->bmiHeader
.biClrUsed
= 256;
727 // Initialize the DIB palette
728 for (i
= 0; i
< 256; i
++) {
729 lpDIBheader
->bmiColors
[i
].rgbReserved
= lpPe
[i
].peFlags
;
730 lpDIBheader
->bmiColors
[i
].rgbRed
= lpPe
[i
].peRed
;
731 lpDIBheader
->bmiColors
[i
].rgbGreen
= lpPe
[i
].peGreen
;
732 lpDIBheader
->bmiColors
[i
].rgbBlue
= lpPe
[i
].peBlue
;
735 *lpDIBHeader
= lpDIBheader
;
740 void wxFreeDIB(LPBITMAPINFO lpDIBHeader
)