1 //////////////////////////////////////////////////////////////////////////// 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  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" 
  47 #include "wx/msw/dib.h" 
  51 #include "wx/xpmdecod.h" 
  53 #ifdef wxHAVE_RAW_BITMAP 
  54 #include "wx/rawbmp.h" 
  57 // missing from mingw32 header 
  59     #define CLR_INVALID ((COLORREF)-1) 
  60 #endif // no CLR_INVALID 
  62 // ---------------------------------------------------------------------------- 
  64 // ---------------------------------------------------------------------------- 
  66 class WXDLLEXPORT wxBitmapRefData 
: public wxGDIImageRefData
 
  70     virtual ~wxBitmapRefData() { Free(); } 
  74     // set the mask object to use as the mask, we take ownership of it 
  75     void SetMask(wxMask 
*mask
) 
  81     // set the HBITMAP to use as the mask 
  82     void SetMask(HBITMAP hbmpMask
) 
  84         SetMask(new wxMask((WXHBITMAP
)hbmpMask
)); 
  88     wxMask 
*GetMask() const { return m_bitmapMask
; } 
  92     wxPalette     m_bitmapPalette
; 
  93 #endif // wxUSE_PALETTE 
  99     // this field is solely for error checking: we detect selecting a bitmap 
 100     // into more than one DC at once or deleting a bitmap still selected into a 
 101     // DC (both are serious programming errors under Windows) 
 102     wxDC         
*m_selectedInto
; 
 103 #endif // __WXDEBUG__ 
 106     // when GetRawData() is called for a DDB we need to convert it to a DIB 
 107     // first to be able to provide direct access to it and we cache that DIB 
 108     // here and convert it back to DDB when UngetRawData() is called 
 112     // true if we have alpha transparency info and can be drawn using 
 116     // true if our HBITMAP is a DIB section, false if it is a DDB 
 120     // optional mask for transparent drawing 
 121     wxMask       
*m_bitmapMask
; 
 123     DECLARE_NO_COPY_CLASS(wxBitmapRefData
) 
 126 // ---------------------------------------------------------------------------- 
 128 // ---------------------------------------------------------------------------- 
 130 IMPLEMENT_DYNAMIC_CLASS(wxBitmap
, wxGDIObject
) 
 131 IMPLEMENT_DYNAMIC_CLASS(wxMask
, wxObject
) 
 133 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler
, wxObject
) 
 135 // ============================================================================ 
 137 // ============================================================================ 
 139 // ---------------------------------------------------------------------------- 
 141 // ---------------------------------------------------------------------------- 
 143 // decide whether we should create a DIB or a DDB for the given parameters 
 144 static bool wxShouldCreateDIB(int w
, int h
, int d
, WXHDC hdc
) 
 147     // here is the logic: 
 149     //  (a) if hdc is specified, the caller explicitly wants DDB 
 150     //  (b) otherwise, create a DIB if depth >= 24 (we don't support 16bpp or 
 152     //  (c) finally, create DIBs under Win9x even if the depth hasn't been 
 153     //      explicitly specified but the current display depth is 24 or more 
 154     //      and the image is "big", i.e. > 16Mb which is the theoretical limit 
 155     //      for DDBs under Win9x 
 157     // consequences (all of which seem to make sense): 
 159     //  (i)     by default, DDBs are created (depth == -1 usually) 
 160     //  (ii)    DIBs can be created by explicitly specifying the depth 
 161     //  (iii)   using a DC always forces creating a DDB 
 165                     wxDIB::GetLineSize(w
, wxDisplayDepth())*h 
> 16*1024*1024)); 
 171 // ---------------------------------------------------------------------------- 
 173 // ---------------------------------------------------------------------------- 
 175 wxBitmapRefData::wxBitmapRefData() 
 178     m_selectedInto 
= NULL
; 
 182     m_hBitmap 
= (WXHBITMAP
) NULL
; 
 191 void wxBitmapRefData::Free() 
 193     wxASSERT_MSG( !m_selectedInto
, 
 194                   wxT("deleting bitmap still selected into wxMemoryDC") ); 
 197     wxASSERT_MSG( !m_dib
, _T("forgot to call wxBitmap::UngetRawData()!") ); 
 202         if ( !::DeleteObject((HBITMAP
)m_hBitmap
) ) 
 204             wxLogLastError(wxT("DeleteObject(hbitmap)")); 
 212 // ---------------------------------------------------------------------------- 
 214 // ---------------------------------------------------------------------------- 
 216 // this function should be called from all wxBitmap ctors 
 217 void wxBitmap::Init() 
 219     // m_refData = NULL; done in the base class ctor 
 222 wxGDIImageRefData 
*wxBitmap::CreateData() const 
 224     return new wxBitmapRefData
; 
 229 bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage
& icon
) 
 231 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
 232     // it may be either HICON or HCURSOR 
 233     HICON hicon 
= (HICON
)icon
.GetHandle(); 
 236     if ( !::GetIconInfo(hicon
, &iconInfo
) ) 
 238         wxLogLastError(wxT("GetIconInfo")); 
 243     wxBitmapRefData 
*refData 
= new wxBitmapRefData
; 
 246     int w 
= icon
.GetWidth(), 
 247         h 
= icon
.GetHeight(); 
 249     refData
->m_width 
= w
; 
 250     refData
->m_height 
= h
; 
 251     refData
->m_depth 
= wxDisplayDepth(); 
 253     refData
->m_hBitmap 
= (WXHBITMAP
)iconInfo
.hbmColor
; 
 255     // the mask returned by GetIconInfo() is inversed compared to the usual 
 257     refData
->SetMask(wxInvertMask(iconInfo
.hbmMask
, w
, h
)); 
 260     // delete the old one now as we don't need it any more 
 261     ::DeleteObject(iconInfo
.hbmMask
); 
 263 #if WXWIN_COMPATIBILITY_2 
 264     refData
->m_ok 
= TRUE
; 
 265 #endif // WXWIN_COMPATIBILITY_2 
 275 bool wxBitmap::CopyFromCursor(const wxCursor
& cursor
) 
 283     wxFAIL_MSG( _T("don't know how to convert cursor to bitmap") ); 
 287     return CopyFromIconOrCursor(cursor
); 
 291 bool wxBitmap::CopyFromIcon(const wxIcon
& icon
) 
 298     // GetIconInfo() doesn't exist under Win16 and I don't know any other way 
 299     // to create a bitmap from icon there - but using this way we won't have 
 302     int width 
= icon
.GetWidth(), 
 303         height 
= icon
.GetHeight(); 
 305     // copy the icon to the bitmap 
 307     HDC hdc 
= ::CreateCompatibleDC(hdcScreen
); 
 308     HBITMAP hbitmap 
= ::CreateCompatibleBitmap(hdcScreen
, width
, height
); 
 309     HBITMAP hbmpOld 
= (HBITMAP
)::SelectObject(hdc
, hbitmap
); 
 311     ::DrawIcon(hdc
, 0, 0, GetHiconOf(icon
)); 
 313     ::SelectObject(hdc
, hbmpOld
); 
 316     wxBitmapRefData 
*refData 
= new wxBitmapRefData
; 
 319     refData
->m_width 
= width
; 
 320     refData
->m_height 
= height
; 
 321     refData
->m_depth 
= wxDisplayDepth(); 
 323     refData
