]>
git.saurik.com Git - wxWidgets.git/blob - src/msw/bitmap.cpp
4f60c09474625650595524649c82711d1a84afd1
   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 #if !defined(__WXMICROWIN__) 
  47 #include "wx/msw/dib.h" 
  51 #include "wx/xpmdecod.h" 
  53 // missing from mingw32 header 
  55     #define CLR_INVALID ((COLORREF)-1) 
  56 #endif // no CLR_INVALID 
  58 // ---------------------------------------------------------------------------- 
  60 // ---------------------------------------------------------------------------- 
  62 IMPLEMENT_DYNAMIC_CLASS(wxBitmap
, wxGDIObject
) 
  63 IMPLEMENT_DYNAMIC_CLASS(wxMask
, wxObject
) 
  65 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler
, wxObject
) 
  67 // ============================================================================ 
  69 // ============================================================================ 
  71 // ---------------------------------------------------------------------------- 
  73 // ---------------------------------------------------------------------------- 
  75 wxBitmapRefData::wxBitmapRefData() 
  78     m_selectedInto 
= NULL
; 
  81     m_hBitmap 
= (WXHBITMAP
) NULL
; 
  84 void wxBitmapRefData::Free() 
  86     wxASSERT_MSG( !m_selectedInto
, 
  87                   wxT("deleting bitmap still selected into wxMemoryDC") ); 
  91         if ( !::DeleteObject((HBITMAP
)m_hBitmap
) ) 
  93             wxLogLastError(wxT("DeleteObject(hbitmap)")); 
 101 // ---------------------------------------------------------------------------- 
 103 // ---------------------------------------------------------------------------- 
 105 // this function should be called from all wxBitmap ctors 
 106 void wxBitmap::Init() 
 108     // m_refData = NULL; done in the base class ctor 
 110     if ( wxTheBitmapList 
) 
 111         wxTheBitmapList
->AddBitmap(this); 
 116 bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage
& icon
) 
 118 #ifndef __WXMICROWIN__ 
 119     // it may be either HICON or HCURSOR 
 120     HICON hicon 
= (HICON
)icon
.GetHandle(); 
 123     if ( !::GetIconInfo(hicon
, &iconInfo
) ) 
 125         wxLogLastError(wxT("GetIconInfo")); 
 130     wxBitmapRefData 
*refData 
= new wxBitmapRefData
; 
 133     int w 
= icon
.GetWidth(), 
 134         h 
= icon
.GetHeight(); 
 136     refData
->m_width 
= w
; 
 137     refData
->m_height 
= h
; 
 138     refData
->m_depth 
= wxDisplayDepth(); 
 140     refData
->m_hBitmap 
= (WXHBITMAP
)iconInfo
.hbmColor
; 
 142     // the mask returned by GetIconInfo() is inversed compared to the usual 
 144     refData
->m_bitmapMask 
= new wxMask((WXHBITMAP
) 
 145                                         wxInvertMask(iconInfo
.hbmMask
, w
, h
)); 
 148     // delete the old one now as we don't need it any more 
 149     ::DeleteObject(iconInfo
.hbmMask
); 
 151 #if WXWIN_COMPATIBILITY_2 
 152     refData
->m_ok 
= TRUE
; 
 153 #endif // WXWIN_COMPATIBILITY_2 
 163 bool wxBitmap::CopyFromCursor(const wxCursor
& cursor
) 
 171     wxFAIL_MSG( _T("don't know how to convert cursor to bitmap") ); 
 175     return CopyFromIconOrCursor(cursor
); 
 179 bool wxBitmap::CopyFromIcon(const wxIcon
& icon
) 
 186     // GetIconInfo() doesn't exist under Win16 and I don't know any other way 
 187     // to create a bitmap from icon there - but using this way we won't have 
 190     int width 
= icon
.GetWidth(), 
 191         height 
= icon
.GetHeight(); 
 193     // copy the icon to the bitmap 
 195     HDC hdc 
= ::CreateCompatibleDC(hdcScreen
); 
 196     HBITMAP hbitmap 
= ::CreateCompatibleBitmap(hdcScreen
, width
, height
); 
 197     HBITMAP hbmpOld 
= (HBITMAP
)::SelectObject(hdc
, hbitmap
); 
 199     ::DrawIcon(hdc
, 0, 0, GetHiconOf(icon
)); 
 201     ::SelectObject(hdc
, hbmpOld
); 
 204     wxBitmapRefData 
*refData 
= new wxBitmapRefData
; 
 207     refData
->m_width 
= width
; 
 208     refData
->m_height 
= height
; 
 209     refData
->m_depth 
= wxDisplayDepth(); 
 211     refData
->m_hBitmap 
= (WXHBITMAP
)hbitmap
; 
 213 #if WXWIN_COMPATIBILITY_2 
 214     refData
->m_ok 
= TRUE
; 
 215 #endif // WXWIN_COMPATIBILITY_2 
 219     return CopyFromIconOrCursor(icon
); 
 220 #endif // Win16/Win32 
 223 wxBitmap::~wxBitmap() 
 226         wxTheBitmapList
->DeleteObject(this); 
 229 wxBitmap::wxBitmap(const char bits
[], int width
, int height
, int depth
) 
 233 #ifndef __WXMICROWIN__ 
 234     wxBitmapRefData 
