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"
36 //-----------------------------------------------------------------------------
38 //-----------------------------------------------------------------------------
40 class wxImageRefData
: public wxObjectRefData
45 ~wxImageRefData(void);
49 unsigned char *m_data
;
51 unsigned char m_maskRed
,m_maskGreen
,m_maskBlue
;
55 wxImageRefData::wxImageRefData(void)
59 m_data
= (unsigned char*) NULL
;
67 wxImageRefData::~wxImageRefData(void)
69 if (m_data
) free( m_data
);
72 wxList
wxImage::sm_handlers
;
74 //-----------------------------------------------------------------------------
76 #define M_IMGDATA ((wxImageRefData *)m_refData)
78 #if !USE_SHARED_LIBRARIES
79 IMPLEMENT_DYNAMIC_CLASS(wxImage
, wxObject
)
86 wxImage::wxImage( int width
, int height
)
88 Create( width
, height
);
91 wxImage::wxImage( const wxString
& name
, long type
)
93 LoadFile( name
, type
);
96 wxImage::wxImage( wxInputStream
& stream
, long type
)
98 LoadFile( stream
, type
);
101 wxImage::wxImage( const wxImage
& image
)
106 wxImage::wxImage( const wxImage
* image
)
108 if (image
) Ref(*image
);
111 void wxImage::Create( int width
, int height
)
113 m_refData
= new wxImageRefData();
115 M_IMGDATA
->m_data
= (unsigned char *) malloc( width
*height
*3 );
116 if (M_IMGDATA
->m_data
)
118 for (int l
= 0; l
< width
*height
*3; l
++) M_IMGDATA
->m_data
[l
] = 0;
120 M_IMGDATA
->m_width
= width
;
121 M_IMGDATA
->m_height
= height
;
122 M_IMGDATA
->m_ok
= TRUE
;
130 void wxImage::Destroy()
135 wxImage
wxImage::Scale( int width
, int height
)
139 wxCHECK_MSG( Ok(), image
, "invlaid image" );
141 wxCHECK_MSG( (width
> 0) && (height
> 0), image
, "invalid image size" );
143 image
.Create( width
, height
);
145 char unsigned *data
= image
.GetData();
147 wxCHECK_MSG( data
, image
, "unable to create image" );
149 if (M_IMGDATA
->m_hasMask
)
150 image
.SetMaskColour( M_IMGDATA
->m_maskRed
, M_IMGDATA
->m_maskGreen
, M_IMGDATA
->m_maskBlue
);
152 double xscale
= (double)width
/ (double)M_IMGDATA
->m_width
;
153 double yscale
= (double)height
/ (double)M_IMGDATA
->m_height
;
155 for (int j
= 0; j
< height
; j
++)
157 for (int i
= 0; i
< width
; i
++)
159 int new_pos
= 3*(j
*width
+ i
);
160 int old_pos
= 3*((long)(j
/yscale
)*M_IMGDATA
->m_width
+ (long)(i
/xscale
));
161 data
[ new_pos
] = M_IMGDATA
->m_data
[ old_pos
];
162 data
[ new_pos
+1 ] = M_IMGDATA
->m_data
[ old_pos
+1 ];
163 data
[ new_pos
+2 ] = M_IMGDATA
->m_data
[ old_pos
+2 ];
170 void wxImage::SetRGB( int x
, int y
, unsigned char r
, unsigned char g
, unsigned char b
)
172 wxCHECK_RET( Ok(), "invalid image" );
174 int w
= M_IMGDATA
->m_width
;
175 int h
= M_IMGDATA
->m_height
;
177 wxCHECK_RET( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), "invalid image index" );
179 long pos
= (y
* w
+ x
) * 3;
181 M_IMGDATA
->m_data
[ pos
] = r
;
182 M_IMGDATA
->m_data
[ pos
+1 ] = g
;
183 M_IMGDATA
->m_data
[ pos
+2 ] = b
;
186 unsigned char wxImage::GetRed( int x
, int y
)
188 wxCHECK_MSG( Ok(), 0, "invalid image" );
190 int w
= M_IMGDATA
->m_width
;
191 int h
= M_IMGDATA
->m_height
;
193 wxCHECK_MSG( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), 0, "invalid image index" );
195 long pos
= (y
* w
+ x
) * 3;
197 return M_IMGDATA
->m_data
[pos
];
200 unsigned char wxImage::GetGreen( int x
, int y
)
202 wxCHECK_MSG( Ok(), 0, "invalid image" );
204 int w
= M_IMGDATA
->m_width
;
205 int h
= M_IMGDATA
->m_height
;
207 wxCHECK_MSG( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), 0, "invalid image index" );
209 long pos
= (y
* w
+ x
) * 3;
211 return M_IMGDATA
->m_data
[pos
+1];
214 unsigned char wxImage::GetBlue( int x
, int y
)
216 wxCHECK_MSG( Ok(), 0, "invalid image" );
218 int w
= M_IMGDATA
->m_width
;
219 int h
= M_IMGDATA
->m_height
;
221 wxCHECK_MSG( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), 0, "invalid image index" );
223 long pos
= (y
* w
+ x
) * 3;
225 return M_IMGDATA
->m_data
[pos
+2];
228 bool wxImage::Ok() const
230 return (M_IMGDATA
&& M_IMGDATA
->m_ok
);
233 char unsigned *wxImage::GetData() const
235 wxCHECK_MSG( Ok(), (char unsigned *)NULL
, "invalid image" );
237 return M_IMGDATA
->m_data
;
240 void wxImage::SetData( char unsigned *WXUNUSED(data
) )
242 wxCHECK_RET( Ok(), "invalid image" );
245 void wxImage::SetMaskColour( unsigned char r
, unsigned char g
, unsigned char b
)
247 wxCHECK_RET( Ok(), "invalid image" );
249 M_IMGDATA
->m_maskRed
= r
;
250 M_IMGDATA
->m_maskGreen
= g
;
251 M_IMGDATA
->m_maskBlue
= b
;
252 M_IMGDATA
->m_hasMask
= TRUE
;
255 unsigned char wxImage::GetMaskRed() const
257 wxCHECK_MSG( Ok(), 0, "invalid image" );
259 return M_IMGDATA
->m_maskRed
;
262 unsigned char wxImage::GetMaskGreen() const
264 wxCHECK_MSG( Ok(), 0, "invalid image" );
266 return M_IMGDATA
->m_maskGreen
;
269 unsigned char wxImage::GetMaskBlue() const
271 wxCHECK_MSG( Ok(), 0, "invalid image" );
273 return M_IMGDATA
->m_maskBlue
;
276 void wxImage::SetMask( bool mask
)
278 wxCHECK_RET( Ok(), "invalid image" );
280 M_IMGDATA
->m_hasMask
= mask
;
283 bool wxImage::HasMask() const
285 wxCHECK_MSG( Ok(), FALSE
, "invalid image" );
287 return M_IMGDATA
->m_hasMask
;
290 int wxImage::GetWidth() const
292 wxCHECK_MSG( Ok(), 0, "invalid image" );
294 return M_IMGDATA
->m_width
;
297 int wxImage::GetHeight() const
299 wxCHECK_MSG( Ok(), 0, "invalid image" );
301 return M_IMGDATA
->m_height
;
304 bool wxImage::LoadFile( const wxString
& filename
, long type
)
306 if (wxFileExists(filename
))
308 wxFileInputStream
stream(filename
);
309 return LoadFile(stream
, type
);
313 wxLogWarning( "Image file does not exist." );
319 bool wxImage::LoadFile( wxInputStream
& stream
, long type
)
323 m_refData
= new wxImageRefData
;
325 wxImageHandler
*handler
= FindHandler(type
);
329 wxLogWarning( "No image handler for type %d defined.", type
);
334 return handler
->LoadFile( this, stream
);
337 bool wxImage::SaveFile( const wxString
& filename
, int type
)
339 wxFileOutputStream
stream(filename
);
341 if ( stream
.LastError() == wxStream_NOERROR
)
342 return SaveFile(stream
, type
);
347 bool wxImage::SaveFile( wxOutputStream
& stream
, int type
)
349 wxCHECK_MSG( Ok(), FALSE
, "invalid image" );
351 wxImageHandler
*handler
= FindHandler(type
);
355 wxLogWarning( "No image handler for type %d defined.", type
);
360 return handler
->SaveFile( this, stream
);
363 void wxImage::AddHandler( wxImageHandler
*handler
)
365 sm_handlers
.Append( handler
);
368 void wxImage::InsertHandler( wxImageHandler
*handler
)
370 sm_handlers
.Insert( handler
);
373 bool wxImage::RemoveHandler( const wxString
& name
)
375 wxImageHandler
*handler
= FindHandler(name
);
378 sm_handlers
.DeleteObject(handler
);
385 wxImageHandler
*wxImage::FindHandler( const wxString
& name
)
387 wxNode
*node
= sm_handlers
.First();
390 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
391 if (handler
->GetName() == name
) return handler
;
394 return (wxImageHandler
*)NULL
;
397 wxImageHandler
*wxImage::FindHandler( const wxString
& extension
, long bitmapType
)
399 wxNode
*node
= sm_handlers
.First();
402 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
403 if ( handler
->GetExtension() == extension
&&
404 (bitmapType
== -1 || handler
->GetType() == bitmapType
) )
408 return (wxImageHandler
*)NULL
;
411 wxImageHandler
*wxImage::FindHandler( long bitmapType
)
413 wxNode
*node
= sm_handlers
.First();
416 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
417 if (handler
->GetType() == bitmapType
) return handler
;
423 void wxImage::InitStandardHandlers()
425 AddHandler( new wxBMPHandler
);
427 AddHandler( new wxPNGHandler
);
431 void wxImage::CleanUpHandlers()
433 wxNode
*node
= sm_handlers
.First();
436 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
437 wxNode
*next
= node
->Next();
444 //-----------------------------------------------------------------------------
446 //-----------------------------------------------------------------------------
448 #if !USE_SHARED_LIBRARIES
449 IMPLEMENT_DYNAMIC_CLASS(wxImageHandler
,wxObject
)
452 bool wxImageHandler::LoadFile( wxImage
*WXUNUSED(image
), wxInputStream
& WXUNUSED(stream
) )
457 bool wxImageHandler::SaveFile( wxImage
*WXUNUSED(image
), wxOutputStream
& WXUNUSED(stream
) )
462 //-----------------------------------------------------------------------------
464 //-----------------------------------------------------------------------------
468 #if !USE_SHARED_LIBRARIES
469 IMPLEMENT_DYNAMIC_CLASS(wxPNGHandler
,wxImageHandler
)
473 static void _PNG_stream_reader( png_structp png_ptr
, png_bytep data
, png_size_t length
)
475 ((wxInputStream
*) png_get_io_ptr( png_ptr
)) -> Read(data
, length
);
478 static void _PNG_stream_writer( png_structp png_ptr
, png_bytep data
, png_size_t length
)
480 ((wxOutputStream
*) png_get_io_ptr( png_ptr
)) -> Write(data
, length
);
483 bool wxPNGHandler::LoadFile( wxImage
*image
, wxInputStream
& stream
)
485 // png_structp png_ptr;
486 // png_infop info_ptr;
487 // unsigned char *ptr, **lines, *ptr2;
488 // int transp,bit_depth,color_type,interlace_type;
489 //png_uint_32 width, height;
494 png_structp png_ptr
= png_create_read_struct( PNG_LIBPNG_VER_STRING
,
495 (voidp
) NULL
, (png_error_ptr
) NULL
, (png_error_ptr
) NULL
);
496 if (!png_ptr
) return FALSE
;
498 png_infop info_ptr
= png_create_info_struct( png_ptr
);
501 png_destroy_read_struct( &png_ptr
, (png_infopp
) NULL
, (png_infopp
) NULL
);
505 if (setjmp(png_ptr
->jmpbuf
))
507 png_destroy_read_struct( &png_ptr
, &info_ptr
, (png_infopp
) NULL
);
511 if (info_ptr
->color_type
== PNG_COLOR_TYPE_RGB_ALPHA
)
513 png_destroy_read_struct( &png_ptr
, &info_ptr
, (png_infopp
) NULL
);
516 png_set_read_fn( png_ptr
, &stream
, _PNG_stream_reader
);
518 png_uint_32 width
,height
;
519 int bit_depth
,color_type
,interlace_type
;
521 png_read_info( png_ptr
, info_ptr
);
522 png_get_IHDR( png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
, &interlace_type
, (int*) NULL
, (int*) NULL
);
524 if (color_type
== PNG_COLOR_TYPE_PALETTE
) png_set_expand( png_ptr
);
526 png_set_strip_16( png_ptr
);
527 png_set_packing( png_ptr
);
528 if (png_get_valid( png_ptr
, info_ptr
, PNG_INFO_tRNS
)) png_set_expand( png_ptr
);
529 png_set_filler( png_ptr
, 0xff, PNG_FILLER_AFTER
);
531 image
->Create( width
, height
);
535 png_destroy_read_struct( &png_ptr
, &info_ptr
, (png_infopp
) NULL
);
539 unsigned char **lines
= (unsigned char **)malloc( height
* sizeof(unsigned char *) );
543 png_destroy_read_struct( &png_ptr
, &info_ptr
, (png_infopp
) NULL
);
547 for (unsigned int i
= 0; i
< height
; i
++)
549 if ((lines
[i
] = (unsigned char *)malloc(width
* (sizeof(unsigned char) * 4))) == NULL
)
552 for (unsigned int n
= 0; n
< i
; n
++) free( lines
[n
] );
554 png_destroy_read_struct( &png_ptr
, &info_ptr
, (png_infopp
) NULL
);
561 png_read_image( png_ptr
, lines
);
562 png_destroy_read_struct( &png_ptr
, &info_ptr
, (png_infopp
) NULL
);
563 unsigned char *ptr
= image
->GetData();
564 if ((color_type
== PNG_COLOR_TYPE_GRAY
) ||
565 (color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
))
567 for (unsigned int y
= 0; y
< height
; y
++)
569 unsigned char *ptr2
= lines
[y
];
570 for (unsigned int x
= 0; x
< width
; x
++)
572 unsigned char r
= *ptr2
++;
573 unsigned char a
= *ptr2
++;
592 for (unsigned int y
= 0; y
< height
; y
++)
594 unsigned char *ptr2
= lines
[y
];
595 for (unsigned int x
= 0; x
< width
; x
++)
597 unsigned char r
= *ptr2
++;
598 unsigned char g
= *ptr2
++;
599 unsigned char b
= *ptr2
++;
600 unsigned char a
= *ptr2
++;
610 if ((r
== 255) && (g
== 0) && (b
== 255)) r
= 254;
619 for (unsigned int j
= 0; j
< height
; j
++) free( lines
[j
] );
624 image
->SetMaskColour( 255, 0, 255 );
628 image
->SetMask( FALSE
);
635 bool wxPNGHandler::SaveFile( wxImage
*image
, wxOutputStream
& stream
)
638 png_structp png_ptr
= png_create_write_struct( PNG_LIBPNG_VER_STRING
, NULL
, NULL
, NULL
);
644 png_infop info_ptr
= png_create_info_struct(png_ptr
);
645 if (info_ptr
== NULL
)
647 png_destroy_write_struct( &png_ptr
, (png_infopp
)NULL
);
651 if (setjmp(png_ptr
->jmpbuf
))
653 png_destroy_write_struct( &png_ptr
, (png_infopp
)NULL
);
657 png_set_write_fn( png_ptr
, &stream
, _PNG_stream_writer
, NULL
);
659 png_set_IHDR( png_ptr
, info_ptr
, image
->GetWidth(), image
->GetHeight(), 8,
660 PNG_COLOR_TYPE_RGB_ALPHA
, PNG_INTERLACE_NONE
,
661 PNG_COMPRESSION_TYPE_BASE
, PNG_FILTER_TYPE_BASE
);
668 png_set_sBIT( png_ptr
, info_ptr
, &sig_bit
);
669 png_write_info( png_ptr
, info_ptr
);
670 png_set_shift( png_ptr
, &sig_bit
);
671 png_set_packing( png_ptr
);
673 unsigned char *data
= (unsigned char *)malloc( image
->GetWidth()*4 );
676 png_destroy_write_struct( &png_ptr
, (png_infopp
)NULL
);
680 for (int y
= 0; y
< image
->GetHeight(); y
++)
682 unsigned char *ptr
= image
->GetData() + (y
* image
->GetWidth() * 3);
683 for (int x
= 0; x
< image
->GetWidth(); x
++)
685 data
[(x
<< 2) + 0] = *ptr
++;
686 data
[(x
<< 2) + 1] = *ptr
++;
687 data
[(x
<< 2) + 2] = *ptr
++;
688 if ((data
[(x
<< 2) + 0] == image
->GetMaskRed()) &&
689 (data
[(x
<< 2) + 1] == image
->GetMaskGreen()) &&
690 (data
[(x
<< 2) + 2] == image
->GetMaskBlue()))
692 data
[(x
<< 2) + 3] = 0;
696 data
[(x
<< 2) + 3] = 255;
699 png_bytep row_ptr
= data
;
700 png_write_rows( png_ptr
, &row_ptr
, 1 );
704 png_write_end( png_ptr
, info_ptr
);
705 png_destroy_write_struct( &png_ptr
, (png_infopp
)NULL
);
714 //-----------------------------------------------------------------------------
716 //-----------------------------------------------------------------------------
718 #if !USE_SHARED_LIBRARIES
719 IMPLEMENT_DYNAMIC_CLASS(wxBMPHandler
,wxImageHandler
)
722 bool wxBMPHandler::LoadFile( wxImage
*image
, wxInputStream
& stream
)
724 unsigned char *data
, *ptr
;
725 int done
, i
, bpp
, planes
, comp
, ncolors
, line
, column
,
726 linesize
, linepos
, rshift
= 0, gshift
= 0, bshift
= 0;
729 long int dbuf
[4], dword
, rmask
= 0, gmask
= 0, bmask
= 0, offset
,
731 off_t start_offset
= stream
.TellI();
735 unsigned char r
, g
, b
;
745 #define BI_BITFIELDS 3
752 * Reading the bmp header
755 stream
.Read(&bbuf
, 2);
757 stream
.Read(dbuf
, 4 * 4);
762 stream
.Read(dbuf
, 4 * 2);
763 int width
= (int)dbuf
[0];
764 int height
= (int)dbuf
[1];
767 wxLogError( "Image width > 32767 pixels for file\n" );
772 wxLogError( "Image height > 32767 pixels for file\n" );
775 stream
.Read(&word
, 2);
777 stream
.Read(&word
, 2);
779 if (bpp
!= 1 && bpp
!= 4 && bpp
!= 8 && bpp
&& 16 && bpp
!= 24 && bpp
!= 32)
781 wxLogError( "unknown bitdepth in file\n" );
784 stream
.Read(dbuf
, 4 * 4);
786 if (comp
!= BI_RGB
&& comp
!= BI_RLE4
&& comp
!= BI_RLE8
&& comp
!= BI_BITFIELDS
)
788 wxLogError( "unknown encoding in Windows BMP file\n" );
791 stream
.Read(dbuf
, 4 * 2);
792 ncolors
= (int)dbuf
[0];
795 /* some more sanity checks */
796 if (((comp
== BI_RLE4
) && (bpp
!= 4)) || ((comp
== BI_RLE8
) && (bpp
!= 8)) || ((comp
== BI_BITFIELDS
) && (bpp
!= 16 && bpp
!= 32)))
798 wxLogError( "encoding of BMP doesn't match bitdepth\n" );
803 cmap
= (struct _cmap
*)malloc(sizeof(struct _cmap
) * ncolors
);
807 wxLogError( "Cannot allocate RAM for color map in BMP file\n" );
814 image
->Create( width
, height
);
815 ptr
= image
->GetData();
818 wxLogError( "Cannot allocate RAM for RGB data in file\n" );
825 * Reading the palette, if it exists.
827 if (bpp
< 16 && ncolors
!= 0)
829 for (i
= 0; i
< ncolors
; i
++)
831 stream
.Read(bbuf
, 4);
837 else if (bpp
== 16 || bpp
== 32)
839 if (comp
== BI_BITFIELDS
)
843 stream
.Read(dbuf
, 4 * 3);
847 /* find shift amount.. ugly, but i can't think of a better way */
848 for (bit
= 0; bit
< bpp
; bit
++)
850 if (bmask
& (1 << bit
))
852 if (gmask
& (1 << bit
))
854 if (rmask
& (1 << bit
))
879 * Reading the image data
881 stream
.SeekI(start_offset
+ offset
);
884 /* set the whole image to the background color */
885 if (bpp
< 16 && (comp
== BI_RLE4
|| comp
== BI_RLE8
))
887 for (i
= 0; i
< width
* height
; i
++)
897 #define poffset (line * width * 3 + column * 3)
900 * BMPs are stored upside down... hmmmmmmmmmm....
903 linesize
= ((width
* bpp
+ 31) / 32) * 4;
904 for (line
= (height
- 1); line
>= 0; line
--)
907 for (column
= 0; column
< width
;)
914 aByte
= stream
.GetC();
919 for (bit
= 0; bit
< 8; bit
++)
921 index
= ((aByte
& (0x80 >> bit
)) ? 1 : 0);
922 ptr
[poffset
] = cmap
[index
].r
;
923 ptr
[poffset
+ 1] = cmap
[index
].g
;
924 ptr
[poffset
+ 2] = cmap
[index
].b
;
932 wxLogError( "can't deal with 4bit encoded yet.\n");
941 for (nibble
= 0; nibble
< 2; nibble
++)
943 index
= ((aByte
& (0xF0 >> nibble
* 4)) >> (!nibble
* 4));
946 ptr
[poffset
] = cmap
[index
].r
;
947 ptr
[poffset
+ 1] = cmap
[index
].g
;
948 ptr
[poffset
+ 2] = cmap
[index
].b
;
960 aByte
= stream
.GetC();
965 /* column = width; */
974 aByte
= stream
.GetC();
976 linepos
= column
* bpp
/ 8;
977 aByte
= stream
.GetC();
982 int absolute
= aByte
;
984 for (i
= 0; i
< absolute
; i
++)
987 aByte
= stream
.GetC();
988 ptr
[poffset
] = cmap
[aByte
].r
;
989 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
990 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
994 aByte
= stream
.GetC();
999 for (i
= 0; i
< first
; i
++)
1001 ptr
[poffset
] = cmap
[aByte
].r
;
1002 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
1003 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
1011 ptr
[poffset
] = cmap
[aByte
].r
;
1012 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
1013 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
1021 stream
.Read(&bbuf
, 3);
1023 ptr
[poffset
] = (unsigned char)bbuf
[2];
1024 ptr
[poffset
+ 1] = (unsigned char)bbuf
[1];
1025 ptr
[poffset
+ 2] = (unsigned char)bbuf
[0];
1032 stream
.Read(&word
, 2);
1034 temp
= (word
& rmask
) >> rshift
;
1035 ptr
[poffset
] = temp
;
1036 temp
= (word
& gmask
) >> gshift
;
1037 ptr
[poffset
+ 1] = temp
;
1038 temp
= (word
& bmask
) >> gshift
;
1039 ptr
[poffset
+ 2] = temp
;
1046 stream
.Read(&dword
, 4);
1048 temp
= (dword
& rmask
) >> rshift
;
1049 ptr
[poffset
] = temp
;
1050 temp
= (dword
& gmask
) >> gshift
;
1051 ptr
[poffset
+ 1] = temp
;
1052 temp
= (dword
& bmask
) >> bshift
;
1053 ptr
[poffset
+ 2] = temp
;
1057 while ((linepos
< linesize
) && (comp
!= 1) && (comp
!= 2))
1059 stream
.Read(&aByte
, 1);
1061 if (stream
.LastError() != wxStream_NOERROR
)
1065 if (cmap
) free(cmap
);
1067 image
->SetMask( FALSE
);
1074 wxBitmap
wxImage::ConvertToBitmap() const
1078 wxCHECK_MSG( Ok(), bitmap
, "invalid image" );
1079 int width
= GetWidth();
1080 int height
= GetHeight();
1081 bitmap
.SetWidth( width
);
1082 bitmap
.SetHeight( height
);
1083 bitmap
.SetDepth( wxDisplayDepth() );
1085 int headersize
= sizeof(BITMAPINFOHEADER
);
1086 LPBITMAPINFO lpDIBh
= (BITMAPINFO
*) malloc( headersize
);
1087 wxCHECK_MSG( lpDIBh
, bitmap
, "could not allocate memory for DIB header" );
1089 // Fill in the DIB header
1090 lpDIBh
->bmiHeader
.biSize
= headersize
;
1091 lpDIBh
->bmiHeader
.biWidth
= width
;
1092 lpDIBh
->bmiHeader
.biHeight
= -height
;
1093 lpDIBh
->bmiHeader
.biSizeImage
= width
* height
* 3;
1095 lpDIBh
->bmiHeader
.biPlanes
= 1;
1096 lpDIBh
->bmiHeader
.biBitCount
= 24;
1097 lpDIBh
->bmiHeader
.biCompression
= BI_RGB
;
1098 lpDIBh
->bmiHeader
.biClrUsed
= 0;
1100 // These seem not needed for our purpose here.
1101 // lpDIBh->bmiHeader.biClrImportant = 0;
1102 // lpDIBh->bmiHeader.biXPelsPerMeter = 0;
1103 // lpDIBh->bmiHeader.biYPelsPerMeter = 0;
1105 unsigned char *lpBits
= (unsigned char *) malloc( width
*height
*3 );
1108 wxFAIL_MSG( "could not allocate memory for DIB" );
1113 unsigned char *data
= GetData();
1115 unsigned char *ptdata
= data
, *ptbits
= lpBits
;
1116 for( int i
=0; i
<width
*height
; i
++ )
1118 *(ptbits
++) = *(ptdata
+2);
1119 *(ptbits
++) = *(ptdata
+1);
1120 *(ptbits
++) = *(ptdata
);
1124 HDC hdc
= ::GetDC(NULL
);
1127 hbitmap
= CreateDIBitmap( hdc
, &(lpDIBh
->bmiHeader
), CBM_INIT
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
1129 // The above line is equivalent to the following two lines.
1130 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
1131 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
1132 // or the following lines
1133 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
1134 // HDC memdc = ::CreateCompatibleDC( hdc );
1135 // ::SelectObject( memdc, hbitmap);
1136 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
1137 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
1138 // ::SelectObject( memdc, 0 );
1139 // ::DeleteDC( memdc );
1141 bitmap
.SetHBITMAP( (WXHBITMAP
) hbitmap
);
1145 unsigned char r
= GetMaskRed();
1146 unsigned char g
= GetMaskGreen();
1147 unsigned char b
= GetMaskBlue();
1148 unsigned char zero
= 0, one
= 255;
1151 for( int i
=0; i
<width
*height
; i
++ )
1153 if( (*(ptdata
++)!=r
) | (*(ptdata
++)!=g
) | (*(ptdata
++)!=b
) )
1166 hbitmap
= ::CreateBitmap( (WORD
)width
, (WORD
)height
, 1, 1, NULL
);
1167 ::SetDIBits( hdc
, hbitmap
, 0, (WORD
)height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
1168 wxMask
*mask
= new wxMask();
1169 mask
->SetMaskBitmap( (WXHBITMAP
) hbitmap
);
1170 bitmap
.SetMask( mask
);
1172 /* The following can also be used but is slow to run
1173 wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
1174 wxMask *mask = new wxMask( bitmap, colour );
1175 bitmap.SetMask( mask );
1179 ::ReleaseDC(NULL
, hdc
);
1183 if( bitmap
.GetHBITMAP() )
1184 bitmap
.SetOk( TRUE
);
1186 bitmap
.SetOk( FALSE
);
1192 wxImage::wxImage( const wxBitmap
&bitmap
)
1196 wxFAIL_MSG( "invalid bitmap" );
1200 int width
= bitmap
.GetWidth();
1201 int height
= bitmap
.GetHeight();
1202 Create( width
, height
);
1203 unsigned char *data
= GetData();
1206 wxFAIL_MSG( "could not allocate data for image" );
1210 int headersize
= sizeof(BITMAPINFOHEADER
);
1211 LPBITMAPINFO lpDIBh
= (BITMAPINFO
*) malloc( headersize
);
1214 wxFAIL_MSG( "could not allocate data for DIB header" );
1219 // Fill in the DIB header
1220 lpDIBh
->bmiHeader
.biSize
= headersize
;
1221 lpDIBh
->bmiHeader
.biWidth
= width
;
1222 lpDIBh
->bmiHeader
.biHeight
= -height
;
1223 lpDIBh
->bmiHeader
.biSizeImage
= width
* height
* 3;
1225 lpDIBh
->bmiHeader
.biPlanes
= 1;
1226 lpDIBh
->bmiHeader
.biBitCount
= 24;
1227 lpDIBh
->bmiHeader
.biCompression
= BI_RGB
;
1228 lpDIBh
->bmiHeader
.biClrUsed
= 0;
1230 // These seem not needed for our purpose here.
1231 // lpDIBh->bmiHeader.biClrImportant = 0;
1232 // lpDIBh->bmiHeader.biXPelsPerMeter = 0;
1233 // lpDIBh->bmiHeader.biYPelsPerMeter = 0;
1235 unsigned char *lpBits
= (unsigned char *) malloc( width
*height
*3 );
1238 wxFAIL_MSG( "could not allocate data for DIB" );
1245 hbitmap
= (HBITMAP
) bitmap
.GetHBITMAP();
1246 HDC hdc
= ::GetDC(NULL
);
1247 ::GetDIBits( hdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
1249 unsigned char *ptdata
= data
, *ptbits
= lpBits
;
1250 for( int i
=0; i
<width
*height
; i
++ )
1252 *(ptdata
++) = *(ptbits
+2);
1253 *(ptdata
++) = *(ptbits
+1);
1254 *(ptdata
++) = *(ptbits
);
1258 if( bitmap
.GetMask() && bitmap
.GetMask()->GetMaskBitmap() )
1260 hbitmap
= (HBITMAP
) bitmap
.GetMask()->GetMaskBitmap();
1261 HDC memdc
= ::CreateCompatibleDC( hdc
);
1262 ::SetTextColor( memdc
, RGB( 0, 0, 0 ) );
1263 ::SetBkColor( memdc
, RGB( 255, 255, 255 ) );
1264 ::GetDIBits( memdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
1265 ::DeleteDC( memdc
);
1266 unsigned char r
=16, g
=16, b
=16; // background set to RGB(16,16,16)
1269 for( int i
=0; i
<width
*height
; i
++ )
1279 SetMaskColour( r
, g
, b
);
1282 ::ReleaseDC(NULL
, hdc
);
1291 #include "gtk/gtk.h"
1292 #include "gdk/gdk.h"
1293 #include "gdk/gdkx.h"
1295 wxBitmap
wxImage::ConvertToBitmap() const
1299 wxCHECK_MSG( Ok(), bitmap
, "invalid image" );
1301 int width
= GetWidth();
1302 int height
= GetHeight();
1304 bitmap
.SetHeight( height
);
1305 bitmap
.SetWidth( width
);
1309 GdkImage
*data_image
=
1310 gdk_image_new( GDK_IMAGE_FASTEST
, gdk_visual_get_system(), width
, height
);
1312 bitmap
.SetPixmap( gdk_pixmap_new( (GdkWindow
*)&gdk_root_parent
, width
, height
, -1 ) );
1316 GdkImage
*mask_image
= (GdkImage
*) NULL
;
1320 unsigned char *mask_data
= (unsigned char*)malloc( ((width
>> 3)+8) * height
);
1322 mask_image
= gdk_image_new_bitmap( gdk_visual_get_system(), mask_data
, width
, height
);
1324 wxMask
*mask
= new wxMask();
1325 mask
->m_bitmap
= gdk_pixmap_new( (GdkWindow
*)&gdk_root_parent
, width
, height
, 1 );
1327 bitmap
.SetMask( mask
);
1332 GdkVisual
*visual
= gdk_window_get_visual( bitmap
.GetPixmap() );
1333 if (visual
== NULL
) visual
= gdk_window_get_visual( (GdkWindow
*) &gdk_root_parent
);
1334 int bpp
= visual
->depth
;
1336 bitmap
.SetDepth( bpp
);
1338 if ((bpp
== 16) && (visual
->red_mask
!= 0xf800)) bpp
= 15;
1339 if (bpp
< 8) bpp
= 8;
1343 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
1344 byte_order b_o
= RGB
;
1348 GdkVisual
*visual
= gdk_visual_get_system();
1349 if ((visual
->red_mask
> visual
->green_mask
) && (visual
->green_mask
> visual
->blue_mask
)) b_o
= RGB
;
1350 else if ((visual
->red_mask
> visual
->blue_mask
) && (visual
->blue_mask
> visual
->green_mask
)) b_o
= RGB
;
1351 else if ((visual
->blue_mask
> visual
->red_mask
) && (visual
->red_mask
> visual
->green_mask
)) b_o
= BRG
;
1352 else if ((visual
->blue_mask
> visual
->green_mask
) && (visual
->green_mask
> visual
->red_mask
)) b_o
= BGR
;
1353 else if ((visual
->green_mask
> visual
->red_mask
) && (visual
->red_mask
> visual
->blue_mask
)) b_o
= GRB
;
1354 else if ((visual
->green_mask
> visual
->blue_mask
) && (visual
->blue_mask
> visual
->red_mask
)) b_o
= GBR
;
1357 int r_mask
= GetMaskRed();
1358 int g_mask
= GetMaskGreen();
1359 int b_mask
= GetMaskBlue();
1361 unsigned char* data
= GetData();
1364 for (int y
= 0; y
< height
; y
++)
1366 for (int x
= 0; x
< width
; x
++)
1368 int r
= data
[index
];
1370 int g
= data
[index
];
1372 int b
= data
[index
];
1377 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
1378 gdk_image_put_pixel( mask_image
, x
, y
, 1 );
1380 gdk_image_put_pixel( mask_image
, x
, y
, 0 );
1388 if (wxTheApp
->m_colorCube
)
1390 pixel
= wxTheApp
->m_colorCube
1391 [ ((r
& 0xf8) << 7) + ((g
& 0xf8) << 2) + ((b
& 0xf8) >> 3) ];
1395 GdkColormap
*cmap
= gtk_widget_get_default_colormap();
1396 GdkColor
*colors
= cmap
->colors
;
1397 int max
= 3 * (65536);
1399 for (int i
= 0; i
< cmap
->size
; i
++)
1401 int rdiff
= (r
<< 8) - colors
[i
].red
;
1402 int gdiff
= (g
<< 8) - colors
[i
].green
;
1403 int bdiff
= (b
<< 8) - colors
[i
].blue
;
1404 int sum
= ABS (rdiff
) + ABS (gdiff
) + ABS (bdiff
);
1405 if (sum
< max
) { pixel
= i
; max
= sum
; }
1409 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1415 guint32 pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
1416 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1421 guint32 pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
1422 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1431 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
1432 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
1433 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
1434 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
1435 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
1436 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
1438 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1447 GdkGC
*data_gc
= gdk_gc_new( bitmap
.GetPixmap() );
1449 gdk_draw_image( bitmap
.GetPixmap(), data_gc
, data_image
, 0, 0, 0, 0, width
, height
);
1451 gdk_image_destroy( data_image
);
1452 gdk_gc_unref( data_gc
);
1458 GdkGC
*mask_gc
= gdk_gc_new( bitmap
.GetMask()->GetBitmap() );
1460 gdk_draw_image( bitmap
.GetMask()->GetBitmap(), mask_gc
, mask_image
, 0, 0, 0, 0, width
, height
);
1462 gdk_image_destroy( mask_image
);
1463 gdk_gc_unref( mask_gc
);
1469 wxImage::wxImage( const wxBitmap
&bitmap
)
1471 wxCHECK_RET( bitmap
.Ok(), "invalid bitmap" );
1473 GdkImage
*gdk_image
= gdk_image_get( bitmap
.GetPixmap(),
1475 bitmap
.GetWidth(), bitmap
.GetHeight() );
1477 wxCHECK_RET( gdk_image
, "couldn't create image" );
1479 Create( bitmap
.GetWidth(), bitmap
.GetHeight() );
1480 char unsigned *data
= GetData();
1484 gdk_image_destroy( gdk_image
);
1485 wxFAIL_MSG( "couldn't create image" );
1489 GdkImage
*gdk_image_mask
= (GdkImage
*) NULL
;
1490 if (bitmap
.GetMask())
1492 gdk_image_mask
= gdk_image_get( bitmap
.GetMask()->GetBitmap(),
1494 bitmap
.GetWidth(), bitmap
.GetHeight() );
1496 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1499 GdkVisual
*visual
= gdk_window_get_visual( bitmap
.GetPixmap() );
1500 if (visual
== NULL
) visual
= gdk_window_get_visual( (GdkWindow
*) &gdk_root_parent
);
1501 int bpp
= visual
->depth
;
1502 if ((bpp
== 16) && (visual
->red_mask
!= 0xf800)) bpp
= 15;
1504 GdkColormap
*cmap
= gtk_widget_get_default_colormap();
1507 for (int j
= 0; j
< bitmap
.GetHeight(); j
++)
1509 for (int i
= 0; i
< bitmap
.GetWidth(); i
++)
1511 int pixel
= gdk_image_get_pixel( gdk_image
, i
, j
);
1514 data
[pos
] = cmap
->colors
[pixel
].red
>> 8;
1515 data
[pos
+1] = cmap
->colors
[pixel
].green
>> 8;
1516 data
[pos
+2] = cmap
->colors
[pixel
].blue
>> 8;
1517 } else if (bpp
== 15)
1519 data
[pos
] = (pixel
>> 7) & 0xf8;
1520 data
[pos
+1] = (pixel
>> 2) & 0xf8;
1521 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1522 } else if (bpp
== 16)
1524 data
[pos
] = (pixel
>> 8) & 0xf8;
1525 data
[pos
+1] = (pixel
>> 3) & 0xfc;
1526 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1529 data
[pos
] = (pixel
>> 16) & 0xff;
1530 data
[pos
+1] = (pixel
>> 8) & 0xff;
1531 data
[pos
+2] = pixel
& 0xff;
1536 int mask_pixel
= gdk_image_get_pixel( gdk_image_mask
, i
, j
);
1537 if (mask_pixel
== 0)
1549 gdk_image_destroy( gdk_image
);
1550 if (gdk_image_mask
) gdk_image_destroy( gdk_image_mask
);
1558 wxBitmap
wxImage::ConvertToBitmap() const
1560 wxFAIL_MSG("Sorry, wxImage::ConvertToBitmap isn't implemented for wxMotif yet.");
1561 return wxNullBitmap
;
1564 wxImage::wxImage( const wxBitmap
&bitmap
)
1566 wxFAIL_MSG("Sorry, wxImage::wxImage(const wxBitmap&) isn't implemented for wxMotif yet.");