->m_hBitmap 
= (WXHBITMAP
)hbitmap
; 
 325 #if WXWIN_COMPATIBILITY_2 
 326     refData
->m_ok 
= TRUE
; 
 327 #endif // WXWIN_COMPATIBILITY_2 
 331     return CopyFromIconOrCursor(icon
); 
 332 #endif // Win16/Win32 
 336 bool wxBitmap::CopyFromDIB(const wxDIB
& dib
) 
 338     wxCHECK_MSG( dib
.IsOk(), FALSE
, _T("invalid DIB in CopyFromDIB") ); 
 340     HBITMAP hbitmap 
= dib
.CreateDDB(); 
 346     wxBitmapRefData 
*refData 
= new wxBitmapRefData
; 
 349     refData
->m_width 
= dib
.GetWidth(); 
 350     refData
->m_height 
= dib
.GetHeight(); 
 351     refData
->m_depth 
= dib
.GetDepth(); 
 353     refData
->m_hBitmap 
= (WXHBITMAP
)hbitmap
; 
 356     wxPalette 
*palette 
= dib
.CreatePalette(); 
 359         refData
->m_bitmapPalette 
= *palette
; 
 363 #endif // wxUSE_PALETTE 
 369 wxBitmap::~wxBitmap() 
 373 wxBitmap::wxBitmap(const char bits
[], int width
, int height
, int depth
) 
 377 #ifndef __WXMICROWIN__ 
 378     wxBitmapRefData 
*refData 
= new wxBitmapRefData
; 
 381     refData
->m_width 
= width
; 
 382     refData
->m_height 
= height
; 
 383     refData
->m_depth 
= depth
; 
 388         // we assume that it is in XBM format which is not quite the same as 
 389         // the format CreateBitmap() wants because the order of bytes in the 
 391         const size_t bytesPerLine 
= (width 
+ 7) / 8; 
 392         const size_t padding 
= bytesPerLine 
% 2; 
 393         const size_t len 
= height 
* ( padding 
+ bytesPerLine 
); 
 394         data 
= (char *)malloc(len
); 
 395         const char *src 
= bits
; 
 398         for ( int rows 
= 0; rows 
< height
; rows
++ ) 
 400             for ( size_t cols 
= 0; cols 
< bytesPerLine
; cols
++ ) 
 402                 unsigned char val 
= *src
++; 
 403                 unsigned char reversed 
= 0; 
 405                 for ( int bits 
= 0; bits 
< 8; bits
++) 
 408                     reversed 
|= (val 
& 0x01); 
 420         // bits should already be in Windows standard format 
 421         data 
= (char *)bits
;    // const_cast is harmless 
 424     HBITMAP hbmp 
= ::CreateBitmap(width
, height
, 1, depth
, data
); 
 427         wxLogLastError(wxT("CreateBitmap")); 
 435     SetHBITMAP((WXHBITMAP
)hbmp
); 
 439 // Create from XPM data 
 440 bool wxBitmap::CreateFromXpm(const char **data
) 
 442 #if wxUSE_IMAGE && wxUSE_XPM 
 445     wxCHECK_MSG( data 
!= NULL
, FALSE
, wxT("invalid bitmap data") ) 
 447     wxXPMDecoder decoder
; 
 448     wxImage img 
= decoder
.ReadData(data
); 
 449     wxCHECK_MSG( img
.Ok(), FALSE
, wxT("invalid bitmap data") ) 
 451     *this = wxBitmap(img
); 
 458 wxBitmap::wxBitmap(int w
, int h
, int d
) 
 462     (void)Create(w
, h
, d
); 
 465 wxBitmap::wxBitmap(int w
, int h
, const wxDC
& dc
) 
 469     (void)Create(w
, h
, dc
); 
 472 wxBitmap::wxBitmap(void *data
, long type
, int width
, int height
, int depth
) 
 476     (void)Create(data
, type
, width
, height
, depth
); 
 479 wxBitmap::wxBitmap(const wxString
& filename
, wxBitmapType type
) 
 483     LoadFile(filename
, (int)type
); 
 486 bool wxBitmap::Create(int width
, int height
, int depth
) 
 488     return DoCreate(width
, height
, depth
, 0); 
 491 bool wxBitmap::Create(int width
, int height
, const wxDC
& dc
) 
 493     wxCHECK_MSG( dc
.Ok(), FALSE
, _T("invalid HDC in wxBitmap::Create()") ); 
 495     return DoCreate(width
, height
, -1, dc
.GetHDC()); 
 498 bool wxBitmap::DoCreate(int w
, int h
, int d
, WXHDC hdc
) 
 502     m_refData 
= new wxBitmapRefData
; 
 504     GetBitmapData()->m_width 
= w
; 
 505     GetBitmapData()->m_height 
= h
; 
 509     if ( wxShouldCreateDIB(w
, h
, d
, hdc
) ) 
 513             // create DIBs without alpha channel by default 
 521         // don't delete the DIB section in dib object dtor 
 524         GetBitmapData()->m_isDIB 
= TRUE
; 
 525         GetBitmapData()->m_depth 
= d
; 
 530             d 
= wxDisplayDepth(); 
 532         GetBitmapData()->m_depth 
= d
; 
 534 #ifndef __WXMICROWIN__ 
 537             hbmp 
= ::CreateBitmap(w
, h
, 1, d
, NULL
); 
 540                 wxLogLastError(wxT("CreateBitmap")); 
 544 #endif // !__WXMICROWIN__ 
 547             hbmp 
= ::CreateCompatibleBitmap(dc
, w
, h
); 
 550                 wxLogLastError(wxT("CreateCompatibleBitmap")); 
 553             GetBitmapData()->m_depth 
= wxDisplayDepth(); 
 557     SetHBITMAP((WXHBITMAP
)hbmp
); 
 559 #if WXWIN_COMPATIBILITY_2 
 560     GetBitmapData()->m_ok 
= hbmp 
!= 0; 
 561 #endif // WXWIN_COMPATIBILITY_2 
 568 // ---------------------------------------------------------------------------- 
 569 // wxImage to/from conversions for Microwin 
 570 // ---------------------------------------------------------------------------- 
 572 // Microwin versions are so different from normal ones that it really doesn't 
 573 // make sense to use #ifdefs inside the function bodies 
 574 #ifdef __WXMICROWIN__ 
 576 bool wxBitmap::CreateFromImage(const wxImage
& image
, int depth
, const wxDC
& dc
) 
 578     // Set this to 1 to experiment with mask code, 
 579     // which currently doesn't work 
 582     m_refData 
= new wxBitmapRefData(); 
 584     // Initial attempt at a simple-minded implementation. 
 585     // The bitmap will always be created at the screen depth, 
 586     // so the 'depth' argument is ignored. 
 588     HDC hScreenDC 
= ::GetDC(NULL
); 
 589     int screenDepth 
= ::GetDeviceCaps(hScreenDC
, BITSPIXEL
); 
 591     HBITMAP hBitmap 
= ::CreateCompatibleBitmap(hScreenDC
, image
.GetWidth(), image
.GetHeight()); 
 592     HBITMAP hMaskBitmap 
= NULL
; 
 593     HBITMAP hOldMaskBitmap 
= NULL
; 
 595     unsigned char maskR 
= 0; 
 596     unsigned char maskG 
= 0; 
 597     unsigned char maskB 
