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 #if !USE_SHARED_LIBRARIES
85 IMPLEMENT_DYNAMIC_CLASS(wxImage
, wxObject
)
92 wxImage::wxImage( int width
, int height
)
94 Create( width
, height
);
97 wxImage::wxImage( const wxString
& name
, long type
)
99 LoadFile( name
, type
);
102 wxImage::wxImage( const wxString
& name
, const wxString
& mimetype
)
104 LoadFile( name
, mimetype
);
108 wxImage::wxImage( wxInputStream
& stream
, long type
)
110 LoadFile( stream
, type
);
113 wxImage::wxImage( wxInputStream
& stream
, const wxString
& mimetype
)
115 LoadFile( stream
, mimetype
);
117 #endif // wxUSE_STREAMS
119 wxImage::wxImage( const wxImage
& image
)
124 wxImage::wxImage( const wxImage
* image
)
126 if (image
) Ref(*image
);
129 void wxImage::Create( int width
, int height
)
131 m_refData
= new wxImageRefData();
133 M_IMGDATA
->m_data
= (unsigned char *) malloc( width
*height
*3 );
134 if (M_IMGDATA
->m_data
)
136 for (int l
= 0; l
< width
*height
*3; l
++) M_IMGDATA
->m_data
[l
] = 0;
138 M_IMGDATA
->m_width
= width
;
139 M_IMGDATA
->m_height
= height
;
140 M_IMGDATA
->m_ok
= TRUE
;
148 void wxImage::Destroy()
153 wxImage
wxImage::Scale( int width
, int height
) const
157 wxCHECK_MSG( Ok(), image
, wxT("invalid image") );
159 wxCHECK_MSG( (width
> 0) && (height
> 0), image
, wxT("invalid image size") );
161 image
.Create( width
, height
);
163 char unsigned *data
= image
.GetData();
165 wxCHECK_MSG( data
, image
, wxT("unable to create image") );
167 if (M_IMGDATA
->m_hasMask
)
168 image
.SetMaskColour( M_IMGDATA
->m_maskRed
, M_IMGDATA
->m_maskGreen
, M_IMGDATA
->m_maskBlue
);
170 long old_height
= M_IMGDATA
->m_height
;
171 long old_width
= M_IMGDATA
->m_width
;
173 char unsigned *source_data
= M_IMGDATA
->m_data
;
174 char unsigned *target_data
= data
;
176 for (long j
= 0; j
< height
; j
++)
178 long y_offset
= (j
* old_height
/ height
) * old_width
;
180 for (long i
= 0; i
< width
; i
++)
183 source_data
+ 3*(y_offset
+ ((i
* old_width
)/ width
)),
192 wxImage
wxImage::GetSubImage( const wxRect
&rect
) const
196 wxCHECK_MSG( Ok(), image
, wxT("invalid image") );
198 wxCHECK_MSG( (rect
.GetLeft()>=0) && (rect
.GetTop()>=0) && (rect
.GetRight()<=GetWidth()) && (rect
.GetBottom()<=GetHeight()),
199 image
, wxT("invalid subimage size") );
201 int subwidth
=rect
.GetWidth();
202 const int subheight
=rect
.GetHeight();
204 image
.Create( subwidth
, subheight
);
206 char unsigned *subdata
= image
.GetData(), *data
=GetData();
208 wxCHECK_MSG( subdata
, image
, wxT("unable to create image") );
210 if (M_IMGDATA
->m_hasMask
)
211 image
.SetMaskColour( M_IMGDATA
->m_maskRed
, M_IMGDATA
->m_maskGreen
, M_IMGDATA
->m_maskBlue
);
213 const int subleft
=3*rect
.GetLeft();
214 const int width
=3*GetWidth();
217 data
+=rect
.GetTop()*width
+subleft
;
219 for (long j
= 0; j
< subheight
; ++j
)
221 memcpy( subdata
, data
, subwidth
);
229 void wxImage::SetRGB( int x
, int y
, unsigned char r
, unsigned char g
, unsigned char b
)
231 wxCHECK_RET( Ok(), wxT("invalid image") );
233 int w
= M_IMGDATA
->m_width
;
234 int h
= M_IMGDATA
->m_height
;
236 wxCHECK_RET( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), wxT("invalid image index") );
238 long pos
= (y
* w
+ x
) * 3;
240 M_IMGDATA
->m_data
[ pos
] = r
;
241 M_IMGDATA
->m_data
[ pos
+1 ] = g
;
242 M_IMGDATA
->m_data
[ pos
+2 ] = b
;
245 unsigned char wxImage::GetRed( int x
, int y
)
247 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
249 int w
= M_IMGDATA
->m_width
;
250 int h
= M_IMGDATA
->m_height
;
252 wxCHECK_MSG( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), 0, wxT("invalid image index") );
254 long pos
= (y
* w
+ x
) * 3;
256 return M_IMGDATA
->m_data
[pos
];
259 unsigned char wxImage::GetGreen( int x
, int y
)
261 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
263 int w
= M_IMGDATA
->m_width
;
264 int h
= M_IMGDATA
->m_height
;
266 wxCHECK_MSG( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), 0, wxT("invalid image index") );
268 long pos
= (y
* w
+ x
) * 3;
270 return M_IMGDATA
->m_data
[pos
+1];
273 unsigned char wxImage::GetBlue( int x
, int y
)
275 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
277 int w
= M_IMGDATA
->m_width
;
278 int h
= M_IMGDATA
->m_height
;
280 wxCHECK_MSG( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), 0, wxT("invalid image index") );
282 long pos
= (y
* w
+ x
) * 3;
284 return M_IMGDATA
->m_data
[pos
+2];
287 bool wxImage::Ok() const
289 return (M_IMGDATA
&& M_IMGDATA
->m_ok
);
292 char unsigned *wxImage::GetData() const
294 wxCHECK_MSG( Ok(), (char unsigned *)NULL
, wxT("invalid image") );
296 return M_IMGDATA
->m_data
;
299 void wxImage::SetData( char unsigned *data
)
301 wxCHECK_RET( Ok(), wxT("invalid image") );
303 wxImageRefData
*newRefData
= new wxImageRefData();
305 newRefData
->m_width
= M_IMGDATA
->m_width
;
306 newRefData
->m_height
= M_IMGDATA
->m_height
;
307 newRefData
->m_data
= data
;
308 newRefData
->m_ok
= TRUE
;
309 newRefData
->m_maskRed
= M_IMGDATA
->m_maskRed
;
310 newRefData
->m_maskGreen
= M_IMGDATA
->m_maskGreen
;
311 newRefData
->m_maskBlue
= M_IMGDATA
->m_maskBlue
;
312 newRefData
->m_hasMask
= M_IMGDATA
->m_hasMask
;
316 m_refData
= newRefData
;
319 void wxImage::SetMaskColour( unsigned char r
, unsigned char g
, unsigned char b
)
321 wxCHECK_RET( Ok(), wxT("invalid image") );
323 M_IMGDATA
->m_maskRed
= r
;
324 M_IMGDATA
->m_maskGreen
= g
;
325 M_IMGDATA
->m_maskBlue
= b
;
326 M_IMGDATA
->m_hasMask
= TRUE
;
329 unsigned char wxImage::GetMaskRed() const
331 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
333 return M_IMGDATA
->m_maskRed
;
336 unsigned char wxImage::GetMaskGreen() const
338 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
340 return M_IMGDATA
->m_maskGreen
;
343 unsigned char wxImage::GetMaskBlue() const
345 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
347 return M_IMGDATA
->m_maskBlue
;
350 void wxImage::SetMask( bool mask
)
352 wxCHECK_RET( Ok(), wxT("invalid image") );
354 M_IMGDATA
->m_hasMask
= mask
;
357 bool wxImage::HasMask() const
359 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid image") );
361 return M_IMGDATA
->m_hasMask
;
364 int wxImage::GetWidth() const
366 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
368 return M_IMGDATA
->m_width
;
371 int wxImage::GetHeight() const
373 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
375 return M_IMGDATA
->m_height
;
378 bool wxImage::LoadFile( const wxString
& filename
, long type
)
381 if (wxFileExists(filename
))
383 wxFileInputStream
stream(filename
);
384 wxBufferedInputStream
bstream( stream
);
385 return LoadFile(bstream
, type
);
389 wxLogError( _("Can't load image from file '%s': file does not exist."), filename
.c_str() );
393 #else // !wxUSE_STREAMS
395 #endif // wxUSE_STREAMS
398 bool wxImage::LoadFile( const wxString
& filename
, const wxString
& mimetype
)
401 if (wxFileExists(filename
))
403 wxFileInputStream
stream(filename
);
404 wxBufferedInputStream
bstream( stream
);
405 return LoadFile(bstream
, mimetype
);
409 wxLogError( _("Can't load image from file '%s': file does not exist."), filename
.c_str() );
413 #else // !wxUSE_STREAMS
415 #endif // wxUSE_STREAMS
418 bool wxImage::SaveFile( const wxString
& filename
, int type
)
421 wxFileOutputStream
stream(filename
);
423 if ( stream
.LastError() == wxStream_NOERROR
)
425 wxBufferedOutputStream
bstream( stream
);
426 return SaveFile(bstream
, type
);
429 #endif // wxUSE_STREAMS
433 bool wxImage::SaveFile( const wxString
& filename
, const wxString
& mimetype
)
436 wxFileOutputStream
stream(filename
);
438 if ( stream
.LastError() == wxStream_NOERROR
)
440 wxBufferedOutputStream
bstream( stream
);
441 return SaveFile(bstream
, mimetype
);
444 #endif // wxUSE_STREAMS
448 bool wxImage::CanRead( const wxString
&name
)
451 wxFileInputStream
stream(name
);
452 return CanRead(stream
);
460 bool wxImage::CanRead( wxInputStream
&stream
)
462 wxList
&list
=GetHandlers();
464 for ( wxList::Node
*node
= list
.GetFirst(); node
; node
= node
->GetNext() )
466 wxImageHandler
*handler
=(wxImageHandler
*)node
->GetData();
467 if (handler
->CanRead( stream
))
474 bool wxImage::LoadFile( wxInputStream
& stream
, long type
)
478 m_refData
= new wxImageRefData
;
480 wxImageHandler
*handler
;
482 if (type
==wxBITMAP_TYPE_ANY
)
484 wxList
&list
=GetHandlers();
486 for ( wxList::Node
*node
= list
.GetFirst(); node
; node
= node
->GetNext() )
488 handler
=(wxImageHandler
*)node
->GetData();
489 if (handler
->CanRead( stream
))
490 return handler
->LoadFile( this, stream
);
494 wxLogWarning( _("No handler found for image type.") );
498 handler
= FindHandler(type
);
502 wxLogWarning( _("No image handler for type %d defined."), type
);
507 return handler
->LoadFile( this, stream
);
510 bool wxImage::LoadFile( wxInputStream
& stream
, const wxString
& mimetype
)
514 m_refData
= new wxImageRefData
;
516 wxImageHandler
*handler
= FindHandlerMime(mimetype
);
520 wxLogWarning( _("No image handler for type %s defined."), mimetype
.GetData() );
525 return handler
->LoadFile( this, stream
);
528 bool wxImage::SaveFile( wxOutputStream
& stream
, int type
)
530 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid image") );
532 wxImageHandler
*handler
= FindHandler(type
);
536 wxLogWarning( _("No image handler for type %d defined."), type
);
541 return handler
->SaveFile( this, stream
);
544 bool wxImage::SaveFile( wxOutputStream
& stream
, const wxString
& mimetype
)
546 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid image") );
548 wxImageHandler
*handler
= FindHandlerMime(mimetype
);
552 wxLogWarning( _("No image handler for type %s defined."), mimetype
.GetData() );
557 return handler
->SaveFile( this, stream
);
559 #endif // wxUSE_STREAMS
561 void wxImage::AddHandler( wxImageHandler
*handler
)
563 // make sure that the memory will be freed at the program end
564 sm_handlers
.DeleteContents(TRUE
);
566 sm_handlers
.Append( handler
);
569 void wxImage::InsertHandler( wxImageHandler
*handler
)
571 // make sure that the memory will be freed at the program end
572 sm_handlers
.DeleteContents(TRUE
);
574 sm_handlers
.Insert( handler
);
577 bool wxImage::RemoveHandler( const wxString
& name
)
579 wxImageHandler
*handler
= FindHandler(name
);
582 sm_handlers
.DeleteObject(handler
);
589 wxImageHandler
*wxImage::FindHandler( const wxString
& name
)
591 wxNode
*node
= sm_handlers
.First();
594 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
595 if (handler
->GetName().Cmp(name
) == 0) return handler
;
599 return (wxImageHandler
*)NULL
;
602 wxImageHandler
*wxImage::FindHandler( const wxString
& extension
, long bitmapType
)
604 wxNode
*node
= sm_handlers
.First();
607 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
608 if ( (handler
->GetExtension().Cmp(extension
) == 0) &&
609 (bitmapType
== -1 || handler
->GetType() == bitmapType
) )
613 return (wxImageHandler
*)NULL
;
616 wxImageHandler
*wxImage::FindHandler( long bitmapType
)
618 wxNode
*node
= sm_handlers
.First();
621 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
622 if (handler
->GetType() == bitmapType
) return handler
;
628 wxImageHandler
*wxImage::FindHandlerMime( const wxString
& mimetype
)
630 wxNode
*node
= sm_handlers
.First();
633 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
634 if (handler
->GetMimeType().IsSameAs(mimetype
, FALSE
)) return handler
;
640 void wxImage::InitStandardHandlers()
642 AddHandler( new wxBMPHandler
);
645 void wxImage::CleanUpHandlers()
647 wxNode
*node
= sm_handlers
.First();
650 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
651 wxNode
*next
= node
->Next();
658 //-----------------------------------------------------------------------------
660 //-----------------------------------------------------------------------------
662 #if !USE_SHARED_LIBRARIES
663 IMPLEMENT_ABSTRACT_CLASS(wxImageHandler
,wxObject
)
667 bool wxImageHandler::LoadFile( wxImage
*WXUNUSED(image
), wxInputStream
& WXUNUSED(stream
), bool WXUNUSED(verbose
), int WXUNUSED(index
) )
672 bool wxImageHandler::SaveFile( wxImage
*WXUNUSED(image
), wxOutputStream
& WXUNUSED(stream
), bool WXUNUSED(verbose
) )
677 int wxImageHandler::GetImageCount( wxInputStream
& WXUNUSED(stream
) )
682 bool wxImageHandler::CanRead( const wxString
& name
)
684 if (wxFileExists(name
))
686 wxFileInputStream
stream(name
);
687 return CanRead(stream
);
691 wxLogError( _("Can't check image format of file '%s': file does not exist."), name
.c_str() );
698 #endif // wxUSE_STREAMS
700 //-----------------------------------------------------------------------------
701 // MSW conversion routines
702 //-----------------------------------------------------------------------------
706 wxBitmap
wxImage::ConvertToBitmap() const
711 // sizeLimit is the MS upper limit for the DIB size
713 int sizeLimit
= 1024*768*3;
715 int sizeLimit
= 0x7fff ;
718 // width and height of the device-dependent bitmap
719 int width
= GetWidth();
720 int bmpHeight
= GetHeight();
722 // calc the number of bytes per scanline and padding
723 int bytePerLine
= width
*3;
724 int sizeDWORD
= sizeof( DWORD
);
725 int lineBoundary
= bytePerLine
% sizeDWORD
;
727 if( lineBoundary
> 0 )
729 padding
= sizeDWORD
- lineBoundary
;
730 bytePerLine
+= padding
;
732 // calc the number of DIBs and heights of DIBs
735 int height
= sizeLimit
/bytePerLine
;
736 if( height
>= bmpHeight
)
740 numDIB
= bmpHeight
/ height
;
741 hRemain
= bmpHeight
% height
;
742 if( hRemain
>0 ) numDIB
++;
745 // set bitmap parameters
747 wxCHECK_MSG( Ok(), bitmap
, wxT("invalid image") );
748 bitmap
.SetWidth( width
);
749 bitmap
.SetHeight( bmpHeight
);
750 bitmap
.SetDepth( wxDisplayDepth() );
752 // create a DIB header
753 int headersize
= sizeof(BITMAPINFOHEADER
);
754 LPBITMAPINFO lpDIBh
= (BITMAPINFO
*) malloc( headersize
);
755 wxCHECK_MSG( lpDIBh
, bitmap
, wxT("could not allocate memory for DIB header") );
756 // Fill in the DIB header
757 lpDIBh
->bmiHeader
.biSize
= headersize
;
758 lpDIBh
->bmiHeader
.biWidth
= (DWORD
)width
;
759 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
760 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
761 // the general formula for biSizeImage:
762 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
763 lpDIBh
->bmiHeader
.biPlanes
= 1;
764 lpDIBh
->bmiHeader
.biBitCount
= 24;
765 lpDIBh
->bmiHeader
.biCompression
= BI_RGB
;
766 lpDIBh
->bmiHeader
.biClrUsed
= 0;
767 // These seem not really needed for our purpose here.
768 lpDIBh
->bmiHeader
.biClrImportant
= 0;
769 lpDIBh
->bmiHeader
.biXPelsPerMeter
= 0;
770 lpDIBh
->bmiHeader
.biYPelsPerMeter
= 0;
771 // memory for DIB data
772 unsigned char *lpBits
;
773 lpBits
= (unsigned char *)malloc( lpDIBh
->bmiHeader
.biSizeImage
);
776 wxFAIL_MSG( wxT("could not allocate memory for DIB") );
781 // create and set the device-dependent bitmap
782 HDC hdc
= ::GetDC(NULL
);
783 HDC memdc
= ::CreateCompatibleDC( hdc
);
785 hbitmap
= ::CreateCompatibleBitmap( hdc
, width
, bmpHeight
);
786 ::SelectObject( memdc
, hbitmap
);
788 // copy image data into DIB data and then into DDB (in a loop)
789 unsigned char *data
= GetData();
792 unsigned char *ptdata
= data
;
793 unsigned char *ptbits
;
795 for( n
=0; n
<numDIB
; n
++ )
797 if( numDIB
> 1 && n
== numDIB
-1 && hRemain
> 0 )
799 // redefine height and size of the (possibly) last smaller DIB
800 // memory is not reallocated
802 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
803 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
807 for( j
=0; j
<height
; j
++ )
809 for( i
=0; i
<width
; i
++ )
811 *(ptbits
++) = *(ptdata
+2);
812 *(ptbits
++) = *(ptdata
+1);
813 *(ptbits
++) = *(ptdata
);
816 for( i
=0; i
< padding
; i
++ ) *(ptbits
++) = 0;
818 ::StretchDIBits( memdc
, 0, origin
, width
, height
,\
819 0, 0, width
, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
, SRCCOPY
);
821 // if numDIB = 1, lines below can also be used
822 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
823 // The above line is equivalent to the following two lines.
824 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
825 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
826 // or the following lines
827 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
828 // HDC memdc = ::CreateCompatibleDC( hdc );
829 // ::SelectObject( memdc, hbitmap);
830 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
831 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
832 // ::SelectObject( memdc, 0 );
833 // ::DeleteDC( memdc );
835 bitmap
.SetHBITMAP( (WXHBITMAP
) hbitmap
);
837 // similarly, created an mono-bitmap for the possible mask
840 hbitmap
= ::CreateBitmap( (WORD
)width
, (WORD
)bmpHeight
, 1, 1, NULL
);
841 ::SelectObject( memdc
, hbitmap
);
842 if( numDIB
== 1 ) height
= bmpHeight
;
843 else height
= sizeLimit
/bytePerLine
;
844 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
845 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
847 unsigned char r
= GetMaskRed();
848 unsigned char g
= GetMaskGreen();
849 unsigned char b
= GetMaskBlue();
850 unsigned char zero
= 0, one
= 255;
852 for( n
=0; n
<numDIB
; n
++ )
854 if( numDIB
> 1 && n
== numDIB
- 1 && hRemain
> 0 )
856 // redefine height and size of the (possibly) last smaller DIB
857 // memory is not reallocated
859 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
860 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
863 for( int j
=0; j
<height
; j
++ )
865 for(i
=0; i
<width
; i
++ )
867 if( (*(ptdata
++)!=r
) | (*(ptdata
++)!=g
) | (*(ptdata
++)!=b
) )
880 for( i
=0; i
< padding
; i
++ ) *(ptbits
++) = zero
;
882 ::StretchDIBits( memdc
, 0, origin
, width
, height
,\
883 0, 0, width
, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
, SRCCOPY
);
886 // create a wxMask object
887 wxMask
*mask
= new wxMask();
888 mask
->SetMaskBitmap( (WXHBITMAP
) hbitmap
);
889 bitmap
.SetMask( mask
);
890 // It will be deleted when the wxBitmap object is deleted (as of 01/1999)
891 /* The following can also be used but is slow to run
892 wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
893 wxMask *mask = new wxMask( bitmap, colour );
894 bitmap.SetMask( mask );
898 // free allocated resources
899 ::SelectObject( memdc
, 0 );
901 ::ReleaseDC(NULL
, hdc
);
905 #if WXWIN_COMPATIBILITY_2
906 // check the wxBitmap object
907 bitmap
.GetBitmapData()->SetOk();
908 #endif // WXWIN_COMPATIBILITY_2
913 wxImage::wxImage( const wxBitmap
&bitmap
)
918 wxFAIL_MSG( wxT("invalid bitmap") );
922 // create an wxImage object
923 int width
= bitmap
.GetWidth();
924 int height
= bitmap
.GetHeight();
925 Create( width
, height
);
926 unsigned char *data
= GetData();
929 wxFAIL_MSG( wxT("could not allocate data for image") );
933 // calc the number of bytes per scanline and padding in the DIB
934 int bytePerLine
= width
*3;
935 int sizeDWORD
= sizeof( DWORD
);
936 int lineBoundary
= bytePerLine
% sizeDWORD
;
938 if( lineBoundary
> 0 )
940 padding
= sizeDWORD
- lineBoundary
;
941 bytePerLine
+= padding
;
944 // create a DIB header
945 int headersize
= sizeof(BITMAPINFOHEADER
);
946 LPBITMAPINFO lpDIBh
= (BITMAPINFO
*) malloc( headersize
);
949 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
953 // Fill in the DIB header
954 lpDIBh
->bmiHeader
.biSize
= headersize
;
955 lpDIBh
->bmiHeader
.biWidth
= width
;
956 lpDIBh
->bmiHeader
.biHeight
= -height
;
957 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
* height
;
958 lpDIBh
->bmiHeader
.biPlanes
= 1;
959 lpDIBh
->bmiHeader
.biBitCount
= 24;
960 lpDIBh
->bmiHeader
.biCompression
= BI_RGB
;
961 lpDIBh
->bmiHeader
.biClrUsed
= 0;
962 // These seem not really needed for our purpose here.
963 lpDIBh
->bmiHeader
.biClrImportant
= 0;
964 lpDIBh
->bmiHeader
.biXPelsPerMeter
= 0;
965 lpDIBh
->bmiHeader
.biYPelsPerMeter
= 0;
966 // memory for DIB data
967 unsigned char *lpBits
;
968 lpBits
= (unsigned char *) malloc( lpDIBh
->bmiHeader
.biSizeImage
);
971 wxFAIL_MSG( wxT("could not allocate data for DIB") );
977 // copy data from the device-dependent bitmap to the DIB
978 HDC hdc
= ::GetDC(NULL
);
980 hbitmap
= (HBITMAP
) bitmap
.GetHBITMAP();
981 ::GetDIBits( hdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
983 // copy DIB data into the wxImage object
985 unsigned char *ptdata
= data
;
986 unsigned char *ptbits
= lpBits
;
987 for( i
=0; i
<height
; i
++ )
989 for( j
=0; j
<width
; j
++ )
991 *(ptdata
++) = *(ptbits
+2);
992 *(ptdata
++) = *(ptbits
+1);
993 *(ptdata
++) = *(ptbits
);
999 // similarly, set data according to the possible mask bitmap
1000 if( bitmap
.GetMask() && bitmap
.GetMask()->GetMaskBitmap() )
1002 hbitmap
= (HBITMAP
) bitmap
.GetMask()->GetMaskBitmap();
1003 // memory DC created, color set, data copied, and memory DC deleted
1004 HDC memdc
= ::CreateCompatibleDC( hdc
);
1005 ::SetTextColor( memdc
, RGB( 0, 0, 0 ) );
1006 ::SetBkColor( memdc
, RGB( 255, 255, 255 ) );
1007 ::GetDIBits( memdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
1008 ::DeleteDC( memdc
);
1009 // background color set to RGB(16,16,16) in consistent with wxGTK
1010 unsigned char r
=16, g
=16, b
=16;
1013 for( i
=0; i
<height
; i
++ )
1015 for( j
=0; j
<width
; j
++ )
1029 SetMaskColour( r
, g
, b
);
1036 // free allocated resources
1037 ::ReleaseDC(NULL
, hdc
);
1046 #include <PictUtils.h>
1048 extern CTabHandle
wxMacCreateColorTable( int numColors
) ;
1049 extern void wxMacDestroyColorTable( CTabHandle colors
) ;
1050 extern void wxMacSetColorTableEntry( CTabHandle newColors
, int index
, int red
, int green
, int blue
) ;
1051 extern GWorldPtr
wxMacCreateGWorld( int height
, int width
, int depth
) ;
1052 extern void wxMacDestroyGWorld( GWorldPtr gw
) ;
1054 wxBitmap
wxImage::ConvertToBitmap() const
1056 // width and height of the device-dependent bitmap
1057 int width
= GetWidth();
1058 int height
= GetHeight();
1062 wxBitmap
bitmap( width
, height
, wxDisplayDepth() ) ;
1069 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1071 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1073 wxMask *mask = new wxMask();
1074 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1076 bitmap.SetMask( mask );
1082 int r_mask
= GetMaskRed();
1083 int g_mask
= GetMaskGreen();
1084 int b_mask
= GetMaskBlue();
1087 GDHandle origDevice
;
1089 GetGWorld( &origPort
, &origDevice
) ;
1090 SetGWorld( bitmap
.GetHBITMAP() , NULL
) ;
1092 register unsigned char* data
= GetData();
1095 for (int y
= 0; y
< height
; y
++)
1098 unsigned char lastr
= 0 ;
1099 unsigned char lastg
= 0 ;
1100 unsigned char lastb
= 0 ;
1101 RGBColor lastcolor
;
1104 for (int x
= 0; x
< width
; x
++)
1106 unsigned char r
= data
[index
++];
1107 unsigned char g
= data
[index
++];
1108 unsigned char b
= data
[index
++];
1110 if ( r
!= lastr
|| g
!= lastg
|| b
!= lastb
)
1112 lastcolor
.red
= ( lastr
<< 8 ) + lastr
;
1113 lastcolor
.green
= ( lastg
<< 8 ) + lastg
;
1114 lastcolor
.blue
= ( lastb
<< 8 ) + lastb
;
1115 RGBForeColor( &lastcolor
) ;
1122 lastcolor
.red
= ( lastr
<< 8 ) + lastr
;
1123 lastcolor
.green
= ( lastg
<< 8 ) + lastg
;
1124 lastcolor
.blue
= ( lastb
<< 8 ) + lastb
;
1125 RGBForeColor( &lastcolor
) ;
1126 LineTo( width
- 1 , y
) ;
1128 for (int x
= 0; x
< width
; x
++)
1130 unsigned char r
= data
[index
++];
1131 unsigned char g
= data
[index
++];
1132 unsigned char b
= data
[index
++];
1134 color
.red
= ( r
<< 8 ) + r
;
1135 color
.green
= ( g
<< 8 ) + g
;
1136 color
.blue
= ( b
<< 8 ) + b
;
1137 SetCPixel( x
, y
, &color
) ;
1142 SetGWorld( origPort
, origDevice
) ;
1148 wxImage::wxImage( const wxBitmap
&bitmap
)
1153 wxFAIL_MSG( "invalid bitmap" );
1157 // create an wxImage object
1158 int width
= bitmap
.GetWidth();
1159 int height
= bitmap
.GetHeight();
1160 Create( width
, height
);
1162 unsigned char *data = GetData();
1165 wxFAIL_MSG( "could not allocate data for image" );
1169 // calc the number of bytes per scanline and padding in the DIB
1170 int bytePerLine = width*3;
1171 int sizeDWORD = sizeof( DWORD );
1172 div_t lineBoundary = div( bytePerLine, sizeDWORD );
1174 if( lineBoundary.rem > 0 )
1176 padding = sizeDWORD - lineBoundary.rem;
1177 bytePerLine += padding;
1180 // create a DIB header
1181 int headersize = sizeof(BITMAPINFOHEADER);
1182 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
1185 wxFAIL_MSG( "could not allocate data for DIB header" );
1189 // Fill in the DIB header
1190 lpDIBh->bmiHeader.biSize = headersize;
1191 lpDIBh->bmiHeader.biWidth = width;
1192 lpDIBh->bmiHeader.biHeight = -height;
1193 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
1194 lpDIBh->bmiHeader.biPlanes = 1;
1195 lpDIBh->bmiHeader.biBitCount = 24;
1196 lpDIBh->bmiHeader.biCompression = BI_RGB;
1197 lpDIBh->bmiHeader.biClrUsed = 0;
1198 // These seem not really needed for our purpose here.
1199 lpDIBh->bmiHeader.biClrImportant = 0;
1200 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
1201 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
1202 // memory for DIB data
1203 unsigned char *lpBits;
1204 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
1207 wxFAIL_MSG( "could not allocate data for DIB" );
1213 // copy data from the device-dependent bitmap to the DIB
1214 HDC hdc = ::GetDC(NULL);
1216 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
1217 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1219 // copy DIB data into the wxImage object
1221 unsigned char *ptdata = data;
1222 unsigned char *ptbits = lpBits;
1223 for( i=0; i<height; i++ )
1225 for( j=0; j<width; j++ )
1227 *(ptdata++) = *(ptbits+2);
1228 *(ptdata++) = *(ptbits+1);
1229 *(ptdata++) = *(ptbits );
1235 // similarly, set data according to the possible mask bitmap
1236 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
1238 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
1239 // memory DC created, color set, data copied, and memory DC deleted
1240 HDC memdc = ::CreateCompatibleDC( hdc );
1241 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
1242 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
1243 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1244 ::DeleteDC( memdc );
1245 // background color set to RGB(16,16,16) in consistent with wxGTK
1246 unsigned char r=16, g=16, b=16;
1249 for( i=0; i<height; i++ )
1251 for( j=0; j<width; j++ )
1265 SetMaskColour( r, g, b );
1272 // free allocated resources
1273 ::ReleaseDC(NULL, hdc);
1281 //-----------------------------------------------------------------------------
1282 // GTK conversion routines
1283 //-----------------------------------------------------------------------------
1287 #include <gtk/gtk.h>
1288 #include <gdk/gdk.h>
1289 #include <gdk/gdkx.h>
1291 #if (GTK_MINOR_VERSION > 0)
1292 #include <gdk/gdkrgb.h>
1295 wxBitmap
wxImage::ConvertToBitmap() const
1299 wxCHECK_MSG( Ok(), bitmap
, wxT("invalid image") );
1301 int width
= GetWidth();
1302 int height
= GetHeight();
1304 bitmap
.SetHeight( height
);
1305 bitmap
.SetWidth( width
);
1307 bitmap
.SetPixmap( gdk_pixmap_new( (GdkWindow
*)&gdk_root_parent
, width
, height
, -1 ) );
1311 GdkVisual
*visual
= gdk_window_get_visual( bitmap
.GetPixmap() );
1312 if (visual
== NULL
) visual
= gdk_visual_get_system();
1313 int bpp
= visual
->depth
;
1315 bitmap
.SetDepth( bpp
);
1317 if ((bpp
== 16) && (visual
->red_mask
!= 0xf800)) bpp
= 15;
1318 if (bpp
< 8) bpp
= 8;
1320 #if (GTK_MINOR_VERSION > 0)
1322 if (!HasMask() && (bpp
> 8))
1324 static bool s_hasInitialized
= FALSE
;
1326 if (!s_hasInitialized
)
1329 s_hasInitialized
= TRUE
;
1332 GdkGC
*gc
= gdk_gc_new( bitmap
.GetPixmap() );
1334 gdk_draw_rgb_image( bitmap
.GetPixmap(),
1338 GDK_RGB_DITHER_NONE
,
1349 // Create picture image
1351 GdkImage
*data_image
=
1352 gdk_image_new( GDK_IMAGE_FASTEST
, gdk_visual_get_system(), width
, height
);
1354 // Create mask image
1356 GdkImage
*mask_image
= (GdkImage
*) NULL
;
1360 unsigned char *mask_data
= (unsigned char*)malloc( ((width
>> 3)+8) * height
);
1362 mask_image
= gdk_image_new_bitmap( gdk_visual_get_system(), mask_data
, width
, height
);
1364 wxMask
*mask
= new wxMask();
1365 mask
->m_bitmap
= gdk_pixmap_new( (GdkWindow
*)&gdk_root_parent
, width
, height
, 1 );
1367 bitmap
.SetMask( mask
);
1372 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
1373 byte_order b_o
= RGB
;
1377 GdkVisual
*visual
= gdk_visual_get_system();
1378 if ((visual
->red_mask
> visual
->green_mask
) && (visual
->green_mask
> visual
->blue_mask
)) b_o
= RGB
;
1379 else if ((visual
->red_mask
> visual
->blue_mask
) && (visual
->blue_mask
> visual
->green_mask
)) b_o
= RGB
;
1380 else if ((visual
->blue_mask
> visual
->red_mask
) && (visual
->red_mask
> visual
->green_mask
)) b_o
= BRG
;
1381 else if ((visual
->blue_mask
> visual
->green_mask
) && (visual
->green_mask
> visual
->red_mask
)) b_o
= BGR
;
1382 else if ((visual
->green_mask
> visual
->red_mask
) && (visual
->red_mask
> visual
->blue_mask
)) b_o
= GRB
;
1383 else if ((visual
->green_mask
> visual
->blue_mask
) && (visual
->blue_mask
> visual
->red_mask
)) b_o
= GBR
;
1386 int r_mask
= GetMaskRed();
1387 int g_mask
= GetMaskGreen();
1388 int b_mask
= GetMaskBlue();
1390 unsigned char* data
= GetData();
1393 for (int y
= 0; y
< height
; y
++)
1395 for (int x
= 0; x
< width
; x
++)
1397 int r
= data
[index
];
1399 int g
= data
[index
];
1401 int b
= data
[index
];
1406 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
1407 gdk_image_put_pixel( mask_image
, x
, y
, 1 );
1409 gdk_image_put_pixel( mask_image
, x
, y
, 0 );
1414 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
1415 gdk_image_put_pixel( mask_image
, x
, y
, 1 );
1417 gdk_image_put_pixel( mask_image
, x
, y
, 0 );
1425 if (wxTheApp
->m_colorCube
)
1427 pixel
= wxTheApp
->m_colorCube
[ ((r
& 0xf8) << 7) + ((g
& 0xf8) << 2) + ((b
& 0xf8) >> 3) ];
1431 GdkColormap
*cmap
= gtk_widget_get_default_colormap();
1432 GdkColor
*colors
= cmap
->colors
;
1433 int max
= 3 * (65536);
1435 for (int i
= 0; i
< cmap
->size
; i
++)
1437 int rdiff
= (r
<< 8) - colors
[i
].red
;
1438 int gdiff
= (g
<< 8) - colors
[i
].green
;
1439 int bdiff
= (b
<< 8) - colors
[i
].blue
;
1440 int sum
= ABS (rdiff
) + ABS (gdiff
) + ABS (bdiff
);
1441 if (sum
< max
) { pixel
= i
; max
= sum
; }
1445 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1451 guint32 pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
1452 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1457 guint32 pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
1458 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1467 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
1468 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
1469 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
1470 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
1471 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
1472 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
1474 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1483 GdkGC
*data_gc
= gdk_gc_new( bitmap
.GetPixmap() );
1485 gdk_draw_image( bitmap
.GetPixmap(), data_gc
, data_image
, 0, 0, 0, 0, width
, height
);
1487 gdk_image_destroy( data_image
);
1488 gdk_gc_unref( data_gc
);
1494 GdkGC
*mask_gc
= gdk_gc_new( bitmap
.GetMask()->GetBitmap() );
1496 gdk_draw_image( bitmap
.GetMask()->GetBitmap(), mask_gc
, mask_image
, 0, 0, 0, 0, width
, height
);
1498 gdk_image_destroy( mask_image
);
1499 gdk_gc_unref( mask_gc
);
1505 wxImage::wxImage( const wxBitmap
&bitmap
)
1507 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
1509 GdkImage
*gdk_image
= (GdkImage
*) NULL
;
1510 if (bitmap
.GetPixmap())
1512 gdk_image
= gdk_image_get( bitmap
.GetPixmap(),
1514 bitmap
.GetWidth(), bitmap
.GetHeight() );
1516 if (bitmap
.GetBitmap())
1518 gdk_image
= gdk_image_get( bitmap
.GetBitmap(),
1520 bitmap
.GetWidth(), bitmap
.GetHeight() );
1523 wxFAIL_MSG( wxT("Ill-formed bitmap") );
1526 wxCHECK_RET( gdk_image
, wxT("couldn't create image") );
1528 Create( bitmap
.GetWidth(), bitmap
.GetHeight() );
1529 char unsigned *data
= GetData();
1533 gdk_image_destroy( gdk_image
);
1534 wxFAIL_MSG( wxT("couldn't create image") );
1538 GdkImage
*gdk_image_mask
= (GdkImage
*) NULL
;
1539 if (bitmap
.GetMask())
1541 gdk_image_mask
= gdk_image_get( bitmap
.GetMask()->GetBitmap(),
1543 bitmap
.GetWidth(), bitmap
.GetHeight() );
1545 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1548 GdkVisual
*visual
= (GdkVisual
*) NULL
;
1549 if (bitmap
.GetPixmap())
1550 visual
= gdk_window_get_visual( bitmap
.GetPixmap() );
1552 visual
= gdk_window_get_visual( bitmap
.GetBitmap() );
1554 if (visual
== NULL
) visual
= gdk_window_get_visual( (GdkWindow
*) &gdk_root_parent
);
1555 int bpp
= visual
->depth
;
1556 if ((bpp
== 16) && (visual
->red_mask
!= 0xf800)) bpp
= 15;
1558 GdkColormap
*cmap
= gtk_widget_get_default_colormap();
1561 for (int j
= 0; j
< bitmap
.GetHeight(); j
++)
1563 for (int i
= 0; i
< bitmap
.GetWidth(); i
++)
1565 wxInt32 pixel
= gdk_image_get_pixel( gdk_image
, i
, j
);
1568 data
[pos
] = cmap
->colors
[pixel
].red
>> 8;
1569 data
[pos
+1] = cmap
->colors
[pixel
].green
>> 8;
1570 data
[pos
+2] = cmap
->colors
[pixel
].blue
>> 8;
1571 } else if (bpp
== 15)
1573 #if (wxBYTE_ORDER == wxBIG_ENDIAN)
1576 data
[pos
] = (pixel
>> 7) & 0xf8;
1577 data
[pos
+1] = (pixel
>> 2) & 0xf8;
1578 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1579 } else if (bpp
== 16)
1581 #if (wxBYTE_ORDER == wxBIG_ENDIAN)
1584 data
[pos
] = (pixel
>> 8) & 0xf8;
1585 data
[pos
+1] = (pixel
>> 3) & 0xfc;
1586 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1589 #if (wxBYTE_ORDER == wxBIG_ENDIAN)
1590 data
[pos
] = (pixel
) & 0xff; // Red
1591 data
[pos
+1] = (pixel
>> 8) & 0xff; // Green
1592 data
[pos
+2] = (pixel
>> 16) & 0xff; // Blue
1594 data
[pos
] = (pixel
>> 16) & 0xff;
1595 data
[pos
+1] = (pixel
>> 8) & 0xff;
1596 data
[pos
+2] = pixel
& 0xff;
1602 int mask_pixel
= gdk_image_get_pixel( gdk_image_mask
, i
, j
);
1603 if (mask_pixel
== 0)
1615 gdk_image_destroy( gdk_image
);
1616 if (gdk_image_mask
) gdk_image_destroy( gdk_image_mask
);
1621 //-----------------------------------------------------------------------------
1622 // Motif conversion routines
1623 //-----------------------------------------------------------------------------
1627 #pragma message disable nosimpint
1631 #pragma message enable nosimpint
1633 #include "wx/utils.h"
1636 wxBitmap
wxImage::ConvertToBitmap() const
1640 wxCHECK_MSG( Ok(), bitmap
, wxT("invalid image") );
1642 int width
= GetWidth();
1643 int height
= GetHeight();
1645 bitmap
.SetHeight( height
);
1646 bitmap
.SetWidth( width
);
1648 Display
*dpy
= (Display
*) wxGetDisplay();
1649 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1650 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1654 XImage
*data_image
= XCreateImage( dpy
, vis
, bpp
, ZPixmap
, 0, 0, width
, height
, 32, 0 );
1655 data_image
->data
= (char*) malloc( data_image
->bytes_per_line
* data_image
->height
);
1657 bitmap
.Create( width
, height
, bpp
);
1662 GdkImage *mask_image = (GdkImage*) NULL;
1666 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1668 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1670 wxMask *mask = new wxMask();
1671 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1673 bitmap.SetMask( mask );
1677 // Retrieve depth info
1679 XVisualInfo vinfo_template
;
1682 vinfo_template
.visual
= vis
;
1683 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1684 vinfo_template
.depth
= bpp
;
1687 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
1689 wxCHECK_MSG( vi
, wxNullBitmap
, wxT("no visual") );
1693 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1694 if (bpp
< 8) bpp
= 8;
1698 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
1699 byte_order b_o
= RGB
;
1703 if ((vi
->red_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->blue_mask
)) b_o
= RGB
;
1704 else if ((vi
->red_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->green_mask
)) b_o
= RGB
;
1705 else if ((vi
->blue_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->green_mask
)) b_o
= BRG
;
1706 else if ((vi
->blue_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->red_mask
)) b_o
= BGR
;
1707 else if ((vi
->green_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->blue_mask
)) b_o
= GRB
;
1708 else if ((vi
->green_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->red_mask
)) b_o
= GBR
;
1712 int r_mask = GetMaskRed();
1713 int g_mask = GetMaskGreen();
1714 int b_mask = GetMaskBlue();
1720 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap( dpy
);
1722 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
1723 XQueryColors( dpy
, cmap
, colors
, 256 );
1726 unsigned char* data
= GetData();
1729 for (int y
= 0; y
< height
; y
++)
1731 for (int x
= 0; x
< width
; x
++)
1733 int r
= data
[index
];
1735 int g
= data
[index
];
1737 int b
= data
[index
];
1743 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1744 gdk_image_put_pixel( mask_image, x, y, 1 );
1746 gdk_image_put_pixel( mask_image, x, y, 0 );
1756 if (wxTheApp->m_colorCube)
1758 pixel = wxTheApp->m_colorCube
1759 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1764 int max
= 3 * (65536);
1765 for (int i
= 0; i
< 256; i
++)
1767 int rdiff
= (r
<< 8) - colors
[i
].red
;
1768 int gdiff
= (g
<< 8) - colors
[i
].green
;
1769 int bdiff
= (b
<< 8) - colors
[i
].blue
;
1770 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
1771 if (sum
< max
) { pixel
= i
; max
= sum
; }
1776 XPutPixel( data_image
, x
, y
, pixel
);
1781 int pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
1782 XPutPixel( data_image
, x
, y
, pixel
);
1787 int pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
1788 XPutPixel( data_image
, x
, y
, pixel
);
1797 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
1798 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
1799 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
1800 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
1801 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
1802 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
1804 XPutPixel( data_image
, x
, y
, pixel
);
1814 gcvalues
.foreground
= BlackPixel( dpy
, DefaultScreen( dpy
) );
1815 GC gc
= XCreateGC( dpy
, RootWindow ( dpy
, DefaultScreen(dpy
) ), GCForeground
, &gcvalues
);
1816 XPutImage( dpy
, (Drawable
)bitmap
.GetPixmap(), gc
, data_image
, 0, 0, 0, 0, width
, height
);
1818 XDestroyImage( data_image
);
1826 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
1828 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
1830 gdk_image_destroy( mask_image );
1831 gdk_gc_unref( mask_gc );
1838 wxImage::wxImage( const wxBitmap
&bitmap
)
1840 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
1842 Display
*dpy
= (Display
*) wxGetDisplay();
1843 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1844 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1846 XImage
*ximage
= XGetImage( dpy
,
1847 (Drawable
)bitmap
.GetPixmap(),
1849 bitmap
.GetWidth(), bitmap
.GetHeight(),
1850 AllPlanes
, ZPixmap
);
1852 wxCHECK_RET( ximage
, wxT("couldn't create image") );
1854 Create( bitmap
.GetWidth(), bitmap
.GetHeight() );
1855 char unsigned *data
= GetData();
1859 XDestroyImage( ximage
);
1860 wxFAIL_MSG( wxT("couldn't create image") );
1865 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1866 if (bitmap.GetMask())
1868 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1870 bitmap.GetWidth(), bitmap.GetHeight() );
1872 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1876 // Retrieve depth info
1878 XVisualInfo vinfo_template
;
1881 vinfo_template
.visual
= vis
;
1882 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1883 vinfo_template
.depth
= bpp
;
1886 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
1888 wxCHECK_RET( vi
, wxT("no visual") );
1890 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1897 Colormap cmap
= (Colormap
)wxTheApp
->GetMainColormap( dpy
);
1899 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
1900 XQueryColors( dpy
, cmap
, colors
, 256 );
1904 for (int j
= 0; j
< bitmap
.GetHeight(); j
++)
1906 for (int i
= 0; i
< bitmap
.GetWidth(); i
++)
1908 int pixel
= XGetPixel( ximage
, i
, j
);
1911 data
[pos
] = colors
[pixel
].red
>> 8;
1912 data
[pos
+1] = colors
[pixel
].green
>> 8;
1913 data
[pos
+2] = colors
[pixel
].blue
>> 8;
1914 } else if (bpp
== 15)
1916 data
[pos
] = (pixel
>> 7) & 0xf8;
1917 data
[pos
+1] = (pixel
>> 2) & 0xf8;
1918 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1919 } else if (bpp
== 16)
1921 data
[pos
] = (pixel
>> 8) & 0xf8;
1922 data
[pos
+1] = (pixel
>> 3) & 0xfc;
1923 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1926 data
[pos
] = (pixel
>> 16) & 0xff;
1927 data
[pos
+1] = (pixel
>> 8) & 0xff;
1928 data
[pos
+2] = pixel
& 0xff;
1934 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1935 if (mask_pixel == 0)
1948 XDestroyImage( ximage
);
1950 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1956 // OS/2 Presentation manager conversion routings
1958 wxBitmap
wxImage::ConvertToBitmap() const
1961 return wxNullBitmap
;
1962 wxBitmap bitmap
; // remove
1965 int sizeLimit = 1024*768*3;
1967 // width and height of the device-dependent bitmap
1968 int width = GetWidth();
1969 int bmpHeight = GetHeight();
1971 // calc the number of bytes per scanline and padding
1972 int bytePerLine = width*3;
1973 int sizeDWORD = sizeof( DWORD );
1974 int lineBoundary = bytePerLine % sizeDWORD;
1976 if( lineBoundary > 0 )
1978 padding = sizeDWORD - lineBoundary;
1979 bytePerLine += padding;
1981 // calc the number of DIBs and heights of DIBs
1984 int height = sizeLimit/bytePerLine;
1985 if( height >= bmpHeight )
1989 numDIB = bmpHeight / height;
1990 hRemain = bmpHeight % height;
1991 if( hRemain >0 ) numDIB++;
1994 // set bitmap parameters
1996 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
1997 bitmap.SetWidth( width );
1998 bitmap.SetHeight( bmpHeight );
1999 bitmap.SetDepth( wxDisplayDepth() );
2001 // create a DIB header
2002 int headersize = sizeof(BITMAPINFOHEADER);
2003 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
2004 wxCHECK_MSG( lpDIBh, bitmap, wxT("could not allocate memory for DIB header") );
2005 // Fill in the DIB header
2006 lpDIBh->bmiHeader.biSize = headersize;
2007 lpDIBh->bmiHeader.biWidth = (DWORD)width;
2008 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2009 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2010 // the general formula for biSizeImage:
2011 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
2012 lpDIBh->bmiHeader.biPlanes = 1;
2013 lpDIBh->bmiHeader.biBitCount = 24;
2014 lpDIBh->bmiHeader.biCompression = BI_RGB;
2015 lpDIBh->bmiHeader.biClrUsed = 0;
2016 // These seem not really needed for our purpose here.
2017 lpDIBh->bmiHeader.biClrImportant = 0;
2018 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2019 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2020 // memory for DIB data
2021 unsigned char *lpBits;
2022 lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
2025 wxFAIL_MSG( wxT("could not allocate memory for DIB") );
2030 // create and set the device-dependent bitmap
2031 HDC hdc = ::GetDC(NULL);
2032 HDC memdc = ::CreateCompatibleDC( hdc );
2034 hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
2035 ::SelectObject( memdc, hbitmap);
2037 // copy image data into DIB data and then into DDB (in a loop)
2038 unsigned char *data = GetData();
2041 unsigned char *ptdata = data;
2042 unsigned char *ptbits;
2044 for( n=0; n<numDIB; n++ )
2046 if( numDIB > 1 && n == numDIB-1 && hRemain > 0 )
2048 // redefine height and size of the (possibly) last smaller DIB
2049 // memory is not reallocated
2051 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2052 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2056 for( j=0; j<height; j++ )
2058 for( i=0; i<width; i++ )
2060 *(ptbits++) = *(ptdata+2);
2061 *(ptbits++) = *(ptdata+1);
2062 *(ptbits++) = *(ptdata );
2065 for( i=0; i< padding; i++ ) *(ptbits++) = 0;
2067 ::StretchDIBits( memdc, 0, origin, width, height,\
2068 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2070 // if numDIB = 1, lines below can also be used
2071 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
2072 // The above line is equivalent to the following two lines.
2073 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2074 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
2075 // or the following lines
2076 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2077 // HDC memdc = ::CreateCompatibleDC( hdc );
2078 // ::SelectObject( memdc, hbitmap);
2079 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
2080 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
2081 // ::SelectObject( memdc, 0 );
2082 // ::DeleteDC( memdc );
2084 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
2086 // similarly, created an mono-bitmap for the possible mask
2089 hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL );
2090 ::SelectObject( memdc, hbitmap);
2091 if( numDIB == 1 ) height = bmpHeight;
2092 else height = sizeLimit/bytePerLine;
2093 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2094 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2096 unsigned char r = GetMaskRed();
2097 unsigned char g = GetMaskGreen();
2098 unsigned char b = GetMaskBlue();
2099 unsigned char zero = 0, one = 255;
2101 for( n=0; n<numDIB; n++ )
2103 if( numDIB > 1 && n == numDIB - 1 && hRemain > 0 )
2105 // redefine height and size of the (possibly) last smaller DIB
2106 // memory is not reallocated
2108 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2109 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2112 for( int j=0; j<height; j++ )
2114 for(i=0; i<width; i++ )
2116 if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
2129 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
2131 ::StretchDIBits( memdc, 0, origin, width, height,\
2132 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2135 // create a wxMask object
2136 wxMask *mask = new wxMask();
2137 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
2138 bitmap.SetMask( mask );
2141 // free allocated resources
2142 ::SelectObject( memdc, 0 );
2143 ::DeleteDC( memdc );
2144 ::ReleaseDC(NULL, hdc);
2148 // check the wxBitmap object
2149 if( bitmap.GetHBITMAP() )
2150 bitmap.SetOk( TRUE );
2152 bitmap.SetOk( FALSE );
2157 wxImage::wxImage( const wxBitmap
&bitmap
)
2162 wxFAIL_MSG( wxT("invalid bitmap") );
2166 // create an wxImage object
2167 int width
= bitmap
.GetWidth();
2168 int height
= bitmap
.GetHeight();
2169 Create( width
, height
);
2170 unsigned char *data
= GetData();
2173 wxFAIL_MSG( wxT("could not allocate data for image") );
2177 // calc the number of bytes per scanline and padding in the DIB
2178 int bytePerLine
= width
*3;
2179 int sizeDWORD
= sizeof( DWORD
);
2180 int lineBoundary
= bytePerLine
% sizeDWORD
;
2182 if( lineBoundary
> 0 )
2184 padding
= sizeDWORD
- lineBoundary
;
2185 bytePerLine
+= padding
;
2189 // create a DIB header
2190 int headersize = sizeof(BITMAPINFOHEADER);
2191 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
2194 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
2198 // Fill in the DIB header
2199 lpDIBh->bmiHeader.biSize = headersize;
2200 lpDIBh->bmiHeader.biWidth = width;
2201 lpDIBh->bmiHeader.biHeight = -height;
2202 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
2203 lpDIBh->bmiHeader.biPlanes = 1;
2204 lpDIBh->bmiHeader.biBitCount = 24;
2205 lpDIBh->bmiHeader.biCompression = BI_RGB;
2206 lpDIBh->bmiHeader.biClrUsed = 0;
2207 // These seem not really needed for our purpose here.
2208 lpDIBh->bmiHeader.biClrImportant = 0;
2209 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2210 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2211 // memory for DIB data
2212 unsigned char *lpBits;
2213 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
2216 wxFAIL_MSG( wxT("could not allocate data for DIB") );
2222 // copy data from the device-dependent bitmap to the DIB
2223 HDC hdc = ::GetDC(NULL);
2225 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
2226 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2228 // copy DIB data into the wxImage object
2230 unsigned char *ptdata = data;
2231 unsigned char *ptbits = lpBits;
2232 for( i=0; i<height; i++ )
2234 for( j=0; j<width; j++ )
2236 *(ptdata++) = *(ptbits+2);
2237 *(ptdata++) = *(ptbits+1);
2238 *(ptdata++) = *(ptbits );
2244 // similarly, set data according to the possible mask bitmap
2245 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
2247 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
2248 // memory DC created, color set, data copied, and memory DC deleted
2249 HDC memdc = ::CreateCompatibleDC( hdc );
2250 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
2251 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
2252 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2253 ::DeleteDC( memdc );
2254 // background color set to RGB(16,16,16) in consistent with wxGTK
2255 unsigned char r=16, g=16, b=16;
2258 for( i=0; i<height; i++ )
2260 for( j=0; j<width; j++ )
2274 SetMaskColour( r, g, b );
2281 // free allocated resources
2282 ::ReleaseDC(NULL, hdc);
2290 // A module to allow wxImage initialization/cleanup
2291 // without calling these functions from app.cpp or from
2292 // the user's application.
2294 class wxImageModule
: public wxModule
2296 DECLARE_DYNAMIC_CLASS(wxImageModule
)
2299 bool OnInit() { wxImage::InitStandardHandlers(); return TRUE
; };
2300 void OnExit() { wxImage::CleanUpHandlers(); };
2303 IMPLEMENT_DYNAMIC_CLASS(wxImageModule
, wxModule
)