1 ///////////////////////////////////////////////////////////////////////////// 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) Robert Roebling 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  11 #pragma implementation "image.h" 
  14 // For compilers that support precompilation, includes "wx.h". 
  15 #include "wx/wxprec.h" 
  22 #include "wx/bitmap.h" 
  26 #include "wx/filefn.h" 
  27 #include "wx/wfstream.h" 
  29 #include "wx/module.h" 
  40     #include "wx/msw/private.h" 
  43 //----------------------------------------------------------------------------- 
  45 //----------------------------------------------------------------------------- 
  47 class wxImageRefData
: public wxObjectRefData
 
  55     unsigned char  *m_data
; 
  57     unsigned char   m_maskRed
,m_maskGreen
,m_maskBlue
; 
  61 wxImageRefData::wxImageRefData() 
  65     m_data 
= (unsigned char*) NULL
; 
  73 wxImageRefData::~wxImageRefData() 
  79 wxList 
wxImage::sm_handlers
; 
  81 //----------------------------------------------------------------------------- 
  83 #define M_IMGDATA ((wxImageRefData *)m_refData) 
  85     IMPLEMENT_DYNAMIC_CLASS(wxImage
, wxObject
) 
  91 wxImage::wxImage( int width
, int height 
) 
  93     Create( width
, height 
); 
  96 wxImage::wxImage( const wxString
& name
, long type 
) 
  98     LoadFile( name
, type 
); 
 101 wxImage::wxImage( const wxString
& name
, const wxString
& mimetype 
) 
 103     LoadFile( name
, mimetype 
); 
 107 wxImage::wxImage( wxInputStream
& stream
, long type 
) 
 109     LoadFile( stream
, type 
); 
 112 wxImage::wxImage( wxInputStream
& stream
, const wxString
& mimetype 
) 
 114     LoadFile( stream
, mimetype 
); 
 116 #endif // wxUSE_STREAMS 
 118 wxImage::wxImage( const wxImage
& image 
) 
 123 wxImage::wxImage( const wxImage
* image 
) 
 125     if (image
) Ref(*image
); 
 128 void wxImage::Create( int width
, int height 
) 
 130     m_refData 
= new wxImageRefData(); 
 132     M_IMGDATA
->m_data 
= (unsigned char *) malloc( width
*height
*3 ); 
 133     if (M_IMGDATA
->m_data
) 
 135         for (int l 
= 0; l 
< width
*height
*3; l
++) M_IMGDATA
->m_data
[l
] = 0; 
 137         M_IMGDATA
->m_width 
= width
; 
 138         M_IMGDATA
->m_height 
= height
; 
 139         M_IMGDATA
->m_ok 
= TRUE
; 
 147 void wxImage::Destroy() 
 152 wxImage 
wxImage::Scale( int width
, int height 
) const 
 156     wxCHECK_MSG( Ok(), image
, wxT("invalid image") ); 
 158     wxCHECK_MSG( (width 
> 0) && (height 
> 0), image
, wxT("invalid image size") ); 
 160     image
.Create( width
, height 
); 
 162     char unsigned *data 
= image
.GetData(); 
 164     wxCHECK_MSG( data
, image
, wxT("unable to create image") ); 
 166     if (M_IMGDATA
->m_hasMask
) 
 167         image
.SetMaskColour( M_IMGDATA
->m_maskRed
, M_IMGDATA
->m_maskGreen
, M_IMGDATA
->m_maskBlue 
); 
 169     long old_height 
= M_IMGDATA
->m_height
; 
 170     long old_width  
= M_IMGDATA
->m_width
; 
 172     char unsigned *source_data 
= M_IMGDATA
->m_data
; 
 173     char unsigned *target_data 
= data
; 
 175     for (long j 
= 0; j 
< height
; j
++) 
 177         long y_offset 
= (j 
* old_height 
/ height
) * old_width
; 
 179         for (long i 
= 0; i 
< width
; i
++) 
 182                 source_data 
+ 3*(y_offset 
+ ((i 
* old_width 
)/ width
)), 
 191 wxImage 
wxImage::GetSubImage( const wxRect 
&rect 
) const 
 195     wxCHECK_MSG( Ok(), image
, wxT("invalid image") ); 
 197     wxCHECK_MSG( (rect
.GetLeft()>=0) && (rect
.GetTop()>=0) && (rect
.GetRight()<=GetWidth()) && (rect
.GetBottom()<=GetHeight()), 
 198                  image
, wxT("invalid subimage size") ); 
 200     int subwidth
=rect
.GetWidth(); 
 201     const int subheight
=rect
.GetHeight(); 
 203     image
.Create( subwidth
, subheight 
); 
 205     char unsigned *subdata 
= image
.GetData(), *data
=GetData(); 
 207     wxCHECK_MSG( subdata
, image
, wxT("unable to create image") ); 
 209     if (M_IMGDATA
->m_hasMask
) 
 210         image
.SetMaskColour( M_IMGDATA
->m_maskRed
, M_IMGDATA
->m_maskGreen
, M_IMGDATA
->m_maskBlue 
); 
 212     const int subleft
=3*rect
.GetLeft(); 
 213     const int width
=3*GetWidth(); 
 216     data
+=rect
.GetTop()*width
+subleft
; 
 218     for (long j 
= 0; j 
< subheight
; ++j
) 
 220         memcpy( subdata
, data
, subwidth
); 
 228 void wxImage::Replace( unsigned char r1
, unsigned char g1
, unsigned char b1
, 
 229                        unsigned char r2
, unsigned char g2
, unsigned char b2 
) 
 231     wxCHECK_RET( Ok(), wxT("invalid image") ); 
 233     char unsigned *data 
= GetData(); 
 235     const int w 
= GetWidth(); 
 236     const int h 
= GetHeight(); 
 238     for (int j 
= 0; j 
< h
; j
++) 
 239         for (int i 
= 0; i 
< w
; i
++) 
 241             if ((data
[0] == r1
) && (data
[1] == g1
) && (data
[2] == b1
)) 
 251 void wxImage::SetRGB( int x
, int y
, unsigned char r
, unsigned char g
, unsigned char b 
) 
 253     wxCHECK_RET( Ok(), wxT("invalid image") ); 
 255     int w 
= M_IMGDATA
->m_width
; 
 256     int h 
= M_IMGDATA
->m_height
; 
 258     wxCHECK_RET( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), wxT("invalid image index") ); 
 260     long pos 
= (y 
* w 
+ x
) * 3; 
 262     M_IMGDATA
->m_data
[ pos   
] = r
; 
 263     M_IMGDATA
->m_data
[ pos
+1 ] = g
; 
 264     M_IMGDATA
->m_data
[ pos
+2 ] = b
; 
 267 unsigned char wxImage::GetRed( int x
, int y 
) 
 269     wxCHECK_MSG( Ok(), 0, wxT("invalid image") ); 
 271     int w 
= M_IMGDATA
->m_width
; 
 272     int h 
= M_IMGDATA
->m_height
; 
 274     wxCHECK_MSG( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), 0, wxT("invalid image index") ); 
 276     long pos 
= (y 
* w 
+ x
) * 3; 
 278     return M_IMGDATA
->m_data
[pos
]; 
 281 unsigned char wxImage::GetGreen( int x
, int y 
) 
 283     wxCHECK_MSG( Ok(), 0, wxT("invalid image") ); 
 285     int w 
= M_IMGDATA
->m_width
; 
 286     int h 
= M_IMGDATA
->m_height
; 
 288     wxCHECK_MSG( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), 0, wxT("invalid image index") ); 
 290     long pos 
= (y 
* w 
+ x
) * 3; 
 292     return M_IMGDATA
->m_data
[pos
+1]; 
 295 unsigned char wxImage::GetBlue( int x
, int y 
) 
 297     wxCHECK_MSG( Ok(), 0, wxT("invalid image") ); 
 299     int w 
= M_IMGDATA
->m_width
; 
 300     int h 
= M_IMGDATA
->m_height
; 
 302     wxCHECK_MSG( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), 0, wxT("invalid image index") ); 
 304     long pos 
= (y 
* w 
+ x
) * 3; 
 306     return M_IMGDATA
->m_data
[pos
+2]; 
 309 bool wxImage::Ok() const 
 311     return (M_IMGDATA 
&& M_IMGDATA
->m_ok
); 
 314 char unsigned *wxImage::GetData() const 
 316     wxCHECK_MSG( Ok(), (char unsigned *)NULL
, wxT("invalid image") ); 
 318     return M_IMGDATA
->m_data
; 
 321 void wxImage::SetData( char unsigned *data 
) 
 323     wxCHECK_RET( Ok(), wxT("invalid image") ); 
 325     wxImageRefData 
*newRefData 
= new wxImageRefData(); 
 327     newRefData
->m_width 
= M_IMGDATA
->m_width
; 
 328     newRefData
->m_height 
= M_IMGDATA
->m_height
; 
 329     newRefData
->m_data 
= data
; 
 330     newRefData
->m_ok 
= TRUE
; 
 331     newRefData
->m_maskRed 
= M_IMGDATA
->m_maskRed
; 
 332     newRefData
->m_maskGreen 
= M_IMGDATA
->m_maskGreen
; 
 333     newRefData
->m_maskBlue 
= M_IMGDATA
->m_maskBlue
; 
 334     newRefData
->m_hasMask 
= M_IMGDATA
->m_hasMask
; 
 338     m_refData 
= newRefData
; 
 341 void wxImage::SetMaskColour( unsigned char r
, unsigned char g
, unsigned char b 
) 
 343     wxCHECK_RET( Ok(), wxT("invalid image") ); 
 345     M_IMGDATA
->m_maskRed 
= r
; 
 346     M_IMGDATA
->m_maskGreen 
= g
; 
 347     M_IMGDATA
->m_maskBlue 
= b
; 
 348     M_IMGDATA
->m_hasMask 
= TRUE
; 
 351 unsigned char wxImage::GetMaskRed() const 
 353     wxCHECK_MSG( Ok(), 0, wxT("invalid image") ); 
 355     return M_IMGDATA
->m_maskRed
; 
 358 unsigned char wxImage::GetMaskGreen() const 
 360     wxCHECK_MSG( Ok(), 0, wxT("invalid image") ); 
 362     return M_IMGDATA
->m_maskGreen
; 
 365 unsigned char wxImage::GetMaskBlue() const 
 367     wxCHECK_MSG( Ok(), 0, wxT("invalid image") ); 
 369     return M_IMGDATA
->m_maskBlue
; 
 372 void wxImage::SetMask( bool mask 
) 
 374     wxCHECK_RET( Ok(), wxT("invalid image") ); 
 376     M_IMGDATA
->m_hasMask 
= mask
; 
 379 bool wxImage::HasMask() const 
 381     wxCHECK_MSG( Ok(), FALSE
, wxT("invalid image") ); 
 383     return M_IMGDATA
->m_hasMask
; 
 386 int wxImage::GetWidth() const 
 388     wxCHECK_MSG( Ok(), 0, wxT("invalid image") ); 
 390     return M_IMGDATA
->m_width
; 
 393 int wxImage::GetHeight() const 
 395     wxCHECK_MSG( Ok(), 0, wxT("invalid image") ); 
 397     return M_IMGDATA
->m_height
; 
 400 bool wxImage::LoadFile( const wxString
& filename
, long type 
) 
 403     if (wxFileExists(filename
)) 
 405         wxFileInputStream 