= 0; 
 599     //    printf("Created bitmap %d\n", (int) hBitmap); 
 602         ::ReleaseDC(NULL
, hScreenDC
); 
 605     HDC hMemDC 
= ::CreateCompatibleDC(hScreenDC
); 
 607     HBITMAP hOldBitmap 
= ::SelectObject(hMemDC
, hBitmap
); 
 608     ::ReleaseDC(NULL
, hScreenDC
); 
 610     // created an mono-bitmap for the possible mask 
 611     bool hasMask 
= image
.HasMask(); 
 616         // FIXME: we should be able to pass bpp = 1, but 
 617         // GdBlit can't handle a different depth 
 619         hMaskBitmap 
= ::CreateBitmap( (WORD
)image
.GetWidth(), (WORD
)image
.GetHeight(), 1, 1, NULL 
); 
 621         hMaskBitmap 
= ::CreateCompatibleBitmap( hMemDC
, (WORD
)image
.GetWidth(), (WORD
)image
.GetHeight()); 
 623         maskR 
= image
.GetMaskRed(); 
 624         maskG 
= image
.GetMaskGreen(); 
 625         maskB 
= image
.GetMaskBlue(); 
 633             hScreenDC 
= ::GetDC(NULL
); 
 634             hMaskDC 
= ::CreateCompatibleDC(hScreenDC
); 
 635            ::ReleaseDC(NULL
, hScreenDC
); 
 637             hOldMaskBitmap 
= ::SelectObject( hMaskDC
, hMaskBitmap
); 
 645     for (i 
= 0; i 
< image
.GetWidth(); i
++) 
 647         for (j 
= 0; j 
< image
.GetHeight(); j
++) 
 649             unsigned char red 
= image
.GetRed(i
, j
); 
 650             unsigned char green 
= image
.GetGreen(i
, j
); 
 651             unsigned char blue 
= image
.GetBlue(i
, j
); 
 653             ::SetPixel(hMemDC
, i
, j
, PALETTERGB(red
, green
, blue
)); 
 657                 // scan the bitmap for the transparent colour and set the corresponding 
 658                 // pixels in the mask to BLACK and the rest to WHITE 
 659                 if (maskR 
== red 
&& maskG 
== green 
&& maskB 
== blue
) 
 660                     ::SetPixel(hMaskDC
, i
, j
, PALETTERGB(0, 0, 0)); 
 662                     ::SetPixel(hMaskDC
, i
, j
, PALETTERGB(255, 255, 255)); 
 667     ::SelectObject(hMemDC
, hOldBitmap
); 
 671         ::SelectObject(hMaskDC
, hOldMaskBitmap
); 
 674         ((wxBitmapRefData
*)m_refData
)->SetMask(hMaskBitmap
); 
 677     SetWidth(image
.GetWidth()); 
 678     SetHeight(image
.GetHeight()); 
 679     SetDepth(screenDepth
); 
 680     SetHBITMAP( (WXHBITMAP
) hBitmap 
); 
 683     // Copy the palette from the source image 
 684     SetPalette(image
.GetPalette()); 
 685 #endif // wxUSE_PALETTE 
 687 #if WXWIN_COMPATIBILITY_2 
 688     // check the wxBitmap object 
 689     GetBitmapData()->SetOk(); 
 690 #endif // WXWIN_COMPATIBILITY_2 
 695 wxImage 
wxBitmap::ConvertToImage() const 
 697     // Initial attempt at a simple-minded implementation. 
 698     // The bitmap will always be created at the screen depth, 
 699     // so the 'depth' argument is ignored. 
 700     // TODO: transparency (create a mask image) 
 704         wxFAIL_MSG( wxT("bitmap is invalid") ); 
 710     wxCHECK_MSG( Ok(), wxNullImage
, wxT("invalid bitmap") ); 
 712     // create an wxImage object 
 713     int width 
= GetWidth(); 
 714     int height 
= GetHeight(); 
 715     image
.Create( width
, height 
); 
 716     unsigned char *data 
= image
.GetData(); 
 719         wxFAIL_MSG( wxT("could not allocate data for image") ); 
 723     HDC hScreenDC 
= ::GetDC(NULL
); 
 725     HDC hMemDC 
= ::CreateCompatibleDC(hScreenDC
); 
 726     ::ReleaseDC(NULL
, hScreenDC
); 
 728     HBITMAP hBitmap 
= (HBITMAP
) GetHBITMAP(); 
 730     HBITMAP hOldBitmap 
= ::SelectObject(hMemDC
, hBitmap
); 
 733     for (i 
= 0; i 
< GetWidth(); i
++) 
 735         for (j 
= 0; j 
< GetHeight(); j
++) 
 737             COLORREF color 
= ::GetPixel(hMemDC
, i
, j
); 
 738             unsigned char red 
= GetRValue(color
); 
 739             unsigned char green 
= GetGValue(color
); 
 740             unsigned char blue 
= GetBValue(color
); 
 742             image
.SetRGB(i
, j
, red
, green
, blue
); 
 746     ::SelectObject(hMemDC
, hOldBitmap
); 
 750     // Copy the palette from the source image 
 752         image
.SetPalette(* GetPalette()); 
 753 #endif // wxUSE_PALETTE 
 758 #endif // __WXMICROWIN__ 
 760 // ---------------------------------------------------------------------------- 
 761 // wxImage to/from conversions 
 762 // ---------------------------------------------------------------------------- 
 764 bool wxBitmap::CreateFromImage(const wxImage
& image
, int depth
) 
 766     return CreateFromImage(image
, depth
, 0); 
 769 bool wxBitmap::CreateFromImage(const wxImage
& image
, const wxDC
& dc
) 
 771     wxCHECK_MSG( dc
.Ok(), FALSE
, 
 772                     _T("invalid HDC in wxBitmap::CreateFromImage()") ); 
 774     return CreateFromImage(image
, -1, dc
.GetHDC()); 
 777 bool wxBitmap::CreateFromImage(const wxImage
& image
, int depth
, WXHDC hdc 
) 
 779     wxCHECK_MSG( image
.Ok(), FALSE
, wxT("invalid image") ); 
 783     // first convert the image to DIB 
 784     const int h 
= image
.GetHeight(); 
 785     const int w 
= image
.GetWidth(); 
 792     // store the bitmap parameters 
 793     wxBitmapRefData 
*refData 
= new wxBitmapRefData
; 
 794     refData
->m_width 
= w
; 
 795     refData
->m_height 
= h
; 
 796     refData
->m_hasAlpha 
= image
.HasAlpha(); 
 801     // next either store DIB as is or create a DDB from it 
 804     // are we going to use DIB? 
 806     // NB: DDBs don't support alpha so if we have alpha channel we must use DIB 
 807     if ( image
.HasAlpha() || wxShouldCreateDIB(w
, h
, depth
, hdc
) ) 
 809         // don't delete the DIB section in dib object dtor 
 810         hbitmap 
= dib
.Detach(); 
 812         refData
->m_isDIB 
= TRUE
; 
 813         refData
->m_depth 
= dib
.GetDepth(); 
 815     else // we need to convert DIB to DDB 
 817         hbitmap 
= dib
.CreateDDB((HDC
)hdc
); 
 819         refData
->m_depth 
= depth 
== -1 ? wxDisplayDepth() : depth
; 
 822     // validate this object 
 823     SetHBITMAP((WXHBITMAP
)hbitmap
); 
 825 #if WXWIN_COMPATIBILITY_2 
 826     m_refData