*refData 
= new wxBitmapRefData
; 
 237     refData
->m_width 
= width
; 
 238     refData
->m_height 
= height
; 
 239     refData
->m_depth 
= depth
; 
 240     refData
->m_numColors 
= 0; 
 241     refData
->m_selectedInto 
= NULL
; 
 246         // we assume that it is in XBM format which is not quite the same as 
 247         // the format CreateBitmap() wants because the order of bytes in the 
 249         const size_t bytesPerLine 
= (width 
+ 7) / 8; 
 250         const size_t padding 
= bytesPerLine 
% 2; 
 251         const size_t len 
= height 
* ( padding 
+ bytesPerLine 
); 
 252         data 
= (char *)malloc(len
); 
 253         const char *src 
= bits
; 
 256         for ( int rows 
= 0; rows 
< height
; rows
++ ) 
 258             for ( size_t cols 
= 0; cols 
< bytesPerLine
; cols
++ ) 
 260                 unsigned char val 
= *src
++; 
 261                 unsigned char reversed 
= 0; 
 263                 for ( int bits 
= 0; bits 
< 8; bits
++) 
 266                     reversed 
|= (val 
& 0x01); 
 278         // bits should already be in Windows standard format 
 279         data 
= (char *)bits
;    // const_cast is harmless 
 282     HBITMAP hbmp 
= ::CreateBitmap(width
, height
, 1, depth
, data
); 
 285         wxLogLastError(wxT("CreateBitmap")); 
 293     SetHBITMAP((WXHBITMAP
)hbmp
); 
 297 // Create from XPM data 
 298 bool wxBitmap::CreateFromXpm(const char **data
) 
 300 #if wxUSE_IMAGE && wxUSE_XPM 
 303     wxCHECK_MSG( data 
!= NULL
, FALSE
, wxT("invalid bitmap data") ) 
 305     wxXPMDecoder decoder
; 
 306     wxImage img 
= decoder
.ReadData(data
); 
 307     wxCHECK_MSG( img
.Ok(), FALSE
, wxT("invalid bitmap data") ) 
 309     *this = wxBitmap(img
); 
 316 wxBitmap::wxBitmap(int w
, int h
, int d
) 
 320     (void)Create(w
, h
, d
); 
 323 wxBitmap::wxBitmap(void *data
, long type
, int width
, int height
, int depth
) 
 327     (void)Create(data
, type
, width
, height
, depth
); 
 330 wxBitmap::wxBitmap(const wxString
& filename
, wxBitmapType type
) 
 334     LoadFile(filename
, (int)type
); 
 337 bool wxBitmap::Create(int w
, int h
, int d
) 
 339 #ifndef __WXMICROWIN__ 
 342     m_refData 
= new wxBitmapRefData
; 
 344     GetBitmapData()->m_width 
= w
; 
 345     GetBitmapData()->m_height 
= h
; 
 346     GetBitmapData()->m_depth 
= d
; 
 352         hbmp 
= ::CreateBitmap(w
, h
, 1, d
, NULL
); 
 355             wxLogLastError(wxT("CreateBitmap")); 
 361         hbmp 
= ::CreateCompatibleBitmap(dc
, w
, h
); 
 364             wxLogLastError(wxT("CreateCompatibleBitmap")); 
 367         GetBitmapData()->m_depth 
= wxDisplayDepth(); 
 370     SetHBITMAP((WXHBITMAP
)hbmp
); 
 372 #if WXWIN_COMPATIBILITY_2 
 373     GetBitmapData()->m_ok 
= hbmp 
!= 0; 
 374 #endif // WXWIN_COMPATIBILITY_2 
 381 // ---------------------------------------------------------------------------- 
 382 // wxImage to/from conversions 
 383 // ---------------------------------------------------------------------------- 
 387 bool wxBitmap::CreateFromImage( const wxImage
& image
, int depth 
) 
 389 #ifdef __WXMICROWIN__ 
 393     wxCHECK_MSG( image
.Ok(), FALSE
, wxT("invalid image") ) 
 395     m_refData 
= new wxBitmapRefData(); 
 397     // sizeLimit is the MS upper limit for the DIB size 
 399     int sizeLimit 
= 1024*768*3; 
 401     int sizeLimit 
= 0x7fff ; 
 404     // width and height of the device-dependent bitmap 
 405     int width 
= image
.GetWidth(); 
 406     int bmpHeight 
= image
.GetHeight(); 
 408     // calc the number of bytes per scanline and padding 
 409     int bytePerLine 
= width
*3; 
 410     int sizeDWORD 
= sizeof( DWORD 
); 
 411     int lineBoundary 
= bytePerLine 
% sizeDWORD
; 
 413     if( lineBoundary 
> 0 ) 
 415         padding 
= sizeDWORD 
- lineBoundary
; 
 416         bytePerLine 
+= padding
; 
 418     // calc the number of DIBs and heights of DIBs 
 421     int height 
= sizeLimit
/bytePerLine
; 
 422     if( height 
>= bmpHeight 
) 
 426         numDIB 
=  bmpHeight 
/ height
; 
 427         hRemain 
