]>
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 // missing from mingw32 header
51 #define CLR_INVALID ((COLORREF)-1)
52 #endif // no CLR_INVALID
54 // ----------------------------------------------------------------------------
56 // ----------------------------------------------------------------------------
58 IMPLEMENT_DYNAMIC_CLASS(wxBitmap
, wxGDIObject
)
59 IMPLEMENT_DYNAMIC_CLASS(wxMask
, wxObject
)
61 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler
, wxObject
)
63 // ============================================================================
65 // ============================================================================
67 // ----------------------------------------------------------------------------
69 // ----------------------------------------------------------------------------
71 wxBitmapRefData::wxBitmapRefData()
74 m_selectedInto
= NULL
;
77 m_hBitmap
= (WXHBITMAP
) NULL
;
80 void wxBitmapRefData::Free()
82 wxASSERT_MSG( !m_selectedInto
,
83 wxT("deleting bitmap still selected into wxMemoryDC") );
87 if ( !::DeleteObject((HBITMAP
)m_hBitmap
) )
89 wxLogLastError(wxT("DeleteObject(hbitmap)"));
97 // ----------------------------------------------------------------------------
99 // ----------------------------------------------------------------------------
101 // this function should be called from all wxBitmap ctors
102 void wxBitmap::Init()
104 // m_refData = NULL; done in the base class ctor
106 if ( wxTheBitmapList
)
107 wxTheBitmapList
->AddBitmap(this);
112 bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage
& icon
)
114 // it may be either HICON or HCURSOR
115 HICON hicon
= (HICON
)icon
.GetHandle();
118 if ( !::GetIconInfo(hicon
, &iconInfo
) )
120 wxLogLastError(wxT("GetIconInfo"));
125 wxBitmapRefData
*refData
= new wxBitmapRefData
;
128 int w
= icon
.GetWidth(),
129 h
= icon
.GetHeight();
131 refData
->m_width
= w
;
132 refData
->m_height
= h
;
133 refData
->m_depth
= wxDisplayDepth();
135 refData
->m_hBitmap
= (WXHBITMAP
)iconInfo
.hbmColor
;
137 // the mask returned by GetIconInfo() is inversed compared to the usual
139 refData
->m_bitmapMask
= new wxMask((WXHBITMAP
)
140 wxInvertMask(iconInfo
.hbmMask
, w
, h
));
142 #if WXWIN_COMPATIBILITY_2
143 refData
->m_ok
= TRUE
;
144 #endif // WXWIN_COMPATIBILITY_2
151 bool wxBitmap::CopyFromCursor(const wxCursor
& cursor
)
159 wxFAIL_MSG( _T("don't know how to convert cursor to bitmap") );
163 return CopyFromIconOrCursor(cursor
);
167 bool wxBitmap::CopyFromIcon(const wxIcon
& icon
)
174 // GetIconInfo() doesn't exist under Win16 and I don't know any other way
175 // to create a bitmap from icon there - but using this way we won't have
178 int width
= icon
.GetWidth(),
179 height
= icon
.GetHeight();
181 // copy the icon to the bitmap
183 HDC hdc
= ::CreateCompatibleDC(hdcScreen
);
184 HBITMAP hbitmap
= ::CreateCompatibleBitmap(hdcScreen
, width
, height
);
185 HBITMAP hbmpOld
= (HBITMAP
)::SelectObject(hdc
, hbitmap
);
187 ::DrawIcon(hdc
, 0, 0, GetHiconOf(icon
));
189 ::SelectObject(hdc
, hbmpOld
);
192 wxBitmapRefData
*refData
= new wxBitmapRefData
;
195 refData
->m_width
= width
;
196 refData
->m_height
= height
;
197 refData
->m_depth
= wxDisplayDepth();
199 refData
->m_hBitmap
= (WXHBITMAP
)hbitmap
;
201 #if WXWIN_COMPATIBILITY_2
202 refData
->m_ok
= TRUE
;
203 #endif // WXWIN_COMPATIBILITY_2
207 return CopyFromIconOrCursor(icon
);
208 #endif // Win16/Win32
211 wxBitmap::~wxBitmap()
214 wxTheBitmapList
->DeleteObject(this);
217 wxBitmap::wxBitmap(const char bits
[], int width
, int height
, int depth
)
221 wxBitmapRefData
*refData
= new wxBitmapRefData
;
224 refData
->m_width
= width
;
225 refData
->m_height
= height
;
226 refData
->m_depth
= depth
;
227 refData
->m_numColors
= 0;
228 refData
->m_selectedInto
= NULL
;
233 // we assume that it is in XBM format which is not quite the same as
234 // the format CreateBitmap() wants because the order of bytes in the
236 static const size_t bytesPerLine
= (width
+ 7) / 8;
237 static const size_t padding
= bytesPerLine
% 2;
238 static const size_t len
= height
* ( padding
+ bytesPerLine
);
239 data
= (char *)malloc(len
);
240 const char *src
= bits
;
243 for ( int rows
= 0; rows
< height
; rows
++ )
245 for ( size_t cols
= 0; cols
< bytesPerLine
; cols
++ )
247 unsigned char val
= *src
++;
248 unsigned char reversed
= 0;
250 for ( int bits
= 0; bits
< 8; bits
++)
253 reversed
|= (val
& 0x01);
265 // bits should already be in Windows standard format
266 data
= (char *)bits
; // const_cast is harmless
269 HBITMAP hbmp
= ::CreateBitmap(width
, height
, 1, depth
, data
);
272 wxLogLastError(wxT("CreateBitmap"));
280 SetHBITMAP((WXHBITMAP
)hbmp
);
283 // Create from XPM data
284 bool wxBitmap::CreateFromXpm(const char **data
)
288 return Create((void *)data
, wxBITMAP_TYPE_XPM_DATA
, 0, 0, 0);
291 wxBitmap::wxBitmap(int w
, int h
, int d
)
295 (void)Create(w
, h
, d
);
298 wxBitmap::wxBitmap(void *data
, long type
, int width
, int height
, int depth
)
302 (void)Create(data
, type
, width
, height
, depth
);
305 wxBitmap::wxBitmap(const wxString
& filename
, wxBitmapType type
)
309 LoadFile(filename
, (int)type
);
312 bool wxBitmap::Create(int w
, int h
, int d
)
316 m_refData
= new wxBitmapRefData
;
318 GetBitmapData()->m_width
= w
;
319 GetBitmapData()->m_height
= h
;
320 GetBitmapData()->m_depth
= d
;
326 hbmp
= ::CreateBitmap(w
, h
, 1, d
, NULL
);
329 wxLogLastError(wxT("CreateBitmap"));
335 hbmp
= ::CreateCompatibleBitmap(dc
, w
, h
);
338 wxLogLastError(wxT("CreateCompatibleBitmap"));
341 GetBitmapData()->m_depth
= wxDisplayDepth();
344 SetHBITMAP((WXHBITMAP
)hbmp
);
346 #if WXWIN_COMPATIBILITY_2
347 GetBitmapData()->m_ok
= hbmp
!= 0;
348 #endif // WXWIN_COMPATIBILITY_2
353 // ----------------------------------------------------------------------------
354 // wxImage to/from conversions
355 // ----------------------------------------------------------------------------
359 bool wxBitmap::CreateFromImage( const wxImage
& image
, int depth
)
361 wxCHECK_MSG( image
.Ok(), FALSE
, wxT("invalid image") )
363 m_refData
= new wxBitmapRefData();
365 // sizeLimit is the MS upper limit for the DIB size
367 int sizeLimit
= 1024*768*3;
369 int sizeLimit
= 0x7fff ;
372 // width and height of the device-dependent bitmap
373 int width
= image
.GetWidth();
374 int bmpHeight
= image
.GetHeight();
376 // calc the number of bytes per scanline and padding
377 int bytePerLine
= width
*3;
378 int sizeDWORD
= sizeof( DWORD
);
379 int lineBoundary
= bytePerLine
% sizeDWORD
;
381 if( lineBoundary
> 0 )
383 padding
= sizeDWORD
- lineBoundary
;
384 bytePerLine
+= padding
;
386 // calc the number of DIBs and heights of DIBs
389 int height
= sizeLimit
/bytePerLine
;
390 if( height
>= bmpHeight
)
394 numDIB
= bmpHeight
/ height
;
395 hRemain
= bmpHeight
% height
;
396 if( hRemain
>0 ) numDIB
++;
399 // set bitmap parameters
400 wxCHECK_MSG( image
.Ok(), FALSE
, wxT("invalid image") );
402 SetHeight( bmpHeight
);
403 if (depth
== -1) depth
= wxDisplayDepth();
406 // create a DIB header
407 int headersize
= sizeof(BITMAPINFOHEADER
);
408 BITMAPINFO
*lpDIBh
= (BITMAPINFO
*) malloc( headersize
);
409 wxCHECK_MSG( lpDIBh
, FALSE
, wxT("could not allocate memory for DIB header") );
410 // Fill in the DIB header
411 lpDIBh
->bmiHeader
.biSize
= headersize
;
412 lpDIBh
->bmiHeader
.biWidth
= (DWORD
)width
;
413 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
414 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
415 // the general formula for biSizeImage:
416 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
417 lpDIBh
->bmiHeader
.biPlanes
= 1;
418 lpDIBh
->bmiHeader
.biBitCount
= 24;
419 lpDIBh
->bmiHeader
.biCompression
= BI_RGB
;
420 lpDIBh
->bmiHeader
.biClrUsed
= 0;
421 // These seem not really needed for our purpose here.
422 lpDIBh
->bmiHeader
.biClrImportant
= 0;
423 lpDIBh
->bmiHeader
.biXPelsPerMeter
= 0;
424 lpDIBh
->bmiHeader
.biYPelsPerMeter
= 0;
425 // memory for DIB data
426 unsigned char *lpBits
;
427 lpBits
= (unsigned char *)malloc( lpDIBh
->bmiHeader
.biSizeImage
);
430 wxFAIL_MSG( wxT("could not allocate memory for DIB") );
435 // create and set the device-dependent bitmap
436 HDC hdc
= ::GetDC(NULL
);
437 HDC memdc
= ::CreateCompatibleDC( hdc
);
439 hbitmap
= ::CreateCompatibleBitmap( hdc
, width
, bmpHeight
);
440 ::SelectObject( memdc
, hbitmap
);
442 HPALETTE hOldPalette
= 0;
443 if (image
.GetPalette().Ok())
445 hOldPalette
= ::SelectPalette(memdc
, (HPALETTE
) image
.GetPalette().GetHPALETTE(), FALSE
);
446 ::RealizePalette(memdc
);
449 // copy image data into DIB data and then into DDB (in a loop)
450 unsigned char *data
= image
.GetData();
453 unsigned char *ptdata
= data
;
454 unsigned char *ptbits
;
456 for( n
=0; n
<numDIB
; n
++ )
458 if( numDIB
> 1 && n
== numDIB
-1 && hRemain
> 0 )
460 // redefine height and size of the (possibly) last smaller DIB
461 // memory is not reallocated
463 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
464 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
468 for( j
=0; j
<height
; j
++ )
470 for( i
=0; i
<width
; i
++ )
472 *(ptbits
++) = *(ptdata
+2);
473 *(ptbits
++) = *(ptdata
+1);
474 *(ptbits
++) = *(ptdata
);
477 for( i
=0; i
< padding
; i
++ ) *(ptbits
++) = 0;
479 ::StretchDIBits( memdc
, 0, origin
, width
, height
,\
480 0, 0, width
, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
, SRCCOPY
);
482 // if numDIB = 1, lines below can also be used
483 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
484 // The above line is equivalent to the following two lines.
485 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
486 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
487 // or the following lines
488 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
489 // HDC memdc = ::CreateCompatibleDC( hdc );
490 // ::SelectObject( memdc, hbitmap);
491 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
492 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
493 // ::SelectObject( memdc, 0 );
494 // ::DeleteDC( memdc );
496 SetHBITMAP( (WXHBITMAP
) hbitmap
);
499 SelectPalette(memdc
, hOldPalette
, FALSE
);
501 // similarly, created an mono-bitmap for the possible mask
502 if( image
.HasMask() )
504 hbitmap
= ::CreateBitmap( (WORD
)width
, (WORD
)bmpHeight
, 1, 1, NULL
);
505 HGDIOBJ hbmpOld
= ::SelectObject( memdc
, hbitmap
);
506 if( numDIB
== 1 ) height
= bmpHeight
;
507 else height
= sizeLimit
/bytePerLine
;
508 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
509 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
511 unsigned char r
= image
.GetMaskRed();
512 unsigned char g
= image
.GetMaskGreen();
513 unsigned char b
= image
.GetMaskBlue();
514 unsigned char zero
= 0, one
= 255;
516 for( n
=0; n
<numDIB
; n
++ )
518 if( numDIB
> 1 && n
== numDIB
- 1 && hRemain
> 0 )
520 // redefine height and size of the (possibly) last smaller DIB
521 // memory is not reallocated
523 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
524 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
527 for( int j
=0; j
<height
; j
++ )
529 for(i
=0; i
<width
; i
++ )
531 // was causing a code gen bug in cw : if( ( cr !=r) || (cg!=g) || (cb!=b) )
532 unsigned char cr
= (*(ptdata
++)) ;
533 unsigned char cg
= (*(ptdata
++)) ;
534 unsigned char cb
= (*(ptdata
++)) ;
536 if( ( cr
!=r
) || (cg
!=g
) || (cb
!=b
) )
549 for( i
=0; i
< padding
; i
++ ) *(ptbits
++) = zero
;
551 ::StretchDIBits( memdc
, 0, origin
, width
, height
,\
552 0, 0, width
, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
, SRCCOPY
);
555 // create a wxMask object
556 wxMask
*mask
= new wxMask();
557 mask
->SetMaskBitmap( (WXHBITMAP
) hbitmap
);
559 // It will be deleted when the wxBitmap object is deleted (as of 01/1999)
560 /* The following can also be used but is slow to run
561 wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
562 wxMask *mask = new wxMask( *this, colour );
566 ::SelectObject( memdc
, hbmpOld
);
569 // free allocated resources
571 ::ReleaseDC(NULL
, hdc
);
575 #if WXWIN_COMPATIBILITY_2
576 // check the wxBitmap object
577 GetBitmapData()->SetOk();
578 #endif // WXWIN_COMPATIBILITY_2
580 if (wxTheBitmapList
) wxTheBitmapList
->AddBitmap(this);
585 wxImage
wxBitmap::ConvertToImage() const
589 wxCHECK_MSG( Ok(), wxNullImage
, wxT("invalid bitmap") );
591 // create an wxImage object
592 int width
= GetWidth();
593 int height
= GetHeight();
594 image
.Create( width
, height
);
595 unsigned char *data
= image
.GetData();
598 wxFAIL_MSG( wxT("could not allocate data for image") );
602 // calc the number of bytes per scanline and padding in the DIB
603 int bytePerLine
= width
*3;
604 int sizeDWORD
= sizeof( DWORD
);
605 int lineBoundary
= bytePerLine
% sizeDWORD
;
607 if( lineBoundary
> 0 )
609 padding
= sizeDWORD
- lineBoundary
;
610 bytePerLine
+= padding
;
613 // create a DIB header
614 int headersize
= sizeof(BITMAPINFOHEADER
);
615 BITMAPINFO
*lpDIBh
= (BITMAPINFO
*) malloc( headersize
);
618 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
622 // Fill in the DIB header
623 lpDIBh
->bmiHeader
.biSize
= headersize
;
624 lpDIBh
->bmiHeader
.biWidth
= width
;
625 lpDIBh
->bmiHeader
.biHeight
= -height
;
626 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
* height
;
627 lpDIBh
->bmiHeader
.biPlanes
= 1;
628 lpDIBh
->bmiHeader
.biBitCount
= 24;
629 lpDIBh
->bmiHeader
.biCompression
= BI_RGB
;
630 lpDIBh
->bmiHeader
.biClrUsed
= 0;
631 // These seem not really needed for our purpose here.
632 lpDIBh
->bmiHeader
.biClrImportant
= 0;
633 lpDIBh
->bmiHeader
.biXPelsPerMeter
= 0;
634 lpDIBh
->bmiHeader
.biYPelsPerMeter
= 0;
635 // memory for DIB data
636 unsigned char *lpBits
;
637 lpBits
= (unsigned char *) malloc( lpDIBh
->bmiHeader
.biSizeImage
);
640 wxFAIL_MSG( wxT("could not allocate data for DIB") );
646 // copy data from the device-dependent bitmap to the DIB
647 HDC hdc
= ::GetDC(NULL
);
649 hbitmap
= (HBITMAP
) GetHBITMAP();
650 ::GetDIBits( hdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
652 // copy DIB data into the wxImage object
654 unsigned char *ptdata
= data
;
655 unsigned char *ptbits
= lpBits
;
656 for( i
=0; i
<height
; i
++ )
658 for( j
=0; j
<width
; j
++ )
660 *(ptdata
++) = *(ptbits
+2);
661 *(ptdata
++) = *(ptbits
+1);
662 *(ptdata
++) = *(ptbits
);
668 // similarly, set data according to the possible mask bitmap
669 if( GetMask() && GetMask()->GetMaskBitmap() )
671 hbitmap
= (HBITMAP
) GetMask()->GetMaskBitmap();
672 // memory DC created, color set, data copied, and memory DC deleted
673 HDC memdc
= ::CreateCompatibleDC( hdc
);
674 ::SetTextColor( memdc
, RGB( 0, 0, 0 ) );
675 ::SetBkColor( memdc
, RGB( 255, 255, 255 ) );
676 ::GetDIBits( memdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
678 // background color set to RGB(16,16,16) in consistent with wxGTK
679 unsigned char r
=16, g
=16, b
=16;
682 for( i
=0; i
<height
; i
++ )
684 for( j
=0; j
<width
; j
++ )
698 image
.SetMaskColour( r
, g
, b
);
699 image
.SetMask( TRUE
);
703 image
.SetMask( FALSE
);
705 // free allocated resources
706 ::ReleaseDC(NULL
, hdc
);
713 #endif // wxUSE_IMAGE
715 bool wxBitmap::LoadFile(const wxString
& filename
, long type
)
719 wxBitmapHandler
*handler
= wxDynamicCast(FindHandler(type
), wxBitmapHandler
);
723 m_refData
= new wxBitmapRefData
;
725 return handler
->LoadFile(this, filename
, type
, -1, -1);
731 if ( image
.LoadFile( filename
, type
) && image
.Ok() )
733 *this = image
.ConvertToBitmap();
738 #endif // wxUSE_IMAGE
743 bool wxBitmap::Create(void *data
, long type
, int width
, int height
, int depth
)
747 wxBitmapHandler
*handler
= wxDynamicCast(FindHandler(type
), wxBitmapHandler
);
751 wxLogDebug(wxT("Failed to create bitmap: no bitmap handler for type %d defined."), type
);
756 m_refData
= new wxBitmapRefData
;
758 return handler
->Create(this, data
, type
, width
, height
, depth
);
761 bool wxBitmap::SaveFile(const wxString
& filename
, int type
, const wxPalette
*palette
)
763 wxBitmapHandler
*handler
= wxDynamicCast(FindHandler(type
), wxBitmapHandler
);
767 return handler
->SaveFile(this, filename
, type
, palette
);
772 // FIXME what about palette? shouldn't we use it?
773 wxImage
image( *this );
776 return image
.SaveFile(filename
, type
);
779 #endif // wxUSE_IMAGE
784 // ----------------------------------------------------------------------------
785 // sub bitmap extraction
786 // ----------------------------------------------------------------------------
788 wxBitmap
wxBitmap::GetSubBitmap( const wxRect
& rect
) const
791 (rect
.x
>= 0) && (rect
.y
>= 0) &&
792 (rect
.x
+rect
.width
<= GetWidth()) &&
793 (rect
.y
+rect
.height
<= GetHeight()),
794 wxNullBitmap
, wxT("Invalid bitmap or bitmap region") );
796 wxBitmap
ret( rect
.width
, rect
.height
, GetDepth() );
797 wxASSERT_MSG( ret
.Ok(), wxT("GetSubBitmap error") );
800 HDC dcSrc
= ::CreateCompatibleDC(NULL
);
801 HDC dcDst
= ::CreateCompatibleDC(NULL
);
802 SelectObject(dcSrc
, (HBITMAP
) GetHBITMAP());
803 SelectObject(dcDst
, (HBITMAP
) ret
.GetHBITMAP());
804 BitBlt(dcDst
, 0, 0, rect
.width
, rect
.height
, dcSrc
, rect
.x
, rect
.y
, SRCCOPY
);
806 // copy mask if there is one
809 HBITMAP hbmpMask
= ::CreateBitmap(rect
.width
, rect
.height
, 1, 1, 0);
811 SelectObject(dcSrc
, (HBITMAP
) GetMask()->GetMaskBitmap());
812 SelectObject(dcDst
, (HBITMAP
) hbmpMask
);
813 BitBlt(dcDst
, 0, 0, rect
.width
, rect
.height
, dcSrc
, rect
.x
, rect
.y
, SRCCOPY
);
815 wxMask
*mask
= new wxMask((WXHBITMAP
) hbmpMask
);
819 SelectObject(dcDst
, NULL
);
820 SelectObject(dcSrc
, NULL
);
827 // ----------------------------------------------------------------------------
828 // wxBitmap accessors
829 // ----------------------------------------------------------------------------
831 void wxBitmap::SetQuality(int q
)
835 GetBitmapData()->m_quality
= q
;
838 #if WXWIN_COMPATIBILITY_2
839 void wxBitmap::SetOk(bool isOk
)
843 GetBitmapData()->m_ok
= isOk
;
845 #endif // WXWIN_COMPATIBILITY_2
847 void wxBitmap::SetPalette(const wxPalette
& palette
)
851 GetBitmapData()->m_bitmapPalette
= palette
;
854 void wxBitmap::SetMask(wxMask
*mask
)
858 GetBitmapData()->m_bitmapMask
= mask
;
861 // Creates a bitmap that matches the device context, from
862 // an arbitray bitmap. At present, the original bitmap must have an
863 // associated palette. TODO: use a default palette if no palette exists.
864 // Contributed by Frederic Villeneuve <frederic.villeneuve@natinst.com>
865 wxBitmap
wxBitmap::GetBitmapForDC(wxDC
& dc
) const
868 wxBitmap
tmpBitmap(GetWidth(), GetHeight(), dc
.GetDepth());
869 HPALETTE hPal
= (HPALETTE
) NULL
;
871 void *lpBits
= (void*) NULL
;
873 if( GetPalette() && GetPalette()->Ok() )
875 tmpBitmap
.SetPalette(*GetPalette());
876 memDC
.SelectObject(tmpBitmap
);
877 memDC
.SetPalette(*GetPalette());
878 hPal
= (HPALETTE
)GetPalette()->GetHPALETTE();
882 hPal
= (HPALETTE
) ::GetStockObject(DEFAULT_PALETTE
);
884 palette
.SetHPALETTE( (WXHPALETTE
)hPal
);
885 tmpBitmap
.SetPalette( palette
);
886 memDC
.SelectObject(tmpBitmap
);
887 memDC
.SetPalette( palette
);
890 // set the height negative because in a DIB the order of the lines is
892 if ( !wxCreateDIB(GetWidth(), -GetHeight(), GetDepth(), hPal
, &lpDib
) )
897 lpBits
= malloc(lpDib
->bmiHeader
.biSizeImage
);
899 ::GetBitmapBits(GetHbitmap(), lpDib
->bmiHeader
.biSizeImage
, lpBits
);
901 ::SetDIBitsToDevice(GetHdcOf(memDC
), 0, 0,
902 GetWidth(), GetHeight(),
903 0, 0, 0, GetHeight(),
904 lpBits
, lpDib
, DIB_RGB_COLORS
);
913 // ----------------------------------------------------------------------------
915 // ----------------------------------------------------------------------------
922 // Construct a mask from a bitmap and a colour indicating
923 // the transparent area
924 wxMask::wxMask(const wxBitmap
& bitmap
, const wxColour
& colour
)
927 Create(bitmap
, colour
);
930 // Construct a mask from a bitmap and a palette index indicating
931 // the transparent area
932 wxMask::wxMask(const wxBitmap
& bitmap
, int paletteIndex
)
935 Create(bitmap
, paletteIndex
);
938 // Construct a mask from a mono bitmap (copies the bitmap).
939 wxMask::wxMask(const wxBitmap
& bitmap
)
948 ::DeleteObject((HBITMAP
) m_maskBitmap
);
951 // Create a mask from a mono bitmap (copies the bitmap).
952 bool wxMask::Create(const wxBitmap
& bitmap
)
954 wxCHECK_MSG( bitmap
.Ok() && bitmap
.GetDepth() == 1, FALSE
,
955 _T("can't create mask from invalid or not monochrome bitmap") );
959 ::DeleteObject((HBITMAP
) m_maskBitmap
);
963 m_maskBitmap
= (WXHBITMAP
) CreateBitmap(
968 HDC srcDC
= CreateCompatibleDC(0);
969 SelectObject(srcDC
, (HBITMAP
) bitmap
.GetHBITMAP());
970 HDC destDC
= CreateCompatibleDC(0);
971 SelectObject(destDC
, (HBITMAP
) m_maskBitmap
);
972 BitBlt(destDC
, 0, 0, bitmap
.GetWidth(), bitmap
.GetHeight(), srcDC
, 0, 0, SRCCOPY
);
973 SelectObject(srcDC
, 0);
975 SelectObject(destDC
, 0);
980 // Create a mask from a bitmap and a palette index indicating
981 // the transparent area
982 bool wxMask::Create(const wxBitmap
& bitmap
, int paletteIndex
)
986 ::DeleteObject((HBITMAP
) m_maskBitmap
);
989 if (bitmap
.Ok() && bitmap
.GetPalette()->Ok())
991 unsigned char red
, green
, blue
;
992 if (bitmap
.GetPalette()->GetRGB(paletteIndex
, &red
, &green
, &blue
))
994 wxColour
transparentColour(red
, green
, blue
);
995 return Create(bitmap
, transparentColour
);
1001 // Create a mask from a bitmap and a colour indicating
1002 // the transparent area
1003 bool wxMask::Create(const wxBitmap
& bitmap
, const wxColour
& colour
)
1005 wxCHECK_MSG( bitmap
.Ok(), FALSE
, _T("invalid bitmap in wxMask::Create") );
1009 ::DeleteObject((HBITMAP
) m_maskBitmap
);
1013 int width
= bitmap
.GetWidth(),
1014 height
= bitmap
.GetHeight();
1016 // scan the bitmap for the transparent colour and set the corresponding
1017 // pixels in the mask to BLACK and the rest to WHITE
1018 COLORREF maskColour
= wxColourToRGB(colour
);
1019 m_maskBitmap
= (WXHBITMAP
)::CreateBitmap(width
, height
, 1, 1, 0);
1021 HDC srcDC
= ::CreateCompatibleDC(NULL
);
1022 HDC destDC
= ::CreateCompatibleDC(NULL
);
1023 if ( !srcDC
|| !destDC
)
1025 wxLogLastError(wxT("CreateCompatibleDC"));
1030 HGDIOBJ hbmpSrcOld
= ::SelectObject(srcDC
, GetHbitmapOf(bitmap
));
1033 wxLogLastError(wxT("SelectObject"));
1038 HGDIOBJ hbmpDstOld
= ::SelectObject(destDC
, (HBITMAP
)m_maskBitmap
);
1041 wxLogLastError(wxT("SelectObject"));
1046 // this is not very efficient, but I can't think of a better way of doing
1048 for ( int w
= 0; ok
&& (w
< width
); w
++ )
1050 for ( int h
= 0; ok
&& (h
< height
); h
++ )
1052 COLORREF col
= GetPixel(srcDC
, w
, h
);
1053 if ( col
== CLR_INVALID
)
1055 wxLogLastError(wxT("GetPixel"));
1057 // doesn't make sense to continue
1063 if ( col
== maskColour
)
1065 ::SetPixel(destDC
, w
, h
, RGB(0, 0, 0));
1069 ::SetPixel(destDC
, w
, h
, RGB(255, 255, 255));
1074 ::SelectObject(srcDC
, hbmpSrcOld
);
1076 ::SelectObject(destDC
, hbmpDstOld
);
1082 // ----------------------------------------------------------------------------
1084 // ----------------------------------------------------------------------------
1086 bool wxBitmapHandler::Create(wxGDIImage
*image
,
1089 int width
, int height
, int depth
)
1091 wxBitmap
*bitmap
= wxDynamicCast(image
, wxBitmap
);
1093 return bitmap
? Create(bitmap
, data
, flags
, width
, height
, depth
) : FALSE
;
1096 bool wxBitmapHandler::Load(wxGDIImage
*image
,
1097 const wxString
& name
,
1099 int width
, int height
)
1101 wxBitmap
*bitmap
= wxDynamicCast(image
, wxBitmap
);
1103 return bitmap
? LoadFile(bitmap
, name
, flags
, width
, height
) : FALSE
;
1106 bool wxBitmapHandler::Save(wxGDIImage
*image
,
1107 const wxString
& name
,
1110 wxBitmap
*bitmap
= wxDynamicCast(image
, wxBitmap
);
1112 return bitmap
? SaveFile(bitmap
, name
, type
) : FALSE
;
1115 bool wxBitmapHandler::Create(wxBitmap
*WXUNUSED(bitmap
),
1116 void *WXUNUSED(data
),
1117 long WXUNUSED(type
),
1118 int WXUNUSED(width
),
1119 int WXUNUSED(height
),
1120 int WXUNUSED(depth
))
1125 bool wxBitmapHandler::LoadFile(wxBitmap
*WXUNUSED(bitmap
),
1126 const wxString
& WXUNUSED(name
),
1127 long WXUNUSED(type
),
1128 int WXUNUSED(desiredWidth
),
1129 int WXUNUSED(desiredHeight
))
1134 bool wxBitmapHandler::SaveFile(wxBitmap
*WXUNUSED(bitmap
),
1135 const wxString
& WXUNUSED(name
),
1137 const wxPalette
*WXUNUSED(palette
))
1142 // ----------------------------------------------------------------------------
1144 // ----------------------------------------------------------------------------
1146 bool wxCreateDIB(long xSize
, long ySize
, long bitsPerPixel
,
1147 HPALETTE hPal
, LPBITMAPINFO
* lpDIBHeader
)
1149 unsigned long i
, headerSize
;
1150 LPBITMAPINFO lpDIBheader
= NULL
;
1151 LPPALETTEENTRY lpPe
= NULL
;
1154 // Allocate space for a DIB header
1155 headerSize
= (sizeof(BITMAPINFOHEADER
) + (256 * sizeof(PALETTEENTRY
)));
1156 lpDIBheader
= (BITMAPINFO
*) malloc(headerSize
);
1157 lpPe
= (PALETTEENTRY
*)((BYTE
*)lpDIBheader
+ sizeof(BITMAPINFOHEADER
));
1159 GetPaletteEntries(hPal
, 0, 256, lpPe
);
1161 memset(lpDIBheader
, 0x00, sizeof(BITMAPINFOHEADER
));
1163 // Fill in the static parts of the DIB header
1164 lpDIBheader
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
1165 lpDIBheader
->bmiHeader
.biWidth
= xSize
;
1166 lpDIBheader
->bmiHeader
.biHeight
= ySize
;
1167 lpDIBheader
->bmiHeader
.biPlanes
= 1;
1169 // this value must be 1, 4, 8 or 24 so PixelDepth can only be
1170 lpDIBheader
->bmiHeader
.biBitCount
= (WORD
)(bitsPerPixel
);
1171 lpDIBheader
->bmiHeader
.biCompression
= BI_RGB
;
1172 lpDIBheader
->bmiHeader
.biSizeImage
= xSize
* abs(ySize
) * bitsPerPixel
>> 3;
1173 lpDIBheader
->bmiHeader
.biClrUsed
= 256;
1176 // Initialize the DIB palette
1177 for (i
= 0; i
< 256; i
++) {
1178 lpDIBheader
->bmiColors
[i
].rgbReserved
= lpPe
[i
].peFlags
;
1179 lpDIBheader
->bmiColors
[i
].rgbRed
= lpPe
[i
].peRed
;
1180 lpDIBheader
->bmiColors
[i
].rgbGreen
= lpPe
[i
].peGreen
;
1181 lpDIBheader
->bmiColors
[i
].rgbBlue
= lpPe
[i
].peBlue
;
1184 *lpDIBHeader
= lpDIBheader
;
1189 void wxFreeDIB(LPBITMAPINFO lpDIBHeader
)
1194 // ----------------------------------------------------------------------------
1195 // other helper functions
1196 // ----------------------------------------------------------------------------
1198 extern HBITMAP
wxInvertMask(HBITMAP hbmpMask
, int w
, int h
)
1200 wxCHECK_MSG( hbmpMask
, 0, _T("invalid bitmap in wxInvertMask") );
1202 // get width/height from the bitmap if not given
1206 ::GetObject(hbmpMask
, sizeof(BITMAP
), (LPVOID
)&bm
);
1211 HDC hdcSrc
= ::CreateCompatibleDC(NULL
);
1212 HDC hdcDst
= ::CreateCompatibleDC(NULL
);
1213 if ( !hdcSrc
|| !hdcDst
)
1215 wxLogLastError(wxT("CreateCompatibleDC"));
1218 HBITMAP hbmpInvMask
= ::CreateBitmap(w
, h
, 1, 1, 0);
1221 wxLogLastError(wxT("CreateBitmap"));
1224 ::SelectObject(hdcSrc
, hbmpMask
);
1225 ::SelectObject(hdcDst
, hbmpInvMask
);
1226 if ( !::BitBlt(hdcDst
, 0, 0, w
, h
,
1230 wxLogLastError(wxT("BitBlt"));