->m_ok 
= TRUE
; 
 827 #endif // WXWIN_COMPATIBILITY_2 
 829     // finally also set the mask if we have one 
 830     if ( image
.HasMask() ) 
 832         SetMask(new wxMask(*this, wxColour(image
.GetMaskRed(), 
 833                                            image
.GetMaskGreen(), 
 834                                            image
.GetMaskBlue()))); 
 840 wxImage 
wxBitmap::ConvertToImage() const 
 842     // FIXME: this is untested code for WinCE, and 
 843     // the mask is not yet handled. 
 845     // http://www.codeproject.com/bitmap/dibsection.asp?print=true 
 848     // the colour used as transparent one in wxImage and the one it is replaced 
 849     // with when it really occurs in the bitmap 
 850     static const int MASK_RED 
= 1; 
 851     static const int MASK_GREEN 
= 2; 
 852     static const int MASK_BLUE 
= 3; 
 853     static const int MASK_BLUE_REPLACEMENT 
= 2; 
 857     wxCHECK_MSG( Ok(), wxNullImage
, wxT("invalid bitmap") ); 
 859     // create an wxImage object 
 860     int width 
= GetWidth(); 
 861     int height 
= GetHeight(); 
 862     image
.Create( width
, height 
); 
 863     unsigned char *data 
= image
.GetData(); 
 866         wxFAIL_MSG( wxT("could not allocate data for image") ); 
 870     // calc the number of bytes per scanline and padding in the DIB 
 871     int bytePerLine 
= width
*3; 
 872     int sizeDWORD 
= sizeof( DWORD 
); 
 873     int lineBoundary 
=  bytePerLine 
% sizeDWORD
; 
 875     if( lineBoundary 
> 0 ) 
 877         padding 
= sizeDWORD 
- lineBoundary
; 
 878         bytePerLine 
+= padding
; 
 881     // create a DIB header 
 882     int headersize 
= sizeof(BITMAPINFOHEADER
); 
 883     BITMAPINFO 
*lpDIBh 
= (BITMAPINFO 
*) malloc( headersize 
); 
 886         wxFAIL_MSG( wxT("could not allocate data for DIB header") ); 
 890     // Fill in the DIB header 
 891     lpDIBh
->bmiHeader
.biSize 
= headersize
; 
 892     lpDIBh
->bmiHeader
.biWidth 
= width
; 
 893     lpDIBh
->bmiHeader
.biHeight 
= -height
; 
 894     lpDIBh
->bmiHeader
.biSizeImage 
= bytePerLine 
* height
; 
 895     lpDIBh
->bmiHeader
.biPlanes 
= 1; 
 896     lpDIBh
->bmiHeader
.biBitCount 
= 24; 
 897     lpDIBh
->bmiHeader
.biCompression 
= BI_RGB
; 
 898     lpDIBh
->bmiHeader
.biClrUsed 
= 0; 
 899     // These seem not really needed for our purpose here. 
 900     lpDIBh
->bmiHeader
.biClrImportant 
= 0; 
 901     lpDIBh
->bmiHeader
.biXPelsPerMeter 
= 0; 
 902     lpDIBh
->bmiHeader
.biYPelsPerMeter 
= 0; 
 904     // memory for DIB data is allocated by CreateDIBSection 
 907     // copy data from the device-dependent bitmap to the DIB 
 908     HDC hdc 
= ::GetDC(NULL
); 
 909     HBITMAP hBitmap 
= (HBITMAP
) GetHBITMAP(); 
 911     HBITMAP hBitmapSection 
= ::CreateDIBSection( hdc
, lpDIBh
, DIB_RGB_COLORS
, & lpBits
, NULL
, 0 ); 
 914         wxFAIL_MSG( wxT("could not create a DIB section") ); 
 918     // Copy the image from the DDB to the DIBSection 
 919     // Need to copy the supplied bitmap onto the newly created DIBsection 
 920     HDC hMemDC 
= CreateCompatibleDC(hdc
); 
 921         HDC hCopyDC 
= CreateCompatibleDC(hdc
); 
 923     if (! hMemDC 
|| ! hCopyDC
)  
 925         wxFAIL_MSG( wxT("unable to create compatible DCs") ); 
 932         SelectPalette(hMemDC
, m_hPal
, FALSE
);   RealizePalette(hMemDC
); 
 933         SelectPalette(hCopyDC
, m_hPal
, FALSE
);  RealizePalette(hCopyDC
); 
 937     HBITMAP hOldMemBitmap  
= (HBITMAP
) SelectObject(hMemDC
,  hBitmap
); 
 938     HBITMAP hOldCopyBitmap 
= (HBITMAP
) SelectObject(hCopyDC
, hBitmapSection
); 
 940     BitBlt(hCopyDC
, 0, 0, GetWidth(), GetHeight(), hMemDC
, 0, 0, SRCCOPY
); 
 942     SelectObject(hMemDC
,  hOldMemBitmap
); 
 943     SelectObject(hCopyDC
, hOldCopyBitmap
); 
 950                 HGDIOBJ hObj 
= ::GetStockObject(DEFAULT_PALETTE
); 
 951         SelectObject(hMemDC
, hObj
); 
 952         SelectObject(hCopyDC
, hObj
); 
 956         ReleaseDC(NULL
, hdc
); 
 958     // copy DIB data into the wxImage object 
 960     unsigned char *ptdata 
= data
; 
 961     unsigned char *ptbits 
= (unsigned char*) lpBits
; 
 962     for( i
=0; i
<height
; i
++ ) 
 964         for( j
=0; j
<width
; j
++ ) 
 966             *(ptdata
++) = *(ptbits
+2); 
 967             *(ptdata
++) = *(ptbits
+1); 
 968             *(ptdata
++) = *(ptbits  
); 
 976     // similarly, set data according to the possible mask bitmap 
 977     if( GetMask() && GetMask()->GetMaskBitmap() ) 
 979         hbitmap 
= (HBITMAP
) GetMask()->GetMaskBitmap(); 
 980         // memory DC created, color set, data copied, and memory DC deleted 
 981         HDC memdc 
= ::CreateCompatibleDC( hdc 
); 
 982         ::SetTextColor( memdc
, RGB( 0, 0, 0 ) ); 
 983         ::SetBkColor( memdc
, RGB( 255, 255, 255 ) ); 
 984         ::GetDIBits( memdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS 
); 
 988         for( i
=0; i
<height
; i
++ ) 
 990             for( j
=0; j
<width
; j
++ ) 
 992                 // is this pixel transparent? 
 995                     if ( (ptdata
[0] == MASK_RED
) && 
 996                             (ptdata
[1] == MASK_GREEN
) && 
 997                                 (ptdata
[2] == MASK_BLUE
) ) 
 999                         // we have to fudge the colour a bit to prevent this 
