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 ::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 if( (*(ptdata
++)!=r
) | (*(ptdata
++)!=g
) | (*(ptdata
++)!=b
) )
899 for( i
=0; i
< padding
; i
++ ) *(ptbits
++) = zero
;
901 ::StretchDIBits( memdc
, 0, origin
, width
, height
,\
902 0, 0, width
, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
, SRCCOPY
);
905 // create a wxMask object
906 wxMask
*mask
= new wxMask();
907 mask
->SetMaskBitmap( (WXHBITMAP
) hbitmap
);
908 bitmap
.SetMask( mask
);
909 // It will be deleted when the wxBitmap object is deleted (as of 01/1999)
910 /* The following can also be used but is slow to run
911 wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
912 wxMask *mask = new wxMask( bitmap, colour );
913 bitmap.SetMask( mask );
917 // free allocated resources
918 ::SelectObject( memdc
, 0 );
920 ::ReleaseDC(NULL
, hdc
);
924 #if WXWIN_COMPATIBILITY_2
925 // check the wxBitmap object
926 bitmap
.GetBitmapData()->SetOk();
927 #endif // WXWIN_COMPATIBILITY_2
932 wxImage::wxImage( const wxBitmap
&bitmap
)
937 wxFAIL_MSG( wxT("invalid bitmap") );
941 // create an wxImage object
942 int width
= bitmap
.GetWidth();
943 int height
= bitmap
.GetHeight();
944 Create( width
, height
);
945 unsigned char *data
= GetData();
948 wxFAIL_MSG( wxT("could not allocate data for image") );
952 // calc the number of bytes per scanline and padding in the DIB
953 int bytePerLine
= width
*3;
954 int sizeDWORD
= sizeof( DWORD
);
955 int lineBoundary
= bytePerLine
% sizeDWORD
;
957 if( lineBoundary
> 0 )
959 padding
= sizeDWORD
- lineBoundary
;
960 bytePerLine
+= padding
;
963 // create a DIB header
964 int headersize
= sizeof(BITMAPINFOHEADER
);
965 BITMAPINFO
*lpDIBh
= (BITMAPINFO
*) malloc( headersize
);
968 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
972 // Fill in the DIB header
973 lpDIBh
->bmiHeader
.biSize
= headersize
;
974 lpDIBh
->bmiHeader
.biWidth
= width
;
975 lpDIBh
->bmiHeader
.biHeight
= -height
;
976 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
* height
;
977 lpDIBh
->bmiHeader
.biPlanes
= 1;
978 lpDIBh
->bmiHeader
.biBitCount
= 24;
979 lpDIBh
->bmiHeader
.biCompression
= BI_RGB
;
980 lpDIBh
->bmiHeader
.biClrUsed
= 0;
981 // These seem not really needed for our purpose here.
982 lpDIBh
->bmiHeader
.biClrImportant
= 0;
983 lpDIBh
->bmiHeader
.biXPelsPerMeter
= 0;
984 lpDIBh
->bmiHeader
.biYPelsPerMeter
= 0;
985 // memory for DIB data
986 unsigned char *lpBits
;
987 lpBits
= (unsigned char *) malloc( lpDIBh
->bmiHeader
.biSizeImage
);
990 wxFAIL_MSG( wxT("could not allocate data for DIB") );
996 // copy data from the device-dependent bitmap to the DIB
997 HDC hdc
= ::GetDC(NULL
);
999 hbitmap
= (HBITMAP
) bitmap
.GetHBITMAP();
1000 ::GetDIBits( hdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
1002 // copy DIB data into the wxImage object
1004 unsigned char *ptdata
= data
;
1005 unsigned char *ptbits
= lpBits
;
1006 for( i
=0; i
<height
; i
++ )
1008 for( j
=0; j
<width
; j
++ )
1010 *(ptdata
++) = *(ptbits
+2);
1011 *(ptdata
++) = *(ptbits
+1);
1012 *(ptdata
++) = *(ptbits
);
1018 // similarly, set data according to the possible mask bitmap
1019 if( bitmap
.GetMask() && bitmap
.GetMask()->GetMaskBitmap() )
1021 hbitmap
= (HBITMAP
) bitmap
.GetMask()->GetMaskBitmap();
1022 // memory DC created, color set, data copied, and memory DC deleted
1023 HDC memdc
= ::CreateCompatibleDC( hdc
);
1024 ::SetTextColor( memdc
, RGB( 0, 0, 0 ) );
1025 ::SetBkColor( memdc
, RGB( 255, 255, 255 ) );
1026 ::GetDIBits( memdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
1027 ::DeleteDC( memdc
);
1028 // background color set to RGB(16,16,16) in consistent with wxGTK
1029 unsigned char r
=16, g
=16, b
=16;
1032 for( i
=0; i
<height
; i
++ )
1034 for( j
=0; j
<width
; j
++ )
1048 SetMaskColour( r
, g
, b
);
1055 // free allocated resources
1056 ::ReleaseDC(NULL
, hdc
);
1065 #include <PictUtils.h>
1067 extern CTabHandle
wxMacCreateColorTable( int numColors
) ;
1068 extern void wxMacDestroyColorTable( CTabHandle colors
) ;
1069 extern void wxMacSetColorTableEntry( CTabHandle newColors
, int index
, int red
, int green
, int blue
) ;
1070 extern GWorldPtr
wxMacCreateGWorld( int height
, int width
, int depth
) ;
1071 extern void wxMacDestroyGWorld( GWorldPtr gw
) ;
1073 wxBitmap
wxImage::ConvertToBitmap() const
1075 // width and height of the device-dependent bitmap
1076 int width
= GetWidth();
1077 int height
= GetHeight();
1081 wxBitmap
bitmap( width
, height
, wxDisplayDepth() ) ;
1088 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1090 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1092 wxMask *mask = new wxMask();
1093 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1095 bitmap.SetMask( mask );
1101 int r_mask
= GetMaskRed();
1102 int g_mask
= GetMaskGreen();
1103 int b_mask
= GetMaskBlue();
1106 GDHandle origDevice
;
1108 GetGWorld( &origPort
, &origDevice
) ;
1109 SetGWorld( bitmap
.GetHBITMAP() , NULL
) ;
1111 register unsigned char* data
= GetData();
1114 for (int y
= 0; y
< height
; y
++)
1117 unsigned char lastr
= 0 ;
1118 unsigned char lastg
= 0 ;
1119 unsigned char lastb
= 0 ;
1120 RGBColor lastcolor
;
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 if ( r
!= lastr
|| g
!= lastg
|| b
!= lastb
)
1131 lastcolor
.red
= ( lastr
<< 8 ) + lastr
;
1132 lastcolor
.green
= ( lastg
<< 8 ) + lastg
;
1133 lastcolor
.blue
= ( lastb
<< 8 ) + lastb
;
1134 RGBForeColor( &lastcolor
) ;
1141 lastcolor
.red
= ( lastr
<< 8 ) + lastr
;
1142 lastcolor
.green
= ( lastg
<< 8 ) + lastg
;
1143 lastcolor
.blue
= ( lastb
<< 8 ) + lastb
;
1144 RGBForeColor( &lastcolor
) ;
1145 LineTo( width
- 1 , y
) ;
1147 for (int x
= 0; x
< width
; x
++)
1149 unsigned char r
= data
[index
++];
1150 unsigned char g
= data
[index
++];
1151 unsigned char b
= data
[index
++];
1153 color
.red
= ( r
<< 8 ) + r
;
1154 color
.green
= ( g
<< 8 ) + g
;
1155 color
.blue
= ( b
<< 8 ) + b
;
1156 SetCPixel( x
, y
, &color
) ;
1161 SetGWorld( origPort
, origDevice
) ;
1167 wxImage::wxImage( const wxBitmap
&bitmap
)
1172 wxFAIL_MSG( "invalid bitmap" );
1176 // create an wxImage object
1177 int width
= bitmap
.GetWidth();
1178 int height
= bitmap
.GetHeight();
1179 Create( width
, height
);
1181 unsigned char *data = GetData();
1184 wxFAIL_MSG( "could not allocate data for image" );
1188 // calc the number of bytes per scanline and padding in the DIB
1189 int bytePerLine = width*3;
1190 int sizeDWORD = sizeof( DWORD );
1191 div_t lineBoundary = div( bytePerLine, sizeDWORD );
1193 if( lineBoundary.rem > 0 )
1195 padding = sizeDWORD - lineBoundary.rem;
1196 bytePerLine += padding;
1199 // create a DIB header
1200 int headersize = sizeof(BITMAPINFOHEADER);
1201 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
1204 wxFAIL_MSG( "could not allocate data for DIB header" );
1208 // Fill in the DIB header
1209 lpDIBh->bmiHeader.biSize = headersize;
1210 lpDIBh->bmiHeader.biWidth = width;
1211 lpDIBh->bmiHeader.biHeight = -height;
1212 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
1213 lpDIBh->bmiHeader.biPlanes = 1;
1214 lpDIBh->bmiHeader.biBitCount = 24;
1215 lpDIBh->bmiHeader.biCompression = BI_RGB;
1216 lpDIBh->bmiHeader.biClrUsed = 0;
1217 // These seem not really needed for our purpose here.
1218 lpDIBh->bmiHeader.biClrImportant = 0;
1219 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
1220 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
1221 // memory for DIB data
1222 unsigned char *lpBits;
1223 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
1226 wxFAIL_MSG( "could not allocate data for DIB" );
1232 // copy data from the device-dependent bitmap to the DIB
1233 HDC hdc = ::GetDC(NULL);
1235 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
1236 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1238 // copy DIB data into the wxImage object
1240 unsigned char *ptdata = data;
1241 unsigned char *ptbits = lpBits;
1242 for( i=0; i<height; i++ )
1244 for( j=0; j<width; j++ )
1246 *(ptdata++) = *(ptbits+2);
1247 *(ptdata++) = *(ptbits+1);
1248 *(ptdata++) = *(ptbits );
1254 // similarly, set data according to the possible mask bitmap
1255 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
1257 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
1258 // memory DC created, color set, data copied, and memory DC deleted
1259 HDC memdc = ::CreateCompatibleDC( hdc );
1260 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
1261 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
1262 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1263 ::DeleteDC( memdc );
1264 // background color set to RGB(16,16,16) in consistent with wxGTK
1265 unsigned char r=16, g=16, b=16;
1268 for( i=0; i<height; i++ )
1270 for( j=0; j<width; j++ )
1284 SetMaskColour( r, g, b );
1291 // free allocated resources
1292 ::ReleaseDC(NULL, hdc);
1300 //-----------------------------------------------------------------------------
1301 // GTK conversion routines
1302 //-----------------------------------------------------------------------------
1306 #include <gtk/gtk.h>
1307 #include <gdk/gdk.h>
1308 #include <gdk/gdkx.h>
1310 #if (GTK_MINOR_VERSION > 0)
1311 #include <gdk/gdkrgb.h>
1314 wxBitmap
wxImage::ConvertToBitmap() const
1318 wxCHECK_MSG( Ok(), bitmap
, wxT("invalid image") );
1320 int width
= GetWidth();
1321 int height
= GetHeight();
1323 bitmap
.SetHeight( height
);
1324 bitmap
.SetWidth( width
);
1326 bitmap
.SetPixmap( gdk_pixmap_new( (GdkWindow
*)&gdk_root_parent
, width
, height
, -1 ) );
1330 GdkVisual
*visual
= gdk_window_get_visual( bitmap
.GetPixmap() );
1331 if (visual
== NULL
) visual
= gdk_visual_get_system();
1332 int bpp
= visual
->depth
;
1334 bitmap
.SetDepth( bpp
);
1336 if ((bpp
== 16) && (visual
->red_mask
!= 0xf800)) bpp
= 15;
1337 if (bpp
< 8) bpp
= 8;
1339 #if (GTK_MINOR_VERSION > 0)
1341 if (!HasMask() && (bpp
> 8))
1343 static bool s_hasInitialized
= FALSE
;
1345 if (!s_hasInitialized
)
1348 s_hasInitialized
= TRUE
;
1351 GdkGC
*gc
= gdk_gc_new( bitmap
.GetPixmap() );
1353 gdk_draw_rgb_image( bitmap
.GetPixmap(),
1357 GDK_RGB_DITHER_NONE
,
1368 // Create picture image
1370 GdkImage
*data_image
=
1371 gdk_image_new( GDK_IMAGE_FASTEST
, gdk_visual_get_system(), width
, height
);
1373 // Create mask image
1375 GdkImage
*mask_image
= (GdkImage
*) NULL
;
1379 unsigned char *mask_data
= (unsigned char*)malloc( ((width
>> 3)+8) * height
);
1381 mask_image
= gdk_image_new_bitmap( gdk_visual_get_system(), mask_data
, width
, height
);
1383 wxMask
*mask
= new wxMask();
1384 mask
->m_bitmap
= gdk_pixmap_new( (GdkWindow
*)&gdk_root_parent
, width
, height
, 1 );
1386 bitmap
.SetMask( mask
);
1391 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
1392 byte_order b_o
= RGB
;
1396 GdkVisual
*visual
= gdk_visual_get_system();
1397 if ((visual
->red_mask
> visual
->green_mask
) && (visual
->green_mask
> visual
->blue_mask
)) b_o
= RGB
;
1398 else if ((visual
->red_mask
> visual
->blue_mask
) && (visual
->blue_mask
> visual
->green_mask
)) b_o
= RGB
;
1399 else if ((visual
->blue_mask
> visual
->red_mask
) && (visual
->red_mask
> visual
->green_mask
)) b_o
= BRG
;
1400 else if ((visual
->blue_mask
> visual
->green_mask
) && (visual
->green_mask
> visual
->red_mask
)) b_o
= BGR
;
1401 else if ((visual
->green_mask
> visual
->red_mask
) && (visual
->red_mask
> visual
->blue_mask
)) b_o
= GRB
;
1402 else if ((visual
->green_mask
> visual
->blue_mask
) && (visual
->blue_mask
> visual
->red_mask
)) b_o
= GBR
;
1405 int r_mask
= GetMaskRed();
1406 int g_mask
= GetMaskGreen();
1407 int b_mask
= GetMaskBlue();
1409 unsigned char* data
= GetData();
1412 for (int y
= 0; y
< height
; y
++)
1414 for (int x
= 0; x
< width
; x
++)
1416 int r
= data
[index
];
1418 int g
= data
[index
];
1420 int b
= data
[index
];
1425 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
1426 gdk_image_put_pixel( mask_image
, x
, y
, 1 );
1428 gdk_image_put_pixel( mask_image
, x
, y
, 0 );
1433 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
1434 gdk_image_put_pixel( mask_image
, x
, y
, 1 );
1436 gdk_image_put_pixel( mask_image
, x
, y
, 0 );
1444 if (wxTheApp
->m_colorCube
)
1446 pixel
= wxTheApp
->m_colorCube
[ ((r
& 0xf8) << 7) + ((g
& 0xf8) << 2) + ((b
& 0xf8) >> 3) ];
1450 GdkColormap
*cmap
= gtk_widget_get_default_colormap();
1451 GdkColor
*colors
= cmap
->colors
;
1452 int max
= 3 * (65536);
1454 for (int i
= 0; i
< cmap
->size
; i
++)
1456 int rdiff
= (r
<< 8) - colors
[i
].red
;
1457 int gdiff
= (g
<< 8) - colors
[i
].green
;
1458 int bdiff
= (b
<< 8) - colors
[i
].blue
;
1459 int sum
= ABS (rdiff
) + ABS (gdiff
) + ABS (bdiff
);
1460 if (sum
< max
) { pixel
= i
; max
= sum
; }
1464 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1470 guint32 pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
1471 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1476 guint32 pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
1477 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1486 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
1487 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
1488 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
1489 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
1490 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
1491 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
1493 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1502 GdkGC
*data_gc
= gdk_gc_new( bitmap
.GetPixmap() );
1504 gdk_draw_image( bitmap
.GetPixmap(), data_gc
, data_image
, 0, 0, 0, 0, width
, height
);
1506 gdk_image_destroy( data_image
);
1507 gdk_gc_unref( data_gc
);
1513 GdkGC
*mask_gc
= gdk_gc_new( bitmap
.GetMask()->GetBitmap() );
1515 gdk_draw_image( bitmap
.GetMask()->GetBitmap(), mask_gc
, mask_image
, 0, 0, 0, 0, width
, height
);
1517 gdk_image_destroy( mask_image
);
1518 gdk_gc_unref( mask_gc
);
1524 wxImage::wxImage( const wxBitmap
&bitmap
)
1526 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
1528 GdkImage
*gdk_image
= (GdkImage
*) NULL
;
1529 if (bitmap
.GetPixmap())
1531 gdk_image
= gdk_image_get( bitmap
.GetPixmap(),
1533 bitmap
.GetWidth(), bitmap
.GetHeight() );
1535 if (bitmap
.GetBitmap())
1537 gdk_image
= gdk_image_get( bitmap
.GetBitmap(),
1539 bitmap
.GetWidth(), bitmap
.GetHeight() );
1542 wxFAIL_MSG( wxT("Ill-formed bitmap") );
1545 wxCHECK_RET( gdk_image
, wxT("couldn't create image") );
1547 Create( bitmap
.GetWidth(), bitmap
.GetHeight() );
1548 char unsigned *data
= GetData();
1552 gdk_image_destroy( gdk_image
);
1553 wxFAIL_MSG( wxT("couldn't create image") );
1557 GdkImage
*gdk_image_mask
= (GdkImage
*) NULL
;
1558 if (bitmap
.GetMask())
1560 gdk_image_mask
= gdk_image_get( bitmap
.GetMask()->GetBitmap(),
1562 bitmap
.GetWidth(), bitmap
.GetHeight() );
1564 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1568 if (bitmap
.GetPixmap())
1570 GdkVisual
*visual
= gdk_window_get_visual( bitmap
.GetPixmap() );
1572 if (visual
== NULL
) visual
= gdk_window_get_visual( (GdkWindow
*) &gdk_root_parent
);
1573 bpp
= visual
->depth
;
1574 if ((bpp
== 16) && (visual
->red_mask
!= 0xf800)) bpp
= 15;
1576 if (bitmap
.GetBitmap())
1581 GdkColormap
*cmap
= gtk_widget_get_default_colormap();
1584 for (int j
= 0; j
< bitmap
.GetHeight(); j
++)
1586 for (int i
= 0; i
< bitmap
.GetWidth(); i
++)
1588 wxInt32 pixel
= gdk_image_get_pixel( gdk_image
, i
, j
);
1603 } else if (bpp
<= 8)
1605 data
[pos
] = cmap
->colors
[pixel
].red
>> 8;
1606 data
[pos
+1] = cmap
->colors
[pixel
].green
>> 8;
1607 data
[pos
+2] = cmap
->colors
[pixel
].blue
>> 8;
1608 } else if (bpp
== 15)
1610 #if (wxBYTE_ORDER == wxBIG_ENDIAN)
1613 data
[pos
] = (pixel
>> 7) & 0xf8;
1614 data
[pos
+1] = (pixel
>> 2) & 0xf8;
1615 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1616 } else if (bpp
== 16)
1618 #if (wxBYTE_ORDER == wxBIG_ENDIAN)
1621 data
[pos
] = (pixel
>> 8) & 0xf8;
1622 data
[pos
+1] = (pixel
>> 3) & 0xfc;
1623 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1626 #if (wxBYTE_ORDER == wxBIG_ENDIAN)
1627 data
[pos
] = (pixel
) & 0xff; // Red
1628 data
[pos
+1] = (pixel
>> 8) & 0xff; // Green
1629 data
[pos
+2] = (pixel
>> 16) & 0xff; // Blue
1631 data
[pos
] = (pixel
>> 16) & 0xff;
1632 data
[pos
+1] = (pixel
>> 8) & 0xff;
1633 data
[pos
+2] = pixel
& 0xff;
1639 int mask_pixel
= gdk_image_get_pixel( gdk_image_mask
, i
, j
);
1640 if (mask_pixel
== 0)
1652 gdk_image_destroy( gdk_image
);
1653 if (gdk_image_mask
) gdk_image_destroy( gdk_image_mask
);
1658 //-----------------------------------------------------------------------------
1659 // Motif conversion routines
1660 //-----------------------------------------------------------------------------
1664 #pragma message disable nosimpint
1668 #pragma message enable nosimpint
1670 #include "wx/utils.h"
1675 Date: Wed, 05 Jan 2000 11:45:40 +0100
1676 From: Frits Boel <boel@niob.knaw.nl>
1677 To: julian.smart@ukonline.co.uk
1678 Subject: Patch for Motif ConvertToBitmap
1682 I've been working on a wxWin application for image processing. From the
1683 beginning, I was surprised by the (lack of) speed of ConvertToBitmap,
1684 till I looked in the source code of image.cpp. I saw that converting a
1685 wxImage to a bitmap with 8-bit pixels is done with comparing every pixel
1686 to the 256 colors of the palet. A very time-consuming piece of code!
1688 Because I wanted a faster application, I've made a 'patch' for this. In
1689 short: every pixel of the image is compared to a sorted list with
1690 colors. If the color is found in the list, the palette entry is
1691 returned; if the color is not found, the color palette is searched and
1692 then the palette entry is returned and the color added to the sorted
1695 Maybe there is another method for this, namely changing the palette
1696 itself (if the colors are known, as is the case with tiffs with a
1697 colormap). I did not look at this, maybe someone else did?
1699 The code of the patch is attached, have a look on it, and maybe you will
1700 ship it with the next release of wxMotif?
1705 Software engineer at Hubrecht Laboratory, The Netherlands.
1712 wxSearchColor( void );
1713 wxSearchColor( int size
, XColor
*colors
);
1714 ~wxSearchColor( void );
1716 int SearchColor( int r
, int g
, int b
);
1718 int AddColor( unsigned int value
, int pos
);
1722 unsigned int *color
;
1729 wxSearchColor::wxSearchColor( void )
1732 this->colors
= (XColor
*) NULL
;
1733 this->color
= (unsigned int *) NULL
;
1734 this->entry
= (int*) NULL
;
1740 wxSearchColor::wxSearchColor( int size
, XColor
*colors
)
1744 this->colors
= colors
;
1745 this->color
= new unsigned int[size
];
1746 this->entry
= new int [size
];
1748 for (i
= 0; i
< this->size
; i
++ ) {
1749 this->entry
[i
] = -1;
1752 this->bottom
= this->top
= ( size
>> 1 );
1755 wxSearchColor::~wxSearchColor( void )
1757 if ( this->color
) delete this->color
;
1758 if ( this->entry
) delete this->entry
;
1761 int wxSearchColor::SearchColor( int r
, int g
, int b
)
1763 unsigned int value
= ( ( ( r
* 256 ) + g
) * 256 ) + b
;
1764 int begin
= this->bottom
;
1765 int end
= this->top
;
1768 while ( begin
<= end
) {
1770 middle
= ( begin
+ end
) >> 1;
1772 if ( value
== this->color
[middle
] ) {
1773 return( this->entry
[middle
] );
1774 } else if ( value
< this->color
[middle
] ) {
1782 return AddColor( value
, middle
);
1785 int wxSearchColor::AddColor( unsigned int value
, int pos
)
1789 int max
= 3 * (65536);
1790 for ( i
= 0; i
< 256; i
++ ) {
1791 int rdiff
= ((value
>> 8) & 0xFF00 ) - colors
[i
].red
;
1792 int gdiff
= ((value
) & 0xFF00 ) - colors
[i
].green
;
1793 int bdiff
= ((value
<< 8) & 0xFF00 ) - colors
[i
].blue
;
1794 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
1795 if (sum
< max
) { pixel
= i
; max
= sum
; }
1798 if ( this->entry
[pos
] < 0 ) {
1799 this->color
[pos
] = value
;
1800 this->entry
[pos
] = pixel
;
1801 } else if ( value
< this->color
[pos
] ) {
1803 if ( this->bottom
> 0 ) {
1804 for ( i
= this->bottom
; i
< pos
; i
++ ) {
1805 this->color
[i
-1] = this->color
[i
];
1806 this->entry
[i
-1] = this->entry
[i
];
1809 this->color
[pos
-1] = value
;
1810 this->entry
[pos
-1] = pixel
;
1811 } else if ( this->top
< this->size
-1 ) {
1812 for ( i
= this->top
; i
>= pos
; i
-- ) {
1813 this->color
[i
+1] = this->color
[i
];
1814 this->entry
[i
+1] = this->entry
[i
];
1817 this->color
[pos
] = value
;
1818 this->entry
[pos
] = pixel
;
1823 if ( this->top
< this->size
-1 ) {
1824 for ( i
= this->top
; i
> pos
; i
-- ) {
1825 this->color
[i
+1] = this->color
[i
];
1826 this->entry
[i
+1] = this->entry
[i
];
1829 this->color
[pos
+1] = value
;
1830 this->entry
[pos
+1] = pixel
;
1831 } else if ( this->bottom
> 0 ) {
1832 for ( i
= this->bottom
; i
< pos
; i
++ ) {
1833 this->color
[i
-1] = this->color
[i
];
1834 this->entry
[i
-1] = this->entry
[i
];
1837 this->color
[pos
] = value
;
1838 this->entry
[pos
] = pixel
;
1846 wxBitmap
wxImage::ConvertToBitmap() const
1850 wxCHECK_MSG( Ok(), bitmap
, wxT("invalid image") );
1852 int width
= GetWidth();
1853 int height
= GetHeight();
1855 bitmap
.SetHeight( height
);
1856 bitmap
.SetWidth( width
);
1858 Display
*dpy
= (Display
*) wxGetDisplay();
1859 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1860 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1864 XImage
*data_image
= XCreateImage( dpy
, vis
, bpp
, ZPixmap
, 0, 0, width
, height
, 32, 0 );
1865 data_image
->data
= (char*) malloc( data_image
->bytes_per_line
* data_image
->height
);
1867 bitmap
.Create( width
, height
, bpp
);
1872 GdkImage *mask_image = (GdkImage*) NULL;
1876 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1878 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1880 wxMask *mask = new wxMask();
1881 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1883 bitmap.SetMask( mask );
1887 // Retrieve depth info
1889 XVisualInfo vinfo_template
;
1892 vinfo_template
.visual
= vis
;
1893 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1894 vinfo_template
.depth
= bpp
;
1897 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
1899 wxCHECK_MSG( vi
, wxNullBitmap
, wxT("no visual") );
1903 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1904 if (bpp
< 8) bpp
= 8;
1908 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
1909 byte_order b_o
= RGB
;
1913 if ((vi
->red_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->blue_mask
)) b_o
= RGB
;
1914 else if ((vi
->red_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->green_mask
)) b_o
= RGB
;
1915 else if ((vi
->blue_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->green_mask
)) b_o
= BRG
;
1916 else if ((vi
->blue_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->red_mask
)) b_o
= BGR
;
1917 else if ((vi
->green_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->blue_mask
)) b_o
= GRB
;
1918 else if ((vi
->green_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->red_mask
)) b_o
= GBR
;
1922 int r_mask = GetMaskRed();
1923 int g_mask = GetMaskGreen();
1924 int b_mask = GetMaskBlue();
1930 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap( dpy
);
1932 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
1933 XQueryColors( dpy
, cmap
, colors
, 256 );
1936 wxSearchColor
scolor( 256, colors
);
1937 unsigned char* data
= GetData();
1940 for (int y
= 0; y
< height
; y
++)
1942 for (int x
= 0; x
< width
; x
++)
1944 int r
= data
[index
];
1946 int g
= data
[index
];
1948 int b
= data
[index
];
1954 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1955 gdk_image_put_pixel( mask_image, x, y, 1 );
1957 gdk_image_put_pixel( mask_image, x, y, 0 );
1965 #if 0 // Old, slower code
1968 if (wxTheApp->m_colorCube)
1970 pixel = wxTheApp->m_colorCube
1971 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1976 int max
= 3 * (65536);
1977 for (int i
= 0; i
< 256; i
++)
1979 int rdiff
= (r
<< 8) - colors
[i
].red
;
1980 int gdiff
= (g
<< 8) - colors
[i
].green
;
1981 int bdiff
= (b
<< 8) - colors
[i
].blue
;
1982 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
1983 if (sum
< max
) { pixel
= i
; max
= sum
; }
1990 // And this is all to get the 'right' color...
1991 int pixel
= scolor
.SearchColor( r
, g
, b
);
1992 XPutPixel( data_image
, x
, y
, pixel
);
1997 int pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
1998 XPutPixel( data_image
, x
, y
, pixel
);
2003 int pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
2004 XPutPixel( data_image
, x
, y
, pixel
);
2013 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
2014 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
2015 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
2016 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
2017 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
2018 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
2020 XPutPixel( data_image
, x
, y
, pixel
);
2030 gcvalues
.foreground
= BlackPixel( dpy
, DefaultScreen( dpy
) );
2031 GC gc
= XCreateGC( dpy
, RootWindow ( dpy
, DefaultScreen(dpy
) ), GCForeground
, &gcvalues
);
2032 XPutImage( dpy
, (Drawable
)bitmap
.GetPixmap(), gc
, data_image
, 0, 0, 0, 0, width
, height
);
2034 XDestroyImage( data_image
);
2042 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
2044 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
2046 gdk_image_destroy( mask_image );
2047 gdk_gc_unref( mask_gc );
2054 wxImage::wxImage( const wxBitmap
&bitmap
)
2056 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
2058 Display
*dpy
= (Display
*) wxGetDisplay();
2059 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
2060 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
2062 XImage
*ximage
= XGetImage( dpy
,
2063 (Drawable
)bitmap
.GetPixmap(),
2065 bitmap
.GetWidth(), bitmap
.GetHeight(),
2066 AllPlanes
, ZPixmap
);
2068 wxCHECK_RET( ximage
, wxT("couldn't create image") );
2070 Create( bitmap
.GetWidth(), bitmap
.GetHeight() );
2071 char unsigned *data
= GetData();
2075 XDestroyImage( ximage
);
2076 wxFAIL_MSG( wxT("couldn't create image") );
2081 GdkImage *gdk_image_mask = (GdkImage*) NULL;
2082 if (bitmap.GetMask())
2084 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
2086 bitmap.GetWidth(), bitmap.GetHeight() );
2088 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
2092 // Retrieve depth info
2094 XVisualInfo vinfo_template
;
2097 vinfo_template
.visual
= vis
;
2098 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
2099 vinfo_template
.depth
= bpp
;
2102 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
2104 wxCHECK_RET( vi
, wxT("no visual") );
2106 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
2113 Colormap cmap
= (Colormap
)wxTheApp
->GetMainColormap( dpy
);
2115 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
2116 XQueryColors( dpy
, cmap
, colors
, 256 );
2120 for (int j
= 0; j
< bitmap
.GetHeight(); j
++)
2122 for (int i
= 0; i
< bitmap
.GetWidth(); i
++)
2124 int pixel
= XGetPixel( ximage
, i
, j
);
2127 data
[pos
] = colors
[pixel
].red
>> 8;
2128 data
[pos
+1] = colors
[pixel
].green
>> 8;
2129 data
[pos
+2] = colors
[pixel
].blue
>> 8;
2130 } else if (bpp
== 15)
2132 data
[pos
] = (pixel
>> 7) & 0xf8;
2133 data
[pos
+1] = (pixel
>> 2) & 0xf8;
2134 data
[pos
+2] = (pixel
<< 3) & 0xf8;
2135 } else if (bpp
== 16)
2137 data
[pos
] = (pixel
>> 8) & 0xf8;
2138 data
[pos
+1] = (pixel
>> 3) & 0xfc;
2139 data
[pos
+2] = (pixel
<< 3) & 0xf8;
2142 data
[pos
] = (pixel
>> 16) & 0xff;
2143 data
[pos
+1] = (pixel
>> 8) & 0xff;
2144 data
[pos
+2] = pixel
& 0xff;
2150 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
2151 if (mask_pixel == 0)
2164 XDestroyImage( ximage
);
2166 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
2172 // OS/2 Presentation manager conversion routings
2174 wxBitmap
wxImage::ConvertToBitmap() const
2177 return wxNullBitmap
;
2178 wxBitmap bitmap
; // remove
2181 int sizeLimit = 1024*768*3;
2183 // width and height of the device-dependent bitmap
2184 int width = GetWidth();
2185 int bmpHeight = GetHeight();
2187 // calc the number of bytes per scanline and padding
2188 int bytePerLine = width*3;
2189 int sizeDWORD = sizeof( DWORD );
2190 int lineBoundary = bytePerLine % sizeDWORD;
2192 if( lineBoundary > 0 )
2194 padding = sizeDWORD - lineBoundary;
2195 bytePerLine += padding;
2197 // calc the number of DIBs and heights of DIBs
2200 int height = sizeLimit/bytePerLine;
2201 if( height >= bmpHeight )
2205 numDIB = bmpHeight / height;
2206 hRemain = bmpHeight % height;
2207 if( hRemain >0 ) numDIB++;
2210 // set bitmap parameters
2212 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
2213 bitmap.SetWidth( width );
2214 bitmap.SetHeight( bmpHeight );
2215 bitmap.SetDepth( wxDisplayDepth() );
2217 // create a DIB header
2218 int headersize = sizeof(BITMAPINFOHEADER);
2219 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
2220 wxCHECK_MSG( lpDIBh, bitmap, wxT("could not allocate memory for DIB header") );
2221 // Fill in the DIB header
2222 lpDIBh->bmiHeader.biSize = headersize;
2223 lpDIBh->bmiHeader.biWidth = (DWORD)width;
2224 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2225 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2226 // the general formula for biSizeImage:
2227 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
2228 lpDIBh->bmiHeader.biPlanes = 1;
2229 lpDIBh->bmiHeader.biBitCount = 24;
2230 lpDIBh->bmiHeader.biCompression = BI_RGB;
2231 lpDIBh->bmiHeader.biClrUsed = 0;
2232 // These seem not really needed for our purpose here.
2233 lpDIBh->bmiHeader.biClrImportant = 0;
2234 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2235 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2236 // memory for DIB data
2237 unsigned char *lpBits;
2238 lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
2241 wxFAIL_MSG( wxT("could not allocate memory for DIB") );
2246 // create and set the device-dependent bitmap
2247 HDC hdc = ::GetDC(NULL);
2248 HDC memdc = ::CreateCompatibleDC( hdc );
2250 hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
2251 ::SelectObject( memdc, hbitmap);
2253 // copy image data into DIB data and then into DDB (in a loop)
2254 unsigned char *data = GetData();
2257 unsigned char *ptdata = data;
2258 unsigned char *ptbits;
2260 for( n=0; n<numDIB; n++ )
2262 if( numDIB > 1 && n == numDIB-1 && hRemain > 0 )
2264 // redefine height and size of the (possibly) last smaller DIB
2265 // memory is not reallocated
2267 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2268 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2272 for( j=0; j<height; j++ )
2274 for( i=0; i<width; i++ )
2276 *(ptbits++) = *(ptdata+2);
2277 *(ptbits++) = *(ptdata+1);
2278 *(ptbits++) = *(ptdata );
2281 for( i=0; i< padding; i++ ) *(ptbits++) = 0;
2283 ::StretchDIBits( memdc, 0, origin, width, height,\
2284 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2286 // if numDIB = 1, lines below can also be used
2287 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
2288 // The above line is equivalent to the following two lines.
2289 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2290 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
2291 // or the following lines
2292 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2293 // HDC memdc = ::CreateCompatibleDC( hdc );
2294 // ::SelectObject( memdc, hbitmap);
2295 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
2296 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
2297 // ::SelectObject( memdc, 0 );
2298 // ::DeleteDC( memdc );
2300 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
2302 // similarly, created an mono-bitmap for the possible mask
2305 hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL );
2306 ::SelectObject( memdc, hbitmap);
2307 if( numDIB == 1 ) height = bmpHeight;
2308 else height = sizeLimit/bytePerLine;
2309 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2310 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2312 unsigned char r = GetMaskRed();
2313 unsigned char g = GetMaskGreen();
2314 unsigned char b = GetMaskBlue();
2315 unsigned char zero = 0, one = 255;
2317 for( n=0; n<numDIB; n++ )
2319 if( numDIB > 1 && n == numDIB - 1 && hRemain > 0 )
2321 // redefine height and size of the (possibly) last smaller DIB
2322 // memory is not reallocated
2324 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2325 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2328 for( int j=0; j<height; j++ )
2330 for(i=0; i<width; i++ )
2332 if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
2345 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
2347 ::StretchDIBits( memdc, 0, origin, width, height,\
2348 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2351 // create a wxMask object
2352 wxMask *mask = new wxMask();
2353 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
2354 bitmap.SetMask( mask );
2357 // free allocated resources
2358 ::SelectObject( memdc, 0 );
2359 ::DeleteDC( memdc );
2360 ::ReleaseDC(NULL, hdc);
2364 // check the wxBitmap object
2365 if( bitmap.GetHBITMAP() )
2366 bitmap.SetOk( TRUE );
2368 bitmap.SetOk( FALSE );
2373 wxImage::wxImage( const wxBitmap
&bitmap
)
2378 wxFAIL_MSG( wxT("invalid bitmap") );
2382 // create an wxImage object
2383 int width
= bitmap
.GetWidth();
2384 int height
= bitmap
.GetHeight();
2385 Create( width
, height
);
2386 unsigned char *data
= GetData();
2389 wxFAIL_MSG( wxT("could not allocate data for image") );
2393 // calc the number of bytes per scanline and padding in the DIB
2394 int bytePerLine
= width
*3;
2395 int sizeDWORD
= sizeof( DWORD
);
2396 int lineBoundary
= bytePerLine
% sizeDWORD
;
2398 if( lineBoundary
> 0 )
2400 padding
= sizeDWORD
- lineBoundary
;
2401 bytePerLine
+= padding
;
2405 // create a DIB header
2406 int headersize = sizeof(BITMAPINFOHEADER);
2407 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
2410 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
2414 // Fill in the DIB header
2415 lpDIBh->bmiHeader.biSize = headersize;
2416 lpDIBh->bmiHeader.biWidth = width;
2417 lpDIBh->bmiHeader.biHeight = -height;
2418 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
2419 lpDIBh->bmiHeader.biPlanes = 1;
2420 lpDIBh->bmiHeader.biBitCount = 24;
2421 lpDIBh->bmiHeader.biCompression = BI_RGB;
2422 lpDIBh->bmiHeader.biClrUsed = 0;
2423 // These seem not really needed for our purpose here.
2424 lpDIBh->bmiHeader.biClrImportant = 0;
2425 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2426 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2427 // memory for DIB data
2428 unsigned char *lpBits;
2429 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
2432 wxFAIL_MSG( wxT("could not allocate data for DIB") );
2438 // copy data from the device-dependent bitmap to the DIB
2439 HDC hdc = ::GetDC(NULL);
2441 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
2442 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2444 // copy DIB data into the wxImage object
2446 unsigned char *ptdata = data;
2447 unsigned char *ptbits = lpBits;
2448 for( i=0; i<height; i++ )
2450 for( j=0; j<width; j++ )
2452 *(ptdata++) = *(ptbits+2);
2453 *(ptdata++) = *(ptbits+1);
2454 *(ptdata++) = *(ptbits );
2460 // similarly, set data according to the possible mask bitmap
2461 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
2463 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
2464 // memory DC created, color set, data copied, and memory DC deleted
2465 HDC memdc = ::CreateCompatibleDC( hdc );
2466 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
2467 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
2468 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2469 ::DeleteDC( memdc );
2470 // background color set to RGB(16,16,16) in consistent with wxGTK
2471 unsigned char r=16, g=16, b=16;
2474 for( i=0; i<height; i++ )
2476 for( j=0; j<width; j++ )
2490 SetMaskColour( r, g, b );
2497 // free allocated resources
2498 ::ReleaseDC(NULL, hdc);
2506 // A module to allow wxImage initialization/cleanup
2507 // without calling these functions from app.cpp or from
2508 // the user's application.
2510 class wxImageModule
: public wxModule
2512 DECLARE_DYNAMIC_CLASS(wxImageModule
)
2515 bool OnInit() { wxImage::InitStandardHandlers(); return TRUE
; };
2516 void OnExit() { wxImage::CleanUpHandlers(); };
2519 IMPLEMENT_DYNAMIC_CLASS(wxImageModule
, wxModule
)
2522 //-----------------------------------------------------------------------------
2525 // Counts and returns the number of different colours. Optionally stops
2526 // when it exceeds 'stopafter' different colours. This is useful, for
2527 // example, to see if the image can be saved as 8-bit (256 colour or
2528 // less, in this case it would be invoked as CountColours(256)). Default
2529 // value for stopafter is -1 (don't care).
2531 unsigned long wxImage::CountColours( unsigned long stopafter
)
2536 unsigned char r
, g
, b
, *p
;
2537 unsigned long size
, nentries
, key
;
2540 size
= GetWidth() * GetHeight();
2543 for (unsigned long j
= 0; (j
< size
) && (nentries
<= stopafter
) ; j
++)
2548 key
= (r
<< 16) | (g
<< 8) | b
;
2550 hnode
= (wxHNode
*) h
.Get(key
);
2554 h
.Put(key
, (wxObject
*)(new wxHNode
));
2559 // delete all HNodes
2561 while ((node
= h
.Next()) != NULL
)
2562 delete (wxHNode
*)node
->GetData();
2569 // Computes the histogram of the image and fills a hash table, indexed
2570 // with integer keys built as 0xRRGGBB, containing wxHNode objects. Each
2571 // wxHNode contains an 'index' (useful to build a palette with the image
2572 // colours) and a 'value', which is the number of pixels in the image with
2575 unsigned long wxImage::ComputeHistogram( wxHashTable
&h
)
2577 unsigned char r
, g
, b
, *p
;
2578 unsigned long size
, nentries
, key
;
2582 size
= GetWidth() * GetHeight();
2585 for (unsigned long j
= 0; j
< size
; j
++)
2590 key
= (r
<< 16) | (g
<< 8) | b
;
2592 hnode
= (wxHNode
*) h
.Get(key
);
2598 hnode
= new wxHNode();
2599 hnode
->index
= nentries
++;
2602 h
.Put(key
, (wxObject
*)hnode
);