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::SetRGB( int x
, int y
, unsigned char r
, unsigned char g
, unsigned char b
)
229 wxCHECK_RET( Ok(), wxT("invalid image") );
231 int w
= M_IMGDATA
->m_width
;
232 int h
= M_IMGDATA
->m_height
;
234 wxCHECK_RET( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), wxT("invalid image index") );
236 long pos
= (y
* w
+ x
) * 3;
238 M_IMGDATA
->m_data
[ pos
] = r
;
239 M_IMGDATA
->m_data
[ pos
+1 ] = g
;
240 M_IMGDATA
->m_data
[ pos
+2 ] = b
;
243 unsigned char wxImage::GetRed( int x
, int y
)
245 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
247 int w
= M_IMGDATA
->m_width
;
248 int h
= M_IMGDATA
->m_height
;
250 wxCHECK_MSG( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), 0, wxT("invalid image index") );
252 long pos
= (y
* w
+ x
) * 3;
254 return M_IMGDATA
->m_data
[pos
];
257 unsigned char wxImage::GetGreen( int x
, int y
)
259 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
261 int w
= M_IMGDATA
->m_width
;
262 int h
= M_IMGDATA
->m_height
;
264 wxCHECK_MSG( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), 0, wxT("invalid image index") );
266 long pos
= (y
* w
+ x
) * 3;
268 return M_IMGDATA
->m_data
[pos
+1];
271 unsigned char wxImage::GetBlue( int x
, int y
)
273 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
275 int w
= M_IMGDATA
->m_width
;
276 int h
= M_IMGDATA
->m_height
;
278 wxCHECK_MSG( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), 0, wxT("invalid image index") );
280 long pos
= (y
* w
+ x
) * 3;
282 return M_IMGDATA
->m_data
[pos
+2];
285 bool wxImage::Ok() const
287 return (M_IMGDATA
&& M_IMGDATA
->m_ok
);
290 char unsigned *wxImage::GetData() const
292 wxCHECK_MSG( Ok(), (char unsigned *)NULL
, wxT("invalid image") );
294 return M_IMGDATA
->m_data
;
297 void wxImage::SetData( char unsigned *data
)
299 wxCHECK_RET( Ok(), wxT("invalid image") );
301 wxImageRefData
*newRefData
= new wxImageRefData();
303 newRefData
->m_width
= M_IMGDATA
->m_width
;
304 newRefData
->m_height
= M_IMGDATA
->m_height
;
305 newRefData
->m_data
= data
;
306 newRefData
->m_ok
= TRUE
;
307 newRefData
->m_maskRed
= M_IMGDATA
->m_maskRed
;
308 newRefData
->m_maskGreen
= M_IMGDATA
->m_maskGreen
;
309 newRefData
->m_maskBlue
= M_IMGDATA
->m_maskBlue
;
310 newRefData
->m_hasMask
= M_IMGDATA
->m_hasMask
;
314 m_refData
= newRefData
;
317 void wxImage::SetMaskColour( unsigned char r
, unsigned char g
, unsigned char b
)
319 wxCHECK_RET( Ok(), wxT("invalid image") );
321 M_IMGDATA
->m_maskRed
= r
;
322 M_IMGDATA
->m_maskGreen
= g
;
323 M_IMGDATA
->m_maskBlue
= b
;
324 M_IMGDATA
->m_hasMask
= TRUE
;
327 unsigned char wxImage::GetMaskRed() const
329 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
331 return M_IMGDATA
->m_maskRed
;
334 unsigned char wxImage::GetMaskGreen() const
336 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
338 return M_IMGDATA
->m_maskGreen
;
341 unsigned char wxImage::GetMaskBlue() const
343 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
345 return M_IMGDATA
->m_maskBlue
;
348 void wxImage::SetMask( bool mask
)
350 wxCHECK_RET( Ok(), wxT("invalid image") );
352 M_IMGDATA
->m_hasMask
= mask
;
355 bool wxImage::HasMask() const
357 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid image") );
359 return M_IMGDATA
->m_hasMask
;
362 int wxImage::GetWidth() const
364 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
366 return M_IMGDATA
->m_width
;
369 int wxImage::GetHeight() const
371 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
373 return M_IMGDATA
->m_height
;
376 bool wxImage::LoadFile( const wxString
& filename
, long type
)
379 if (wxFileExists(filename
))
381 wxFileInputStream
stream(filename
);
382 wxBufferedInputStream
bstream( stream
);
383 return LoadFile(bstream
, type
);
387 wxLogError( _("Can't load image from file '%s': file does not exist."), filename
.c_str() );
391 #else // !wxUSE_STREAMS
393 #endif // wxUSE_STREAMS
396 bool wxImage::LoadFile( const wxString
& filename
, const wxString
& mimetype
)
399 if (wxFileExists(filename
))
401 wxFileInputStream
stream(filename
);
402 wxBufferedInputStream
bstream( stream
);
403 return LoadFile(bstream
, mimetype
);
407 wxLogError( _("Can't load image from file '%s': file does not exist."), filename
.c_str() );
411 #else // !wxUSE_STREAMS
413 #endif // wxUSE_STREAMS
416 bool wxImage::SaveFile( const wxString
& filename
, int type
)
419 wxFileOutputStream
stream(filename
);
421 if ( stream
.LastError() == wxStream_NOERROR
)
423 wxBufferedOutputStream
bstream( stream
);
424 return SaveFile(bstream
, type
);
427 #endif // wxUSE_STREAMS
431 bool wxImage::SaveFile( const wxString
& filename
, const wxString
& mimetype
)
434 wxFileOutputStream
stream(filename
);
436 if ( stream
.LastError() == wxStream_NOERROR
)
438 wxBufferedOutputStream
bstream( stream
);
439 return SaveFile(bstream
, mimetype
);
442 #endif // wxUSE_STREAMS
446 bool wxImage::CanRead( const wxString
&name
)
449 wxFileInputStream
stream(name
);
450 return CanRead(stream
);
458 bool wxImage::CanRead( wxInputStream
&stream
)
460 wxList
&list
=GetHandlers();
462 for ( wxList::Node
*node
= list
.GetFirst(); node
; node
= node
->GetNext() )
464 wxImageHandler
*handler
=(wxImageHandler
*)node
->GetData();
465 if (handler
->CanRead( stream
))
472 bool wxImage::LoadFile( wxInputStream
& stream
, long type
)
476 m_refData
= new wxImageRefData
;
478 wxImageHandler
*handler
;
480 if (type
==wxBITMAP_TYPE_ANY
)
482 wxList
&list
=GetHandlers();
484 for ( wxList::Node
*node
= list
.GetFirst(); node
; node
= node
->GetNext() )
486 handler
=(wxImageHandler
*)node
->GetData();
487 if (handler
->CanRead( stream
))
488 return handler
->LoadFile( this, stream
);
492 wxLogWarning( _("No handler found for image type.") );
496 handler
= FindHandler(type
);
500 wxLogWarning( _("No image handler for type %d defined."), type
);
505 return handler
->LoadFile( this, stream
);
508 bool wxImage::LoadFile( wxInputStream
& stream
, const wxString
& mimetype
)
512 m_refData
= new wxImageRefData
;
514 wxImageHandler
*handler
= FindHandlerMime(mimetype
);
518 wxLogWarning( _("No image handler for type %s defined."), mimetype
.GetData() );
523 return handler
->LoadFile( this, stream
);
526 bool wxImage::SaveFile( wxOutputStream
& stream
, int type
)
528 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid image") );
530 wxImageHandler
*handler
= FindHandler(type
);
534 wxLogWarning( _("No image handler for type %d defined."), type
);
539 return handler
->SaveFile( this, stream
);
542 bool wxImage::SaveFile( wxOutputStream
& stream
, const wxString
& mimetype
)
544 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid image") );
546 wxImageHandler
*handler
= FindHandlerMime(mimetype
);
550 wxLogWarning( _("No image handler for type %s defined."), mimetype
.GetData() );
555 return handler
->SaveFile( this, stream
);
557 #endif // wxUSE_STREAMS
559 void wxImage::AddHandler( wxImageHandler
*handler
)
561 // make sure that the memory will be freed at the program end
562 sm_handlers
.DeleteContents(TRUE
);
564 sm_handlers
.Append( handler
);
567 void wxImage::InsertHandler( wxImageHandler
*handler
)
569 // make sure that the memory will be freed at the program end
570 sm_handlers
.DeleteContents(TRUE
);
572 sm_handlers
.Insert( handler
);
575 bool wxImage::RemoveHandler( const wxString
& name
)
577 wxImageHandler
*handler
= FindHandler(name
);
580 sm_handlers
.DeleteObject(handler
);
587 wxImageHandler
*wxImage::FindHandler( const wxString
& name
)
589 wxNode
*node
= sm_handlers
.First();
592 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
593 if (handler
->GetName().Cmp(name
) == 0) return handler
;
597 return (wxImageHandler
*)NULL
;
600 wxImageHandler
*wxImage::FindHandler( const wxString
& extension
, long bitmapType
)
602 wxNode
*node
= sm_handlers
.First();
605 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
606 if ( (handler
->GetExtension().Cmp(extension
) == 0) &&
607 (bitmapType
== -1 || handler
->GetType() == bitmapType
) )
611 return (wxImageHandler
*)NULL
;
614 wxImageHandler
*wxImage::FindHandler( long bitmapType
)
616 wxNode
*node
= sm_handlers
.First();
619 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
620 if (handler
->GetType() == bitmapType
) return handler
;
626 wxImageHandler
*wxImage::FindHandlerMime( const wxString
& mimetype
)
628 wxNode
*node
= sm_handlers
.First();
631 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
632 if (handler
->GetMimeType().IsSameAs(mimetype
, FALSE
)) return handler
;
638 void wxImage::InitStandardHandlers()
640 AddHandler( new wxBMPHandler
);
643 void wxImage::CleanUpHandlers()
645 wxNode
*node
= sm_handlers
.First();
648 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
649 wxNode
*next
= node
->Next();
656 //-----------------------------------------------------------------------------
658 //-----------------------------------------------------------------------------
660 IMPLEMENT_ABSTRACT_CLASS(wxImageHandler
,wxObject
)
663 bool wxImageHandler::LoadFile( wxImage
*WXUNUSED(image
), wxInputStream
& WXUNUSED(stream
), bool WXUNUSED(verbose
), int WXUNUSED(index
) )
668 bool wxImageHandler::SaveFile( wxImage
*WXUNUSED(image
), wxOutputStream
& WXUNUSED(stream
), bool WXUNUSED(verbose
) )
673 int wxImageHandler::GetImageCount( wxInputStream
& WXUNUSED(stream
) )
678 bool wxImageHandler::CanRead( const wxString
& name
)
680 if (wxFileExists(name
))
682 wxFileInputStream
stream(name
);
683 return CanRead(stream
);
687 wxLogError( _("Can't check image format of file '%s': file does not exist."), name
.c_str() );
694 #endif // wxUSE_STREAMS
696 //-----------------------------------------------------------------------------
697 // MSW conversion routines
698 //-----------------------------------------------------------------------------
702 wxBitmap
wxImage::ConvertToBitmap() const
707 // sizeLimit is the MS upper limit for the DIB size
709 int sizeLimit
= 1024*768*3;
711 int sizeLimit
= 0x7fff ;
714 // width and height of the device-dependent bitmap
715 int width
= GetWidth();
716 int bmpHeight
= GetHeight();
718 // calc the number of bytes per scanline and padding
719 int bytePerLine
= width
*3;
720 int sizeDWORD
= sizeof( DWORD
);
721 int lineBoundary
= bytePerLine
% sizeDWORD
;
723 if( lineBoundary
> 0 )
725 padding
= sizeDWORD
- lineBoundary
;
726 bytePerLine
+= padding
;
728 // calc the number of DIBs and heights of DIBs
731 int height
= sizeLimit
/bytePerLine
;
732 if( height
>= bmpHeight
)
736 numDIB
= bmpHeight
/ height
;
737 hRemain
= bmpHeight
% height
;
738 if( hRemain
>0 ) numDIB
++;
741 // set bitmap parameters
743 wxCHECK_MSG( Ok(), bitmap
, wxT("invalid image") );
744 bitmap
.SetWidth( width
);
745 bitmap
.SetHeight( bmpHeight
);
746 bitmap
.SetDepth( wxDisplayDepth() );
748 // create a DIB header
749 int headersize
= sizeof(BITMAPINFOHEADER
);
750 LPBITMAPINFO lpDIBh
= (BITMAPINFO
*) malloc( headersize
);
751 wxCHECK_MSG( lpDIBh
, bitmap
, wxT("could not allocate memory for DIB header") );
752 // Fill in the DIB header
753 lpDIBh
->bmiHeader
.biSize
= headersize
;
754 lpDIBh
->bmiHeader
.biWidth
= (DWORD
)width
;
755 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
756 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
757 // the general formula for biSizeImage:
758 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
759 lpDIBh
->bmiHeader
.biPlanes
= 1;
760 lpDIBh
->bmiHeader
.biBitCount
= 24;
761 lpDIBh
->bmiHeader
.biCompression
= BI_RGB
;
762 lpDIBh
->bmiHeader
.biClrUsed
= 0;
763 // These seem not really needed for our purpose here.
764 lpDIBh
->bmiHeader
.biClrImportant
= 0;
765 lpDIBh
->bmiHeader
.biXPelsPerMeter
= 0;
766 lpDIBh
->bmiHeader
.biYPelsPerMeter
= 0;
767 // memory for DIB data
768 unsigned char *lpBits
;
769 lpBits
= (unsigned char *)malloc( lpDIBh
->bmiHeader
.biSizeImage
);
772 wxFAIL_MSG( wxT("could not allocate memory for DIB") );
777 // create and set the device-dependent bitmap
778 HDC hdc
= ::GetDC(NULL
);
779 HDC memdc
= ::CreateCompatibleDC( hdc
);
781 hbitmap
= ::CreateCompatibleBitmap( hdc
, width
, bmpHeight
);
782 ::SelectObject( memdc
, hbitmap
);
784 // copy image data into DIB data and then into DDB (in a loop)
785 unsigned char *data
= GetData();
788 unsigned char *ptdata
= data
;
789 unsigned char *ptbits
;
791 for( n
=0; n
<numDIB
; n
++ )
793 if( numDIB
> 1 && n
== numDIB
-1 && hRemain
> 0 )
795 // redefine height and size of the (possibly) last smaller DIB
796 // memory is not reallocated
798 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
799 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
803 for( j
=0; j
<height
; j
++ )
805 for( i
=0; i
<width
; i
++ )
807 *(ptbits
++) = *(ptdata
+2);
808 *(ptbits
++) = *(ptdata
+1);
809 *(ptbits
++) = *(ptdata
);
812 for( i
=0; i
< padding
; i
++ ) *(ptbits
++) = 0;
814 ::StretchDIBits( memdc
, 0, origin
, width
, height
,\
815 0, 0, width
, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
, SRCCOPY
);
817 // if numDIB = 1, lines below can also be used
818 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
819 // The above line is equivalent to the following two lines.
820 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
821 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
822 // or the following lines
823 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
824 // HDC memdc = ::CreateCompatibleDC( hdc );
825 // ::SelectObject( memdc, hbitmap);
826 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
827 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
828 // ::SelectObject( memdc, 0 );
829 // ::DeleteDC( memdc );
831 bitmap
.SetHBITMAP( (WXHBITMAP
) hbitmap
);
833 // similarly, created an mono-bitmap for the possible mask
836 hbitmap
= ::CreateBitmap( (WORD
)width
, (WORD
)bmpHeight
, 1, 1, NULL
);
837 ::SelectObject( memdc
, hbitmap
);
838 if( numDIB
== 1 ) height
= bmpHeight
;
839 else height
= sizeLimit
/bytePerLine
;
840 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
841 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
843 unsigned char r
= GetMaskRed();
844 unsigned char g
= GetMaskGreen();
845 unsigned char b
= GetMaskBlue();
846 unsigned char zero
= 0, one
= 255;
848 for( n
=0; n
<numDIB
; n
++ )
850 if( numDIB
> 1 && n
== numDIB
- 1 && hRemain
> 0 )
852 // redefine height and size of the (possibly) last smaller DIB
853 // memory is not reallocated
855 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
856 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
859 for( int j
=0; j
<height
; j
++ )
861 for(i
=0; i
<width
; i
++ )
863 if( (*(ptdata
++)!=r
) | (*(ptdata
++)!=g
) | (*(ptdata
++)!=b
) )
876 for( i
=0; i
< padding
; i
++ ) *(ptbits
++) = zero
;
878 ::StretchDIBits( memdc
, 0, origin
, width
, height
,\
879 0, 0, width
, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
, SRCCOPY
);
882 // create a wxMask object
883 wxMask
*mask
= new wxMask();
884 mask
->SetMaskBitmap( (WXHBITMAP
) hbitmap
);
885 bitmap
.SetMask( mask
);
886 // It will be deleted when the wxBitmap object is deleted (as of 01/1999)
887 /* The following can also be used but is slow to run
888 wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
889 wxMask *mask = new wxMask( bitmap, colour );
890 bitmap.SetMask( mask );
894 // free allocated resources
895 ::SelectObject( memdc
, 0 );
897 ::ReleaseDC(NULL
, hdc
);
901 #if WXWIN_COMPATIBILITY_2
902 // check the wxBitmap object
903 bitmap
.GetBitmapData()->SetOk();
904 #endif // WXWIN_COMPATIBILITY_2
909 wxImage::wxImage( const wxBitmap
&bitmap
)
914 wxFAIL_MSG( wxT("invalid bitmap") );
918 // create an wxImage object
919 int width
= bitmap
.GetWidth();
920 int height
= bitmap
.GetHeight();
921 Create( width
, height
);
922 unsigned char *data
= GetData();
925 wxFAIL_MSG( wxT("could not allocate data for image") );
929 // calc the number of bytes per scanline and padding in the DIB
930 int bytePerLine
= width
*3;
931 int sizeDWORD
= sizeof( DWORD
);
932 int lineBoundary
= bytePerLine
% sizeDWORD
;
934 if( lineBoundary
> 0 )
936 padding
= sizeDWORD
- lineBoundary
;
937 bytePerLine
+= padding
;
940 // create a DIB header
941 int headersize
= sizeof(BITMAPINFOHEADER
);
942 LPBITMAPINFO lpDIBh
= (BITMAPINFO
*) malloc( headersize
);
945 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
949 // Fill in the DIB header
950 lpDIBh
->bmiHeader
.biSize
= headersize
;
951 lpDIBh
->bmiHeader
.biWidth
= width
;
952 lpDIBh
->bmiHeader
.biHeight
= -height
;
953 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
* height
;
954 lpDIBh
->bmiHeader
.biPlanes
= 1;
955 lpDIBh
->bmiHeader
.biBitCount
= 24;
956 lpDIBh
->bmiHeader
.biCompression
= BI_RGB
;
957 lpDIBh
->bmiHeader
.biClrUsed
= 0;
958 // These seem not really needed for our purpose here.
959 lpDIBh
->bmiHeader
.biClrImportant
= 0;
960 lpDIBh
->bmiHeader
.biXPelsPerMeter
= 0;
961 lpDIBh
->bmiHeader
.biYPelsPerMeter
= 0;
962 // memory for DIB data
963 unsigned char *lpBits
;
964 lpBits
= (unsigned char *) malloc( lpDIBh
->bmiHeader
.biSizeImage
);
967 wxFAIL_MSG( wxT("could not allocate data for DIB") );
973 // copy data from the device-dependent bitmap to the DIB
974 HDC hdc
= ::GetDC(NULL
);
976 hbitmap
= (HBITMAP
) bitmap
.GetHBITMAP();
977 ::GetDIBits( hdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
979 // copy DIB data into the wxImage object
981 unsigned char *ptdata
= data
;
982 unsigned char *ptbits
= lpBits
;
983 for( i
=0; i
<height
; i
++ )
985 for( j
=0; j
<width
; j
++ )
987 *(ptdata
++) = *(ptbits
+2);
988 *(ptdata
++) = *(ptbits
+1);
989 *(ptdata
++) = *(ptbits
);
995 // similarly, set data according to the possible mask bitmap
996 if( bitmap
.GetMask() && bitmap
.GetMask()->GetMaskBitmap() )
998 hbitmap
= (HBITMAP
) bitmap
.GetMask()->GetMaskBitmap();
999 // memory DC created, color set, data copied, and memory DC deleted
1000 HDC memdc
= ::CreateCompatibleDC( hdc
);
1001 ::SetTextColor( memdc
, RGB( 0, 0, 0 ) );
1002 ::SetBkColor( memdc
, RGB( 255, 255, 255 ) );
1003 ::GetDIBits( memdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
1004 ::DeleteDC( memdc
);
1005 // background color set to RGB(16,16,16) in consistent with wxGTK
1006 unsigned char r
=16, g
=16, b
=16;
1009 for( i
=0; i
<height
; i
++ )
1011 for( j
=0; j
<width
; j
++ )
1025 SetMaskColour( r
, g
, b
);
1032 // free allocated resources
1033 ::ReleaseDC(NULL
, hdc
);
1042 #include <PictUtils.h>
1044 extern CTabHandle
wxMacCreateColorTable( int numColors
) ;
1045 extern void wxMacDestroyColorTable( CTabHandle colors
) ;
1046 extern void wxMacSetColorTableEntry( CTabHandle newColors
, int index
, int red
, int green
, int blue
) ;
1047 extern GWorldPtr
wxMacCreateGWorld( int height
, int width
, int depth
) ;
1048 extern void wxMacDestroyGWorld( GWorldPtr gw
) ;
1050 wxBitmap
wxImage::ConvertToBitmap() const
1052 // width and height of the device-dependent bitmap
1053 int width
= GetWidth();
1054 int height
= GetHeight();
1058 wxBitmap
bitmap( width
, height
, wxDisplayDepth() ) ;
1065 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1067 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1069 wxMask *mask = new wxMask();
1070 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1072 bitmap.SetMask( mask );
1078 int r_mask
= GetMaskRed();
1079 int g_mask
= GetMaskGreen();
1080 int b_mask
= GetMaskBlue();
1083 GDHandle origDevice
;
1085 GetGWorld( &origPort
, &origDevice
) ;
1086 SetGWorld( bitmap
.GetHBITMAP() , NULL
) ;
1088 register unsigned char* data
= GetData();
1091 for (int y
= 0; y
< height
; y
++)
1094 unsigned char lastr
= 0 ;
1095 unsigned char lastg
= 0 ;
1096 unsigned char lastb
= 0 ;
1097 RGBColor lastcolor
;
1100 for (int x
= 0; x
< width
; x
++)
1102 unsigned char r
= data
[index
++];
1103 unsigned char g
= data
[index
++];
1104 unsigned char b
= data
[index
++];
1106 if ( r
!= lastr
|| g
!= lastg
|| b
!= lastb
)
1108 lastcolor
.red
= ( lastr
<< 8 ) + lastr
;
1109 lastcolor
.green
= ( lastg
<< 8 ) + lastg
;
1110 lastcolor
.blue
= ( lastb
<< 8 ) + lastb
;
1111 RGBForeColor( &lastcolor
) ;
1118 lastcolor
.red
= ( lastr
<< 8 ) + lastr
;
1119 lastcolor
.green
= ( lastg
<< 8 ) + lastg
;
1120 lastcolor
.blue
= ( lastb
<< 8 ) + lastb
;
1121 RGBForeColor( &lastcolor
) ;
1122 LineTo( width
- 1 , y
) ;
1124 for (int x
= 0; x
< width
; x
++)
1126 unsigned char r
= data
[index
++];
1127 unsigned char g
= data
[index
++];
1128 unsigned char b
= data
[index
++];
1130 color
.red
= ( r
<< 8 ) + r
;
1131 color
.green
= ( g
<< 8 ) + g
;
1132 color
.blue
= ( b
<< 8 ) + b
;
1133 SetCPixel( x
, y
, &color
) ;
1138 SetGWorld( origPort
, origDevice
) ;
1144 wxImage::wxImage( const wxBitmap
&bitmap
)
1149 wxFAIL_MSG( "invalid bitmap" );
1153 // create an wxImage object
1154 int width
= bitmap
.GetWidth();
1155 int height
= bitmap
.GetHeight();
1156 Create( width
, height
);
1158 unsigned char *data = GetData();
1161 wxFAIL_MSG( "could not allocate data for image" );
1165 // calc the number of bytes per scanline and padding in the DIB
1166 int bytePerLine = width*3;
1167 int sizeDWORD = sizeof( DWORD );
1168 div_t lineBoundary = div( bytePerLine, sizeDWORD );
1170 if( lineBoundary.rem > 0 )
1172 padding = sizeDWORD - lineBoundary.rem;
1173 bytePerLine += padding;
1176 // create a DIB header
1177 int headersize = sizeof(BITMAPINFOHEADER);
1178 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
1181 wxFAIL_MSG( "could not allocate data for DIB header" );
1185 // Fill in the DIB header
1186 lpDIBh->bmiHeader.biSize = headersize;
1187 lpDIBh->bmiHeader.biWidth = width;
1188 lpDIBh->bmiHeader.biHeight = -height;
1189 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
1190 lpDIBh->bmiHeader.biPlanes = 1;
1191 lpDIBh->bmiHeader.biBitCount = 24;
1192 lpDIBh->bmiHeader.biCompression = BI_RGB;
1193 lpDIBh->bmiHeader.biClrUsed = 0;
1194 // These seem not really needed for our purpose here.
1195 lpDIBh->bmiHeader.biClrImportant = 0;
1196 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
1197 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
1198 // memory for DIB data
1199 unsigned char *lpBits;
1200 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
1203 wxFAIL_MSG( "could not allocate data for DIB" );
1209 // copy data from the device-dependent bitmap to the DIB
1210 HDC hdc = ::GetDC(NULL);
1212 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
1213 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1215 // copy DIB data into the wxImage object
1217 unsigned char *ptdata = data;
1218 unsigned char *ptbits = lpBits;
1219 for( i=0; i<height; i++ )
1221 for( j=0; j<width; j++ )
1223 *(ptdata++) = *(ptbits+2);
1224 *(ptdata++) = *(ptbits+1);
1225 *(ptdata++) = *(ptbits );
1231 // similarly, set data according to the possible mask bitmap
1232 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
1234 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
1235 // memory DC created, color set, data copied, and memory DC deleted
1236 HDC memdc = ::CreateCompatibleDC( hdc );
1237 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
1238 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
1239 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1240 ::DeleteDC( memdc );
1241 // background color set to RGB(16,16,16) in consistent with wxGTK
1242 unsigned char r=16, g=16, b=16;
1245 for( i=0; i<height; i++ )
1247 for( j=0; j<width; j++ )
1261 SetMaskColour( r, g, b );
1268 // free allocated resources
1269 ::ReleaseDC(NULL, hdc);
1277 //-----------------------------------------------------------------------------
1278 // GTK conversion routines
1279 //-----------------------------------------------------------------------------
1283 #include <gtk/gtk.h>
1284 #include <gdk/gdk.h>
1285 #include <gdk/gdkx.h>
1287 #if (GTK_MINOR_VERSION > 0)
1288 #include <gdk/gdkrgb.h>
1291 wxBitmap
wxImage::ConvertToBitmap() const
1295 wxCHECK_MSG( Ok(), bitmap
, wxT("invalid image") );
1297 int width
= GetWidth();
1298 int height
= GetHeight();
1300 bitmap
.SetHeight( height
);
1301 bitmap
.SetWidth( width
);
1303 bitmap
.SetPixmap( gdk_pixmap_new( (GdkWindow
*)&gdk_root_parent
, width
, height
, -1 ) );
1307 GdkVisual
*visual
= gdk_window_get_visual( bitmap
.GetPixmap() );
1308 if (visual
== NULL
) visual
= gdk_visual_get_system();
1309 int bpp
= visual
->depth
;
1311 bitmap
.SetDepth( bpp
);
1313 if ((bpp
== 16) && (visual
->red_mask
!= 0xf800)) bpp
= 15;
1314 if (bpp
< 8) bpp
= 8;
1316 #if (GTK_MINOR_VERSION > 0)
1318 if (!HasMask() && (bpp
> 8))
1320 static bool s_hasInitialized
= FALSE
;
1322 if (!s_hasInitialized
)
1325 s_hasInitialized
= TRUE
;
1328 GdkGC
*gc
= gdk_gc_new( bitmap
.GetPixmap() );
1330 gdk_draw_rgb_image( bitmap
.GetPixmap(),
1334 GDK_RGB_DITHER_NONE
,
1345 // Create picture image
1347 GdkImage
*data_image
=
1348 gdk_image_new( GDK_IMAGE_FASTEST
, gdk_visual_get_system(), width
, height
);
1350 // Create mask image
1352 GdkImage
*mask_image
= (GdkImage
*) NULL
;
1356 unsigned char *mask_data
= (unsigned char*)malloc( ((width
>> 3)+8) * height
);
1358 mask_image
= gdk_image_new_bitmap( gdk_visual_get_system(), mask_data
, width
, height
);
1360 wxMask
*mask
= new wxMask();
1361 mask
->m_bitmap
= gdk_pixmap_new( (GdkWindow
*)&gdk_root_parent
, width
, height
, 1 );
1363 bitmap
.SetMask( mask
);
1368 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
1369 byte_order b_o
= RGB
;
1373 GdkVisual
*visual
= gdk_visual_get_system();
1374 if ((visual
->red_mask
> visual
->green_mask
) && (visual
->green_mask
> visual
->blue_mask
)) b_o
= RGB
;
1375 else if ((visual
->red_mask
> visual
->blue_mask
) && (visual
->blue_mask
> visual
->green_mask
)) b_o
= RGB
;
1376 else if ((visual
->blue_mask
> visual
->red_mask
) && (visual
->red_mask
> visual
->green_mask
)) b_o
= BRG
;
1377 else if ((visual
->blue_mask
> visual
->green_mask
) && (visual
->green_mask
> visual
->red_mask
)) b_o
= BGR
;
1378 else if ((visual
->green_mask
> visual
->red_mask
) && (visual
->red_mask
> visual
->blue_mask
)) b_o
= GRB
;
1379 else if ((visual
->green_mask
> visual
->blue_mask
) && (visual
->blue_mask
> visual
->red_mask
)) b_o
= GBR
;
1382 int r_mask
= GetMaskRed();
1383 int g_mask
= GetMaskGreen();
1384 int b_mask
= GetMaskBlue();
1386 unsigned char* data
= GetData();
1389 for (int y
= 0; y
< height
; y
++)
1391 for (int x
= 0; x
< width
; x
++)
1393 int r
= data
[index
];
1395 int g
= data
[index
];
1397 int b
= data
[index
];
1402 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
1403 gdk_image_put_pixel( mask_image
, x
, y
, 1 );
1405 gdk_image_put_pixel( mask_image
, x
, y
, 0 );
1410 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
1411 gdk_image_put_pixel( mask_image
, x
, y
, 1 );
1413 gdk_image_put_pixel( mask_image
, x
, y
, 0 );
1421 if (wxTheApp
->m_colorCube
)
1423 pixel
= wxTheApp
->m_colorCube
[ ((r
& 0xf8) << 7) + ((g
& 0xf8) << 2) + ((b
& 0xf8) >> 3) ];
1427 GdkColormap
*cmap
= gtk_widget_get_default_colormap();
1428 GdkColor
*colors
= cmap
->colors
;
1429 int max
= 3 * (65536);
1431 for (int i
= 0; i
< cmap
->size
; i
++)
1433 int rdiff
= (r
<< 8) - colors
[i
].red
;
1434 int gdiff
= (g
<< 8) - colors
[i
].green
;
1435 int bdiff
= (b
<< 8) - colors
[i
].blue
;
1436 int sum
= ABS (rdiff
) + ABS (gdiff
) + ABS (bdiff
);
1437 if (sum
< max
) { pixel
= i
; max
= sum
; }
1441 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1447 guint32 pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
1448 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1453 guint32 pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
1454 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1463 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
1464 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
1465 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
1466 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
1467 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
1468 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
1470 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1479 GdkGC
*data_gc
= gdk_gc_new( bitmap
.GetPixmap() );
1481 gdk_draw_image( bitmap
.GetPixmap(), data_gc
, data_image
, 0, 0, 0, 0, width
, height
);
1483 gdk_image_destroy( data_image
);
1484 gdk_gc_unref( data_gc
);
1490 GdkGC
*mask_gc
= gdk_gc_new( bitmap
.GetMask()->GetBitmap() );
1492 gdk_draw_image( bitmap
.GetMask()->GetBitmap(), mask_gc
, mask_image
, 0, 0, 0, 0, width
, height
);
1494 gdk_image_destroy( mask_image
);
1495 gdk_gc_unref( mask_gc
);
1501 wxImage::wxImage( const wxBitmap
&bitmap
)
1503 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
1505 GdkImage
*gdk_image
= (GdkImage
*) NULL
;
1506 if (bitmap
.GetPixmap())
1508 gdk_image
= gdk_image_get( bitmap
.GetPixmap(),
1510 bitmap
.GetWidth(), bitmap
.GetHeight() );
1512 if (bitmap
.GetBitmap())
1514 gdk_image
= gdk_image_get( bitmap
.GetBitmap(),
1516 bitmap
.GetWidth(), bitmap
.GetHeight() );
1519 wxFAIL_MSG( wxT("Ill-formed bitmap") );
1522 wxCHECK_RET( gdk_image
, wxT("couldn't create image") );
1524 Create( bitmap
.GetWidth(), bitmap
.GetHeight() );
1525 char unsigned *data
= GetData();
1529 gdk_image_destroy( gdk_image
);
1530 wxFAIL_MSG( wxT("couldn't create image") );
1534 GdkImage
*gdk_image_mask
= (GdkImage
*) NULL
;
1535 if (bitmap
.GetMask())
1537 gdk_image_mask
= gdk_image_get( bitmap
.GetMask()->GetBitmap(),
1539 bitmap
.GetWidth(), bitmap
.GetHeight() );
1541 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1544 GdkVisual
*visual
= (GdkVisual
*) NULL
;
1545 if (bitmap
.GetPixmap())
1546 visual
= gdk_window_get_visual( bitmap
.GetPixmap() );
1548 visual
= gdk_window_get_visual( bitmap
.GetBitmap() );
1550 if (visual
== NULL
) visual
= gdk_window_get_visual( (GdkWindow
*) &gdk_root_parent
);
1551 int bpp
= visual
->depth
;
1552 if ((bpp
== 16) && (visual
->red_mask
!= 0xf800)) bpp
= 15;
1554 GdkColormap
*cmap
= gtk_widget_get_default_colormap();
1557 for (int j
= 0; j
< bitmap
.GetHeight(); j
++)
1559 for (int i
= 0; i
< bitmap
.GetWidth(); i
++)
1561 wxInt32 pixel
= gdk_image_get_pixel( gdk_image
, i
, j
);
1564 data
[pos
] = cmap
->colors
[pixel
].red
>> 8;
1565 data
[pos
+1] = cmap
->colors
[pixel
].green
>> 8;
1566 data
[pos
+2] = cmap
->colors
[pixel
].blue
>> 8;
1567 } else if (bpp
== 15)
1569 #if (wxBYTE_ORDER == wxBIG_ENDIAN)
1572 data
[pos
] = (pixel
>> 7) & 0xf8;
1573 data
[pos
+1] = (pixel
>> 2) & 0xf8;
1574 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1575 } else if (bpp
== 16)
1577 #if (wxBYTE_ORDER == wxBIG_ENDIAN)
1580 data
[pos
] = (pixel
>> 8) & 0xf8;
1581 data
[pos
+1] = (pixel
>> 3) & 0xfc;
1582 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1585 #if (wxBYTE_ORDER == wxBIG_ENDIAN)
1586 data
[pos
] = (pixel
) & 0xff; // Red
1587 data
[pos
+1] = (pixel
>> 8) & 0xff; // Green
1588 data
[pos
+2] = (pixel
>> 16) & 0xff; // Blue
1590 data
[pos
] = (pixel
>> 16) & 0xff;
1591 data
[pos
+1] = (pixel
>> 8) & 0xff;
1592 data
[pos
+2] = pixel
& 0xff;
1598 int mask_pixel
= gdk_image_get_pixel( gdk_image_mask
, i
, j
);
1599 if (mask_pixel
== 0)
1611 gdk_image_destroy( gdk_image
);
1612 if (gdk_image_mask
) gdk_image_destroy( gdk_image_mask
);
1617 //-----------------------------------------------------------------------------
1618 // Motif conversion routines
1619 //-----------------------------------------------------------------------------
1623 #pragma message disable nosimpint
1627 #pragma message enable nosimpint
1629 #include "wx/utils.h"
1632 wxBitmap
wxImage::ConvertToBitmap() const
1636 wxCHECK_MSG( Ok(), bitmap
, wxT("invalid image") );
1638 int width
= GetWidth();
1639 int height
= GetHeight();
1641 bitmap
.SetHeight( height
);
1642 bitmap
.SetWidth( width
);
1644 Display
*dpy
= (Display
*) wxGetDisplay();
1645 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1646 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1650 XImage
*data_image
= XCreateImage( dpy
, vis
, bpp
, ZPixmap
, 0, 0, width
, height
, 32, 0 );
1651 data_image
->data
= (char*) malloc( data_image
->bytes_per_line
* data_image
->height
);
1653 bitmap
.Create( width
, height
, bpp
);
1658 GdkImage *mask_image = (GdkImage*) NULL;
1662 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1664 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1666 wxMask *mask = new wxMask();
1667 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1669 bitmap.SetMask( mask );
1673 // Retrieve depth info
1675 XVisualInfo vinfo_template
;
1678 vinfo_template
.visual
= vis
;
1679 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1680 vinfo_template
.depth
= bpp
;
1683 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
1685 wxCHECK_MSG( vi
, wxNullBitmap
, wxT("no visual") );
1689 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1690 if (bpp
< 8) bpp
= 8;
1694 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
1695 byte_order b_o
= RGB
;
1699 if ((vi
->red_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->blue_mask
)) b_o
= RGB
;
1700 else if ((vi
->red_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->green_mask
)) b_o
= RGB
;
1701 else if ((vi
->blue_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->green_mask
)) b_o
= BRG
;
1702 else if ((vi
->blue_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->red_mask
)) b_o
= BGR
;
1703 else if ((vi
->green_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->blue_mask
)) b_o
= GRB
;
1704 else if ((vi
->green_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->red_mask
)) b_o
= GBR
;
1708 int r_mask = GetMaskRed();
1709 int g_mask = GetMaskGreen();
1710 int b_mask = GetMaskBlue();
1716 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap( dpy
);
1718 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
1719 XQueryColors( dpy
, cmap
, colors
, 256 );
1722 unsigned char* data
= GetData();
1725 for (int y
= 0; y
< height
; y
++)
1727 for (int x
= 0; x
< width
; x
++)
1729 int r
= data
[index
];
1731 int g
= data
[index
];
1733 int b
= data
[index
];
1739 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1740 gdk_image_put_pixel( mask_image, x, y, 1 );
1742 gdk_image_put_pixel( mask_image, x, y, 0 );
1752 if (wxTheApp->m_colorCube)
1754 pixel = wxTheApp->m_colorCube
1755 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1760 int max
= 3 * (65536);
1761 for (int i
= 0; i
< 256; i
++)
1763 int rdiff
= (r
<< 8) - colors
[i
].red
;
1764 int gdiff
= (g
<< 8) - colors
[i
].green
;
1765 int bdiff
= (b
<< 8) - colors
[i
].blue
;
1766 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
1767 if (sum
< max
) { pixel
= i
; max
= sum
; }
1772 XPutPixel( data_image
, x
, y
, pixel
);
1777 int pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
1778 XPutPixel( data_image
, x
, y
, pixel
);
1783 int pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
1784 XPutPixel( data_image
, x
, y
, pixel
);
1793 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
1794 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
1795 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
1796 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
1797 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
1798 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
1800 XPutPixel( data_image
, x
, y
, pixel
);
1810 gcvalues
.foreground
= BlackPixel( dpy
, DefaultScreen( dpy
) );
1811 GC gc
= XCreateGC( dpy
, RootWindow ( dpy
, DefaultScreen(dpy
) ), GCForeground
, &gcvalues
);
1812 XPutImage( dpy
, (Drawable
)bitmap
.GetPixmap(), gc
, data_image
, 0, 0, 0, 0, width
, height
);
1814 XDestroyImage( data_image
);
1822 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
1824 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
1826 gdk_image_destroy( mask_image );
1827 gdk_gc_unref( mask_gc );
1834 wxImage::wxImage( const wxBitmap
&bitmap
)
1836 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
1838 Display
*dpy
= (Display
*) wxGetDisplay();
1839 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1840 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1842 XImage
*ximage
= XGetImage( dpy
,
1843 (Drawable
)bitmap
.GetPixmap(),
1845 bitmap
.GetWidth(), bitmap
.GetHeight(),
1846 AllPlanes
, ZPixmap
);
1848 wxCHECK_RET( ximage
, wxT("couldn't create image") );
1850 Create( bitmap
.GetWidth(), bitmap
.GetHeight() );
1851 char unsigned *data
= GetData();
1855 XDestroyImage( ximage
);
1856 wxFAIL_MSG( wxT("couldn't create image") );
1861 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1862 if (bitmap.GetMask())
1864 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1866 bitmap.GetWidth(), bitmap.GetHeight() );
1868 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1872 // Retrieve depth info
1874 XVisualInfo vinfo_template
;
1877 vinfo_template
.visual
= vis
;
1878 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1879 vinfo_template
.depth
= bpp
;
1882 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
1884 wxCHECK_RET( vi
, wxT("no visual") );
1886 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1893 Colormap cmap
= (Colormap
)wxTheApp
->GetMainColormap( dpy
);
1895 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
1896 XQueryColors( dpy
, cmap
, colors
, 256 );
1900 for (int j
= 0; j
< bitmap
.GetHeight(); j
++)
1902 for (int i
= 0; i
< bitmap
.GetWidth(); i
++)
1904 int pixel
= XGetPixel( ximage
, i
, j
);
1907 data
[pos
] = colors
[pixel
].red
>> 8;
1908 data
[pos
+1] = colors
[pixel
].green
>> 8;
1909 data
[pos
+2] = colors
[pixel
].blue
>> 8;
1910 } else if (bpp
== 15)
1912 data
[pos
] = (pixel
>> 7) & 0xf8;
1913 data
[pos
+1] = (pixel
>> 2) & 0xf8;
1914 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1915 } else if (bpp
== 16)
1917 data
[pos
] = (pixel
>> 8) & 0xf8;
1918 data
[pos
+1] = (pixel
>> 3) & 0xfc;
1919 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1922 data
[pos
] = (pixel
>> 16) & 0xff;
1923 data
[pos
+1] = (pixel
>> 8) & 0xff;
1924 data
[pos
+2] = pixel
& 0xff;
1930 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1931 if (mask_pixel == 0)
1944 XDestroyImage( ximage
);
1946 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1952 // OS/2 Presentation manager conversion routings
1954 wxBitmap
wxImage::ConvertToBitmap() const
1957 return wxNullBitmap
;
1958 wxBitmap bitmap
; // remove
1961 int sizeLimit = 1024*768*3;
1963 // width and height of the device-dependent bitmap
1964 int width = GetWidth();
1965 int bmpHeight = GetHeight();
1967 // calc the number of bytes per scanline and padding
1968 int bytePerLine = width*3;
1969 int sizeDWORD = sizeof( DWORD );
1970 int lineBoundary = bytePerLine % sizeDWORD;
1972 if( lineBoundary > 0 )
1974 padding = sizeDWORD - lineBoundary;
1975 bytePerLine += padding;
1977 // calc the number of DIBs and heights of DIBs
1980 int height = sizeLimit/bytePerLine;
1981 if( height >= bmpHeight )
1985 numDIB = bmpHeight / height;
1986 hRemain = bmpHeight % height;
1987 if( hRemain >0 ) numDIB++;
1990 // set bitmap parameters
1992 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
1993 bitmap.SetWidth( width );
1994 bitmap.SetHeight( bmpHeight );
1995 bitmap.SetDepth( wxDisplayDepth() );
1997 // create a DIB header
1998 int headersize = sizeof(BITMAPINFOHEADER);
1999 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
2000 wxCHECK_MSG( lpDIBh, bitmap, wxT("could not allocate memory for DIB header") );
2001 // Fill in the DIB header
2002 lpDIBh->bmiHeader.biSize = headersize;
2003 lpDIBh->bmiHeader.biWidth = (DWORD)width;
2004 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2005 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2006 // the general formula for biSizeImage:
2007 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
2008 lpDIBh->bmiHeader.biPlanes = 1;
2009 lpDIBh->bmiHeader.biBitCount = 24;
2010 lpDIBh->bmiHeader.biCompression = BI_RGB;
2011 lpDIBh->bmiHeader.biClrUsed = 0;
2012 // These seem not really needed for our purpose here.
2013 lpDIBh->bmiHeader.biClrImportant = 0;
2014 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2015 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2016 // memory for DIB data
2017 unsigned char *lpBits;
2018 lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
2021 wxFAIL_MSG( wxT("could not allocate memory for DIB") );
2026 // create and set the device-dependent bitmap
2027 HDC hdc = ::GetDC(NULL);
2028 HDC memdc = ::CreateCompatibleDC( hdc );
2030 hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
2031 ::SelectObject( memdc, hbitmap);
2033 // copy image data into DIB data and then into DDB (in a loop)
2034 unsigned char *data = GetData();
2037 unsigned char *ptdata = data;
2038 unsigned char *ptbits;
2040 for( n=0; n<numDIB; n++ )
2042 if( numDIB > 1 && n == numDIB-1 && hRemain > 0 )
2044 // redefine height and size of the (possibly) last smaller DIB
2045 // memory is not reallocated
2047 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2048 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2052 for( j=0; j<height; j++ )
2054 for( i=0; i<width; i++ )
2056 *(ptbits++) = *(ptdata+2);
2057 *(ptbits++) = *(ptdata+1);
2058 *(ptbits++) = *(ptdata );
2061 for( i=0; i< padding; i++ ) *(ptbits++) = 0;
2063 ::StretchDIBits( memdc, 0, origin, width, height,\
2064 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2066 // if numDIB = 1, lines below can also be used
2067 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
2068 // The above line is equivalent to the following two lines.
2069 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2070 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
2071 // or the following lines
2072 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2073 // HDC memdc = ::CreateCompatibleDC( hdc );
2074 // ::SelectObject( memdc, hbitmap);
2075 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
2076 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
2077 // ::SelectObject( memdc, 0 );
2078 // ::DeleteDC( memdc );
2080 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
2082 // similarly, created an mono-bitmap for the possible mask
2085 hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL );
2086 ::SelectObject( memdc, hbitmap);
2087 if( numDIB == 1 ) height = bmpHeight;
2088 else height = sizeLimit/bytePerLine;
2089 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2090 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2092 unsigned char r = GetMaskRed();
2093 unsigned char g = GetMaskGreen();
2094 unsigned char b = GetMaskBlue();
2095 unsigned char zero = 0, one = 255;
2097 for( n=0; n<numDIB; n++ )
2099 if( numDIB > 1 && n == numDIB - 1 && hRemain > 0 )
2101 // redefine height and size of the (possibly) last smaller DIB
2102 // memory is not reallocated
2104 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2105 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2108 for( int j=0; j<height; j++ )
2110 for(i=0; i<width; i++ )
2112 if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
2125 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
2127 ::StretchDIBits( memdc, 0, origin, width, height,\
2128 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2131 // create a wxMask object
2132 wxMask *mask = new wxMask();
2133 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
2134 bitmap.SetMask( mask );
2137 // free allocated resources
2138 ::SelectObject( memdc, 0 );
2139 ::DeleteDC( memdc );
2140 ::ReleaseDC(NULL, hdc);
2144 // check the wxBitmap object
2145 if( bitmap.GetHBITMAP() )
2146 bitmap.SetOk( TRUE );
2148 bitmap.SetOk( FALSE );
2153 wxImage::wxImage( const wxBitmap
&bitmap
)
2158 wxFAIL_MSG( wxT("invalid bitmap") );
2162 // create an wxImage object
2163 int width
= bitmap
.GetWidth();
2164 int height
= bitmap
.GetHeight();
2165 Create( width
, height
);
2166 unsigned char *data
= GetData();
2169 wxFAIL_MSG( wxT("could not allocate data for image") );
2173 // calc the number of bytes per scanline and padding in the DIB
2174 int bytePerLine
= width
*3;
2175 int sizeDWORD
= sizeof( DWORD
);
2176 int lineBoundary
= bytePerLine
% sizeDWORD
;
2178 if( lineBoundary
> 0 )
2180 padding
= sizeDWORD
- lineBoundary
;
2181 bytePerLine
+= padding
;
2185 // create a DIB header
2186 int headersize = sizeof(BITMAPINFOHEADER);
2187 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
2190 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
2194 // Fill in the DIB header
2195 lpDIBh->bmiHeader.biSize = headersize;
2196 lpDIBh->bmiHeader.biWidth = width;
2197 lpDIBh->bmiHeader.biHeight = -height;
2198 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
2199 lpDIBh->bmiHeader.biPlanes = 1;
2200 lpDIBh->bmiHeader.biBitCount = 24;
2201 lpDIBh->bmiHeader.biCompression = BI_RGB;
2202 lpDIBh->bmiHeader.biClrUsed = 0;
2203 // These seem not really needed for our purpose here.
2204 lpDIBh->bmiHeader.biClrImportant = 0;
2205 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2206 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2207 // memory for DIB data
2208 unsigned char *lpBits;
2209 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
2212 wxFAIL_MSG( wxT("could not allocate data for DIB") );
2218 // copy data from the device-dependent bitmap to the DIB
2219 HDC hdc = ::GetDC(NULL);
2221 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
2222 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2224 // copy DIB data into the wxImage object
2226 unsigned char *ptdata = data;
2227 unsigned char *ptbits = lpBits;
2228 for( i=0; i<height; i++ )
2230 for( j=0; j<width; j++ )
2232 *(ptdata++) = *(ptbits+2);
2233 *(ptdata++) = *(ptbits+1);
2234 *(ptdata++) = *(ptbits );
2240 // similarly, set data according to the possible mask bitmap
2241 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
2243 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
2244 // memory DC created, color set, data copied, and memory DC deleted
2245 HDC memdc = ::CreateCompatibleDC( hdc );
2246 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
2247 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
2248 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2249 ::DeleteDC( memdc );
2250 // background color set to RGB(16,16,16) in consistent with wxGTK
2251 unsigned char r=16, g=16, b=16;
2254 for( i=0; i<height; i++ )
2256 for( j=0; j<width; j++ )
2270 SetMaskColour( r, g, b );
2277 // free allocated resources
2278 ::ReleaseDC(NULL, hdc);
2286 // A module to allow wxImage initialization/cleanup
2287 // without calling these functions from app.cpp or from
2288 // the user's application.
2290 class wxImageModule
: public wxModule
2292 DECLARE_DYNAMIC_CLASS(wxImageModule
)
2295 bool OnInit() { wxImage::InitStandardHandlers(); return TRUE
; };
2296 void OnExit() { wxImage::CleanUpHandlers(); };
2299 IMPLEMENT_DYNAMIC_CLASS(wxImageModule
, wxModule
)
2302 //-----------------------------------------------------------------------------
2305 // Counts and returns the number of different colours. Optionally stops
2306 // when it reaches 'stopat' different colours. This is useful, for example,
2307 // to see if the image can be saved as 8-bit (256 colour or less, in this
2308 // case it would be invoked as CountColours(257)). Default value for stopat
2309 // is -1 (don't care).
2311 unsigned long wxImage::CountColours( unsigned long stopat
)
2316 unsigned char r
, g
, b
, *p
;
2317 unsigned long size
, nentries
, key
;
2320 size
= GetWidth() * GetHeight();
2323 for (unsigned long j
= 0; (j
< size
) && (nentries
< stopat
) ; j
++)
2328 key
= (r
<< 16) | (g
<< 8) | b
;
2330 hnode
= (wxHNode
*) h
.Get(key
);
2334 h
.Put(key
, (wxObject
*)(new wxHNode
));
2339 // delete all HNodes
2341 while ((node
= h
.Next()) != NULL
)
2342 delete (wxHNode
*)node
->GetData();
2349 // Computes the histogram of the image and fills a hash table, indexed
2350 // with integer keys built as 0xRRGGBB, containing wxHNode objects. Each
2351 // wxHNode contains an 'index' (useful to build a palette with the image
2352 // colours) and a 'value', which is the number of pixels in the image with
2355 unsigned long wxImage::ComputeHistogram( wxHashTable
&h
)
2357 unsigned char r
, g
, b
, *p
;
2358 unsigned long size
, nentries
, key
;
2362 size
= GetWidth() * GetHeight();
2365 for (unsigned long j
= 0; j
< size
; j
++)
2370 key
= (r
<< 16) | (g
<< 8) | b
;
2372 hnode
= (wxHNode
*) h
.Get(key
);
2378 hnode
= new wxHNode();
2379 hnode
->index
= nentries
++;
2382 h
.Put(key
, (wxObject
*)hnode
);