1000                         // pixel from appearing transparent 
1001                         ptdata
[2] = MASK_BLUE_REPLACEMENT
; 
1005                 else // masked pixel 
1007                     *(ptdata
++)  = MASK_RED
; 
1008                     *(ptdata
++)  = MASK_GREEN
; 
1009                     *(ptdata
++)  = MASK_BLUE
; 
1016         image
.SetMaskColour( MASK_RED
, MASK_GREEN
, MASK_BLUE 
); 
1017         image
.SetMask( TRUE 
); 
1022         image
.SetMask( FALSE 
); 
1025     // free allocated resources 
1026     ::ReleaseDC(NULL
, hdc
); 
1029     // Delete the DIB section 
1030     ::DeleteObject(hBitmapSection
); 
1034     // the colour used as transparent one in wxImage and the one it is replaced 
1035     // with when it really occurs in the bitmap 
1036     static const int MASK_RED 
= 1; 
1037     static const int MASK_GREEN 
= 2; 
1038     static const int MASK_BLUE 
= 3; 
1039     static const int MASK_BLUE_REPLACEMENT 
= 2; 
1043     wxCHECK_MSG( Ok(), wxNullImage
, wxT("invalid bitmap") ); 
1045     // create an wxImage object 
1046     int width 
= GetWidth(); 
1047     int height 
= GetHeight(); 
1048     image
.Create( width
, height 
); 
1049     unsigned char *data 
= image
.GetData(); 
1052         wxFAIL_MSG( wxT("could not allocate data for image") ); 
1056     // calc the number of bytes per scanline and padding in the DIB 
1057     int bytePerLine 
= width
*3; 
1058     int sizeDWORD 
= sizeof( DWORD 
); 
1059     int lineBoundary 
=  bytePerLine 
% sizeDWORD
; 
1061     if( lineBoundary 
> 0 ) 
1063         padding 
= sizeDWORD 
- lineBoundary
; 
1064         bytePerLine 
+= padding
; 
1067     // create a DIB header 
1068     int headersize 
= sizeof(BITMAPINFOHEADER
); 
1069     BITMAPINFO 
*lpDIBh 
= (BITMAPINFO 
*) malloc( headersize 
); 
1072         wxFAIL_MSG( wxT("could not allocate data for DIB header") ); 
1076     // Fill in the DIB header 
1077     lpDIBh
->bmiHeader
.biSize 
= headersize
; 
1078     lpDIBh
->bmiHeader
.biWidth 
= width
; 
1079     lpDIBh
->bmiHeader
.biHeight 
= -height
; 
1080     lpDIBh
->bmiHeader
.biSizeImage 
= bytePerLine 
* height
; 
1081     lpDIBh
->bmiHeader
.biPlanes 
= 1; 
1082     lpDIBh
->bmiHeader
.biBitCount 
= 24; 
1083     lpDIBh
->bmiHeader
.biCompression 
= BI_RGB
; 
1084     lpDIBh
->bmiHeader
.biClrUsed 
= 0; 
1085     // These seem not really needed for our purpose here. 
1086     lpDIBh
->bmiHeader
.biClrImportant 
= 0; 
1087     lpDIBh
->bmiHeader
.biXPelsPerMeter 
= 0; 
1088     lpDIBh
->bmiHeader
.biYPelsPerMeter 
= 0; 
1089     // memory for DIB data 
1090     unsigned char *lpBits
; 
1091     lpBits 
= (unsigned char *) malloc( lpDIBh
->bmiHeader
.biSizeImage 
); 
1094         wxFAIL_MSG( wxT("could not allocate data for DIB") ); 
1100     // copy data from the device-dependent bitmap to the DIB 
1101     HDC hdc 
= ::GetDC(NULL
); 
1103     hbitmap 
= (HBITMAP
) GetHBITMAP(); 
1104     ::GetDIBits( hdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS 
); 
1106     // copy DIB data into the wxImage object 
1108     unsigned char *ptdata 
= data
; 
1109     unsigned char *ptbits 
= lpBits
; 
1110     for( i
=0; i
<height
; i
++ ) 
1112         for( j
=0; j
<width
; j
++ ) 
1114             *(ptdata
++) = *(ptbits
+2); 
1115             *(ptdata
++) = *(ptbits
+1); 
1116             *(ptdata
++) = *(ptbits  
); 
1122     // similarly, set data according to the possible mask bitmap 
1123     if( GetMask() && GetMask()->GetMaskBitmap() ) 
1125         hbitmap 
= (HBITMAP
) GetMask()->GetMaskBitmap(); 
1126         // memory DC created, color set, data copied, and memory DC deleted 
1127         HDC memdc 
= ::CreateCompatibleDC( hdc 
); 
1128         ::SetTextColor( memdc
, RGB( 0, 0, 0 ) ); 
1129         ::SetBkColor( memdc
, RGB( 255, 255, 255 ) ); 
1130         ::GetDIBits( memdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS 
); 
1131         ::DeleteDC( memdc 
); 
1134         for( i
=0; i
<height
; i
++ ) 
1136             for( j
=0; j
<width
; j
++ ) 
1138                 // is this pixel transparent? 
1141                     if ( (ptdata
[0] == MASK_RED
) && 
1142                             (ptdata
[1] == MASK_GREEN
) && 
1143                                 (ptdata
[2] == MASK_BLUE
) ) 
1145                         // we have to fudge the colour a bit to prevent this 
1146                         // pixel from appearing transparent 
1147                         ptdata
[2] = MASK_BLUE_REPLACEMENT
; 
1151                 else // masked pixel 
1153                     *(ptdata
++)  = MASK_RED
; 
1154                     *(ptdata
++)  = MASK_GREEN
; 
1155                     *(ptdata
++)  = MASK_BLUE
; 
1162         image
.SetMaskColour( MASK_RED
, MASK_GREEN
, MASK_BLUE 
); 
1163         image
.SetMask( TRUE 
); 
1167         image
.SetMask( FALSE 
); 
1169     // free allocated resources 
1170     ::ReleaseDC(NULL
, hdc
); 
1178 #endif // wxUSE_IMAGE 
1180 // ---------------------------------------------------------------------------- 
1181 // loading and saving bitmaps 
1182 // ---------------------------------------------------------------------------- 
1184 bool wxBitmap::LoadFile(const wxString
& filename
, long type
) 
1188     wxBitmapHandler 
*handler 
= wxDynamicCast(FindHandler(type
), wxBitmapHandler
); 
1192         m_refData 
= new wxBitmapRefData
; 
1194         return handler
->LoadFile(this, filename
, type
, -1, -1); 
1200         if ( image
.LoadFile( filename
, type 
) && image
.Ok() ) 
1202             *this = wxBitmap(image
); 
1207 #endif // wxUSE_IMAGE 
1212 bool wxBitmap::Create(void *data
, long type
, int width
, int height
, int depth
) 
1216     wxBitmapHandler 
*handler 
= wxDynamicCast(FindHandler(type
), wxBitmapHandler
); 
1220         wxLogDebug(wxT("Failed to create bitmap: no bitmap handler for type %ld defined."), type
); 
1225     m_refData 
= new wxBitmapRefData
; 
1227     return handler
->Create(this, data
, type
, width
, height
, depth
); 
1230 bool wxBitmap::SaveFile(const wxString
& filename
, 
1232                         const wxPalette 
*palette
) 
1234     wxBitmapHandler 
*handler 
= wxDynamicCast(FindHandler(type
), wxBitmapHandler
); 
1238         return handler
->SaveFile(this, filename
, type
, palette
); 
1243         // FIXME what about palette? shouldn't we use it? 
1244         wxImage image 
= ConvertToImage(); 
1247             return image
.SaveFile(filename
, type
); 
1250 #endif // wxUSE_IMAGE 
1255 // ---------------------------------------------------------------------------- 
1256 // sub bitmap extraction 
1257 // ---------------------------------------------------------------------------- 
1259 wxBitmap 
wxBitmap::GetSubBitmap( const wxRect
& rect
) const 
1261     wxCHECK_MSG( Ok() && 
1262                  (rect
.x 
>= 0) && (rect
.y 
>= 0) && 
1263                  (rect
.x
+rect
.width 
<= GetWidth()) && 
1264                  (rect
.y
+rect
.height 
<= GetHeight()), 
1265                  wxNullBitmap
, wxT("Invalid bitmap or bitmap region") ); 
1267     wxBitmap 
ret( rect
.width
, rect
.height 
); 
1268     wxASSERT_MSG( ret
.Ok(), wxT("GetSubBitmap error") ); 
1270 #ifndef __WXMICROWIN__ 
1271     // TODO: copy alpha channel data if any 
1278         SelectInHDC 
selectSrc(dcSrc
, GetHbitmap()), 
1279                     selectDst(dcDst
, GetHbitmapOf(ret
)); 
1281         if ( !selectSrc 
|| !selectDst 
) 
1283             wxLogLastError(_T("SelectObjct(hBitmap)")); 
1286         if ( !::BitBlt(dcDst
, 0, 0, rect
.width
, rect
.height
, 
1287                        dcSrc
, rect
.x
, rect
.y
, SRCCOPY
) ) 
1289             wxLogLastError(_T("BitBlt")); 
1293     // copy mask if there is one 
1296         HBITMAP hbmpMask 
= ::CreateBitmap(rect
.width
, rect
.height
, 1, 1, 0); 
1298         SelectInHDC 
selectSrc(dcSrc
, (HBITMAP
) GetMask()->GetMaskBitmap()), 
1299                     selectDst(dcDst
, hbmpMask
); 
1301         if ( !::BitBlt(dcDst
, 0, 0, rect
.width
, rect
.height
, 
1302                        dcSrc
, rect
.x
, rect
.y
, SRCCOPY
) ) 
1304             wxLogLastError(_T("BitBlt")); 
1307         wxMask 
*mask 
= new wxMask((WXHBITMAP
) hbmpMask
); 
1310 #endif // !__WXMICROWIN__ 
1315 // ---------------------------------------------------------------------------- 
1316 // wxBitmap accessors 
1317 // ---------------------------------------------------------------------------- 
1320 wxPalette
* wxBitmap::GetPalette() const 
1322     return GetBitmapData() ? &GetBitmapData()->m_bitmapPalette
 