stream(filename
); 
 406         wxBufferedInputStream 
bstream( stream 
); 
 407         return LoadFile(bstream
, type
); 
 411         wxLogError( _("Can't load image from file '%s': file does not exist."), filename
.c_str() ); 
 415 #else // !wxUSE_STREAMS 
 417 #endif // wxUSE_STREAMS 
 420 bool wxImage::LoadFile( const wxString
& filename
, const wxString
& mimetype 
) 
 423     if (wxFileExists(filename
)) 
 425         wxFileInputStream 
stream(filename
); 
 426         wxBufferedInputStream 
bstream( stream 
); 
 427         return LoadFile(bstream
, mimetype
); 
 431         wxLogError( _("Can't load image from file '%s': file does not exist."), filename
.c_str() ); 
 435 #else // !wxUSE_STREAMS 
 437 #endif // wxUSE_STREAMS 
 440 bool wxImage::SaveFile( const wxString
& filename
, int type 
) 
 443     wxFileOutputStream 
stream(filename
); 
 445     if ( stream
.LastError() == wxStream_NOERROR 
) 
 447         wxBufferedOutputStream 
bstream( stream 
); 
 448         return SaveFile(bstream
, type
); 
 451 #endif // wxUSE_STREAMS 
 455 bool wxImage::SaveFile( const wxString
& filename
, const wxString
& mimetype 
) 
 458     wxFileOutputStream 
stream(filename
); 
 460     if ( stream
.LastError() == wxStream_NOERROR 
) 
 462         wxBufferedOutputStream 
bstream( stream 
); 
 463         return SaveFile(bstream
, mimetype
); 
 466 #endif // wxUSE_STREAMS 
 470 bool wxImage::CanRead( const wxString 
&name 
) 
 473   wxFileInputStream 
stream(name
); 
 474   return CanRead(stream
); 
 482 bool wxImage::CanRead( wxInputStream 
&stream 
) 
 484   wxList 
&list
=GetHandlers(); 
 486   for ( wxList::Node 
*node 
= list
.GetFirst(); node
; node 
= node
->GetNext() ) 
 488       wxImageHandler 
*handler
=(wxImageHandler
*)node
->GetData(); 
 489       if (handler
->CanRead( stream 
)) 
 496 bool wxImage::LoadFile( wxInputStream
& stream
, long type 
) 
 500     m_refData 
= new wxImageRefData
; 
 502     wxImageHandler 
*handler
; 
 504     if (type
==wxBITMAP_TYPE_ANY
) 
 506         wxList 
&list
=GetHandlers(); 
 508         for ( wxList::Node 
*node 
= list
.GetFirst(); node
; node 
= node
->GetNext() ) 
 510              handler
=(wxImageHandler
*)node
->GetData(); 
 511              if (handler
->CanRead( stream 
)) 
 512                  return handler
->LoadFile( this, stream 
); 
 516         wxLogWarning( _("No handler found for image type.") ); 
 520     handler 
= FindHandler(type
); 
 524         wxLogWarning( _("No image handler for type %d defined."), type 
); 
 529     return handler
->LoadFile( this, stream 
); 
 532 bool wxImage::LoadFile( wxInputStream
& stream
, const wxString
& mimetype 
) 
 536     m_refData 
= new wxImageRefData
; 
 538     wxImageHandler 
*handler 
= FindHandlerMime(mimetype
); 
 542         wxLogWarning( _("No image handler for type %s defined."), mimetype
.GetData() ); 
 547     return handler
->LoadFile( this, stream 
); 
 550 bool wxImage::SaveFile( wxOutputStream
& stream
, int type 
) 
 552     wxCHECK_MSG( Ok(), FALSE
, wxT("invalid image") ); 
 554     wxImageHandler 
*handler 
= FindHandler(type
); 
 558         wxLogWarning( _("No image handler for type %d defined."), type 
); 
 563     return handler
->SaveFile( this, stream 
); 
 566 bool wxImage::SaveFile( wxOutputStream
& stream
, const wxString
& mimetype 
) 
 568     wxCHECK_MSG( Ok(), FALSE
, wxT("invalid image") ); 
 570     wxImageHandler 
*handler 
= FindHandlerMime(mimetype
); 
 574         wxLogWarning( _("No image handler for type %s defined."), mimetype
.GetData() ); 
 579     return handler
->SaveFile( this, stream 
); 
 581 #endif // wxUSE_STREAMS 
 583 void wxImage::AddHandler( wxImageHandler 
*handler 
) 
 585     // make sure that the memory will be freed at the program end 
 586     sm_handlers
.DeleteContents(TRUE
); 
 588     sm_handlers
.Append( handler 
); 
 591 void wxImage::InsertHandler( wxImageHandler 
*handler 
) 
 593     // make sure that the memory will be freed at the program end 
 594     sm_handlers
.DeleteContents(TRUE
); 
 596     sm_handlers
.Insert( handler 
); 
 599 bool wxImage::RemoveHandler( const wxString
& name 
) 
 601     wxImageHandler 
*handler 
= FindHandler(name
); 
 604         sm_handlers
.DeleteObject(handler
); 
 611 wxImageHandler 
*wxImage::FindHandler( const wxString
& name 
) 
 613     wxNode 
*node 
= sm_handlers
.First(); 
 616         wxImageHandler 
*handler 
= (wxImageHandler
*)node
->Data(); 
 617         if (handler
->GetName().Cmp(name
) == 0) return handler
; 
 621     return (wxImageHandler 
*)NULL
; 
 624 wxImageHandler 
*wxImage::FindHandler( const wxString
& extension
, long bitmapType 
) 
 626     wxNode 
*node 
= sm_handlers
.First(); 
 629         wxImageHandler 
*handler 
= (wxImageHandler
*)node
->Data(); 
 630         if ( (handler
->GetExtension().Cmp(extension
) == 0) && 
 631             (bitmapType 
== -1 || handler
->GetType() == bitmapType
) ) 
 635     return (wxImageHandler
*)NULL
; 
 638 wxImageHandler 
*wxImage::FindHandler( long bitmapType 
) 
 640     wxNode 
*node 
= sm_handlers
.First(); 
 643         wxImageHandler 
*handler 
= (wxImageHandler 
*)node
->Data(); 
 644         if (handler
->GetType() == bitmapType
) return handler
; 
 650 wxImageHandler 
*wxImage::FindHandlerMime( const wxString
& mimetype 
) 
 652     wxNode 
*node 
= sm_handlers
.First(); 
 655         wxImageHandler 
*handler 
= (wxImageHandler 
*)node
->Data(); 
 656         if (handler
->GetMimeType().IsSameAs(mimetype
, FALSE
)) return handler
; 
 662 void wxImage::InitStandardHandlers() 
 664   AddHandler( new wxBMPHandler 
); 
 667 void wxImage::CleanUpHandlers() 
 669     wxNode 
*node 
= sm_handlers
.First(); 
 672         wxImageHandler 
*handler 
= (wxImageHandler 
*)node
->Data(); 
 673         wxNode 
*next 
= node
->Next(); 
 680 //----------------------------------------------------------------------------- 
 682 //----------------------------------------------------------------------------- 
 684 IMPLEMENT_ABSTRACT_CLASS(wxImageHandler
,wxObject
) 
 687 bool wxImageHandler::LoadFile( wxImage 
*WXUNUSED(image
), wxInputStream
& WXUNUSED(stream
), bool WXUNUSED(verbose
), int WXUNUSED(index
) ) 
 692 bool wxImageHandler::SaveFile( wxImage 
*WXUNUSED(image
), wxOutputStream
& WXUNUSED(stream
), bool WXUNUSED(verbose
) ) 
 697 int wxImageHandler::GetImageCount( wxInputStream
& WXUNUSED(stream
) ) 
 702 bool wxImageHandler::CanRead( const wxString
& name 
) 
 704     if (wxFileExists(name
)) 
 706         wxFileInputStream 
stream(name
); 
 707         return CanRead(stream
); 
 711         wxLogError( _("Can't check image format of file '%s': file does not exist."), name
.c_str() ); 
 718 #endif // wxUSE_STREAMS 
 720 //----------------------------------------------------------------------------- 
 721 // MSW conversion routines 
 722 //----------------------------------------------------------------------------- 
 726 wxBitmap 
wxImage::ConvertToBitmap() const 
 731     // sizeLimit is the MS upper limit for the DIB size 
 733     int sizeLimit 
= 1024*768*3; 
 735     int sizeLimit 
= 0x7fff ; 
 738     // width and height of the device-dependent bitmap 
 739     int width 
= GetWidth(); 
 740     int bmpHeight 
= GetHeight(); 
 742     // calc the number of bytes per scanline and padding 
 743     int bytePerLine 
= width
*3; 
 744     int sizeDWORD 
= sizeof( DWORD 
); 
 745     int lineBoundary 
= bytePerLine 
% sizeDWORD
; 
 747     if( lineBoundary 
> 0 ) 
 749         padding 
= sizeDWORD 
- lineBoundary
; 
 750         bytePerLine 
+= padding
; 
 752     // calc the number of DIBs and heights of DIBs 
 755     int height 
= sizeLimit
/bytePerLine
; 
 756     if( height 
>= bmpHeight 
) 
 760         numDIB 
=  bmpHeight 
/ height
; 
 761         hRemain 
= bmpHeight 
% height
; 
 762         if( hRemain 
>0 )  numDIB
++; 
 765     // set bitmap parameters 
 767     wxCHECK_MSG( Ok(), bitmap
, wxT("invalid image") ); 
 768     bitmap
.SetWidth( width 
); 
 769     bitmap
.SetHeight( bmpHeight 
); 
 770     bitmap
.SetDepth( wxDisplayDepth() ); 
 772     // create a DIB header 
 773     int headersize 
= sizeof(BITMAPINFOHEADER
); 
 774     BITMAPINFO 
*lpDIBh 
= (BITMAPINFO 
*) malloc( headersize 
); 
 775     wxCHECK_MSG( lpDIBh
, bitmap
, wxT("could not allocate memory for DIB header") ); 
 776     // Fill in the DIB header 
 777     lpDIBh
->bmiHeader
.biSize 
= headersize
; 
 778     lpDIBh
->bmiHeader
.biWidth 
= (DWORD
)width
; 
 779     lpDIBh
->bmiHeader
.biHeight 
= (DWORD
)(-height
); 
 780     lpDIBh
->bmiHeader
.biSizeImage 
= bytePerLine
*height
; 
 781     //   the general formula for biSizeImage: 
 782     //      ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height; 
 783     lpDIBh
->bmiHeader
.biPlanes 
= 1; 
 784     lpDIBh
->bmiHeader
.biBitCount 
= 24; 
 785     lpDIBh
->bmiHeader
.biCompression 
= BI_RGB
; 
 786     lpDIBh
->bmiHeader
.biClrUsed 
= 0; 
 787     // These seem not really needed for our purpose here. 
 788     lpDIBh
->bmiHeader
.biClrImportant 
= 0; 
 789     lpDIBh
->bmiHeader
.biXPelsPerMeter 
= 0; 
 790     lpDIBh
->bmiHeader
.biYPelsPerMeter 
= 0; 
 791     // memory for DIB data 
 792     unsigned char *lpBits
; 
 793     lpBits 
