]>
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 bool wxBitmap::CreateFromImage( const wxImage
& image
, int depth
)
355 wxCHECK_MSG( image
.Ok(), FALSE
, wxT("invalid image") )
357 m_refData
= new wxBitmapRefData();
359 // sizeLimit is the MS upper limit for the DIB size
361 int sizeLimit
= 1024*768*3;
363 int sizeLimit
= 0x7fff ;
366 // width and height of the device-dependent bitmap
367 int width
= image
.GetWidth();
368 int bmpHeight
= image
.GetHeight();
370 // calc the number of bytes per scanline and padding
371 int bytePerLine
= width
*3;
372 int sizeDWORD
= sizeof( DWORD
);
373 int lineBoundary
= bytePerLine
% sizeDWORD
;
375 if( lineBoundary
> 0 )
377 padding
= sizeDWORD
- lineBoundary
;
378 bytePerLine
+= padding
;
380 // calc the number of DIBs and heights of DIBs
383 int height
= sizeLimit
/bytePerLine
;
384 if( height
>= bmpHeight
)
388 numDIB
= bmpHeight
/ height
;
389 hRemain
= bmpHeight
% height
;
390 if( hRemain
>0 ) numDIB
++;
393 // set bitmap parameters
394 wxCHECK_MSG( image
.Ok(), FALSE
, wxT("invalid image") );
396 SetHeight( bmpHeight
);
397 if (depth
== -1) depth
= wxDisplayDepth();
400 // create a DIB header
401 int headersize
= sizeof(BITMAPINFOHEADER
);
402 BITMAPINFO
*lpDIBh
= (BITMAPINFO
*) malloc( headersize
);
403 wxCHECK_MSG( lpDIBh
, FALSE
, wxT("could not allocate memory for DIB header") );
404 // Fill in the DIB header
405 lpDIBh
->bmiHeader
.biSize
= headersize
;
406 lpDIBh
->bmiHeader
.biWidth
= (DWORD
)width
;
407 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
408 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
409 // the general formula for biSizeImage:
410 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
411 lpDIBh
->bmiHeader
.biPlanes
= 1;
412 lpDIBh
->bmiHeader
.biBitCount
= 24;
413 lpDIBh
->bmiHeader
.biCompression
= BI_RGB
;
414 lpDIBh
->bmiHeader
.biClrUsed
= 0;
415 // These seem not really needed for our purpose here.
416 lpDIBh
->bmiHeader
.biClrImportant
= 0;
417 lpDIBh
->bmiHeader
.biXPelsPerMeter
= 0;
418 lpDIBh
->bmiHeader
.biYPelsPerMeter
= 0;
419 // memory for DIB data
420 unsigned char *lpBits
;
421 lpBits
= (unsigned char *)malloc( lpDIBh
->bmiHeader
.biSizeImage
);
424 wxFAIL_MSG( wxT("could not allocate memory for DIB") );
429 // create and set the device-dependent bitmap
430 HDC hdc
= ::GetDC(NULL
);
431 HDC memdc
= ::CreateCompatibleDC( hdc
);
433 hbitmap
= ::CreateCompatibleBitmap( hdc
, width
, bmpHeight
);
434 ::SelectObject( memdc
, hbitmap
);
436 HPALETTE hOldPalette
= 0;
437 if (image
.GetPalette().Ok())
439 hOldPalette
= ::SelectPalette(memdc
, (HPALETTE
) image
.GetPalette().GetHPALETTE(), FALSE
);
440 ::RealizePalette(memdc
);
443 // copy image data into DIB data and then into DDB (in a loop)
444 unsigned char *data
= image
.GetData();
447 unsigned char *ptdata
= data
;
448 unsigned char *ptbits
;
450 for( n
=0; n
<numDIB
; n
++ )
452 if( numDIB
> 1 && n
== numDIB
-1 && hRemain
> 0 )
454 // redefine height and size of the (possibly) last smaller DIB
455 // memory is not reallocated
457 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
458 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
462 for( j
=0; j
<height
; j
++ )
464 for( i
=0; i
<width
; i
++ )
466 *(ptbits
++) = *(ptdata
+2);
467 *(ptbits
++) = *(ptdata
+1);
468 *(ptbits
++) = *(ptdata
);
471 for( i
=0; i
< padding
; i
++ ) *(ptbits
++) = 0;
473 ::StretchDIBits( memdc
, 0, origin
, width
, height
,\
474 0, 0, width
, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
, SRCCOPY
);
476 // if numDIB = 1, lines below can also be used
477 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
478 // The above line is equivalent to the following two lines.
479 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
480 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
481 // or the following lines
482 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
483 // HDC memdc = ::CreateCompatibleDC( hdc );
484 // ::SelectObject( memdc, hbitmap);
485 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
486 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
487 // ::SelectObject( memdc, 0 );
488 // ::DeleteDC( memdc );
490 SetHBITMAP( (WXHBITMAP
) hbitmap
);
493 SelectPalette(memdc
, hOldPalette
, FALSE
);
495 // similarly, created an mono-bitmap for the possible mask
496 if( image
.HasMask() )
498 hbitmap
= ::CreateBitmap( (WORD
)width
, (WORD
)bmpHeight
, 1, 1, NULL
);
499 HGDIOBJ hbmpOld
= ::SelectObject( memdc
, hbitmap
);
500 if( numDIB
== 1 ) height
= bmpHeight
;
501 else height
= sizeLimit
/bytePerLine
;
502 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
503 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
505 unsigned char r
= image
.GetMaskRed();
506 unsigned char g
= image
.GetMaskGreen();
507 unsigned char b
= image
.GetMaskBlue();
508 unsigned char zero
= 0, one
= 255;
510 for( n
=0; n
<numDIB
; n
++ )
512 if( numDIB
> 1 && n
== numDIB
- 1 && hRemain
> 0 )
514 // redefine height and size of the (possibly) last smaller DIB
515 // memory is not reallocated
517 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
518 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
521 for( int j
=0; j
<height
; j
++ )
523 for(i
=0; i
<width
; i
++ )
525 // was causing a code gen bug in cw : if( ( cr !=r) || (cg!=g) || (cb!=b) )
526 unsigned char cr
= (*(ptdata
++)) ;
527 unsigned char cg
= (*(ptdata
++)) ;
528 unsigned char cb
= (*(ptdata
++)) ;
530 if( ( cr
!=r
) || (cg
!=g
) || (cb
!=b
) )
543 for( i
=0; i
< padding
; i
++ ) *(ptbits
++) = zero
;
545 ::StretchDIBits( memdc
, 0, origin
, width
, height
,\
546 0, 0, width
, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
, SRCCOPY
);
549 // create a wxMask object
550 wxMask
*mask
= new wxMask();
551 mask
->SetMaskBitmap( (WXHBITMAP
) hbitmap
);
553 // It will be deleted when the wxBitmap object is deleted (as of 01/1999)
554 /* The following can also be used but is slow to run
555 wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
556 wxMask *mask = new wxMask( *this, colour );
560 ::SelectObject( memdc
, hbmpOld
);
563 // free allocated resources
565 ::ReleaseDC(NULL
, hdc
);
569 #if WXWIN_COMPATIBILITY_2
570 // check the wxBitmap object
571 GetBitmapData()->SetOk();
572 #endif // WXWIN_COMPATIBILITY_2
574 if (wxTheBitmapList
) wxTheBitmapList
->AddBitmap(this);
579 wxImage
wxBitmap::ConvertToImage() const
583 wxCHECK_MSG( Ok(), wxNullImage
, wxT("invalid bitmap") );
585 // create an wxImage object
586 int width
= GetWidth();
587 int height
= GetHeight();
588 image
.Create( width
, height
);
589 unsigned char *data
= image
.GetData();
592 wxFAIL_MSG( wxT("could not allocate data for image") );
596 // calc the number of bytes per scanline and padding in the DIB
597 int bytePerLine
= width
*3;
598 int sizeDWORD
= sizeof( DWORD
);
599 int lineBoundary
= bytePerLine
% sizeDWORD
;
601 if( lineBoundary
> 0 )
603 padding
= sizeDWORD
- lineBoundary
;
604 bytePerLine
+= padding
;
607 // create a DIB header
608 int headersize
= sizeof(BITMAPINFOHEADER
);
609 BITMAPINFO
*lpDIBh
= (BITMAPINFO
*) malloc( headersize
);
612 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
616 // Fill in the DIB header
617 lpDIBh
->bmiHeader
.biSize
= headersize
;
618 lpDIBh
->bmiHeader
.biWidth
= width
;
619 lpDIBh
->bmiHeader
.biHeight
= -height
;
620 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
* height
;
621 lpDIBh
->bmiHeader
.biPlanes
= 1;
622 lpDIBh
->bmiHeader
.biBitCount
= 24;
623 lpDIBh
->bmiHeader
.biCompression
= BI_RGB
;
624 lpDIBh
->bmiHeader
.biClrUsed
= 0;
625 // These seem not really needed for our purpose here.
626 lpDIBh
->bmiHeader
.biClrImportant
= 0;
627 lpDIBh
->bmiHeader
.biXPelsPerMeter
= 0;
628 lpDIBh
->bmiHeader
.biYPelsPerMeter
= 0;
629 // memory for DIB data
630 unsigned char *lpBits
;
631 lpBits
= (unsigned char *) malloc( lpDIBh
->bmiHeader
.biSizeImage
);
634 wxFAIL_MSG( wxT("could not allocate data for DIB") );
640 // copy data from the device-dependent bitmap to the DIB
641 HDC hdc
= ::GetDC(NULL
);
643 hbitmap
= (HBITMAP
) GetHBITMAP();
644 ::GetDIBits( hdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
646 // copy DIB data into the wxImage object
648 unsigned char *ptdata
= data
;
649 unsigned char *ptbits
= lpBits
;
650 for( i
=0; i
<height
; i
++ )
652 for( j
=0; j
<width
; j
++ )
654 *(ptdata
++) = *(ptbits
+2);
655 *(ptdata
++) = *(ptbits
+1);
656 *(ptdata
++) = *(ptbits
);
662 // similarly, set data according to the possible mask bitmap
663 if( GetMask() && GetMask()->GetMaskBitmap() )
665 hbitmap
= (HBITMAP
) GetMask()->GetMaskBitmap();
666 // memory DC created, color set, data copied, and memory DC deleted
667 HDC memdc
= ::CreateCompatibleDC( hdc
);
668 ::SetTextColor( memdc
, RGB( 0, 0, 0 ) );
669 ::SetBkColor( memdc
, RGB( 255, 255, 255 ) );
670 ::GetDIBits( memdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
672 // background color set to RGB(16,16,16) in consistent with wxGTK
673 unsigned char r
=16, g
=16, b
=16;
676 for( i
=0; i
<height
; i
++ )
678 for( j
=0; j
<width
; j
++ )
692 image
.SetMaskColour( r
, g
, b
);
693 image
.SetMask( TRUE
);
697 image
.SetMask( FALSE
);
699 // free allocated resources
700 ::ReleaseDC(NULL
, hdc
);
707 bool wxBitmap::LoadFile(const wxString
& filename
, long type
)
711 wxBitmapHandler
*handler
= wxDynamicCast(FindHandler(type
), wxBitmapHandler
);
715 m_refData
= new wxBitmapRefData
;
717 return handler
->LoadFile(this, filename
, type
, -1, -1);
722 if ( !image
.LoadFile( filename
, type
) || !image
.Ok() )
725 *this = image
.ConvertToBitmap();
731 bool wxBitmap::Create(void *data
, long type
, int width
, int height
, int depth
)
735 wxBitmapHandler
*handler
= wxDynamicCast(FindHandler(type
), wxBitmapHandler
);
739 wxLogDebug(wxT("Failed to create bitmap: no bitmap handler for type %d defined."), type
);
744 m_refData
= new wxBitmapRefData
;
746 return handler
->Create(this, data
, type
, width
, height
, depth
);
749 bool wxBitmap::SaveFile(const wxString
& filename
, int type
, const wxPalette
*palette
)
751 wxBitmapHandler
*handler
= wxDynamicCast(FindHandler(type
), wxBitmapHandler
);
755 return handler
->SaveFile(this, filename
, type
, palette
);
759 // FIXME what about palette? shouldn't we use it?
760 wxImage
image( *this );
764 return image
.SaveFile( filename
, type
);
768 // ----------------------------------------------------------------------------
769 // sub bitmap extraction
770 // ----------------------------------------------------------------------------
772 wxBitmap
wxBitmap::GetSubBitmap( const wxRect
& rect
) const
775 (rect
.x
>= 0) && (rect
.y
>= 0) &&
776 (rect
.x
+rect
.width
<= GetWidth()) &&
777 (rect
.y
+rect
.height
<= GetHeight()),
778 wxNullBitmap
, wxT("Invalid bitmap or bitmap region") );
780 wxBitmap
ret( rect
.width
, rect
.height
, GetDepth() );
781 wxASSERT_MSG( ret
.Ok(), wxT("GetSubBitmap error") );
784 HDC dcSrc
= ::CreateCompatibleDC(NULL
);
785 HDC dcDst
= ::CreateCompatibleDC(NULL
);
786 SelectObject(dcSrc
, (HBITMAP
) GetHBITMAP());
787 SelectObject(dcDst
, (HBITMAP
) ret
.GetHBITMAP());
788 BitBlt(dcDst
, 0, 0, rect
.width
, rect
.height
, dcSrc
, rect
.x
, rect
.y
, SRCCOPY
);
790 // copy mask if there is one
793 HBITMAP hbmpMask
= ::CreateBitmap(rect
.width
, rect
.height
, 1, 1, 0);
795 SelectObject(dcSrc
, (HBITMAP
) GetMask()->GetMaskBitmap());
796 SelectObject(dcDst
, (HBITMAP
) hbmpMask
);
797 BitBlt(dcDst
, 0, 0, rect
.width
, rect
.height
, dcSrc
, rect
.x
, rect
.y
, SRCCOPY
);
799 wxMask
*mask
= new wxMask((WXHBITMAP
) hbmpMask
);
803 SelectObject(dcDst
, NULL
);
804 SelectObject(dcSrc
, NULL
);
811 // ----------------------------------------------------------------------------
812 // wxBitmap accessors
813 // ----------------------------------------------------------------------------
815 void wxBitmap::SetQuality(int q
)
819 GetBitmapData()->m_quality
= q
;
822 #if WXWIN_COMPATIBILITY_2
823 void wxBitmap::SetOk(bool isOk
)
827 GetBitmapData()->m_ok
= isOk
;
829 #endif // WXWIN_COMPATIBILITY_2
831 void wxBitmap::SetPalette(const wxPalette
& palette
)
835 GetBitmapData()->m_bitmapPalette
= palette
;
838 void wxBitmap::SetMask(wxMask
*mask
)
842 GetBitmapData()->m_bitmapMask
= mask
;
845 // Creates a bitmap that matches the device context, from
846 // an arbitray bitmap. At present, the original bitmap must have an
847 // associated palette. TODO: use a default palette if no palette exists.
848 // Contributed by Frederic Villeneuve <frederic.villeneuve@natinst.com>
849 wxBitmap
wxBitmap::GetBitmapForDC(wxDC
& dc
) const
852 wxBitmap
tmpBitmap(GetWidth(), GetHeight(), dc
.GetDepth());
853 HPALETTE hPal
= (HPALETTE
) NULL
;
855 void *lpBits
= (void*) NULL
;
857 if( GetPalette() && GetPalette()->Ok() )
859 tmpBitmap
.SetPalette(*GetPalette());
860 memDC
.SelectObject(tmpBitmap
);
861 memDC
.SetPalette(*GetPalette());
862 hPal
= (HPALETTE
)GetPalette()->GetHPALETTE();
866 hPal
= (HPALETTE
) ::GetStockObject(DEFAULT_PALETTE
);
868 palette
.SetHPALETTE( (WXHPALETTE
)hPal
);
869 tmpBitmap
.SetPalette( palette
);
870 memDC
.SelectObject(tmpBitmap
);
871 memDC
.SetPalette( palette
);
874 // set the height negative because in a DIB the order of the lines is
876 if ( !wxCreateDIB(GetWidth(), -GetHeight(), GetDepth(), hPal
, &lpDib
) )
881 lpBits
= malloc(lpDib
->bmiHeader
.biSizeImage
);
883 ::GetBitmapBits(GetHbitmap(), lpDib
->bmiHeader
.biSizeImage
, lpBits
);
885 ::SetDIBitsToDevice(GetHdcOf(memDC
), 0, 0,
886 GetWidth(), GetHeight(),
887 0, 0, 0, GetHeight(),
888 lpBits
, lpDib
, DIB_RGB_COLORS
);
897 // ----------------------------------------------------------------------------
899 // ----------------------------------------------------------------------------
906 // Construct a mask from a bitmap and a colour indicating
907 // the transparent area
908 wxMask::wxMask(const wxBitmap
& bitmap
, const wxColour
& colour
)
911 Create(bitmap
, colour
);
914 // Construct a mask from a bitmap and a palette index indicating
915 // the transparent area
916 wxMask::wxMask(const wxBitmap
& bitmap
, int paletteIndex
)
919 Create(bitmap
, paletteIndex
);
922 // Construct a mask from a mono bitmap (copies the bitmap).
923 wxMask::wxMask(const wxBitmap
& bitmap
)
932 ::DeleteObject((HBITMAP
) m_maskBitmap
);
935 // Create a mask from a mono bitmap (copies the bitmap).
936 bool wxMask::Create(const wxBitmap
& bitmap
)
938 wxCHECK_MSG( bitmap
.Ok() && bitmap
.GetDepth() == 1, FALSE
,
939 _T("can't create mask from invalid or not monochrome bitmap") );
943 ::DeleteObject((HBITMAP
) m_maskBitmap
);
947 m_maskBitmap
= (WXHBITMAP
) CreateBitmap(
952 HDC srcDC
= CreateCompatibleDC(0);
953 SelectObject(srcDC
, (HBITMAP
) bitmap
.GetHBITMAP());
954 HDC destDC
= CreateCompatibleDC(0);
955 SelectObject(destDC
, (HBITMAP
) m_maskBitmap
);
956 BitBlt(destDC
, 0, 0, bitmap
.GetWidth(), bitmap
.GetHeight(), srcDC
, 0, 0, SRCCOPY
);
957 SelectObject(srcDC
, 0);
959 SelectObject(destDC
, 0);
964 // Create a mask from a bitmap and a palette index indicating
965 // the transparent area
966 bool wxMask::Create(const wxBitmap
& bitmap
, int paletteIndex
)
970 ::DeleteObject((HBITMAP
) m_maskBitmap
);
973 if (bitmap
.Ok() && bitmap
.GetPalette()->Ok())
975 unsigned char red
, green
, blue
;
976 if (bitmap
.GetPalette()->GetRGB(paletteIndex
, &red
, &green
, &blue
))
978 wxColour
transparentColour(red
, green
, blue
);
979 return Create(bitmap
, transparentColour
);
985 // Create a mask from a bitmap and a colour indicating
986 // the transparent area
987 bool wxMask::Create(const wxBitmap
& bitmap
, const wxColour
& colour
)
989 wxCHECK_MSG( bitmap
.Ok(), FALSE
, _T("invalid bitmap in wxMask::Create") );
993 ::DeleteObject((HBITMAP
) m_maskBitmap
);
997 int width
= bitmap
.GetWidth(),
998 height
= bitmap
.GetHeight();
1000 // scan the bitmap for the transparent colour and set the corresponding
1001 // pixels in the mask to BLACK and the rest to WHITE
1002 COLORREF maskColour
= wxColourToRGB(colour
);
1003 m_maskBitmap
= (WXHBITMAP
)::CreateBitmap(width
, height
, 1, 1, 0);
1005 HDC srcDC
= ::CreateCompatibleDC(NULL
);
1006 HDC destDC
= ::CreateCompatibleDC(NULL
);
1007 if ( !srcDC
|| !destDC
)
1009 wxLogLastError(wxT("CreateCompatibleDC"));
1014 HGDIOBJ hbmpSrcOld
= ::SelectObject(srcDC
, GetHbitmapOf(bitmap
));
1017 wxLogLastError(wxT("SelectObject"));
1022 HGDIOBJ hbmpDstOld
= ::SelectObject(destDC
, (HBITMAP
)m_maskBitmap
);
1025 wxLogLastError(wxT("SelectObject"));
1030 // this is not very efficient, but I can't think of a better way of doing
1032 for ( int w
= 0; ok
&& (w
< width
); w
++ )
1034 for ( int h
= 0; ok
&& (h
< height
); h
++ )
1036 COLORREF col
= GetPixel(srcDC
, w
, h
);
1037 if ( col
== CLR_INVALID
)
1039 wxLogLastError(wxT("GetPixel"));
1041 // doesn't make sense to continue
1047 if ( col
== maskColour
)
1049 ::SetPixel(destDC
, w
, h
, RGB(0, 0, 0));
1053 ::SetPixel(destDC
, w
, h
, RGB(255, 255, 255));
1058 ::SelectObject(srcDC
, hbmpSrcOld
);
1060 ::SelectObject(destDC
, hbmpDstOld
);
1066 // ----------------------------------------------------------------------------
1068 // ----------------------------------------------------------------------------
1070 bool wxBitmapHandler::Create(wxGDIImage
*image
,
1073 int width
, int height
, int depth
)
1075 wxBitmap
*bitmap
= wxDynamicCast(image
, wxBitmap
);
1077 return bitmap
? Create(bitmap
, data
, flags
, width
, height
, depth
) : FALSE
;
1080 bool wxBitmapHandler::Load(wxGDIImage
*image
,
1081 const wxString
& name
,
1083 int width
, int height
)
1085 wxBitmap
*bitmap
= wxDynamicCast(image
, wxBitmap
);
1087 return bitmap
? LoadFile(bitmap
, name
, flags
, width
, height
) : FALSE
;
1090 bool wxBitmapHandler::Save(wxGDIImage
*image
,
1091 const wxString
& name
,
1094 wxBitmap
*bitmap
= wxDynamicCast(image
, wxBitmap
);
1096 return bitmap
? SaveFile(bitmap
, name
, type
) : FALSE
;
1099 bool wxBitmapHandler::Create(wxBitmap
*WXUNUSED(bitmap
),
1100 void *WXUNUSED(data
),
1101 long WXUNUSED(type
),
1102 int WXUNUSED(width
),
1103 int WXUNUSED(height
),
1104 int WXUNUSED(depth
))
1109 bool wxBitmapHandler::LoadFile(wxBitmap
*WXUNUSED(bitmap
),
1110 const wxString
& WXUNUSED(name
),
1111 long WXUNUSED(type
),
1112 int WXUNUSED(desiredWidth
),
1113 int WXUNUSED(desiredHeight
))
1118 bool wxBitmapHandler::SaveFile(wxBitmap
*WXUNUSED(bitmap
),
1119 const wxString
& WXUNUSED(name
),
1121 const wxPalette
*WXUNUSED(palette
))
1126 // ----------------------------------------------------------------------------
1128 // ----------------------------------------------------------------------------
1130 bool wxCreateDIB(long xSize
, long ySize
, long bitsPerPixel
,
1131 HPALETTE hPal
, LPBITMAPINFO
* lpDIBHeader
)
1133 unsigned long i
, headerSize
;
1134 LPBITMAPINFO lpDIBheader
= NULL
;
1135 LPPALETTEENTRY lpPe
= NULL
;
1138 // Allocate space for a DIB header
1139 headerSize
= (sizeof(BITMAPINFOHEADER
) + (256 * sizeof(PALETTEENTRY
)));
1140 lpDIBheader
= (BITMAPINFO
*) malloc(headerSize
);
1141 lpPe
= (PALETTEENTRY
*)((BYTE
*)lpDIBheader
+ sizeof(BITMAPINFOHEADER
));
1143 GetPaletteEntries(hPal
, 0, 256, lpPe
);
1145 memset(lpDIBheader
, 0x00, sizeof(BITMAPINFOHEADER
));
1147 // Fill in the static parts of the DIB header
1148 lpDIBheader
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
1149 lpDIBheader
->bmiHeader
.biWidth
= xSize
;
1150 lpDIBheader
->bmiHeader
.biHeight
= ySize
;
1151 lpDIBheader
->bmiHeader
.biPlanes
= 1;
1153 // this value must be 1, 4, 8 or 24 so PixelDepth can only be
1154 lpDIBheader
->bmiHeader
.biBitCount
= (WORD
)(bitsPerPixel
);
1155 lpDIBheader
->bmiHeader
.biCompression
= BI_RGB
;
1156 lpDIBheader
->bmiHeader
.biSizeImage
= xSize
* abs(ySize
) * bitsPerPixel
>> 3;
1157 lpDIBheader
->bmiHeader
.biClrUsed
= 256;
1160 // Initialize the DIB palette
1161 for (i
= 0; i
< 256; i
++) {
1162 lpDIBheader
->bmiColors
[i
].rgbReserved
= lpPe
[i
].peFlags
;
1163 lpDIBheader
->bmiColors
[i
].rgbRed
= lpPe
[i
].peRed
;
1164 lpDIBheader
->bmiColors
[i
].rgbGreen
= lpPe
[i
].peGreen
;
1165 lpDIBheader
->bmiColors
[i
].rgbBlue
= lpPe
[i
].peBlue
;
1168 *lpDIBHeader
= lpDIBheader
;
1173 void wxFreeDIB(LPBITMAPINFO lpDIBHeader
)
1178 // ----------------------------------------------------------------------------
1179 // other helper functions
1180 // ----------------------------------------------------------------------------
1182 extern HBITMAP
wxInvertMask(HBITMAP hbmpMask
, int w
, int h
)
1184 wxCHECK_MSG( hbmpMask
, 0, _T("invalid bitmap in wxInvertMask") );
1186 // get width/height from the bitmap if not given
1190 ::GetObject(hbmpMask
, sizeof(BITMAP
), (LPVOID
)&bm
);
1195 HDC hdcSrc
= ::CreateCompatibleDC(NULL
);
1196 HDC hdcDst
= ::CreateCompatibleDC(NULL
);
1197 if ( !hdcSrc
|| !hdcDst
)
1199 wxLogLastError(wxT("CreateCompatibleDC"));
1202 HBITMAP hbmpInvMask
= ::CreateBitmap(w
, h
, 1, 1, 0);
1205 wxLogLastError(wxT("CreateBitmap"));
1208 ::SelectObject(hdcSrc
, hbmpMask
);
1209 ::SelectObject(hdcDst
, hbmpInvMask
);
1210 if ( !::BitBlt(hdcDst
, 0, 0, w
, h
,
1214 wxLogLastError(wxT("BitBlt"));