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"
39 #include "wx/msw/private.h"
42 //-----------------------------------------------------------------------------
44 //-----------------------------------------------------------------------------
46 class wxImageRefData
: public wxObjectRefData
54 unsigned char *m_data
;
56 unsigned char m_maskRed
,m_maskGreen
,m_maskBlue
;
60 wxImageRefData::wxImageRefData()
64 m_data
= (unsigned char*) NULL
;
72 wxImageRefData::~wxImageRefData()
78 wxList
wxImage::sm_handlers
;
80 //-----------------------------------------------------------------------------
82 #define M_IMGDATA ((wxImageRefData *)m_refData)
84 IMPLEMENT_DYNAMIC_CLASS(wxImage
, wxObject
)
90 wxImage::wxImage( int width
, int height
)
92 Create( width
, height
);
95 wxImage::wxImage( const wxString
& name
, long type
)
97 LoadFile( name
, type
);
100 wxImage::wxImage( const wxString
& name
, const wxString
& mimetype
)
102 LoadFile( name
, mimetype
);
106 wxImage::wxImage( wxInputStream
& stream
, long type
)
108 LoadFile( stream
, type
);
111 wxImage::wxImage( wxInputStream
& stream
, const wxString
& mimetype
)
113 LoadFile( stream
, mimetype
);
115 #endif // wxUSE_STREAMS
117 wxImage::wxImage( const wxImage
& image
)
122 wxImage::wxImage( const wxImage
* image
)
124 if (image
) Ref(*image
);
127 void wxImage::Create( int width
, int height
)
129 m_refData
= new wxImageRefData();
131 M_IMGDATA
->m_data
= (unsigned char *) malloc( width
*height
*3 );
132 if (M_IMGDATA
->m_data
)
134 for (int l
= 0; l
< width
*height
*3; l
++) M_IMGDATA
->m_data
[l
] = 0;
136 M_IMGDATA
->m_width
= width
;
137 M_IMGDATA
->m_height
= height
;
138 M_IMGDATA
->m_ok
= TRUE
;
146 void wxImage::Destroy()
151 wxImage
wxImage::Scale( int width
, int height
) const
155 wxCHECK_MSG( Ok(), image
, wxT("invalid image") );
157 wxCHECK_MSG( (width
> 0) && (height
> 0), image
, wxT("invalid image size") );
159 image
.Create( width
, height
);
161 char unsigned *data
= image
.GetData();
163 wxCHECK_MSG( data
, image
, wxT("unable to create image") );
165 if (M_IMGDATA
->m_hasMask
)
166 image
.SetMaskColour( M_IMGDATA
->m_maskRed
, M_IMGDATA
->m_maskGreen
, M_IMGDATA
->m_maskBlue
);
168 long old_height
= M_IMGDATA
->m_height
;
169 long old_width
= M_IMGDATA
->m_width
;
171 char unsigned *source_data
= M_IMGDATA
->m_data
;
172 char unsigned *target_data
= data
;
174 for (long j
= 0; j
< height
; j
++)
176 long y_offset
= (j
* old_height
/ height
) * old_width
;
178 for (long i
= 0; i
< width
; i
++)
181 source_data
+ 3*(y_offset
+ ((i
* old_width
)/ width
)),
190 wxImage
wxImage::GetSubImage( const wxRect
&rect
) const
194 wxCHECK_MSG( Ok(), image
, wxT("invalid image") );
196 wxCHECK_MSG( (rect
.GetLeft()>=0) && (rect
.GetTop()>=0) && (rect
.GetRight()<=GetWidth()) && (rect
.GetBottom()<=GetHeight()),
197 image
, wxT("invalid subimage size") );
199 int subwidth
=rect
.GetWidth();
200 const int subheight
=rect
.GetHeight();
202 image
.Create( subwidth
, subheight
);
204 char unsigned *subdata
= image
.GetData(), *data
=GetData();
206 wxCHECK_MSG( subdata
, image
, wxT("unable to create image") );
208 if (M_IMGDATA
->m_hasMask
)
209 image
.SetMaskColour( M_IMGDATA
->m_maskRed
, M_IMGDATA
->m_maskGreen
, M_IMGDATA
->m_maskBlue
);
211 const int subleft
=3*rect
.GetLeft();
212 const int width
=3*GetWidth();
215 data
+=rect
.GetTop()*width
+subleft
;
217 for (long j
= 0; j
< subheight
; ++j
)
219 memcpy( subdata
, data
, subwidth
);
227 void wxImage::Replace( unsigned char r1
, unsigned char g1
, unsigned char b1
,
228 unsigned char r2
, unsigned char g2
, unsigned char b2
)
230 wxCHECK_RET( Ok(), wxT("invalid image") );
232 char unsigned *data
= GetData();
234 const int w
= GetWidth();
235 const int h
= GetHeight();
237 for (int j
= 0; j
< h
; j
++)
238 for (int i
= 0; i
< w
; i
++)
240 if ((data
[0] == r1
) && (data
[1] == g1
) && (data
[2] == b1
))
250 void wxImage::SetRGB( int x
, int y
, unsigned char r
, unsigned char g
, unsigned char b
)
252 wxCHECK_RET( Ok(), wxT("invalid image") );
254 int w
= M_IMGDATA
->m_width
;
255 int h
= M_IMGDATA
->m_height
;
257 wxCHECK_RET( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), wxT("invalid image index") );
259 long pos
= (y
* w
+ x
) * 3;
261 M_IMGDATA
->m_data
[ pos
] = r
;
262 M_IMGDATA
->m_data
[ pos
+1 ] = g
;
263 M_IMGDATA
->m_data
[ pos
+2 ] = b
;
266 unsigned char wxImage::GetRed( int x
, int y
)
268 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
270 int w
= M_IMGDATA
->m_width
;
271 int h
= M_IMGDATA
->m_height
;
273 wxCHECK_MSG( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), 0, wxT("invalid image index") );
275 long pos
= (y
* w
+ x
) * 3;
277 return M_IMGDATA
->m_data
[pos
];
280 unsigned char wxImage::GetGreen( int x
, int y
)
282 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
284 int w
= M_IMGDATA
->m_width
;
285 int h
= M_IMGDATA
->m_height
;
287 wxCHECK_MSG( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), 0, wxT("invalid image index") );
289 long pos
= (y
* w
+ x
) * 3;
291 return M_IMGDATA
->m_data
[pos
+1];
294 unsigned char wxImage::GetBlue( int x
, int y
)
296 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
298 int w
= M_IMGDATA
->m_width
;
299 int h
= M_IMGDATA
->m_height
;
301 wxCHECK_MSG( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), 0, wxT("invalid image index") );
303 long pos
= (y
* w
+ x
) * 3;
305 return M_IMGDATA
->m_data
[pos
+2];
308 bool wxImage::Ok() const
310 return (M_IMGDATA
&& M_IMGDATA
->m_ok
);
313 char unsigned *wxImage::GetData() const
315 wxCHECK_MSG( Ok(), (char unsigned *)NULL
, wxT("invalid image") );
317 return M_IMGDATA
->m_data
;
320 void wxImage::SetData( char unsigned *data
)
322 wxCHECK_RET( Ok(), wxT("invalid image") );
324 wxImageRefData
*newRefData
= new wxImageRefData();
326 newRefData
->m_width
= M_IMGDATA
->m_width
;
327 newRefData
->m_height
= M_IMGDATA
->m_height
;
328 newRefData
->m_data
= data
;
329 newRefData
->m_ok
= TRUE
;
330 newRefData
->m_maskRed
= M_IMGDATA
->m_maskRed
;
331 newRefData
->m_maskGreen
= M_IMGDATA
->m_maskGreen
;
332 newRefData
->m_maskBlue
= M_IMGDATA
->m_maskBlue
;
333 newRefData
->m_hasMask
= M_IMGDATA
->m_hasMask
;
337 m_refData
= newRefData
;
340 void wxImage::SetMaskColour( unsigned char r
, unsigned char g
, unsigned char b
)
342 wxCHECK_RET( Ok(), wxT("invalid image") );
344 M_IMGDATA
->m_maskRed
= r
;
345 M_IMGDATA
->m_maskGreen
= g
;
346 M_IMGDATA
->m_maskBlue
= b
;
347 M_IMGDATA
->m_hasMask
= TRUE
;
350 unsigned char wxImage::GetMaskRed() const
352 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
354 return M_IMGDATA
->m_maskRed
;
357 unsigned char wxImage::GetMaskGreen() const
359 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
361 return M_IMGDATA
->m_maskGreen
;
364 unsigned char wxImage::GetMaskBlue() const
366 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
368 return M_IMGDATA
->m_maskBlue
;
371 void wxImage::SetMask( bool mask
)
373 wxCHECK_RET( Ok(), wxT("invalid image") );
375 M_IMGDATA
->m_hasMask
= mask
;
378 bool wxImage::HasMask() const
380 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid image") );
382 return M_IMGDATA
->m_hasMask
;
385 int wxImage::GetWidth() const
387 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
389 return M_IMGDATA
->m_width
;
392 int wxImage::GetHeight() const
394 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
396 return M_IMGDATA
->m_height
;
399 bool wxImage::LoadFile( const wxString
& filename
, long type
)
402 if (wxFileExists(filename
))
404 wxFileInputStream
stream(filename
);
405 wxBufferedInputStream
bstream( stream
);
406 return LoadFile(bstream
, type
);
410 wxLogError( _("Can't load image from file '%s': file does not exist."), filename
.c_str() );
414 #else // !wxUSE_STREAMS
416 #endif // wxUSE_STREAMS
419 bool wxImage::LoadFile( const wxString
& filename
, const wxString
& mimetype
)
422 if (wxFileExists(filename
))
424 wxFileInputStream
stream(filename
);
425 wxBufferedInputStream
bstream( stream
);
426 return LoadFile(bstream
, mimetype
);
430 wxLogError( _("Can't load image from file '%s': file does not exist."), filename
.c_str() );
434 #else // !wxUSE_STREAMS
436 #endif // wxUSE_STREAMS
439 bool wxImage::SaveFile( const wxString
& filename
, int type
)
442 wxFileOutputStream
stream(filename
);
444 if ( stream
.LastError() == wxStream_NOERROR
)
446 wxBufferedOutputStream
bstream( stream
);
447 return SaveFile(bstream
, type
);
450 #endif // wxUSE_STREAMS
454 bool wxImage::SaveFile( const wxString
& filename
, const wxString
& mimetype
)
457 wxFileOutputStream
stream(filename
);
459 if ( stream
.LastError() == wxStream_NOERROR
)
461 wxBufferedOutputStream
bstream( stream
);
462 return SaveFile(bstream
, mimetype
);
465 #endif // wxUSE_STREAMS
469 bool wxImage::CanRead( const wxString
&name
)
472 wxFileInputStream
stream(name
);
473 return CanRead(stream
);
481 bool wxImage::CanRead( wxInputStream
&stream
)
483 wxList
&list
=GetHandlers();
485 for ( wxList::Node
*node
= list
.GetFirst(); node
; node
= node
->GetNext() )
487 wxImageHandler
*handler
=(wxImageHandler
*)node
->GetData();
488 if (handler
->CanRead( stream
))
495 bool wxImage::LoadFile( wxInputStream
& stream
, long type
)
499 m_refData
= new wxImageRefData
;
501 wxImageHandler
*handler
;
503 if (type
==wxBITMAP_TYPE_ANY
)
505 wxList
&list
=GetHandlers();
507 for ( wxList::Node
*node
= list
.GetFirst(); node
; node
= node
->GetNext() )
509 handler
=(wxImageHandler
*)node
->GetData();
510 if (handler
->CanRead( stream
))
511 return handler
->LoadFile( this, stream
);
515 wxLogWarning( _("No handler found for image type.") );
519 handler
= FindHandler(type
);
523 wxLogWarning( _("No image handler for type %d defined."), type
);
528 return handler
->LoadFile( this, stream
);
531 bool wxImage::LoadFile( wxInputStream
& stream
, const wxString
& mimetype
)
535 m_refData
= new wxImageRefData
;
537 wxImageHandler
*handler
= FindHandlerMime(mimetype
);
541 wxLogWarning( _("No image handler for type %s defined."), mimetype
.GetData() );
546 return handler
->LoadFile( this, stream
);
549 bool wxImage::SaveFile( wxOutputStream
& stream
, int type
)
551 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid image") );
553 wxImageHandler
*handler
= FindHandler(type
);
557 wxLogWarning( _("No image handler for type %d defined."), type
);
562 return handler
->SaveFile( this, stream
);
565 bool wxImage::SaveFile( wxOutputStream
& stream
, const wxString
& mimetype
)
567 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid image") );
569 wxImageHandler
*handler
= FindHandlerMime(mimetype
);
573 wxLogWarning( _("No image handler for type %s defined."), mimetype
.GetData() );
578 return handler
->SaveFile( this, stream
);
580 #endif // wxUSE_STREAMS
582 void wxImage::AddHandler( wxImageHandler
*handler
)
584 // make sure that the memory will be freed at the program end
585 sm_handlers
.DeleteContents(TRUE
);
587 sm_handlers
.Append( handler
);
590 void wxImage::InsertHandler( wxImageHandler
*handler
)
592 // make sure that the memory will be freed at the program end
593 sm_handlers
.DeleteContents(TRUE
);
595 sm_handlers
.Insert( handler
);
598 bool wxImage::RemoveHandler( const wxString
& name
)
600 wxImageHandler
*handler
= FindHandler(name
);
603 sm_handlers
.DeleteObject(handler
);
610 wxImageHandler
*wxImage::FindHandler( const wxString
& name
)
612 wxNode
*node
= sm_handlers
.First();
615 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
616 if (handler
->GetName().Cmp(name
) == 0) return handler
;
620 return (wxImageHandler
*)NULL
;
623 wxImageHandler
*wxImage::FindHandler( const wxString
& extension
, long bitmapType
)
625 wxNode
*node
= sm_handlers
.First();
628 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
629 if ( (handler
->GetExtension().Cmp(extension
) == 0) &&
630 (bitmapType
== -1 || handler
->GetType() == bitmapType
) )
634 return (wxImageHandler
*)NULL
;
637 wxImageHandler
*wxImage::FindHandler( long bitmapType
)
639 wxNode
*node
= sm_handlers
.First();
642 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
643 if (handler
->GetType() == bitmapType
) return handler
;
649 wxImageHandler
*wxImage::FindHandlerMime( const wxString
& mimetype
)
651 wxNode
*node
= sm_handlers
.First();
654 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
655 if (handler
->GetMimeType().IsSameAs(mimetype
, FALSE
)) return handler
;
661 void wxImage::InitStandardHandlers()
663 AddHandler( new wxBMPHandler
);
666 void wxImage::CleanUpHandlers()
668 wxNode
*node
= sm_handlers
.First();
671 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
672 wxNode
*next
= node
->Next();
679 //-----------------------------------------------------------------------------
681 //-----------------------------------------------------------------------------
683 IMPLEMENT_ABSTRACT_CLASS(wxImageHandler
,wxObject
)
686 bool wxImageHandler::LoadFile( wxImage
*WXUNUSED(image
), wxInputStream
& WXUNUSED(stream
), bool WXUNUSED(verbose
), int WXUNUSED(index
) )
691 bool wxImageHandler::SaveFile( wxImage
*WXUNUSED(image
), wxOutputStream
& WXUNUSED(stream
), bool WXUNUSED(verbose
) )
696 int wxImageHandler::GetImageCount( wxInputStream
& WXUNUSED(stream
) )
701 bool wxImageHandler::CanRead( const wxString
& name
)
703 if (wxFileExists(name
))
705 wxFileInputStream
stream(name
);
706 return CanRead(stream
);
710 wxLogError( _("Can't check image format of file '%s': file does not exist."), name
.c_str() );
717 #endif // wxUSE_STREAMS
719 //-----------------------------------------------------------------------------
720 // MSW conversion routines
721 //-----------------------------------------------------------------------------
725 wxBitmap
wxImage::ConvertToBitmap() const
730 // sizeLimit is the MS upper limit for the DIB size
732 int sizeLimit
= 1024*768*3;
734 int sizeLimit
= 0x7fff ;
737 // width and height of the device-dependent bitmap
738 int width
= GetWidth();
739 int bmpHeight
= GetHeight();
741 // calc the number of bytes per scanline and padding
742 int bytePerLine
= width
*3;
743 int sizeDWORD
= sizeof( DWORD
);
744 int lineBoundary
= bytePerLine
% sizeDWORD
;
746 if( lineBoundary
> 0 )
748 padding
= sizeDWORD
- lineBoundary
;
749 bytePerLine
+= padding
;
751 // calc the number of DIBs and heights of DIBs
754 int height
= sizeLimit
/bytePerLine
;
755 if( height
>= bmpHeight
)
759 numDIB
= bmpHeight
/ height
;
760 hRemain
= bmpHeight
% height
;
761 if( hRemain
>0 ) numDIB
++;
764 // set bitmap parameters
766 wxCHECK_MSG( Ok(), bitmap
, wxT("invalid image") );
767 bitmap
.SetWidth( width
);
768 bitmap
.SetHeight( bmpHeight
);
769 bitmap
.SetDepth( wxDisplayDepth() );
771 // create a DIB header
772 int headersize
= sizeof(BITMAPINFOHEADER
);
773 BITMAPINFO
*lpDIBh
= (BITMAPINFO
*) malloc( headersize
);
774 wxCHECK_MSG( lpDIBh
, bitmap
, wxT("could not allocate memory for DIB header") );
775 // Fill in the DIB header
776 lpDIBh
->bmiHeader
.biSize
= headersize
;
777 lpDIBh
->bmiHeader
.biWidth
= (DWORD
)width
;
778 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
779 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
780 // the general formula for biSizeImage:
781 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
782 lpDIBh
->bmiHeader
.biPlanes
= 1;
783 lpDIBh
->bmiHeader
.biBitCount
= 24;
784 lpDIBh
->bmiHeader
.biCompression
= BI_RGB
;
785 lpDIBh
->bmiHeader
.biClrUsed
= 0;
786 // These seem not really needed for our purpose here.
787 lpDIBh
->bmiHeader
.biClrImportant
= 0;
788 lpDIBh
->bmiHeader
.biXPelsPerMeter
= 0;
789 lpDIBh
->bmiHeader
.biYPelsPerMeter
= 0;
790 // memory for DIB data
791 unsigned char *lpBits
;
792 lpBits
= (unsigned char *)malloc( lpDIBh
->bmiHeader
.biSizeImage
);
795 wxFAIL_MSG( wxT("could not allocate memory for DIB") );
800 // create and set the device-dependent bitmap
801 HDC hdc
= ::GetDC(NULL
);
802 HDC memdc
= ::CreateCompatibleDC( hdc
);
804 hbitmap
= ::CreateCompatibleBitmap( hdc
, width
, bmpHeight
);
805 ::SelectObject( memdc
, hbitmap
);
807 // copy image data into DIB data and then into DDB (in a loop)
808 unsigned char *data
= GetData();
811 unsigned char *ptdata
= data
;
812 unsigned char *ptbits
;
814 for( n
=0; n
<numDIB
; n
++ )
816 if( numDIB
> 1 && n
== numDIB
-1 && hRemain
> 0 )
818 // redefine height and size of the (possibly) last smaller DIB
819 // memory is not reallocated
821 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
822 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
826 for( j
=0; j
<height
; j
++ )
828 for( i
=0; i
<width
; i
++ )
830 *(ptbits
++) = *(ptdata
+2);
831 *(ptbits
++) = *(ptdata
+1);
832 *(ptbits
++) = *(ptdata
);
835 for( i
=0; i
< padding
; i
++ ) *(ptbits
++) = 0;
837 ::StretchDIBits( memdc
, 0, origin
, width
, height
,\
838 0, 0, width
, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
, SRCCOPY
);
840 // if numDIB = 1, lines below can also be used
841 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
842 // The above line is equivalent to the following two lines.
843 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
844 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
845 // or the following lines
846 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
847 // HDC memdc = ::CreateCompatibleDC( hdc );
848 // ::SelectObject( memdc, hbitmap);
849 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
850 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
851 // ::SelectObject( memdc, 0 );
852 // ::DeleteDC( memdc );
854 bitmap
.SetHBITMAP( (WXHBITMAP
) hbitmap
);
856 // similarly, created an mono-bitmap for the possible mask
859 hbitmap
= ::CreateBitmap( (WORD
)width
, (WORD
)bmpHeight
, 1, 1, NULL
);
860 HGDIOBJ hbmpOld
= ::SelectObject( memdc
, hbitmap
);
861 if( numDIB
== 1 ) height
= bmpHeight
;
862 else height
= sizeLimit
/bytePerLine
;
863 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
864 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
866 unsigned char r
= GetMaskRed();
867 unsigned char g
= GetMaskGreen();
868 unsigned char b
= GetMaskBlue();
869 unsigned char zero
= 0, one
= 255;
871 for( n
=0; n
<numDIB
; n
++ )
873 if( numDIB
> 1 && n
== numDIB
- 1 && hRemain
> 0 )
875 // redefine height and size of the (possibly) last smaller DIB
876 // memory is not reallocated
878 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
879 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
882 for( int j
=0; j
<height
; j
++ )
884 for(i
=0; i
<width
; i
++ )
886 // was causing a code gen bug in cw : if( ( cr !=r) || (cg!=g) || (cb!=b) )
887 unsigned char cr
= (*(ptdata
++)) ;
888 unsigned char cg
= (*(ptdata
++)) ;
889 unsigned char cb
= (*(ptdata
++)) ;
891 if( ( cr
!=r
) || (cg
!=g
) || (cb
!=b
) )
904 for( i
=0; i
< padding
; i
++ ) *(ptbits
++) = zero
;
906 ::StretchDIBits( memdc
, 0, origin
, width
, height
,\
907 0, 0, width
, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
, SRCCOPY
);
910 // create a wxMask object
911 wxMask
*mask
= new wxMask();
912 mask
->SetMaskBitmap( (WXHBITMAP
) hbitmap
);
913 bitmap
.SetMask( mask
);
914 // It will be deleted when the wxBitmap object is deleted (as of 01/1999)
915 /* The following can also be used but is slow to run
916 wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
917 wxMask *mask = new wxMask( bitmap, colour );
918 bitmap.SetMask( mask );
921 ::SelectObject( memdc
, hbmpOld
);
924 // free allocated resources
926 ::ReleaseDC(NULL
, hdc
);
930 #if WXWIN_COMPATIBILITY_2
931 // check the wxBitmap object
932 bitmap
.GetBitmapData()->SetOk();
933 #endif // WXWIN_COMPATIBILITY_2
938 wxImage::wxImage( const wxBitmap
&bitmap
)
943 wxFAIL_MSG( wxT("invalid bitmap") );
947 // create an wxImage object
948 int width
= bitmap
.GetWidth();
949 int height
= bitmap
.GetHeight();
950 Create( width
, height
);
951 unsigned char *data
= GetData();
954 wxFAIL_MSG( wxT("could not allocate data for image") );
958 // calc the number of bytes per scanline and padding in the DIB
959 int bytePerLine
= width
*3;
960 int sizeDWORD
= sizeof( DWORD
);
961 int lineBoundary
= bytePerLine
% sizeDWORD
;
963 if( lineBoundary
> 0 )
965 padding
= sizeDWORD
- lineBoundary
;
966 bytePerLine
+= padding
;
969 // create a DIB header
970 int headersize
= sizeof(BITMAPINFOHEADER
);
971 BITMAPINFO
*lpDIBh
= (BITMAPINFO
*) malloc( headersize
);
974 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
978 // Fill in the DIB header
979 lpDIBh
->bmiHeader
.biSize
= headersize
;
980 lpDIBh
->bmiHeader
.biWidth
= width
;
981 lpDIBh
->bmiHeader
.biHeight
= -height
;
982 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
* height
;
983 lpDIBh
->bmiHeader
.biPlanes
= 1;
984 lpDIBh
->bmiHeader
.biBitCount
= 24;
985 lpDIBh
->bmiHeader
.biCompression
= BI_RGB
;
986 lpDIBh
->bmiHeader
.biClrUsed
= 0;
987 // These seem not really needed for our purpose here.
988 lpDIBh
->bmiHeader
.biClrImportant
= 0;
989 lpDIBh
->bmiHeader
.biXPelsPerMeter
= 0;
990 lpDIBh
->bmiHeader
.biYPelsPerMeter
= 0;
991 // memory for DIB data
992 unsigned char *lpBits
;
993 lpBits
= (unsigned char *) malloc( lpDIBh
->bmiHeader
.biSizeImage
);
996 wxFAIL_MSG( wxT("could not allocate data for DIB") );
1002 // copy data from the device-dependent bitmap to the DIB
1003 HDC hdc
= ::GetDC(NULL
);
1005 hbitmap
= (HBITMAP
) bitmap
.GetHBITMAP();
1006 ::GetDIBits( hdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
1008 // copy DIB data into the wxImage object
1010 unsigned char *ptdata
= data
;
1011 unsigned char *ptbits
= lpBits
;
1012 for( i
=0; i
<height
; i
++ )
1014 for( j
=0; j
<width
; j
++ )
1016 *(ptdata
++) = *(ptbits
+2);
1017 *(ptdata
++) = *(ptbits
+1);
1018 *(ptdata
++) = *(ptbits
);
1024 // similarly, set data according to the possible mask bitmap
1025 if( bitmap
.GetMask() && bitmap
.GetMask()->GetMaskBitmap() )
1027 hbitmap
= (HBITMAP
) bitmap
.GetMask()->GetMaskBitmap();
1028 // memory DC created, color set, data copied, and memory DC deleted
1029 HDC memdc
= ::CreateCompatibleDC( hdc
);
1030 ::SetTextColor( memdc
, RGB( 0, 0, 0 ) );
1031 ::SetBkColor( memdc
, RGB( 255, 255, 255 ) );
1032 ::GetDIBits( memdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
1033 ::DeleteDC( memdc
);
1034 // background color set to RGB(16,16,16) in consistent with wxGTK
1035 unsigned char r
=16, g
=16, b
=16;
1038 for( i
=0; i
<height
; i
++ )
1040 for( j
=0; j
<width
; j
++ )
1054 SetMaskColour( r
, g
, b
);
1061 // free allocated resources
1062 ::ReleaseDC(NULL
, hdc
);
1071 #include <PictUtils.h>
1073 extern CTabHandle
wxMacCreateColorTable( int numColors
) ;
1074 extern void wxMacDestroyColorTable( CTabHandle colors
) ;
1075 extern void wxMacSetColorTableEntry( CTabHandle newColors
, int index
, int red
, int green
, int blue
) ;
1076 extern GWorldPtr
wxMacCreateGWorld( int height
, int width
, int depth
) ;
1077 extern void wxMacDestroyGWorld( GWorldPtr gw
) ;
1079 wxBitmap
wxImage::ConvertToBitmap() const
1081 // width and height of the device-dependent bitmap
1082 int width
= GetWidth();
1083 int height
= GetHeight();
1087 wxBitmap
bitmap( width
, height
, wxDisplayDepth() ) ;
1094 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1096 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1098 wxMask *mask = new wxMask();
1099 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1101 bitmap.SetMask( mask );
1107 int r_mask
= GetMaskRed();
1108 int g_mask
= GetMaskGreen();
1109 int b_mask
= GetMaskBlue();
1112 GDHandle origDevice
;
1114 GetGWorld( &origPort
, &origDevice
) ;
1115 SetGWorld( bitmap
.GetHBITMAP() , NULL
) ;
1117 register unsigned char* data
= GetData();
1120 for (int y
= 0; y
< height
; y
++)
1122 for (int x
= 0; x
< width
; x
++)
1124 unsigned char r
= data
[index
++];
1125 unsigned char g
= data
[index
++];
1126 unsigned char b
= data
[index
++];
1128 color
.red
= ( r
<< 8 ) + r
;
1129 color
.green
= ( g
<< 8 ) + g
;
1130 color
.blue
= ( b
<< 8 ) + b
;
1131 SetCPixel( x
, y
, &color
) ;
1135 SetGWorld( origPort
, origDevice
) ;
1139 wxColour
colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
1140 wxMask
*mask
= new wxMask( bitmap
, colour
);
1141 bitmap
.SetMask( mask
);
1147 wxImage::wxImage( const wxBitmap
&bitmap
)
1152 wxFAIL_MSG( "invalid bitmap" );
1156 // create an wxImage object
1157 int width
= bitmap
.GetWidth();
1158 int height
= bitmap
.GetHeight();
1159 Create( width
, height
);
1161 unsigned char *data = GetData();
1164 wxFAIL_MSG( "could not allocate data for image" );
1168 // calc the number of bytes per scanline and padding in the DIB
1169 int bytePerLine = width*3;
1170 int sizeDWORD = sizeof( DWORD );
1171 div_t lineBoundary = div( bytePerLine, sizeDWORD );
1173 if( lineBoundary.rem > 0 )
1175 padding = sizeDWORD - lineBoundary.rem;
1176 bytePerLine += padding;
1179 // create a DIB header
1180 int headersize = sizeof(BITMAPINFOHEADER);
1181 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
1184 wxFAIL_MSG( "could not allocate data for DIB header" );
1188 // Fill in the DIB header
1189 lpDIBh->bmiHeader.biSize = headersize;
1190 lpDIBh->bmiHeader.biWidth = width;
1191 lpDIBh->bmiHeader.biHeight = -height;
1192 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
1193 lpDIBh->bmiHeader.biPlanes = 1;
1194 lpDIBh->bmiHeader.biBitCount = 24;
1195 lpDIBh->bmiHeader.biCompression = BI_RGB;
1196 lpDIBh->bmiHeader.biClrUsed = 0;
1197 // These seem not really needed for our purpose here.
1198 lpDIBh->bmiHeader.biClrImportant = 0;
1199 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
1200 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
1201 // memory for DIB data
1202 unsigned char *lpBits;
1203 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
1206 wxFAIL_MSG( "could not allocate data for DIB" );
1212 // copy data from the device-dependent bitmap to the DIB
1213 HDC hdc = ::GetDC(NULL);
1215 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
1216 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1218 // copy DIB data into the wxImage object
1220 unsigned char *ptdata = data;
1221 unsigned char *ptbits = lpBits;
1222 for( i=0; i<height; i++ )
1224 for( j=0; j<width; j++ )
1226 *(ptdata++) = *(ptbits+2);
1227 *(ptdata++) = *(ptbits+1);
1228 *(ptdata++) = *(ptbits );
1234 // similarly, set data according to the possible mask bitmap
1235 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
1237 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
1238 // memory DC created, color set, data copied, and memory DC deleted
1239 HDC memdc = ::CreateCompatibleDC( hdc );
1240 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
1241 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
1242 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1243 ::DeleteDC( memdc );
1244 // background color set to RGB(16,16,16) in consistent with wxGTK
1245 unsigned char r=16, g=16, b=16;
1248 for( i=0; i<height; i++ )
1250 for( j=0; j<width; j++ )
1264 SetMaskColour( r, g, b );
1271 // free allocated resources
1272 ::ReleaseDC(NULL, hdc);
1280 //-----------------------------------------------------------------------------
1281 // GTK conversion routines
1282 //-----------------------------------------------------------------------------
1286 #include <gtk/gtk.h>
1287 #include <gdk/gdk.h>
1288 #include <gdk/gdkx.h>
1290 #if (GTK_MINOR_VERSION > 0)
1291 #include <gdk/gdkrgb.h>
1294 extern GtkWidget
*wxRootWindow
;
1296 wxBitmap
wxImage::ConvertToMonoBitmap( unsigned char red
, unsigned char green
, unsigned char blue
)
1300 wxCHECK_MSG( Ok(), bitmap
, wxT("invalid image") );
1302 int width
= GetWidth();
1303 int height
= GetHeight();
1305 bitmap
.SetHeight( height
);
1306 bitmap
.SetWidth( width
);
1308 bitmap
.SetBitmap( gdk_pixmap_new( wxRootWindow
->window
, width
, height
, 1 ) );
1310 bitmap
.SetDepth( 1 );
1312 // Create picture image
1314 unsigned char *data_data
= (unsigned char*)malloc( ((width
>> 3)+8) * height
);
1316 GdkImage
*data_image
=
1317 gdk_image_new_bitmap( gdk_visual_get_system(), data_data
, width
, height
);
1319 // Create mask image
1321 GdkImage
*mask_image
= (GdkImage
*) NULL
;
1325 unsigned char *mask_data
= (unsigned char*)malloc( ((width
>> 3)+8) * height
);
1327 mask_image
= gdk_image_new_bitmap( gdk_visual_get_system(), mask_data
, width
, height
);
1329 wxMask
*mask
= new wxMask();
1330 mask
->m_bitmap
= gdk_pixmap_new( wxRootWindow
->window
, width
, height
, 1 );
1332 bitmap
.SetMask( mask
);
1335 int r_mask
= GetMaskRed();
1336 int g_mask
= GetMaskGreen();
1337 int b_mask
= GetMaskBlue();
1339 unsigned char* data
= GetData();
1342 for (int y
= 0; y
< height
; y
++)
1344 for (int x
= 0; x
< width
; x
++)
1346 int r
= data
[index
];
1348 int g
= data
[index
];
1350 int b
= data
[index
];
1355 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
1356 gdk_image_put_pixel( mask_image
, x
, y
, 1 );
1358 gdk_image_put_pixel( mask_image
, x
, y
, 0 );
1361 if ((r
== red
) && (b
== blue
) && (g
== green
))
1362 gdk_image_put_pixel( data_image
, x
, y
, 1 );
1364 gdk_image_put_pixel( data_image
, x
, y
, 0 );
1371 GdkGC
*data_gc
= gdk_gc_new( bitmap
.GetBitmap() );
1373 gdk_draw_image( bitmap
.GetBitmap(), data_gc
, data_image
, 0, 0, 0, 0, width
, height
);
1375 gdk_image_destroy( data_image
);
1376 gdk_gc_unref( data_gc
);
1382 GdkGC
*mask_gc
= gdk_gc_new( bitmap
.GetMask()->GetBitmap() );
1384 gdk_draw_image( bitmap
.GetMask()->GetBitmap(), mask_gc
, mask_image
, 0, 0, 0, 0, width
, height
);
1386 gdk_image_destroy( mask_image
);
1387 gdk_gc_unref( mask_gc
);
1394 wxBitmap
wxImage::ConvertToBitmap() const
1398 wxCHECK_MSG( Ok(), bitmap
, wxT("invalid image") );
1400 int width
= GetWidth();
1401 int height
= GetHeight();
1403 bitmap
.SetHeight( height
);
1404 bitmap
.SetWidth( width
);
1406 bitmap
.SetPixmap( gdk_pixmap_new( wxRootWindow
->window
, width
, height
, -1 ) );
1410 GdkVisual
*visual
= gdk_window_get_visual( bitmap
.GetPixmap() );
1411 if (visual
== NULL
) visual
= gdk_visual_get_system();
1412 int bpp
= visual
->depth
;
1414 bitmap
.SetDepth( bpp
);
1416 if ((bpp
== 16) && (visual
->red_mask
!= 0xf800)) bpp
= 15;
1417 if (bpp
< 8) bpp
= 8;
1419 #if (GTK_MINOR_VERSION > 0)
1421 if (!HasMask() && (bpp
> 8))
1423 static bool s_hasInitialized
= FALSE
;
1425 if (!s_hasInitialized
)
1428 s_hasInitialized
= TRUE
;
1431 GdkGC
*gc
= gdk_gc_new( bitmap
.GetPixmap() );
1433 gdk_draw_rgb_image( bitmap
.GetPixmap(),
1437 GDK_RGB_DITHER_NONE
,
1448 // Create picture image
1450 GdkImage
*data_image
=
1451 gdk_image_new( GDK_IMAGE_FASTEST
, gdk_visual_get_system(), width
, height
);
1453 // Create mask image
1455 GdkImage
*mask_image
= (GdkImage
*) NULL
;
1459 unsigned char *mask_data
= (unsigned char*)malloc( ((width
>> 3)+8) * height
);
1461 mask_image
= gdk_image_new_bitmap( gdk_visual_get_system(), mask_data
, width
, height
);
1463 wxMask
*mask
= new wxMask();
1464 mask
->m_bitmap
= gdk_pixmap_new( wxRootWindow
->window
, width
, height
, 1 );
1466 bitmap
.SetMask( mask
);
1471 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
1472 byte_order b_o
= RGB
;
1476 GdkVisual
*visual
= gdk_visual_get_system();
1477 if ((visual
->red_mask
> visual
->green_mask
) && (visual
->green_mask
> visual
->blue_mask
)) b_o
= RGB
;
1478 else if ((visual
->red_mask
> visual
->blue_mask
) && (visual
->blue_mask
> visual
->green_mask
)) b_o
= RGB
;
1479 else if ((visual
->blue_mask
> visual
->red_mask
) && (visual
->red_mask
> visual
->green_mask
)) b_o
= BRG
;
1480 else if ((visual
->blue_mask
> visual
->green_mask
) && (visual
->green_mask
> visual
->red_mask
)) b_o
= BGR
;
1481 else if ((visual
->green_mask
> visual
->red_mask
) && (visual
->red_mask
> visual
->blue_mask
)) b_o
= GRB
;
1482 else if ((visual
->green_mask
> visual
->blue_mask
) && (visual
->blue_mask
> visual
->red_mask
)) b_o
= GBR
;
1485 int r_mask
= GetMaskRed();
1486 int g_mask
= GetMaskGreen();
1487 int b_mask
= GetMaskBlue();
1489 unsigned char* data
= GetData();
1492 for (int y
= 0; y
< height
; y
++)
1494 for (int x
= 0; x
< width
; x
++)
1496 int r
= data
[index
];
1498 int g
= data
[index
];
1500 int b
= data
[index
];
1505 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
1506 gdk_image_put_pixel( mask_image
, x
, y
, 1 );
1508 gdk_image_put_pixel( mask_image
, x
, y
, 0 );
1516 if (wxTheApp
->m_colorCube
)
1518 pixel
= wxTheApp
->m_colorCube
[ ((r
& 0xf8) << 7) + ((g
& 0xf8) << 2) + ((b
& 0xf8) >> 3) ];
1522 GdkColormap
*cmap
= gtk_widget_get_default_colormap();
1523 GdkColor
*colors
= cmap
->colors
;
1524 int max
= 3 * (65536);
1526 for (int i
= 0; i
< cmap
->size
; i
++)
1528 int rdiff
= (r
<< 8) - colors
[i
].red
;
1529 int gdiff
= (g
<< 8) - colors
[i
].green
;
1530 int bdiff
= (b
<< 8) - colors
[i
].blue
;
1531 int sum
= ABS (rdiff
) + ABS (gdiff
) + ABS (bdiff
);
1532 if (sum
< max
) { pixel
= i
; max
= sum
; }
1536 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1542 guint32 pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
1543 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1548 guint32 pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
1549 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1558 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
1559 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
1560 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
1561 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
1562 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
1563 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
1565 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1574 GdkGC
*data_gc
= gdk_gc_new( bitmap
.GetPixmap() );
1576 gdk_draw_image( bitmap
.GetPixmap(), data_gc
, data_image
, 0, 0, 0, 0, width
, height
);
1578 gdk_image_destroy( data_image
);
1579 gdk_gc_unref( data_gc
);
1585 GdkGC
*mask_gc
= gdk_gc_new( bitmap
.GetMask()->GetBitmap() );
1587 gdk_draw_image( bitmap
.GetMask()->GetBitmap(), mask_gc
, mask_image
, 0, 0, 0, 0, width
, height
);
1589 gdk_image_destroy( mask_image
);
1590 gdk_gc_unref( mask_gc
);
1596 wxImage::wxImage( const wxBitmap
&bitmap
)
1598 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
1600 GdkImage
*gdk_image
= (GdkImage
*) NULL
;
1601 if (bitmap
.GetPixmap())
1603 gdk_image
= gdk_image_get( bitmap
.GetPixmap(),
1605 bitmap
.GetWidth(), bitmap
.GetHeight() );
1607 if (bitmap
.GetBitmap())
1609 gdk_image
= gdk_image_get( bitmap
.GetBitmap(),
1611 bitmap
.GetWidth(), bitmap
.GetHeight() );
1614 wxFAIL_MSG( wxT("Ill-formed bitmap") );
1617 wxCHECK_RET( gdk_image
, wxT("couldn't create image") );
1619 Create( bitmap
.GetWidth(), bitmap
.GetHeight() );
1620 char unsigned *data
= GetData();
1624 gdk_image_destroy( gdk_image
);
1625 wxFAIL_MSG( wxT("couldn't create image") );
1629 GdkImage
*gdk_image_mask
= (GdkImage
*) NULL
;
1630 if (bitmap
.GetMask())
1632 gdk_image_mask
= gdk_image_get( bitmap
.GetMask()->GetBitmap(),
1634 bitmap
.GetWidth(), bitmap
.GetHeight() );
1636 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1640 int red_shift_right
= 0;
1641 int green_shift_right
= 0;
1642 int blue_shift_right
= 0;
1643 int red_shift_left
= 0;
1644 int green_shift_left
= 0;
1645 int blue_shift_left
= 0;
1646 bool use_shift
= FALSE
;
1648 if (bitmap
.GetPixmap())
1650 GdkVisual
*visual
= gdk_window_get_visual( bitmap
.GetPixmap() );
1652 if (visual
== NULL
) visual
= gdk_window_get_visual( wxRootWindow
->window
);
1653 bpp
= visual
->depth
;
1654 if (bpp
== 16) bpp
= visual
->red_prec
+ visual
->green_prec
+ visual
->blue_prec
;
1655 red_shift_right
= visual
->red_shift
;
1656 red_shift_left
= 8-visual
->red_prec
;
1657 green_shift_right
= visual
->green_shift
;
1658 green_shift_left
= 8-visual
->green_prec
;
1659 blue_shift_right
= visual
->blue_shift
;
1660 blue_shift_left
= 8-visual
->blue_prec
;
1662 use_shift
= (visual
->type
== GDK_VISUAL_TRUE_COLOR
) || (visual
->type
== GDK_VISUAL_DIRECT_COLOR
);
1664 if (bitmap
.GetBitmap())
1670 GdkColormap
*cmap
= gtk_widget_get_default_colormap();
1673 for (int j
= 0; j
< bitmap
.GetHeight(); j
++)
1675 for (int i
= 0; i
< bitmap
.GetWidth(); i
++)
1677 wxUint32 pixel
= gdk_image_get_pixel( gdk_image
, i
, j
);
1695 data
[pos
] = (pixel
>> red_shift_right
) << red_shift_left
;
1696 data
[pos
+1] = (pixel
>> green_shift_right
) << green_shift_left
;
1697 data
[pos
+2] = (pixel
>> blue_shift_right
) << blue_shift_left
;
1699 else if (cmap
->colors
)
1701 data
[pos
] = cmap
->colors
[pixel
].red
>> 8;
1702 data
[pos
+1] = cmap
->colors
[pixel
].green
>> 8;
1703 data
[pos
+2] = cmap
->colors
[pixel
].blue
>> 8;
1707 wxFAIL_MSG( wxT("Image conversion failed. Unknown visual type.") );
1712 int mask_pixel
= gdk_image_get_pixel( gdk_image_mask
, i
, j
);
1713 if (mask_pixel
== 0)
1725 gdk_image_destroy( gdk_image
);
1726 if (gdk_image_mask
) gdk_image_destroy( gdk_image_mask
);
1731 //-----------------------------------------------------------------------------
1732 // Motif conversion routines
1733 //-----------------------------------------------------------------------------
1737 #pragma message disable nosimpint
1741 #pragma message enable nosimpint
1743 #include "wx/utils.h"
1748 Date: Wed, 05 Jan 2000 11:45:40 +0100
1749 From: Frits Boel <boel@niob.knaw.nl>
1750 To: julian.smart@ukonline.co.uk
1751 Subject: Patch for Motif ConvertToBitmap
1755 I've been working on a wxWin application for image processing. From the
1756 beginning, I was surprised by the (lack of) speed of ConvertToBitmap,
1757 till I looked in the source code of image.cpp. I saw that converting a
1758 wxImage to a bitmap with 8-bit pixels is done with comparing every pixel
1759 to the 256 colors of the palet. A very time-consuming piece of code!
1761 Because I wanted a faster application, I've made a 'patch' for this. In
1762 short: every pixel of the image is compared to a sorted list with
1763 colors. If the color is found in the list, the palette entry is
1764 returned; if the color is not found, the color palette is searched and
1765 then the palette entry is returned and the color added to the sorted
1768 Maybe there is another method for this, namely changing the palette
1769 itself (if the colors are known, as is the case with tiffs with a
1770 colormap). I did not look at this, maybe someone else did?
1772 The code of the patch is attached, have a look on it, and maybe you will
1773 ship it with the next release of wxMotif?
1778 Software engineer at Hubrecht Laboratory, The Netherlands.
1785 wxSearchColor( void );
1786 wxSearchColor( int size
, XColor
*colors
);
1787 ~wxSearchColor( void );
1789 int SearchColor( int r
, int g
, int b
);
1791 int AddColor( unsigned int value
, int pos
);
1795 unsigned int *color
;
1802 wxSearchColor::wxSearchColor( void )
1805 colors
= (XColor
*) NULL
;
1806 color
= (unsigned int *) NULL
;
1807 entry
= (int*) NULL
;
1813 wxSearchColor::wxSearchColor( int size_
, XColor
*colors_
)
1818 color
= new unsigned int[size
];
1819 entry
= new int [size
];
1821 for (i
= 0; i
< size
; i
++ ) {
1825 bottom
= top
= ( size
>> 1 );
1828 wxSearchColor::~wxSearchColor( void )
1830 if ( color
) delete color
;
1831 if ( entry
) delete entry
;
1834 int wxSearchColor::SearchColor( int r
, int g
, int b
)
1836 unsigned int value
= ( ( ( r
* 256 ) + g
) * 256 ) + b
;
1841 while ( begin
<= end
) {
1843 middle
= ( begin
+ end
) >> 1;
1845 if ( value
== color
[middle
] ) {
1846 return( entry
[middle
] );
1847 } else if ( value
< color
[middle
] ) {
1855 return AddColor( value
, middle
);
1858 int wxSearchColor::AddColor( unsigned int value
, int pos
)
1862 int max
= 3 * (65536);
1863 for ( i
= 0; i
< 256; i
++ ) {
1864 int rdiff
= ((value
>> 8) & 0xFF00 ) - colors
[i
].red
;
1865 int gdiff
= ((value
) & 0xFF00 ) - colors
[i
].green
;
1866 int bdiff
= ((value
<< 8) & 0xFF00 ) - colors
[i
].blue
;
1867 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
1868 if (sum
< max
) { pixel
= i
; max
= sum
; }
1871 if ( entry
[pos
] < 0 ) {
1874 } else if ( value
< color
[pos
] ) {
1877 for ( i
= bottom
; i
< pos
; i
++ ) {
1878 color
[i
-1] = color
[i
];
1879 entry
[i
-1] = entry
[i
];
1882 color
[pos
-1] = value
;
1883 entry
[pos
-1] = pixel
;
1884 } else if ( top
< size
-1 ) {
1885 for ( i
= top
; i
>= pos
; i
-- ) {
1886 color
[i
+1] = color
[i
];
1887 entry
[i
+1] = entry
[i
];
1896 if ( top
< size
-1 ) {
1897 for ( i
= top
; i
> pos
; i
-- ) {
1898 color
[i
+1] = color
[i
];
1899 entry
[i
+1] = entry
[i
];
1902 color
[pos
+1] = value
;
1903 entry
[pos
+1] = pixel
;
1904 } else if ( bottom
> 0 ) {
1905 for ( i
= bottom
; i
< pos
; i
++ ) {
1906 color
[i
-1] = color
[i
];
1907 entry
[i
-1] = entry
[i
];
1919 wxBitmap
wxImage::ConvertToBitmap() const
1923 wxCHECK_MSG( Ok(), bitmap
, wxT("invalid image") );
1925 int width
= GetWidth();
1926 int height
= GetHeight();
1928 bitmap
.SetHeight( height
);
1929 bitmap
.SetWidth( width
);
1931 Display
*dpy
= (Display
*) wxGetDisplay();
1932 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1933 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1937 XImage
*data_image
= XCreateImage( dpy
, vis
, bpp
, ZPixmap
, 0, 0, width
, height
, 32, 0 );
1938 data_image
->data
= (char*) malloc( data_image
->bytes_per_line
* data_image
->height
);
1940 bitmap
.Create( width
, height
, bpp
);
1945 GdkImage *mask_image = (GdkImage*) NULL;
1949 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1951 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1953 wxMask *mask = new wxMask();
1954 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1956 bitmap.SetMask( mask );
1960 // Retrieve depth info
1962 XVisualInfo vinfo_template
;
1965 vinfo_template
.visual
= vis
;
1966 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1967 vinfo_template
.depth
= bpp
;
1970 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
1972 wxCHECK_MSG( vi
, wxNullBitmap
, wxT("no visual") );
1976 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1977 if (bpp
< 8) bpp
= 8;
1981 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
1982 byte_order b_o
= RGB
;
1986 if ((vi
->red_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->blue_mask
)) b_o
= RGB
;
1987 else if ((vi
->red_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->green_mask
)) b_o
= RGB
;
1988 else if ((vi
->blue_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->green_mask
)) b_o
= BRG
;
1989 else if ((vi
->blue_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->red_mask
)) b_o
= BGR
;
1990 else if ((vi
->green_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->blue_mask
)) b_o
= GRB
;
1991 else if ((vi
->green_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->red_mask
)) b_o
= GBR
;
1995 int r_mask = GetMaskRed();
1996 int g_mask = GetMaskGreen();
1997 int b_mask = GetMaskBlue();
2003 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap( dpy
);
2005 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
2006 XQueryColors( dpy
, cmap
, colors
, 256 );
2009 wxSearchColor
scolor( 256, colors
);
2010 unsigned char* data
= GetData();
2013 for (int y
= 0; y
< height
; y
++)
2015 for (int x
= 0; x
< width
; x
++)
2017 int r
= data
[index
];
2019 int g
= data
[index
];
2021 int b
= data
[index
];
2027 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
2028 gdk_image_put_pixel( mask_image, x, y, 1 );
2030 gdk_image_put_pixel( mask_image, x, y, 0 );
2038 #if 0 // Old, slower code
2041 if (wxTheApp->m_colorCube)
2043 pixel = wxTheApp->m_colorCube
2044 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
2049 int max
= 3 * (65536);
2050 for (int i
= 0; i
< 256; i
++)
2052 int rdiff
= (r
<< 8) - colors
[i
].red
;
2053 int gdiff
= (g
<< 8) - colors
[i
].green
;
2054 int bdiff
= (b
<< 8) - colors
[i
].blue
;
2055 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
2056 if (sum
< max
) { pixel
= i
; max
= sum
; }
2063 // And this is all to get the 'right' color...
2064 int pixel
= scolor
.SearchColor( r
, g
, b
);
2065 XPutPixel( data_image
, x
, y
, pixel
);
2070 int pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
2071 XPutPixel( data_image
, x
, y
, pixel
);
2076 int pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
2077 XPutPixel( data_image
, x
, y
, pixel
);
2086 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
2087 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
2088 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
2089 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
2090 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
2091 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
2093 XPutPixel( data_image
, x
, y
, pixel
);
2103 gcvalues
.foreground
= BlackPixel( dpy
, DefaultScreen( dpy
) );
2104 GC gc
= XCreateGC( dpy
, RootWindow ( dpy
, DefaultScreen(dpy
) ), GCForeground
, &gcvalues
);
2105 XPutImage( dpy
, (Drawable
)bitmap
.GetPixmap(), gc
, data_image
, 0, 0, 0, 0, width
, height
);
2107 XDestroyImage( data_image
);
2115 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
2117 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
2119 gdk_image_destroy( mask_image );
2120 gdk_gc_unref( mask_gc );
2127 wxImage::wxImage( const wxBitmap
&bitmap
)
2129 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
2131 Display
*dpy
= (Display
*) wxGetDisplay();
2132 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
2133 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
2135 XImage
*ximage
= XGetImage( dpy
,
2136 (Drawable
)bitmap
.GetPixmap(),
2138 bitmap
.GetWidth(), bitmap
.GetHeight(),
2139 AllPlanes
, ZPixmap
);
2141 wxCHECK_RET( ximage
, wxT("couldn't create image") );
2143 Create( bitmap
.GetWidth(), bitmap
.GetHeight() );
2144 char unsigned *data
= GetData();
2148 XDestroyImage( ximage
);
2149 wxFAIL_MSG( wxT("couldn't create image") );
2154 GdkImage *gdk_image_mask = (GdkImage*) NULL;
2155 if (bitmap.GetMask())
2157 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
2159 bitmap.GetWidth(), bitmap.GetHeight() );
2161 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
2165 // Retrieve depth info
2167 XVisualInfo vinfo_template
;
2170 vinfo_template
.visual
= vis
;
2171 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
2172 vinfo_template
.depth
= bpp
;
2175 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
2177 wxCHECK_RET( vi
, wxT("no visual") );
2179 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
2186 Colormap cmap
= (Colormap
)wxTheApp
->GetMainColormap( dpy
);
2188 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
2189 XQueryColors( dpy
, cmap
, colors
, 256 );
2193 for (int j
= 0; j
< bitmap
.GetHeight(); j
++)
2195 for (int i
= 0; i
< bitmap
.GetWidth(); i
++)
2197 int pixel
= XGetPixel( ximage
, i
, j
);
2200 data
[pos
] = colors
[pixel
].red
>> 8;
2201 data
[pos
+1] = colors
[pixel
].green
>> 8;
2202 data
[pos
+2] = colors
[pixel
].blue
>> 8;
2203 } else if (bpp
== 15)
2205 data
[pos
] = (pixel
>> 7) & 0xf8;
2206 data
[pos
+1] = (pixel
>> 2) & 0xf8;
2207 data
[pos
+2] = (pixel
<< 3) & 0xf8;
2208 } else if (bpp
== 16)
2210 data
[pos
] = (pixel
>> 8) & 0xf8;
2211 data
[pos
+1] = (pixel
>> 3) & 0xfc;
2212 data
[pos
+2] = (pixel
<< 3) & 0xf8;
2215 data
[pos
] = (pixel
>> 16) & 0xff;
2216 data
[pos
+1] = (pixel
>> 8) & 0xff;
2217 data
[pos
+2] = pixel
& 0xff;
2223 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
2224 if (mask_pixel == 0)
2237 XDestroyImage( ximage
);
2239 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
2245 // OS/2 Presentation manager conversion routings
2247 wxBitmap
wxImage::ConvertToBitmap() const
2250 return wxNullBitmap
;
2251 wxBitmap bitmap
; // remove
2254 int sizeLimit = 1024*768*3;
2256 // width and height of the device-dependent bitmap
2257 int width = GetWidth();
2258 int bmpHeight = GetHeight();
2260 // calc the number of bytes per scanline and padding
2261 int bytePerLine = width*3;
2262 int sizeDWORD = sizeof( DWORD );
2263 int lineBoundary = bytePerLine % sizeDWORD;
2265 if( lineBoundary > 0 )
2267 padding = sizeDWORD - lineBoundary;
2268 bytePerLine += padding;
2270 // calc the number of DIBs and heights of DIBs
2273 int height = sizeLimit/bytePerLine;
2274 if( height >= bmpHeight )
2278 numDIB = bmpHeight / height;
2279 hRemain = bmpHeight % height;
2280 if( hRemain >0 ) numDIB++;
2283 // set bitmap parameters
2285 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
2286 bitmap.SetWidth( width );
2287 bitmap.SetHeight( bmpHeight );
2288 bitmap.SetDepth( wxDisplayDepth() );
2290 // create a DIB header
2291 int headersize = sizeof(BITMAPINFOHEADER);
2292 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
2293 wxCHECK_MSG( lpDIBh, bitmap, wxT("could not allocate memory for DIB header") );
2294 // Fill in the DIB header
2295 lpDIBh->bmiHeader.biSize = headersize;
2296 lpDIBh->bmiHeader.biWidth = (DWORD)width;
2297 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2298 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2299 // the general formula for biSizeImage:
2300 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
2301 lpDIBh->bmiHeader.biPlanes = 1;
2302 lpDIBh->bmiHeader.biBitCount = 24;
2303 lpDIBh->bmiHeader.biCompression = BI_RGB;
2304 lpDIBh->bmiHeader.biClrUsed = 0;
2305 // These seem not really needed for our purpose here.
2306 lpDIBh->bmiHeader.biClrImportant = 0;
2307 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2308 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2309 // memory for DIB data
2310 unsigned char *lpBits;
2311 lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
2314 wxFAIL_MSG( wxT("could not allocate memory for DIB") );
2319 // create and set the device-dependent bitmap
2320 HDC hdc = ::GetDC(NULL);
2321 HDC memdc = ::CreateCompatibleDC( hdc );
2323 hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
2324 ::SelectObject( memdc, hbitmap);
2326 // copy image data into DIB data and then into DDB (in a loop)
2327 unsigned char *data = GetData();
2330 unsigned char *ptdata = data;
2331 unsigned char *ptbits;
2333 for( n=0; n<numDIB; n++ )
2335 if( numDIB > 1 && n == numDIB-1 && hRemain > 0 )
2337 // redefine height and size of the (possibly) last smaller DIB
2338 // memory is not reallocated
2340 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2341 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2345 for( j=0; j<height; j++ )
2347 for( i=0; i<width; i++ )
2349 *(ptbits++) = *(ptdata+2);
2350 *(ptbits++) = *(ptdata+1);
2351 *(ptbits++) = *(ptdata );
2354 for( i=0; i< padding; i++ ) *(ptbits++) = 0;
2356 ::StretchDIBits( memdc, 0, origin, width, height,\
2357 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2359 // if numDIB = 1, lines below can also be used
2360 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
2361 // The above line is equivalent to the following two lines.
2362 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2363 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
2364 // or the following lines
2365 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2366 // HDC memdc = ::CreateCompatibleDC( hdc );
2367 // ::SelectObject( memdc, hbitmap);
2368 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
2369 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
2370 // ::SelectObject( memdc, 0 );
2371 // ::DeleteDC( memdc );
2373 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
2375 // similarly, created an mono-bitmap for the possible mask
2378 hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL );
2379 ::SelectObject( memdc, hbitmap);
2380 if( numDIB == 1 ) height = bmpHeight;
2381 else height = sizeLimit/bytePerLine;
2382 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2383 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2385 unsigned char r = GetMaskRed();
2386 unsigned char g = GetMaskGreen();
2387 unsigned char b = GetMaskBlue();
2388 unsigned char zero = 0, one = 255;
2390 for( n=0; n<numDIB; n++ )
2392 if( numDIB > 1 && n == numDIB - 1 && hRemain > 0 )
2394 // redefine height and size of the (possibly) last smaller DIB
2395 // memory is not reallocated
2397 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2398 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2401 for( int j=0; j<height; j++ )
2403 for(i=0; i<width; i++ )
2405 if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
2418 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
2420 ::StretchDIBits( memdc, 0, origin, width, height,\
2421 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2424 // create a wxMask object
2425 wxMask *mask = new wxMask();
2426 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
2427 bitmap.SetMask( mask );
2430 // free allocated resources
2431 ::SelectObject( memdc, 0 );
2432 ::DeleteDC( memdc );
2433 ::ReleaseDC(NULL, hdc);
2437 // check the wxBitmap object
2438 if( bitmap.GetHBITMAP() )
2439 bitmap.SetOk( TRUE );
2441 bitmap.SetOk( FALSE );
2446 wxImage::wxImage( const wxBitmap
&bitmap
)
2451 wxFAIL_MSG( wxT("invalid bitmap") );
2455 // create an wxImage object
2456 int width
= bitmap
.GetWidth();
2457 int height
= bitmap
.GetHeight();
2458 Create( width
, height
);
2459 unsigned char *data
= GetData();
2462 wxFAIL_MSG( wxT("could not allocate data for image") );
2466 // calc the number of bytes per scanline and padding in the DIB
2467 int bytePerLine
= width
*3;
2468 int sizeDWORD
= sizeof( DWORD
);
2469 int lineBoundary
= bytePerLine
% sizeDWORD
;
2471 if( lineBoundary
> 0 )
2473 padding
= sizeDWORD
- lineBoundary
;
2474 bytePerLine
+= padding
;
2478 // create a DIB header
2479 int headersize = sizeof(BITMAPINFOHEADER);
2480 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
2483 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
2487 // Fill in the DIB header
2488 lpDIBh->bmiHeader.biSize = headersize;
2489 lpDIBh->bmiHeader.biWidth = width;
2490 lpDIBh->bmiHeader.biHeight = -height;
2491 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
2492 lpDIBh->bmiHeader.biPlanes = 1;
2493 lpDIBh->bmiHeader.biBitCount = 24;
2494 lpDIBh->bmiHeader.biCompression = BI_RGB;
2495 lpDIBh->bmiHeader.biClrUsed = 0;
2496 // These seem not really needed for our purpose here.
2497 lpDIBh->bmiHeader.biClrImportant = 0;
2498 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2499 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2500 // memory for DIB data
2501 unsigned char *lpBits;
2502 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
2505 wxFAIL_MSG( wxT("could not allocate data for DIB") );
2511 // copy data from the device-dependent bitmap to the DIB
2512 HDC hdc = ::GetDC(NULL);
2514 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
2515 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2517 // copy DIB data into the wxImage object
2519 unsigned char *ptdata = data;
2520 unsigned char *ptbits = lpBits;
2521 for( i=0; i<height; i++ )
2523 for( j=0; j<width; j++ )
2525 *(ptdata++) = *(ptbits+2);
2526 *(ptdata++) = *(ptbits+1);
2527 *(ptdata++) = *(ptbits );
2533 // similarly, set data according to the possible mask bitmap
2534 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
2536 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
2537 // memory DC created, color set, data copied, and memory DC deleted
2538 HDC memdc = ::CreateCompatibleDC( hdc );
2539 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
2540 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
2541 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2542 ::DeleteDC( memdc );
2543 // background color set to RGB(16,16,16) in consistent with wxGTK
2544 unsigned char r=16, g=16, b=16;
2547 for( i=0; i<height; i++ )
2549 for( j=0; j<width; j++ )
2563 SetMaskColour( r, g, b );
2570 // free allocated resources
2571 ::ReleaseDC(NULL, hdc);
2579 // A module to allow wxImage initialization/cleanup
2580 // without calling these functions from app.cpp or from
2581 // the user's application.
2583 class wxImageModule
: public wxModule
2585 DECLARE_DYNAMIC_CLASS(wxImageModule
)
2588 bool OnInit() { wxImage::InitStandardHandlers(); return TRUE
; };
2589 void OnExit() { wxImage::CleanUpHandlers(); };
2592 IMPLEMENT_DYNAMIC_CLASS(wxImageModule
, wxModule
)
2595 //-----------------------------------------------------------------------------
2598 // Counts and returns the number of different colours. Optionally stops
2599 // when it exceeds 'stopafter' different colours. This is useful, for
2600 // example, to see if the image can be saved as 8-bit (256 colour or
2601 // less, in this case it would be invoked as CountColours(256)). Default
2602 // value for stopafter is -1 (don't care).
2604 unsigned long wxImage::CountColours( unsigned long stopafter
)
2609 unsigned char r
, g
, b
, *p
;
2610 unsigned long size
, nentries
, key
;
2613 size
= GetWidth() * GetHeight();
2616 for (unsigned long j
= 0; (j
< size
) && (nentries
<= stopafter
) ; j
++)
2621 key
= (r
<< 16) | (g
<< 8) | b
;
2623 hnode
= (wxHNode
*) h
.Get(key
);
2627 h
.Put(key
, (wxObject
*)(new wxHNode
));
2632 // delete all HNodes
2634 while ((node
= h
.Next()) != NULL
)
2635 delete (wxHNode
*)node
->GetData();
2642 // Computes the histogram of the image and fills a hash table, indexed
2643 // with integer keys built as 0xRRGGBB, containing wxHNode objects. Each
2644 // wxHNode contains an 'index' (useful to build a palette with the image
2645 // colours) and a 'value', which is the number of pixels in the image with
2648 unsigned long wxImage::ComputeHistogram( wxHashTable
&h
)
2650 unsigned char r
, g
, b
, *p
;
2651 unsigned long size
, nentries
, key
;
2655 size
= GetWidth() * GetHeight();
2658 for (unsigned long j
= 0; j
< size
; j
++)
2663 key
= (r
<< 16) | (g
<< 8) | b
;
2665 hnode
= (wxHNode
*) h
.Get(key
);
2671 hnode
= new wxHNode();
2672 hnode
->index
= nentries
++;
2675 h
.Put(key
, (wxObject
*)hnode
);