= (unsigned char *)malloc( lpDIBh
->bmiHeader
.biSizeImage 
); 
 796         wxFAIL_MSG( wxT("could not allocate memory for DIB") ); 
 801     // create and set the device-dependent bitmap 
 802     HDC hdc 
= ::GetDC(NULL
); 
 803     HDC memdc 
= ::CreateCompatibleDC( hdc 
); 
 805     hbitmap 
= ::CreateCompatibleBitmap( hdc
, width
, bmpHeight 
); 
 806     ::SelectObject( memdc
, hbitmap
); 
 808     // copy image data into DIB data and then into DDB (in a loop) 
 809     unsigned char *data 
= GetData(); 
 812     unsigned char *ptdata 
= data
; 
 813     unsigned char *ptbits
; 
 815     for( n
=0; n
<numDIB
; n
++ ) 
 817         if( numDIB 
> 1 && n 
== numDIB
-1 && hRemain 
> 0 ) 
 819             // redefine height and size of the (possibly) last smaller DIB 
 820             // memory is not reallocated 
 822             lpDIBh
->bmiHeader
.biHeight 
= (DWORD
)(-height
); 
 823             lpDIBh
->bmiHeader
.biSizeImage 
= bytePerLine
*height
; 
 827         for( j
=0; j
<height
; j
++ ) 
 829             for( i
=0; i
<width
; i
++ ) 
 831                 *(ptbits
++) = *(ptdata
+2); 
 832                 *(ptbits
++) = *(ptdata
+1); 
 833                 *(ptbits
++) = *(ptdata  
); 
 836             for( i
=0; i
< padding
; i
++ )   *(ptbits
++) = 0; 
 838         ::StretchDIBits( memdc
, 0, origin
, width
, height
,\
 
 839             0, 0, width
, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
, SRCCOPY
); 
 841         // if numDIB = 1,  lines below can also be used 
 842         //    hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS ); 
 843         // The above line is equivalent to the following two lines. 
 844         //    hbitmap = ::CreateCompatibleBitmap( hdc, width, height ); 
 845         //    ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS); 
 846         // or the following lines 
 847         //    hbitmap = ::CreateCompatibleBitmap( hdc, width, height ); 
 848         //    HDC memdc = ::CreateCompatibleDC( hdc ); 
 849         //    ::SelectObject( memdc, hbitmap); 
 850         //    ::SetDIBitsToDevice( memdc, 0, 0, width, height, 
 851         //            0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS); 
 852         //    ::SelectObject( memdc, 0 ); 
 853         //    ::DeleteDC( memdc ); 
 855     bitmap
.SetHBITMAP( (WXHBITMAP
) hbitmap 
); 
 857     // similarly, created an mono-bitmap for the possible mask 
 860         hbitmap 
= ::CreateBitmap( (WORD
)width
, (WORD
)bmpHeight
, 1, 1, NULL 
); 
 861         HGDIOBJ hbmpOld 
= ::SelectObject( memdc
, hbitmap
); 
 862         if( numDIB 
== 1 )   height 
= bmpHeight
; 
 863         else                height 
= sizeLimit
/bytePerLine
; 
 864         lpDIBh
->bmiHeader
.biHeight 
= (DWORD
)(-height
); 
 865         lpDIBh
->bmiHeader
.biSizeImage 
= bytePerLine
*height
; 
 867         unsigned char r 
= GetMaskRed(); 
 868         unsigned char g 
= GetMaskGreen(); 
 869         unsigned char b 
= GetMaskBlue(); 
 870         unsigned char zero 
= 0, one 
= 255; 
 872         for( n
=0; n
<numDIB
; n
++ ) 
 874             if( numDIB 
> 1 && n 
== numDIB 
- 1 && hRemain 
> 0 ) 
 876                 // redefine height and size of the (possibly) last smaller DIB 
 877                 // memory is not reallocated 
 879                 lpDIBh
->bmiHeader
.biHeight 
= (DWORD
)(-height
); 
 880                 lpDIBh
->bmiHeader
.biSizeImage 
= bytePerLine
*height
; 
 883             for( int j
=0; j
<height
; j
++ ) 
 885                 for(i
=0; i
<width
; i
++ ) 
 887                     // was causing a code gen bug in cw : if( ( cr !=r) || (cg!=g) || (cb!=b) ) 
 888                         unsigned char cr 
= (*(ptdata
++)) ; 
 889                         unsigned char cg 
= (*(ptdata
++)) ; 
 890                         unsigned char cb 
= (*(ptdata
++)) ; 
 892                     if( ( cr 
!=r
) || (cg
!=g
) || (cb
!=b
) ) 
 905                 for( i
=0; i
< padding
; i
++ )   *(ptbits
++) = zero
; 
 907             ::StretchDIBits( memdc
, 0, origin
, width
, height
,\
 
 908                 0, 0, width
, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
, SRCCOPY
); 
 911         // create a wxMask object 
 912         wxMask 
*mask 
= new wxMask(); 
 913         mask
->SetMaskBitmap( (WXHBITMAP
) hbitmap 
); 
 914         bitmap