= bmpHeight 
% height
; 
 428         if( hRemain 
>0 )  numDIB
++; 
 431     // set bitmap parameters 
 432     wxCHECK_MSG( image
.Ok(), FALSE
, wxT("invalid image") ); 
 434     SetHeight( bmpHeight 
); 
 435     if (depth 
== -1) depth 
= wxDisplayDepth(); 
 438     // Copy the palette from the source image 
 439     SetPalette(image
.GetPalette()); 
 441     // create a DIB header 
 442     int headersize 
= sizeof(BITMAPINFOHEADER
); 
 443     BITMAPINFO 
*lpDIBh 
= (BITMAPINFO 
*) malloc( headersize 
); 
 444     wxCHECK_MSG( lpDIBh
, FALSE
, wxT("could not allocate memory for DIB header") ); 
 445     // Fill in the DIB header 
 446     lpDIBh
->bmiHeader
.biSize 
= headersize
; 
 447     lpDIBh
->bmiHeader
.biWidth 
= (DWORD
)width
; 
 448     lpDIBh
->bmiHeader
.biHeight 
= (DWORD
)(-height
); 
 449     lpDIBh
->bmiHeader
.biSizeImage 
= bytePerLine
*height
; 
 450     //   the general formula for biSizeImage: 
 451     //      ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height; 
 452     lpDIBh
->bmiHeader
.biPlanes 
= 1; 
 453     lpDIBh
->bmiHeader
.biBitCount 
= 24; 
 454     lpDIBh
->bmiHeader
.biCompression 
= BI_RGB
; 
 455     lpDIBh
->bmiHeader
.biClrUsed 
= 0; 
 456     // These seem not really needed for our purpose here. 
 457     lpDIBh
->bmiHeader
.biClrImportant 
= 0; 
 458     lpDIBh
->bmiHeader
.biXPelsPerMeter 
= 0; 
 459     lpDIBh
->bmiHeader
.biYPelsPerMeter 
= 0; 
 460     // memory for DIB data 
 461     unsigned char *lpBits
; 
 462     lpBits 
= (unsigned char *)malloc( lpDIBh
->bmiHeader
.biSizeImage 
); 
 465         wxFAIL_MSG( wxT("could not allocate memory for DIB") ); 
 470     // create and set the device-dependent bitmap 
 471     HDC hdc 
= ::GetDC(NULL
); 
 472     HDC memdc 
= ::CreateCompatibleDC( hdc 
); 
 474     hbitmap 
= ::CreateCompatibleBitmap( hdc
, width
, bmpHeight 
); 
 475     ::SelectObject( memdc
, hbitmap
); 
 478     HPALETTE hOldPalette 
= 0; 
 479     if (image
.GetPalette().Ok()) 
 481         hOldPalette 
= ::SelectPalette(memdc
, (HPALETTE
) image
.GetPalette().GetHPALETTE(), FALSE
); 
 482         ::RealizePalette(memdc
); 
 484 #endif // wxUSE_PALETTE 
 486     // copy image data into DIB data and then into DDB (in a loop) 
 487     unsigned char *data 
= image
.GetData(); 
 490     unsigned char *ptdata 
= data
; 
 491     unsigned char *ptbits
; 
 493     for( n
=0; n
<numDIB
; n
++ ) 
 495         if( numDIB 
> 1 && n 
== numDIB
-1 && hRemain 
> 0 ) 
 497             // redefine height and size of the (possibly) last smaller DIB 
 498             // memory is not reallocated 
 500             lpDIBh
->bmiHeader
.biHeight 
= (DWORD
)(-height
); 
 501             lpDIBh
->bmiHeader
.biSizeImage 
= bytePerLine
*height
; 
 505         for( j
=0; j
<height
; j
++ ) 
 507             for( i
=0; i
<width
; i
++ ) 
 509                 *(ptbits
++) = *(ptdata
+2); 
 510                 *(ptbits
++) = *(ptdata
+1); 
 511                 *(ptbits
++) = *(ptdata  
); 
 514             for( i
=0; i
< padding
; i
++ )   *(ptbits
++) = 0; 
 516         ::StretchDIBits( memdc
, 0, origin
, width
, height
,\
 
 517             0, 0, width
, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
, SRCCOPY
); 
 519         // if numDIB = 1,  lines below can also be used 
 520         //    hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS ); 
 521         // The above line is equivalent to the following two lines. 
 522         //    hbitmap = ::CreateCompatibleBitmap( hdc, width, height ); 
 523         //    ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS); 
 524         // or the following lines 
 525         //    hbitmap = ::CreateCompatibleBitmap( hdc, width, height ); 
 526         //    HDC memdc = ::CreateCompatibleDC( hdc ); 
 527         //    ::SelectObject( memdc, hbitmap); 
 528         //    ::SetDIBitsToDevice( memdc, 0, 0, width, height, 
 529         //            0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS); 
 530         //    ::SelectObject( memdc, 0 ); 
 531         //    ::DeleteDC( memdc ); 
 533     SetHBITMAP( (WXHBITMAP
) hbitmap 
); 
 537         SelectPalette(memdc
, hOldPalette
, FALSE
); 
 538 #endif // wxUSE_PALETTE 
 540     // similarly, created an mono-bitmap for the possible mask 
 541     if( image
.HasMask() ) 
 543         hbitmap 
