]> git.saurik.com Git - wxWidgets.git/blob - src/common/image.cpp
menu title is drawn in bold font and the commands from it are ignored
[wxWidgets.git] / src / common / image.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: image.cpp
3 // Purpose: wxImage
4 // Author: Robert Roebling
5 // RCS-ID: $Id$
6 // Copyright: (c) Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation "image.h"
12 #endif
13
14 // For compilers that support precompilation, includes "wx.h".
15 #include "wx/wxprec.h"
16
17 #ifdef __BORLANDC__
18 #pragma hdrstop
19 #endif
20
21 #include "wx/image.h"
22 #include "wx/bitmap.h"
23 #include "wx/debug.h"
24 #include "wx/log.h"
25 #include "wx/app.h"
26 #if wxUSE_LIBPNG
27 #include "../png/png.h"
28 #endif
29 #if wxUSE_LIBJPEG
30 extern "C" {
31 #include <jpeglib.h>
32 }
33 #endif
34 #include "wx/filefn.h"
35 #include "wx/wfstream.h"
36 #include "wx/intl.h"
37
38 #ifdef __SALFORDC__
39 #ifdef FAR
40 #undef FAR
41 #endif
42 #endif
43
44 #ifdef __WXMSW__
45 #include <windows.h>
46 #endif
47
48 //-----------------------------------------------------------------------------
49 // wxImage
50 //-----------------------------------------------------------------------------
51
52 class wxImageRefData: public wxObjectRefData
53 {
54
55 public:
56 wxImageRefData(void);
57 ~wxImageRefData(void);
58
59 int m_width;
60 int m_height;
61 unsigned char *m_data;
62 bool m_hasMask;
63 unsigned char m_maskRed,m_maskGreen,m_maskBlue;
64 bool m_ok;
65 };
66
67 wxImageRefData::wxImageRefData(void)
68 {
69 m_width = 0;
70 m_height = 0;
71 m_data = (unsigned char*) NULL;
72 m_ok = FALSE;
73 m_maskRed = 0;
74 m_maskGreen = 0;
75 m_maskBlue = 0;
76 m_hasMask = FALSE;
77 }
78
79 wxImageRefData::~wxImageRefData(void)
80 {
81 if (m_data) free( m_data );
82 }
83
84 wxList wxImage::sm_handlers;
85
86 //-----------------------------------------------------------------------------
87
88 #define M_IMGDATA ((wxImageRefData *)m_refData)
89
90 #if !USE_SHARED_LIBRARIES
91 IMPLEMENT_DYNAMIC_CLASS(wxImage, wxObject)
92 #endif
93
94 wxImage::wxImage()
95 {
96 }
97
98 wxImage::wxImage( int width, int height )
99 {
100 Create( width, height );
101 }
102
103 wxImage::wxImage( const wxString& name, long type )
104 {
105 LoadFile( name, type );
106 }
107
108 #if wxUSE_STREAMS
109 wxImage::wxImage( wxInputStream& stream, long type )
110 {
111 LoadFile( stream, type );
112 }
113 #endif // wxUSE_STREAMS
114
115 wxImage::wxImage( const wxImage& image )
116 {
117 Ref(image);
118 }
119
120 wxImage::wxImage( const wxImage* image )
121 {
122 if (image) Ref(*image);
123 }
124
125 void wxImage::Create( int width, int height )
126 {
127 m_refData = new wxImageRefData();
128
129 M_IMGDATA->m_data = (unsigned char *) malloc( width*height*3 );
130 if (M_IMGDATA->m_data)
131 {
132 for (int l = 0; l < width*height*3; l++) M_IMGDATA->m_data[l] = 0;
133
134 M_IMGDATA->m_width = width;
135 M_IMGDATA->m_height = height;
136 M_IMGDATA->m_ok = TRUE;
137 }
138 else
139 {
140 UnRef();
141 }
142 }
143
144 void wxImage::Destroy()
145 {
146 UnRef();
147 }
148
149 wxImage wxImage::Scale( int width, int height )
150 {
151 wxImage image;
152
153 wxCHECK_MSG( Ok(), image, "invlaid image" );
154
155 wxCHECK_MSG( (width > 0) && (height > 0), image, "invalid image size" );
156
157 image.Create( width, height );
158
159 char unsigned *data = image.GetData();
160
161 wxCHECK_MSG( data, image, "unable to create image" );
162
163 if (M_IMGDATA->m_hasMask)
164 image.SetMaskColour( M_IMGDATA->m_maskRed, M_IMGDATA->m_maskGreen, M_IMGDATA->m_maskBlue );
165
166 long old_height = M_IMGDATA->m_height;
167 long old_width = M_IMGDATA->m_width;
168
169 char unsigned *source_data = M_IMGDATA->m_data;
170 char unsigned *target_data = data;
171
172 for (long j = 0; j < height; j++)
173 {
174 long y_offset = (j * old_height / height) * old_width;
175
176 for (long i = 0; i < width; i++)
177 {
178 memcpy( target_data,
179 source_data + 3*(y_offset + ((i * old_width )/ width)),
180 3 );
181 target_data += 3;
182 }
183 }
184
185 return image;
186 }
187
188 void wxImage::SetRGB( int x, int y, unsigned char r, unsigned char g, unsigned char b )
189 {
190 wxCHECK_RET( Ok(), "invalid image" );
191
192 int w = M_IMGDATA->m_width;
193 int h = M_IMGDATA->m_height;
194
195 wxCHECK_RET( (x>=0) && (y>=0) && (x<w) && (y<h), "invalid image index" );
196
197 long pos = (y * w + x) * 3;
198
199 M_IMGDATA->m_data[ pos ] = r;
200 M_IMGDATA->m_data[ pos+1 ] = g;
201 M_IMGDATA->m_data[ pos+2 ] = b;
202 }
203
204 unsigned char wxImage::GetRed( int x, int y )
205 {
206 wxCHECK_MSG( Ok(), 0, "invalid image" );
207
208 int w = M_IMGDATA->m_width;
209 int h = M_IMGDATA->m_height;
210
211 wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, "invalid image index" );
212
213 long pos = (y * w + x) * 3;
214
215 return M_IMGDATA->m_data[pos];
216 }
217
218 unsigned char wxImage::GetGreen( int x, int y )
219 {
220 wxCHECK_MSG( Ok(), 0, "invalid image" );
221
222 int w = M_IMGDATA->m_width;
223 int h = M_IMGDATA->m_height;
224
225 wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, "invalid image index" );
226
227 long pos = (y * w + x) * 3;
228
229 return M_IMGDATA->m_data[pos+1];
230 }
231
232 unsigned char wxImage::GetBlue( int x, int y )
233 {
234 wxCHECK_MSG( Ok(), 0, "invalid image" );
235
236 int w = M_IMGDATA->m_width;
237 int h = M_IMGDATA->m_height;
238
239 wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, "invalid image index" );
240
241 long pos = (y * w + x) * 3;
242
243 return M_IMGDATA->m_data[pos+2];
244 }
245
246 bool wxImage::Ok() const
247 {
248 return (M_IMGDATA && M_IMGDATA->m_ok);
249 }
250
251 char unsigned *wxImage::GetData() const
252 {
253 wxCHECK_MSG( Ok(), (char unsigned *)NULL, "invalid image" );
254
255 return M_IMGDATA->m_data;
256 }
257
258 void wxImage::SetData( char unsigned *WXUNUSED(data) )
259 {
260 wxCHECK_RET( Ok(), "invalid image" );
261 }
262
263 void wxImage::SetMaskColour( unsigned char r, unsigned char g, unsigned char b )
264 {
265 wxCHECK_RET( Ok(), "invalid image" );
266
267 M_IMGDATA->m_maskRed = r;
268 M_IMGDATA->m_maskGreen = g;
269 M_IMGDATA->m_maskBlue = b;
270 M_IMGDATA->m_hasMask = TRUE;
271 }
272
273 unsigned char wxImage::GetMaskRed() const
274 {
275 wxCHECK_MSG( Ok(), 0, "invalid image" );
276
277 return M_IMGDATA->m_maskRed;
278 }
279
280 unsigned char wxImage::GetMaskGreen() const
281 {
282 wxCHECK_MSG( Ok(), 0, "invalid image" );
283
284 return M_IMGDATA->m_maskGreen;
285 }
286
287 unsigned char wxImage::GetMaskBlue() const
288 {
289 wxCHECK_MSG( Ok(), 0, "invalid image" );
290
291 return M_IMGDATA->m_maskBlue;
292 }
293
294 void wxImage::SetMask( bool mask )
295 {
296 wxCHECK_RET( Ok(), "invalid image" );
297
298 M_IMGDATA->m_hasMask = mask;
299 }
300
301 bool wxImage::HasMask() const
302 {
303 wxCHECK_MSG( Ok(), FALSE, "invalid image" );
304
305 return M_IMGDATA->m_hasMask;
306 }
307
308 int wxImage::GetWidth() const
309 {
310 wxCHECK_MSG( Ok(), 0, "invalid image" );
311
312 return M_IMGDATA->m_width;
313 }
314
315 int wxImage::GetHeight() const
316 {
317 wxCHECK_MSG( Ok(), 0, "invalid image" );
318
319 return M_IMGDATA->m_height;
320 }
321
322 bool wxImage::LoadFile( const wxString& filename, long type )
323 {
324 #if wxUSE_STREAMS
325 if (wxFileExists(filename))
326 {
327 wxFileInputStream stream(filename);
328 return LoadFile(stream, type);
329 }
330
331 else {
332 wxLogError( "Can't load image from file '%s': file does not exist.", filename.c_str() );
333
334 return FALSE;
335 }
336 #else // !wxUSE_STREAMS
337 return FALSE;
338 #endif // wxUSE_STREAMS
339 }
340
341 bool wxImage::SaveFile( const wxString& filename, int type )
342 {
343 #if wxUSE_STREAMS
344 wxFileOutputStream stream(filename);
345
346 if ( stream.LastError() == wxStream_NOERROR )
347 return SaveFile(stream, type);
348 else
349 #endif // wxUSE_STREAMS
350 return FALSE;
351 }
352
353 #if wxUSE_STREAMS
354 bool wxImage::LoadFile( wxInputStream& stream, long type )
355 {
356 UnRef();
357
358 m_refData = new wxImageRefData;
359
360 wxImageHandler *handler = FindHandler(type);
361
362 if (handler == NULL)
363 {
364 wxLogWarning( "No image handler for type %d defined.", type );
365
366 return FALSE;
367 }
368
369 return handler->LoadFile( this, stream );
370 }
371
372 bool wxImage::SaveFile( wxOutputStream& stream, int type )
373 {
374 wxCHECK_MSG( Ok(), FALSE, "invalid image" );
375
376 wxImageHandler *handler = FindHandler(type);
377
378 if (handler == NULL)
379 {
380 wxLogWarning( "No image handler for type %d defined.", type );
381
382 return FALSE;
383 }
384
385 return handler->SaveFile( this, stream );
386 }
387 #endif // wxUSE_STREAMS
388
389 void wxImage::AddHandler( wxImageHandler *handler )
390 {
391 // make sure that the memory will be freed at the program end
392 sm_handlers.DeleteContents(TRUE);
393
394 sm_handlers.Append( handler );
395 }
396
397 void wxImage::InsertHandler( wxImageHandler *handler )
398 {
399 // make sure that the memory will be freed at the program end
400 sm_handlers.DeleteContents(TRUE);
401
402 sm_handlers.Insert( handler );
403 }
404
405 bool wxImage::RemoveHandler( const wxString& name )
406 {
407 wxImageHandler *handler = FindHandler(name);
408 if (handler)
409 {
410 sm_handlers.DeleteObject(handler);
411 return TRUE;
412 }
413 else
414 return FALSE;
415 }
416
417 wxImageHandler *wxImage::FindHandler( const wxString& name )
418 {
419 wxNode *node = sm_handlers.First();
420 while (node)
421 {
422 wxImageHandler *handler = (wxImageHandler*)node->Data();
423 if (handler->GetName().Cmp(name) == 0) return handler;
424
425 node = node->Next();
426 }
427 return (wxImageHandler *)NULL;
428 }
429
430 wxImageHandler *wxImage::FindHandler( const wxString& extension, long bitmapType )
431 {
432 wxNode *node = sm_handlers.First();
433 while (node)
434 {
435 wxImageHandler *handler = (wxImageHandler*)node->Data();
436 if ( (handler->GetExtension().Cmp(extension) == 0) &&
437 (bitmapType == -1 || handler->GetType() == bitmapType) )
438 return handler;
439 node = node->Next();
440 }
441 return (wxImageHandler*)NULL;
442 }
443
444 wxImageHandler *wxImage::FindHandler( long bitmapType )
445 {
446 wxNode *node = sm_handlers.First();
447 while (node)
448 {
449 wxImageHandler *handler = (wxImageHandler *)node->Data();
450 if (handler->GetType() == bitmapType) return handler;
451 node = node->Next();
452 }
453 return NULL;
454 }
455
456 void wxImage::InitStandardHandlers()
457 {
458 AddHandler( new wxBMPHandler );
459 #if wxUSE_LIBPNG
460 AddHandler( new wxPNGHandler );
461 #endif
462 }
463
464 void wxImage::CleanUpHandlers()
465 {
466 wxNode *node = sm_handlers.First();
467 while (node)
468 {
469 wxImageHandler *handler = (wxImageHandler *)node->Data();
470 wxNode *next = node->Next();
471 delete handler;
472 delete node;
473 node = next;
474 }
475 }
476
477 //-----------------------------------------------------------------------------
478 // wxImageHandler
479 //-----------------------------------------------------------------------------
480
481 #if !USE_SHARED_LIBRARIES
482 IMPLEMENT_DYNAMIC_CLASS(wxImageHandler,wxObject)
483 #endif
484
485 #if wxUSE_STREAMS
486 bool wxImageHandler::LoadFile( wxImage *WXUNUSED(image), wxInputStream& WXUNUSED(stream) )
487 {
488 return FALSE;
489 }
490
491 bool wxImageHandler::SaveFile( wxImage *WXUNUSED(image), wxOutputStream& WXUNUSED(stream) )
492 {
493 return FALSE;
494 }
495 #endif // wxUSE_STREAMS
496
497 //-----------------------------------------------------------------------------
498 // wxPNGHandler
499 //-----------------------------------------------------------------------------
500
501 #if wxUSE_LIBPNG
502
503 #if !USE_SHARED_LIBRARIES
504 IMPLEMENT_DYNAMIC_CLASS(wxPNGHandler,wxImageHandler)
505 #endif
506
507
508 #if wxUSE_STREAMS
509 static void _PNG_stream_reader( png_structp png_ptr, png_bytep data, png_size_t length )
510 {
511 ((wxInputStream*) png_get_io_ptr( png_ptr )) -> Read(data, length);
512 }
513
514 static void _PNG_stream_writer( png_structp png_ptr, png_bytep data, png_size_t length )
515 {
516 ((wxOutputStream*) png_get_io_ptr( png_ptr )) -> Write(data, length);
517 }
518
519 bool wxPNGHandler::LoadFile( wxImage *image, wxInputStream& stream )
520 {
521 // VZ: as this function uses setjmp() the only fool proof error handling
522 // method is to use goto (setjmp is not really C++ dtors friendly...)
523
524 unsigned char **lines = (unsigned char **) NULL;
525 unsigned int i;
526 png_infop info_ptr = (png_infop) NULL;
527
528 image->Destroy();
529
530 png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING,
531 (voidp) NULL,
532 (png_error_ptr) NULL,
533 (png_error_ptr) NULL );
534 if (!png_ptr)
535 goto error;
536
537 info_ptr = png_create_info_struct( png_ptr );
538 if (!info_ptr)
539 goto error;
540
541 if (setjmp(png_ptr->jmpbuf))
542 goto error;
543
544 if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
545 goto error;
546
547 png_set_read_fn( png_ptr, &stream, _PNG_stream_reader);
548
549 png_uint_32 width,height;
550 int bit_depth,color_type,interlace_type;
551
552 png_read_info( png_ptr, info_ptr );
553 png_get_IHDR( png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, (int*) NULL, (int*) NULL );
554
555 if (color_type == PNG_COLOR_TYPE_PALETTE)
556 png_set_expand( png_ptr );
557
558 png_set_strip_16( png_ptr );
559 png_set_packing( png_ptr );
560 if (png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS))
561 png_set_expand( png_ptr );
562 png_set_filler( png_ptr, 0xff, PNG_FILLER_AFTER );
563
564 image->Create( width, height );
565
566 if (!image->Ok())
567 goto error;
568
569 lines = (unsigned char **)malloc( height * sizeof(unsigned char *) );
570 if (lines == NULL)
571 goto error;
572
573 for (i = 0; i < height; i++)
574 {
575 if ((lines[i] = (unsigned char *)malloc(width * (sizeof(unsigned char) * 4))) == NULL)
576 {
577 for ( unsigned int n = 0; n < i; n++ )
578 free( lines[n] );
579 goto error;
580 }
581 }
582
583 // loaded successfully!
584 {
585 int transp = 0;
586 png_read_image( png_ptr, lines );
587 png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL );
588 unsigned char *ptr = image->GetData();
589 if ((color_type == PNG_COLOR_TYPE_GRAY) ||
590 (color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
591 {
592 for (unsigned int y = 0; y < height; y++)
593 {
594 unsigned char *ptr2 = lines[y];
595 for (unsigned int x = 0; x < width; x++)
596 {
597 unsigned char r = *ptr2++;
598 unsigned char a = *ptr2++;
599 if (a < 128)
600 {
601 *ptr++ = 255;
602 *ptr++ = 0;
603 *ptr++ = 255;
604 transp = 1;
605 }
606 else
607 {
608 *ptr++ = r;
609 *ptr++ = r;
610 *ptr++ = r;
611 }
612 }
613 }
614 }
615 else
616 {
617 for (unsigned int y = 0; y < height; y++)
618 {
619 unsigned char *ptr2 = lines[y];
620 for (unsigned int x = 0; x < width; x++)
621 {
622 unsigned char r = *ptr2++;
623 unsigned char g = *ptr2++;
624 unsigned char b = *ptr2++;
625 unsigned char a = *ptr2++;
626 if (a < 128)
627 {
628 *ptr++ = 255;
629 *ptr++ = 0;
630 *ptr++ = 255;
631 transp = 1;
632 }
633 else
634 {
635 if ((r == 255) && (g == 0) && (b == 255)) r = 254;
636 *ptr++ = r;
637 *ptr++ = g;
638 *ptr++ = b;
639 }
640 }
641 }
642 }
643
644 for ( unsigned int j = 0; j < height; j++ )
645 free( lines[j] );
646 free( lines );
647
648 if (transp)
649 {
650 image->SetMaskColour( 255, 0, 255 );
651 }
652 else
653 {
654 image->SetMask( FALSE );
655 }
656 }
657
658 return TRUE;
659
660 error:
661 wxLogError(_("Couldn't load a PNG image - probably file is corrupted."));
662
663 if ( image->Ok() )
664 {
665 image->Destroy();
666 }
667
668 if ( lines )
669 {
670 free( lines );
671 }
672
673 if ( png_ptr )
674 {
675 if ( info_ptr )
676 {
677 png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL );
678 free(info_ptr);
679 }
680 else
681 png_destroy_read_struct( &png_ptr, (png_infopp) NULL, (png_infopp) NULL );
682 }
683 return FALSE;
684 }
685
686
687 bool wxPNGHandler::SaveFile( wxImage *image, wxOutputStream& stream )
688 {
689 {
690 png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
691 if (!png_ptr)
692 {
693 return FALSE;
694 }
695
696 png_infop info_ptr = png_create_info_struct(png_ptr);
697 if (info_ptr == NULL)
698 {
699 png_destroy_write_struct( &png_ptr, (png_infopp)NULL );
700 return FALSE;
701 }
702
703 if (setjmp(png_ptr->jmpbuf))
704 {
705 png_destroy_write_struct( &png_ptr, (png_infopp)NULL );
706 return FALSE;
707 }
708
709 png_set_write_fn( png_ptr, &stream, _PNG_stream_writer, NULL);
710
711 png_set_IHDR( png_ptr, info_ptr, image->GetWidth(), image->GetHeight(), 8,
712 PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
713 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
714
715 png_color_8 sig_bit;
716 sig_bit.red = 8;
717 sig_bit.green = 8;
718 sig_bit.blue = 8;
719 sig_bit.alpha = 8;
720 png_set_sBIT( png_ptr, info_ptr, &sig_bit );
721 png_write_info( png_ptr, info_ptr );
722 png_set_shift( png_ptr, &sig_bit );
723 png_set_packing( png_ptr );
724
725 unsigned char *data = (unsigned char *)malloc( image->GetWidth()*4 );
726 if (!data)
727 {
728 png_destroy_write_struct( &png_ptr, (png_infopp)NULL );
729 return FALSE;
730 }
731
732 for (int y = 0; y < image->GetHeight(); y++)
733 {
734 unsigned char *ptr = image->GetData() + (y * image->GetWidth() * 3);
735 for (int x = 0; x < image->GetWidth(); x++)
736 {
737 data[(x << 2) + 0] = *ptr++;
738 data[(x << 2) + 1] = *ptr++;
739 data[(x << 2) + 2] = *ptr++;
740 if ((data[(x << 2) + 0] == image->GetMaskRed()) &&
741 (data[(x << 2) + 1] == image->GetMaskGreen()) &&
742 (data[(x << 2) + 2] == image->GetMaskBlue()))
743 {
744 data[(x << 2) + 3] = 0;
745 }
746 else
747 {
748 data[(x << 2) + 3] = 255;
749 }
750 }
751 png_bytep row_ptr = data;
752 png_write_rows( png_ptr, &row_ptr, 1 );
753 }
754
755 free(data);
756 png_write_end( png_ptr, info_ptr );
757 png_destroy_write_struct( &png_ptr, (png_infopp)&info_ptr );
758 }
759 return TRUE;
760 }
761 #endif // wxUSE_STREAMS
762
763 #endif
764
765 // wxUSE_LIBPNG
766
767
768 //-----------------------------------------------------------------------------
769 // wxJPEGHandler
770 //-----------------------------------------------------------------------------
771
772 #if wxUSE_LIBJPEG
773
774 #if !USE_SHARED_LIBRARIES
775 IMPLEMENT_DYNAMIC_CLASS(wxJPEGHandler,wxImageHandler)
776 #endif
777
778 #if wxUSE_STREAMS
779
780
781 //------------- JPEG Data Source Manager
782
783 typedef struct {
784 struct jpeg_source_mgr pub; /* public fields */
785
786 JOCTET* buffer; /* start of buffer */
787 } my_source_mgr;
788
789 typedef my_source_mgr * my_src_ptr;
790
791 METHODDEF(void) my_init_source ( j_decompress_ptr cinfo )
792 {
793 }
794
795 METHODDEF(boolean) my_fill_input_buffer ( j_decompress_ptr cinfo )
796 {
797 return TRUE;
798 }
799
800 METHODDEF(void) my_skip_input_data ( j_decompress_ptr cinfo, long num_bytes )
801 {
802 my_src_ptr src = (my_src_ptr) cinfo->src;
803
804 src->pub.next_input_byte += (size_t) num_bytes;
805 src->pub.bytes_in_buffer -= (size_t) num_bytes;
806 }
807
808 METHODDEF(void) my_term_source ( j_decompress_ptr cinfo )
809 {
810 my_src_ptr src = (my_src_ptr) cinfo->src;
811
812 free (src->buffer);
813 }
814
815 void jpeg_wxio_src( j_decompress_ptr cinfo, wxInputStream& infile )
816 {
817 my_src_ptr src;
818
819 if (cinfo->src == NULL) { /* first time for this JPEG object? */
820 cinfo->src = (struct jpeg_source_mgr *)
821 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
822 sizeof(my_source_mgr));
823 src = (my_src_ptr) cinfo->src;
824 }
825 src = (my_src_ptr) cinfo->src;
826 src->pub.bytes_in_buffer = infile.StreamSize(); /* forces fill_input_buffer on first read */
827 src->buffer = (JOCTET *) malloc (infile.StreamSize());
828 src->pub.next_input_byte = src->buffer; /* until buffer loaded */
829 infile.Read(src->buffer, infile.StreamSize());
830
831 src->pub.init_source = my_init_source;
832 src->pub.fill_input_buffer = my_fill_input_buffer;
833 src->pub.skip_input_data = my_skip_input_data;
834 src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
835 src->pub.term_source = my_term_source;
836 }
837
838
839
840 bool wxJPEGHandler::LoadFile( wxImage *image, wxInputStream& stream )
841 {
842 struct jpeg_decompress_struct cinfo;
843 struct jpeg_error_mgr jerr;
844 JSAMPARRAY tempbuf;
845 unsigned char *ptr;
846 unsigned stride;
847
848 image->Destroy();
849 cinfo.err = jpeg_std_error( &jerr );
850 jpeg_create_decompress( &cinfo );
851 jpeg_wxio_src( &cinfo, stream );
852 jpeg_read_header( &cinfo, TRUE );
853 cinfo.out_color_space = JCS_RGB;
854 jpeg_start_decompress( &cinfo );
855
856 image->Create( cinfo.image_width, cinfo.image_height );
857 if (!image->Ok()) {
858 jpeg_finish_decompress( &cinfo );
859 jpeg_destroy_decompress( &cinfo );
860 return FALSE;
861 }
862 image->SetMask( FALSE );
863 ptr = image->GetData();
864 stride = cinfo.output_width * 3;
865 tempbuf = (*cinfo.mem->alloc_sarray)
866 ((j_common_ptr) &cinfo, JPOOL_IMAGE, stride, 1 );
867
868 while ( cinfo.output_scanline < cinfo.output_height ) {
869 jpeg_read_scanlines( &cinfo, tempbuf, 1 );
870 memcpy( ptr, tempbuf[0], stride );
871 ptr += stride;
872 }
873 jpeg_finish_decompress( &cinfo );
874 jpeg_destroy_decompress( &cinfo );
875 return TRUE;
876 }
877
878
879
880
881
882 typedef struct {
883 struct jpeg_destination_mgr pub;
884
885 wxOutputStream *stream;
886 JOCTET * buffer;
887 } my_destination_mgr;
888
889 typedef my_destination_mgr * my_dest_ptr;
890
891 #define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */
892
893 METHODDEF(void) init_destination (j_compress_ptr cinfo)
894 {
895 my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
896
897 /* Allocate the output buffer --- it will be released when done with image */
898 dest->buffer = (JOCTET *)
899 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
900 OUTPUT_BUF_SIZE * sizeof(JOCTET));
901 dest->pub.next_output_byte = dest->buffer;
902 dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
903 }
904
905 METHODDEF(boolean) empty_output_buffer (j_compress_ptr cinfo)
906 {
907 my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
908
909 dest->stream->Write(dest->buffer, OUTPUT_BUF_SIZE);
910 dest->pub.next_output_byte = dest->buffer;
911 dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
912 return TRUE;
913 }
914
915 METHODDEF(void) term_destination (j_compress_ptr cinfo)
916 {
917 my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
918 size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
919 /* Write any data remaining in the buffer */
920 if (datacount > 0)
921 dest->stream->Write(dest->buffer, datacount);
922 }
923
924 GLOBAL(void) jpeg_wxio_dest (j_compress_ptr cinfo, wxOutputStream& outfile)
925 {
926 my_dest_ptr dest;
927
928 if (cinfo->dest == NULL) { /* first time for this JPEG object? */
929 cinfo->dest = (struct jpeg_destination_mgr *)
930 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
931 sizeof(my_destination_mgr));
932 }
933
934 dest = (my_dest_ptr) cinfo->dest;
935 dest->pub.init_destination = init_destination;
936 dest->pub.empty_output_buffer = empty_output_buffer;
937 dest->pub.term_destination = term_destination;
938 dest->stream = &outfile;
939 }
940
941
942
943 bool wxJPEGHandler::SaveFile( wxImage *image, wxOutputStream& stream )
944 {
945 struct jpeg_compress_struct cinfo;
946 struct jpeg_error_mgr jerr;
947 JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
948 JSAMPLE *image_buffer;
949 int stride; /* physical row width in image buffer */
950
951 cinfo.err = jpeg_std_error(&jerr);
952 jpeg_create_compress(&cinfo);
953 jpeg_wxio_dest(&cinfo, stream);
954
955 cinfo.image_width = image->GetWidth();
956 cinfo.image_height = image->GetHeight();
957 cinfo.input_components = 3;
958 cinfo.in_color_space = JCS_RGB;
959 jpeg_set_defaults(&cinfo);
960 jpeg_start_compress(&cinfo, TRUE);
961
962 stride = cinfo.image_width * 3; /* JSAMPLEs per row in image_buffer */
963 image_buffer = image->GetData();
964 while (cinfo.next_scanline < cinfo.image_height) {
965 row_pointer[0] = &image_buffer[cinfo.next_scanline * stride];
966 jpeg_write_scanlines( &cinfo, row_pointer, 1 );
967 }
968 jpeg_finish_compress(&cinfo);
969 jpeg_destroy_compress(&cinfo);
970
971 return TRUE;
972 }
973 #endif // wxUSE_STREAMS
974
975 #endif
976
977 // wxUSE_LIBJPEG
978
979
980
981 //-----------------------------------------------------------------------------
982 // wxBMPHandler
983 //-----------------------------------------------------------------------------
984
985 #if !USE_SHARED_LIBRARIES
986 IMPLEMENT_DYNAMIC_CLASS(wxBMPHandler,wxImageHandler)
987 #endif
988
989 #if wxUSE_STREAMS
990 bool wxBMPHandler::LoadFile( wxImage *image, wxInputStream& stream )
991 {
992 unsigned char *data, *ptr;
993 int done, i, bpp, planes, comp, ncolors, line, column,
994 linesize, linepos, rshift = 0, gshift = 0, bshift = 0;
995 unsigned char aByte;
996 short int word;
997 long int dbuf[4], dword, rmask = 0, gmask = 0, bmask = 0, offset,
998 size;
999 off_t start_offset = stream.TellI();
1000 signed char bbuf[4];
1001 struct _cmap
1002 {
1003 unsigned char r, g, b;
1004 }
1005 *cmap = NULL;
1006 #ifndef BI_RGB
1007 #define BI_RGB 0
1008 #define BI_RLE8 1
1009 #define BI_RLE4 2
1010 #endif
1011
1012 #ifndef BI_BITFIELDS
1013 #define BI_BITFIELDS 3
1014 #endif
1015
1016 image->Destroy();
1017
1018 done = 0;
1019 /*
1020 * Reading the bmp header
1021 */
1022
1023 stream.Read(&bbuf, 2);
1024
1025 stream.Read(dbuf, 4 * 4);
1026
1027 size = dbuf[0];
1028 offset = dbuf[2];
1029
1030 stream.Read(dbuf, 4 * 2);
1031 int width = (int)dbuf[0];
1032 int height = (int)dbuf[1];
1033 if (width > 32767)
1034 {
1035 wxLogError( "Image width > 32767 pixels for file\n" );
1036 return FALSE;
1037 }
1038 if (height > 32767)
1039 {
1040 wxLogError( "Image height > 32767 pixels for file\n" );
1041 return FALSE;
1042 }
1043 stream.Read(&word, 2);
1044 planes = (int)word;
1045 stream.Read(&word, 2);
1046 bpp = (int)word;
1047 if (bpp != 1 && bpp != 4 && bpp != 8 && bpp && 16 && bpp != 24 && bpp != 32)
1048 {
1049 wxLogError( "unknown bitdepth in file\n" );
1050 return FALSE;
1051 }
1052 stream.Read(dbuf, 4 * 4);
1053 comp = (int)dbuf[0];
1054 if (comp != BI_RGB && comp != BI_RLE4 && comp != BI_RLE8 && comp != BI_BITFIELDS)
1055 {
1056 wxLogError( "unknown encoding in Windows BMP file\n" );
1057 return FALSE;
1058 }
1059 stream.Read(dbuf, 4 * 2);
1060 ncolors = (int)dbuf[0];
1061 if (ncolors == 0)
1062 ncolors = 1 << bpp;
1063 /* some more sanity checks */
1064 if (((comp == BI_RLE4) && (bpp != 4)) || ((comp == BI_RLE8) && (bpp != 8)) || ((comp == BI_BITFIELDS) && (bpp != 16 && bpp != 32)))
1065 {
1066 wxLogError( "encoding of BMP doesn't match bitdepth\n" );
1067 return FALSE;
1068 }
1069 if (bpp < 16)
1070 {
1071 cmap = (struct _cmap *)malloc(sizeof(struct _cmap) * ncolors);
1072
1073 if (!cmap)
1074 {
1075 wxLogError( "Cannot allocate RAM for color map in BMP file\n" );
1076 return FALSE;
1077 }
1078 }
1079 else
1080 cmap = NULL;
1081
1082 image->Create( width, height );
1083 ptr = image->GetData();
1084 if (!ptr)
1085 {
1086 wxLogError( "Cannot allocate RAM for RGB data in file\n" );
1087 if (cmap)
1088 free(cmap);
1089 return FALSE;
1090 }
1091
1092 /*
1093 * Reading the palette, if it exists.
1094 */
1095 if (bpp < 16 && ncolors != 0)
1096 {
1097 for (i = 0; i < ncolors; i++)
1098 {
1099 stream.Read(bbuf, 4);
1100 cmap[i].b = bbuf[0];
1101 cmap[i].g = bbuf[1];
1102 cmap[i].r = bbuf[2];
1103 }
1104 }
1105 else if (bpp == 16 || bpp == 32)
1106 {
1107 if (comp == BI_BITFIELDS)
1108 {
1109 int bit = 0;
1110
1111 stream.Read(dbuf, 4 * 3);
1112 bmask = dbuf[0];
1113 gmask = dbuf[1];
1114 rmask = dbuf[2];
1115 /* find shift amount.. ugly, but i can't think of a better way */
1116 for (bit = 0; bit < bpp; bit++)
1117 {
1118 if (bmask & (1 << bit))
1119 bshift = bit;
1120 if (gmask & (1 << bit))
1121 gshift = bit;
1122 if (rmask & (1 << bit))
1123 rshift = bit;
1124 }
1125 }
1126 else if (bpp == 16)
1127 {
1128 rmask = 0x7C00;
1129 gmask = 0x03E0;
1130 bmask = 0x001F;
1131 rshift = 10;
1132 gshift = 5;
1133 bshift = 0;
1134 }
1135 else if (bpp == 32)
1136 {
1137 rmask = 0x00FF0000;
1138 gmask = 0x0000FF00;
1139 bmask = 0x000000FF;
1140 rshift = 16;
1141 gshift = 8;
1142 bshift = 0;
1143 }
1144 }
1145
1146 /*
1147 * Reading the image data
1148 */
1149 stream.SeekI(start_offset + offset);
1150 data = ptr;
1151
1152 /* set the whole image to the background color */
1153 if (bpp < 16 && (comp == BI_RLE4 || comp == BI_RLE8))
1154 {
1155 for (i = 0; i < width * height; i++)
1156 {
1157 *ptr++ = cmap[0].r;
1158 *ptr++ = cmap[0].g;
1159 *ptr++ = cmap[0].b;
1160 }
1161 ptr = data;
1162 }
1163 line = 0;
1164 column = 0;
1165 #define poffset (line * width * 3 + column * 3)
1166
1167 /*
1168 * BMPs are stored upside down... hmmmmmmmmmm....
1169 */
1170
1171 linesize = ((width * bpp + 31) / 32) * 4;
1172 for (line = (height - 1); line >= 0; line--)
1173 {
1174 linepos = 0;
1175 for (column = 0; column < width;)
1176 {
1177 if (bpp < 16)
1178 {
1179 int index;
1180
1181 linepos++;
1182 aByte = stream.GetC();
1183 if (bpp == 1)
1184 {
1185 int bit = 0;
1186
1187 for (bit = 0; bit < 8; bit++)
1188 {
1189 index = ((aByte & (0x80 >> bit)) ? 1 : 0);
1190 ptr[poffset] = cmap[index].r;
1191 ptr[poffset + 1] = cmap[index].g;
1192 ptr[poffset + 2] = cmap[index].b;
1193 column++;
1194 }
1195 }
1196 else if (bpp == 4)
1197 {
1198 if (comp == BI_RLE4)
1199 {
1200 wxLogError( "can't deal with 4bit encoded yet.\n");
1201 image->Destroy();
1202 free(cmap);
1203 return FALSE;
1204 }
1205 else
1206 {
1207 int nibble = 0;
1208
1209 for (nibble = 0; nibble < 2; nibble++)
1210 {
1211 index = ((aByte & (0xF0 >> nibble * 4)) >> (!nibble * 4));
1212 if (index >= 16)
1213 index = 15;
1214 ptr[poffset] = cmap[index].r;
1215 ptr[poffset + 1] = cmap[index].g;
1216 ptr[poffset + 2] = cmap[index].b;
1217 column++;
1218 }
1219 }
1220 }
1221 else if (bpp == 8)
1222 {
1223 if (comp == BI_RLE8)
1224 {
1225 unsigned char first;
1226
1227 first = aByte;
1228 aByte = stream.GetC();
1229 if (first == 0)
1230 {
1231 if (aByte == 0)
1232 {
1233 /* column = width; */
1234 }
1235 else if (aByte == 1)
1236 {
1237 column = width;
1238 line = -1;
1239 }
1240 else if (aByte == 2)
1241 {
1242 aByte = stream.GetC();
1243 column += aByte;
1244 linepos = column * bpp / 8;
1245 aByte = stream.GetC();
1246 line += aByte;
1247 }
1248 else
1249 {
1250 int absolute = aByte;
1251
1252 for (i = 0; i < absolute; i++)
1253 {
1254 linepos++;
1255 aByte = stream.GetC();
1256 ptr[poffset] = cmap[aByte].r;
1257 ptr[poffset + 1] = cmap[aByte].g;
1258 ptr[poffset + 2] = cmap[aByte].b;
1259 column++;
1260 }
1261 if (absolute & 0x01)
1262 aByte = stream.GetC();
1263 }
1264 }
1265 else
1266 {
1267 for (i = 0; i < first; i++)
1268 {
1269 ptr[poffset] = cmap[aByte].r;
1270 ptr[poffset + 1] = cmap[aByte].g;
1271 ptr[poffset + 2] = cmap[aByte].b;
1272 column++;
1273 linepos++;
1274 }
1275 }
1276 }
1277 else
1278 {
1279 ptr[poffset] = cmap[aByte].r;
1280 ptr[poffset + 1] = cmap[aByte].g;
1281 ptr[poffset + 2] = cmap[aByte].b;
1282 column++;
1283 linepos += size;
1284 }
1285 }
1286 }
1287 else if (bpp == 24)
1288 {
1289 stream.Read(&bbuf, 3);
1290 linepos += 3;
1291 ptr[poffset] = (unsigned char)bbuf[2];
1292 ptr[poffset + 1] = (unsigned char)bbuf[1];
1293 ptr[poffset + 2] = (unsigned char)bbuf[0];
1294 column++;
1295 }
1296 else if (bpp == 16)
1297 {
1298 unsigned char temp;
1299
1300 stream.Read(&word, 2);
1301 linepos += 2;
1302 temp = (word & rmask) >> rshift;
1303 ptr[poffset] = temp;
1304 temp = (word & gmask) >> gshift;
1305 ptr[poffset + 1] = temp;
1306 temp = (word & bmask) >> gshift;
1307 ptr[poffset + 2] = temp;
1308 column++;
1309 }
1310 else
1311 {
1312 unsigned char temp;
1313
1314 stream.Read(&dword, 4);
1315 linepos += 4;
1316 temp = (dword & rmask) >> rshift;
1317 ptr[poffset] = temp;
1318 temp = (dword & gmask) >> gshift;
1319 ptr[poffset + 1] = temp;
1320 temp = (dword & bmask) >> bshift;
1321 ptr[poffset + 2] = temp;
1322 column++;
1323 }
1324 }
1325 while ((linepos < linesize) && (comp != 1) && (comp != 2))
1326 {
1327 stream.Read(&aByte, 1);
1328 linepos += 1;
1329 if (stream.LastError() != wxStream_NOERROR)
1330 break;
1331 }
1332 }
1333 if (cmap) free(cmap);
1334
1335 image->SetMask( FALSE );
1336
1337 return TRUE;
1338 }
1339 #endif // wxUSE_STREAMS
1340
1341 #ifdef __WXMSW__
1342
1343 wxBitmap wxImage::ConvertToBitmap() const
1344 {
1345 // sizeLimit is the MS upper limit for the DIB size
1346 int sizeLimit = 1024*768*3;
1347
1348 // width and height of the device-dependent bitmap
1349 int width = GetWidth();
1350 int bmpHeight = GetHeight();
1351
1352 // calc the number of bytes per scanline and padding
1353 int bytePerLine = width*3;
1354 int sizeDWORD = sizeof( DWORD );
1355 div_t lineBoundary = div( bytePerLine, sizeDWORD );
1356 int padding = 0;
1357 if( lineBoundary.rem > 0 )
1358 {
1359 padding = sizeDWORD - lineBoundary.rem;
1360 bytePerLine += padding;
1361 }
1362 // calc the number of DIBs and heights of DIBs
1363 int numDIB = 1;
1364 int hRemain = 0;
1365 int height = sizeLimit/bytePerLine;
1366 if( height >= bmpHeight )
1367 height = bmpHeight;
1368 else
1369 {
1370 div_t result = div( bmpHeight, height );
1371 numDIB = result.quot;
1372 hRemain = result.rem;
1373 if( hRemain >0 ) numDIB++;
1374 }
1375
1376 // set bitmap parameters
1377 wxBitmap bitmap;
1378 wxCHECK_MSG( Ok(), bitmap, "invalid image" );
1379 bitmap.SetWidth( width );
1380 bitmap.SetHeight( bmpHeight );
1381 bitmap.SetDepth( wxDisplayDepth() );
1382
1383 // create a DIB header
1384 int headersize = sizeof(BITMAPINFOHEADER);
1385 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
1386 wxCHECK_MSG( lpDIBh, bitmap, "could not allocate memory for DIB header" );
1387 // Fill in the DIB header
1388 lpDIBh->bmiHeader.biSize = headersize;
1389 lpDIBh->bmiHeader.biWidth = (DWORD)width;
1390 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
1391 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
1392 // the general formula for biSizeImage:
1393 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
1394 lpDIBh->bmiHeader.biPlanes = 1;
1395 lpDIBh->bmiHeader.biBitCount = 24;
1396 lpDIBh->bmiHeader.biCompression = BI_RGB;
1397 lpDIBh->bmiHeader.biClrUsed = 0;
1398 // These seem not really needed for our purpose here.
1399 lpDIBh->bmiHeader.biClrImportant = 0;
1400 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
1401 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
1402 // memory for DIB data
1403 unsigned char *lpBits;
1404 lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
1405 if( !lpBits )
1406 {
1407 wxFAIL_MSG( "could not allocate memory for DIB" );
1408 free( lpDIBh );
1409 return bitmap;
1410 }
1411
1412 // create and set the device-dependent bitmap
1413 HDC hdc = ::GetDC(NULL);
1414 HDC memdc = ::CreateCompatibleDC( hdc );
1415 HBITMAP hbitmap;
1416 hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
1417 ::SelectObject( memdc, hbitmap);
1418
1419 // copy image data into DIB data and then into DDB (in a loop)
1420 unsigned char *data = GetData();
1421 int i, j, n;
1422 int origin = 0;
1423 unsigned char *ptdata = data;
1424 unsigned char *ptbits;
1425
1426 for( n=0; n<numDIB; n++ )
1427 {
1428 if( numDIB > 1 && n == numDIB-1 && hRemain > 0 )
1429 {
1430 // redefine height and size of the (possibly) last smaller DIB
1431 // memory is not reallocated
1432 height = hRemain;
1433 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
1434 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
1435 }
1436 ptbits = lpBits;
1437
1438 for( j=0; j<height; j++ )
1439 {
1440 for( i=0; i<width; i++ )
1441 {
1442 *(ptbits++) = *(ptdata+2);
1443 *(ptbits++) = *(ptdata+1);
1444 *(ptbits++) = *(ptdata );
1445 ptdata += 3;
1446 }
1447 for( i=0; i< padding; i++ ) *(ptbits++) = 0;
1448 }
1449 ::StretchDIBits( memdc, 0, origin, width, height,\
1450 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
1451 origin += height;
1452 // if numDIB = 1, lines below can also be used
1453 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
1454 // The above line is equivalent to the following two lines.
1455 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
1456 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
1457 // or the following lines
1458 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
1459 // HDC memdc = ::CreateCompatibleDC( hdc );
1460 // ::SelectObject( memdc, hbitmap);
1461 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
1462 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
1463 // ::SelectObject( memdc, 0 );
1464 // ::DeleteDC( memdc );
1465 }
1466 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
1467
1468 // similarly, created an mono-bitmap for the possible mask
1469 if( HasMask() )
1470 {
1471 hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL );
1472 ::SelectObject( memdc, hbitmap);
1473 if( numDIB == 1 ) height = bmpHeight;
1474 else height = sizeLimit/bytePerLine;
1475 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
1476 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
1477 origin = 0;
1478 unsigned char r = GetMaskRed();
1479 unsigned char g = GetMaskGreen();
1480 unsigned char b = GetMaskBlue();
1481 unsigned char zero = 0, one = 255;
1482 ptdata = data;
1483 for( n=0; n<numDIB; n++ )
1484 {
1485 if( numDIB > 1 && n == numDIB - 1 && hRemain > 0 )
1486 {
1487 // redefine height and size of the (possibly) last smaller DIB
1488 // memory is not reallocated
1489 height = hRemain;
1490 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
1491 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
1492 }
1493 ptbits = lpBits;
1494 for( int j=0; j<height; j++ )
1495 {
1496 for( int i=0; i<width; i++ )
1497 {
1498 if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
1499 {
1500 *(ptbits++) = one;
1501 *(ptbits++) = one;
1502 *(ptbits++) = one;
1503 }
1504 else
1505 {
1506 *(ptbits++) = zero;
1507 *(ptbits++) = zero;
1508 *(ptbits++) = zero;
1509 }
1510 }
1511 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
1512 }
1513 ::StretchDIBits( memdc, 0, origin, width, height,\
1514 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
1515 origin += height;
1516 }
1517 // create a wxMask object
1518 wxMask *mask = new wxMask();
1519 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
1520 bitmap.SetMask( mask );
1521 // It will be deleted when the wxBitmap object is deleted (as of 01/1999)
1522 /* The following can also be used but is slow to run
1523 wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
1524 wxMask *mask = new wxMask( bitmap, colour );
1525 bitmap.SetMask( mask );
1526 */
1527 }
1528
1529 // free allocated resources
1530 ::SelectObject( memdc, 0 );
1531 ::DeleteDC( memdc );
1532 ::ReleaseDC(NULL, hdc);
1533 free(lpDIBh);
1534 free(lpBits);
1535
1536 // check the wxBitmap object
1537 if( bitmap.GetHBITMAP() )
1538 bitmap.SetOk( TRUE );
1539 else
1540 bitmap.SetOk( FALSE );
1541
1542 return bitmap;
1543 }
1544
1545 wxImage::wxImage( const wxBitmap &bitmap )
1546 {
1547 // check the bitmap
1548 if( !bitmap.Ok() )
1549 {
1550 wxFAIL_MSG( "invalid bitmap" );
1551 return;
1552 }
1553
1554 // create an wxImage object
1555 int width = bitmap.GetWidth();
1556 int height = bitmap.GetHeight();
1557 Create( width, height );
1558 unsigned char *data = GetData();
1559 if( !data )
1560 {
1561 wxFAIL_MSG( "could not allocate data for image" );
1562 return;
1563 }
1564
1565 // calc the number of bytes per scanline and padding in the DIB
1566 int bytePerLine = width*3;
1567 int sizeDWORD = sizeof( DWORD );
1568 div_t lineBoundary = div( bytePerLine, sizeDWORD );
1569 int padding = 0;
1570 if( lineBoundary.rem > 0 )
1571 {
1572 padding = sizeDWORD - lineBoundary.rem;
1573 bytePerLine += padding;
1574 }
1575
1576 // create a DIB header
1577 int headersize = sizeof(BITMAPINFOHEADER);
1578 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
1579 if( !lpDIBh )
1580 {
1581 wxFAIL_MSG( "could not allocate data for DIB header" );
1582 free( data );
1583 return;
1584 }
1585 // Fill in the DIB header
1586 lpDIBh->bmiHeader.biSize = headersize;
1587 lpDIBh->bmiHeader.biWidth = width;
1588 lpDIBh->bmiHeader.biHeight = -height;
1589 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
1590 lpDIBh->bmiHeader.biPlanes = 1;
1591 lpDIBh->bmiHeader.biBitCount = 24;
1592 lpDIBh->bmiHeader.biCompression = BI_RGB;
1593 lpDIBh->bmiHeader.biClrUsed = 0;
1594 // These seem not really needed for our purpose here.
1595 lpDIBh->bmiHeader.biClrImportant = 0;
1596 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
1597 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
1598 // memory for DIB data
1599 unsigned char *lpBits;
1600 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
1601 if( !lpBits )
1602 {
1603 wxFAIL_MSG( "could not allocate data for DIB" );
1604 free( data );
1605 free( lpDIBh );
1606 return;
1607 }
1608
1609 // copy data from the device-dependent bitmap to the DIB
1610 HDC hdc = ::GetDC(NULL);
1611 HBITMAP hbitmap;
1612 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
1613 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1614
1615 // copy DIB data into the wxImage object
1616 int i, j;
1617 unsigned char *ptdata = data;
1618 unsigned char *ptbits = lpBits;
1619 for( i=0; i<height; i++ )
1620 {
1621 for( j=0; j<width; j++ )
1622 {
1623 *(ptdata++) = *(ptbits+2);
1624 *(ptdata++) = *(ptbits+1);
1625 *(ptdata++) = *(ptbits );
1626 ptbits += 3;
1627 }
1628 ptbits += padding;
1629 }
1630
1631 // similarly, set data according to the possible mask bitmap
1632 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
1633 {
1634 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
1635 // memory DC created, color set, data copied, and memory DC deleted
1636 HDC memdc = ::CreateCompatibleDC( hdc );
1637 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
1638 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
1639 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1640 ::DeleteDC( memdc );
1641 // background color set to RGB(16,16,16) in consistent with wxGTK
1642 unsigned char r=16, g=16, b=16;
1643 ptdata = data;
1644 ptbits = lpBits;
1645 for( i=0; i<height; i++ )
1646 {
1647 for( j=0; j<width; j++ )
1648 {
1649 if( *ptbits != 0 )
1650 ptdata += 3;
1651 else
1652 {
1653 *(ptdata++) = r;
1654 *(ptdata++) = g;
1655 *(ptdata++) = b;
1656 }
1657 ptbits += 3;
1658 }
1659 ptbits += padding;
1660 }
1661 SetMaskColour( r, g, b );
1662 SetMask( TRUE );
1663 }
1664 else
1665 {
1666 SetMask( FALSE );
1667 }
1668 // free allocated resources
1669 ::ReleaseDC(NULL, hdc);
1670 free(lpDIBh);
1671 free(lpBits);
1672 }
1673
1674 #endif
1675
1676 #ifdef __WXGTK__
1677
1678 #include "gtk/gtk.h"
1679 #include "gdk/gdk.h"
1680 #include "gdk/gdkx.h"
1681
1682 wxBitmap wxImage::ConvertToBitmap() const
1683 {
1684 wxBitmap bitmap;
1685
1686 wxCHECK_MSG( Ok(), bitmap, "invalid image" );
1687
1688 int width = GetWidth();
1689 int height = GetHeight();
1690
1691 bitmap.SetHeight( height );
1692 bitmap.SetWidth( width );
1693
1694 // Create picture
1695
1696 GdkImage *data_image =
1697 gdk_image_new( GDK_IMAGE_FASTEST, gdk_visual_get_system(), width, height );
1698
1699 bitmap.SetPixmap( gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, -1 ) );
1700
1701 // Create mask
1702
1703 GdkImage *mask_image = (GdkImage*) NULL;
1704
1705 if (HasMask())
1706 {
1707 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1708
1709 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1710
1711 wxMask *mask = new wxMask();
1712 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1713
1714 bitmap.SetMask( mask );
1715 }
1716
1717 // Retrieve depth
1718
1719 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
1720 if (visual == NULL) visual = gdk_window_get_visual( (GdkWindow*) &gdk_root_parent );
1721 int bpp = visual->depth;
1722
1723 bitmap.SetDepth( bpp );
1724
1725 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
1726 if (bpp < 8) bpp = 8;
1727
1728 // Render
1729
1730 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1731 byte_order b_o = RGB;
1732
1733 if (bpp >= 24)
1734 {
1735 GdkVisual *visual = gdk_visual_get_system();
1736 if ((visual->red_mask > visual->green_mask) && (visual->green_mask > visual->blue_mask)) b_o = RGB;
1737 else if ((visual->red_mask > visual->blue_mask) && (visual->blue_mask > visual->green_mask)) b_o = RGB;
1738 else if ((visual->blue_mask > visual->red_mask) && (visual->red_mask > visual->green_mask)) b_o = BRG;
1739 else if ((visual->blue_mask > visual->green_mask) && (visual->green_mask > visual->red_mask)) b_o = BGR;
1740 else if ((visual->green_mask > visual->red_mask) && (visual->red_mask > visual->blue_mask)) b_o = GRB;
1741 else if ((visual->green_mask > visual->blue_mask) && (visual->blue_mask > visual->red_mask)) b_o = GBR;
1742 }
1743
1744 int r_mask = GetMaskRed();
1745 int g_mask = GetMaskGreen();
1746 int b_mask = GetMaskBlue();
1747
1748 unsigned char* data = GetData();
1749
1750 int index = 0;
1751 for (int y = 0; y < height; y++)
1752 {
1753 for (int x = 0; x < width; x++)
1754 {
1755 int r = data[index];
1756 index++;
1757 int g = data[index];
1758 index++;
1759 int b = data[index];
1760 index++;
1761
1762 if (HasMask())
1763 {
1764 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1765 gdk_image_put_pixel( mask_image, x, y, 1 );
1766 else
1767 gdk_image_put_pixel( mask_image, x, y, 0 );
1768 }
1769
1770 if (HasMask())
1771 {
1772 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1773 gdk_image_put_pixel( mask_image, x, y, 1 );
1774 else
1775 gdk_image_put_pixel( mask_image, x, y, 0 );
1776 }
1777
1778 switch (bpp)
1779 {
1780 case 8:
1781 {
1782 int pixel = -1;
1783 if (wxTheApp->m_colorCube)
1784 {
1785 pixel = wxTheApp->m_colorCube[ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1786 }
1787 else
1788 {
1789 GdkColormap *cmap = gtk_widget_get_default_colormap();
1790 GdkColor *colors = cmap->colors;
1791 int max = 3 * (65536);
1792
1793 for (int i = 0; i < cmap->size; i++)
1794 {
1795 int rdiff = (r << 8) - colors[i].red;
1796 int gdiff = (g << 8) - colors[i].green;
1797 int bdiff = (b << 8) - colors[i].blue;
1798 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1799 if (sum < max) { pixel = i; max = sum; }
1800 }
1801 }
1802
1803 gdk_image_put_pixel( data_image, x, y, pixel );
1804
1805 break;
1806 }
1807 case 15:
1808 {
1809 guint32 pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1810 gdk_image_put_pixel( data_image, x, y, pixel );
1811 break;
1812 }
1813 case 16:
1814 {
1815 guint32 pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1816 gdk_image_put_pixel( data_image, x, y, pixel );
1817 break;
1818 }
1819 case 32:
1820 case 24:
1821 {
1822 guint32 pixel = 0;
1823 switch (b_o)
1824 {
1825 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1826 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1827 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1828 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1829 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1830 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1831 }
1832 gdk_image_put_pixel( data_image, x, y, pixel );
1833 }
1834 default: break;
1835 }
1836 } // for
1837 } // for
1838
1839 // Blit picture
1840
1841 GdkGC *data_gc = gdk_gc_new( bitmap.GetPixmap() );
1842
1843 gdk_draw_image( bitmap.GetPixmap(), data_gc, data_image, 0, 0, 0, 0, width, height );
1844
1845 gdk_image_destroy( data_image );
1846 gdk_gc_unref( data_gc );
1847
1848 // Blit mask
1849
1850 if (HasMask())
1851 {
1852 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
1853
1854 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
1855
1856 gdk_image_destroy( mask_image );
1857 gdk_gc_unref( mask_gc );
1858 }
1859
1860 return bitmap;
1861 }
1862
1863 wxImage::wxImage( const wxBitmap &bitmap )
1864 {
1865 wxCHECK_RET( bitmap.Ok(), "invalid bitmap" );
1866
1867 GdkImage *gdk_image = gdk_image_get( bitmap.GetPixmap(),
1868 0, 0,
1869 bitmap.GetWidth(), bitmap.GetHeight() );
1870
1871 wxCHECK_RET( gdk_image, "couldn't create image" );
1872
1873 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1874 char unsigned *data = GetData();
1875
1876 if (!data)
1877 {
1878 gdk_image_destroy( gdk_image );
1879 wxFAIL_MSG( "couldn't create image" );
1880 return;
1881 }
1882
1883 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1884 if (bitmap.GetMask())
1885 {
1886 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1887 0, 0,
1888 bitmap.GetWidth(), bitmap.GetHeight() );
1889
1890 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1891 }
1892
1893 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
1894 if (visual == NULL) visual = gdk_window_get_visual( (GdkWindow*) &gdk_root_parent );
1895 int bpp = visual->depth;
1896 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
1897
1898 GdkColormap *cmap = gtk_widget_get_default_colormap();
1899
1900 long pos = 0;
1901 for (int j = 0; j < bitmap.GetHeight(); j++)
1902 {
1903 for (int i = 0; i < bitmap.GetWidth(); i++)
1904 {
1905 int pixel = gdk_image_get_pixel( gdk_image, i, j );
1906 if (bpp <= 8)
1907 {
1908 data[pos] = cmap->colors[pixel].red >> 8;
1909 data[pos+1] = cmap->colors[pixel].green >> 8;
1910 data[pos+2] = cmap->colors[pixel].blue >> 8;
1911 } else if (bpp == 15)
1912 {
1913 data[pos] = (pixel >> 7) & 0xf8;
1914 data[pos+1] = (pixel >> 2) & 0xf8;
1915 data[pos+2] = (pixel << 3) & 0xf8;
1916 } else if (bpp == 16)
1917 {
1918 data[pos] = (pixel >> 8) & 0xf8;
1919 data[pos+1] = (pixel >> 3) & 0xfc;
1920 data[pos+2] = (pixel << 3) & 0xf8;
1921 } else
1922 {
1923 data[pos] = (pixel >> 16) & 0xff;
1924 data[pos+1] = (pixel >> 8) & 0xff;
1925 data[pos+2] = pixel & 0xff;
1926 }
1927
1928 if (gdk_image_mask)
1929 {
1930 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1931 if (mask_pixel == 0)
1932 {
1933 data[pos] = 16;
1934 data[pos+1] = 16;
1935 data[pos+2] = 16;
1936 }
1937 }
1938
1939 pos += 3;
1940 }
1941 }
1942
1943 gdk_image_destroy( gdk_image );
1944 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1945 }
1946
1947 #endif
1948
1949 #ifdef __WXMOTIF__
1950
1951 #include <Xm/Xm.h>
1952 #include "wx/utils.h"
1953 #include <math.h>
1954
1955 wxBitmap wxImage::ConvertToBitmap() const
1956 {
1957 wxBitmap bitmap;
1958
1959 wxCHECK_MSG( Ok(), bitmap, "invalid image" );
1960
1961 int width = GetWidth();
1962 int height = GetHeight();
1963
1964 bitmap.SetHeight( height );
1965 bitmap.SetWidth( width );
1966
1967 Display *dpy = (Display*) wxGetDisplay();
1968 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1969 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1970
1971 // Create image
1972
1973 XImage *data_image = XCreateImage( dpy, vis, bpp, ZPixmap, 0, 0, width, height, 32, 0 );
1974 data_image->data = new char[ data_image->bytes_per_line * data_image->height ];
1975
1976 bitmap.Create( width, height, bpp );
1977
1978 /*
1979 // Create mask
1980
1981 GdkImage *mask_image = (GdkImage*) NULL;
1982
1983 if (HasMask())
1984 {
1985 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1986
1987 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1988
1989 wxMask *mask = new wxMask();
1990 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1991
1992 bitmap.SetMask( mask );
1993 }
1994 */
1995
1996 // Retrieve depth info
1997
1998 XVisualInfo vinfo_template;
1999 XVisualInfo *vi;
2000
2001 vinfo_template.visual = vis;
2002 vinfo_template.visualid = XVisualIDFromVisual( vis );
2003 vinfo_template.depth = bpp;
2004 int nitem = 0;
2005
2006 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
2007
2008 if (!vi)
2009 {
2010 printf("no visual.\n" );
2011 return wxNullBitmap;
2012 }
2013
2014 XFree( vi );
2015
2016 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
2017 if (bpp < 8) bpp = 8;
2018
2019 // Render
2020
2021 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
2022 byte_order b_o = RGB;
2023
2024 if (bpp >= 24)
2025 {
2026 if ((vi->red_mask > vi->green_mask) && (vi->green_mask > vi->blue_mask)) b_o = RGB;
2027 else if ((vi->red_mask > vi->blue_mask) && (vi->blue_mask > vi->green_mask)) b_o = RGB;
2028 else if ((vi->blue_mask > vi->red_mask) && (vi->red_mask > vi->green_mask)) b_o = BRG;
2029 else if ((vi->blue_mask > vi->green_mask) && (vi->green_mask > vi->red_mask)) b_o = BGR;
2030 else if ((vi->green_mask > vi->red_mask) && (vi->red_mask > vi->blue_mask)) b_o = GRB;
2031 else if ((vi->green_mask > vi->blue_mask) && (vi->blue_mask > vi->red_mask)) b_o = GBR;
2032 }
2033
2034 /*
2035 int r_mask = GetMaskRed();
2036 int g_mask = GetMaskGreen();
2037 int b_mask = GetMaskBlue();
2038 */
2039
2040 XColor colors[256];
2041 if (bpp == 8)
2042 {
2043 Colormap cmap = (Colormap) wxTheApp->GetMainColormap( dpy );
2044
2045 for (int i = 0; i < 256; i++) colors[i].pixel = i;
2046 XQueryColors( dpy, cmap, colors, 256 );
2047 }
2048
2049 unsigned char* data = GetData();
2050
2051 int index = 0;
2052 for (int y = 0; y < height; y++)
2053 {
2054 for (int x = 0; x < width; x++)
2055 {
2056 int r = data[index];
2057 index++;
2058 int g = data[index];
2059 index++;
2060 int b = data[index];
2061 index++;
2062
2063 /*
2064 if (HasMask())
2065 {
2066 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
2067 gdk_image_put_pixel( mask_image, x, y, 1 );
2068 else
2069 gdk_image_put_pixel( mask_image, x, y, 0 );
2070 }
2071 */
2072
2073 switch (bpp)
2074 {
2075 case 8:
2076 {
2077 int pixel = -1;
2078 /*
2079 if (wxTheApp->m_colorCube)
2080 {
2081 pixel = wxTheApp->m_colorCube
2082 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
2083 }
2084 else
2085 {
2086 */
2087 int max = 3 * (65536);
2088 for (int i = 0; i < 256; i++)
2089 {
2090 int rdiff = (r << 8) - colors[i].red;
2091 int gdiff = (g << 8) - colors[i].green;
2092 int bdiff = (b << 8) - colors[i].blue;
2093 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
2094 if (sum < max) { pixel = i; max = sum; }
2095 }
2096 /*
2097 }
2098 */
2099 XPutPixel( data_image, x, y, pixel );
2100 break;
2101 }
2102 case 15:
2103 {
2104 int pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
2105 XPutPixel( data_image, x, y, pixel );
2106 break;
2107 }
2108 case 16:
2109 {
2110 int pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
2111 XPutPixel( data_image, x, y, pixel );
2112 break;
2113 }
2114 case 32:
2115 case 24:
2116 {
2117 int pixel = 0;
2118 switch (b_o)
2119 {
2120 case RGB: pixel = (r << 16) | (g << 8) | b; break;
2121 case RBG: pixel = (r << 16) | (b << 8) | g; break;
2122 case BRG: pixel = (b << 16) | (r << 8) | g; break;
2123 case BGR: pixel = (b << 16) | (g << 8) | r; break;
2124 case GRB: pixel = (g << 16) | (r << 8) | b; break;
2125 case GBR: pixel = (g << 16) | (b << 8) | r; break;
2126 }
2127 XPutPixel( data_image, x, y, pixel );
2128 }
2129 default: break;
2130 }
2131 } // for
2132 } // for
2133
2134 // Blit picture
2135
2136 XGCValues gcvalues;
2137 gcvalues.foreground = BlackPixel( dpy, DefaultScreen( dpy ) );
2138 GC gc = XCreateGC( dpy, RootWindow ( dpy, DefaultScreen(dpy) ), GCForeground, &gcvalues );
2139 XPutImage( dpy, (Drawable)bitmap.GetPixmap(), gc, data_image, 0, 0, 0, 0, width, height );
2140
2141 XDestroyImage( data_image );
2142 XFreeGC( dpy, gc );
2143
2144 /*
2145 // Blit mask
2146
2147 if (HasMask())
2148 {
2149 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
2150
2151 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
2152
2153 gdk_image_destroy( mask_image );
2154 gdk_gc_unref( mask_gc );
2155 }
2156 */
2157
2158 return bitmap;
2159 }
2160
2161 wxImage::wxImage( const wxBitmap &bitmap )
2162 {
2163 wxCHECK_RET( bitmap.Ok(), "invalid bitmap" );
2164
2165 Display *dpy = (Display*) wxGetDisplay();
2166 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
2167 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
2168
2169 XImage *ximage = XGetImage( dpy,
2170 (Drawable)bitmap.GetPixmap(),
2171 0, 0,
2172 bitmap.GetWidth(), bitmap.GetHeight(),
2173 AllPlanes, ZPixmap );
2174
2175 wxCHECK_RET( ximage, "couldn't create image" );
2176
2177 Create( bitmap.GetWidth(), bitmap.GetHeight() );
2178 char unsigned *data = GetData();
2179
2180 if (!data)
2181 {
2182 XDestroyImage( ximage );
2183 wxFAIL_MSG( "couldn't create image" );
2184 return;
2185 }
2186
2187 /*
2188 GdkImage *gdk_image_mask = (GdkImage*) NULL;
2189 if (bitmap.GetMask())
2190 {
2191 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
2192 0, 0,
2193 bitmap.GetWidth(), bitmap.GetHeight() );
2194
2195 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
2196 }
2197 */
2198
2199 // Retrieve depth info
2200
2201 XVisualInfo vinfo_template;
2202 XVisualInfo *vi;
2203
2204 vinfo_template.visual = vis;
2205 vinfo_template.visualid = XVisualIDFromVisual( vis );
2206 vinfo_template.depth = bpp;
2207 int nitem = 0;
2208
2209 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
2210
2211 if (!vi)
2212 {
2213 printf("no visual.\n" );
2214 return;
2215 }
2216
2217 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
2218
2219 XFree( vi );
2220
2221 XColor colors[256];
2222 if (bpp == 8)
2223 {
2224 Colormap cmap = (Colormap)wxTheApp->GetMainColormap( dpy );
2225
2226 for (int i = 0; i < 256; i++) colors[i].pixel = i;
2227 XQueryColors( dpy, cmap, colors, 256 );
2228 }
2229
2230 long pos = 0;
2231 for (int j = 0; j < bitmap.GetHeight(); j++)
2232 {
2233 for (int i = 0; i < bitmap.GetWidth(); i++)
2234 {
2235 int pixel = XGetPixel( ximage, i, j );
2236 if (bpp <= 8)
2237 {
2238 data[pos] = colors[pixel].red >> 8;
2239 data[pos+1] = colors[pixel].green >> 8;
2240 data[pos+2] = colors[pixel].blue >> 8;
2241 } else if (bpp == 15)
2242 {
2243 data[pos] = (pixel >> 7) & 0xf8;
2244 data[pos+1] = (pixel >> 2) & 0xf8;
2245 data[pos+2] = (pixel << 3) & 0xf8;
2246 } else if (bpp == 16)
2247 {
2248 data[pos] = (pixel >> 8) & 0xf8;
2249 data[pos+1] = (pixel >> 3) & 0xfc;
2250 data[pos+2] = (pixel << 3) & 0xf8;
2251 } else
2252 {
2253 data[pos] = (pixel >> 16) & 0xff;
2254 data[pos+1] = (pixel >> 8) & 0xff;
2255 data[pos+2] = pixel & 0xff;
2256 }
2257
2258 /*
2259 if (gdk_image_mask)
2260 {
2261 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
2262 if (mask_pixel == 0)
2263 {
2264 data[pos] = 16;
2265 data[pos+1] = 16;
2266 data[pos+2] = 16;
2267 }
2268 }
2269 */
2270
2271 pos += 3;
2272 }
2273 }
2274
2275 XDestroyImage( ximage );
2276 /*
2277 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
2278 */
2279 }
2280 #endif