1323                            : (wxPalette 
*) NULL
; 
1327 wxMask 
*wxBitmap::GetMask() const 
1329     return GetBitmapData() ? GetBitmapData()->GetMask() : (wxMask 
*) NULL
; 
1334 wxDC 
*wxBitmap::GetSelectedInto() const 
1336     return GetBitmapData() ? GetBitmapData()->m_selectedInto 
: (wxDC 
*) NULL
; 
1341 #if WXWIN_COMPATIBILITY_2_4 
1343 int wxBitmap::GetQuality() const 
1348 #endif // WXWIN_COMPATIBILITY_2_4 
1350 void wxBitmap::UseAlpha() 
1352     if ( GetBitmapData() ) 
1353         GetBitmapData()->m_hasAlpha 
= true; 
1356 bool wxBitmap::HasAlpha() const 
1358     return GetBitmapData() && GetBitmapData()->m_hasAlpha
; 
1361 // ---------------------------------------------------------------------------- 
1363 // ---------------------------------------------------------------------------- 
1367 void wxBitmap::SetSelectedInto(wxDC 
*dc
) 
1369     if ( GetBitmapData() ) 
1370         GetBitmapData()->m_selectedInto 
= dc
; 
1377 void wxBitmap::SetPalette(const wxPalette
& palette
) 
1381     GetBitmapData()->m_bitmapPalette 
= palette
; 
1384 #endif // wxUSE_PALETTE 
1386 void wxBitmap::SetMask(wxMask 
*mask
) 
1390     GetBitmapData()->SetMask(mask
); 
1393 #if WXWIN_COMPATIBILITY_2 
1395 void wxBitmap::SetOk(bool isOk
) 
1399     GetBitmapData()->m_ok 
= isOk
; 
1402 #endif // WXWIN_COMPATIBILITY_2 
1404 #if WXWIN_COMPATIBILITY_2_4 
1406 void wxBitmap::SetQuality(int WXUNUSED(quality
)) 
1410 #endif // WXWIN_COMPATIBILITY_2_4 
1412 // ---------------------------------------------------------------------------- 
1413 // raw bitmap access support 
1414 // ---------------------------------------------------------------------------- 
1416 #ifdef wxHAVE_RAW_BITMAP 
1417 void *wxBitmap::GetRawData(wxPixelDataBase
& data
, int bpp
) 
1422         // no bitmap, no data (raw or otherwise) 
1426     // if we're already a DIB we can access our data directly, but if not we 
1427     // need to convert this DDB to a DIB section and use it for raw access and 
1428     // then convert it back 
1430     if ( !GetBitmapData()->m_isDIB 
) 
1432         wxCHECK_MSG( !GetBitmapData()->m_dib
, FALSE
, 
1433                         _T("GetRawData() may be called only once") ); 
1435         wxDIB 
*dib 
= new wxDIB(*this); 
1443         // we'll free it in UngetRawData() 
1444         GetBitmapData()->m_dib 
= dib
; 
1446         hDIB 
= dib
->GetHandle(); 
1450         hDIB 
= GetHbitmap(); 
1454     if ( ::GetObject(hDIB
, sizeof(ds
), &ds
) != sizeof(DIBSECTION
) ) 
1456         wxFAIL_MSG( _T("failed to get DIBSECTION from a DIB?") ); 
1461     // check that the bitmap is in correct format 
1462     if ( ds
.dsBm
.bmBitsPixel 
!= bpp 
) 
1464         wxFAIL_MSG( _T("incorrect bitmap type in wxBitmap::GetRawData()") ); 
1469     // ok, store the relevant info in wxPixelDataBase 
1470     const LONG h 
= ds
.dsBm
.bmHeight
; 
1472     data
.m_width 
= ds
.dsBm
.bmWidth
; 
1475     // remember that DIBs are stored in top to bottom order! 
1476     const LONG bytesPerRow 
= ds
.dsBm
.bmWidthBytes
; 
1477     data
.m_stride 
= -bytesPerRow
; 
1479     char *bits 
= (char *)ds
.dsBm
.bmBits
; 
1482         bits 
+= (h 
- 1)*bytesPerRow
; 
1491 void wxBitmap::UngetRawData(wxPixelDataBase
& dataBase
) 
1497     // the cast is ugly but we can't do without it and without making this 
1498     // function template (and hence inline) unfortunately 
1499     typedef wxPixelData
<wxBitmap
, wxAlphaPixelFormat
> PixelData
; 
1500     PixelData
& data 
= (PixelData 
&)dataBase
; 
1504         // invalid data, don't crash -- but don't assert neither as we're 
1505         // called automatically from wxPixelDataBase dtor and so there is no 
1506         // way to prevent this from happening 
1510     if ( GetBitmapData()->m_hasAlpha 
) 
1512         // AlphaBlend() wants to have premultiplied source alpha but 
1513         // wxRawBitmap API uses normal, not premultiplied, colours, so adjust 
1515         PixelData::Iterator 
p(data
); 
1517         const int w 
= data
.GetWidth(); 
1518         const int h 
= data
.GetHeight(); 
1520         for ( int y 
= 0; y 
< h
; y
++ ) 
1522             PixelData::Iterator rowStart 
= p
; 
1524             for ( int x 
= 0; x 
< w
; x
++ ) 
1526                 const unsigned alpha 
= p
.Alpha(); 
1528                 p
.Red() = (p
.Red() * alpha 
+ 127) / 255; 
1529                 p
.Blue() = (p
.Blue() * alpha 
+ 127) / 255; 
1530                 p
.Green() = (p
.Green() * alpha 
+ 127) / 255; 
1539         // if we're a DDB we need to convert DIB back to DDB now to make the 
1540         // changes made via raw bitmap access effective 
1541         if ( !GetBitmapData()->m_isDIB 
) 
1543             wxDIB 
*dib 
= GetBitmapData()->m_dib
; 
1544             GetBitmapData()->m_dib 
= NULL
; 
1553 #endif // #ifdef wxHAVE_RAW_BITMAP 
1555 // ---------------------------------------------------------------------------- 
1557 // ---------------------------------------------------------------------------- 
1564 // Construct a mask from a bitmap and a colour indicating 
1565 // the transparent area 
1566 wxMask::wxMask(const wxBitmap
& bitmap
, const wxColour
& colour
) 
1569     Create(bitmap
, colour
); 
1572 // Construct a mask from a bitmap and a palette index indicating 
1573 // the transparent area 
1574 wxMask::wxMask(const wxBitmap
& bitmap
, int paletteIndex
) 
1577     Create(bitmap
, paletteIndex
); 
1580 // Construct a mask from a mono bitmap (copies the bitmap). 
1581 wxMask::wxMask(const wxBitmap
& bitmap
) 
1590         ::DeleteObject((HBITMAP
) m_maskBitmap
); 
1593 // Create a mask from a mono bitmap (copies the bitmap). 
1594 bool wxMask::Create(const wxBitmap
& bitmap
) 
1596 #ifndef __WXMICROWIN__ 
1597     wxCHECK_MSG( bitmap
.Ok() && bitmap
.GetDepth() == 1, FALSE
, 
1598                  _T("can't create mask from invalid or not monochrome bitmap") ); 
1602         ::DeleteObject((HBITMAP
) m_maskBitmap
); 
1606     m_maskBitmap 
= (WXHBITMAP
) CreateBitmap( 
1611     HDC srcDC 
= CreateCompatibleDC(0); 
1612     SelectObject(srcDC
, (HBITMAP
) bitmap
.GetHBITMAP()); 
1613     HDC destDC 
= CreateCompatibleDC(0); 
1614     SelectObject(destDC
, (HBITMAP
) m_maskBitmap
); 
1615     BitBlt(destDC
, 0, 0, bitmap
.GetWidth(), bitmap
.GetHeight(), srcDC
, 0, 0, SRCCOPY
); 
1616     SelectObject(srcDC
, 0); 
1618     SelectObject(destDC
, 0); 
1626 // Create a mask from a bitmap and a palette index indicating 
1627 // the transparent area 
1628 bool wxMask::Create(const wxBitmap
& bitmap
, int paletteIndex
) 
1632         ::DeleteObject((HBITMAP
) m_maskBitmap
); 
1637     if (bitmap
.Ok() && bitmap
.GetPalette()->Ok()) 
1639         unsigned char red
, green
, blue
; 
1640         if (bitmap
.GetPalette()->GetRGB(paletteIndex
, &red
, &green
, &blue
)) 
1642             wxColour 
transparentColour(red
, green
, blue
); 
1643             return Create(bitmap
, transparentColour
); 
1646 #endif // wxUSE_PALETTE 
1651 // Create a mask from a bitmap and a colour indicating 
1652 // the transparent area 
1653 bool wxMask::Create(const wxBitmap
& bitmap
, const wxColour
& colour
) 
1655 #ifndef __WXMICROWIN__ 
1656     wxCHECK_MSG( bitmap
.Ok(), FALSE
, _T("invalid bitmap in wxMask::Create") ); 
1660         ::DeleteObject((HBITMAP
) m_maskBitmap
); 
1664     int width 
= bitmap
.GetWidth(), 
1665         height 
= bitmap
.GetHeight(); 
1667     // scan the bitmap for the transparent colour and set the corresponding 
1668     // pixels in the mask to BLACK and the rest to WHITE 
1669     COLORREF maskColour 
= wxColourToPalRGB(colour
); 
1670     m_maskBitmap 
= (WXHBITMAP
)::CreateBitmap(width
, height
, 1, 1, 0); 
1672     HDC srcDC 
= ::CreateCompatibleDC(NULL
); 
1673     HDC destDC 
= ::CreateCompatibleDC(NULL
); 
1674     if ( !srcDC 
|| !destDC 
) 
1676         wxLogLastError(wxT("CreateCompatibleDC")); 
1681     // SelectObject() will fail 
1682     wxASSERT_MSG( !bitmap
.GetSelectedInto(), 
1683                   _T("bitmap can't be selected in another DC") ); 
1685     HGDIOBJ hbmpSrcOld 
= ::SelectObject(srcDC
, GetHbitmapOf(bitmap
)); 
1688         wxLogLastError(wxT("SelectObject")); 
1693     HGDIOBJ hbmpDstOld 
= ::SelectObject(destDC
, (HBITMAP
)m_maskBitmap
); 
1696         wxLogLastError(wxT("SelectObject")); 
1703         // this will create a monochrome bitmap with 0 points for the pixels 
1704         // which have the same value as the background colour and 1 for the 
1706         ::SetBkColor(srcDC
, maskColour
); 
1707         ::BitBlt(destDC
, 0, 0, width
, height
, srcDC
, 0, 0, NOTSRCCOPY
); 
1710     ::SelectObject(srcDC
, hbmpSrcOld
); 
1712     ::SelectObject(destDC
, hbmpDstOld
); 
1716 #else // __WXMICROWIN__ 
1718 #endif // __WXMICROWIN__/!__WXMICROWIN__ 
1721 // ---------------------------------------------------------------------------- 
1723 // ---------------------------------------------------------------------------- 
1725 bool wxBitmapHandler::Create(wxGDIImage 
*image
, 
1728                              int width
, int height
, int depth
) 
1730     wxBitmap 
*bitmap 
= wxDynamicCast(image
, wxBitmap
); 
1732     return bitmap 
? Create(bitmap
, data
, flags
, width
, height
, depth
) : FALSE
; 
1735 bool wxBitmapHandler::Load(wxGDIImage 
*image
, 
1736                            const wxString
& name
, 
1738                            int width
, int height
) 
1740     wxBitmap 
*bitmap 
= wxDynamicCast(image
, wxBitmap
); 
1742     return bitmap 
? LoadFile(bitmap
, name
, flags
, width
, height
) : FALSE
; 
1745 bool wxBitmapHandler::Save(wxGDIImage 
*image
, 
1746                            const wxString
& name
, 
1749     wxBitmap 
*bitmap 
= wxDynamicCast(image
, wxBitmap
); 
1751     return bitmap 
? SaveFile(bitmap
, name
, type
) : FALSE
; 
1754 bool wxBitmapHandler::Create(wxBitmap 
*WXUNUSED(bitmap
), 
1755                              void *WXUNUSED(data
), 
1756                              long WXUNUSED(type
), 
1757                              int WXUNUSED(width
), 
1758                              int WXUNUSED(height
), 
1759                              int WXUNUSED(depth
)) 
1764 bool wxBitmapHandler::LoadFile(wxBitmap 
*WXUNUSED(bitmap
), 
1765                                const wxString
& WXUNUSED(name
), 
1766                                long WXUNUSED(type
), 
1767                                int WXUNUSED(desiredWidth
), 
1768                                int WXUNUSED(desiredHeight
)) 
1773 bool wxBitmapHandler::SaveFile(wxBitmap 
*WXUNUSED(bitmap
), 
1774                                const wxString
& WXUNUSED(name
), 
1776                                const wxPalette 
*WXUNUSED(palette
)) 
1781 // ---------------------------------------------------------------------------- 
1783 // ---------------------------------------------------------------------------- 
1785 #ifndef __WXMICROWIN__ 
1786 bool wxCreateDIB(long xSize
, long ySize
, long bitsPerPixel
, 
1787                  HPALETTE hPal
, LPBITMAPINFO
* lpDIBHeader
) 
1789    unsigned long   i
, headerSize
; 
1790    LPBITMAPINFO    lpDIBheader 
= NULL
; 
1791    LPPALETTEENTRY  lpPe 
= NULL
; 
1794    // Allocate space for a DIB header 
1795    headerSize 
= (sizeof(BITMAPINFOHEADER
) + (256 * sizeof(PALETTEENTRY
))); 
1796    lpDIBheader 
= (BITMAPINFO 
*) malloc(headerSize
); 
1797    lpPe 
= (PALETTEENTRY 
*)((BYTE
*)lpDIBheader 
+ sizeof(BITMAPINFOHEADER
)); 
1799    GetPaletteEntries(hPal
, 0, 256, lpPe
); 
1801    memset(lpDIBheader
, 0x00, sizeof(BITMAPINFOHEADER
)); 
1803    // Fill in the static parts of the DIB header 
1804    lpDIBheader
->bmiHeader
.biSize 
= sizeof(BITMAPINFOHEADER
); 
1805    lpDIBheader
->bmiHeader
.biWidth 
= xSize
; 
1806    lpDIBheader
->bmiHeader
.biHeight 
= ySize
; 
1807    lpDIBheader
->bmiHeader
.biPlanes 
= 1; 
1809    // this value must be 1, 4, 8 or 24 so PixelDepth can only be 
1810    lpDIBheader
->bmiHeader
.biBitCount 
= (WORD
)(bitsPerPixel
); 
1811    lpDIBheader
->bmiHeader
.biCompression 
= BI_RGB
; 
1812    lpDIBheader
->bmiHeader
.biSizeImage 
= xSize 
* abs(ySize
) * bitsPerPixel 
>> 3; 
1813    lpDIBheader
->bmiHeader
.biClrUsed 
= 256; 
1816    // Initialize the DIB palette 
1817    for (i 
= 0; i 
< 256; i
++) { 
1818       lpDIBheader
->bmiColors
[i
].rgbReserved 
= lpPe
[i
].peFlags
; 
1819       lpDIBheader
->bmiColors
[i
].rgbRed 
= lpPe
[i
].peRed
; 
1820       lpDIBheader
->bmiColors
[i
].rgbGreen 
= lpPe
[i
].peGreen
; 
1821       lpDIBheader
->bmiColors
[i
].rgbBlue 
= lpPe
[i
].peBlue
; 
1824    *lpDIBHeader 
= lpDIBheader
; 
1829 void wxFreeDIB(LPBITMAPINFO lpDIBHeader
) 
1835 // ---------------------------------------------------------------------------- 
1836 // global helper functions implemented here 
1837 // ---------------------------------------------------------------------------- 
1839 // helper of wxBitmapToHICON/HCURSOR 
1841 HICON 
wxBitmapToIconOrCursor(const wxBitmap
& bmp
, 
1848         // we can't create an icon/cursor form nothing 
1852     wxMask 
*mask 
= bmp
.GetMask(); 
1855         // we must have a mask for an icon, so even if it's probably incorrect, 
1856         // do create it (grey is the "standard" transparent colour) 
1857         mask 
= new wxMask(bmp
, *wxLIGHT_GREY
); 
1861     iconInfo
.fIcon 
= iconWanted
;  // do we want an icon or a cursor? 
1864         iconInfo
.xHotspot 
= hotSpotX
; 
1865         iconInfo
.yHotspot 
= hotSpotY
; 
1868     iconInfo
.hbmMask 
= wxInvertMask((HBITMAP
)mask
->GetMaskBitmap()); 
1869     iconInfo
.hbmColor 
= GetHbitmapOf(bmp
); 
1871     // black out the transparent area to preserve background colour, because 
1872     // Windows blits the original bitmap using SRCINVERT (XOR) after applying 
1873     // the mask to the dest rect. 
1875         MemoryHDC dcSrc
, dcDst
; 
1876         SelectInHDC 
selectMask(dcSrc
, (HBITMAP
)mask
->GetMaskBitmap()), 
1877                     selectBitmap(dcDst
, iconInfo
.hbmColor
); 
1879         if ( !::BitBlt(dcDst
, 0, 0, bmp
.GetWidth(), bmp
.GetHeight(), 
1880                        dcSrc
, 0, 0, SRCAND
) ) 
1882             wxLogLastError(_T("BitBlt")); 
1886     HICON hicon 
= ::CreateIconIndirect(&iconInfo
); 
1888     if ( !bmp
.GetMask() ) 
1890         // we created the mask, now delete it 
1894     // delete the inverted mask bitmap we created as well 
1895     ::DeleteObject(iconInfo
.hbmMask
); 
1900 HICON 
wxBitmapToHICON(const wxBitmap
& bmp
) 
1902     return wxBitmapToIconOrCursor(bmp
, TRUE
, 0, 0); 
1905 HCURSOR 
wxBitmapToHCURSOR(const wxBitmap
& bmp
, int hotSpotX
, int hotSpotY
) 
1907     return (HCURSOR
)wxBitmapToIconOrCursor(bmp
, FALSE
, hotSpotX
, hotSpotY
); 
1910 HBITMAP 
wxInvertMask(HBITMAP hbmpMask
, int w
, int h
) 
1912 #ifndef __WXMICROWIN__ 
1913     wxCHECK_MSG( hbmpMask
, 0, _T("invalid bitmap in wxInvertMask") ); 
1915     // get width/height from the bitmap if not given 
1919         ::GetObject(hbmpMask
, sizeof(BITMAP
), (LPVOID
)&bm
); 
1924     HDC hdcSrc 
= ::CreateCompatibleDC(NULL
); 
1925     HDC hdcDst 
= ::CreateCompatibleDC(NULL
); 
1926     if ( !hdcSrc 
|| !hdcDst 
) 
1928         wxLogLastError(wxT("CreateCompatibleDC")); 
1931     HBITMAP hbmpInvMask 
= ::CreateBitmap(w
, h
, 1, 1, 0); 
1934         wxLogLastError(wxT("CreateBitmap")); 
1937     ::SelectObject(hdcSrc
, hbmpMask
); 
1938     ::SelectObject(hdcDst
, hbmpInvMask
); 
1939     if ( !::BitBlt(hdcDst
, 0, 0, w
, h
, 
1943         wxLogLastError(wxT("BitBlt"));