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"
27 #include "../png/png.h"
29 #include "wx/filefn.h"
30 #include "wx/wfstream.h"
43 //-----------------------------------------------------------------------------
45 //-----------------------------------------------------------------------------
47 class wxImageRefData
: public wxObjectRefData
52 ~wxImageRefData(void);
56 unsigned char *m_data
;
58 unsigned char m_maskRed
,m_maskGreen
,m_maskBlue
;
62 wxImageRefData::wxImageRefData(void)
66 m_data
= (unsigned char*) NULL
;
74 wxImageRefData::~wxImageRefData(void)
76 if (m_data
) free( m_data
);
79 wxList
wxImage::sm_handlers
;
81 //-----------------------------------------------------------------------------
83 #define M_IMGDATA ((wxImageRefData *)m_refData)
85 #if !USE_SHARED_LIBRARIES
86 IMPLEMENT_DYNAMIC_CLASS(wxImage
, wxObject
)
93 wxImage::wxImage( int width
, int height
)
95 Create( width
, height
);
98 wxImage::wxImage( const wxString
& name
, long type
)
100 LoadFile( name
, type
);
104 wxImage::wxImage( wxInputStream
& stream
, long type
)
106 LoadFile( stream
, type
);
108 #endif // wxUSE_STREAMS
110 wxImage::wxImage( const wxImage
& image
)
115 wxImage::wxImage( const wxImage
* image
)
117 if (image
) Ref(*image
);
120 void wxImage::Create( int width
, int height
)
122 m_refData
= new wxImageRefData();
124 M_IMGDATA
->m_data
= (unsigned char *) malloc( width
*height
*3 );
125 if (M_IMGDATA
->m_data
)
127 for (int l
= 0; l
< width
*height
*3; l
++) M_IMGDATA
->m_data
[l
] = 0;
129 M_IMGDATA
->m_width
= width
;
130 M_IMGDATA
->m_height
= height
;
131 M_IMGDATA
->m_ok
= TRUE
;
139 void wxImage::Destroy()
144 wxImage
wxImage::Scale( int width
, int height
)
148 wxCHECK_MSG( Ok(), image
, "invlaid image" );
150 wxCHECK_MSG( (width
> 0) && (height
> 0), image
, "invalid image size" );
152 image
.Create( width
, height
);
154 char unsigned *data
= image
.GetData();
156 wxCHECK_MSG( data
, image
, "unable to create image" );
158 if (M_IMGDATA
->m_hasMask
)
159 image
.SetMaskColour( M_IMGDATA
->m_maskRed
, M_IMGDATA
->m_maskGreen
, M_IMGDATA
->m_maskBlue
);
161 double xscale
= (double)width
/ (double)M_IMGDATA
->m_width
;
162 double yscale
= (double)height
/ (double)M_IMGDATA
->m_height
;
164 for (int j
= 0; j
< height
; j
++)
166 for (int i
= 0; i
< width
; i
++)
168 int new_pos
= 3*(j
*width
+ i
);
169 int old_pos
= 3*((long)(j
/yscale
)*M_IMGDATA
->m_width
+ (long)(i
/xscale
));
170 data
[ new_pos
] = M_IMGDATA
->m_data
[ old_pos
];
171 data
[ new_pos
+1 ] = M_IMGDATA
->m_data
[ old_pos
+1 ];
172 data
[ new_pos
+2 ] = M_IMGDATA
->m_data
[ old_pos
+2 ];
179 void wxImage::SetRGB( int x
, int y
, unsigned char r
, unsigned char g
, unsigned char b
)
181 wxCHECK_RET( Ok(), "invalid image" );
183 int w
= M_IMGDATA
->m_width
;
184 int h
= M_IMGDATA
->m_height
;
186 wxCHECK_RET( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), "invalid image index" );
188 long pos
= (y
* w
+ x
) * 3;
190 M_IMGDATA
->m_data
[ pos
] = r
;
191 M_IMGDATA
->m_data
[ pos
+1 ] = g
;
192 M_IMGDATA
->m_data
[ pos
+2 ] = b
;
195 unsigned char wxImage::GetRed( int x
, int y
)
197 wxCHECK_MSG( Ok(), 0, "invalid image" );
199 int w
= M_IMGDATA
->m_width
;
200 int h
= M_IMGDATA
->m_height
;
202 wxCHECK_MSG( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), 0, "invalid image index" );
204 long pos
= (y
* w
+ x
) * 3;
206 return M_IMGDATA
->m_data
[pos
];
209 unsigned char wxImage::GetGreen( int x
, int y
)
211 wxCHECK_MSG( Ok(), 0, "invalid image" );
213 int w
= M_IMGDATA
->m_width
;
214 int h
= M_IMGDATA
->m_height
;
216 wxCHECK_MSG( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), 0, "invalid image index" );
218 long pos
= (y
* w
+ x
) * 3;
220 return M_IMGDATA
->m_data
[pos
+1];
223 unsigned char wxImage::GetBlue( int x
, int y
)
225 wxCHECK_MSG( Ok(), 0, "invalid image" );
227 int w
= M_IMGDATA
->m_width
;
228 int h
= M_IMGDATA
->m_height
;
230 wxCHECK_MSG( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), 0, "invalid image index" );
232 long pos
= (y
* w
+ x
) * 3;
234 return M_IMGDATA
->m_data
[pos
+2];
237 bool wxImage::Ok() const
239 return (M_IMGDATA
&& M_IMGDATA
->m_ok
);
242 char unsigned *wxImage::GetData() const
244 wxCHECK_MSG( Ok(), (char unsigned *)NULL
, "invalid image" );
246 return M_IMGDATA
->m_data
;
249 void wxImage::SetData( char unsigned *WXUNUSED(data
) )
251 wxCHECK_RET( Ok(), "invalid image" );
254 void wxImage::SetMaskColour( unsigned char r
, unsigned char g
, unsigned char b
)
256 wxCHECK_RET( Ok(), "invalid image" );
258 M_IMGDATA
->m_maskRed
= r
;
259 M_IMGDATA
->m_maskGreen
= g
;
260 M_IMGDATA
->m_maskBlue
= b
;
261 M_IMGDATA
->m_hasMask
= TRUE
;
264 unsigned char wxImage::GetMaskRed() const
266 wxCHECK_MSG( Ok(), 0, "invalid image" );
268 return M_IMGDATA
->m_maskRed
;
271 unsigned char wxImage::GetMaskGreen() const
273 wxCHECK_MSG( Ok(), 0, "invalid image" );
275 return M_IMGDATA
->m_maskGreen
;
278 unsigned char wxImage::GetMaskBlue() const
280 wxCHECK_MSG( Ok(), 0, "invalid image" );
282 return M_IMGDATA
->m_maskBlue
;
285 void wxImage::SetMask( bool mask
)
287 wxCHECK_RET( Ok(), "invalid image" );
289 M_IMGDATA
->m_hasMask
= mask
;
292 bool wxImage::HasMask() const
294 wxCHECK_MSG( Ok(), FALSE
, "invalid image" );
296 return M_IMGDATA
->m_hasMask
;
299 int wxImage::GetWidth() const
301 wxCHECK_MSG( Ok(), 0, "invalid image" );
303 return M_IMGDATA
->m_width
;
306 int wxImage::GetHeight() const
308 wxCHECK_MSG( Ok(), 0, "invalid image" );
310 return M_IMGDATA
->m_height
;
313 bool wxImage::LoadFile( const wxString
& filename
, long type
)
316 if (wxFileExists(filename
))
318 wxFileInputStream
stream(filename
);
319 return LoadFile(stream
, type
);
323 wxLogError( "Can't load image from file '%s': file does not exist.", filename
.c_str() );
327 #else // !wxUSE_STREAMS
329 #endif // wxUSE_STREAMS
332 bool wxImage::SaveFile( const wxString
& filename
, int type
)
335 wxFileOutputStream
stream(filename
);
337 if ( stream
.LastError() == wxStream_NOERROR
)
338 return SaveFile(stream
, type
);
340 #endif // wxUSE_STREAMS
345 bool wxImage::LoadFile( wxInputStream
& stream
, long type
)
349 m_refData
= new wxImageRefData
;
351 wxImageHandler
*handler
= FindHandler(type
);
355 wxLogWarning( "No image handler for type %d defined.", type
);
360 return handler
->LoadFile( this, stream
);
363 bool wxImage::SaveFile( wxOutputStream
& stream
, int type
)
365 wxCHECK_MSG( Ok(), FALSE
, "invalid image" );
367 wxImageHandler
*handler
= FindHandler(type
);
371 wxLogWarning( "No image handler for type %d defined.", type
);
376 return handler
->SaveFile( this, stream
);
378 #endif // wxUSE_STREAMS
380 void wxImage::AddHandler( wxImageHandler
*handler
)
382 // make sure that the memory will be freed at the program end
383 sm_handlers
.DeleteContents(TRUE
);
385 sm_handlers
.Append( handler
);
388 void wxImage::InsertHandler( wxImageHandler
*handler
)
390 // make sure that the memory will be freed at the program end
391 sm_handlers
.DeleteContents(TRUE
);
393 sm_handlers
.Insert( handler
);
396 bool wxImage::RemoveHandler( const wxString
& name
)
398 wxImageHandler
*handler
= FindHandler(name
);
401 sm_handlers
.DeleteObject(handler
);
408 wxImageHandler
*wxImage::FindHandler( const wxString
& name
)
410 wxNode
*node
= sm_handlers
.First();
413 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
414 if (handler
->GetName().Cmp(name
) == 0) return handler
;
418 return (wxImageHandler
*)NULL
;
421 wxImageHandler
*wxImage::FindHandler( const wxString
& extension
, long bitmapType
)
423 wxNode
*node
= sm_handlers
.First();
426 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
427 if ( (handler
->GetExtension().Cmp(extension
) == 0) &&
428 (bitmapType
== -1 || handler
->GetType() == bitmapType
) )
432 return (wxImageHandler
*)NULL
;
435 wxImageHandler
*wxImage::FindHandler( long bitmapType
)
437 wxNode
*node
= sm_handlers
.First();
440 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
441 if (handler
->GetType() == bitmapType
) return handler
;
447 void wxImage::InitStandardHandlers()
449 AddHandler( new wxBMPHandler
);
451 AddHandler( new wxPNGHandler
);
455 void wxImage::CleanUpHandlers()
457 wxNode
*node
= sm_handlers
.First();
460 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
461 wxNode
*next
= node
->Next();
468 //-----------------------------------------------------------------------------
470 //-----------------------------------------------------------------------------
472 #if !USE_SHARED_LIBRARIES
473 IMPLEMENT_DYNAMIC_CLASS(wxImageHandler
,wxObject
)
477 bool wxImageHandler::LoadFile( wxImage
*WXUNUSED(image
), wxInputStream
& WXUNUSED(stream
) )
482 bool wxImageHandler::SaveFile( wxImage
*WXUNUSED(image
), wxOutputStream
& WXUNUSED(stream
) )
486 #endif // wxUSE_STREAMS
488 //-----------------------------------------------------------------------------
490 //-----------------------------------------------------------------------------
494 #if !USE_SHARED_LIBRARIES
495 IMPLEMENT_DYNAMIC_CLASS(wxPNGHandler
,wxImageHandler
)
500 static void _PNG_stream_reader( png_structp png_ptr
, png_bytep data
, png_size_t length
)
502 ((wxInputStream
*) png_get_io_ptr( png_ptr
)) -> Read(data
, length
);
505 static void _PNG_stream_writer( png_structp png_ptr
, png_bytep data
, png_size_t length
)
507 ((wxOutputStream
*) png_get_io_ptr( png_ptr
)) -> Write(data
, length
);
510 bool wxPNGHandler::LoadFile( wxImage
*image
, wxInputStream
& stream
)
512 // VZ: as this function uses setjmp() the only fool proof error handling
513 // method is to use goto (setjmp is not really C++ dtors friendly...)
515 unsigned char **lines
= (unsigned char **) NULL
;
517 png_infop info_ptr
= (png_infop
) NULL
;
521 png_structp png_ptr
= png_create_read_struct( PNG_LIBPNG_VER_STRING
,
523 (png_error_ptr
) NULL
,
524 (png_error_ptr
) NULL
);
528 info_ptr
= png_create_info_struct( png_ptr
);
532 if (setjmp(png_ptr
->jmpbuf
))
535 if (info_ptr
->color_type
== PNG_COLOR_TYPE_RGB_ALPHA
)
538 png_set_read_fn( png_ptr
, &stream
, _PNG_stream_reader
);
540 png_uint_32 width
,height
;
541 int bit_depth
,color_type
,interlace_type
;
543 png_read_info( png_ptr
, info_ptr
);
544 png_get_IHDR( png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
, &interlace_type
, (int*) NULL
, (int*) NULL
);
546 if (color_type
== PNG_COLOR_TYPE_PALETTE
)
547 png_set_expand( png_ptr
);
549 png_set_strip_16( png_ptr
);
550 png_set_packing( png_ptr
);
551 if (png_get_valid( png_ptr
, info_ptr
, PNG_INFO_tRNS
))
552 png_set_expand( png_ptr
);
553 png_set_filler( png_ptr
, 0xff, PNG_FILLER_AFTER
);
555 image
->Create( width
, height
);
560 lines
= (unsigned char **)malloc( height
* sizeof(unsigned char *) );
564 for (i
= 0; i
< height
; i
++)
566 if ((lines
[i
] = (unsigned char *)malloc(width
* (sizeof(unsigned char) * 4))) == NULL
)
568 for ( unsigned int n
= 0; n
< i
; n
++ )
574 // loaded successfully!
577 png_read_image( png_ptr
, lines
);
578 png_destroy_read_struct( &png_ptr
, &info_ptr
, (png_infopp
) NULL
);
579 unsigned char *ptr
= image
->GetData();
580 if ((color_type
== PNG_COLOR_TYPE_GRAY
) ||
581 (color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
))
583 for (unsigned int y
= 0; y
< height
; y
++)
585 unsigned char *ptr2
= lines
[y
];
586 for (unsigned int x
= 0; x
< width
; x
++)
588 unsigned char r
= *ptr2
++;
589 unsigned char a
= *ptr2
++;
608 for (unsigned int y
= 0; y
< height
; y
++)
610 unsigned char *ptr2
= lines
[y
];
611 for (unsigned int x
= 0; x
< width
; x
++)
613 unsigned char r
= *ptr2
++;
614 unsigned char g
= *ptr2
++;
615 unsigned char b
= *ptr2
++;
616 unsigned char a
= *ptr2
++;
626 if ((r
== 255) && (g
== 0) && (b
== 255)) r
= 254;
635 for ( unsigned int j
= 0; j
< height
; j
++ )
641 image
->SetMaskColour( 255, 0, 255 );
645 image
->SetMask( FALSE
);
652 wxLogError(_("Couldn't load a PNG image - probably file is corrupted."));
668 png_destroy_read_struct( &png_ptr
, &info_ptr
, (png_infopp
) NULL
);
672 png_destroy_read_struct( &png_ptr
, (png_infopp
) NULL
, (png_infopp
) NULL
);
678 bool wxPNGHandler::SaveFile( wxImage
*image
, wxOutputStream
& stream
)
681 png_structp png_ptr
= png_create_write_struct( PNG_LIBPNG_VER_STRING
, NULL
, NULL
, NULL
);
687 png_infop info_ptr
= png_create_info_struct(png_ptr
);
688 if (info_ptr
== NULL
)
690 png_destroy_write_struct( &png_ptr
, (png_infopp
)NULL
);
694 if (setjmp(png_ptr
->jmpbuf
))
696 png_destroy_write_struct( &png_ptr
, (png_infopp
)NULL
);
700 png_set_write_fn( png_ptr
, &stream
, _PNG_stream_writer
, NULL
);
702 png_set_IHDR( png_ptr
, info_ptr
, image
->GetWidth(), image
->GetHeight(), 8,
703 PNG_COLOR_TYPE_RGB_ALPHA
, PNG_INTERLACE_NONE
,
704 PNG_COMPRESSION_TYPE_BASE
, PNG_FILTER_TYPE_BASE
);
711 png_set_sBIT( png_ptr
, info_ptr
, &sig_bit
);
712 png_write_info( png_ptr
, info_ptr
);
713 png_set_shift( png_ptr
, &sig_bit
);
714 png_set_packing( png_ptr
);
716 unsigned char *data
= (unsigned char *)malloc( image
->GetWidth()*4 );
719 png_destroy_write_struct( &png_ptr
, (png_infopp
)NULL
);
723 for (int y
= 0; y
< image
->GetHeight(); y
++)
725 unsigned char *ptr
= image
->GetData() + (y
* image
->GetWidth() * 3);
726 for (int x
= 0; x
< image
->GetWidth(); x
++)
728 data
[(x
<< 2) + 0] = *ptr
++;
729 data
[(x
<< 2) + 1] = *ptr
++;
730 data
[(x
<< 2) + 2] = *ptr
++;
731 if ((data
[(x
<< 2) + 0] == image
->GetMaskRed()) &&
732 (data
[(x
<< 2) + 1] == image
->GetMaskGreen()) &&
733 (data
[(x
<< 2) + 2] == image
->GetMaskBlue()))
735 data
[(x
<< 2) + 3] = 0;
739 data
[(x
<< 2) + 3] = 255;
742 png_bytep row_ptr
= data
;
743 png_write_rows( png_ptr
, &row_ptr
, 1 );
747 png_write_end( png_ptr
, info_ptr
);
748 png_destroy_write_struct( &png_ptr
, (png_infopp
)&info_ptr
);
752 #endif // wxUSE_STREAMS
758 //-----------------------------------------------------------------------------
760 //-----------------------------------------------------------------------------
762 #if !USE_SHARED_LIBRARIES
763 IMPLEMENT_DYNAMIC_CLASS(wxBMPHandler
,wxImageHandler
)
767 bool wxBMPHandler::LoadFile( wxImage
*image
, wxInputStream
& stream
)
769 unsigned char *data
, *ptr
;
770 int done
, i
, bpp
, planes
, comp
, ncolors
, line
, column
,
771 linesize
, linepos
, rshift
= 0, gshift
= 0, bshift
= 0;
774 long int dbuf
[4], dword
, rmask
= 0, gmask
= 0, bmask
= 0, offset
,
776 off_t start_offset
= stream
.TellI();
780 unsigned char r
, g
, b
;
790 #define BI_BITFIELDS 3
797 * Reading the bmp header
800 stream
.Read(&bbuf
, 2);
802 stream
.Read(dbuf
, 4 * 4);
807 stream
.Read(dbuf
, 4 * 2);
808 int width
= (int)dbuf
[0];
809 int height
= (int)dbuf
[1];
812 wxLogError( "Image width > 32767 pixels for file\n" );
817 wxLogError( "Image height > 32767 pixels for file\n" );
820 stream
.Read(&word
, 2);
822 stream
.Read(&word
, 2);
824 if (bpp
!= 1 && bpp
!= 4 && bpp
!= 8 && bpp
&& 16 && bpp
!= 24 && bpp
!= 32)
826 wxLogError( "unknown bitdepth in file\n" );
829 stream
.Read(dbuf
, 4 * 4);
831 if (comp
!= BI_RGB
&& comp
!= BI_RLE4
&& comp
!= BI_RLE8
&& comp
!= BI_BITFIELDS
)
833 wxLogError( "unknown encoding in Windows BMP file\n" );
836 stream
.Read(dbuf
, 4 * 2);
837 ncolors
= (int)dbuf
[0];
840 /* some more sanity checks */
841 if (((comp
== BI_RLE4
) && (bpp
!= 4)) || ((comp
== BI_RLE8
) && (bpp
!= 8)) || ((comp
== BI_BITFIELDS
) && (bpp
!= 16 && bpp
!= 32)))
843 wxLogError( "encoding of BMP doesn't match bitdepth\n" );
848 cmap
= (struct _cmap
*)malloc(sizeof(struct _cmap
) * ncolors
);
852 wxLogError( "Cannot allocate RAM for color map in BMP file\n" );
859 image
->Create( width
, height
);
860 ptr
= image
->GetData();
863 wxLogError( "Cannot allocate RAM for RGB data in file\n" );
870 * Reading the palette, if it exists.
872 if (bpp
< 16 && ncolors
!= 0)
874 for (i
= 0; i
< ncolors
; i
++)
876 stream
.Read(bbuf
, 4);
882 else if (bpp
== 16 || bpp
== 32)
884 if (comp
== BI_BITFIELDS
)
888 stream
.Read(dbuf
, 4 * 3);
892 /* find shift amount.. ugly, but i can't think of a better way */
893 for (bit
= 0; bit
< bpp
; bit
++)
895 if (bmask
& (1 << bit
))
897 if (gmask
& (1 << bit
))
899 if (rmask
& (1 << bit
))
924 * Reading the image data
926 stream
.SeekI(start_offset
+ offset
);
929 /* set the whole image to the background color */
930 if (bpp
< 16 && (comp
== BI_RLE4
|| comp
== BI_RLE8
))
932 for (i
= 0; i
< width
* height
; i
++)
942 #define poffset (line * width * 3 + column * 3)
945 * BMPs are stored upside down... hmmmmmmmmmm....
948 linesize
= ((width
* bpp
+ 31) / 32) * 4;
949 for (line
= (height
- 1); line
>= 0; line
--)
952 for (column
= 0; column
< width
;)
959 aByte
= stream
.GetC();
964 for (bit
= 0; bit
< 8; bit
++)
966 index
= ((aByte
& (0x80 >> bit
)) ? 1 : 0);
967 ptr
[poffset
] = cmap
[index
].r
;
968 ptr
[poffset
+ 1] = cmap
[index
].g
;
969 ptr
[poffset
+ 2] = cmap
[index
].b
;
977 wxLogError( "can't deal with 4bit encoded yet.\n");
986 for (nibble
= 0; nibble
< 2; nibble
++)
988 index
= ((aByte
& (0xF0 >> nibble
* 4)) >> (!nibble
* 4));
991 ptr
[poffset
] = cmap
[index
].r
;
992 ptr
[poffset
+ 1] = cmap
[index
].g
;
993 ptr
[poffset
+ 2] = cmap
[index
].b
;
1000 if (comp
== BI_RLE8
)
1002 unsigned char first
;
1005 aByte
= stream
.GetC();
1010 /* column = width; */
1012 else if (aByte
== 1)
1017 else if (aByte
== 2)
1019 aByte
= stream
.GetC();
1021 linepos
= column
* bpp
/ 8;
1022 aByte
= stream
.GetC();
1027 int absolute
= aByte
;
1029 for (i
= 0; i
< absolute
; i
++)
1032 aByte
= stream
.GetC();
1033 ptr
[poffset
] = cmap
[aByte
].r
;
1034 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
1035 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
1038 if (absolute
& 0x01)
1039 aByte
= stream
.GetC();
1044 for (i
= 0; i
< first
; i
++)
1046 ptr
[poffset
] = cmap
[aByte
].r
;
1047 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
1048 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
1056 ptr
[poffset
] = cmap
[aByte
].r
;
1057 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
1058 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
1066 stream
.Read(&bbuf
, 3);
1068 ptr
[poffset
] = (unsigned char)bbuf
[2];
1069 ptr
[poffset
+ 1] = (unsigned char)bbuf
[1];
1070 ptr
[poffset
+ 2] = (unsigned char)bbuf
[0];
1077 stream
.Read(&word
, 2);
1079 temp
= (word
& rmask
) >> rshift
;
1080 ptr
[poffset
] = temp
;
1081 temp
= (word
& gmask
) >> gshift
;
1082 ptr
[poffset
+ 1] = temp
;
1083 temp
= (word
& bmask
) >> gshift
;
1084 ptr
[poffset
+ 2] = temp
;
1091 stream
.Read(&dword
, 4);
1093 temp
= (dword
& rmask
) >> rshift
;
1094 ptr
[poffset
] = temp
;
1095 temp
= (dword
& gmask
) >> gshift
;
1096 ptr
[poffset
+ 1] = temp
;
1097 temp
= (dword
& bmask
) >> bshift
;
1098 ptr
[poffset
+ 2] = temp
;
1102 while ((linepos
< linesize
) && (comp
!= 1) && (comp
!= 2))
1104 stream
.Read(&aByte
, 1);
1106 if (stream
.LastError() != wxStream_NOERROR
)
1110 if (cmap
) free(cmap
);
1112 image
->SetMask( FALSE
);
1116 #endif // wxUSE_STREAMS
1120 wxBitmap
wxImage::ConvertToBitmap() const
1122 // sizeLimit is the MS upper limit for the DIB size
1123 int sizeLimit
= 1024*768*3;
1125 // width and height of the device-dependent bitmap
1126 int width
= GetWidth();
1127 int bmpHeight
= GetHeight();
1129 // calc the number of bytes per scanline and padding
1130 int bytePerLine
= width
*3;
1131 int sizeDWORD
= sizeof( DWORD
);
1132 div_t lineBoundary
= div( bytePerLine
, sizeDWORD
);
1134 if( lineBoundary
.rem
> 0 )
1136 padding
= sizeDWORD
- lineBoundary
.rem
;
1137 bytePerLine
+= padding
;
1139 // calc the number of DIBs and heights of DIBs
1142 int height
= sizeLimit
/bytePerLine
;
1143 if( height
>= bmpHeight
)
1147 div_t result
= div( bmpHeight
, height
);
1148 numDIB
= result
.quot
;
1149 hRemain
= result
.rem
;
1150 if( hRemain
>0 ) numDIB
++;
1153 // set bitmap parameters
1155 wxCHECK_MSG( Ok(), bitmap
, "invalid image" );
1156 bitmap
.SetWidth( width
);
1157 bitmap
.SetHeight( bmpHeight
);
1158 bitmap
.SetDepth( wxDisplayDepth() );
1160 // create a DIB header
1161 int headersize
= sizeof(BITMAPINFOHEADER
);
1162 LPBITMAPINFO lpDIBh
= (BITMAPINFO
*) malloc( headersize
);
1163 wxCHECK_MSG( lpDIBh
, bitmap
, "could not allocate memory for DIB header" );
1164 // Fill in the DIB header
1165 lpDIBh
->bmiHeader
.biSize
= headersize
;
1166 lpDIBh
->bmiHeader
.biWidth
= (DWORD
)width
;
1167 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
1168 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
1169 // the general formula for biSizeImage:
1170 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
1171 lpDIBh
->bmiHeader
.biPlanes
= 1;
1172 lpDIBh
->bmiHeader
.biBitCount
= 24;
1173 lpDIBh
->bmiHeader
.biCompression
= BI_RGB
;
1174 lpDIBh
->bmiHeader
.biClrUsed
= 0;
1175 // These seem not really needed for our purpose here.
1176 lpDIBh
->bmiHeader
.biClrImportant
= 0;
1177 lpDIBh
->bmiHeader
.biXPelsPerMeter
= 0;
1178 lpDIBh
->bmiHeader
.biYPelsPerMeter
= 0;
1179 // memory for DIB data
1180 unsigned char *lpBits
;
1181 lpBits
= (unsigned char *)malloc( lpDIBh
->bmiHeader
.biSizeImage
);
1184 wxFAIL_MSG( "could not allocate memory for DIB" );
1189 // create and set the device-dependent bitmap
1190 HDC hdc
= ::GetDC(NULL
);
1191 HDC memdc
= ::CreateCompatibleDC( hdc
);
1193 hbitmap
= ::CreateCompatibleBitmap( hdc
, width
, bmpHeight
);
1194 ::SelectObject( memdc
, hbitmap
);
1196 // copy image data into DIB data and then into DDB (in a loop)
1197 unsigned char *data
= GetData();
1200 unsigned char *ptdata
= data
;
1201 unsigned char *ptbits
;
1203 for( n
=0; n
<numDIB
; n
++ )
1205 if( numDIB
> 1 && n
== numDIB
-1 && hRemain
> 0 )
1207 // redefine height and size of the (possibly) last smaller DIB
1208 // memory is not reallocated
1210 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
1211 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
1215 for( j
=0; j
<height
; j
++ )
1217 for( i
=0; i
<width
; i
++ )
1219 *(ptbits
++) = *(ptdata
+2);
1220 *(ptbits
++) = *(ptdata
+1);
1221 *(ptbits
++) = *(ptdata
);
1224 for( i
=0; i
< padding
; i
++ ) *(ptbits
++) = 0;
1226 ::StretchDIBits( memdc
, 0, origin
, width
, height
,\
1227 0, 0, width
, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
, SRCCOPY
);
1229 // if numDIB = 1, lines below can also be used
1230 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
1231 // The above line is equivalent to the following two lines.
1232 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
1233 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
1234 // or the following lines
1235 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
1236 // HDC memdc = ::CreateCompatibleDC( hdc );
1237 // ::SelectObject( memdc, hbitmap);
1238 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
1239 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
1240 // ::SelectObject( memdc, 0 );
1241 // ::DeleteDC( memdc );
1243 bitmap
.SetHBITMAP( (WXHBITMAP
) hbitmap
);
1245 // similarly, created an mono-bitmap for the possible mask
1248 hbitmap
= ::CreateBitmap( (WORD
)width
, (WORD
)bmpHeight
, 1, 1, NULL
);
1249 ::SelectObject( memdc
, hbitmap
);
1250 if( numDIB
== 1 ) height
= bmpHeight
;
1251 else height
= sizeLimit
/bytePerLine
;
1252 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
1253 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
1255 unsigned char r
= GetMaskRed();
1256 unsigned char g
= GetMaskGreen();
1257 unsigned char b
= GetMaskBlue();
1258 unsigned char zero
= 0, one
= 255;
1260 for( n
=0; n
<numDIB
; n
++ )
1262 if( numDIB
> 1 && n
== numDIB
- 1 && hRemain
> 0 )
1264 // redefine height and size of the (possibly) last smaller DIB
1265 // memory is not reallocated
1267 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
1268 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
1271 for( int j
=0; j
<height
; j
++ )
1273 for( int i
=0; i
<width
; i
++ )
1275 if( (*(ptdata
++)!=r
) | (*(ptdata
++)!=g
) | (*(ptdata
++)!=b
) )
1288 for( i
=0; i
< padding
; i
++ ) *(ptbits
++) = zero
;
1290 ::StretchDIBits( memdc
, 0, origin
, width
, height
,\
1291 0, 0, width
, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
, SRCCOPY
);
1294 // create a wxMask object
1295 wxMask
*mask
= new wxMask();
1296 mask
->SetMaskBitmap( (WXHBITMAP
) hbitmap
);
1297 bitmap
.SetMask( mask
);
1298 // It will be deleted when the wxBitmap object is deleted (as of 01/1999)
1299 /* The following can also be used but is slow to run
1300 wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
1301 wxMask *mask = new wxMask( bitmap, colour );
1302 bitmap.SetMask( mask );
1306 // free allocated resources
1307 ::SelectObject( memdc
, 0 );
1308 ::DeleteDC( memdc
);
1309 ::ReleaseDC(NULL
, hdc
);
1313 // check the wxBitmap object
1314 if( bitmap
.GetHBITMAP() )
1315 bitmap
.SetOk( TRUE
);
1317 bitmap
.SetOk( FALSE
);
1322 wxImage::wxImage( const wxBitmap
&bitmap
)
1327 wxFAIL_MSG( "invalid bitmap" );
1331 // create an wxImage object
1332 int width
= bitmap
.GetWidth();
1333 int height
= bitmap
.GetHeight();
1334 Create( width
, height
);
1335 unsigned char *data
= GetData();
1338 wxFAIL_MSG( "could not allocate data for image" );
1342 // calc the number of bytes per scanline and padding in the DIB
1343 int bytePerLine
= width
*3;
1344 int sizeDWORD
= sizeof( DWORD
);
1345 div_t lineBoundary
= div( bytePerLine
, sizeDWORD
);
1347 if( lineBoundary
.rem
> 0 )
1349 padding
= sizeDWORD
- lineBoundary
.rem
;
1350 bytePerLine
+= padding
;
1353 // create a DIB header
1354 int headersize
= sizeof(BITMAPINFOHEADER
);
1355 LPBITMAPINFO lpDIBh
= (BITMAPINFO
*) malloc( headersize
);
1358 wxFAIL_MSG( "could not allocate data for DIB header" );
1362 // Fill in the DIB header
1363 lpDIBh
->bmiHeader
.biSize
= headersize
;
1364 lpDIBh
->bmiHeader
.biWidth
= width
;
1365 lpDIBh
->bmiHeader
.biHeight
= -height
;
1366 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
* height
;
1367 lpDIBh
->bmiHeader
.biPlanes
= 1;
1368 lpDIBh
->bmiHeader
.biBitCount
= 24;
1369 lpDIBh
->bmiHeader
.biCompression
= BI_RGB
;
1370 lpDIBh
->bmiHeader
.biClrUsed
= 0;
1371 // These seem not really needed for our purpose here.
1372 lpDIBh
->bmiHeader
.biClrImportant
= 0;
1373 lpDIBh
->bmiHeader
.biXPelsPerMeter
= 0;
1374 lpDIBh
->bmiHeader
.biYPelsPerMeter
= 0;
1375 // memory for DIB data
1376 unsigned char *lpBits
;
1377 lpBits
= (unsigned char *) malloc( lpDIBh
->bmiHeader
.biSizeImage
);
1380 wxFAIL_MSG( "could not allocate data for DIB" );
1386 // copy data from the device-dependent bitmap to the DIB
1387 HDC hdc
= ::GetDC(NULL
);
1389 hbitmap
= (HBITMAP
) bitmap
.GetHBITMAP();
1390 ::GetDIBits( hdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
1392 // copy DIB data into the wxImage object
1394 unsigned char *ptdata
= data
;
1395 unsigned char *ptbits
= lpBits
;
1396 for( i
=0; i
<height
; i
++ )
1398 for( j
=0; j
<width
; j
++ )
1400 *(ptdata
++) = *(ptbits
+2);
1401 *(ptdata
++) = *(ptbits
+1);
1402 *(ptdata
++) = *(ptbits
);
1408 // similarly, set data according to the possible mask bitmap
1409 if( bitmap
.GetMask() && bitmap
.GetMask()->GetMaskBitmap() )
1411 hbitmap
= (HBITMAP
) bitmap
.GetMask()->GetMaskBitmap();
1412 // memory DC created, color set, data copied, and memory DC deleted
1413 HDC memdc
= ::CreateCompatibleDC( hdc
);
1414 ::SetTextColor( memdc
, RGB( 0, 0, 0 ) );
1415 ::SetBkColor( memdc
, RGB( 255, 255, 255 ) );
1416 ::GetDIBits( memdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
1417 ::DeleteDC( memdc
);
1418 // background color set to RGB(16,16,16) in consistent with wxGTK
1419 unsigned char r
=16, g
=16, b
=16;
1422 for( i
=0; i
<height
; i
++ )
1424 for( j
=0; j
<width
; j
++ )
1438 SetMaskColour( r
, g
, b
);
1445 // free allocated resources
1446 ::ReleaseDC(NULL
, hdc
);
1455 #include "gtk/gtk.h"
1456 #include "gdk/gdk.h"
1457 #include "gdk/gdkx.h"
1459 wxBitmap
wxImage::ConvertToBitmap() const
1463 wxCHECK_MSG( Ok(), bitmap
, "invalid image" );
1465 int width
= GetWidth();
1466 int height
= GetHeight();
1468 bitmap
.SetHeight( height
);
1469 bitmap
.SetWidth( width
);
1473 GdkImage
*data_image
=
1474 gdk_image_new( GDK_IMAGE_FASTEST
, gdk_visual_get_system(), width
, height
);
1476 bitmap
.SetPixmap( gdk_pixmap_new( (GdkWindow
*)&gdk_root_parent
, width
, height
, -1 ) );
1480 GdkImage
*mask_image
= (GdkImage
*) NULL
;
1484 unsigned char *mask_data
= (unsigned char*)malloc( ((width
>> 3)+8) * height
);
1486 mask_image
= gdk_image_new_bitmap( gdk_visual_get_system(), mask_data
, width
, height
);
1488 wxMask
*mask
= new wxMask();
1489 mask
->m_bitmap
= gdk_pixmap_new( (GdkWindow
*)&gdk_root_parent
, width
, height
, 1 );
1491 bitmap
.SetMask( mask
);
1496 GdkVisual
*visual
= gdk_window_get_visual( bitmap
.GetPixmap() );
1497 if (visual
== NULL
) visual
= gdk_window_get_visual( (GdkWindow
*) &gdk_root_parent
);
1498 int bpp
= visual
->depth
;
1500 bitmap
.SetDepth( bpp
);
1502 if ((bpp
== 16) && (visual
->red_mask
!= 0xf800)) bpp
= 15;
1503 if (bpp
< 8) bpp
= 8;
1507 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
1508 byte_order b_o
= RGB
;
1512 GdkVisual
*visual
= gdk_visual_get_system();
1513 if ((visual
->red_mask
> visual
->green_mask
) && (visual
->green_mask
> visual
->blue_mask
)) b_o
= RGB
;
1514 else if ((visual
->red_mask
> visual
->blue_mask
) && (visual
->blue_mask
> visual
->green_mask
)) b_o
= RGB
;
1515 else if ((visual
->blue_mask
> visual
->red_mask
) && (visual
->red_mask
> visual
->green_mask
)) b_o
= BRG
;
1516 else if ((visual
->blue_mask
> visual
->green_mask
) && (visual
->green_mask
> visual
->red_mask
)) b_o
= BGR
;
1517 else if ((visual
->green_mask
> visual
->red_mask
) && (visual
->red_mask
> visual
->blue_mask
)) b_o
= GRB
;
1518 else if ((visual
->green_mask
> visual
->blue_mask
) && (visual
->blue_mask
> visual
->red_mask
)) b_o
= GBR
;
1521 int r_mask
= GetMaskRed();
1522 int g_mask
= GetMaskGreen();
1523 int b_mask
= GetMaskBlue();
1525 unsigned char* data
= GetData();
1528 for (int y
= 0; y
< height
; y
++)
1530 for (int x
= 0; x
< width
; x
++)
1532 int r
= data
[index
];
1534 int g
= data
[index
];
1536 int b
= data
[index
];
1541 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
1542 gdk_image_put_pixel( mask_image
, x
, y
, 1 );
1544 gdk_image_put_pixel( mask_image
, x
, y
, 0 );
1549 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
1550 gdk_image_put_pixel( mask_image
, x
, y
, 1 );
1552 gdk_image_put_pixel( mask_image
, x
, y
, 0 );
1560 if (wxTheApp
->m_colorCube
)
1562 pixel
= wxTheApp
->m_colorCube
[ ((r
& 0xf8) << 7) + ((g
& 0xf8) << 2) + ((b
& 0xf8) >> 3) ];
1566 GdkColormap
*cmap
= gtk_widget_get_default_colormap();
1567 GdkColor
*colors
= cmap
->colors
;
1568 int max
= 3 * (65536);
1570 for (int i
= 0; i
< cmap
->size
; i
++)
1572 int rdiff
= (r
<< 8) - colors
[i
].red
;
1573 int gdiff
= (g
<< 8) - colors
[i
].green
;
1574 int bdiff
= (b
<< 8) - colors
[i
].blue
;
1575 int sum
= ABS (rdiff
) + ABS (gdiff
) + ABS (bdiff
);
1576 if (sum
< max
) { pixel
= i
; max
= sum
; }
1580 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1586 guint32 pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
1587 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1592 guint32 pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
1593 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1602 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
1603 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
1604 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
1605 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
1606 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
1607 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
1609 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1618 GdkGC
*data_gc
= gdk_gc_new( bitmap
.GetPixmap() );
1620 gdk_draw_image( bitmap
.GetPixmap(), data_gc
, data_image
, 0, 0, 0, 0, width
, height
);
1622 gdk_image_destroy( data_image
);
1623 gdk_gc_unref( data_gc
);
1629 GdkGC
*mask_gc
= gdk_gc_new( bitmap
.GetMask()->GetBitmap() );
1631 gdk_draw_image( bitmap
.GetMask()->GetBitmap(), mask_gc
, mask_image
, 0, 0, 0, 0, width
, height
);
1633 gdk_image_destroy( mask_image
);
1634 gdk_gc_unref( mask_gc
);
1640 wxImage::wxImage( const wxBitmap
&bitmap
)
1642 wxCHECK_RET( bitmap
.Ok(), "invalid bitmap" );
1644 GdkImage
*gdk_image
= gdk_image_get( bitmap
.GetPixmap(),
1646 bitmap
.GetWidth(), bitmap
.GetHeight() );
1648 wxCHECK_RET( gdk_image
, "couldn't create image" );
1650 Create( bitmap
.GetWidth(), bitmap
.GetHeight() );
1651 char unsigned *data
= GetData();
1655 gdk_image_destroy( gdk_image
);
1656 wxFAIL_MSG( "couldn't create image" );
1660 GdkImage
*gdk_image_mask
= (GdkImage
*) NULL
;
1661 if (bitmap
.GetMask())
1663 gdk_image_mask
= gdk_image_get( bitmap
.GetMask()->GetBitmap(),
1665 bitmap
.GetWidth(), bitmap
.GetHeight() );
1667 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1670 GdkVisual
*visual
= gdk_window_get_visual( bitmap
.GetPixmap() );
1671 if (visual
== NULL
) visual
= gdk_window_get_visual( (GdkWindow
*) &gdk_root_parent
);
1672 int bpp
= visual
->depth
;
1673 if ((bpp
== 16) && (visual
->red_mask
!= 0xf800)) bpp
= 15;
1675 GdkColormap
*cmap
= gtk_widget_get_default_colormap();
1678 for (int j
= 0; j
< bitmap
.GetHeight(); j
++)
1680 for (int i
= 0; i
< bitmap
.GetWidth(); i
++)
1682 int pixel
= gdk_image_get_pixel( gdk_image
, i
, j
);
1685 data
[pos
] = cmap
->colors
[pixel
].red
>> 8;
1686 data
[pos
+1] = cmap
->colors
[pixel
].green
>> 8;
1687 data
[pos
+2] = cmap
->colors
[pixel
].blue
>> 8;
1688 } else if (bpp
== 15)
1690 data
[pos
] = (pixel
>> 7) & 0xf8;
1691 data
[pos
+1] = (pixel
>> 2) & 0xf8;
1692 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1693 } else if (bpp
== 16)
1695 data
[pos
] = (pixel
>> 8) & 0xf8;
1696 data
[pos
+1] = (pixel
>> 3) & 0xfc;
1697 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1700 data
[pos
] = (pixel
>> 16) & 0xff;
1701 data
[pos
+1] = (pixel
>> 8) & 0xff;
1702 data
[pos
+2] = pixel
& 0xff;
1707 int mask_pixel
= gdk_image_get_pixel( gdk_image_mask
, i
, j
);
1708 if (mask_pixel
== 0)
1720 gdk_image_destroy( gdk_image
);
1721 if (gdk_image_mask
) gdk_image_destroy( gdk_image_mask
);
1729 #include "wx/utils.h"
1732 wxBitmap
wxImage::ConvertToBitmap() const
1736 wxCHECK_MSG( Ok(), bitmap
, "invalid image" );
1738 int width
= GetWidth();
1739 int height
= GetHeight();
1741 bitmap
.SetHeight( height
);
1742 bitmap
.SetWidth( width
);
1744 Display
*dpy
= (Display
*) wxGetDisplay();
1745 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1746 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1750 XImage
*data_image
= XCreateImage( dpy
, vis
, bpp
, ZPixmap
, 0, 0, width
, height
, 32, 0 );
1751 data_image
->data
= new char[ data_image
->bytes_per_line
* data_image
->height
];
1753 bitmap
.Create( width
, height
, bpp
);
1758 GdkImage *mask_image = (GdkImage*) NULL;
1762 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1764 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1766 wxMask *mask = new wxMask();
1767 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1769 bitmap.SetMask( mask );
1773 // Retrieve depth info
1775 XVisualInfo vinfo_template
;
1778 vinfo_template
.visual
= vis
;
1779 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1780 vinfo_template
.depth
= bpp
;
1783 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
1787 printf("no visual.\n" );
1788 return wxNullBitmap
;
1793 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1794 if (bpp
< 8) bpp
= 8;
1798 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
1799 byte_order b_o
= RGB
;
1803 if ((vi
->red_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->blue_mask
)) b_o
= RGB
;
1804 else if ((vi
->red_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->green_mask
)) b_o
= RGB
;
1805 else if ((vi
->blue_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->green_mask
)) b_o
= BRG
;
1806 else if ((vi
->blue_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->red_mask
)) b_o
= BGR
;
1807 else if ((vi
->green_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->blue_mask
)) b_o
= GRB
;
1808 else if ((vi
->green_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->red_mask
)) b_o
= GBR
;
1812 int r_mask = GetMaskRed();
1813 int g_mask = GetMaskGreen();
1814 int b_mask = GetMaskBlue();
1820 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap( dpy
);
1822 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
1823 XQueryColors( dpy
, cmap
, colors
, 256 );
1826 unsigned char* data
= GetData();
1829 for (int y
= 0; y
< height
; y
++)
1831 for (int x
= 0; x
< width
; x
++)
1833 int r
= data
[index
];
1835 int g
= data
[index
];
1837 int b
= data
[index
];
1843 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1844 gdk_image_put_pixel( mask_image, x, y, 1 );
1846 gdk_image_put_pixel( mask_image, x, y, 0 );
1856 if (wxTheApp->m_colorCube)
1858 pixel = wxTheApp->m_colorCube
1859 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1864 int max
= 3 * (65536);
1865 for (int i
= 0; i
< 256; i
++)
1867 int rdiff
= (r
<< 8) - colors
[i
].red
;
1868 int gdiff
= (g
<< 8) - colors
[i
].green
;
1869 int bdiff
= (b
<< 8) - colors
[i
].blue
;
1870 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
1871 if (sum
< max
) { pixel
= i
; max
= sum
; }
1876 XPutPixel( data_image
, x
, y
, pixel
);
1881 int pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
1882 XPutPixel( data_image
, x
, y
, pixel
);
1887 int pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
1888 XPutPixel( data_image
, x
, y
, pixel
);
1897 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
1898 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
1899 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
1900 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
1901 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
1902 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
1904 XPutPixel( data_image
, x
, y
, pixel
);
1914 gcvalues
.foreground
= BlackPixel( dpy
, DefaultScreen( dpy
) );
1915 GC gc
= XCreateGC( dpy
, RootWindow ( dpy
, DefaultScreen(dpy
) ), GCForeground
, &gcvalues
);
1916 XPutImage( dpy
, (Drawable
)bitmap
.GetPixmap(), gc
, data_image
, 0, 0, 0, 0, width
, height
);
1918 XDestroyImage( data_image
);
1926 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
1928 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
1930 gdk_image_destroy( mask_image );
1931 gdk_gc_unref( mask_gc );
1938 wxImage::wxImage( const wxBitmap
&bitmap
)
1940 wxCHECK_RET( bitmap
.Ok(), "invalid bitmap" );
1942 Display
*dpy
= (Display
*) wxGetDisplay();
1943 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1944 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1946 XImage
*ximage
= XGetImage( dpy
,
1947 (Drawable
)bitmap
.GetPixmap(),
1949 bitmap
.GetWidth(), bitmap
.GetHeight(),
1950 AllPlanes
, ZPixmap
);
1952 wxCHECK_RET( ximage
, "couldn't create image" );
1954 Create( bitmap
.GetWidth(), bitmap
.GetHeight() );
1955 char unsigned *data
= GetData();
1959 XDestroyImage( ximage
);
1960 wxFAIL_MSG( "couldn't create image" );
1965 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1966 if (bitmap.GetMask())
1968 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1970 bitmap.GetWidth(), bitmap.GetHeight() );
1972 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1976 // Retrieve depth info
1978 XVisualInfo vinfo_template
;
1981 vinfo_template
.visual
= vis
;
1982 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1983 vinfo_template
.depth
= bpp
;
1986 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
1990 printf("no visual.\n" );
1994 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
2001 Colormap cmap
= (Colormap
)wxTheApp
->GetMainColormap( dpy
);
2003 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
2004 XQueryColors( dpy
, cmap
, colors
, 256 );
2008 for (int j
= 0; j
< bitmap
.GetHeight(); j
++)
2010 for (int i
= 0; i
< bitmap
.GetWidth(); i
++)
2012 int pixel
= XGetPixel( ximage
, i
, j
);
2015 data
[pos
] = colors
[pixel
].red
>> 8;
2016 data
[pos
+1] = colors
[pixel
].green
>> 8;
2017 data
[pos
+2] = colors
[pixel
].blue
>> 8;
2018 } else if (bpp
== 15)
2020 data
[pos
] = (pixel
>> 7) & 0xf8;
2021 data
[pos
+1] = (pixel
>> 2) & 0xf8;
2022 data
[pos
+2] = (pixel
<< 3) & 0xf8;
2023 } else if (bpp
== 16)
2025 data
[pos
] = (pixel
>> 8) & 0xf8;
2026 data
[pos
+1] = (pixel
>> 3) & 0xfc;
2027 data
[pos
+2] = (pixel
<< 3) & 0xf8;
2030 data
[pos
] = (pixel
>> 16) & 0xff;
2031 data
[pos
+1] = (pixel
>> 8) & 0xff;
2032 data
[pos
+2] = pixel
& 0xff;
2038 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
2039 if (mask_pixel == 0)
2052 XDestroyImage( ximage
);
2054 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );