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"
34 #include "wx/filefn.h"
35 #include "wx/wfstream.h"
37 #include "wx/module.h"
52 //-----------------------------------------------------------------------------
54 //-----------------------------------------------------------------------------
56 class wxImageRefData
: public wxObjectRefData
61 ~wxImageRefData(void);
65 unsigned char *m_data
;
67 unsigned char m_maskRed
,m_maskGreen
,m_maskBlue
;
71 wxImageRefData::wxImageRefData(void)
75 m_data
= (unsigned char*) NULL
;
83 wxImageRefData::~wxImageRefData(void)
85 if (m_data
) free( m_data
);
88 wxList
wxImage::sm_handlers
;
90 //-----------------------------------------------------------------------------
92 #define M_IMGDATA ((wxImageRefData *)m_refData)
94 #if !USE_SHARED_LIBRARIES
95 IMPLEMENT_DYNAMIC_CLASS(wxImage
, wxObject
)
102 wxImage::wxImage( int width
, int height
)
104 Create( width
, height
);
107 wxImage::wxImage( const wxString
& name
, long type
)
109 LoadFile( name
, type
);
113 wxImage::wxImage( wxInputStream
& stream
, long type
)
115 LoadFile( stream
, type
);
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
)
157 wxCHECK_MSG( Ok(), image
, "invlaid image" );
159 wxCHECK_MSG( (width
> 0) && (height
> 0), image
, "invalid image size" );
161 image
.Create( width
, height
);
163 char unsigned *data
= image
.GetData();
165 wxCHECK_MSG( data
, image
, "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 void wxImage::SetRGB( int x
, int y
, unsigned char r
, unsigned char g
, unsigned char b
)
194 wxCHECK_RET( Ok(), "invalid image" );
196 int w
= M_IMGDATA
->m_width
;
197 int h
= M_IMGDATA
->m_height
;
199 wxCHECK_RET( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), "invalid image index" );
201 long pos
= (y
* w
+ x
) * 3;
203 M_IMGDATA
->m_data
[ pos
] = r
;
204 M_IMGDATA
->m_data
[ pos
+1 ] = g
;
205 M_IMGDATA
->m_data
[ pos
+2 ] = b
;
208 unsigned char wxImage::GetRed( int x
, int y
)
210 wxCHECK_MSG( Ok(), 0, "invalid image" );
212 int w
= M_IMGDATA
->m_width
;
213 int h
= M_IMGDATA
->m_height
;
215 wxCHECK_MSG( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), 0, "invalid image index" );
217 long pos
= (y
* w
+ x
) * 3;
219 return M_IMGDATA
->m_data
[pos
];
222 unsigned char wxImage::GetGreen( int x
, int y
)
224 wxCHECK_MSG( Ok(), 0, "invalid image" );
226 int w
= M_IMGDATA
->m_width
;
227 int h
= M_IMGDATA
->m_height
;
229 wxCHECK_MSG( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), 0, "invalid image index" );
231 long pos
= (y
* w
+ x
) * 3;
233 return M_IMGDATA
->m_data
[pos
+1];
236 unsigned char wxImage::GetBlue( int x
, int y
)
238 wxCHECK_MSG( Ok(), 0, "invalid image" );
240 int w
= M_IMGDATA
->m_width
;
241 int h
= M_IMGDATA
->m_height
;
243 wxCHECK_MSG( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), 0, "invalid image index" );
245 long pos
= (y
* w
+ x
) * 3;
247 return M_IMGDATA
->m_data
[pos
+2];
250 bool wxImage::Ok() const
252 return (M_IMGDATA
&& M_IMGDATA
->m_ok
);
255 char unsigned *wxImage::GetData() const
257 wxCHECK_MSG( Ok(), (char unsigned *)NULL
, "invalid image" );
259 return M_IMGDATA
->m_data
;
262 void wxImage::SetData( char unsigned *data
)
264 wxCHECK_RET( Ok(), "invalid image" );
266 memcpy(M_IMGDATA
->m_data
, data
, M_IMGDATA
->m_width
* M_IMGDATA
->m_height
* 3);
269 void wxImage::SetMaskColour( unsigned char r
, unsigned char g
, unsigned char b
)
271 wxCHECK_RET( Ok(), "invalid image" );
273 M_IMGDATA
->m_maskRed
= r
;
274 M_IMGDATA
->m_maskGreen
= g
;
275 M_IMGDATA
->m_maskBlue
= b
;
276 M_IMGDATA
->m_hasMask
= TRUE
;
279 unsigned char wxImage::GetMaskRed() const
281 wxCHECK_MSG( Ok(), 0, "invalid image" );
283 return M_IMGDATA
->m_maskRed
;
286 unsigned char wxImage::GetMaskGreen() const
288 wxCHECK_MSG( Ok(), 0, "invalid image" );
290 return M_IMGDATA
->m_maskGreen
;
293 unsigned char wxImage::GetMaskBlue() const
295 wxCHECK_MSG( Ok(), 0, "invalid image" );
297 return M_IMGDATA
->m_maskBlue
;
300 void wxImage::SetMask( bool mask
)
302 wxCHECK_RET( Ok(), "invalid image" );
304 M_IMGDATA
->m_hasMask
= mask
;
307 bool wxImage::HasMask() const
309 wxCHECK_MSG( Ok(), FALSE
, "invalid image" );
311 return M_IMGDATA
->m_hasMask
;
314 int wxImage::GetWidth() const
316 wxCHECK_MSG( Ok(), 0, "invalid image" );
318 return M_IMGDATA
->m_width
;
321 int wxImage::GetHeight() const
323 wxCHECK_MSG( Ok(), 0, "invalid image" );
325 return M_IMGDATA
->m_height
;
328 bool wxImage::LoadFile( const wxString
& filename
, long type
)
331 if (wxFileExists(filename
))
333 wxFileInputStream
stream(filename
);
334 return LoadFile(stream
, type
);
338 wxLogError( "Can't load image from file '%s': file does not exist.", filename
.c_str() );
342 #else // !wxUSE_STREAMS
344 #endif // wxUSE_STREAMS
347 bool wxImage::SaveFile( const wxString
& filename
, int type
)
350 wxFileOutputStream
stream(filename
);
352 if ( stream
.LastError() == wxStream_NOERROR
)
353 return SaveFile(stream
, type
);
355 #endif // wxUSE_STREAMS
360 bool wxImage::LoadFile( wxInputStream
& stream
, long type
)
364 m_refData
= new wxImageRefData
;
366 wxImageHandler
*handler
= FindHandler(type
);
370 wxLogWarning( "No image handler for type %d defined.", type
);
375 return handler
->LoadFile( this, stream
);
378 bool wxImage::SaveFile( wxOutputStream
& stream
, int type
)
380 wxCHECK_MSG( Ok(), FALSE
, "invalid image" );
382 wxImageHandler
*handler
= FindHandler(type
);
386 wxLogWarning( "No image handler for type %d defined.", type
);
391 return handler
->SaveFile( this, stream
);
393 #endif // wxUSE_STREAMS
395 void wxImage::AddHandler( wxImageHandler
*handler
)
397 // make sure that the memory will be freed at the program end
398 sm_handlers
.DeleteContents(TRUE
);
400 sm_handlers
.Append( handler
);
403 void wxImage::InsertHandler( wxImageHandler
*handler
)
405 // make sure that the memory will be freed at the program end
406 sm_handlers
.DeleteContents(TRUE
);
408 sm_handlers
.Insert( handler
);
411 bool wxImage::RemoveHandler( const wxString
& name
)
413 wxImageHandler
*handler
= FindHandler(name
);
416 sm_handlers
.DeleteObject(handler
);
423 wxImageHandler
*wxImage::FindHandler( const wxString
& name
)
425 wxNode
*node
= sm_handlers
.First();
428 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
429 if (handler
->GetName().Cmp(name
) == 0) return handler
;
433 return (wxImageHandler
*)NULL
;
436 wxImageHandler
*wxImage::FindHandler( const wxString
& extension
, long bitmapType
)
438 wxNode
*node
= sm_handlers
.First();
441 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
442 if ( (handler
->GetExtension().Cmp(extension
) == 0) &&
443 (bitmapType
== -1 || handler
->GetType() == bitmapType
) )
447 return (wxImageHandler
*)NULL
;
450 wxImageHandler
*wxImage::FindHandler( long bitmapType
)
452 wxNode
*node
= sm_handlers
.First();
455 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
456 if (handler
->GetType() == bitmapType
) return handler
;
462 void wxImage::InitStandardHandlers()
464 AddHandler( new wxBMPHandler
);
466 AddHandler( new wxPNGHandler
);
470 void wxImage::CleanUpHandlers()
472 wxNode
*node
= sm_handlers
.First();
475 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
476 wxNode
*next
= node
->Next();
483 //-----------------------------------------------------------------------------
485 //-----------------------------------------------------------------------------
487 #if !USE_SHARED_LIBRARIES
488 IMPLEMENT_DYNAMIC_CLASS(wxImageHandler
,wxObject
)
492 bool wxImageHandler::LoadFile( wxImage
*WXUNUSED(image
), wxInputStream
& WXUNUSED(stream
) )
497 bool wxImageHandler::SaveFile( wxImage
*WXUNUSED(image
), wxOutputStream
& WXUNUSED(stream
) )
501 #endif // wxUSE_STREAMS
503 //-----------------------------------------------------------------------------
505 //-----------------------------------------------------------------------------
509 #if !USE_SHARED_LIBRARIES
510 IMPLEMENT_DYNAMIC_CLASS(wxPNGHandler
,wxImageHandler
)
515 static void _PNG_stream_reader( png_structp png_ptr
, png_bytep data
, png_size_t length
)
517 ((wxInputStream
*) png_get_io_ptr( png_ptr
)) -> Read(data
, length
);
520 static void _PNG_stream_writer( png_structp png_ptr
, png_bytep data
, png_size_t length
)
522 ((wxOutputStream
*) png_get_io_ptr( png_ptr
)) -> Write(data
, length
);
525 bool wxPNGHandler::LoadFile( wxImage
*image
, wxInputStream
& stream
)
527 // VZ: as this function uses setjmp() the only fool proof error handling
528 // method is to use goto (setjmp is not really C++ dtors friendly...)
530 unsigned char **lines
= (unsigned char **) NULL
;
532 png_infop info_ptr
= (png_infop
) NULL
;
536 png_structp png_ptr
= png_create_read_struct( PNG_LIBPNG_VER_STRING
,
538 (png_error_ptr
) NULL
,
539 (png_error_ptr
) NULL
);
543 info_ptr
= png_create_info_struct( png_ptr
);
547 if (setjmp(png_ptr
->jmpbuf
))
550 if (info_ptr
->color_type
== PNG_COLOR_TYPE_RGB_ALPHA
)
553 png_set_read_fn( png_ptr
, &stream
, _PNG_stream_reader
);
555 png_uint_32 width
,height
;
556 int bit_depth
,color_type
,interlace_type
;
558 png_read_info( png_ptr
, info_ptr
);
559 png_get_IHDR( png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
, &interlace_type
, (int*) NULL
, (int*) NULL
);
561 if (color_type
== PNG_COLOR_TYPE_PALETTE
)
562 png_set_expand( png_ptr
);
564 png_set_strip_16( png_ptr
);
565 png_set_packing( png_ptr
);
566 if (png_get_valid( png_ptr
, info_ptr
, PNG_INFO_tRNS
))
567 png_set_expand( png_ptr
);
568 png_set_filler( png_ptr
, 0xff, PNG_FILLER_AFTER
);
570 image
->Create( width
, height
);
575 lines
= (unsigned char **)malloc( height
* sizeof(unsigned char *) );
579 for (i
= 0; i
< height
; i
++)
581 if ((lines
[i
] = (unsigned char *)malloc(width
* (sizeof(unsigned char) * 4))) == NULL
)
583 for ( unsigned int n
= 0; n
< i
; n
++ )
589 // loaded successfully!
592 png_read_image( png_ptr
, lines
);
593 png_destroy_read_struct( &png_ptr
, &info_ptr
, (png_infopp
) NULL
);
594 unsigned char *ptr
= image
->GetData();
595 if ((color_type
== PNG_COLOR_TYPE_GRAY
) ||
596 (color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
))
598 for (unsigned int y
= 0; y
< height
; y
++)
600 unsigned char *ptr2
= lines
[y
];
601 for (unsigned int x
= 0; x
< width
; x
++)
603 unsigned char r
= *ptr2
++;
604 unsigned char a
= *ptr2
++;
623 for (unsigned int y
= 0; y
< height
; y
++)
625 unsigned char *ptr2
= lines
[y
];
626 for (unsigned int x
= 0; x
< width
; x
++)
628 unsigned char r
= *ptr2
++;
629 unsigned char g
= *ptr2
++;
630 unsigned char b
= *ptr2
++;
631 unsigned char a
= *ptr2
++;
641 if ((r
== 255) && (g
== 0) && (b
== 255)) r
= 254;
650 for ( unsigned int j
= 0; j
< height
; j
++ )
656 image
->SetMaskColour( 255, 0, 255 );
660 image
->SetMask( FALSE
);
667 wxLogError(_("Couldn't load a PNG image - probably file is corrupted."));
683 png_destroy_read_struct( &png_ptr
, &info_ptr
, (png_infopp
) NULL
);
687 png_destroy_read_struct( &png_ptr
, (png_infopp
) NULL
, (png_infopp
) NULL
);
693 bool wxPNGHandler::SaveFile( wxImage
*image
, wxOutputStream
& stream
)
696 png_structp png_ptr
= png_create_write_struct( PNG_LIBPNG_VER_STRING
, NULL
, NULL
, NULL
);
702 png_infop info_ptr
= png_create_info_struct(png_ptr
);
703 if (info_ptr
== NULL
)
705 png_destroy_write_struct( &png_ptr
, (png_infopp
)NULL
);
709 if (setjmp(png_ptr
->jmpbuf
))
711 png_destroy_write_struct( &png_ptr
, (png_infopp
)NULL
);
715 png_set_write_fn( png_ptr
, &stream
, _PNG_stream_writer
, NULL
);
717 png_set_IHDR( png_ptr
, info_ptr
, image
->GetWidth(), image
->GetHeight(), 8,
718 PNG_COLOR_TYPE_RGB_ALPHA
, PNG_INTERLACE_NONE
,
719 PNG_COMPRESSION_TYPE_BASE
, PNG_FILTER_TYPE_BASE
);
726 png_set_sBIT( png_ptr
, info_ptr
, &sig_bit
);
727 png_write_info( png_ptr
, info_ptr
);
728 png_set_shift( png_ptr
, &sig_bit
);
729 png_set_packing( png_ptr
);
731 unsigned char *data
= (unsigned char *)malloc( image
->GetWidth()*4 );
734 png_destroy_write_struct( &png_ptr
, (png_infopp
)NULL
);
738 for (int y
= 0; y
< image
->GetHeight(); y
++)
740 unsigned char *ptr
= image
->GetData() + (y
* image
->GetWidth() * 3);
741 for (int x
= 0; x
< image
->GetWidth(); x
++)
743 data
[(x
<< 2) + 0] = *ptr
++;
744 data
[(x
<< 2) + 1] = *ptr
++;
745 data
[(x
<< 2) + 2] = *ptr
++;
746 if ((data
[(x
<< 2) + 0] == image
->GetMaskRed()) &&
747 (data
[(x
<< 2) + 1] == image
->GetMaskGreen()) &&
748 (data
[(x
<< 2) + 2] == image
->GetMaskBlue()))
750 data
[(x
<< 2) + 3] = 0;
754 data
[(x
<< 2) + 3] = 255;
757 png_bytep row_ptr
= data
;
758 png_write_rows( png_ptr
, &row_ptr
, 1 );
762 png_write_end( png_ptr
, info_ptr
);
763 png_destroy_write_struct( &png_ptr
, (png_infopp
)&info_ptr
);
767 #endif // wxUSE_STREAMS
774 //-----------------------------------------------------------------------------
776 //-----------------------------------------------------------------------------
780 #if !USE_SHARED_LIBRARIES
781 IMPLEMENT_DYNAMIC_CLASS(wxJPEGHandler
,wxImageHandler
)
787 //------------- JPEG Data Source Manager
790 struct jpeg_source_mgr pub
; /* public fields */
792 JOCTET
* buffer
; /* start of buffer */
795 typedef my_source_mgr
* my_src_ptr
;
797 METHODDEF(void) my_init_source ( j_decompress_ptr cinfo
)
801 METHODDEF(boolean
) my_fill_input_buffer ( j_decompress_ptr cinfo
)
806 METHODDEF(void) my_skip_input_data ( j_decompress_ptr cinfo
, long num_bytes
)
808 my_src_ptr src
= (my_src_ptr
) cinfo
->src
;
810 src
->pub
.next_input_byte
+= (size_t) num_bytes
;
811 src
->pub
.bytes_in_buffer
-= (size_t) num_bytes
;
814 METHODDEF(void) my_term_source ( j_decompress_ptr cinfo
)
816 my_src_ptr src
= (my_src_ptr
) cinfo
->src
;
821 void jpeg_wxio_src( j_decompress_ptr cinfo
, wxInputStream
& infile
)
825 if (cinfo
->src
== NULL
) { /* first time for this JPEG object? */
826 cinfo
->src
= (struct jpeg_source_mgr
*)
827 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
828 sizeof(my_source_mgr
));
829 src
= (my_src_ptr
) cinfo
->src
;
831 src
= (my_src_ptr
) cinfo
->src
;
832 src
->pub
.bytes_in_buffer
= infile
.StreamSize(); /* forces fill_input_buffer on first read */
833 src
->buffer
= (JOCTET
*) malloc (infile
.StreamSize());
834 src
->pub
.next_input_byte
= src
->buffer
; /* until buffer loaded */
835 infile
.Read(src
->buffer
, infile
.StreamSize());
837 src
->pub
.init_source
= my_init_source
;
838 src
->pub
.fill_input_buffer
= my_fill_input_buffer
;
839 src
->pub
.skip_input_data
= my_skip_input_data
;
840 src
->pub
.resync_to_restart
= jpeg_resync_to_restart
; /* use default method */
841 src
->pub
.term_source
= my_term_source
;
846 bool wxJPEGHandler::LoadFile( wxImage
*image
, wxInputStream
& stream
)
848 struct jpeg_decompress_struct cinfo
;
849 struct jpeg_error_mgr jerr
;
855 cinfo
.err
= jpeg_std_error( &jerr
);
856 jpeg_create_decompress( &cinfo
);
857 jpeg_wxio_src( &cinfo
, stream
);
858 jpeg_read_header( &cinfo
, TRUE
);
859 cinfo
.out_color_space
= JCS_RGB
;
860 jpeg_start_decompress( &cinfo
);
862 image
->Create( cinfo
.image_width
, cinfo
.image_height
);
864 jpeg_finish_decompress( &cinfo
);
865 jpeg_destroy_decompress( &cinfo
);
868 image
->SetMask( FALSE
);
869 ptr
= image
->GetData();
870 stride
= cinfo
.output_width
* 3;
871 tempbuf
= (*cinfo
.mem
->alloc_sarray
)
872 ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
, stride
, 1 );
874 while ( cinfo
.output_scanline
< cinfo
.output_height
) {
875 jpeg_read_scanlines( &cinfo
, tempbuf
, 1 );
876 memcpy( ptr
, tempbuf
[0], stride
);
879 jpeg_finish_decompress( &cinfo
);
880 jpeg_destroy_decompress( &cinfo
);
889 struct jpeg_destination_mgr pub
;
891 wxOutputStream
*stream
;
893 } my_destination_mgr
;
895 typedef my_destination_mgr
* my_dest_ptr
;
897 #define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */
899 METHODDEF(void) init_destination (j_compress_ptr cinfo
)
901 my_dest_ptr dest
= (my_dest_ptr
) cinfo
->dest
;
903 /* Allocate the output buffer --- it will be released when done with image */
904 dest
->buffer
= (JOCTET
*)
905 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_IMAGE
,
906 OUTPUT_BUF_SIZE
* sizeof(JOCTET
));
907 dest
->pub
.next_output_byte
= dest
->buffer
;
908 dest
->pub
.free_in_buffer
= OUTPUT_BUF_SIZE
;
911 METHODDEF(boolean
) empty_output_buffer (j_compress_ptr cinfo
)
913 my_dest_ptr dest
= (my_dest_ptr
) cinfo
->dest
;
915 dest
->stream
->Write(dest
->buffer
, OUTPUT_BUF_SIZE
);
916 dest
->pub
.next_output_byte
= dest
->buffer
;
917 dest
->pub
.free_in_buffer
= OUTPUT_BUF_SIZE
;
921 METHODDEF(void) term_destination (j_compress_ptr cinfo
)
923 my_dest_ptr dest
= (my_dest_ptr
) cinfo
->dest
;
924 size_t datacount
= OUTPUT_BUF_SIZE
- dest
->pub
.free_in_buffer
;
925 /* Write any data remaining in the buffer */
927 dest
->stream
->Write(dest
->buffer
, datacount
);
930 GLOBAL(void) jpeg_wxio_dest (j_compress_ptr cinfo
, wxOutputStream
& outfile
)
934 if (cinfo
->dest
== NULL
) { /* first time for this JPEG object? */
935 cinfo
->dest
= (struct jpeg_destination_mgr
*)
936 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
937 sizeof(my_destination_mgr
));
940 dest
= (my_dest_ptr
) cinfo
->dest
;
941 dest
->pub
.init_destination
= init_destination
;
942 dest
->pub
.empty_output_buffer
= empty_output_buffer
;
943 dest
->pub
.term_destination
= term_destination
;
944 dest
->stream
= &outfile
;
949 bool wxJPEGHandler::SaveFile( wxImage
*image
, wxOutputStream
& stream
)
951 struct jpeg_compress_struct cinfo
;
952 struct jpeg_error_mgr jerr
;
953 JSAMPROW row_pointer
[1]; /* pointer to JSAMPLE row[s] */
954 JSAMPLE
*image_buffer
;
955 int stride
; /* physical row width in image buffer */
957 cinfo
.err
= jpeg_std_error(&jerr
);
958 jpeg_create_compress(&cinfo
);
959 jpeg_wxio_dest(&cinfo
, stream
);
961 cinfo
.image_width
= image
->GetWidth();
962 cinfo
.image_height
= image
->GetHeight();
963 cinfo
.input_components
= 3;
964 cinfo
.in_color_space
= JCS_RGB
;
965 jpeg_set_defaults(&cinfo
);
966 jpeg_start_compress(&cinfo
, TRUE
);
968 stride
= cinfo
.image_width
* 3; /* JSAMPLEs per row in image_buffer */
969 image_buffer
= image
->GetData();
970 while (cinfo
.next_scanline
< cinfo
.image_height
) {
971 row_pointer
[0] = &image_buffer
[cinfo
.next_scanline
* stride
];
972 jpeg_write_scanlines( &cinfo
, row_pointer
, 1 );
974 jpeg_finish_compress(&cinfo
);
975 jpeg_destroy_compress(&cinfo
);
979 #endif // wxUSE_STREAMS
987 //-----------------------------------------------------------------------------
989 //-----------------------------------------------------------------------------
991 #if !USE_SHARED_LIBRARIES
992 IMPLEMENT_DYNAMIC_CLASS(wxBMPHandler
,wxImageHandler
)
996 bool wxBMPHandler::LoadFile( wxImage
*image
, wxInputStream
& stream
)
998 unsigned char *data
, *ptr
;
999 int done
, i
, bpp
, planes
, comp
, ncolors
, line
, column
,
1000 linesize
, linepos
, rshift
= 0, gshift
= 0, bshift
= 0;
1001 unsigned char aByte
;
1003 long int dbuf
[4], dword
, rmask
= 0, gmask
= 0, bmask
= 0, offset
,
1005 off_t start_offset
= stream
.TellI();
1006 signed char bbuf
[4];
1009 unsigned char r
, g
, b
;
1018 #ifndef BI_BITFIELDS
1019 #define BI_BITFIELDS 3
1026 * Reading the bmp header
1029 stream
.Read(&bbuf
, 2);
1031 stream
.Read(dbuf
, 4 * 4);
1036 stream
.Read(dbuf
, 4 * 2);
1037 int width
= (int)dbuf
[0];
1038 int height
= (int)dbuf
[1];
1041 wxLogError( "Image width > 32767 pixels for file\n" );
1046 wxLogError( "Image height > 32767 pixels for file\n" );
1049 stream
.Read(&word
, 2);
1051 stream
.Read(&word
, 2);
1053 if (bpp
!= 1 && bpp
!= 4 && bpp
!= 8 && bpp
&& 16 && bpp
!= 24 && bpp
!= 32)
1055 wxLogError( "unknown bitdepth in file\n" );
1058 stream
.Read(dbuf
, 4 * 4);
1059 comp
= (int)dbuf
[0];
1060 if (comp
!= BI_RGB
&& comp
!= BI_RLE4
&& comp
!= BI_RLE8
&& comp
!= BI_BITFIELDS
)
1062 wxLogError( "unknown encoding in Windows BMP file\n" );
1065 stream
.Read(dbuf
, 4 * 2);
1066 ncolors
= (int)dbuf
[0];
1069 /* some more sanity checks */
1070 if (((comp
== BI_RLE4
) && (bpp
!= 4)) || ((comp
== BI_RLE8
) && (bpp
!= 8)) || ((comp
== BI_BITFIELDS
) && (bpp
!= 16 && bpp
!= 32)))
1072 wxLogError( "encoding of BMP doesn't match bitdepth\n" );
1077 cmap
= (struct _cmap
*)malloc(sizeof(struct _cmap
) * ncolors
);
1081 wxLogError( "Cannot allocate RAM for color map in BMP file\n" );
1088 image
->Create( width
, height
);
1089 ptr
= image
->GetData();
1092 wxLogError( "Cannot allocate RAM for RGB data in file\n" );
1099 * Reading the palette, if it exists.
1101 if (bpp
< 16 && ncolors
!= 0)
1103 for (i
= 0; i
< ncolors
; i
++)
1105 stream
.Read(bbuf
, 4);
1106 cmap
[i
].b
= bbuf
[0];
1107 cmap
[i
].g
= bbuf
[1];
1108 cmap
[i
].r
= bbuf
[2];
1111 else if (bpp
== 16 || bpp
== 32)
1113 if (comp
== BI_BITFIELDS
)
1117 stream
.Read(dbuf
, 4 * 3);
1121 /* find shift amount.. ugly, but i can't think of a better way */
1122 for (bit
= 0; bit
< bpp
; bit
++)
1124 if (bmask
& (1 << bit
))
1126 if (gmask
& (1 << bit
))
1128 if (rmask
& (1 << bit
))
1153 * Reading the image data
1155 stream
.SeekI(start_offset
+ offset
);
1158 /* set the whole image to the background color */
1159 if (bpp
< 16 && (comp
== BI_RLE4
|| comp
== BI_RLE8
))
1161 for (i
= 0; i
< width
* height
; i
++)
1171 #define poffset (line * width * 3 + column * 3)
1174 * BMPs are stored upside down... hmmmmmmmmmm....
1177 linesize
= ((width
* bpp
+ 31) / 32) * 4;
1178 for (line
= (height
- 1); line
>= 0; line
--)
1181 for (column
= 0; column
< width
;)
1188 aByte
= stream
.GetC();
1193 for (bit
= 0; bit
< 8; bit
++)
1195 index
= ((aByte
& (0x80 >> bit
)) ? 1 : 0);
1196 ptr
[poffset
] = cmap
[index
].r
;
1197 ptr
[poffset
+ 1] = cmap
[index
].g
;
1198 ptr
[poffset
+ 2] = cmap
[index
].b
;
1204 if (comp
== BI_RLE4
)
1206 wxLogError( "can't deal with 4bit encoded yet.\n");
1215 for (nibble
= 0; nibble
< 2; nibble
++)
1217 index
= ((aByte
& (0xF0 >> nibble
* 4)) >> (!nibble
* 4));
1220 ptr
[poffset
] = cmap
[index
].r
;
1221 ptr
[poffset
+ 1] = cmap
[index
].g
;
1222 ptr
[poffset
+ 2] = cmap
[index
].b
;
1229 if (comp
== BI_RLE8
)
1231 unsigned char first
;
1234 aByte
= stream
.GetC();
1239 /* column = width; */
1241 else if (aByte
== 1)
1246 else if (aByte
== 2)
1248 aByte
= stream
.GetC();
1250 linepos
= column
* bpp
/ 8;
1251 aByte
= stream
.GetC();
1256 int absolute
= aByte
;
1258 for (i
= 0; i
< absolute
; i
++)
1261 aByte
= stream
.GetC();
1262 ptr
[poffset
] = cmap
[aByte
].r
;
1263 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
1264 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
1267 if (absolute
& 0x01)
1268 aByte
= stream
.GetC();
1273 for (i
= 0; i
< first
; i
++)
1275 ptr
[poffset
] = cmap
[aByte
].r
;
1276 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
1277 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
1285 ptr
[poffset
] = cmap
[aByte
].r
;
1286 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
1287 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
1295 stream
.Read(&bbuf
, 3);
1297 ptr
[poffset
] = (unsigned char)bbuf
[2];
1298 ptr
[poffset
+ 1] = (unsigned char)bbuf
[1];
1299 ptr
[poffset
+ 2] = (unsigned char)bbuf
[0];
1306 stream
.Read(&word
, 2);
1308 temp
= (word
& rmask
) >> rshift
;
1309 ptr
[poffset
] = temp
;
1310 temp
= (word
& gmask
) >> gshift
;
1311 ptr
[poffset
+ 1] = temp
;
1312 temp
= (word
& bmask
) >> gshift
;
1313 ptr
[poffset
+ 2] = temp
;
1320 stream
.Read(&dword
, 4);
1322 temp
= (dword
& rmask
) >> rshift
;
1323 ptr
[poffset
] = temp
;
1324 temp
= (dword
& gmask
) >> gshift
;
1325 ptr
[poffset
+ 1] = temp
;
1326 temp
= (dword
& bmask
) >> bshift
;
1327 ptr
[poffset
+ 2] = temp
;
1331 while ((linepos
< linesize
) && (comp
!= 1) && (comp
!= 2))
1333 stream
.Read(&aByte
, 1);
1335 if (stream
.LastError() != wxStream_NOERROR
)
1339 if (cmap
) free(cmap
);
1341 image
->SetMask( FALSE
);
1345 #endif // wxUSE_STREAMS
1349 wxBitmap
wxImage::ConvertToBitmap() const
1351 // sizeLimit is the MS upper limit for the DIB size
1352 int sizeLimit
= 1024*768*3;
1354 // width and height of the device-dependent bitmap
1355 int width
= GetWidth();
1356 int bmpHeight
= GetHeight();
1358 // calc the number of bytes per scanline and padding
1359 int bytePerLine
= width
*3;
1360 int sizeDWORD
= sizeof( DWORD
);
1361 div_t lineBoundary
= div( bytePerLine
, sizeDWORD
);
1363 if( lineBoundary
.rem
> 0 )
1365 padding
= sizeDWORD
- lineBoundary
.rem
;
1366 bytePerLine
+= padding
;
1368 // calc the number of DIBs and heights of DIBs
1371 int height
= sizeLimit
/bytePerLine
;
1372 if( height
>= bmpHeight
)
1376 div_t result
= div( bmpHeight
, height
);
1377 numDIB
= result
.quot
;
1378 hRemain
= result
.rem
;
1379 if( hRemain
>0 ) numDIB
++;
1382 // set bitmap parameters
1384 wxCHECK_MSG( Ok(), bitmap
, "invalid image" );
1385 bitmap
.SetWidth( width
);
1386 bitmap
.SetHeight( bmpHeight
);
1387 bitmap
.SetDepth( wxDisplayDepth() );
1389 // create a DIB header
1390 int headersize
= sizeof(BITMAPINFOHEADER
);
1391 LPBITMAPINFO lpDIBh
= (BITMAPINFO
*) malloc( headersize
);
1392 wxCHECK_MSG( lpDIBh
, bitmap
, "could not allocate memory for DIB header" );
1393 // Fill in the DIB header
1394 lpDIBh
->bmiHeader
.biSize
= headersize
;
1395 lpDIBh
->bmiHeader
.biWidth
= (DWORD
)width
;
1396 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
1397 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
1398 // the general formula for biSizeImage:
1399 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
1400 lpDIBh
->bmiHeader
.biPlanes
= 1;
1401 lpDIBh
->bmiHeader
.biBitCount
= 24;
1402 lpDIBh
->bmiHeader
.biCompression
= BI_RGB
;
1403 lpDIBh
->bmiHeader
.biClrUsed
= 0;
1404 // These seem not really needed for our purpose here.
1405 lpDIBh
->bmiHeader
.biClrImportant
= 0;
1406 lpDIBh
->bmiHeader
.biXPelsPerMeter
= 0;
1407 lpDIBh
->bmiHeader
.biYPelsPerMeter
= 0;
1408 // memory for DIB data
1409 unsigned char *lpBits
;
1410 lpBits
= (unsigned char *)malloc( lpDIBh
->bmiHeader
.biSizeImage
);
1413 wxFAIL_MSG( "could not allocate memory for DIB" );
1418 // create and set the device-dependent bitmap
1419 HDC hdc
= ::GetDC(NULL
);
1420 HDC memdc
= ::CreateCompatibleDC( hdc
);
1422 hbitmap
= ::CreateCompatibleBitmap( hdc
, width
, bmpHeight
);
1423 ::SelectObject( memdc
, hbitmap
);
1425 // copy image data into DIB data and then into DDB (in a loop)
1426 unsigned char *data
= GetData();
1429 unsigned char *ptdata
= data
;
1430 unsigned char *ptbits
;
1432 for( n
=0; n
<numDIB
; n
++ )
1434 if( numDIB
> 1 && n
== numDIB
-1 && hRemain
> 0 )
1436 // redefine height and size of the (possibly) last smaller DIB
1437 // memory is not reallocated
1439 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
1440 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
1444 for( j
=0; j
<height
; j
++ )
1446 for( i
=0; i
<width
; i
++ )
1448 *(ptbits
++) = *(ptdata
+2);
1449 *(ptbits
++) = *(ptdata
+1);
1450 *(ptbits
++) = *(ptdata
);
1453 for( i
=0; i
< padding
; i
++ ) *(ptbits
++) = 0;
1455 ::StretchDIBits( memdc
, 0, origin
, width
, height
,\
1456 0, 0, width
, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
, SRCCOPY
);
1458 // if numDIB = 1, lines below can also be used
1459 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
1460 // The above line is equivalent to the following two lines.
1461 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
1462 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
1463 // or the following lines
1464 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
1465 // HDC memdc = ::CreateCompatibleDC( hdc );
1466 // ::SelectObject( memdc, hbitmap);
1467 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
1468 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
1469 // ::SelectObject( memdc, 0 );
1470 // ::DeleteDC( memdc );
1472 bitmap
.SetHBITMAP( (WXHBITMAP
) hbitmap
);
1474 // similarly, created an mono-bitmap for the possible mask
1477 hbitmap
= ::CreateBitmap( (WORD
)width
, (WORD
)bmpHeight
, 1, 1, NULL
);
1478 ::SelectObject( memdc
, hbitmap
);
1479 if( numDIB
== 1 ) height
= bmpHeight
;
1480 else height
= sizeLimit
/bytePerLine
;
1481 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
1482 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
1484 unsigned char r
= GetMaskRed();
1485 unsigned char g
= GetMaskGreen();
1486 unsigned char b
= GetMaskBlue();
1487 unsigned char zero
= 0, one
= 255;
1489 for( n
=0; n
<numDIB
; n
++ )
1491 if( numDIB
> 1 && n
== numDIB
- 1 && hRemain
> 0 )
1493 // redefine height and size of the (possibly) last smaller DIB
1494 // memory is not reallocated
1496 lpDIBh
->bmiHeader
.biHeight
= (DWORD
)(-height
);
1497 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
*height
;
1500 for( int j
=0; j
<height
; j
++ )
1502 for(i
=0; i
<width
; i
++ )
1504 if( (*(ptdata
++)!=r
) | (*(ptdata
++)!=g
) | (*(ptdata
++)!=b
) )
1517 for( i
=0; i
< padding
; i
++ ) *(ptbits
++) = zero
;
1519 ::StretchDIBits( memdc
, 0, origin
, width
, height
,\
1520 0, 0, width
, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
, SRCCOPY
);
1523 // create a wxMask object
1524 wxMask
*mask
= new wxMask();
1525 mask
->SetMaskBitmap( (WXHBITMAP
) hbitmap
);
1526 bitmap
.SetMask( mask
);
1527 // It will be deleted when the wxBitmap object is deleted (as of 01/1999)
1528 /* The following can also be used but is slow to run
1529 wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
1530 wxMask *mask = new wxMask( bitmap, colour );
1531 bitmap.SetMask( mask );
1535 // free allocated resources
1536 ::SelectObject( memdc
, 0 );
1537 ::DeleteDC( memdc
);
1538 ::ReleaseDC(NULL
, hdc
);
1542 // check the wxBitmap object
1543 if( bitmap
.GetHBITMAP() )
1544 bitmap
.SetOk( TRUE
);
1546 bitmap
.SetOk( FALSE
);
1551 wxImage::wxImage( const wxBitmap
&bitmap
)
1556 wxFAIL_MSG( "invalid bitmap" );
1560 // create an wxImage object
1561 int width
= bitmap
.GetWidth();
1562 int height
= bitmap
.GetHeight();
1563 Create( width
, height
);
1564 unsigned char *data
= GetData();
1567 wxFAIL_MSG( "could not allocate data for image" );
1571 // calc the number of bytes per scanline and padding in the DIB
1572 int bytePerLine
= width
*3;
1573 int sizeDWORD
= sizeof( DWORD
);
1574 div_t lineBoundary
= div( bytePerLine
, sizeDWORD
);
1576 if( lineBoundary
.rem
> 0 )
1578 padding
= sizeDWORD
- lineBoundary
.rem
;
1579 bytePerLine
+= padding
;
1582 // create a DIB header
1583 int headersize
= sizeof(BITMAPINFOHEADER
);
1584 LPBITMAPINFO lpDIBh
= (BITMAPINFO
*) malloc( headersize
);
1587 wxFAIL_MSG( "could not allocate data for DIB header" );
1591 // Fill in the DIB header
1592 lpDIBh
->bmiHeader
.biSize
= headersize
;
1593 lpDIBh
->bmiHeader
.biWidth
= width
;
1594 lpDIBh
->bmiHeader
.biHeight
= -height
;
1595 lpDIBh
->bmiHeader
.biSizeImage
= bytePerLine
* height
;
1596 lpDIBh
->bmiHeader
.biPlanes
= 1;
1597 lpDIBh
->bmiHeader
.biBitCount
= 24;
1598 lpDIBh
->bmiHeader
.biCompression
= BI_RGB
;
1599 lpDIBh
->bmiHeader
.biClrUsed
= 0;
1600 // These seem not really needed for our purpose here.
1601 lpDIBh
->bmiHeader
.biClrImportant
= 0;
1602 lpDIBh
->bmiHeader
.biXPelsPerMeter
= 0;
1603 lpDIBh
->bmiHeader
.biYPelsPerMeter
= 0;
1604 // memory for DIB data
1605 unsigned char *lpBits
;
1606 lpBits
= (unsigned char *) malloc( lpDIBh
->bmiHeader
.biSizeImage
);
1609 wxFAIL_MSG( "could not allocate data for DIB" );
1615 // copy data from the device-dependent bitmap to the DIB
1616 HDC hdc
= ::GetDC(NULL
);
1618 hbitmap
= (HBITMAP
) bitmap
.GetHBITMAP();
1619 ::GetDIBits( hdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
1621 // copy DIB data into the wxImage object
1623 unsigned char *ptdata
= data
;
1624 unsigned char *ptbits
= lpBits
;
1625 for( i
=0; i
<height
; i
++ )
1627 for( j
=0; j
<width
; j
++ )
1629 *(ptdata
++) = *(ptbits
+2);
1630 *(ptdata
++) = *(ptbits
+1);
1631 *(ptdata
++) = *(ptbits
);
1637 // similarly, set data according to the possible mask bitmap
1638 if( bitmap
.GetMask() && bitmap
.GetMask()->GetMaskBitmap() )
1640 hbitmap
= (HBITMAP
) bitmap
.GetMask()->GetMaskBitmap();
1641 // memory DC created, color set, data copied, and memory DC deleted
1642 HDC memdc
= ::CreateCompatibleDC( hdc
);
1643 ::SetTextColor( memdc
, RGB( 0, 0, 0 ) );
1644 ::SetBkColor( memdc
, RGB( 255, 255, 255 ) );
1645 ::GetDIBits( memdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
1646 ::DeleteDC( memdc
);
1647 // background color set to RGB(16,16,16) in consistent with wxGTK
1648 unsigned char r
=16, g
=16, b
=16;
1651 for( i
=0; i
<height
; i
++ )
1653 for( j
=0; j
<width
; j
++ )
1667 SetMaskColour( r
, g
, b
);
1674 // free allocated resources
1675 ::ReleaseDC(NULL
, hdc
);
1684 #include "gtk/gtk.h"
1685 #include "gdk/gdk.h"
1686 #include "gdk/gdkx.h"
1688 wxBitmap
wxImage::ConvertToBitmap() const
1692 wxCHECK_MSG( Ok(), bitmap
, "invalid image" );
1694 int width
= GetWidth();
1695 int height
= GetHeight();
1697 bitmap
.SetHeight( height
);
1698 bitmap
.SetWidth( width
);
1702 GdkImage
*data_image
=
1703 gdk_image_new( GDK_IMAGE_FASTEST
, gdk_visual_get_system(), width
, height
);
1705 bitmap
.SetPixmap( gdk_pixmap_new( (GdkWindow
*)&gdk_root_parent
, width
, height
, -1 ) );
1709 GdkImage
*mask_image
= (GdkImage
*) NULL
;
1713 unsigned char *mask_data
= (unsigned char*)malloc( ((width
>> 3)+8) * height
);
1715 mask_image
= gdk_image_new_bitmap( gdk_visual_get_system(), mask_data
, width
, height
);
1717 wxMask
*mask
= new wxMask();
1718 mask
->m_bitmap
= gdk_pixmap_new( (GdkWindow
*)&gdk_root_parent
, width
, height
, 1 );
1720 bitmap
.SetMask( mask
);
1725 GdkVisual
*visual
= gdk_window_get_visual( bitmap
.GetPixmap() );
1726 if (visual
== NULL
) visual
= gdk_window_get_visual( (GdkWindow
*) &gdk_root_parent
);
1727 int bpp
= visual
->depth
;
1729 bitmap
.SetDepth( bpp
);
1731 if ((bpp
== 16) && (visual
->red_mask
!= 0xf800)) bpp
= 15;
1732 if (bpp
< 8) bpp
= 8;
1736 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
1737 byte_order b_o
= RGB
;
1741 GdkVisual
*visual
= gdk_visual_get_system();
1742 if ((visual
->red_mask
> visual
->green_mask
) && (visual
->green_mask
> visual
->blue_mask
)) b_o
= RGB
;
1743 else if ((visual
->red_mask
> visual
->blue_mask
) && (visual
->blue_mask
> visual
->green_mask
)) b_o
= RGB
;
1744 else if ((visual
->blue_mask
> visual
->red_mask
) && (visual
->red_mask
> visual
->green_mask
)) b_o
= BRG
;
1745 else if ((visual
->blue_mask
> visual
->green_mask
) && (visual
->green_mask
> visual
->red_mask
)) b_o
= BGR
;
1746 else if ((visual
->green_mask
> visual
->red_mask
) && (visual
->red_mask
> visual
->blue_mask
)) b_o
= GRB
;
1747 else if ((visual
->green_mask
> visual
->blue_mask
) && (visual
->blue_mask
> visual
->red_mask
)) b_o
= GBR
;
1750 int r_mask
= GetMaskRed();
1751 int g_mask
= GetMaskGreen();
1752 int b_mask
= GetMaskBlue();
1754 unsigned char* data
= GetData();
1757 for (int y
= 0; y
< height
; y
++)
1759 for (int x
= 0; x
< width
; x
++)
1761 int r
= data
[index
];
1763 int g
= data
[index
];
1765 int b
= data
[index
];
1770 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
1771 gdk_image_put_pixel( mask_image
, x
, y
, 1 );
1773 gdk_image_put_pixel( mask_image
, x
, y
, 0 );
1778 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
1779 gdk_image_put_pixel( mask_image
, x
, y
, 1 );
1781 gdk_image_put_pixel( mask_image
, x
, y
, 0 );
1789 if (wxTheApp
->m_colorCube
)
1791 pixel
= wxTheApp
->m_colorCube
[ ((r
& 0xf8) << 7) + ((g
& 0xf8) << 2) + ((b
& 0xf8) >> 3) ];
1795 GdkColormap
*cmap
= gtk_widget_get_default_colormap();
1796 GdkColor
*colors
= cmap
->colors
;
1797 int max
= 3 * (65536);
1799 for (int i
= 0; i
< cmap
->size
; i
++)
1801 int rdiff
= (r
<< 8) - colors
[i
].red
;
1802 int gdiff
= (g
<< 8) - colors
[i
].green
;
1803 int bdiff
= (b
<< 8) - colors
[i
].blue
;
1804 int sum
= ABS (rdiff
) + ABS (gdiff
) + ABS (bdiff
);
1805 if (sum
< max
) { pixel
= i
; max
= sum
; }
1809 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1815 guint32 pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
1816 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1821 guint32 pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
1822 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1831 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
1832 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
1833 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
1834 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
1835 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
1836 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
1838 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1847 GdkGC
*data_gc
= gdk_gc_new( bitmap
.GetPixmap() );
1849 gdk_draw_image( bitmap
.GetPixmap(), data_gc
, data_image
, 0, 0, 0, 0, width
, height
);
1851 gdk_image_destroy( data_image
);
1852 gdk_gc_unref( data_gc
);
1858 GdkGC
*mask_gc
= gdk_gc_new( bitmap
.GetMask()->GetBitmap() );
1860 gdk_draw_image( bitmap
.GetMask()->GetBitmap(), mask_gc
, mask_image
, 0, 0, 0, 0, width
, height
);
1862 gdk_image_destroy( mask_image
);
1863 gdk_gc_unref( mask_gc
);
1869 wxImage::wxImage( const wxBitmap
&bitmap
)
1871 wxCHECK_RET( bitmap
.Ok(), "invalid bitmap" );
1873 GdkImage
*gdk_image
= gdk_image_get( bitmap
.GetPixmap(),
1875 bitmap
.GetWidth(), bitmap
.GetHeight() );
1877 wxCHECK_RET( gdk_image
, "couldn't create image" );
1879 Create( bitmap
.GetWidth(), bitmap
.GetHeight() );
1880 char unsigned *data
= GetData();
1884 gdk_image_destroy( gdk_image
);
1885 wxFAIL_MSG( "couldn't create image" );
1889 GdkImage
*gdk_image_mask
= (GdkImage
*) NULL
;
1890 if (bitmap
.GetMask())
1892 gdk_image_mask
= gdk_image_get( bitmap
.GetMask()->GetBitmap(),
1894 bitmap
.GetWidth(), bitmap
.GetHeight() );
1896 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1899 GdkVisual
*visual
= gdk_window_get_visual( bitmap
.GetPixmap() );
1900 if (visual
== NULL
) visual
= gdk_window_get_visual( (GdkWindow
*) &gdk_root_parent
);
1901 int bpp
= visual
->depth
;
1902 if ((bpp
== 16) && (visual
->red_mask
!= 0xf800)) bpp
= 15;
1904 GdkColormap
*cmap
= gtk_widget_get_default_colormap();
1907 for (int j
= 0; j
< bitmap
.GetHeight(); j
++)
1909 for (int i
= 0; i
< bitmap
.GetWidth(); i
++)
1911 int pixel
= gdk_image_get_pixel( gdk_image
, i
, j
);
1914 data
[pos
] = cmap
->colors
[pixel
].red
>> 8;
1915 data
[pos
+1] = cmap
->colors
[pixel
].green
>> 8;
1916 data
[pos
+2] = cmap
->colors
[pixel
].blue
>> 8;
1917 } else if (bpp
== 15)
1919 data
[pos
] = (pixel
>> 7) & 0xf8;
1920 data
[pos
+1] = (pixel
>> 2) & 0xf8;
1921 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1922 } else if (bpp
== 16)
1924 data
[pos
] = (pixel
>> 8) & 0xf8;
1925 data
[pos
+1] = (pixel
>> 3) & 0xfc;
1926 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1929 data
[pos
] = (pixel
>> 16) & 0xff;
1930 data
[pos
+1] = (pixel
>> 8) & 0xff;
1931 data
[pos
+2] = pixel
& 0xff;
1936 int mask_pixel
= gdk_image_get_pixel( gdk_image_mask
, i
, j
);
1937 if (mask_pixel
== 0)
1949 gdk_image_destroy( gdk_image
);
1950 if (gdk_image_mask
) gdk_image_destroy( gdk_image_mask
);
1958 #include "wx/utils.h"
1961 wxBitmap
wxImage::ConvertToBitmap() const
1965 wxCHECK_MSG( Ok(), bitmap
, "invalid image" );
1967 int width
= GetWidth();
1968 int height
= GetHeight();
1970 bitmap
.SetHeight( height
);
1971 bitmap
.SetWidth( width
);
1973 Display
*dpy
= (Display
*) wxGetDisplay();
1974 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1975 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1979 XImage
*data_image
= XCreateImage( dpy
, vis
, bpp
, ZPixmap
, 0, 0, width
, height
, 32, 0 );
1980 data_image
->data
= (char*) malloc( data_image
->bytes_per_line
* data_image
->height
);
1982 bitmap
.Create( width
, height
, bpp
);
1987 GdkImage *mask_image = (GdkImage*) NULL;
1991 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1993 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1995 wxMask *mask = new wxMask();
1996 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1998 bitmap.SetMask( mask );
2002 // Retrieve depth info
2004 XVisualInfo vinfo_template
;
2007 vinfo_template
.visual
= vis
;
2008 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
2009 vinfo_template
.depth
= bpp
;
2012 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
2016 printf("no visual.\n" );
2017 return wxNullBitmap
;
2022 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
2023 if (bpp
< 8) bpp
= 8;
2027 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
2028 byte_order b_o
= RGB
;
2032 if ((vi
->red_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->blue_mask
)) b_o
= RGB
;
2033 else if ((vi
->red_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->green_mask
)) b_o
= RGB
;
2034 else if ((vi
->blue_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->green_mask
)) b_o
= BRG
;
2035 else if ((vi
->blue_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->red_mask
)) b_o
= BGR
;
2036 else if ((vi
->green_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->blue_mask
)) b_o
= GRB
;
2037 else if ((vi
->green_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->red_mask
)) b_o
= GBR
;
2041 int r_mask = GetMaskRed();
2042 int g_mask = GetMaskGreen();
2043 int b_mask = GetMaskBlue();
2049 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap( dpy
);
2051 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
2052 XQueryColors( dpy
, cmap
, colors
, 256 );
2055 unsigned char* data
= GetData();
2058 for (int y
= 0; y
< height
; y
++)
2060 for (int x
= 0; x
< width
; x
++)
2062 int r
= data
[index
];
2064 int g
= data
[index
];
2066 int b
= data
[index
];
2072 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
2073 gdk_image_put_pixel( mask_image, x, y, 1 );
2075 gdk_image_put_pixel( mask_image, x, y, 0 );
2085 if (wxTheApp->m_colorCube)
2087 pixel = wxTheApp->m_colorCube
2088 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
2093 int max
= 3 * (65536);
2094 for (int i
= 0; i
< 256; i
++)
2096 int rdiff
= (r
<< 8) - colors
[i
].red
;
2097 int gdiff
= (g
<< 8) - colors
[i
].green
;
2098 int bdiff
= (b
<< 8) - colors
[i
].blue
;
2099 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
2100 if (sum
< max
) { pixel
= i
; max
= sum
; }
2105 XPutPixel( data_image
, x
, y
, pixel
);
2110 int pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
2111 XPutPixel( data_image
, x
, y
, pixel
);
2116 int pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
2117 XPutPixel( data_image
, x
, y
, pixel
);
2126 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
2127 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
2128 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
2129 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
2130 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
2131 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
2133 XPutPixel( data_image
, x
, y
, pixel
);
2143 gcvalues
.foreground
= BlackPixel( dpy
, DefaultScreen( dpy
) );
2144 GC gc
= XCreateGC( dpy
, RootWindow ( dpy
, DefaultScreen(dpy
) ), GCForeground
, &gcvalues
);
2145 XPutImage( dpy
, (Drawable
)bitmap
.GetPixmap(), gc
, data_image
, 0, 0, 0, 0, width
, height
);
2147 XDestroyImage( data_image
);
2155 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
2157 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
2159 gdk_image_destroy( mask_image );
2160 gdk_gc_unref( mask_gc );
2167 wxImage::wxImage( const wxBitmap
&bitmap
)
2169 wxCHECK_RET( bitmap
.Ok(), "invalid bitmap" );
2171 Display
*dpy
= (Display
*) wxGetDisplay();
2172 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
2173 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
2175 XImage
*ximage
= XGetImage( dpy
,
2176 (Drawable
)bitmap
.GetPixmap(),
2178 bitmap
.GetWidth(), bitmap
.GetHeight(),
2179 AllPlanes
, ZPixmap
);
2181 wxCHECK_RET( ximage
, "couldn't create image" );
2183 Create( bitmap
.GetWidth(), bitmap
.GetHeight() );
2184 char unsigned *data
= GetData();
2188 XDestroyImage( ximage
);
2189 wxFAIL_MSG( "couldn't create image" );
2194 GdkImage *gdk_image_mask = (GdkImage*) NULL;
2195 if (bitmap.GetMask())
2197 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
2199 bitmap.GetWidth(), bitmap.GetHeight() );
2201 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
2205 // Retrieve depth info
2207 XVisualInfo vinfo_template
;
2210 vinfo_template
.visual
= vis
;
2211 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
2212 vinfo_template
.depth
= bpp
;
2215 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
2219 printf("no visual.\n" );
2223 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
2230 Colormap cmap
= (Colormap
)wxTheApp
->GetMainColormap( dpy
);
2232 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
2233 XQueryColors( dpy
, cmap
, colors
, 256 );
2237 for (int j
= 0; j
< bitmap
.GetHeight(); j
++)
2239 for (int i
= 0; i
< bitmap
.GetWidth(); i
++)
2241 int pixel
= XGetPixel( ximage
, i
, j
);
2244 data
[pos
] = colors
[pixel
].red
>> 8;
2245 data
[pos
+1] = colors
[pixel
].green
>> 8;
2246 data
[pos
+2] = colors
[pixel
].blue
>> 8;
2247 } else if (bpp
== 15)
2249 data
[pos
] = (pixel
>> 7) & 0xf8;
2250 data
[pos
+1] = (pixel
>> 2) & 0xf8;
2251 data
[pos
+2] = (pixel
<< 3) & 0xf8;
2252 } else if (bpp
== 16)
2254 data
[pos
] = (pixel
>> 8) & 0xf8;
2255 data
[pos
+1] = (pixel
>> 3) & 0xfc;
2256 data
[pos
+2] = (pixel
<< 3) & 0xf8;
2259 data
[pos
] = (pixel
>> 16) & 0xff;
2260 data
[pos
+1] = (pixel
>> 8) & 0xff;
2261 data
[pos
+2] = pixel
& 0xff;
2267 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
2268 if (mask_pixel == 0)
2281 XDestroyImage( ximage
);
2283 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
2288 // A module to allow wxImage initialization/cleanup
2289 // without calling these functions from app.cpp or from
2290 // the user's application.
2292 class wxImageModule
: public wxModule
2294 DECLARE_DYNAMIC_CLASS(wxImageModule
)
2297 bool OnInit() { wxImage::InitStandardHandlers(); return TRUE
; };
2298 void OnExit() { wxImage::CleanUpHandlers(); };
2301 IMPLEMENT_DYNAMIC_CLASS(wxImageModule
, wxModule
)