= ::CreateBitmap( (WORD
)width
, (WORD
)bmpHeight
, 1, 1, NULL 
); 
 544         HGDIOBJ hbmpOld 
= ::SelectObject( memdc
, hbitmap
); 
 545         if( numDIB 
== 1 )   height 
= bmpHeight
; 
 546         else                height 
= sizeLimit
/bytePerLine
; 
 547         lpDIBh
->bmiHeader
.biHeight 
= (DWORD
)(-height
); 
 548         lpDIBh
->bmiHeader
.biSizeImage 
= bytePerLine
*height
; 
 550         unsigned char r 
= image
.GetMaskRed(); 
 551         unsigned char g 
= image
.GetMaskGreen(); 
 552         unsigned char b 
= image
.GetMaskBlue(); 
 553         unsigned char zero 
= 0, one 
= 255; 
 555         for( n
=0; n
<numDIB
; n
++ ) 
 557             if( numDIB 
> 1 && n 
== numDIB 
- 1 && hRemain 
> 0 ) 
 559                 // redefine height and size of the (possibly) last smaller DIB 
 560                 // memory is not reallocated 
 562                 lpDIBh
->bmiHeader
.biHeight 
= (DWORD
)(-height
); 
 563                 lpDIBh
->bmiHeader
.biSizeImage 
= bytePerLine
*height
; 
 566             for( int j
=0; j
<height
; j
++ ) 
 568                 for(i
=0; i
<width
; i
++ ) 
 570                     // was causing a code gen bug in cw : if( ( cr !=r) || (cg!=g) || (cb!=b) ) 
 571                     unsigned char cr 
= (*(ptdata
++)) ; 
 572                     unsigned char cg 
= (*(ptdata
++)) ; 
 573                     unsigned char cb 
= (*(ptdata
++)) ; 
 575                     if( ( cr 
!=r
) || (cg
!=g
) || (cb
!=b
) ) 
 588                 for( i
=0; i
< padding
; i
++ )   *(ptbits
++) = zero
; 
 590             ::StretchDIBits( memdc
, 0, origin
, width
, height
,\
 
 591                 0, 0, width
, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
, SRCCOPY
); 
 594         // create a wxMask object 
 595         wxMask 
*mask 
= new wxMask(); 
 596         mask