.SetMask( mask 
); 
 915         // It will be deleted when the wxBitmap object is deleted (as of 01/1999) 
 916         /* The following can also be used but is slow to run 
 917         wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue()); 
 918         wxMask *mask = new wxMask( bitmap, colour ); 
 919         bitmap.SetMask( mask ); 
 922         ::SelectObject( memdc
, hbmpOld 
); 
 925     // free allocated resources 
 927     ::ReleaseDC(NULL
, hdc
); 
 931 #if WXWIN_COMPATIBILITY_2 
 932     // check the wxBitmap object 
 933     bitmap
.GetBitmapData()->SetOk(); 
 934 #endif // WXWIN_COMPATIBILITY_2 
 939 wxImage::wxImage( const wxBitmap 
&bitmap 
) 
 944         wxFAIL_MSG( wxT("invalid bitmap") ); 
 948     // create an wxImage object 
 949     int width 
= bitmap
.GetWidth(); 
 950     int height 
= bitmap
.GetHeight(); 
 951     Create( width
, height 
); 
 952     unsigned char *data 
= GetData(); 
 955         wxFAIL_MSG( wxT("could not allocate data for image") ); 
 959     // calc the number of bytes per scanline and padding in the DIB 
 960     int bytePerLine 
= width
*3; 
 961     int sizeDWORD 
= sizeof( DWORD 
); 
 962     int lineBoundary 
=  bytePerLine 
% sizeDWORD
; 
 964     if( lineBoundary 
> 0 ) 
 966         padding 
= sizeDWORD 
- lineBoundary
; 
 967         bytePerLine 
+= padding
; 
 970     // create a DIB header 
 971     int headersize 
= sizeof(BITMAPINFOHEADER
); 
 972     BITMAPINFO 
*lpDIBh 
= (BITMAPINFO 
*) malloc( headersize 
); 
 975         wxFAIL_MSG( wxT("could not allocate data for DIB header") ); 
 979     // Fill in the DIB header 
 980     lpDIBh
->bmiHeader
.biSize 
= headersize
; 
 981     lpDIBh
->bmiHeader
.biWidth 
= width
; 
 982     lpDIBh
->bmiHeader
.biHeight 
= -height
; 
 983     lpDIBh
->bmiHeader
.biSizeImage 
= bytePerLine 
* height
; 
 984     lpDIBh
->bmiHeader
.biPlanes 
= 1; 
 985     lpDIBh
->bmiHeader
.biBitCount 
= 24; 
 986     lpDIBh
->bmiHeader
.biCompression 
= BI_RGB
; 
 987     lpDIBh
->bmiHeader
.biClrUsed 
= 0; 
 988     // These seem not really needed for our purpose here. 
 989     lpDIBh
->bmiHeader
.biClrImportant 
= 0; 
 990     lpDIBh
->bmiHeader
.biXPelsPerMeter 
= 0; 
 991     lpDIBh
->bmiHeader
.biYPelsPerMeter 
= 0; 
 992     // memory for DIB data 
 993     unsigned char *lpBits
; 
 994     lpBits 
= (unsigned char *) malloc( lpDIBh
->bmiHeader
.biSizeImage 
); 
 997         wxFAIL_MSG( wxT("could not allocate data for DIB") ); 
1003     // copy data from the device-dependent bitmap to the DIB 
1004     HDC hdc 
= ::GetDC(NULL
); 
1006     hbitmap 
= (HBITMAP
) bitmap
.GetHBITMAP(); 
1007     ::GetDIBits( hdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS 
); 
1009     // copy DIB data into the wxImage object 
1011     unsigned char *ptdata 
= data
; 
1012     unsigned char *ptbits 
= lpBits
; 
1013     for( i
=0; i
<height
; i
++ ) 
1015         for( j
=0; j
<width
; j
++ ) 
1017             *(ptdata
++) = *(ptbits
+2); 
1018             *(ptdata
++) = *(ptbits
+1); 
1019             *(ptdata
++) = *(ptbits  
); 
1025     // similarly, set data according to the possible mask bitmap 
1026     if( bitmap
.GetMask() && bitmap
.GetMask()->GetMaskBitmap() ) 
1028         hbitmap 
= (HBITMAP
) bitmap
.GetMask()->GetMaskBitmap(); 
1029         // memory DC created, color set, data copied, and memory DC deleted 
1030         HDC memdc 
= ::CreateCompatibleDC( hdc 
); 
1031         ::SetTextColor( memdc
, RGB( 0, 0, 0 ) ); 
1032         ::SetBkColor( memdc
, RGB( 255, 255, 255 ) ); 
1033         ::GetDIBits( memdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS 
); 
1034         ::DeleteDC( memdc 
); 
1035         // background color set to RGB(16,16,16) in consistent with wxGTK 
1036         unsigned char r
=16, g
=16, b
=16; 
1039         for( i
=0; i
<height
; i
++ ) 
1041             for( j
=0; j
<width
; j
++ ) 
1055         SetMaskColour( r
, g
, b 
); 
1062     // free allocated resources 
1063     ::ReleaseDC(NULL
, hdc
); 
1072 #include <PictUtils.h> 
1074 extern CTabHandle 
wxMacCreateColorTable( int numColors 
) ; 
1075 extern void wxMacDestroyColorTable( CTabHandle colors 
) ; 
1076 extern void wxMacSetColorTableEntry( CTabHandle newColors 
, int index 
, int red 
, int green 
,  int blue 
) ; 
1077 extern GWorldPtr 
wxMacCreateGWorld( int height 
, int width 
, int depth 
) ; 
1078 extern void wxMacDestroyGWorld( GWorldPtr gw 
) ; 
1080 wxBitmap 
wxImage::ConvertToBitmap() const 
1082     // width and height of the device-dependent bitmap 
1083     int width 
= GetWidth(); 
1084     int height 
= GetHeight(); 
1088     wxBitmap 
bitmap( width 
, height 
, wxDisplayDepth() ) ; 
1095         unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height ); 
1097         mask_image =  gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height ); 
1099         wxMask *mask = new wxMask(); 
1100         mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 ); 
1102         bitmap.SetMask( mask ); 
1108     int r_mask 
= GetMaskRed(); 
1109     int g_mask 
= GetMaskGreen(); 
1110     int b_mask 
= GetMaskBlue(); 
1113                 GDHandle        origDevice 
; 
1115                 GetGWorld( &origPort 
, &origDevice 
) ; 
1116                 SetGWorld( bitmap
.GetHBITMAP() , NULL 
) ; 
1118     register unsigned char* data 
= GetData(); 
1121     for (int y 
= 0; y 
< height
; y
++) 
1123         for (int x 
= 0; x 
< width
; x
++) 
1125                     unsigned char r 
= data
[index
++]; 
1126                     unsigned char g 
= data
[index
++]; 
1127                     unsigned char b 
= data
[index
++]; 
1129                        color
.red 
= ( r  
<< 8 ) + r 
; 
1130                        color
.green 
= ( g 
<< 8 ) + g 
; 
1131                        color
.blue 
= ( b 
<< 8 ) + b 
; 
1132                        SetCPixel( x 
, y 
, &color 
) ; 
1136            SetGWorld( origPort 
, origDevice 
) ; 
1140         wxColour 
colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue()); 
1141         wxMask 
*mask 
= new wxMask( bitmap
, colour 
); 
1142         bitmap
.SetMask( mask 
); 
1148 wxImage::wxImage( const wxBitmap 
&bitmap 
) 
1153         wxFAIL_MSG( "invalid bitmap" ); 
1157     // create an wxImage object 
1158     int width 
= bitmap
.GetWidth(); 
1159     int height 
= bitmap
.GetHeight(); 
1160     Create( width
, height 
); 
1162     unsigned char *data = GetData(); 
1165         wxFAIL_MSG( "could not allocate data for image" ); 
1169     // calc the number of bytes per scanline and padding in the DIB 
1170     int bytePerLine = width*3; 
1171     int sizeDWORD = sizeof( DWORD ); 
1172     div_t lineBoundary = div( bytePerLine, sizeDWORD ); 
1174     if( lineBoundary.rem > 0 ) 
1176         padding = sizeDWORD - lineBoundary.rem; 
1177         bytePerLine += padding; 
1180     // create a DIB header 
1181     int headersize = sizeof(BITMAPINFOHEADER); 
1182     LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize ); 
1185         wxFAIL_MSG( "could not allocate data for DIB header" ); 
1189     // Fill in the DIB header 
1190     lpDIBh->bmiHeader.biSize = headersize; 
1191     lpDIBh->bmiHeader.biWidth = width; 
1192     lpDIBh->bmiHeader.biHeight = -height; 
1193     lpDIBh->bmiHeader.biSizeImage = bytePerLine * height; 
1194     lpDIBh->bmiHeader.biPlanes = 1; 
1195     lpDIBh->bmiHeader.biBitCount = 24; 
1196     lpDIBh->bmiHeader.biCompression = BI_RGB; 
1197     lpDIBh->bmiHeader.biClrUsed = 0; 
1198     // These seem not really needed for our purpose here. 
1199     lpDIBh->bmiHeader.biClrImportant = 0; 
1200     lpDIBh->bmiHeader.biXPelsPerMeter = 0; 
1201     lpDIBh->bmiHeader.biYPelsPerMeter = 0; 
1202     // memory for DIB data 
1203     unsigned char *lpBits; 
1204     lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage ); 
1207         wxFAIL_MSG( "could not allocate data for DIB" ); 
1213     // copy data from the device-dependent bitmap to the DIB 
1214     HDC hdc = ::GetDC(NULL); 
1216     hbitmap = (HBITMAP) bitmap.GetHBITMAP(); 
1217     ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS ); 
1219     // copy DIB data into the wxImage object 
1221     unsigned char *ptdata = data; 
1222     unsigned char *ptbits = lpBits; 
1223     for( i=0; i<height; i++ ) 
1225         for( j=0; j<width; j++ ) 
1227             *(ptdata++) = *(ptbits+2); 
1228             *(ptdata++) = *(ptbits+1); 
1229             *(ptdata++) = *(ptbits  ); 
1235     // similarly, set data according to the possible mask bitmap 
1236     if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() ) 
1238         hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap(); 
1239         // memory DC created, color set, data copied, and memory DC deleted 
1240         HDC memdc = ::CreateCompatibleDC( hdc ); 
1241         ::SetTextColor( memdc, RGB( 0, 0, 0 ) ); 
1242         ::SetBkColor( memdc, RGB( 255, 255, 255 ) ); 
1243         ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS ); 
1244         ::DeleteDC( memdc ); 
1245         // background color set to RGB(16,16,16) in consistent with wxGTK 
1246         unsigned char r=16, g=16, b=16; 
1249         for( i=0; i<height; i++ ) 
1251             for( j=0; j<width; j++ ) 
1265         SetMaskColour( r, g, b ); 
1272     // free allocated resources 
1273     ::ReleaseDC(NULL, hdc); 
1281 //----------------------------------------------------------------------------- 
1282 // GTK conversion routines 
1283 //----------------------------------------------------------------------------- 
1287 #include <gtk/gtk.h> 
1288 #include <gdk/gdk.h> 
1289 #include <gdk/gdkx.h> 
1291 #if (GTK_MINOR_VERSION > 0) 
1292 #include <gdk/gdkrgb.h> 
1295 extern GtkWidget 
*wxRootWindow
; 
1297 wxBitmap 
wxImage::ConvertToMonoBitmap( unsigned char red
, unsigned char green
, unsigned char blue 
) 
1301     wxCHECK_MSG( Ok(), bitmap
, wxT("invalid image") ); 
1303     int width 
= GetWidth(); 
1304     int height 
= GetHeight(); 
1306     bitmap
.SetHeight( height 
); 
1307     bitmap
.SetWidth( width 
); 
1309     bitmap
.SetBitmap( gdk_pixmap_new( wxRootWindow
->window
, width
, height
, 1 ) ); 
1311     bitmap
.SetDepth( 1 ); 
1313     GdkVisual 
*visual 
= gdk_window_get_visual( wxRootWindow
->window 
); 
1316     // Create picture image 
1318     unsigned char *data_data 
= (unsigned char*)malloc( ((width 
>> 3)+8) * height 
); 
1320     GdkImage 
*data_image 
= 
1321         gdk_image_new_bitmap( visual
, data_data
, width
, height 
); 
1323     // Create mask image 
1325     GdkImage 
*mask_image 
= (GdkImage
*) NULL
; 
1329         unsigned char *mask_data 
= (unsigned char*)malloc( ((width 
>> 3)+8) * height 
); 
1331         mask_image 
=  gdk_image_new_bitmap( visual
, mask_data
, width
, height 
); 
1333         wxMask 
*mask 
= new wxMask(); 
1334         mask
->m_bitmap 
= gdk_pixmap_new( wxRootWindow
->window
, width
, height
, 1 ); 
1336         bitmap
.SetMask( mask 
); 
1339     int r_mask 
= GetMaskRed(); 
1340     int g_mask 
= GetMaskGreen(); 
1341     int b_mask 
= GetMaskBlue(); 
1343     unsigned char* data 
= GetData(); 
1346     for (int y 
= 0; y 
< height
; y
++) 
1348         for (int x 
= 0; x 
< width
; x
++) 
1350             int r 
= data
[index
]; 
1352             int g 
= data
[index
]; 
1354             int b 
= data
[index
]; 
1359                 if ((r 
== r_mask
) && (b 
== b_mask
) && (g 
== g_mask
)) 
1360                     gdk_image_put_pixel( mask_image
, x
, y
, 1 ); 
1362                     gdk_image_put_pixel( mask_image
, x
, y
, 0 ); 
1365             if ((r 
== red
) && (b 
== blue
) && (g 
== green
)) 
1366                 gdk_image_put_pixel( data_image
, x
, y
, 1 ); 
1368                 gdk_image_put_pixel( data_image
, x
, y
, 0 ); 
1375     GdkGC 
*data_gc 
= gdk_gc_new( bitmap
.GetBitmap() ); 
1377     gdk_draw_image( bitmap
.GetBitmap(), data_gc
, data_image
, 0, 0, 0, 0, width
, height 
); 
1379     gdk_image_destroy( data_image 
); 
1380     gdk_gc_unref( data_gc 
); 
1386         GdkGC 
*mask_gc 
= gdk_gc_new( bitmap
.GetMask()->GetBitmap() ); 
1388         gdk_draw_image( bitmap
.GetMask()->GetBitmap(), mask_gc
, mask_image
, 0, 0, 0, 0, width
, height 
); 
1390         gdk_image_destroy( mask_image 
); 
1391         gdk_gc_unref( mask_gc 
); 
1398 wxBitmap 
wxImage::ConvertToBitmap() const 
1402     wxCHECK_MSG( Ok(), bitmap
, wxT("invalid image") ); 
1404     int width 
= GetWidth(); 
1405     int height 
= GetHeight(); 
1407     bitmap
.SetHeight( height 
); 
1408     bitmap
.SetWidth( width 
); 
1410     bitmap
.SetPixmap( gdk_pixmap_new( wxRootWindow
->window
, width
, height
, -1 ) ); 
1414     GdkVisual 
*visual 
= gdk_window_get_visual( wxRootWindow
->window 
); 
1417     int bpp 
= visual
->depth
; 
1419     bitmap
.SetDepth( bpp 
); 
1421     if ((bpp 
== 16) && (visual
->red_mask 
!= 0xf800)) bpp 
= 15; 
1422     if (bpp 
< 8) bpp 
= 8; 
1424 #if (GTK_MINOR_VERSION > 0) 
1426     if (!HasMask() && (bpp 
> 8)) 
1428         static bool s_hasInitialized 
= FALSE
; 
1430         if (!s_hasInitialized
) 
1433             s_hasInitialized 
= TRUE
; 
1436         GdkGC 
*gc 
= gdk_gc_new( bitmap
.GetPixmap() ); 
1438         gdk_draw_rgb_image( bitmap
.GetPixmap(), 
1442                             GDK_RGB_DITHER_NONE
, 
1453     // Create picture image 
1455     GdkImage 
*data_image 
= 
1456         gdk_image_new( GDK_IMAGE_FASTEST
, visual
, width
, height 
); 
1458     // Create mask image 
1460     GdkImage 
*mask_image 
= (GdkImage
*) NULL
; 
1464         unsigned char *mask_data 
= (unsigned char*)malloc( ((width 
>> 3)+8) * height 
); 
1466         mask_image 
=  gdk_image_new_bitmap( visual
, mask_data
, width
, height 
); 
1468         wxMask 
*mask 
= new wxMask(); 
1469         mask
->m_bitmap 
= gdk_pixmap_new( wxRootWindow
->window
, width
, height
, 1 ); 
1471         bitmap
.SetMask( mask 
); 
1476     enum byte_order 
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR 
}; 
1477     byte_order b_o 
= RGB
; 
1481         if ((visual
->red_mask 
> visual
->green_mask
) && (visual
->green_mask 
> visual
->blue_mask
))      b_o 
= RGB
; 
1482         else if ((visual
->red_mask 
> visual
->blue_mask
) && (visual
->blue_mask 
> visual
->green_mask
))  b_o 
= RGB
; 
1483         else if ((visual
->blue_mask 
> visual
->red_mask
) && (visual
->red_mask 
> visual
->green_mask
))   b_o 
= BRG
; 
1484         else if ((visual
->blue_mask 
> visual
->green_mask
) && (visual
->green_mask 
> visual
->red_mask
)) b_o 
= BGR
; 
1485         else if ((visual
->green_mask 
> visual
->red_mask
) && (visual
->red_mask 
> visual
->blue_mask
))   b_o 
= GRB
; 
1486         else if ((visual
->green_mask 
> visual
->blue_mask
) && (visual
->blue_mask 
> visual
->red_mask
))  b_o 
= GBR
; 
1489     int r_mask 
= GetMaskRed(); 
1490     int g_mask 
= GetMaskGreen(); 
1491     int b_mask 
= GetMaskBlue(); 
1493     unsigned char* data 
= GetData(); 
1496     for (int y 
= 0; y 
< height
; y
++) 
1498         for (int x 
= 0; x 
< width
; x
++) 
1500             int r 
= data
[index
]; 
1502             int g 
= data
[index
]; 
1504             int b 
= data
[index
]; 
1509                 if ((r 
== r_mask
) && (b 
== b_mask
) && (g 
== g_mask
)) 
1510                     gdk_image_put_pixel( mask_image
, x
, y
, 1 ); 
1512                     gdk_image_put_pixel( mask_image
, x
, y
, 0 ); 
1520                     if (wxTheApp
->m_colorCube
) 
1522                         pixel 
= wxTheApp
->m_colorCube
[ ((r 
& 0xf8) << 7) + ((g 
& 0xf8) << 2) + ((b 
& 0xf8) >> 3) ]; 
1526                         GdkColormap 
*cmap 
= gtk_widget_get_default_colormap(); 
1527                         GdkColor 
*colors 
= cmap
->colors
; 
1528                         int max 
= 3 * (65536); 
1530                         for (int i 
= 0; i 
< cmap
->size
; i
++) 
1532                             int rdiff 
= (r 
<< 8) - colors
[i
].red
; 
1533                             int gdiff 
= (g 
<< 8) - colors
[i
].green
; 
1534                             int bdiff 
= (b 
<< 8) - colors
[i
].blue
; 
1535                             int sum 
= ABS (rdiff
) + ABS (gdiff
) + ABS (bdiff
); 
1536                             if (sum 
< max
) { pixel 
= i
; max 
= sum
; } 
1540                     gdk_image_put_pixel( data_image
, x
, y
, pixel 
); 
1546                     guint32 pixel 
= ((r 
& 0xf8) << 7) | ((g 
& 0xf8) << 2) | ((b 
& 0xf8) >> 3); 
1547                     gdk_image_put_pixel( data_image
, x
, y
, pixel 
); 
1552                     guint32 pixel 
= ((r 
& 0xf8) << 8) | ((g 
& 0xfc) << 3) | ((b 
& 0xf8) >> 3); 
1553                     gdk_image_put_pixel( data_image
, x
, y
, pixel 
); 
1562                     case RGB
: pixel 
= (r 
<< 16) | (g 
<< 8) | b
; break; 
1563                     case RBG
: pixel 
= (r 
<< 16) | (b 
<< 8) | g
; break; 
1564                     case BRG
: pixel 
= (b 
<< 16) | (r 
<< 8) | g
; break; 
1565                     case BGR
: pixel 
= (b 
<< 16) | (g 
<< 8) | r
; break; 
1566                     case GRB
: pixel 
= (g 
<< 16) | (r 
<< 8) | b
; break; 
1567                     case GBR
: pixel 
= (g 
<< 16) | (b 
<< 8) | r
; break; 
1569                     gdk_image_put_pixel( data_image
, x
, y
, pixel 
); 
1578     GdkGC 
*data_gc 
= gdk_gc_new( bitmap
.GetPixmap() ); 
1580     gdk_draw_image( bitmap
.GetPixmap(), data_gc
, data_image
, 0, 0, 0, 0, width
, height 
); 
1582     gdk_image_destroy( data_image 
); 
1583     gdk_gc_unref( data_gc 
); 
1589         GdkGC 
*mask_gc 
= gdk_gc_new( bitmap
.GetMask()->GetBitmap() ); 
1591         gdk_draw_image( bitmap
.GetMask()->GetBitmap(), mask_gc
, mask_image
, 0, 0, 0, 0, width
, height 
); 
1593         gdk_image_destroy( mask_image 
); 
1594         gdk_gc_unref( mask_gc 
); 
1600 wxImage::wxImage( const wxBitmap 
&bitmap 
) 
1602     wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") ); 
1604     GdkImage 
*gdk_image 
= (GdkImage
*) NULL
; 
1605     if (bitmap
.GetPixmap()) 
1607         gdk_image 
= gdk_image_get( bitmap
.GetPixmap(), 
1609             bitmap
.GetWidth(), bitmap
.GetHeight() ); 
1611     if (bitmap
.GetBitmap()) 
1613         gdk_image 
= gdk_image_get( bitmap
.GetBitmap(), 
1615             bitmap
.GetWidth(), bitmap
.GetHeight() ); 
1618         wxFAIL_MSG( wxT("Ill-formed bitmap") ); 
1621     wxCHECK_RET( gdk_image
, wxT("couldn't create image") ); 
1623     Create( bitmap
.GetWidth(), bitmap
.GetHeight() ); 
1624     char unsigned *data 
= GetData(); 
1628         gdk_image_destroy( gdk_image 
); 
1629         wxFAIL_MSG( wxT("couldn't create image") ); 
1633     GdkImage 
*gdk_image_mask 
= (GdkImage
*) NULL
; 
1634     if (bitmap
.GetMask()) 
1636         gdk_image_mask 
= gdk_image_get( bitmap
.GetMask()->GetBitmap(), 
1638             bitmap
.GetWidth(), bitmap
.GetHeight() ); 
1640         SetMaskColour( 16, 16, 16 );  // anything unlikely and dividable 
1644     int red_shift_right 
= 0; 
1645     int green_shift_right 
= 0; 
1646     int blue_shift_right 
= 0; 
1647     int red_shift_left 
= 0; 
1648     int green_shift_left 
= 0; 
1649     int blue_shift_left 
= 0; 
1650     bool use_shift 
= FALSE
; 
1652     if (bitmap
.GetPixmap()) 
1654         GdkVisual 
*visual 
= gdk_window_get_visual( bitmap
.GetPixmap() ); 
1656         if (visual 
== NULL
) visual 
= gdk_window_get_visual( wxRootWindow
->window 
); 
1657         bpp 
= visual
->depth
; 
1658         if (bpp 
== 16) bpp 
= visual
->red_prec 
+ visual
->green_prec 
+ visual
->blue_prec
; 
1659         red_shift_right 
= visual
->red_shift
; 
1660         red_shift_left 
= 8-visual
->red_prec
; 
1661         green_shift_right 
= visual
->green_shift
; 
1662         green_shift_left 
= 8-visual
->green_prec
; 
1663         blue_shift_right 
= visual
->blue_shift
; 
1664         blue_shift_left 
= 8-visual
->blue_prec
; 
1666         use_shift 
= (visual
->type 
== GDK_VISUAL_TRUE_COLOR
) || (visual
->type 
== GDK_VISUAL_DIRECT_COLOR
); 
1668     if (bitmap
.GetBitmap()) 
1674     GdkColormap 
*cmap 
= gtk_widget_get_default_colormap(); 
1677     for (int j 
= 0; j 
< bitmap
.GetHeight(); j
++) 
1679         for (int i 
= 0; i 
< bitmap
.GetWidth(); i
++) 
1681             wxUint32 pixel 
= gdk_image_get_pixel( gdk_image
, i
, j 
); 
1699                 data
[pos
] =   (pixel 
>> red_shift_right
)   << red_shift_left
; 
1700                 data
[pos
+1] = (pixel 
>> green_shift_right
) << green_shift_left
; 
1701                 data
[pos
+2] = (pixel 
>> blue_shift_right
)  << blue_shift_left
; 
1703             else if (cmap
->colors
) 
1705                 data
[pos
] =   cmap
->colors
[pixel
].red   
>> 8; 
1706                 data
[pos
+1] = cmap
->colors
[pixel
].green 
>> 8; 
1707                 data
[pos
+2] = cmap
->colors
[pixel
].blue  
>> 8; 
1711                 wxFAIL_MSG( wxT("Image conversion failed. Unknown visual type.") ); 
1716                 int mask_pixel 
= gdk_image_get_pixel( gdk_image_mask
, i
, j 
); 
1717                 if (mask_pixel 
== 0) 
1729     gdk_image_destroy( gdk_image 
); 
1730     if (gdk_image_mask
) gdk_image_destroy( gdk_image_mask 
); 
1735 //----------------------------------------------------------------------------- 
1736 // Motif conversion routines 
1737 //----------------------------------------------------------------------------- 
1741 #pragma message disable nosimpint 
1745 #pragma message enable nosimpint 
1747 #include "wx/utils.h" 
1752 Date: Wed, 05 Jan 2000 11:45:40 +0100 
1753 From: Frits Boel <boel@niob.knaw.nl> 
1754 To: julian.smart@ukonline.co.uk 
1755 Subject: Patch for Motif ConvertToBitmap 
1759 I've been working on a wxWin application for image processing. From the 
1760 beginning, I was surprised by the (lack of) speed of ConvertToBitmap, 
1761 till I looked in the source code of image.cpp. I saw that converting a 
1762 wxImage to a bitmap with 8-bit pixels is done with comparing every pixel 
1763 to the 256 colors of the palet. A very time-consuming piece of code! 
1765 Because I wanted a faster application, I've made a 'patch' for this. In 
1766 short: every pixel of the image is compared to a sorted list with 
1767 colors. If the color is found in the list, the palette entry is 
1768 returned; if the color is not found, the color palette is searched and 
1769 then the palette entry is returned and the color added to the sorted 
1772 Maybe there is another method for this, namely changing the palette 
1773 itself (if the colors are known, as is the case with tiffs with a 
1774 colormap). I did not look at this, maybe someone else did? 
1776 The code of the patch is attached, have a look on it, and maybe you will 
1777 ship it with the next release of wxMotif? 
1782 Software engineer at Hubrecht Laboratory, The Netherlands. 
1789   wxSearchColor( void ); 
1790   wxSearchColor( int size
, XColor 
*colors 
); 
1791   ~wxSearchColor( void ); 
1793   int SearchColor( int r
, int g
, int b 
); 
1795   int AddColor( unsigned int value
, int pos 
); 
1799   unsigned int *color
; 
1806 wxSearchColor::wxSearchColor( void ) 
1809   colors 
= (XColor
*) NULL
; 
1810   color  
= (unsigned int *) NULL
; 
1811   entry  
= (int*) NULL
; 
1817 wxSearchColor::wxSearchColor( int size_
, XColor 
*colors_ 
) 
1822     color  
= new unsigned int[size
]; 
1823     entry  
= new int         [size
]; 
1825     for (i 
= 0; i 
< size
; i
++ ) { 
1829     bottom 
= top 
= ( size 
>> 1 ); 
1832 wxSearchColor::~wxSearchColor( void ) 
1834   if ( color 
) delete color
; 
1835   if ( entry 
) delete entry
; 
1838 int wxSearchColor::SearchColor( int r
, int g
, int b 
) 
1840   unsigned int value 
= ( ( ( r 
* 256 ) + g 
) * 256 ) + b
; 
1845   while ( begin 
<= end 
) { 
1847     middle 
= ( begin 
+ end 
) >> 1; 
1849     if ( value 
== color
[middle
] ) { 
1850       return( entry
[middle
] ); 
1851     } else if ( value 
< color
[middle
] ) { 
1859   return AddColor( value
, middle 
); 
1862 int wxSearchColor::AddColor( unsigned int value
, int pos 
) 
1866   int max 
= 3 * (65536); 
1867   for ( i 
= 0; i 
< 256; i
++ ) { 
1868     int rdiff 
= ((value 
>> 8) & 0xFF00 ) - colors
[i
].red
; 
1869     int gdiff 
= ((value     
) & 0xFF00 ) - colors
[i
].green
; 
1870     int bdiff 
= ((value 
<< 8) & 0xFF00 ) - colors
[i
].blue
; 
1871     int sum 
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
); 
1872     if (sum 
< max
) { pixel 
= i
; max 
= sum
; } 
1875   if ( entry
[pos
] < 0 ) { 
1878   } else if ( value 
< color
[pos
] ) { 
1881       for ( i 
= bottom
; i 
< pos
; i
++ ) { 
1882         color
[i
-1] = color
[i
]; 
1883         entry
[i
-1] = entry
[i
]; 
1886       color
[pos
-1] = value
; 
1887       entry
[pos
-1] = pixel
; 
1888     } else if ( top 
< size
-1 ) { 
1889       for ( i 
= top
; i 
>= pos
; i
-- ) { 
1890         color
[i
+1] = color
[i
]; 
1891         entry
[i
+1] = entry
[i
]; 
1900     if ( top 
< size
-1 ) { 
1901       for ( i 
= top
; i 
> pos
; i
-- ) { 
1902         color
[i
+1] = color
[i
]; 
1903         entry
[i
+1] = entry
[i
]; 
1906       color
[pos
+1] = value
; 
1907       entry
[pos
+1] = pixel
; 
1908     } else if ( bottom 
> 0 ) { 
1909       for ( i 
= bottom
; i 
< pos
; i
++ ) { 
1910         color
[i
-1] = color
[i
]; 
1911         entry
[i
-1] = entry
[i
]; 
1923 wxBitmap 
wxImage::ConvertToBitmap() const 
1927     wxCHECK_MSG( Ok(), bitmap
, wxT("invalid image") ); 
1929     int width 
= GetWidth(); 
1930     int height 
= GetHeight(); 
1932     bitmap
.SetHeight( height 
); 
1933     bitmap
.SetWidth( width 
); 
1935     Display 
*dpy 
= (Display
*) wxGetDisplay(); 
1936     Visual
* vis 
= DefaultVisual( dpy
, DefaultScreen( dpy 
) ); 
1937     int bpp 
= DefaultDepth( dpy
, DefaultScreen( dpy 
) ); 
1941     XImage 
*data_image 
= XCreateImage( dpy
, vis
, bpp
, ZPixmap
, 0, 0, width
, height
, 32, 0 ); 
1942     data_image
->data 
= (char*) malloc( data_image
->bytes_per_line 
* data_image
->height 
); 
1944     bitmap
.Create( width
, height
, bpp 
); 
1949       GdkImage *mask_image = (GdkImage*) NULL; 
1953         unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height ); 
1955           mask_image =  gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height ); 
1957             wxMask *mask = new wxMask(); 
1958             mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 ); 
1960               bitmap.SetMask( mask ); 
1964     // Retrieve depth info 
1966     XVisualInfo vinfo_template
; 
1969     vinfo_template
.visual 
= vis
; 
1970     vinfo_template
.visualid 
= XVisualIDFromVisual( vis 
); 
1971     vinfo_template
.depth 
= bpp
; 
1974     vi 
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem 
); 
1976     wxCHECK_MSG( vi
, wxNullBitmap
, wxT("no visual") ); 
1980     if ((bpp 
== 16) && (vi
->red_mask 
!= 0xf800)) bpp 
= 15; 
1981     if (bpp 
< 8) bpp 
= 8; 
1985     enum byte_order 
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR 
}; 
1986     byte_order b_o 
= RGB
; 
1990         if ((vi
->red_mask 
> vi
->green_mask
) && (vi
->green_mask 
> vi
->blue_mask
))      b_o 
= RGB
; 
1991         else if ((vi
->red_mask 
> vi
->blue_mask
) && (vi
->blue_mask 
> vi
->green_mask
))  b_o 
= RGB
; 
1992         else if ((vi
->blue_mask 
> vi
->red_mask
) && (vi
->red_mask 
> vi
->green_mask
))   b_o 
= BRG
; 
1993         else if ((vi
->blue_mask 
> vi
->green_mask
) && (vi
->green_mask 
> vi
->red_mask
)) b_o 
= BGR
; 
1994         else if ((vi
->green_mask 
> vi
->red_mask
) && (vi
->red_mask 
> vi
->blue_mask
))   b_o 
= GRB
; 
1995         else if ((vi
->green_mask 
> vi
->blue_mask
) && (vi
->blue_mask 
> vi
->red_mask
))  b_o 
= GBR
; 
1999     int r_mask = GetMaskRed(); 
2000     int g_mask = GetMaskGreen(); 
2001     int b_mask = GetMaskBlue(); 
2007         Colormap cmap 
= (Colormap
) wxTheApp
->GetMainColormap( dpy 
); 
2009         for (int i 
= 0; i 
< 256; i
++) colors
[i
].pixel 
= i
; 
2010         XQueryColors( dpy
, cmap
, colors
, 256 ); 
2013     wxSearchColor 
scolor( 256, colors 
); 
2014     unsigned char* data 
= GetData(); 
2017     for (int y 
= 0; y 
< height
; y
++) 
2019         for (int x 
= 0; x 
< width
; x
++) 
2021             int r 
= data
[index
]; 
2023             int g 
= data
[index
]; 
2025             int b 
= data
[index
]; 
2031             if ((r == r_mask) && (b == b_mask) && (g == g_mask)) 
2032             gdk_image_put_pixel( mask_image, x, y, 1 ); 
2034             gdk_image_put_pixel( mask_image, x, y, 0 ); 
2042 #if 0 // Old, slower code 
2045                     if (wxTheApp->m_colorCube) 
2047                     pixel = wxTheApp->m_colorCube 
2048                     [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ]; 
2053                     int max 
= 3 * (65536); 
2054                     for (int i 
= 0; i 
< 256; i
++) 
2056                         int rdiff 
= (r 
<< 8) - colors
[i
].red
; 
2057                         int gdiff 
= (g 
<< 8) - colors
[i
].green
; 
2058                         int bdiff 
= (b 
<< 8) - colors
[i
].blue
; 
2059                         int sum 
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
); 
2060                         if (sum 
< max
) { pixel 
= i
; max 
= sum
; } 
2067                     // And this is all to get the 'right' color... 
2068                     int pixel 
= scolor
.SearchColor( r
, g
, b 
); 
2069                     XPutPixel( data_image
, x
, y
, pixel 
); 
2074                     int pixel 
= ((r 
& 0xf8) << 7) | ((g 
& 0xf8) << 2) | ((b 
& 0xf8) >> 3); 
2075                     XPutPixel( data_image
, x
, y
, pixel 
); 
2080                     int pixel 
= ((r 
& 0xf8) << 8) | ((g 
& 0xfc) << 3) | ((b 
& 0xf8) >> 3); 
2081                     XPutPixel( data_image
, x
, y
, pixel 
); 
2090                     case RGB
: pixel 
= (r 
<< 16) | (g 
<< 8) | b
; break; 
2091                     case RBG
: pixel 
= (r 
<< 16) | (b 
<< 8) | g
; break; 
2092                     case BRG
: pixel 
= (b 
<< 16) | (r 
<< 8) | g
; break; 
2093                     case BGR
: pixel 
= (b 
<< 16) | (g 
<< 8) | r
; break; 
2094                     case GRB
: pixel 
= (g 
<< 16) | (r 
<< 8) | b
; break; 
2095                     case GBR
: pixel 
= (g 
<< 16) | (b 
<< 8) | r
; break; 
2097                     XPutPixel( data_image
, x
, y
, pixel 
); 
2107     gcvalues
.foreground 
= BlackPixel( dpy
, DefaultScreen( dpy 
) ); 
2108     GC gc 
= XCreateGC( dpy
, RootWindow ( dpy
, DefaultScreen(dpy
) ), GCForeground
, &gcvalues 
); 
2109     XPutImage( dpy
, (Drawable
)bitmap
.GetPixmap(), gc
, data_image
, 0, 0, 0, 0, width
, height 
); 
2111     XDestroyImage( data_image 
); 
2119       GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() ); 
2121         gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height ); 
2123           gdk_image_destroy( mask_image ); 
2124           gdk_gc_unref( mask_gc ); 
2131 wxImage::wxImage( const wxBitmap 
&bitmap 
) 
2133     wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") ); 
2135     Display 
*dpy 
= (Display
*) wxGetDisplay(); 
2136     Visual
* vis 
= DefaultVisual( dpy
, DefaultScreen( dpy 
) ); 
2137     int bpp 
= DefaultDepth( dpy
, DefaultScreen( dpy 
) ); 
2139     XImage 
*ximage 
= XGetImage( dpy
, 
2140         (Drawable
)bitmap
.GetPixmap(), 
2142         bitmap
.GetWidth(), bitmap
.GetHeight(), 
2143         AllPlanes
, ZPixmap 
); 
2145     wxCHECK_RET( ximage
, wxT("couldn't create image") ); 
2147     Create( bitmap
.GetWidth(), bitmap
.GetHeight() ); 
2148     char unsigned *data 
= GetData(); 
2152         XDestroyImage( ximage 
); 
2153         wxFAIL_MSG( wxT("couldn't create image") ); 
2158     GdkImage *gdk_image_mask = (GdkImage*) NULL; 
2159     if (bitmap.GetMask()) 
2161     gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(), 
2163     bitmap.GetWidth(), bitmap.GetHeight() ); 
2165       SetMaskColour( 16, 16, 16 );  // anything unlikely and dividable 
2169     // Retrieve depth info 
2171     XVisualInfo vinfo_template
; 
2174     vinfo_template
.visual 
= vis
; 
2175     vinfo_template
.visualid 
= XVisualIDFromVisual( vis 
); 
2176     vinfo_template
.depth 
= bpp
; 
2179     vi 
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem 
); 
2181     wxCHECK_RET( vi
, wxT("no visual") ); 
2183     if ((bpp 
== 16) && (vi
->red_mask 
!= 0xf800)) bpp 
= 15; 
2190         Colormap cmap 
= (Colormap
)wxTheApp
->GetMainColormap( dpy 
); 
2192         for (int i 
= 0; i 
< 256; i
++) colors
[i
].pixel 
= i
; 
2193         XQueryColors( dpy
, cmap
, colors
, 256 ); 
2197     for (int j 
= 0; j 
< bitmap
.GetHeight(); j
++) 
2199         for (int i 
= 0; i 
< bitmap
.GetWidth(); i
++) 
2201             int pixel 
= XGetPixel( ximage
, i
, j 
); 
2204                 data
[pos
] = colors
[pixel
].red 
>> 8; 
2205                 data
[pos
+1] = colors
[pixel
].green 
>> 8; 
2206                 data
[pos
+2] = colors
[pixel
].blue 
>> 8; 
2207             } else if (bpp 
== 15) 
2209                 data
[pos
] = (pixel 
>> 7) & 0xf8; 
2210                 data
[pos
+1] = (pixel 
>> 2) & 0xf8; 
2211                 data
[pos
+2] = (pixel 
<< 3) & 0xf8; 
2212             } else if (bpp 
== 16) 
2214                 data
[pos
] = (pixel 
>> 8) & 0xf8; 
2215                 data
[pos
+1] = (pixel 
>> 3) & 0xfc; 
2216                 data
[pos
+2] = (pixel 
<< 3) & 0xf8; 
2219                 data
[pos
] = (pixel 
>> 16) & 0xff; 
2220                 data
[pos
+1] = (pixel 
>> 8) & 0xff; 
2221                 data
[pos
+2] = pixel 
& 0xff; 
2227             int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j ); 
2228             if (mask_pixel == 0) 
2241     XDestroyImage( ximage 
); 
2243     if (gdk_image_mask) gdk_image_destroy( gdk_image_mask ); 
2249 // OS/2 Presentation manager conversion routings 
2251 wxBitmap 
wxImage::ConvertToBitmap() const 
2254         return wxNullBitmap
; 
2255     wxBitmap bitmap
; // remove 
2258     int sizeLimit = 1024*768*3; 
2260     // width and height of the device-dependent bitmap 
2261     int width = GetWidth(); 
2262     int bmpHeight = GetHeight(); 
2264     // calc the number of bytes per scanline and padding 
2265     int bytePerLine = width*3; 
2266     int sizeDWORD = sizeof( DWORD ); 
2267     int lineBoundary = bytePerLine % sizeDWORD; 
2269     if( lineBoundary > 0 ) 
2271         padding = sizeDWORD - lineBoundary; 
2272         bytePerLine += padding; 
2274     // calc the number of DIBs and heights of DIBs 
2277     int height = sizeLimit/bytePerLine; 
2278     if( height >= bmpHeight ) 
2282         numDIB =  bmpHeight / height; 
2283         hRemain = bmpHeight % height; 
2284         if( hRemain >0 )  numDIB++; 
2287     // set bitmap parameters 
2289     wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") ); 
2290     bitmap.SetWidth( width ); 
2291     bitmap.SetHeight( bmpHeight ); 
2292     bitmap.SetDepth( wxDisplayDepth() ); 
2294     // create a DIB header 
2295     int headersize = sizeof(BITMAPINFOHEADER); 
2296     LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize ); 
2297     wxCHECK_MSG( lpDIBh, bitmap, wxT("could not allocate memory for DIB header") ); 
2298     // Fill in the DIB header 
2299     lpDIBh->bmiHeader.biSize = headersize; 
2300     lpDIBh->bmiHeader.biWidth = (DWORD)width; 
2301     lpDIBh->bmiHeader.biHeight = (DWORD)(-height); 
2302     lpDIBh->bmiHeader.biSizeImage = bytePerLine*height; 
2303     //   the general formula for biSizeImage: 
2304     //      ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height; 
2305     lpDIBh->bmiHeader.biPlanes = 1; 
2306     lpDIBh->bmiHeader.biBitCount = 24; 
2307     lpDIBh->bmiHeader.biCompression = BI_RGB; 
2308     lpDIBh->bmiHeader.biClrUsed = 0; 
2309     // These seem not really needed for our purpose here. 
2310     lpDIBh->bmiHeader.biClrImportant = 0; 
2311     lpDIBh->bmiHeader.biXPelsPerMeter = 0; 
2312     lpDIBh->bmiHeader.biYPelsPerMeter = 0; 
2313     // memory for DIB data 
2314     unsigned char *lpBits; 
2315     lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage ); 
2318         wxFAIL_MSG( wxT("could not allocate memory for DIB") ); 
2323     // create and set the device-dependent bitmap 
2324     HDC hdc = ::GetDC(NULL); 
2325     HDC memdc = ::CreateCompatibleDC( hdc ); 
2327     hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight ); 
2328     ::SelectObject( memdc, hbitmap); 
2330     // copy image data into DIB data and then into DDB (in a loop) 
2331     unsigned char *data = GetData(); 
2334     unsigned char *ptdata = data; 
2335     unsigned char *ptbits; 
2337     for( n=0; n<numDIB; n++ ) 
2339         if( numDIB > 1 && n == numDIB-1 && hRemain > 0 ) 
2341             // redefine height and size of the (possibly) last smaller DIB 
2342             // memory is not reallocated 
2344             lpDIBh->bmiHeader.biHeight = (DWORD)(-height); 
2345             lpDIBh->bmiHeader.biSizeImage = bytePerLine*height; 
2349         for( j=0; j<height; j++ ) 
2351             for( i=0; i<width; i++ ) 
2353                 *(ptbits++) = *(ptdata+2); 
2354                 *(ptbits++) = *(ptdata+1); 
2355                 *(ptbits++) = *(ptdata  ); 
2358             for( i=0; i< padding; i++ )   *(ptbits++) = 0; 
2360         ::StretchDIBits( memdc, 0, origin, width, height,\ 
2361             0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY); 
2363         // if numDIB = 1,  lines below can also be used 
2364         //    hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS ); 
2365         // The above line is equivalent to the following two lines. 
2366         //    hbitmap = ::CreateCompatibleBitmap( hdc, width, height ); 
2367         //    ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS); 
2368         // or the following lines 
2369         //    hbitmap = ::CreateCompatibleBitmap( hdc, width, height ); 
2370         //    HDC memdc = ::CreateCompatibleDC( hdc ); 
2371         //    ::SelectObject( memdc, hbitmap); 
2372         //    ::SetDIBitsToDevice( memdc, 0, 0, width, height, 
2373         //            0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS); 
2374         //    ::SelectObject( memdc, 0 ); 
2375         //    ::DeleteDC( memdc ); 
2377     bitmap.SetHBITMAP( (WXHBITMAP) hbitmap ); 
2379     // similarly, created an mono-bitmap for the possible mask 
2382         hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL ); 
2383         ::SelectObject( memdc, hbitmap); 
2384         if( numDIB == 1 )   height = bmpHeight; 
2385         else                height = sizeLimit/bytePerLine; 
2386         lpDIBh->bmiHeader.biHeight = (DWORD)(-height); 
2387         lpDIBh->bmiHeader.biSizeImage = bytePerLine*height; 
2389         unsigned char r = GetMaskRed(); 
2390         unsigned char g = GetMaskGreen(); 
2391         unsigned char b = GetMaskBlue(); 
2392         unsigned char zero = 0, one = 255; 
2394         for( n=0; n<numDIB; n++ ) 
2396             if( numDIB > 1 && n == numDIB - 1 && hRemain > 0 ) 
2398                 // redefine height and size of the (possibly) last smaller DIB 
2399                 // memory is not reallocated 
2401                 lpDIBh->bmiHeader.biHeight = (DWORD)(-height); 
2402                 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height; 
2405             for( int j=0; j<height; j++ ) 
2407                 for(i=0; i<width; i++ ) 
2409                     if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) ) 
2422                 for( i=0; i< padding; i++ )   *(ptbits++) = zero; 
2424             ::StretchDIBits( memdc, 0, origin, width, height,\ 
2425                 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY); 
2428         // create a wxMask object 
2429         wxMask *mask = new wxMask(); 
2430         mask->SetMaskBitmap( (WXHBITMAP) hbitmap ); 
2431         bitmap.SetMask( mask ); 
2434     // free allocated resources 
2435     ::SelectObject( memdc, 0 ); 
2436     ::DeleteDC( memdc ); 
2437     ::ReleaseDC(NULL, hdc); 
2441     // check the wxBitmap object 
2442     if( bitmap.GetHBITMAP() ) 
2443         bitmap.SetOk( TRUE ); 
2445         bitmap.SetOk( FALSE ); 
2450 wxImage::wxImage( const wxBitmap 
&bitmap 
) 
2455         wxFAIL_MSG( wxT("invalid bitmap") ); 
2459     // create an wxImage object 
2460     int width 
= bitmap
.GetWidth(); 
2461     int height 
= bitmap
.GetHeight(); 
2462     Create( width
, height 
); 
2463     unsigned char *data 
= GetData(); 
2466         wxFAIL_MSG( wxT("could not allocate data for image") ); 
2470     // calc the number of bytes per scanline and padding in the DIB 
2471     int bytePerLine 
= width
*3; 
2472     int sizeDWORD 
= sizeof( DWORD 
); 
2473     int lineBoundary 
=  bytePerLine 
% sizeDWORD
; 
2475     if( lineBoundary 
> 0 ) 
2477         padding 
= sizeDWORD 
- lineBoundary
; 
2478         bytePerLine 
+= padding
; 
2482     // create a DIB header 
2483     int headersize = sizeof(BITMAPINFOHEADER); 
2484     LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize ); 
2487         wxFAIL_MSG( wxT("could not allocate data for DIB header") ); 
2491     // Fill in the DIB header 
2492     lpDIBh->bmiHeader.biSize = headersize; 
2493     lpDIBh->bmiHeader.biWidth = width; 
2494     lpDIBh->bmiHeader.biHeight = -height; 
2495     lpDIBh->bmiHeader.biSizeImage = bytePerLine * height; 
2496     lpDIBh->bmiHeader.biPlanes = 1; 
2497     lpDIBh->bmiHeader.biBitCount = 24; 
2498     lpDIBh->bmiHeader.biCompression = BI_RGB; 
2499     lpDIBh->bmiHeader.biClrUsed = 0; 
2500     // These seem not really needed for our purpose here. 
2501     lpDIBh->bmiHeader.biClrImportant = 0; 
2502     lpDIBh->bmiHeader.biXPelsPerMeter = 0; 
2503     lpDIBh->bmiHeader.biYPelsPerMeter = 0; 
2504     // memory for DIB data 
2505     unsigned char *lpBits; 
2506     lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage ); 
2509         wxFAIL_MSG( wxT("could not allocate data for DIB") ); 
2515     // copy data from the device-dependent bitmap to the DIB 
2516     HDC hdc = ::GetDC(NULL); 
2518     hbitmap = (HBITMAP) bitmap.GetHBITMAP(); 
2519     ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS ); 
2521     // copy DIB data into the wxImage object 
2523     unsigned char *ptdata = data; 
2524     unsigned char *ptbits = lpBits; 
2525     for( i=0; i<height; i++ ) 
2527         for( j=0; j<width; j++ ) 
2529             *(ptdata++) = *(ptbits+2); 
2530             *(ptdata++) = *(ptbits+1); 
2531             *(ptdata++) = *(ptbits  ); 
2537     // similarly, set data according to the possible mask bitmap 
2538     if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() ) 
2540         hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap(); 
2541         // memory DC created, color set, data copied, and memory DC deleted 
2542         HDC memdc = ::CreateCompatibleDC( hdc ); 
2543         ::SetTextColor( memdc, RGB( 0, 0, 0 ) ); 
2544         ::SetBkColor( memdc, RGB( 255, 255, 255 ) ); 
2545         ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS ); 
2546         ::DeleteDC( memdc ); 
2547         // background color set to RGB(16,16,16) in consistent with wxGTK 
2548         unsigned char r=16, g=16, b=16; 
2551         for( i=0; i<height; i++ ) 
2553             for( j=0; j<width; j++ ) 
2567         SetMaskColour( r, g, b ); 
2574     // free allocated resources 
2575     ::ReleaseDC(NULL, hdc); 
2583 // A module to allow wxImage initialization/cleanup 
2584 // without calling these functions from app.cpp or from 
2585 // the user's application. 
2587 class wxImageModule
: public wxModule
 
2589 DECLARE_DYNAMIC_CLASS(wxImageModule
) 
2592     bool OnInit() { wxImage::InitStandardHandlers(); return TRUE
; }; 
2593     void OnExit() { wxImage::CleanUpHandlers(); }; 
2596 IMPLEMENT_DYNAMIC_CLASS(wxImageModule
, wxModule
) 
2599 //----------------------------------------------------------------------------- 
2602 // Counts and returns the number of different colours. Optionally stops 
2603 // when it exceeds 'stopafter' different colours. This is useful, for 
2604 // example, to see if the image can be saved as 8-bit (256 colour or 
2605 // less, in this case it would be invoked as CountColours(256)). Default 
2606 // value for stopafter is -1 (don't care). 
2608 unsigned long wxImage::CountColours( unsigned long stopafter 
) 
2613     unsigned char r
, g
, b
, *p
; 
2614     unsigned long size
, nentries
, key
; 
2617     size 
= GetWidth() * GetHeight(); 
2620     for (unsigned long j 
= 0; (j 
< size
) && (nentries 
<= stopafter
) ; j
++) 
2625         key 
= (r 
<< 16) | (g 
<< 8) | b
; 
2627         hnode 
= (wxHNode 
*) h
.Get(key
); 
2631             h
.Put(key
, (wxObject 
*)(new wxHNode
)); 
2636     // delete all HNodes 
2638     while ((node 
= h
.Next()) != NULL
) 
2639         delete (wxHNode 
*)node
->GetData(); 
2646 // Computes the histogram of the image and fills a hash table, indexed 
2647 // with integer keys built as 0xRRGGBB, containing wxHNode objects. Each 
2648 // wxHNode contains an 'index' (useful to build a palette with the image 
2649 // colours) and a 'value', which is the number of pixels in the image with 
2652 unsigned long wxImage::ComputeHistogram( wxHashTable 
&h 
) 
2654     unsigned char r
, g
, b
, *p
; 
2655     unsigned long size
, nentries
, key
; 
2659     size 
= GetWidth() * GetHeight(); 
2662     for (unsigned long j 
= 0; j 
< size
; j
++) 
2667         key 
= (r 
<< 16) | (g 
<< 8) | b
; 
2669         hnode 
= (wxHNode 
*) h
.Get(key
); 
2675             hnode 
= new wxHNode(); 
2676             hnode
->index 
= nentries
++; 
2679             h
.Put(key
, (wxObject 
*)hnode
); 
2687  * Rotation code by Carlos Moreno 
2690 struct wxRotationPixel
 
2692     unsigned char rgb
[3]; 
2695 struct wxRotationPoint
 
2697         wxRotationPoint (double _x
, double _y
) : x(_x
), y(_y
) {} 
2698         wxRotationPoint (const wxPoint 
& p
) : x(p
.x
), y(p
.y
) {} 
2702 static const wxRotationPixel gs_BlankPixel 
= {0,0,0}; 
2703 static const double gs_Epsilon 
= 1e-10; 
2705 static inline int wxCint (double x
) 
2707     return (x 
> 0) ? (int) (x 
+ 0.5) : (int) (x 
- 0.5); 
2711 // Auxiliary function to rotate a point (x,y) with respect to point p0 
2712 // make it inline and use a straight return to facilitate optimization 
2713 // also, the function receives the sine and cosine of the angle to avoid 
2714 // repeating the time-consuming calls to these functions -- sin/cos can 
2715 // be computed and stored in the calling function. 
2717 inline wxRotationPoint 
rotated_point (const wxRotationPoint 
& p
, double cos_angle
, double sin_angle
, const wxRotationPoint 
& p0
) 
2719     return wxRotationPoint (p0
.x 
+ (p
.x 
- p0
.x
) * cos_angle 
- (p
.y 
- p0
.y
) * sin_angle
, 
2720                   p0
.y 
+ (p
.y 
- p0
.y
) * cos_angle 
+ (p
.x 
- p0
.x
) * sin_angle
); 
2723 inline wxRotationPoint 
rotated_point (double x
, double y
, double cos_angle
, double sin_angle
, const wxRotationPoint 
& p0
) 
2725     return rotated_point (wxRotationPoint(x
,y
), cos_angle
, sin_angle
, p0
); 
2728 wxImage 
wxImage::Rotate(double angle
, const wxPoint 
& centre_of_rotation
, bool interpolating
, wxPoint 
* offset_after_rotation
) const 
2730     const wxImage
& img 
= * this; 
2732     angle 
= -angle
;     // screen coordinates are a mirror image of "real" coordinates 
2734         // Create pointer-based array to accelerate access to wxImage's data 
2735     wxRotationPixel 
** data 
= new wxRotationPixel 
* [img
.GetHeight()]; 
2737     data
[0] = (wxRotationPixel 
*) img
.GetData(); 
2739     for (i 
= 1; i 
< img
.GetHeight(); i
++) 
2741         data
[i
] = data
[i 
- 1] + img
.GetWidth(); 
2744         // pre-compute coefficients for rotation formula (sine and cosine of the angle) 
2745     const double cos_angle 
= cos(angle
); 
2746     const double sin_angle 
= sin(angle
); 
2748         // Create new Image to store the result 
2749             // First, find rectangle that covers the rotated image;  to do that, 
2750             // rotate the four corners 
2752     const wxRotationPoint 
& p0 
= centre_of_rotation
; 
2754     wxRotationPoint p1 
= rotated_point (0, 0, cos_angle
, sin_angle
, p0
); 
2755     wxRotationPoint p2 
= rotated_point (0, img
.GetHeight(), cos_angle
, sin_angle
, p0
); 
2756     wxRotationPoint p3 
= rotated_point (img
.GetWidth(), 0, cos_angle
, sin_angle
, p0
); 
2757     wxRotationPoint p4 
= rotated_point (img
.GetWidth(), img
.GetHeight(), cos_angle
, sin_angle
, p0
); 
2759     int x1 
= floor (wxMin (wxMin(p1
.x
, p2
.x
), wxMin(p3
.x
, p4
.x
))); 
2760     int y1 
= floor (wxMin (wxMin(p1
.y
, p2
.y
), wxMin(p3
.y
, p4
.y
))); 
2762     int x2 
= ceil (wxMax (wxMax(p1
.x
, p2
.x
), wxMax(p3
.x
, p4
.x
))); 
2763     int y2 
= ceil (wxMax (wxMax(p1
.y
, p2
.y
), wxMax(p3
.y
, p4
.y
))); 
2765     wxImage 
rotated (x2 
- x1 
+ 1, y2 
- y1 
+ 1); 
2767     if (offset_after_rotation 
!= NULL
) 
2769         *offset_after_rotation 
= wxPoint (x1
, y1
); 
2773     wxRotationPixel 
** result_data 
= new wxRotationPixel 
* [rotated
.GetHeight()]; 
2775     result_data
[0] = (wxRotationPixel 
*) rotated
.GetData(); 
2777     for (i 
= 1; i 
< rotated
.GetHeight(); i
++) 
2779         result_data
[i
] = result_data
[i 
- 1] + rotated
.GetWidth(); 
2782         // Now, for each point of the rotated image, find where it came from, by 
2783         // performing an inverse rotation (a rotation of -angle) and getting the 
2784         // pixel at those coordinates 
2787     for (x 
= 0; x 
< rotated
.GetWidth(); x
++) 
2789         for (int y 
= 0; y 
< rotated
.GetHeight(); y
++) 
2791             wxRotationPoint src 
= rotated_point (x 
+ x1
, y 
+ y1
, cos_angle
, -sin_angle
, p0
); 
2795                 if (0 < src
.x 
&& src
.x 
< img
.GetWidth() - 1 && 
2796                     0 < src
.y 
&& src
.y 
< img
.GetHeight() - 1) 
2798                         // interpolate using the 4 enclosing grid-points.  Those 
2799                         // points can be obtained using floor and ceiling of the 
2800                         // exact coordinates of the point 
2802                     const int x1 
= wxCint(floor(src
.x
)); 
2803                     const int y1 
= wxCint(floor(src
.y
)); 
2804                     const int x2 
= wxCint(ceil(src
.x
)); 
2805                     const int y2 
= wxCint(ceil(src
.y
)); 
2807                         // get four points and the distances (square of the distance, 
2808                         // for efficiency reasons) for the interpolation formula 
2809                     const wxRotationPixel 
& v1 
= data
[y1
][x1
]; 
2810                     const wxRotationPixel 
& v2 
= data
[y1
][x2
]; 
2811                     const wxRotationPixel 
& v3 
= data
[y2
][x2
]; 
2812                     const wxRotationPixel 
& v4 
= data
[y2
][x1
]; 
2814                     const double d1 
= (src
.x 
- x1
) * (src
.x 
- x1
) + (src
.y 
- y1
) * (src
.y 
- y1
); 
2815                     const double d2 
= (src
.x 
- x2
) * (src
.x 
- x2
) + (src
.y 
- y1
) * (src
.y 
- y1
); 
2816                     const double d3 
= (src
.x 
- x2
) * (src
.x 
- x2
) + (src
.y 
- y2
) * (src
.y 
- y2
); 
2817                     const double d4 
= (src
.x 
- x1
) * (src
.x 
- x1
) + (src
.y 
- y2
) * (src
.y 
- y2
); 
2819                         // Now interpolate as a weighted average of the four surrounding 
2820                         // points, where the weights are the distances to each of those points 
2822                         // If the point is exactly at one point of the grid of the source 
2823                         // image, then don't interpolate -- just assign the pixel 
2825                     if (d1 
< gs_Epsilon
)                // d1,d2,d3,d4 are positive -- no need for abs() 
2827                         result_data
[y
][x
] = v1
; 
2829                     else if (d2 
< gs_Epsilon
) 
2831                         result_data
[y
][x
] = v2
; 
2833                     else if (d3 
< gs_Epsilon
) 
2835                         result_data
[y
][x
] = v3
; 
2837                     else if (d4 
< gs_Epsilon
) 
2839                         result_data
[y
][x
] = v4
; 
2843                                 // weights for the weighted average are proportional to the inverse of the distance 
2844                         const w1 
= 1/d1
, w2 
= 1/d2
, w3 
= 1/d3
, w4 
= 1/d4
; 
2846                             for (int i 
= 0; i 
< 3; i
++)     // repeat calculation for R, G, and B 
2848                                 result_data
[y
][x
].rgb
[i
] = 
2849                                 (unsigned char) ( (w1 
* v1
.rgb
[i
] + w2 
* v2
.rgb
[i
] + 
2850                                                                  w3 
* v3
.rgb
[i
] + w4 
* v4
.rgb
[i
]) / 
2851                                                              (w1 
+ w2 
+ w3 
+ w4
) ); 
2857                     result_data
[y
][x
] = gs_BlankPixel
; 
2862                 const int & xs 
= wxCint (src
.x
);      // wxCint performs rounding to the 
2863                 const int & ys 
= wxCint (src
.y
);      // closest integer 
2865                 if (0 <= xs 
&& xs 
< img
.GetWidth() && 
2866                     0 <= ys 
&& ys 
< img
.GetHeight()) 
2868                     result_data
[y
][x
] = data
[ys
][xs
]; 
2872                     result_data
[y
][x
] = gs_BlankPixel
;