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"
1673 wxBitmap
wxImage::ConvertToBitmap() const
1677 wxCHECK_MSG( Ok(), bitmap
, wxT("invalid image") );
1679 int width
= GetWidth();
1680 int height
= GetHeight();
1682 bitmap
.SetHeight( height
);
1683 bitmap
.SetWidth( width
);
1685 Display
*dpy
= (Display
*) wxGetDisplay();
1686 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1687 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1691 XImage
*data_image
= XCreateImage( dpy
, vis
, bpp
, ZPixmap
, 0, 0, width
, height
, 32, 0 );
1692 data_image
->data
= (char*) malloc( data_image
->bytes_per_line
* data_image
->height
);
1694 bitmap
.Create( width
, height
, bpp
);
1699 GdkImage *mask_image = (GdkImage*) NULL;
1703 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1705 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1707 wxMask *mask = new wxMask();
1708 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1710 bitmap.SetMask( mask );
1714 // Retrieve depth info
1716 XVisualInfo vinfo_template
;
1719 vinfo_template
.visual
= vis
;
1720 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1721 vinfo_template
.depth
= bpp
;
1724 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
1726 wxCHECK_MSG( vi
, wxNullBitmap
, wxT("no visual") );
1730 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1731 if (bpp
< 8) bpp
= 8;
1735 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
1736 byte_order b_o
= RGB
;
1740 if ((vi
->red_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->blue_mask
)) b_o
= RGB
;
1741 else if ((vi
->red_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->green_mask
)) b_o
= RGB
;
1742 else if ((vi
->blue_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->green_mask
)) b_o
= BRG
;
1743 else if ((vi
->blue_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->red_mask
)) b_o
= BGR
;
1744 else if ((vi
->green_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->blue_mask
)) b_o
= GRB
;
1745 else if ((vi
->green_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->red_mask
)) b_o
= GBR
;
1749 int r_mask = GetMaskRed();
1750 int g_mask = GetMaskGreen();
1751 int b_mask = GetMaskBlue();
1757 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap( dpy
);
1759 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
1760 XQueryColors( dpy
, cmap
, colors
, 256 );
1763 unsigned char* data
= GetData();
1766 for (int y
= 0; y
< height
; y
++)
1768 for (int x
= 0; x
< width
; x
++)
1770 int r
= data
[index
];
1772 int g
= data
[index
];
1774 int b
= data
[index
];
1780 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1781 gdk_image_put_pixel( mask_image, x, y, 1 );
1783 gdk_image_put_pixel( mask_image, x, y, 0 );
1793 if (wxTheApp->m_colorCube)
1795 pixel = wxTheApp->m_colorCube
1796 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1801 int max
= 3 * (65536);
1802 for (int i
= 0; i
< 256; i
++)
1804 int rdiff
= (r
<< 8) - colors
[i
].red
;
1805 int gdiff
= (g
<< 8) - colors
[i
].green
;
1806 int bdiff
= (b
<< 8) - colors
[i
].blue
;
1807 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
1808 if (sum
< max
) { pixel
= i
; max
= sum
; }
1813 XPutPixel( data_image
, x
, y
, pixel
);
1818 int pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
1819 XPutPixel( data_image
, x
, y
, pixel
);
1824 int pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
1825 XPutPixel( data_image
, x
, y
, pixel
);
1834 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
1835 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
1836 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
1837 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
1838 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
1839 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
1841 XPutPixel( data_image
, x
, y
, pixel
);
1851 gcvalues
.foreground
= BlackPixel( dpy
, DefaultScreen( dpy
) );
1852 GC gc
= XCreateGC( dpy
, RootWindow ( dpy
, DefaultScreen(dpy
) ), GCForeground
, &gcvalues
);
1853 XPutImage( dpy
, (Drawable
)bitmap
.GetPixmap(), gc
, data_image
, 0, 0, 0, 0, width
, height
);
1855 XDestroyImage( data_image
);
1863 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
1865 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
1867 gdk_image_destroy( mask_image );
1868 gdk_gc_unref( mask_gc );
1875 wxImage::wxImage( const wxBitmap
&bitmap
)
1877 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
1879 Display
*dpy
= (Display
*) wxGetDisplay();
1880 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1881 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1883 XImage
*ximage
= XGetImage( dpy
,
1884 (Drawable
)bitmap
.GetPixmap(),
1886 bitmap
.GetWidth(), bitmap
.GetHeight(),
1887 AllPlanes
, ZPixmap
);
1889 wxCHECK_RET( ximage
, wxT("couldn't create image") );
1891 Create( bitmap
.GetWidth(), bitmap
.GetHeight() );
1892 char unsigned *data
= GetData();
1896 XDestroyImage( ximage
);
1897 wxFAIL_MSG( wxT("couldn't create image") );
1902 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1903 if (bitmap.GetMask())
1905 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1907 bitmap.GetWidth(), bitmap.GetHeight() );
1909 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1913 // Retrieve depth info
1915 XVisualInfo vinfo_template
;
1918 vinfo_template
.visual
= vis
;
1919 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1920 vinfo_template
.depth
= bpp
;
1923 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
1925 wxCHECK_RET( vi
, wxT("no visual") );
1927 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1934 Colormap cmap
= (Colormap
)wxTheApp
->GetMainColormap( dpy
);
1936 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
1937 XQueryColors( dpy
, cmap
, colors
, 256 );
1941 for (int j
= 0; j
< bitmap
.GetHeight(); j
++)
1943 for (int i
= 0; i
< bitmap
.GetWidth(); i
++)
1945 int pixel
= XGetPixel( ximage
, i
, j
);
1948 data
[pos
] = colors
[pixel
].red
>> 8;
1949 data
[pos
+1] = colors
[pixel
].green
>> 8;
1950 data
[pos
+2] = colors
[pixel
].blue
>> 8;
1951 } else if (bpp
== 15)
1953 data
[pos
] = (pixel
>> 7) & 0xf8;
1954 data
[pos
+1] = (pixel
>> 2) & 0xf8;
1955 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1956 } else if (bpp
== 16)
1958 data
[pos
] = (pixel
>> 8) & 0xf8;
1959 data
[pos
+1] = (pixel
>> 3) & 0xfc;
1960 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1963 data
[pos
] = (pixel
>> 16) & 0xff;
1964 data
[pos
+1] = (pixel
>> 8) & 0xff;
1965 data
[pos
+2] = pixel
& 0xff;
1971 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1972 if (mask_pixel == 0)
1985 XDestroyImage( ximage
);
1987 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1993 // OS/2 Presentation manager conversion routings
1995 wxBitmap
wxImage::ConvertToBitmap() const
1998 return wxNullBitmap
;
1999 wxBitmap bitmap
; // remove
2002 int sizeLimit = 1024*768*3;
2004 // width and height of the device-dependent bitmap
2005 int width = GetWidth();
2006 int bmpHeight = GetHeight();
2008 // calc the number of bytes per scanline and padding
2009 int bytePerLine = width*3;
2010 int sizeDWORD = sizeof( DWORD );
2011 int lineBoundary = bytePerLine % sizeDWORD;
2013 if( lineBoundary > 0 )
2015 padding = sizeDWORD - lineBoundary;
2016 bytePerLine += padding;
2018 // calc the number of DIBs and heights of DIBs
2021 int height = sizeLimit/bytePerLine;
2022 if( height >= bmpHeight )
2026 numDIB = bmpHeight / height;
2027 hRemain = bmpHeight % height;
2028 if( hRemain >0 ) numDIB++;
2031 // set bitmap parameters
2033 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
2034 bitmap.SetWidth( width );
2035 bitmap.SetHeight( bmpHeight );
2036 bitmap.SetDepth( wxDisplayDepth() );
2038 // create a DIB header
2039 int headersize = sizeof(BITMAPINFOHEADER);
2040 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
2041 wxCHECK_MSG( lpDIBh, bitmap, wxT("could not allocate memory for DIB header") );
2042 // Fill in the DIB header
2043 lpDIBh->bmiHeader.biSize = headersize;
2044 lpDIBh->bmiHeader.biWidth = (DWORD)width;
2045 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2046 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2047 // the general formula for biSizeImage:
2048 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
2049 lpDIBh->bmiHeader.biPlanes = 1;
2050 lpDIBh->bmiHeader.biBitCount = 24;
2051 lpDIBh->bmiHeader.biCompression = BI_RGB;
2052 lpDIBh->bmiHeader.biClrUsed = 0;
2053 // These seem not really needed for our purpose here.
2054 lpDIBh->bmiHeader.biClrImportant = 0;
2055 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2056 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2057 // memory for DIB data
2058 unsigned char *lpBits;
2059 lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
2062 wxFAIL_MSG( wxT("could not allocate memory for DIB") );
2067 // create and set the device-dependent bitmap
2068 HDC hdc = ::GetDC(NULL);
2069 HDC memdc = ::CreateCompatibleDC( hdc );
2071 hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
2072 ::SelectObject( memdc, hbitmap);
2074 // copy image data into DIB data and then into DDB (in a loop)
2075 unsigned char *data = GetData();
2078 unsigned char *ptdata = data;
2079 unsigned char *ptbits;
2081 for( n=0; n<numDIB; n++ )
2083 if( numDIB > 1 && n == numDIB-1 && hRemain > 0 )
2085 // redefine height and size of the (possibly) last smaller DIB
2086 // memory is not reallocated
2088 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2089 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2093 for( j=0; j<height; j++ )
2095 for( i=0; i<width; i++ )
2097 *(ptbits++) = *(ptdata+2);
2098 *(ptbits++) = *(ptdata+1);
2099 *(ptbits++) = *(ptdata );
2102 for( i=0; i< padding; i++ ) *(ptbits++) = 0;
2104 ::StretchDIBits( memdc, 0, origin, width, height,\
2105 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2107 // if numDIB = 1, lines below can also be used
2108 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
2109 // The above line is equivalent to the following two lines.
2110 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2111 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
2112 // or the following lines
2113 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2114 // HDC memdc = ::CreateCompatibleDC( hdc );
2115 // ::SelectObject( memdc, hbitmap);
2116 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
2117 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
2118 // ::SelectObject( memdc, 0 );
2119 // ::DeleteDC( memdc );
2121 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
2123 // similarly, created an mono-bitmap for the possible mask
2126 hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL );
2127 ::SelectObject( memdc, hbitmap);
2128 if( numDIB == 1 ) height = bmpHeight;
2129 else height = sizeLimit/bytePerLine;
2130 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2131 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2133 unsigned char r = GetMaskRed();
2134 unsigned char g = GetMaskGreen();
2135 unsigned char b = GetMaskBlue();
2136 unsigned char zero = 0, one = 255;
2138 for( n=0; n<numDIB; n++ )
2140 if( numDIB > 1 && n == numDIB - 1 && hRemain > 0 )
2142 // redefine height and size of the (possibly) last smaller DIB
2143 // memory is not reallocated
2145 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2146 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2149 for( int j=0; j<height; j++ )
2151 for(i=0; i<width; i++ )
2153 if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
2166 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
2168 ::StretchDIBits( memdc, 0, origin, width, height,\
2169 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2172 // create a wxMask object
2173 wxMask *mask = new wxMask();
2174 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
2175 bitmap.SetMask( mask );
2178 // free allocated resources
2179 ::SelectObject( memdc, 0 );
2180 ::DeleteDC( memdc );
2181 ::ReleaseDC(NULL, hdc);
2185 // check the wxBitmap object
2186 if( bitmap.GetHBITMAP() )
2187 bitmap.SetOk( TRUE );
2189 bitmap.SetOk( FALSE );
2194 wxImage::wxImage( const wxBitmap
&bitmap
)
2199 wxFAIL_MSG( wxT("invalid bitmap") );
2203 // create an wxImage object
2204 int width
= bitmap
.GetWidth();
2205 int height
= bitmap
.GetHeight();
2206 Create( width
, height
);
2207 unsigned char *data
= GetData();
2210 wxFAIL_MSG( wxT("could not allocate data for image") );
2214 // calc the number of bytes per scanline and padding in the DIB
2215 int bytePerLine
= width
*3;
2216 int sizeDWORD
= sizeof( DWORD
);
2217 int lineBoundary
= bytePerLine
% sizeDWORD
;
2219 if( lineBoundary
> 0 )
2221 padding
= sizeDWORD
- lineBoundary
;
2222 bytePerLine
+= padding
;
2226 // create a DIB header
2227 int headersize = sizeof(BITMAPINFOHEADER);
2228 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
2231 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
2235 // Fill in the DIB header
2236 lpDIBh->bmiHeader.biSize = headersize;
2237 lpDIBh->bmiHeader.biWidth = width;
2238 lpDIBh->bmiHeader.biHeight = -height;
2239 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
2240 lpDIBh->bmiHeader.biPlanes = 1;
2241 lpDIBh->bmiHeader.biBitCount = 24;
2242 lpDIBh->bmiHeader.biCompression = BI_RGB;
2243 lpDIBh->bmiHeader.biClrUsed = 0;
2244 // These seem not really needed for our purpose here.
2245 lpDIBh->bmiHeader.biClrImportant = 0;
2246 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2247 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2248 // memory for DIB data
2249 unsigned char *lpBits;
2250 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
2253 wxFAIL_MSG( wxT("could not allocate data for DIB") );
2259 // copy data from the device-dependent bitmap to the DIB
2260 HDC hdc = ::GetDC(NULL);
2262 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
2263 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2265 // copy DIB data into the wxImage object
2267 unsigned char *ptdata = data;
2268 unsigned char *ptbits = lpBits;
2269 for( i=0; i<height; i++ )
2271 for( j=0; j<width; j++ )
2273 *(ptdata++) = *(ptbits+2);
2274 *(ptdata++) = *(ptbits+1);
2275 *(ptdata++) = *(ptbits );
2281 // similarly, set data according to the possible mask bitmap
2282 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
2284 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
2285 // memory DC created, color set, data copied, and memory DC deleted
2286 HDC memdc = ::CreateCompatibleDC( hdc );
2287 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
2288 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
2289 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2290 ::DeleteDC( memdc );
2291 // background color set to RGB(16,16,16) in consistent with wxGTK
2292 unsigned char r=16, g=16, b=16;
2295 for( i=0; i<height; i++ )
2297 for( j=0; j<width; j++ )
2311 SetMaskColour( r, g, b );
2318 // free allocated resources
2319 ::ReleaseDC(NULL, hdc);
2327 // A module to allow wxImage initialization/cleanup
2328 // without calling these functions from app.cpp or from
2329 // the user's application.
2331 class wxImageModule
: public wxModule
2333 DECLARE_DYNAMIC_CLASS(wxImageModule
)
2336 bool OnInit() { wxImage::InitStandardHandlers(); return TRUE
; };
2337 void OnExit() { wxImage::CleanUpHandlers(); };
2340 IMPLEMENT_DYNAMIC_CLASS(wxImageModule
, wxModule
)
2343 //-----------------------------------------------------------------------------
2346 // Counts and returns the number of different colours. Optionally stops
2347 // when it exceeds 'stopafter' different colours. This is useful, for
2348 // example, to see if the image can be saved as 8-bit (256 colour or
2349 // less, in this case it would be invoked as CountColours(256)). Default
2350 // value for stopafter is -1 (don't care).
2352 unsigned long wxImage::CountColours( unsigned long stopafter
)
2357 unsigned char r
, g
, b
, *p
;
2358 unsigned long size
, nentries
, key
;
2361 size
= GetWidth() * GetHeight();
2364 for (unsigned long j
= 0; (j
< size
) && (nentries
<= stopafter
) ; j
++)
2369 key
= (r
<< 16) | (g
<< 8) | b
;
2371 hnode
= (wxHNode
*) h
.Get(key
);
2375 h
.Put(key
, (wxObject
*)(new wxHNode
));
2380 // delete all HNodes
2382 while ((node
= h
.Next()) != NULL
)
2383 delete (wxHNode
*)node
->GetData();
2390 // Computes the histogram of the image and fills a hash table, indexed
2391 // with integer keys built as 0xRRGGBB, containing wxHNode objects. Each
2392 // wxHNode contains an 'index' (useful to build a palette with the image
2393 // colours) and a 'value', which is the number of pixels in the image with
2396 unsigned long wxImage::ComputeHistogram( wxHashTable
&h
)
2398 unsigned char r
, g
, b
, *p
;
2399 unsigned long size
, nentries
, key
;
2403 size
= GetWidth() * GetHeight();
2406 for (unsigned long j
= 0; j
< size
; j
++)
2411 key
= (r
<< 16) | (g
<< 8) | b
;
2413 hnode
= (wxHNode
*) h
.Get(key
);
2419 hnode
= new wxHNode();
2420 hnode
->index
= nentries
++;
2423 h
.Put(key
, (wxObject
*)hnode
);