->SetMaskBitmap( (WXHBITMAP
) hbitmap 
); 
 598         // It will be deleted when the wxBitmap object is deleted (as of 01/1999) 
 599         /* The following can also be used but is slow to run 
 600         wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue()); 
 601         wxMask *mask = new wxMask( *this, colour ); 
 605         ::SelectObject( memdc
, hbmpOld 
); 
 608     // free allocated resources 
 610     ::ReleaseDC(NULL
, hdc
); 
 614 #if WXWIN_COMPATIBILITY_2 
 615     // check the wxBitmap object 
 616     GetBitmapData()->SetOk(); 
 617 #endif // WXWIN_COMPATIBILITY_2 
 619     if (wxTheBitmapList
) wxTheBitmapList
->AddBitmap(this); 
 625 wxImage 
wxBitmap::ConvertToImage() const 
 627 #ifdef __WXMICROWIN__ 
 633     wxCHECK_MSG( Ok(), wxNullImage
, wxT("invalid bitmap") ); 
 635     // create an wxImage object 
 636     int width 
= GetWidth(); 
 637     int height 
= GetHeight(); 
 638     image
.Create( width
, height 
); 
 639     unsigned char *data 
= image
.GetData(); 
 642         wxFAIL_MSG( wxT("could not allocate data for image") ); 
 646     // calc the number of bytes per scanline and padding in the DIB 
 647     int bytePerLine 
= width
*3; 
 648     int sizeDWORD 
= sizeof( DWORD 
); 
 649     int lineBoundary 
=  bytePerLine 
% sizeDWORD
; 
 651     if( lineBoundary 
> 0 ) 
 653         padding 
= sizeDWORD 
- lineBoundary
; 
 654         bytePerLine 
+= padding
; 
 657     // create a DIB header 
 658     int headersize 
= sizeof(BITMAPINFOHEADER
); 
 659     BITMAPINFO 
*lpDIBh 
= (BITMAPINFO 
*) malloc( headersize 
); 
 662         wxFAIL_MSG( wxT("could not allocate data for DIB header") ); 
 666     // Fill in the DIB header 
 667     lpDIBh
->bmiHeader
.biSize 
= headersize
; 
 668     lpDIBh
->bmiHeader
.biWidth 
= width
; 
 669     lpDIBh
->bmiHeader
.biHeight 
= -height
; 
 670     lpDIBh
->bmiHeader
.biSizeImage 
= bytePerLine 
* height
; 
 671     lpDIBh
->bmiHeader
.biPlanes 
= 1; 
 672     lpDIBh
->bmiHeader
.biBitCount 
= 24; 
 673     lpDIBh
->bmiHeader
.biCompression 
= BI_RGB
; 
 674     lpDIBh
->bmiHeader
.biClrUsed 
= 0; 
 675     // These seem not really needed for our purpose here. 
 676     lpDIBh
->bmiHeader
.biClrImportant 
= 0; 
 677     lpDIBh
->bmiHeader
.biXPelsPerMeter 
= 0; 
 678     lpDIBh
->bmiHeader
.biYPelsPerMeter 
= 0; 
 679     // memory for DIB data 
 680     unsigned char *lpBits
; 
 681     lpBits 
= (unsigned char *) malloc( lpDIBh
->bmiHeader
.biSizeImage 
); 
 684         wxFAIL_MSG( wxT("could not allocate data for DIB") ); 
 690     // copy data from the device-dependent bitmap to the DIB 
 691     HDC hdc 
= ::GetDC(NULL
); 
 693     hbitmap 
= (HBITMAP
) GetHBITMAP(); 
 694     ::GetDIBits( hdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS 
); 
 696     // copy DIB data into the wxImage object 
 698     unsigned char *ptdata 
= data
; 
 699     unsigned char *ptbits 
= lpBits
; 
 700     for( i
=0; i
<height
; i
++ ) 
 702         for( j
=0; j
<width
; j
++ ) 
 704             *(ptdata
++) = *(ptbits
+2); 
 705             *(ptdata
++) = *(ptbits
+1); 
 706             *(ptdata
++) = *(ptbits  
); 
 712     // similarly, set data according to the possible mask bitmap 
 713     if( GetMask() && GetMask()->GetMaskBitmap() ) 
 715         hbitmap 
= (HBITMAP
) GetMask()->GetMaskBitmap(); 
 716         // memory DC created, color set, data copied, and memory DC deleted 
 717         HDC memdc 
= ::CreateCompatibleDC( hdc 
); 
 718         ::SetTextColor( memdc
, RGB( 0, 0, 0 ) ); 
 719         ::SetBkColor( memdc
, RGB( 255, 255, 255 ) ); 
 720         ::GetDIBits( memdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS 
); 
 722         // background color set to RGB(16,16,16) in consistent with wxGTK 
 723         unsigned char r
=16, g
=16, b
=16; 
 726         for( i
=0; i
<height
; i
++ ) 
 728             for( j
=0; j
<width
; j
++ ) 
 742         image
.SetMaskColour( r
, g
, b 
); 
 743         image
.SetMask( TRUE 
); 
 747         image
.SetMask( FALSE 
); 
 749     // free allocated resources 
 750     ::ReleaseDC(NULL
, hdc
); 
 758 #endif // wxUSE_IMAGE 
 760 bool wxBitmap::LoadFile(const wxString
& filename
, long type
) 
 764     wxBitmapHandler 
*handler 
= wxDynamicCast(FindHandler(type
), wxBitmapHandler
); 
 768         m_refData 
= new wxBitmapRefData
; 
 770         return handler
->LoadFile(this, filename
, type
, -1, -1); 
 776         if ( image
.LoadFile( filename
, type 
) && image
.Ok() ) 
 778             *this = image
.ConvertToBitmap(); 
 783 #endif // wxUSE_IMAGE 
 788 bool wxBitmap::Create(void *data
, long type
, int width
, int height
, int depth
) 
 792     wxBitmapHandler 
*handler 
= wxDynamicCast(FindHandler(type
), wxBitmapHandler
); 
 796         wxLogDebug(wxT("Failed to create bitmap: no bitmap handler for type %d defined."), type
); 
 801     m_refData 
= new wxBitmapRefData
; 
 803     return handler
->Create(this, data
, type
, width
, height
, depth
); 
 806 bool wxBitmap::SaveFile(const wxString
& filename
, 
 808                         const wxPalette 
*palette
) 
 810     wxBitmapHandler 
*handler 
= wxDynamicCast(FindHandler(type
), wxBitmapHandler
); 
 814         return handler
->SaveFile(this, filename
, type
, palette
); 
 819         // FIXME what about palette? shouldn't we use it? 
 820         wxImage 
image( *this ); 
 823             return image
.SaveFile(filename
, type
); 
 826 #endif // wxUSE_IMAGE 
 831 // ---------------------------------------------------------------------------- 
 832 // sub bitmap extraction 
 833 // ---------------------------------------------------------------------------- 
 835 wxBitmap 
wxBitmap::GetSubBitmap( const wxRect
& rect
) const 
 837 #ifndef __WXMICROWIN__ 
 839                  (rect
.x 
>= 0) && (rect
.y 
>= 0) && 
 840                  (rect
.x
+rect
.width 
<= GetWidth()) && 
 841                  (rect
.y
+rect
.height 
<= GetHeight()), 
 842                  wxNullBitmap
, wxT("Invalid bitmap or bitmap region") ); 
 844     wxBitmap 
ret( rect
.width
, rect
.height
, GetDepth() ); 
 845     wxASSERT_MSG( ret
.Ok(), wxT("GetSubBitmap error") ); 
 848     HDC dcSrc 
= ::CreateCompatibleDC(NULL
); 
 849     HDC dcDst 
= ::CreateCompatibleDC(NULL
); 
 850     SelectObject(dcSrc
, (HBITMAP
) GetHBITMAP()); 
 851     SelectObject(dcDst
, (HBITMAP
) ret
.GetHBITMAP()); 
 852     BitBlt(dcDst
, 0, 0, rect
.width
, rect
.height
, dcSrc
, rect
.x
, rect
.y
, SRCCOPY
); 
 854     // copy mask if there is one 
 857         HBITMAP hbmpMask 
= ::CreateBitmap(rect
.width
, rect
.height
, 1, 1, 0); 
 859         SelectObject(dcSrc
, (HBITMAP
) GetMask()->GetMaskBitmap()); 
 860         SelectObject(dcDst
, (HBITMAP
) hbmpMask
); 
 861         BitBlt(dcDst
, 0, 0, rect
.width
, rect
.height
, dcSrc
, rect
.x
, rect
.y
, SRCCOPY
); 
 863         wxMask 
*mask 
= new wxMask((WXHBITMAP
) hbmpMask
); 
 867     SelectObject(dcDst
, NULL
); 
 868     SelectObject(dcSrc
, NULL
); 
 878 // ---------------------------------------------------------------------------- 
 879 // wxBitmap accessors 
 880 // ---------------------------------------------------------------------------- 
 882 void wxBitmap::SetQuality(int q
) 
 886     GetBitmapData()->m_quality 
= q
; 
 889 #if WXWIN_COMPATIBILITY_2 
 890 void wxBitmap::SetOk(bool isOk
) 
 894     GetBitmapData()->m_ok 
= isOk
; 
 896 #endif // WXWIN_COMPATIBILITY_2 
 900 void wxBitmap::SetPalette(const wxPalette
& palette
) 
 904     GetBitmapData()->m_bitmapPalette 
= palette
; 
 907 #endif // wxUSE_PALETTE 
 909 void wxBitmap::SetMask(wxMask 
*mask
) 
 913     GetBitmapData()->m_bitmapMask 
= mask
; 
 916 // Creates a bitmap that matches the device context, from 
 917 // an arbitray bitmap. At present, the original bitmap must have an 
 918 // associated palette. TODO: use a default palette if no palette exists. 
 919 // Contributed by Frederic Villeneuve <frederic.villeneuve@natinst.com> 
 920 wxBitmap 
wxBitmap::GetBitmapForDC(wxDC
& dc
) const 
 922 #ifdef __WXMICROWIN__ 
 926     wxBitmap        
tmpBitmap(GetWidth(), GetHeight(), dc
.GetDepth()); 
 927     HPALETTE        hPal 
= (HPALETTE
) NULL
; 
 929     void            *lpBits 
= (void*) NULL
; 
 932     if( GetPalette() && GetPalette()->Ok() ) 
 934         tmpBitmap
.SetPalette(*GetPalette()); 
 935         memDC
.SelectObject(tmpBitmap
); 
 936         memDC
.SetPalette(*GetPalette()); 
 937         hPal 
= (HPALETTE
)GetPalette()->GetHPALETTE(); 
 941         hPal 
= (HPALETTE
) ::GetStockObject(DEFAULT_PALETTE
); 
 943         palette
.SetHPALETTE( (WXHPALETTE
)hPal 
); 
 944         tmpBitmap
.SetPalette( palette 
); 
 945         memDC
.SelectObject(tmpBitmap
); 
 946         memDC
.SetPalette( palette 
); 
 948 #else // !wxUSE_PALETTE 
 949     hPal 
= (HPALETTE
) ::GetStockObject(DEFAULT_PALETTE
); 
 950 #endif // wxUSE_PALETTE/!wxUSE_PALETTE 
 952     // set the height negative because in a DIB the order of the lines is 
 954     if ( !wxCreateDIB(GetWidth(), -GetHeight(), GetDepth(), hPal
, &lpDib
) ) 
 959     lpBits 
= malloc(lpDib
->bmiHeader
.biSizeImage
); 
 961     ::GetBitmapBits(GetHbitmap(), lpDib
->bmiHeader
.biSizeImage
, lpBits
); 
 963     ::SetDIBitsToDevice(GetHdcOf(memDC
), 0, 0, 
 964                         GetWidth(), GetHeight(), 
 965                         0, 0, 0, GetHeight(), 
 966                         lpBits
, lpDib
, DIB_RGB_COLORS
); 
 976 // ---------------------------------------------------------------------------- 
 978 // ---------------------------------------------------------------------------- 
 985 // Construct a mask from a bitmap and a colour indicating 
 986 // the transparent area 
 987 wxMask::wxMask(const wxBitmap
& bitmap
, const wxColour
& colour
) 
 990     Create(bitmap
, colour
); 
 993 // Construct a mask from a bitmap and a palette index indicating 
 994 // the transparent area 
 995 wxMask::wxMask(const wxBitmap
& bitmap
, int paletteIndex
) 
 998     Create(bitmap
, paletteIndex
); 
1001 // Construct a mask from a mono bitmap (copies the bitmap). 
1002 wxMask::wxMask(const wxBitmap
& bitmap
) 
1011         ::DeleteObject((HBITMAP
) m_maskBitmap
); 
1014 // Create a mask from a mono bitmap (copies the bitmap). 
1015 bool wxMask::Create(const wxBitmap
& bitmap
) 
1017 #ifndef __WXMICROWIN__ 
1018     wxCHECK_MSG( bitmap
.Ok() && bitmap
.GetDepth() == 1, FALSE
, 
1019                  _T("can't create mask from invalid or not monochrome bitmap") ); 
1023         ::DeleteObject((HBITMAP
) m_maskBitmap
); 
1027     m_maskBitmap 
= (WXHBITMAP
) CreateBitmap( 
1032     HDC srcDC 
= CreateCompatibleDC(0); 
1033     SelectObject(srcDC
, (HBITMAP
) bitmap
.GetHBITMAP()); 
1034     HDC destDC 
= CreateCompatibleDC(0); 
1035     SelectObject(destDC
, (HBITMAP
) m_maskBitmap
); 
1036     BitBlt(destDC
, 0, 0, bitmap
.GetWidth(), bitmap
.GetHeight(), srcDC
, 0, 0, SRCCOPY
); 
1037     SelectObject(srcDC
, 0); 
1039     SelectObject(destDC
, 0); 
1047 // Create a mask from a bitmap and a palette index indicating 
1048 // the transparent area 
1049 bool wxMask::Create(const wxBitmap
& bitmap
, int paletteIndex
) 
1053         ::DeleteObject((HBITMAP
) m_maskBitmap
); 
1058     if (bitmap
.Ok() && bitmap
.GetPalette()->Ok()) 
1060         unsigned char red
, green
, blue
; 
1061         if (bitmap
.GetPalette()->GetRGB(paletteIndex
, &red
, &green
, &blue
)) 
1063             wxColour 
transparentColour(red
, green
, blue
); 
1064             return Create(bitmap
, transparentColour
); 
1067 #endif // wxUSE_PALETTE 
1072 // Create a mask from a bitmap and a colour indicating 
1073 // the transparent area 
1074 bool wxMask::Create(const wxBitmap
& bitmap
, const wxColour
& colour
) 
1076 #ifndef __WXMICROWIN__ 
1077     wxCHECK_MSG( bitmap
.Ok(), FALSE
, _T("invalid bitmap in wxMask::Create") ); 
1081         ::DeleteObject((HBITMAP
) m_maskBitmap
); 
1085     int width 
= bitmap
.GetWidth(), 
1086         height 
= bitmap
.GetHeight(); 
1088     // scan the bitmap for the transparent colour and set the corresponding 
1089     // pixels in the mask to BLACK and the rest to WHITE 
1090     COLORREF maskColour 
= wxColourToRGB(colour
); 
1091     m_maskBitmap 
= (WXHBITMAP
)::CreateBitmap(width
, height
, 1, 1, 0); 
1093     HDC srcDC 
= ::CreateCompatibleDC(NULL
); 
1094     HDC destDC 
= ::CreateCompatibleDC(NULL
); 
1095     if ( !srcDC 
|| !destDC 
) 
1097         wxLogLastError(wxT("CreateCompatibleDC")); 
1102     // SelectObject() will fail 
1103     wxASSERT_MSG( !bitmap
.GetSelectedInto(), 
1104                   _T("bitmap can't be selected in another DC") ); 
1106     HGDIOBJ hbmpSrcOld 
= ::SelectObject(srcDC
, GetHbitmapOf(bitmap
)); 
1109         wxLogLastError(wxT("SelectObject")); 
1114     HGDIOBJ hbmpDstOld 
= ::SelectObject(destDC
, (HBITMAP
)m_maskBitmap
); 
1117         wxLogLastError(wxT("SelectObject")); 
1122     // this is not very efficient, but I can't think of a better way of doing 
1124     for ( int w 
= 0; ok 
&& (w 
< width
); w
++ ) 
1126         for ( int h 
= 0; ok 
&& (h 
< height
); h
++ ) 
1128             COLORREF col 
= GetPixel(srcDC
, w
, h
); 
1129             if ( col 
== CLR_INVALID 
) 
1131                 wxLogLastError(wxT("GetPixel")); 
1133                 // doesn't make sense to continue 
1139             if ( col 
== maskColour 
) 
1141                 ::SetPixel(destDC
, w
, h
, RGB(0, 0, 0)); 
1145                 ::SetPixel(destDC
, w
, h
, RGB(255, 255, 255)); 
1150     ::SelectObject(srcDC
, hbmpSrcOld
); 
1152     ::SelectObject(destDC
, hbmpDstOld
); 
1161 // ---------------------------------------------------------------------------- 
1163 // ---------------------------------------------------------------------------- 
1165 bool wxBitmapHandler::Create(wxGDIImage 
*image
, 
1168                              int width
, int height
, int depth
) 
1170     wxBitmap 
*bitmap 
= wxDynamicCast(image
, wxBitmap
); 
1172     return bitmap 
? Create(bitmap
, data
, flags
, width
, height
, depth
) : FALSE
; 
1175 bool wxBitmapHandler::Load(wxGDIImage 
*image
, 
1176                            const wxString
& name
, 
1178                            int width
, int height
) 
1180     wxBitmap 
*bitmap 
= wxDynamicCast(image
, wxBitmap
); 
1182     return bitmap 
? LoadFile(bitmap
, name
, flags
, width
, height
) : FALSE
; 
1185 bool wxBitmapHandler::Save(wxGDIImage 
*image
, 
1186                            const wxString
& name
, 
1189     wxBitmap 
*bitmap 
= wxDynamicCast(image
, wxBitmap
); 
1191     return bitmap 
? SaveFile(bitmap
, name
, type
) : FALSE
; 
1194 bool wxBitmapHandler::Create(wxBitmap 
*WXUNUSED(bitmap
), 
1195                              void *WXUNUSED(data
), 
1196                              long WXUNUSED(type
), 
1197                              int WXUNUSED(width
), 
1198                              int WXUNUSED(height
), 
1199                              int WXUNUSED(depth
)) 
1204 bool wxBitmapHandler::LoadFile(wxBitmap 
*WXUNUSED(bitmap
), 
1205                                const wxString
& WXUNUSED(name
), 
1206                                long WXUNUSED(type
), 
1207                                int WXUNUSED(desiredWidth
), 
1208                                int WXUNUSED(desiredHeight
)) 
1213 bool wxBitmapHandler::SaveFile(wxBitmap 
*WXUNUSED(bitmap
), 
1214                                const wxString
& WXUNUSED(name
), 
1216                                const wxPalette 
*WXUNUSED(palette
)) 
1221 // ---------------------------------------------------------------------------- 
1223 // ---------------------------------------------------------------------------- 
1225 #ifndef __WXMICROWIN__ 
1226 bool wxCreateDIB(long xSize
, long ySize
, long bitsPerPixel
, 
1227                  HPALETTE hPal
, LPBITMAPINFO
* lpDIBHeader
) 
1229    unsigned long   i
, headerSize
; 
1230    LPBITMAPINFO    lpDIBheader 
= NULL
; 
1231    LPPALETTEENTRY  lpPe 
= NULL
; 
1234    // Allocate space for a DIB header 
1235    headerSize 
= (sizeof(BITMAPINFOHEADER
) + (256 * sizeof(PALETTEENTRY
))); 
1236    lpDIBheader 
= (BITMAPINFO 
*) malloc(headerSize
); 
1237    lpPe 
= (PALETTEENTRY 
*)((BYTE
*)lpDIBheader 
+ sizeof(BITMAPINFOHEADER
)); 
1239    GetPaletteEntries(hPal
, 0, 256, lpPe
); 
1241    memset(lpDIBheader
, 0x00, sizeof(BITMAPINFOHEADER
)); 
1243    // Fill in the static parts of the DIB header 
1244    lpDIBheader
->bmiHeader
.biSize 
= sizeof(BITMAPINFOHEADER
); 
1245    lpDIBheader
->bmiHeader
.biWidth 
= xSize
; 
1246    lpDIBheader
->bmiHeader
.biHeight 
= ySize
; 
1247    lpDIBheader
->bmiHeader
.biPlanes 
= 1; 
1249    // this value must be 1, 4, 8 or 24 so PixelDepth can only be 
1250    lpDIBheader
->bmiHeader
.biBitCount 
= (WORD
)(bitsPerPixel
); 
1251    lpDIBheader
->bmiHeader
.biCompression 
= BI_RGB
; 
1252    lpDIBheader
->bmiHeader
.biSizeImage 
= xSize 
* abs(ySize
) * bitsPerPixel 
>> 3; 
1253    lpDIBheader
->bmiHeader
.biClrUsed 
= 256; 
1256    // Initialize the DIB palette 
1257    for (i 
= 0; i 
< 256; i
++) { 
1258       lpDIBheader
->bmiColors
[i
].rgbReserved 
= lpPe
[i
].peFlags
; 
1259       lpDIBheader
->bmiColors
[i
].rgbRed 
= lpPe
[i
].peRed
; 
1260       lpDIBheader
->bmiColors
[i
].rgbGreen 
= lpPe
[i
].peGreen
; 
1261       lpDIBheader
->bmiColors
[i
].rgbBlue 
= lpPe
[i
].peBlue
; 
1264    *lpDIBHeader 
= lpDIBheader
; 
1269 void wxFreeDIB(LPBITMAPINFO lpDIBHeader
) 
1275 // ---------------------------------------------------------------------------- 
1276 // other helper functions 
1277 // ---------------------------------------------------------------------------- 
1279 extern HBITMAP 
wxInvertMask(HBITMAP hbmpMask
, int w
, int h
) 
1281 #ifndef __WXMICROWIN__ 
1282     wxCHECK_MSG( hbmpMask
, 0, _T("invalid bitmap in wxInvertMask") ); 
1284     // get width/height from the bitmap if not given 
1288         ::GetObject(hbmpMask
, sizeof(BITMAP
), (LPVOID
)&bm
); 
1293     HDC hdcSrc 
= ::CreateCompatibleDC(NULL
); 
1294     HDC hdcDst 
= ::CreateCompatibleDC(NULL
); 
1295     if ( !hdcSrc 
|| !hdcDst 
) 
1297         wxLogLastError(wxT("CreateCompatibleDC")); 
1300     HBITMAP hbmpInvMask 
= ::CreateBitmap(w
, h
, 1, 1, 0); 
1303         wxLogLastError(wxT("CreateBitmap")); 
1306     ::SelectObject(hdcSrc
, hbmpMask
); 
1307     ::SelectObject(hdcDst
, hbmpInvMask
); 
1308     if ( !::BitBlt(hdcDst
, 0, 0, w
, h
, 
1312         wxLogLastError(wxT("BitBlt"));