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 // 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 );
922 // free allocated resources
923 ::SelectObject( memdc
, 0 );
925 ::ReleaseDC(NULL
, hdc
);
929 #if WXWIN_COMPATIBILITY_2
930 // check the wxBitmap object
931 bitmap
.GetBitmapData()->SetOk();
932 #endif // WXWIN_COMPATIBILITY_2
937 wxImage::wxImage( const wxBitmap
&bitmap
)
942 wxFAIL_MSG( wxT("invalid bitmap") );
946 // create an wxImage object
947 int width
= bitmap
.GetWidth();
948 int height
= bitmap
.GetHeight();
949 Create( width
, height
);
950 unsigned char *data
= GetData();
953 wxFAIL_MSG( wxT("could not allocate data for image") );
957 // calc the number of bytes per scanline and padding in the DIB
958 int bytePerLine
= width
*3;
959 int sizeDWORD
= sizeof( DWORD
);
960 int lineBoundary
= bytePerLine
% sizeDWORD
;
962 if( lineBoundary
> 0 )
964 padding
= sizeDWORD
- lineBoundary
;
965 bytePerLine
+= padding
;
968 // create a DIB header
969 int headersize
= sizeof(BITMAPINFOHEADER
);
970 BITMAPINFO
*lpDIBh
= (BITMAPINFO
*) malloc( headersize
);
973 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
977 // Fill in the DIB header
978 lpDIBh
->bmiHeader
.biSize
= headersize
;
979 lpDIBh
->bmiHeader
.biWidth
= width
;
980 lpDIBh
->bmiHeader
.biHeight
= -height
;
981 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
* height
;
982 lpDIBh
->bmiHeader
.biPlanes
= 1;
983 lpDIBh
->bmiHeader
.biBitCount
= 24;
984 lpDIBh
->bmiHeader
.biCompression
= BI_RGB
;
985 lpDIBh
->bmiHeader
.biClrUsed
= 0;
986 // These seem not really needed for our purpose here.
987 lpDIBh
->bmiHeader
.biClrImportant
= 0;
988 lpDIBh
->bmiHeader
.biXPelsPerMeter
= 0;
989 lpDIBh
->bmiHeader
.biYPelsPerMeter
= 0;
990 // memory for DIB data
991 unsigned char *lpBits
;
992 lpBits
= (unsigned char *) malloc( lpDIBh
->bmiHeader
.biSizeImage
);
995 wxFAIL_MSG( wxT("could not allocate data for DIB") );
1001 // copy data from the device-dependent bitmap to the DIB
1002 HDC hdc
= ::GetDC(NULL
);
1004 hbitmap
= (HBITMAP
) bitmap
.GetHBITMAP();
1005 ::GetDIBits( hdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
1007 // copy DIB data into the wxImage object
1009 unsigned char *ptdata
= data
;
1010 unsigned char *ptbits
= lpBits
;
1011 for( i
=0; i
<height
; i
++ )
1013 for( j
=0; j
<width
; j
++ )
1015 *(ptdata
++) = *(ptbits
+2);
1016 *(ptdata
++) = *(ptbits
+1);
1017 *(ptdata
++) = *(ptbits
);
1023 // similarly, set data according to the possible mask bitmap
1024 if( bitmap
.GetMask() && bitmap
.GetMask()->GetMaskBitmap() )
1026 hbitmap
= (HBITMAP
) bitmap
.GetMask()->GetMaskBitmap();
1027 // memory DC created, color set, data copied, and memory DC deleted
1028 HDC memdc
= ::CreateCompatibleDC( hdc
);
1029 ::SetTextColor( memdc
, RGB( 0, 0, 0 ) );
1030 ::SetBkColor( memdc
, RGB( 255, 255, 255 ) );
1031 ::GetDIBits( memdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
1032 ::DeleteDC( memdc
);
1033 // background color set to RGB(16,16,16) in consistent with wxGTK
1034 unsigned char r
=16, g
=16, b
=16;
1037 for( i
=0; i
<height
; i
++ )
1039 for( j
=0; j
<width
; j
++ )
1053 SetMaskColour( r
, g
, b
);
1060 // free allocated resources
1061 ::ReleaseDC(NULL
, hdc
);
1070 #include <PictUtils.h>
1072 extern CTabHandle
wxMacCreateColorTable( int numColors
) ;
1073 extern void wxMacDestroyColorTable( CTabHandle colors
) ;
1074 extern void wxMacSetColorTableEntry( CTabHandle newColors
, int index
, int red
, int green
, int blue
) ;
1075 extern GWorldPtr
wxMacCreateGWorld( int height
, int width
, int depth
) ;
1076 extern void wxMacDestroyGWorld( GWorldPtr gw
) ;
1078 wxBitmap
wxImage::ConvertToBitmap() const
1080 // width and height of the device-dependent bitmap
1081 int width
= GetWidth();
1082 int height
= GetHeight();
1086 wxBitmap
bitmap( width
, height
, wxDisplayDepth() ) ;
1093 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1095 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1097 wxMask *mask = new wxMask();
1098 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1100 bitmap.SetMask( mask );
1106 int r_mask
= GetMaskRed();
1107 int g_mask
= GetMaskGreen();
1108 int b_mask
= GetMaskBlue();
1111 GDHandle origDevice
;
1113 GetGWorld( &origPort
, &origDevice
) ;
1114 SetGWorld( bitmap
.GetHBITMAP() , NULL
) ;
1116 register unsigned char* data
= GetData();
1119 for (int y
= 0; y
< height
; y
++)
1121 for (int x
= 0; x
< width
; x
++)
1123 unsigned char r
= data
[index
++];
1124 unsigned char g
= data
[index
++];
1125 unsigned char b
= data
[index
++];
1127 color
.red
= ( r
<< 8 ) + r
;
1128 color
.green
= ( g
<< 8 ) + g
;
1129 color
.blue
= ( b
<< 8 ) + b
;
1130 SetCPixel( x
, y
, &color
) ;
1134 SetGWorld( origPort
, origDevice
) ;
1138 wxColour
colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
1139 wxMask
*mask
= new wxMask( bitmap
, colour
);
1140 bitmap
.SetMask( mask
);
1146 wxImage::wxImage( const wxBitmap
&bitmap
)
1151 wxFAIL_MSG( "invalid bitmap" );
1155 // create an wxImage object
1156 int width
= bitmap
.GetWidth();
1157 int height
= bitmap
.GetHeight();
1158 Create( width
, height
);
1160 unsigned char *data = GetData();
1163 wxFAIL_MSG( "could not allocate data for image" );
1167 // calc the number of bytes per scanline and padding in the DIB
1168 int bytePerLine = width*3;
1169 int sizeDWORD = sizeof( DWORD );
1170 div_t lineBoundary = div( bytePerLine, sizeDWORD );
1172 if( lineBoundary.rem > 0 )
1174 padding = sizeDWORD - lineBoundary.rem;
1175 bytePerLine += padding;
1178 // create a DIB header
1179 int headersize = sizeof(BITMAPINFOHEADER);
1180 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
1183 wxFAIL_MSG( "could not allocate data for DIB header" );
1187 // Fill in the DIB header
1188 lpDIBh->bmiHeader.biSize = headersize;
1189 lpDIBh->bmiHeader.biWidth = width;
1190 lpDIBh->bmiHeader.biHeight = -height;
1191 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
1192 lpDIBh->bmiHeader.biPlanes = 1;
1193 lpDIBh->bmiHeader.biBitCount = 24;
1194 lpDIBh->bmiHeader.biCompression = BI_RGB;
1195 lpDIBh->bmiHeader.biClrUsed = 0;
1196 // These seem not really needed for our purpose here.
1197 lpDIBh->bmiHeader.biClrImportant = 0;
1198 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
1199 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
1200 // memory for DIB data
1201 unsigned char *lpBits;
1202 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
1205 wxFAIL_MSG( "could not allocate data for DIB" );
1211 // copy data from the device-dependent bitmap to the DIB
1212 HDC hdc = ::GetDC(NULL);
1214 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
1215 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1217 // copy DIB data into the wxImage object
1219 unsigned char *ptdata = data;
1220 unsigned char *ptbits = lpBits;
1221 for( i=0; i<height; i++ )
1223 for( j=0; j<width; j++ )
1225 *(ptdata++) = *(ptbits+2);
1226 *(ptdata++) = *(ptbits+1);
1227 *(ptdata++) = *(ptbits );
1233 // similarly, set data according to the possible mask bitmap
1234 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
1236 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
1237 // memory DC created, color set, data copied, and memory DC deleted
1238 HDC memdc = ::CreateCompatibleDC( hdc );
1239 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
1240 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
1241 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1242 ::DeleteDC( memdc );
1243 // background color set to RGB(16,16,16) in consistent with wxGTK
1244 unsigned char r=16, g=16, b=16;
1247 for( i=0; i<height; i++ )
1249 for( j=0; j<width; j++ )
1263 SetMaskColour( r, g, b );
1270 // free allocated resources
1271 ::ReleaseDC(NULL, hdc);
1279 //-----------------------------------------------------------------------------
1280 // GTK conversion routines
1281 //-----------------------------------------------------------------------------
1285 #include <gtk/gtk.h>
1286 #include <gdk/gdk.h>
1287 #include <gdk/gdkx.h>
1289 #if (GTK_MINOR_VERSION > 0)
1290 #include <gdk/gdkrgb.h>
1293 wxBitmap
wxImage::ConvertToMonoBitmap( unsigned char red
, unsigned char green
, unsigned char blue
)
1297 wxCHECK_MSG( Ok(), bitmap
, wxT("invalid image") );
1299 int width
= GetWidth();
1300 int height
= GetHeight();
1302 bitmap
.SetHeight( height
);
1303 bitmap
.SetWidth( width
);
1305 bitmap
.SetBitmap( gdk_pixmap_new( (GdkWindow
*)&gdk_root_parent
, width
, height
, 1 ) );
1307 bitmap
.SetDepth( 1 );
1309 // Create picture image
1311 unsigned char *data_data
= (unsigned char*)malloc( ((width
>> 3)+8) * height
);
1313 GdkImage
*data_image
=
1314 gdk_image_new_bitmap( gdk_visual_get_system(), data_data
, width
, height
);
1316 // Create mask image
1318 GdkImage
*mask_image
= (GdkImage
*) NULL
;
1322 unsigned char *mask_data
= (unsigned char*)malloc( ((width
>> 3)+8) * height
);
1324 mask_image
= gdk_image_new_bitmap( gdk_visual_get_system(), mask_data
, width
, height
);
1326 wxMask
*mask
= new wxMask();
1327 mask
->m_bitmap
= gdk_pixmap_new( (GdkWindow
*)&gdk_root_parent
, width
, height
, 1 );
1329 bitmap
.SetMask( mask
);
1332 int r_mask
= GetMaskRed();
1333 int g_mask
= GetMaskGreen();
1334 int b_mask
= GetMaskBlue();
1336 unsigned char* data
= GetData();
1339 for (int y
= 0; y
< height
; y
++)
1341 for (int x
= 0; x
< width
; x
++)
1343 int r
= data
[index
];
1345 int g
= data
[index
];
1347 int b
= data
[index
];
1352 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
1353 gdk_image_put_pixel( mask_image
, x
, y
, 1 );
1355 gdk_image_put_pixel( mask_image
, x
, y
, 0 );
1358 if ((r
== red
) && (b
== blue
) && (g
== green
))
1359 gdk_image_put_pixel( data_image
, x
, y
, 1 );
1361 gdk_image_put_pixel( data_image
, x
, y
, 0 );
1368 GdkGC
*data_gc
= gdk_gc_new( bitmap
.GetBitmap() );
1370 gdk_draw_image( bitmap
.GetBitmap(), data_gc
, data_image
, 0, 0, 0, 0, width
, height
);
1372 gdk_image_destroy( data_image
);
1373 gdk_gc_unref( data_gc
);
1379 GdkGC
*mask_gc
= gdk_gc_new( bitmap
.GetMask()->GetBitmap() );
1381 gdk_draw_image( bitmap
.GetMask()->GetBitmap(), mask_gc
, mask_image
, 0, 0, 0, 0, width
, height
);
1383 gdk_image_destroy( mask_image
);
1384 gdk_gc_unref( mask_gc
);
1391 wxBitmap
wxImage::ConvertToBitmap() const
1395 wxCHECK_MSG( Ok(), bitmap
, wxT("invalid image") );
1397 int width
= GetWidth();
1398 int height
= GetHeight();
1400 bitmap
.SetHeight( height
);
1401 bitmap
.SetWidth( width
);
1403 bitmap
.SetPixmap( gdk_pixmap_new( (GdkWindow
*)&gdk_root_parent
, width
, height
, -1 ) );
1407 GdkVisual
*visual
= gdk_window_get_visual( bitmap
.GetPixmap() );
1408 if (visual
== NULL
) visual
= gdk_visual_get_system();
1409 int bpp
= visual
->depth
;
1411 bitmap
.SetDepth( bpp
);
1413 if ((bpp
== 16) && (visual
->red_mask
!= 0xf800)) bpp
= 15;
1414 if (bpp
< 8) bpp
= 8;
1416 #if (GTK_MINOR_VERSION > 0)
1418 if (!HasMask() && (bpp
> 8))
1420 static bool s_hasInitialized
= FALSE
;
1422 if (!s_hasInitialized
)
1425 s_hasInitialized
= TRUE
;
1428 GdkGC
*gc
= gdk_gc_new( bitmap
.GetPixmap() );
1430 gdk_draw_rgb_image( bitmap
.GetPixmap(),
1434 GDK_RGB_DITHER_NONE
,
1445 // Create picture image
1447 GdkImage
*data_image
=
1448 gdk_image_new( GDK_IMAGE_FASTEST
, gdk_visual_get_system(), width
, height
);
1450 // Create mask image
1452 GdkImage
*mask_image
= (GdkImage
*) NULL
;
1456 unsigned char *mask_data
= (unsigned char*)malloc( ((width
>> 3)+8) * height
);
1458 mask_image
= gdk_image_new_bitmap( gdk_visual_get_system(), mask_data
, width
, height
);
1460 wxMask
*mask
= new wxMask();
1461 mask
->m_bitmap
= gdk_pixmap_new( (GdkWindow
*)&gdk_root_parent
, width
, height
, 1 );
1463 bitmap
.SetMask( mask
);
1468 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
1469 byte_order b_o
= RGB
;
1473 GdkVisual
*visual
= gdk_visual_get_system();
1474 if ((visual
->red_mask
> visual
->green_mask
) && (visual
->green_mask
> visual
->blue_mask
)) b_o
= RGB
;
1475 else if ((visual
->red_mask
> visual
->blue_mask
) && (visual
->blue_mask
> visual
->green_mask
)) b_o
= RGB
;
1476 else if ((visual
->blue_mask
> visual
->red_mask
) && (visual
->red_mask
> visual
->green_mask
)) b_o
= BRG
;
1477 else if ((visual
->blue_mask
> visual
->green_mask
) && (visual
->green_mask
> visual
->red_mask
)) b_o
= BGR
;
1478 else if ((visual
->green_mask
> visual
->red_mask
) && (visual
->red_mask
> visual
->blue_mask
)) b_o
= GRB
;
1479 else if ((visual
->green_mask
> visual
->blue_mask
) && (visual
->blue_mask
> visual
->red_mask
)) b_o
= GBR
;
1482 int r_mask
= GetMaskRed();
1483 int g_mask
= GetMaskGreen();
1484 int b_mask
= GetMaskBlue();
1486 unsigned char* data
= GetData();
1489 for (int y
= 0; y
< height
; y
++)
1491 for (int x
= 0; x
< width
; x
++)
1493 int r
= data
[index
];
1495 int g
= data
[index
];
1497 int b
= data
[index
];
1502 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
1503 gdk_image_put_pixel( mask_image
, x
, y
, 1 );
1505 gdk_image_put_pixel( mask_image
, x
, y
, 0 );
1513 if (wxTheApp
->m_colorCube
)
1515 pixel
= wxTheApp
->m_colorCube
[ ((r
& 0xf8) << 7) + ((g
& 0xf8) << 2) + ((b
& 0xf8) >> 3) ];
1519 GdkColormap
*cmap
= gtk_widget_get_default_colormap();
1520 GdkColor
*colors
= cmap
->colors
;
1521 int max
= 3 * (65536);
1523 for (int i
= 0; i
< cmap
->size
; i
++)
1525 int rdiff
= (r
<< 8) - colors
[i
].red
;
1526 int gdiff
= (g
<< 8) - colors
[i
].green
;
1527 int bdiff
= (b
<< 8) - colors
[i
].blue
;
1528 int sum
= ABS (rdiff
) + ABS (gdiff
) + ABS (bdiff
);
1529 if (sum
< max
) { pixel
= i
; max
= sum
; }
1533 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1539 guint32 pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
1540 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1545 guint32 pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
1546 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1555 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
1556 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
1557 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
1558 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
1559 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
1560 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
1562 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1571 GdkGC
*data_gc
= gdk_gc_new( bitmap
.GetPixmap() );
1573 gdk_draw_image( bitmap
.GetPixmap(), data_gc
, data_image
, 0, 0, 0, 0, width
, height
);
1575 gdk_image_destroy( data_image
);
1576 gdk_gc_unref( data_gc
);
1582 GdkGC
*mask_gc
= gdk_gc_new( bitmap
.GetMask()->GetBitmap() );
1584 gdk_draw_image( bitmap
.GetMask()->GetBitmap(), mask_gc
, mask_image
, 0, 0, 0, 0, width
, height
);
1586 gdk_image_destroy( mask_image
);
1587 gdk_gc_unref( mask_gc
);
1593 wxImage::wxImage( const wxBitmap
&bitmap
)
1595 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
1597 GdkImage
*gdk_image
= (GdkImage
*) NULL
;
1598 if (bitmap
.GetPixmap())
1600 gdk_image
= gdk_image_get( bitmap
.GetPixmap(),
1602 bitmap
.GetWidth(), bitmap
.GetHeight() );
1604 if (bitmap
.GetBitmap())
1606 gdk_image
= gdk_image_get( bitmap
.GetBitmap(),
1608 bitmap
.GetWidth(), bitmap
.GetHeight() );
1611 wxFAIL_MSG( wxT("Ill-formed bitmap") );
1614 wxCHECK_RET( gdk_image
, wxT("couldn't create image") );
1616 Create( bitmap
.GetWidth(), bitmap
.GetHeight() );
1617 char unsigned *data
= GetData();
1621 gdk_image_destroy( gdk_image
);
1622 wxFAIL_MSG( wxT("couldn't create image") );
1626 GdkImage
*gdk_image_mask
= (GdkImage
*) NULL
;
1627 if (bitmap
.GetMask())
1629 gdk_image_mask
= gdk_image_get( bitmap
.GetMask()->GetBitmap(),
1631 bitmap
.GetWidth(), bitmap
.GetHeight() );
1633 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1637 int red_shift_right
= 0;
1638 int green_shift_right
= 0;
1639 int blue_shift_right
= 0;
1640 int red_shift_left
= 0;
1641 int green_shift_left
= 0;
1642 int blue_shift_left
= 0;
1643 bool use_shift
= FALSE
;
1645 if (bitmap
.GetPixmap())
1647 GdkVisual
*visual
= gdk_window_get_visual( bitmap
.GetPixmap() );
1649 if (visual
== NULL
) visual
= gdk_window_get_visual( (GdkWindow
*) &gdk_root_parent
);
1650 bpp
= visual
->depth
;
1651 if (bpp
== 16) bpp
= visual
->red_prec
+ visual
->green_prec
+ visual
->blue_prec
;
1652 red_shift_right
= visual
->red_shift
;
1653 red_shift_left
= 8-visual
->red_prec
;
1654 green_shift_right
= visual
->green_shift
;
1655 green_shift_left
= 8-visual
->green_prec
;
1656 blue_shift_right
= visual
->blue_shift
;
1657 blue_shift_left
= 8-visual
->blue_prec
;
1659 use_shift
= (visual
->type
== GDK_VISUAL_TRUE_COLOR
) || (visual
->type
== GDK_VISUAL_DIRECT_COLOR
);
1661 if (bitmap
.GetBitmap())
1667 GdkColormap
*cmap
= gtk_widget_get_default_colormap();
1670 for (int j
= 0; j
< bitmap
.GetHeight(); j
++)
1672 for (int i
= 0; i
< bitmap
.GetWidth(); i
++)
1674 wxUint32 pixel
= gdk_image_get_pixel( gdk_image
, i
, j
);
1692 data
[pos
] = (pixel
>> red_shift_right
) << red_shift_left
;
1693 data
[pos
+1] = (pixel
>> green_shift_right
) << green_shift_left
;
1694 data
[pos
+2] = (pixel
>> blue_shift_right
) << blue_shift_left
;
1696 else if (cmap
->colors
)
1698 data
[pos
] = cmap
->colors
[pixel
].red
>> 8;
1699 data
[pos
+1] = cmap
->colors
[pixel
].green
>> 8;
1700 data
[pos
+2] = cmap
->colors
[pixel
].blue
>> 8;
1704 wxFAIL_MSG( wxT("Image conversion failed. Unknown visual type.") );
1709 int mask_pixel
= gdk_image_get_pixel( gdk_image_mask
, i
, j
);
1710 if (mask_pixel
== 0)
1722 gdk_image_destroy( gdk_image
);
1723 if (gdk_image_mask
) gdk_image_destroy( gdk_image_mask
);
1728 //-----------------------------------------------------------------------------
1729 // Motif conversion routines
1730 //-----------------------------------------------------------------------------
1734 #pragma message disable nosimpint
1738 #pragma message enable nosimpint
1740 #include "wx/utils.h"
1745 Date: Wed, 05 Jan 2000 11:45:40 +0100
1746 From: Frits Boel <boel@niob.knaw.nl>
1747 To: julian.smart@ukonline.co.uk
1748 Subject: Patch for Motif ConvertToBitmap
1752 I've been working on a wxWin application for image processing. From the
1753 beginning, I was surprised by the (lack of) speed of ConvertToBitmap,
1754 till I looked in the source code of image.cpp. I saw that converting a
1755 wxImage to a bitmap with 8-bit pixels is done with comparing every pixel
1756 to the 256 colors of the palet. A very time-consuming piece of code!
1758 Because I wanted a faster application, I've made a 'patch' for this. In
1759 short: every pixel of the image is compared to a sorted list with
1760 colors. If the color is found in the list, the palette entry is
1761 returned; if the color is not found, the color palette is searched and
1762 then the palette entry is returned and the color added to the sorted
1765 Maybe there is another method for this, namely changing the palette
1766 itself (if the colors are known, as is the case with tiffs with a
1767 colormap). I did not look at this, maybe someone else did?
1769 The code of the patch is attached, have a look on it, and maybe you will
1770 ship it with the next release of wxMotif?
1775 Software engineer at Hubrecht Laboratory, The Netherlands.
1782 wxSearchColor( void );
1783 wxSearchColor( int size
, XColor
*colors
);
1784 ~wxSearchColor( void );
1786 int SearchColor( int r
, int g
, int b
);
1788 int AddColor( unsigned int value
, int pos
);
1792 unsigned int *color
;
1799 wxSearchColor::wxSearchColor( void )
1802 this->colors
= (XColor
*) NULL
;
1803 this->color
= (unsigned int *) NULL
;
1804 this->entry
= (int*) NULL
;
1810 wxSearchColor::wxSearchColor( int size
, XColor
*colors
)
1814 this->colors
= colors
;
1815 this->color
= new unsigned int[size
];
1816 this->entry
= new int [size
];
1818 for (i
= 0; i
< this->size
; i
++ ) {
1819 this->entry
[i
] = -1;
1822 this->bottom
= this->top
= ( size
>> 1 );
1825 wxSearchColor::~wxSearchColor( void )
1827 if ( this->color
) delete this->color
;
1828 if ( this->entry
) delete this->entry
;
1831 int wxSearchColor::SearchColor( int r
, int g
, int b
)
1833 unsigned int value
= ( ( ( r
* 256 ) + g
) * 256 ) + b
;
1834 int begin
= this->bottom
;
1835 int end
= this->top
;
1838 while ( begin
<= end
) {
1840 middle
= ( begin
+ end
) >> 1;
1842 if ( value
== this->color
[middle
] ) {
1843 return( this->entry
[middle
] );
1844 } else if ( value
< this->color
[middle
] ) {
1852 return AddColor( value
, middle
);
1855 int wxSearchColor::AddColor( unsigned int value
, int pos
)
1859 int max
= 3 * (65536);
1860 for ( i
= 0; i
< 256; i
++ ) {
1861 int rdiff
= ((value
>> 8) & 0xFF00 ) - colors
[i
].red
;
1862 int gdiff
= ((value
) & 0xFF00 ) - colors
[i
].green
;
1863 int bdiff
= ((value
<< 8) & 0xFF00 ) - colors
[i
].blue
;
1864 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
1865 if (sum
< max
) { pixel
= i
; max
= sum
; }
1868 if ( this->entry
[pos
] < 0 ) {
1869 this->color
[pos
] = value
;
1870 this->entry
[pos
] = pixel
;
1871 } else if ( value
< this->color
[pos
] ) {
1873 if ( this->bottom
> 0 ) {
1874 for ( i
= this->bottom
; i
< pos
; i
++ ) {
1875 this->color
[i
-1] = this->color
[i
];
1876 this->entry
[i
-1] = this->entry
[i
];
1879 this->color
[pos
-1] = value
;
1880 this->entry
[pos
-1] = pixel
;
1881 } else if ( this->top
< this->size
-1 ) {
1882 for ( i
= this->top
; i
>= pos
; i
-- ) {
1883 this->color
[i
+1] = this->color
[i
];
1884 this->entry
[i
+1] = this->entry
[i
];
1887 this->color
[pos
] = value
;
1888 this->entry
[pos
] = pixel
;
1893 if ( this->top
< this->size
-1 ) {
1894 for ( i
= this->top
; i
> pos
; i
-- ) {
1895 this->color
[i
+1] = this->color
[i
];
1896 this->entry
[i
+1] = this->entry
[i
];
1899 this->color
[pos
+1] = value
;
1900 this->entry
[pos
+1] = pixel
;
1901 } else if ( this->bottom
> 0 ) {
1902 for ( i
= this->bottom
; i
< pos
; i
++ ) {
1903 this->color
[i
-1] = this->color
[i
];
1904 this->entry
[i
-1] = this->entry
[i
];
1907 this->color
[pos
] = value
;
1908 this->entry
[pos
] = pixel
;
1916 wxBitmap
wxImage::ConvertToBitmap() const
1920 wxCHECK_MSG( Ok(), bitmap
, wxT("invalid image") );
1922 int width
= GetWidth();
1923 int height
= GetHeight();
1925 bitmap
.SetHeight( height
);
1926 bitmap
.SetWidth( width
);
1928 Display
*dpy
= (Display
*) wxGetDisplay();
1929 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1930 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1934 XImage
*data_image
= XCreateImage( dpy
, vis
, bpp
, ZPixmap
, 0, 0, width
, height
, 32, 0 );
1935 data_image
->data
= (char*) malloc( data_image
->bytes_per_line
* data_image
->height
);
1937 bitmap
.Create( width
, height
, bpp
);
1942 GdkImage *mask_image = (GdkImage*) NULL;
1946 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1948 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1950 wxMask *mask = new wxMask();
1951 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1953 bitmap.SetMask( mask );
1957 // Retrieve depth info
1959 XVisualInfo vinfo_template
;
1962 vinfo_template
.visual
= vis
;
1963 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1964 vinfo_template
.depth
= bpp
;
1967 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
1969 wxCHECK_MSG( vi
, wxNullBitmap
, wxT("no visual") );
1973 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1974 if (bpp
< 8) bpp
= 8;
1978 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
1979 byte_order b_o
= RGB
;
1983 if ((vi
->red_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->blue_mask
)) b_o
= RGB
;
1984 else if ((vi
->red_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->green_mask
)) b_o
= RGB
;
1985 else if ((vi
->blue_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->green_mask
)) b_o
= BRG
;
1986 else if ((vi
->blue_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->red_mask
)) b_o
= BGR
;
1987 else if ((vi
->green_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->blue_mask
)) b_o
= GRB
;
1988 else if ((vi
->green_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->red_mask
)) b_o
= GBR
;
1992 int r_mask = GetMaskRed();
1993 int g_mask = GetMaskGreen();
1994 int b_mask = GetMaskBlue();
2000 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap( dpy
);
2002 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
2003 XQueryColors( dpy
, cmap
, colors
, 256 );
2006 wxSearchColor
scolor( 256, colors
);
2007 unsigned char* data
= GetData();
2010 for (int y
= 0; y
< height
; y
++)
2012 for (int x
= 0; x
< width
; x
++)
2014 int r
= data
[index
];
2016 int g
= data
[index
];
2018 int b
= data
[index
];
2024 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
2025 gdk_image_put_pixel( mask_image, x, y, 1 );
2027 gdk_image_put_pixel( mask_image, x, y, 0 );
2035 #if 0 // Old, slower code
2038 if (wxTheApp->m_colorCube)
2040 pixel = wxTheApp->m_colorCube
2041 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
2046 int max
= 3 * (65536);
2047 for (int i
= 0; i
< 256; i
++)
2049 int rdiff
= (r
<< 8) - colors
[i
].red
;
2050 int gdiff
= (g
<< 8) - colors
[i
].green
;
2051 int bdiff
= (b
<< 8) - colors
[i
].blue
;
2052 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
2053 if (sum
< max
) { pixel
= i
; max
= sum
; }
2060 // And this is all to get the 'right' color...
2061 int pixel
= scolor
.SearchColor( r
, g
, b
);
2062 XPutPixel( data_image
, x
, y
, pixel
);
2067 int pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
2068 XPutPixel( data_image
, x
, y
, pixel
);
2073 int pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
2074 XPutPixel( data_image
, x
, y
, pixel
);
2083 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
2084 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
2085 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
2086 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
2087 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
2088 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
2090 XPutPixel( data_image
, x
, y
, pixel
);
2100 gcvalues
.foreground
= BlackPixel( dpy
, DefaultScreen( dpy
) );
2101 GC gc
= XCreateGC( dpy
, RootWindow ( dpy
, DefaultScreen(dpy
) ), GCForeground
, &gcvalues
);
2102 XPutImage( dpy
, (Drawable
)bitmap
.GetPixmap(), gc
, data_image
, 0, 0, 0, 0, width
, height
);
2104 XDestroyImage( data_image
);
2112 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
2114 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
2116 gdk_image_destroy( mask_image );
2117 gdk_gc_unref( mask_gc );
2124 wxImage::wxImage( const wxBitmap
&bitmap
)
2126 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
2128 Display
*dpy
= (Display
*) wxGetDisplay();
2129 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
2130 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
2132 XImage
*ximage
= XGetImage( dpy
,
2133 (Drawable
)bitmap
.GetPixmap(),
2135 bitmap
.GetWidth(), bitmap
.GetHeight(),
2136 AllPlanes
, ZPixmap
);
2138 wxCHECK_RET( ximage
, wxT("couldn't create image") );
2140 Create( bitmap
.GetWidth(), bitmap
.GetHeight() );
2141 char unsigned *data
= GetData();
2145 XDestroyImage( ximage
);
2146 wxFAIL_MSG( wxT("couldn't create image") );
2151 GdkImage *gdk_image_mask = (GdkImage*) NULL;
2152 if (bitmap.GetMask())
2154 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
2156 bitmap.GetWidth(), bitmap.GetHeight() );
2158 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
2162 // Retrieve depth info
2164 XVisualInfo vinfo_template
;
2167 vinfo_template
.visual
= vis
;
2168 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
2169 vinfo_template
.depth
= bpp
;
2172 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
2174 wxCHECK_RET( vi
, wxT("no visual") );
2176 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
2183 Colormap cmap
= (Colormap
)wxTheApp
->GetMainColormap( dpy
);
2185 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
2186 XQueryColors( dpy
, cmap
, colors
, 256 );
2190 for (int j
= 0; j
< bitmap
.GetHeight(); j
++)
2192 for (int i
= 0; i
< bitmap
.GetWidth(); i
++)
2194 int pixel
= XGetPixel( ximage
, i
, j
);
2197 data
[pos
] = colors
[pixel
].red
>> 8;
2198 data
[pos
+1] = colors
[pixel
].green
>> 8;
2199 data
[pos
+2] = colors
[pixel
].blue
>> 8;
2200 } else if (bpp
== 15)
2202 data
[pos
] = (pixel
>> 7) & 0xf8;
2203 data
[pos
+1] = (pixel
>> 2) & 0xf8;
2204 data
[pos
+2] = (pixel
<< 3) & 0xf8;
2205 } else if (bpp
== 16)
2207 data
[pos
] = (pixel
>> 8) & 0xf8;
2208 data
[pos
+1] = (pixel
>> 3) & 0xfc;
2209 data
[pos
+2] = (pixel
<< 3) & 0xf8;
2212 data
[pos
] = (pixel
>> 16) & 0xff;
2213 data
[pos
+1] = (pixel
>> 8) & 0xff;
2214 data
[pos
+2] = pixel
& 0xff;
2220 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
2221 if (mask_pixel == 0)
2234 XDestroyImage( ximage
);
2236 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
2242 // OS/2 Presentation manager conversion routings
2244 wxBitmap
wxImage::ConvertToBitmap() const
2247 return wxNullBitmap
;
2248 wxBitmap bitmap
; // remove
2251 int sizeLimit = 1024*768*3;
2253 // width and height of the device-dependent bitmap
2254 int width = GetWidth();
2255 int bmpHeight = GetHeight();
2257 // calc the number of bytes per scanline and padding
2258 int bytePerLine = width*3;
2259 int sizeDWORD = sizeof( DWORD );
2260 int lineBoundary = bytePerLine % sizeDWORD;
2262 if( lineBoundary > 0 )
2264 padding = sizeDWORD - lineBoundary;
2265 bytePerLine += padding;
2267 // calc the number of DIBs and heights of DIBs
2270 int height = sizeLimit/bytePerLine;
2271 if( height >= bmpHeight )
2275 numDIB = bmpHeight / height;
2276 hRemain = bmpHeight % height;
2277 if( hRemain >0 ) numDIB++;
2280 // set bitmap parameters
2282 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
2283 bitmap.SetWidth( width );
2284 bitmap.SetHeight( bmpHeight );
2285 bitmap.SetDepth( wxDisplayDepth() );
2287 // create a DIB header
2288 int headersize = sizeof(BITMAPINFOHEADER);
2289 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
2290 wxCHECK_MSG( lpDIBh, bitmap, wxT("could not allocate memory for DIB header") );
2291 // Fill in the DIB header
2292 lpDIBh->bmiHeader.biSize = headersize;
2293 lpDIBh->bmiHeader.biWidth = (DWORD)width;
2294 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2295 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2296 // the general formula for biSizeImage:
2297 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
2298 lpDIBh->bmiHeader.biPlanes = 1;
2299 lpDIBh->bmiHeader.biBitCount = 24;
2300 lpDIBh->bmiHeader.biCompression = BI_RGB;
2301 lpDIBh->bmiHeader.biClrUsed = 0;
2302 // These seem not really needed for our purpose here.
2303 lpDIBh->bmiHeader.biClrImportant = 0;
2304 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2305 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2306 // memory for DIB data
2307 unsigned char *lpBits;
2308 lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
2311 wxFAIL_MSG( wxT("could not allocate memory for DIB") );
2316 // create and set the device-dependent bitmap
2317 HDC hdc = ::GetDC(NULL);
2318 HDC memdc = ::CreateCompatibleDC( hdc );
2320 hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
2321 ::SelectObject( memdc, hbitmap);
2323 // copy image data into DIB data and then into DDB (in a loop)
2324 unsigned char *data = GetData();
2327 unsigned char *ptdata = data;
2328 unsigned char *ptbits;
2330 for( n=0; n<numDIB; n++ )
2332 if( numDIB > 1 && n == numDIB-1 && hRemain > 0 )
2334 // redefine height and size of the (possibly) last smaller DIB
2335 // memory is not reallocated
2337 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2338 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2342 for( j=0; j<height; j++ )
2344 for( i=0; i<width; i++ )
2346 *(ptbits++) = *(ptdata+2);
2347 *(ptbits++) = *(ptdata+1);
2348 *(ptbits++) = *(ptdata );
2351 for( i=0; i< padding; i++ ) *(ptbits++) = 0;
2353 ::StretchDIBits( memdc, 0, origin, width, height,\
2354 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2356 // if numDIB = 1, lines below can also be used
2357 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
2358 // The above line is equivalent to the following two lines.
2359 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2360 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
2361 // or the following lines
2362 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2363 // HDC memdc = ::CreateCompatibleDC( hdc );
2364 // ::SelectObject( memdc, hbitmap);
2365 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
2366 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
2367 // ::SelectObject( memdc, 0 );
2368 // ::DeleteDC( memdc );
2370 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
2372 // similarly, created an mono-bitmap for the possible mask
2375 hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL );
2376 ::SelectObject( memdc, hbitmap);
2377 if( numDIB == 1 ) height = bmpHeight;
2378 else height = sizeLimit/bytePerLine;
2379 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2380 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2382 unsigned char r = GetMaskRed();
2383 unsigned char g = GetMaskGreen();
2384 unsigned char b = GetMaskBlue();
2385 unsigned char zero = 0, one = 255;
2387 for( n=0; n<numDIB; n++ )
2389 if( numDIB > 1 && n == numDIB - 1 && hRemain > 0 )
2391 // redefine height and size of the (possibly) last smaller DIB
2392 // memory is not reallocated
2394 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2395 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2398 for( int j=0; j<height; j++ )
2400 for(i=0; i<width; i++ )
2402 if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
2415 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
2417 ::StretchDIBits( memdc, 0, origin, width, height,\
2418 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2421 // create a wxMask object
2422 wxMask *mask = new wxMask();
2423 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
2424 bitmap.SetMask( mask );
2427 // free allocated resources
2428 ::SelectObject( memdc, 0 );
2429 ::DeleteDC( memdc );
2430 ::ReleaseDC(NULL, hdc);
2434 // check the wxBitmap object
2435 if( bitmap.GetHBITMAP() )
2436 bitmap.SetOk( TRUE );
2438 bitmap.SetOk( FALSE );
2443 wxImage::wxImage( const wxBitmap
&bitmap
)
2448 wxFAIL_MSG( wxT("invalid bitmap") );
2452 // create an wxImage object
2453 int width
= bitmap
.GetWidth();
2454 int height
= bitmap
.GetHeight();
2455 Create( width
, height
);
2456 unsigned char *data
= GetData();
2459 wxFAIL_MSG( wxT("could not allocate data for image") );
2463 // calc the number of bytes per scanline and padding in the DIB
2464 int bytePerLine
= width
*3;
2465 int sizeDWORD
= sizeof( DWORD
);
2466 int lineBoundary
= bytePerLine
% sizeDWORD
;
2468 if( lineBoundary
> 0 )
2470 padding
= sizeDWORD
- lineBoundary
;
2471 bytePerLine
+= padding
;
2475 // create a DIB header
2476 int headersize = sizeof(BITMAPINFOHEADER);
2477 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
2480 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
2484 // Fill in the DIB header
2485 lpDIBh->bmiHeader.biSize = headersize;
2486 lpDIBh->bmiHeader.biWidth = width;
2487 lpDIBh->bmiHeader.biHeight = -height;
2488 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
2489 lpDIBh->bmiHeader.biPlanes = 1;
2490 lpDIBh->bmiHeader.biBitCount = 24;
2491 lpDIBh->bmiHeader.biCompression = BI_RGB;
2492 lpDIBh->bmiHeader.biClrUsed = 0;
2493 // These seem not really needed for our purpose here.
2494 lpDIBh->bmiHeader.biClrImportant = 0;
2495 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2496 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2497 // memory for DIB data
2498 unsigned char *lpBits;
2499 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
2502 wxFAIL_MSG( wxT("could not allocate data for DIB") );
2508 // copy data from the device-dependent bitmap to the DIB
2509 HDC hdc = ::GetDC(NULL);
2511 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
2512 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2514 // copy DIB data into the wxImage object
2516 unsigned char *ptdata = data;
2517 unsigned char *ptbits = lpBits;
2518 for( i=0; i<height; i++ )
2520 for( j=0; j<width; j++ )
2522 *(ptdata++) = *(ptbits+2);
2523 *(ptdata++) = *(ptbits+1);
2524 *(ptdata++) = *(ptbits );
2530 // similarly, set data according to the possible mask bitmap
2531 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
2533 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
2534 // memory DC created, color set, data copied, and memory DC deleted
2535 HDC memdc = ::CreateCompatibleDC( hdc );
2536 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
2537 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
2538 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2539 ::DeleteDC( memdc );
2540 // background color set to RGB(16,16,16) in consistent with wxGTK
2541 unsigned char r=16, g=16, b=16;
2544 for( i=0; i<height; i++ )
2546 for( j=0; j<width; j++ )
2560 SetMaskColour( r, g, b );
2567 // free allocated resources
2568 ::ReleaseDC(NULL, hdc);
2576 // A module to allow wxImage initialization/cleanup
2577 // without calling these functions from app.cpp or from
2578 // the user's application.
2580 class wxImageModule
: public wxModule
2582 DECLARE_DYNAMIC_CLASS(wxImageModule
)
2585 bool OnInit() { wxImage::InitStandardHandlers(); return TRUE
; };
2586 void OnExit() { wxImage::CleanUpHandlers(); };
2589 IMPLEMENT_DYNAMIC_CLASS(wxImageModule
, wxModule
)
2592 //-----------------------------------------------------------------------------
2595 // Counts and returns the number of different colours. Optionally stops
2596 // when it exceeds 'stopafter' different colours. This is useful, for
2597 // example, to see if the image can be saved as 8-bit (256 colour or
2598 // less, in this case it would be invoked as CountColours(256)). Default
2599 // value for stopafter is -1 (don't care).
2601 unsigned long wxImage::CountColours( unsigned long stopafter
)
2606 unsigned char r
, g
, b
, *p
;
2607 unsigned long size
, nentries
, key
;
2610 size
= GetWidth() * GetHeight();
2613 for (unsigned long j
= 0; (j
< size
) && (nentries
<= stopafter
) ; j
++)
2618 key
= (r
<< 16) | (g
<< 8) | b
;
2620 hnode
= (wxHNode
*) h
.Get(key
);
2624 h
.Put(key
, (wxObject
*)(new wxHNode
));
2629 // delete all HNodes
2631 while ((node
= h
.Next()) != NULL
)
2632 delete (wxHNode
*)node
->GetData();
2639 // Computes the histogram of the image and fills a hash table, indexed
2640 // with integer keys built as 0xRRGGBB, containing wxHNode objects. Each
2641 // wxHNode contains an 'index' (useful to build a palette with the image
2642 // colours) and a 'value', which is the number of pixels in the image with
2645 unsigned long wxImage::ComputeHistogram( wxHashTable
&h
)
2647 unsigned char r
, g
, b
, *p
;
2648 unsigned long size
, nentries
, key
;
2652 size
= GetWidth() * GetHeight();
2655 for (unsigned long j
= 0; j
< size
; j
++)
2660 key
= (r
<< 16) | (g
<< 8) | b
;
2662 hnode
= (wxHNode
*) h
.Get(key
);
2668 hnode
= new wxHNode();
2669 hnode
->index
= nentries
++;
2672 h
.Put(key
, (wxObject
*)hnode
);