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 return LoadFile(stream
, type
);
388 wxLogError( _("Can't load image from file '%s': file does not exist."), filename
.c_str() );
392 #else // !wxUSE_STREAMS
394 #endif // wxUSE_STREAMS
397 bool wxImage::LoadFile( const wxString
& filename
, const wxString
& mimetype
)
400 if (wxFileExists(filename
))
402 wxFileInputStream
stream(filename
);
403 return LoadFile(stream
, 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
)
422 return SaveFile(stream
, type
);
424 #endif // wxUSE_STREAMS
428 bool wxImage::SaveFile( const wxString
& filename
, const wxString
& mimetype
)
431 wxFileOutputStream
stream(filename
);
433 if ( stream
.LastError() == wxStream_NOERROR
)
434 return SaveFile(stream
, mimetype
);
436 #endif // wxUSE_STREAMS
440 bool wxImage::CanRead( const wxString
&name
)
443 wxFileInputStream
stream(name
);
444 return CanRead(stream
);
452 bool wxImage::CanRead( wxInputStream
&stream
)
454 wxList
&list
=GetHandlers();
456 for ( wxList::Node
*node
= list
.GetFirst(); node
; node
= node
->GetNext() )
458 wxImageHandler
*handler
=(wxImageHandler
*)node
->GetData();
459 if (handler
->CanRead( stream
))
466 bool wxImage::LoadFile( wxInputStream
& stream
, long type
)
470 m_refData
= new wxImageRefData
;
472 wxImageHandler
*handler
;
474 if (type
==wxBITMAP_TYPE_ANY
)
476 wxList
&list
=GetHandlers();
478 for ( wxList::Node
*node
= list
.GetFirst(); node
; node
= node
->GetNext() )
480 handler
=(wxImageHandler
*)node
->GetData();
481 if (handler
->CanRead( stream
))
482 return handler
->LoadFile( this, stream
);
486 wxLogWarning( _("No handler found for image type.") );
490 handler
= FindHandler(type
);
494 wxLogWarning( _("No image handler for type %d defined."), type
);
499 return handler
->LoadFile( this, stream
);
502 bool wxImage::LoadFile( wxInputStream
& stream
, const wxString
& mimetype
)
506 m_refData
= new wxImageRefData
;
508 wxImageHandler
*handler
= FindHandlerMime(mimetype
);
512 wxLogWarning( _("No image handler for type %s defined."), mimetype
.GetData() );
517 return handler
->LoadFile( this, stream
);
520 bool wxImage::SaveFile( wxOutputStream
& stream
, int type
)
522 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid image") );
524 wxImageHandler
*handler
= FindHandler(type
);
528 wxLogWarning( _("No image handler for type %d defined."), type
);
533 return handler
->SaveFile( this, stream
);
536 bool wxImage::SaveFile( wxOutputStream
& stream
, const wxString
& mimetype
)
538 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid image") );
540 wxImageHandler
*handler
= FindHandlerMime(mimetype
);
544 wxLogWarning( _("No image handler for type %s defined."), mimetype
.GetData() );
549 return handler
->SaveFile( this, stream
);
551 #endif // wxUSE_STREAMS
553 void wxImage::AddHandler( wxImageHandler
*handler
)
555 // make sure that the memory will be freed at the program end
556 sm_handlers
.DeleteContents(TRUE
);
558 sm_handlers
.Append( handler
);
561 void wxImage::InsertHandler( wxImageHandler
*handler
)
563 // make sure that the memory will be freed at the program end
564 sm_handlers
.DeleteContents(TRUE
);
566 sm_handlers
.Insert( handler
);
569 bool wxImage::RemoveHandler( const wxString
& name
)
571 wxImageHandler
*handler
= FindHandler(name
);
574 sm_handlers
.DeleteObject(handler
);
581 wxImageHandler
*wxImage::FindHandler( const wxString
& name
)
583 wxNode
*node
= sm_handlers
.First();
586 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
587 if (handler
->GetName().Cmp(name
) == 0) return handler
;
591 return (wxImageHandler
*)NULL
;
594 wxImageHandler
*wxImage::FindHandler( const wxString
& extension
, long bitmapType
)
596 wxNode
*node
= sm_handlers
.First();
599 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
600 if ( (handler
->GetExtension().Cmp(extension
) == 0) &&
601 (bitmapType
== -1 || handler
->GetType() == bitmapType
) )
605 return (wxImageHandler
*)NULL
;
608 wxImageHandler
*wxImage::FindHandler( long bitmapType
)
610 wxNode
*node
= sm_handlers
.First();
613 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
614 if (handler
->GetType() == bitmapType
) return handler
;
620 wxImageHandler
*wxImage::FindHandlerMime( const wxString
& mimetype
)
622 wxNode
*node
= sm_handlers
.First();
625 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
626 if (handler
->GetMimeType().IsSameAs(mimetype
, FALSE
)) return handler
;
632 void wxImage::InitStandardHandlers()
634 AddHandler( new wxBMPHandler
);
637 void wxImage::CleanUpHandlers()
639 wxNode
*node
= sm_handlers
.First();
642 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
643 wxNode
*next
= node
->Next();
650 //-----------------------------------------------------------------------------
652 //-----------------------------------------------------------------------------
654 #if !USE_SHARED_LIBRARIES
655 IMPLEMENT_ABSTRACT_CLASS(wxImageHandler
,wxObject
)
659 bool wxImageHandler::LoadFile( wxImage
*WXUNUSED(image
), wxInputStream
& WXUNUSED(stream
), bool WXUNUSED(verbose
), int WXUNUSED(index
) )
664 bool wxImageHandler::SaveFile( wxImage
*WXUNUSED(image
), wxOutputStream
& WXUNUSED(stream
), bool WXUNUSED(verbose
) )
669 int wxImageHandler::GetImageCount( wxInputStream
& WXUNUSED(stream
) )
674 bool wxImageHandler::CanRead( const wxString
& name
)
676 if (wxFileExists(name
))
678 wxFileInputStream
stream(name
);
679 return CanRead(stream
);
683 wxLogError( _("Can't check image format of file '%s': file does not exist."), name
.c_str() );
690 #endif // wxUSE_STREAMS
692 //-----------------------------------------------------------------------------
693 // MSW conversion routines
694 //-----------------------------------------------------------------------------
698 wxBitmap
wxImage::ConvertToBitmap() const
703 // sizeLimit is the MS upper limit for the DIB size
705 int sizeLimit
= 1024*768*3;
707 int sizeLimit
= 0x7fff ;
710 // width and height of the device-dependent bitmap
711 int width
= GetWidth();
712 int bmpHeight
= GetHeight();
714 // calc the number of bytes per scanline and padding
715 int bytePerLine
= width
*3;
716 int sizeDWORD
= sizeof( DWORD
);
717 int lineBoundary
= bytePerLine
% sizeDWORD
;
719 if( lineBoundary
> 0 )
721 padding
= sizeDWORD
- lineBoundary
;
722 bytePerLine
+= padding
;
724 // calc the number of DIBs and heights of DIBs
727 int height
= sizeLimit
/bytePerLine
;
728 if( height
>= bmpHeight
)
732 numDIB
= bmpHeight
/ height
;
733 hRemain
= bmpHeight
% height
;
734 if( hRemain
>0 ) numDIB
++;
737 // set bitmap parameters
739 wxCHECK_MSG( Ok(), bitmap
, wxT("invalid image") );
740 bitmap
.SetWidth( width
);
741 bitmap
.SetHeight( bmpHeight
);
742 bitmap
.SetDepth( wxDisplayDepth() );
744 // create a DIB header
745 int headersize
= sizeof(BITMAPINFOHEADER
);
746 LPBITMAPINFO lpDIBh
= (BITMAPINFO
*) malloc( headersize
);
747 wxCHECK_MSG( lpDIBh
, bitmap
, wxT("could not allocate memory for DIB header") );
748 // Fill in the DIB header
749 lpDIBh
->bmiHeader
.biSize
= headersize
;
750 lpDIBh
->bmiHeader
.biWidth
= (DWORD
)width
;
751 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
752 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
753 // the general formula for biSizeImage:
754 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
755 lpDIBh
->bmiHeader
.biPlanes
= 1;
756 lpDIBh
->bmiHeader
.biBitCount
= 24;
757 lpDIBh
->bmiHeader
.biCompression
= BI_RGB
;
758 lpDIBh
->bmiHeader
.biClrUsed
= 0;
759 // These seem not really needed for our purpose here.
760 lpDIBh
->bmiHeader
.biClrImportant
= 0;
761 lpDIBh
->bmiHeader
.biXPelsPerMeter
= 0;
762 lpDIBh
->bmiHeader
.biYPelsPerMeter
= 0;
763 // memory for DIB data
764 unsigned char *lpBits
;
765 lpBits
= (unsigned char *)malloc( lpDIBh
->bmiHeader
.biSizeImage
);
768 wxFAIL_MSG( wxT("could not allocate memory for DIB") );
773 // create and set the device-dependent bitmap
774 HDC hdc
= ::GetDC(NULL
);
775 HDC memdc
= ::CreateCompatibleDC( hdc
);
777 hbitmap
= ::CreateCompatibleBitmap( hdc
, width
, bmpHeight
);
778 ::SelectObject( memdc
, hbitmap
);
780 // copy image data into DIB data and then into DDB (in a loop)
781 unsigned char *data
= GetData();
784 unsigned char *ptdata
= data
;
785 unsigned char *ptbits
;
787 for( n
=0; n
<numDIB
; n
++ )
789 if( numDIB
> 1 && n
== numDIB
-1 && hRemain
> 0 )
791 // redefine height and size of the (possibly) last smaller DIB
792 // memory is not reallocated
794 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
795 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
799 for( j
=0; j
<height
; j
++ )
801 for( i
=0; i
<width
; i
++ )
803 *(ptbits
++) = *(ptdata
+2);
804 *(ptbits
++) = *(ptdata
+1);
805 *(ptbits
++) = *(ptdata
);
808 for( i
=0; i
< padding
; i
++ ) *(ptbits
++) = 0;
810 ::StretchDIBits( memdc
, 0, origin
, width
, height
,\
811 0, 0, width
, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
, SRCCOPY
);
813 // if numDIB = 1, lines below can also be used
814 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
815 // The above line is equivalent to the following two lines.
816 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
817 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
818 // or the following lines
819 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
820 // HDC memdc = ::CreateCompatibleDC( hdc );
821 // ::SelectObject( memdc, hbitmap);
822 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
823 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
824 // ::SelectObject( memdc, 0 );
825 // ::DeleteDC( memdc );
827 bitmap
.SetHBITMAP( (WXHBITMAP
) hbitmap
);
829 // similarly, created an mono-bitmap for the possible mask
832 hbitmap
= ::CreateBitmap( (WORD
)width
, (WORD
)bmpHeight
, 1, 1, NULL
);
833 ::SelectObject( memdc
, hbitmap
);
834 if( numDIB
== 1 ) height
= bmpHeight
;
835 else height
= sizeLimit
/bytePerLine
;
836 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
837 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
839 unsigned char r
= GetMaskRed();
840 unsigned char g
= GetMaskGreen();
841 unsigned char b
= GetMaskBlue();
842 unsigned char zero
= 0, one
= 255;
844 for( n
=0; n
<numDIB
; n
++ )
846 if( numDIB
> 1 && n
== numDIB
- 1 && hRemain
> 0 )
848 // redefine height and size of the (possibly) last smaller DIB
849 // memory is not reallocated
851 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
852 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
855 for( int j
=0; j
<height
; j
++ )
857 for(i
=0; i
<width
; i
++ )
859 if( (*(ptdata
++)!=r
) | (*(ptdata
++)!=g
) | (*(ptdata
++)!=b
) )
872 for( i
=0; i
< padding
; i
++ ) *(ptbits
++) = zero
;
874 ::StretchDIBits( memdc
, 0, origin
, width
, height
,\
875 0, 0, width
, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
, SRCCOPY
);
878 // create a wxMask object
879 wxMask
*mask
= new wxMask();
880 mask
->SetMaskBitmap( (WXHBITMAP
) hbitmap
);
881 bitmap
.SetMask( mask
);
882 // It will be deleted when the wxBitmap object is deleted (as of 01/1999)
883 /* The following can also be used but is slow to run
884 wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
885 wxMask *mask = new wxMask( bitmap, colour );
886 bitmap.SetMask( mask );
890 // free allocated resources
891 ::SelectObject( memdc
, 0 );
893 ::ReleaseDC(NULL
, hdc
);
897 #if WXWIN_COMPATIBILITY_2
898 // check the wxBitmap object
899 bitmap
.GetBitmapData()->SetOk();
900 #endif // WXWIN_COMPATIBILITY_2
905 wxImage::wxImage( const wxBitmap
&bitmap
)
910 wxFAIL_MSG( wxT("invalid bitmap") );
914 // create an wxImage object
915 int width
= bitmap
.GetWidth();
916 int height
= bitmap
.GetHeight();
917 Create( width
, height
);
918 unsigned char *data
= GetData();
921 wxFAIL_MSG( wxT("could not allocate data for image") );
925 // calc the number of bytes per scanline and padding in the DIB
926 int bytePerLine
= width
*3;
927 int sizeDWORD
= sizeof( DWORD
);
928 int lineBoundary
= bytePerLine
% sizeDWORD
;
930 if( lineBoundary
> 0 )
932 padding
= sizeDWORD
- lineBoundary
;
933 bytePerLine
+= padding
;
936 // create a DIB header
937 int headersize
= sizeof(BITMAPINFOHEADER
);
938 LPBITMAPINFO lpDIBh
= (BITMAPINFO
*) malloc( headersize
);
941 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
945 // Fill in the DIB header
946 lpDIBh
->bmiHeader
.biSize
= headersize
;
947 lpDIBh
->bmiHeader
.biWidth
= width
;
948 lpDIBh
->bmiHeader
.biHeight
= -height
;
949 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
* height
;
950 lpDIBh
->bmiHeader
.biPlanes
= 1;
951 lpDIBh
->bmiHeader
.biBitCount
= 24;
952 lpDIBh
->bmiHeader
.biCompression
= BI_RGB
;
953 lpDIBh
->bmiHeader
.biClrUsed
= 0;
954 // These seem not really needed for our purpose here.
955 lpDIBh
->bmiHeader
.biClrImportant
= 0;
956 lpDIBh
->bmiHeader
.biXPelsPerMeter
= 0;
957 lpDIBh
->bmiHeader
.biYPelsPerMeter
= 0;
958 // memory for DIB data
959 unsigned char *lpBits
;
960 lpBits
= (unsigned char *) malloc( lpDIBh
->bmiHeader
.biSizeImage
);
963 wxFAIL_MSG( wxT("could not allocate data for DIB") );
969 // copy data from the device-dependent bitmap to the DIB
970 HDC hdc
= ::GetDC(NULL
);
972 hbitmap
= (HBITMAP
) bitmap
.GetHBITMAP();
973 ::GetDIBits( hdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
975 // copy DIB data into the wxImage object
977 unsigned char *ptdata
= data
;
978 unsigned char *ptbits
= lpBits
;
979 for( i
=0; i
<height
; i
++ )
981 for( j
=0; j
<width
; j
++ )
983 *(ptdata
++) = *(ptbits
+2);
984 *(ptdata
++) = *(ptbits
+1);
985 *(ptdata
++) = *(ptbits
);
991 // similarly, set data according to the possible mask bitmap
992 if( bitmap
.GetMask() && bitmap
.GetMask()->GetMaskBitmap() )
994 hbitmap
= (HBITMAP
) bitmap
.GetMask()->GetMaskBitmap();
995 // memory DC created, color set, data copied, and memory DC deleted
996 HDC memdc
= ::CreateCompatibleDC( hdc
);
997 ::SetTextColor( memdc
, RGB( 0, 0, 0 ) );
998 ::SetBkColor( memdc
, RGB( 255, 255, 255 ) );
999 ::GetDIBits( memdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
1000 ::DeleteDC( memdc
);
1001 // background color set to RGB(16,16,16) in consistent with wxGTK
1002 unsigned char r
=16, g
=16, b
=16;
1005 for( i
=0; i
<height
; i
++ )
1007 for( j
=0; j
<width
; j
++ )
1021 SetMaskColour( r
, g
, b
);
1028 // free allocated resources
1029 ::ReleaseDC(NULL
, hdc
);
1038 #include <PictUtils.h>
1040 extern CTabHandle
wxMacCreateColorTable( int numColors
) ;
1041 extern void wxMacDestroyColorTable( CTabHandle colors
) ;
1042 extern void wxMacSetColorTableEntry( CTabHandle newColors
, int index
, int red
, int green
, int blue
) ;
1043 extern GWorldPtr
wxMacCreateGWorld( int height
, int width
, int depth
) ;
1044 extern void wxMacDestroyGWorld( GWorldPtr gw
) ;
1046 wxBitmap
wxImage::ConvertToBitmap() const
1048 // width and height of the device-dependent bitmap
1049 int width
= GetWidth();
1050 int height
= GetHeight();
1054 wxBitmap
bitmap( width
, height
, wxDisplayDepth() ) ;
1061 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1063 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1065 wxMask *mask = new wxMask();
1066 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1068 bitmap.SetMask( mask );
1074 int r_mask
= GetMaskRed();
1075 int g_mask
= GetMaskGreen();
1076 int b_mask
= GetMaskBlue();
1079 GDHandle origDevice
;
1081 GetGWorld( &origPort
, &origDevice
) ;
1082 SetGWorld( bitmap
.GetHBITMAP() , NULL
) ;
1084 register unsigned char* data
= GetData();
1087 for (int y
= 0; y
< height
; y
++)
1090 unsigned char lastr
= 0 ;
1091 unsigned char lastg
= 0 ;
1092 unsigned char lastb
= 0 ;
1093 RGBColor lastcolor
;
1096 for (int x
= 0; x
< width
; x
++)
1098 unsigned char r
= data
[index
++];
1099 unsigned char g
= data
[index
++];
1100 unsigned char b
= data
[index
++];
1102 if ( r
!= lastr
|| g
!= lastg
|| b
!= lastb
)
1104 lastcolor
.red
= ( lastr
<< 8 ) + lastr
;
1105 lastcolor
.green
= ( lastg
<< 8 ) + lastg
;
1106 lastcolor
.blue
= ( lastb
<< 8 ) + lastb
;
1107 RGBForeColor( &lastcolor
) ;
1114 lastcolor
.red
= ( lastr
<< 8 ) + lastr
;
1115 lastcolor
.green
= ( lastg
<< 8 ) + lastg
;
1116 lastcolor
.blue
= ( lastb
<< 8 ) + lastb
;
1117 RGBForeColor( &lastcolor
) ;
1118 LineTo( width
- 1 , y
) ;
1120 for (int x
= 0; x
< width
; x
++)
1122 unsigned char r
= data
[index
++];
1123 unsigned char g
= data
[index
++];
1124 unsigned char b
= data
[index
++];
1126 color
.red
= ( r
<< 8 ) + r
;
1127 color
.green
= ( g
<< 8 ) + g
;
1128 color
.blue
= ( b
<< 8 ) + b
;
1129 SetCPixel( x
, y
, &color
) ;
1134 SetGWorld( origPort
, origDevice
) ;
1140 wxImage::wxImage( const wxBitmap
&bitmap
)
1145 wxFAIL_MSG( "invalid bitmap" );
1149 // create an wxImage object
1150 int width
= bitmap
.GetWidth();
1151 int height
= bitmap
.GetHeight();
1152 Create( width
, height
);
1154 unsigned char *data = GetData();
1157 wxFAIL_MSG( "could not allocate data for image" );
1161 // calc the number of bytes per scanline and padding in the DIB
1162 int bytePerLine = width*3;
1163 int sizeDWORD = sizeof( DWORD );
1164 div_t lineBoundary = div( bytePerLine, sizeDWORD );
1166 if( lineBoundary.rem > 0 )
1168 padding = sizeDWORD - lineBoundary.rem;
1169 bytePerLine += padding;
1172 // create a DIB header
1173 int headersize = sizeof(BITMAPINFOHEADER);
1174 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
1177 wxFAIL_MSG( "could not allocate data for DIB header" );
1181 // Fill in the DIB header
1182 lpDIBh->bmiHeader.biSize = headersize;
1183 lpDIBh->bmiHeader.biWidth = width;
1184 lpDIBh->bmiHeader.biHeight = -height;
1185 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
1186 lpDIBh->bmiHeader.biPlanes = 1;
1187 lpDIBh->bmiHeader.biBitCount = 24;
1188 lpDIBh->bmiHeader.biCompression = BI_RGB;
1189 lpDIBh->bmiHeader.biClrUsed = 0;
1190 // These seem not really needed for our purpose here.
1191 lpDIBh->bmiHeader.biClrImportant = 0;
1192 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
1193 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
1194 // memory for DIB data
1195 unsigned char *lpBits;
1196 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
1199 wxFAIL_MSG( "could not allocate data for DIB" );
1205 // copy data from the device-dependent bitmap to the DIB
1206 HDC hdc = ::GetDC(NULL);
1208 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
1209 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1211 // copy DIB data into the wxImage object
1213 unsigned char *ptdata = data;
1214 unsigned char *ptbits = lpBits;
1215 for( i=0; i<height; i++ )
1217 for( j=0; j<width; j++ )
1219 *(ptdata++) = *(ptbits+2);
1220 *(ptdata++) = *(ptbits+1);
1221 *(ptdata++) = *(ptbits );
1227 // similarly, set data according to the possible mask bitmap
1228 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
1230 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
1231 // memory DC created, color set, data copied, and memory DC deleted
1232 HDC memdc = ::CreateCompatibleDC( hdc );
1233 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
1234 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
1235 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1236 ::DeleteDC( memdc );
1237 // background color set to RGB(16,16,16) in consistent with wxGTK
1238 unsigned char r=16, g=16, b=16;
1241 for( i=0; i<height; i++ )
1243 for( j=0; j<width; j++ )
1257 SetMaskColour( r, g, b );
1264 // free allocated resources
1265 ::ReleaseDC(NULL, hdc);
1273 //-----------------------------------------------------------------------------
1274 // GTK conversion routines
1275 //-----------------------------------------------------------------------------
1279 #include <gtk/gtk.h>
1280 #include <gdk/gdk.h>
1281 #include <gdk/gdkx.h>
1283 #if (GTK_MINOR_VERSION > 0)
1284 #include <gdk/gdkrgb.h>
1287 wxBitmap
wxImage::ConvertToBitmap() const
1291 wxCHECK_MSG( Ok(), bitmap
, wxT("invalid image") );
1293 int width
= GetWidth();
1294 int height
= GetHeight();
1296 bitmap
.SetHeight( height
);
1297 bitmap
.SetWidth( width
);
1299 bitmap
.SetPixmap( gdk_pixmap_new( (GdkWindow
*)&gdk_root_parent
, width
, height
, -1 ) );
1303 GdkVisual
*visual
= gdk_window_get_visual( bitmap
.GetPixmap() );
1304 if (visual
== NULL
) visual
= gdk_visual_get_system();
1305 int bpp
= visual
->depth
;
1307 bitmap
.SetDepth( bpp
);
1309 if ((bpp
== 16) && (visual
->red_mask
!= 0xf800)) bpp
= 15;
1310 if (bpp
< 8) bpp
= 8;
1312 #if (GTK_MINOR_VERSION > 0)
1314 if (!HasMask() && (bpp
> 8))
1316 static bool s_hasInitialized
= FALSE
;
1318 if (!s_hasInitialized
)
1321 s_hasInitialized
= TRUE
;
1324 GdkGC
*gc
= gdk_gc_new( bitmap
.GetPixmap() );
1326 gdk_draw_rgb_image( bitmap
.GetPixmap(),
1330 GDK_RGB_DITHER_NONE
,
1341 // Create picture image
1343 GdkImage
*data_image
=
1344 gdk_image_new( GDK_IMAGE_FASTEST
, gdk_visual_get_system(), width
, height
);
1346 // Create mask image
1348 GdkImage
*mask_image
= (GdkImage
*) NULL
;
1352 unsigned char *mask_data
= (unsigned char*)malloc( ((width
>> 3)+8) * height
);
1354 mask_image
= gdk_image_new_bitmap( gdk_visual_get_system(), mask_data
, width
, height
);
1356 wxMask
*mask
= new wxMask();
1357 mask
->m_bitmap
= gdk_pixmap_new( (GdkWindow
*)&gdk_root_parent
, width
, height
, 1 );
1359 bitmap
.SetMask( mask
);
1364 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
1365 byte_order b_o
= RGB
;
1369 GdkVisual
*visual
= gdk_visual_get_system();
1370 if ((visual
->red_mask
> visual
->green_mask
) && (visual
->green_mask
> visual
->blue_mask
)) b_o
= RGB
;
1371 else if ((visual
->red_mask
> visual
->blue_mask
) && (visual
->blue_mask
> visual
->green_mask
)) b_o
= RGB
;
1372 else if ((visual
->blue_mask
> visual
->red_mask
) && (visual
->red_mask
> visual
->green_mask
)) b_o
= BRG
;
1373 else if ((visual
->blue_mask
> visual
->green_mask
) && (visual
->green_mask
> visual
->red_mask
)) b_o
= BGR
;
1374 else if ((visual
->green_mask
> visual
->red_mask
) && (visual
->red_mask
> visual
->blue_mask
)) b_o
= GRB
;
1375 else if ((visual
->green_mask
> visual
->blue_mask
) && (visual
->blue_mask
> visual
->red_mask
)) b_o
= GBR
;
1378 int r_mask
= GetMaskRed();
1379 int g_mask
= GetMaskGreen();
1380 int b_mask
= GetMaskBlue();
1382 unsigned char* data
= GetData();
1385 for (int y
= 0; y
< height
; y
++)
1387 for (int x
= 0; x
< width
; x
++)
1389 int r
= data
[index
];
1391 int g
= data
[index
];
1393 int b
= data
[index
];
1398 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
1399 gdk_image_put_pixel( mask_image
, x
, y
, 1 );
1401 gdk_image_put_pixel( mask_image
, x
, y
, 0 );
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 );
1417 if (wxTheApp
->m_colorCube
)
1419 pixel
= wxTheApp
->m_colorCube
[ ((r
& 0xf8) << 7) + ((g
& 0xf8) << 2) + ((b
& 0xf8) >> 3) ];
1423 GdkColormap
*cmap
= gtk_widget_get_default_colormap();
1424 GdkColor
*colors
= cmap
->colors
;
1425 int max
= 3 * (65536);
1427 for (int i
= 0; i
< cmap
->size
; i
++)
1429 int rdiff
= (r
<< 8) - colors
[i
].red
;
1430 int gdiff
= (g
<< 8) - colors
[i
].green
;
1431 int bdiff
= (b
<< 8) - colors
[i
].blue
;
1432 int sum
= ABS (rdiff
) + ABS (gdiff
) + ABS (bdiff
);
1433 if (sum
< max
) { pixel
= i
; max
= sum
; }
1437 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1443 guint32 pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
1444 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1449 guint32 pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
1450 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1459 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
1460 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
1461 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
1462 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
1463 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
1464 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
1466 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1475 GdkGC
*data_gc
= gdk_gc_new( bitmap
.GetPixmap() );
1477 gdk_draw_image( bitmap
.GetPixmap(), data_gc
, data_image
, 0, 0, 0, 0, width
, height
);
1479 gdk_image_destroy( data_image
);
1480 gdk_gc_unref( data_gc
);
1486 GdkGC
*mask_gc
= gdk_gc_new( bitmap
.GetMask()->GetBitmap() );
1488 gdk_draw_image( bitmap
.GetMask()->GetBitmap(), mask_gc
, mask_image
, 0, 0, 0, 0, width
, height
);
1490 gdk_image_destroy( mask_image
);
1491 gdk_gc_unref( mask_gc
);
1497 wxImage::wxImage( const wxBitmap
&bitmap
)
1499 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
1501 GdkImage
*gdk_image
= (GdkImage
*) NULL
;
1502 if (bitmap
.GetPixmap())
1504 gdk_image
= gdk_image_get( bitmap
.GetPixmap(),
1506 bitmap
.GetWidth(), bitmap
.GetHeight() );
1508 if (bitmap
.GetBitmap())
1510 gdk_image
= gdk_image_get( bitmap
.GetBitmap(),
1512 bitmap
.GetWidth(), bitmap
.GetHeight() );
1515 wxFAIL_MSG( wxT("Ill-formed bitmap") );
1518 wxCHECK_RET( gdk_image
, wxT("couldn't create image") );
1520 Create( bitmap
.GetWidth(), bitmap
.GetHeight() );
1521 char unsigned *data
= GetData();
1525 gdk_image_destroy( gdk_image
);
1526 wxFAIL_MSG( wxT("couldn't create image") );
1530 GdkImage
*gdk_image_mask
= (GdkImage
*) NULL
;
1531 if (bitmap
.GetMask())
1533 gdk_image_mask
= gdk_image_get( bitmap
.GetMask()->GetBitmap(),
1535 bitmap
.GetWidth(), bitmap
.GetHeight() );
1537 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1540 GdkVisual
*visual
= (GdkVisual
*) NULL
;
1541 if (bitmap
.GetPixmap())
1542 visual
= gdk_window_get_visual( bitmap
.GetPixmap() );
1544 visual
= gdk_window_get_visual( bitmap
.GetBitmap() );
1546 if (visual
== NULL
) visual
= gdk_window_get_visual( (GdkWindow
*) &gdk_root_parent
);
1547 int bpp
= visual
->depth
;
1548 if ((bpp
== 16) && (visual
->red_mask
!= 0xf800)) bpp
= 15;
1550 GdkColormap
*cmap
= gtk_widget_get_default_colormap();
1553 for (int j
= 0; j
< bitmap
.GetHeight(); j
++)
1555 for (int i
= 0; i
< bitmap
.GetWidth(); i
++)
1557 wxInt32 pixel
= gdk_image_get_pixel( gdk_image
, i
, j
);
1560 data
[pos
] = cmap
->colors
[pixel
].red
>> 8;
1561 data
[pos
+1] = cmap
->colors
[pixel
].green
>> 8;
1562 data
[pos
+2] = cmap
->colors
[pixel
].blue
>> 8;
1563 } else if (bpp
== 15)
1565 #if (wxBYTE_ORDER == wxBIG_ENDIAN)
1568 data
[pos
] = (pixel
>> 7) & 0xf8;
1569 data
[pos
+1] = (pixel
>> 2) & 0xf8;
1570 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1571 } else if (bpp
== 16)
1573 #if (wxBYTE_ORDER == wxBIG_ENDIAN)
1576 data
[pos
] = (pixel
>> 8) & 0xf8;
1577 data
[pos
+1] = (pixel
>> 3) & 0xfc;
1578 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1581 #if (wxBYTE_ORDER == wxBIG_ENDIAN)
1582 data
[pos
] = (pixel
) & 0xff; // Red
1583 data
[pos
+1] = (pixel
>> 8) & 0xff; // Green
1584 data
[pos
+2] = (pixel
>> 16) & 0xff; // Blue
1586 data
[pos
] = (pixel
>> 16) & 0xff;
1587 data
[pos
+1] = (pixel
>> 8) & 0xff;
1588 data
[pos
+2] = pixel
& 0xff;
1594 int mask_pixel
= gdk_image_get_pixel( gdk_image_mask
, i
, j
);
1595 if (mask_pixel
== 0)
1607 gdk_image_destroy( gdk_image
);
1608 if (gdk_image_mask
) gdk_image_destroy( gdk_image_mask
);
1613 //-----------------------------------------------------------------------------
1614 // Motif conversion routines
1615 //-----------------------------------------------------------------------------
1619 #pragma message disable nosimpint
1623 #pragma message enable nosimpint
1625 #include "wx/utils.h"
1628 wxBitmap
wxImage::ConvertToBitmap() const
1632 wxCHECK_MSG( Ok(), bitmap
, wxT("invalid image") );
1634 int width
= GetWidth();
1635 int height
= GetHeight();
1637 bitmap
.SetHeight( height
);
1638 bitmap
.SetWidth( width
);
1640 Display
*dpy
= (Display
*) wxGetDisplay();
1641 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1642 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1646 XImage
*data_image
= XCreateImage( dpy
, vis
, bpp
, ZPixmap
, 0, 0, width
, height
, 32, 0 );
1647 data_image
->data
= (char*) malloc( data_image
->bytes_per_line
* data_image
->height
);
1649 bitmap
.Create( width
, height
, bpp
);
1654 GdkImage *mask_image = (GdkImage*) NULL;
1658 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1660 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1662 wxMask *mask = new wxMask();
1663 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1665 bitmap.SetMask( mask );
1669 // Retrieve depth info
1671 XVisualInfo vinfo_template
;
1674 vinfo_template
.visual
= vis
;
1675 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1676 vinfo_template
.depth
= bpp
;
1679 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
1681 wxCHECK_MSG( vi
, wxNullBitmap
, wxT("no visual") );
1685 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1686 if (bpp
< 8) bpp
= 8;
1690 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
1691 byte_order b_o
= RGB
;
1695 if ((vi
->red_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->blue_mask
)) b_o
= RGB
;
1696 else if ((vi
->red_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->green_mask
)) b_o
= RGB
;
1697 else if ((vi
->blue_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->green_mask
)) b_o
= BRG
;
1698 else if ((vi
->blue_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->red_mask
)) b_o
= BGR
;
1699 else if ((vi
->green_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->blue_mask
)) b_o
= GRB
;
1700 else if ((vi
->green_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->red_mask
)) b_o
= GBR
;
1704 int r_mask = GetMaskRed();
1705 int g_mask = GetMaskGreen();
1706 int b_mask = GetMaskBlue();
1712 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap( dpy
);
1714 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
1715 XQueryColors( dpy
, cmap
, colors
, 256 );
1718 unsigned char* data
= GetData();
1721 for (int y
= 0; y
< height
; y
++)
1723 for (int x
= 0; x
< width
; x
++)
1725 int r
= data
[index
];
1727 int g
= data
[index
];
1729 int b
= data
[index
];
1735 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1736 gdk_image_put_pixel( mask_image, x, y, 1 );
1738 gdk_image_put_pixel( mask_image, x, y, 0 );
1748 if (wxTheApp->m_colorCube)
1750 pixel = wxTheApp->m_colorCube
1751 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1756 int max
= 3 * (65536);
1757 for (int i
= 0; i
< 256; i
++)
1759 int rdiff
= (r
<< 8) - colors
[i
].red
;
1760 int gdiff
= (g
<< 8) - colors
[i
].green
;
1761 int bdiff
= (b
<< 8) - colors
[i
].blue
;
1762 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
1763 if (sum
< max
) { pixel
= i
; max
= sum
; }
1768 XPutPixel( data_image
, x
, y
, pixel
);
1773 int pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
1774 XPutPixel( data_image
, x
, y
, pixel
);
1779 int pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
1780 XPutPixel( data_image
, x
, y
, pixel
);
1789 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
1790 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
1791 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
1792 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
1793 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
1794 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
1796 XPutPixel( data_image
, x
, y
, pixel
);
1806 gcvalues
.foreground
= BlackPixel( dpy
, DefaultScreen( dpy
) );
1807 GC gc
= XCreateGC( dpy
, RootWindow ( dpy
, DefaultScreen(dpy
) ), GCForeground
, &gcvalues
);
1808 XPutImage( dpy
, (Drawable
)bitmap
.GetPixmap(), gc
, data_image
, 0, 0, 0, 0, width
, height
);
1810 XDestroyImage( data_image
);
1818 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
1820 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
1822 gdk_image_destroy( mask_image );
1823 gdk_gc_unref( mask_gc );
1830 wxImage::wxImage( const wxBitmap
&bitmap
)
1832 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
1834 Display
*dpy
= (Display
*) wxGetDisplay();
1835 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1836 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1838 XImage
*ximage
= XGetImage( dpy
,
1839 (Drawable
)bitmap
.GetPixmap(),
1841 bitmap
.GetWidth(), bitmap
.GetHeight(),
1842 AllPlanes
, ZPixmap
);
1844 wxCHECK_RET( ximage
, wxT("couldn't create image") );
1846 Create( bitmap
.GetWidth(), bitmap
.GetHeight() );
1847 char unsigned *data
= GetData();
1851 XDestroyImage( ximage
);
1852 wxFAIL_MSG( wxT("couldn't create image") );
1857 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1858 if (bitmap.GetMask())
1860 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1862 bitmap.GetWidth(), bitmap.GetHeight() );
1864 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1868 // Retrieve depth info
1870 XVisualInfo vinfo_template
;
1873 vinfo_template
.visual
= vis
;
1874 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1875 vinfo_template
.depth
= bpp
;
1878 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
1880 wxCHECK_RET( vi
, wxT("no visual") );
1882 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1889 Colormap cmap
= (Colormap
)wxTheApp
->GetMainColormap( dpy
);
1891 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
1892 XQueryColors( dpy
, cmap
, colors
, 256 );
1896 for (int j
= 0; j
< bitmap
.GetHeight(); j
++)
1898 for (int i
= 0; i
< bitmap
.GetWidth(); i
++)
1900 int pixel
= XGetPixel( ximage
, i
, j
);
1903 data
[pos
] = colors
[pixel
].red
>> 8;
1904 data
[pos
+1] = colors
[pixel
].green
>> 8;
1905 data
[pos
+2] = colors
[pixel
].blue
>> 8;
1906 } else if (bpp
== 15)
1908 data
[pos
] = (pixel
>> 7) & 0xf8;
1909 data
[pos
+1] = (pixel
>> 2) & 0xf8;
1910 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1911 } else if (bpp
== 16)
1913 data
[pos
] = (pixel
>> 8) & 0xf8;
1914 data
[pos
+1] = (pixel
>> 3) & 0xfc;
1915 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1918 data
[pos
] = (pixel
>> 16) & 0xff;
1919 data
[pos
+1] = (pixel
>> 8) & 0xff;
1920 data
[pos
+2] = pixel
& 0xff;
1926 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1927 if (mask_pixel == 0)
1940 XDestroyImage( ximage
);
1942 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1948 // OS/2 Presentation manager conversion routings
1950 wxBitmap
wxImage::ConvertToBitmap() const
1953 return wxNullBitmap
;
1954 wxBitmap bitmap
; // remove
1957 int sizeLimit = 1024*768*3;
1959 // width and height of the device-dependent bitmap
1960 int width = GetWidth();
1961 int bmpHeight = GetHeight();
1963 // calc the number of bytes per scanline and padding
1964 int bytePerLine = width*3;
1965 int sizeDWORD = sizeof( DWORD );
1966 int lineBoundary = bytePerLine % sizeDWORD;
1968 if( lineBoundary > 0 )
1970 padding = sizeDWORD - lineBoundary;
1971 bytePerLine += padding;
1973 // calc the number of DIBs and heights of DIBs
1976 int height = sizeLimit/bytePerLine;
1977 if( height >= bmpHeight )
1981 numDIB = bmpHeight / height;
1982 hRemain = bmpHeight % height;
1983 if( hRemain >0 ) numDIB++;
1986 // set bitmap parameters
1988 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
1989 bitmap.SetWidth( width );
1990 bitmap.SetHeight( bmpHeight );
1991 bitmap.SetDepth( wxDisplayDepth() );
1993 // create a DIB header
1994 int headersize = sizeof(BITMAPINFOHEADER);
1995 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
1996 wxCHECK_MSG( lpDIBh, bitmap, wxT("could not allocate memory for DIB header") );
1997 // Fill in the DIB header
1998 lpDIBh->bmiHeader.biSize = headersize;
1999 lpDIBh->bmiHeader.biWidth = (DWORD)width;
2000 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2001 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2002 // the general formula for biSizeImage:
2003 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
2004 lpDIBh->bmiHeader.biPlanes = 1;
2005 lpDIBh->bmiHeader.biBitCount = 24;
2006 lpDIBh->bmiHeader.biCompression = BI_RGB;
2007 lpDIBh->bmiHeader.biClrUsed = 0;
2008 // These seem not really needed for our purpose here.
2009 lpDIBh->bmiHeader.biClrImportant = 0;
2010 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2011 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2012 // memory for DIB data
2013 unsigned char *lpBits;
2014 lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
2017 wxFAIL_MSG( wxT("could not allocate memory for DIB") );
2022 // create and set the device-dependent bitmap
2023 HDC hdc = ::GetDC(NULL);
2024 HDC memdc = ::CreateCompatibleDC( hdc );
2026 hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
2027 ::SelectObject( memdc, hbitmap);
2029 // copy image data into DIB data and then into DDB (in a loop)
2030 unsigned char *data = GetData();
2033 unsigned char *ptdata = data;
2034 unsigned char *ptbits;
2036 for( n=0; n<numDIB; n++ )
2038 if( numDIB > 1 && n == numDIB-1 && hRemain > 0 )
2040 // redefine height and size of the (possibly) last smaller DIB
2041 // memory is not reallocated
2043 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2044 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2048 for( j=0; j<height; j++ )
2050 for( i=0; i<width; i++ )
2052 *(ptbits++) = *(ptdata+2);
2053 *(ptbits++) = *(ptdata+1);
2054 *(ptbits++) = *(ptdata );
2057 for( i=0; i< padding; i++ ) *(ptbits++) = 0;
2059 ::StretchDIBits( memdc, 0, origin, width, height,\
2060 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2062 // if numDIB = 1, lines below can also be used
2063 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
2064 // The above line is equivalent to the following two lines.
2065 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2066 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
2067 // or the following lines
2068 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2069 // HDC memdc = ::CreateCompatibleDC( hdc );
2070 // ::SelectObject( memdc, hbitmap);
2071 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
2072 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
2073 // ::SelectObject( memdc, 0 );
2074 // ::DeleteDC( memdc );
2076 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
2078 // similarly, created an mono-bitmap for the possible mask
2081 hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL );
2082 ::SelectObject( memdc, hbitmap);
2083 if( numDIB == 1 ) height = bmpHeight;
2084 else height = sizeLimit/bytePerLine;
2085 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2086 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2088 unsigned char r = GetMaskRed();
2089 unsigned char g = GetMaskGreen();
2090 unsigned char b = GetMaskBlue();
2091 unsigned char zero = 0, one = 255;
2093 for( n=0; n<numDIB; n++ )
2095 if( numDIB > 1 && n == numDIB - 1 && hRemain > 0 )
2097 // redefine height and size of the (possibly) last smaller DIB
2098 // memory is not reallocated
2100 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2101 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2104 for( int j=0; j<height; j++ )
2106 for(i=0; i<width; i++ )
2108 if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
2121 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
2123 ::StretchDIBits( memdc, 0, origin, width, height,\
2124 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2127 // create a wxMask object
2128 wxMask *mask = new wxMask();
2129 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
2130 bitmap.SetMask( mask );
2133 // free allocated resources
2134 ::SelectObject( memdc, 0 );
2135 ::DeleteDC( memdc );
2136 ::ReleaseDC(NULL, hdc);
2140 // check the wxBitmap object
2141 if( bitmap.GetHBITMAP() )
2142 bitmap.SetOk( TRUE );
2144 bitmap.SetOk( FALSE );
2149 wxImage::wxImage( const wxBitmap
&bitmap
)
2154 wxFAIL_MSG( wxT("invalid bitmap") );
2158 // create an wxImage object
2159 int width
= bitmap
.GetWidth();
2160 int height
= bitmap
.GetHeight();
2161 Create( width
, height
);
2162 unsigned char *data
= GetData();
2165 wxFAIL_MSG( wxT("could not allocate data for image") );
2169 // calc the number of bytes per scanline and padding in the DIB
2170 int bytePerLine
= width
*3;
2171 int sizeDWORD
= sizeof( DWORD
);
2172 int lineBoundary
= bytePerLine
% sizeDWORD
;
2174 if( lineBoundary
> 0 )
2176 padding
= sizeDWORD
- lineBoundary
;
2177 bytePerLine
+= padding
;
2181 // create a DIB header
2182 int headersize = sizeof(BITMAPINFOHEADER);
2183 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
2186 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
2190 // Fill in the DIB header
2191 lpDIBh->bmiHeader.biSize = headersize;
2192 lpDIBh->bmiHeader.biWidth = width;
2193 lpDIBh->bmiHeader.biHeight = -height;
2194 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
2195 lpDIBh->bmiHeader.biPlanes = 1;
2196 lpDIBh->bmiHeader.biBitCount = 24;
2197 lpDIBh->bmiHeader.biCompression = BI_RGB;
2198 lpDIBh->bmiHeader.biClrUsed = 0;
2199 // These seem not really needed for our purpose here.
2200 lpDIBh->bmiHeader.biClrImportant = 0;
2201 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2202 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2203 // memory for DIB data
2204 unsigned char *lpBits;
2205 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
2208 wxFAIL_MSG( wxT("could not allocate data for DIB") );
2214 // copy data from the device-dependent bitmap to the DIB
2215 HDC hdc = ::GetDC(NULL);
2217 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
2218 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2220 // copy DIB data into the wxImage object
2222 unsigned char *ptdata = data;
2223 unsigned char *ptbits = lpBits;
2224 for( i=0; i<height; i++ )
2226 for( j=0; j<width; j++ )
2228 *(ptdata++) = *(ptbits+2);
2229 *(ptdata++) = *(ptbits+1);
2230 *(ptdata++) = *(ptbits );
2236 // similarly, set data according to the possible mask bitmap
2237 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
2239 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
2240 // memory DC created, color set, data copied, and memory DC deleted
2241 HDC memdc = ::CreateCompatibleDC( hdc );
2242 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
2243 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
2244 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2245 ::DeleteDC( memdc );
2246 // background color set to RGB(16,16,16) in consistent with wxGTK
2247 unsigned char r=16, g=16, b=16;
2250 for( i=0; i<height; i++ )
2252 for( j=0; j<width; j++ )
2266 SetMaskColour( r, g, b );
2273 // free allocated resources
2274 ::ReleaseDC(NULL, hdc);
2282 // A module to allow wxImage initialization/cleanup
2283 // without calling these functions from app.cpp or from
2284 // the user's application.
2286 class wxImageModule
: public wxModule
2288 DECLARE_DYNAMIC_CLASS(wxImageModule
)
2291 bool OnInit() { wxImage::InitStandardHandlers(); return TRUE
; };
2292 void OnExit() { wxImage::CleanUpHandlers(); };
2295 IMPLEMENT_DYNAMIC_CLASS(wxImageModule
, wxModule
)