]> git.saurik.com Git - wxWidgets.git/blob - src/common/image.cpp
storable objects use _() and wxLogXXX instead of message boxes
[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 #ifdef wxUSE_LIBPNG
26 #include "../png/png.h"
27 #endif
28 #include "wx/filefn.h"
29
30 #ifdef __WXMSW__
31 #include <windows.h>
32 #endif
33
34 //-----------------------------------------------------------------------------
35 // wxImage
36 //-----------------------------------------------------------------------------
37
38 class wxImageRefData: public wxObjectRefData
39 {
40
41 public:
42 wxImageRefData(void);
43 ~wxImageRefData(void);
44
45 int m_width;
46 int m_height;
47 unsigned char *m_data;
48 bool m_hasMask;
49 unsigned char m_maskRed,m_maskGreen,m_maskBlue;
50 bool m_ok;
51 };
52
53 wxImageRefData::wxImageRefData(void)
54 {
55 m_width = 0;
56 m_height = 0;
57 m_data = (unsigned char*) NULL;
58 m_ok = FALSE;
59 m_maskRed = 0;
60 m_maskGreen = 0;
61 m_maskBlue = 0;
62 m_hasMask = FALSE;
63 }
64
65 wxImageRefData::~wxImageRefData(void)
66 {
67 if (m_data) free( m_data );
68 }
69
70 wxList wxImage::sm_handlers;
71
72 //-----------------------------------------------------------------------------
73
74 #define M_IMGDATA ((wxImageRefData *)m_refData)
75
76 #if !USE_SHARED_LIBRARIES
77 IMPLEMENT_DYNAMIC_CLASS(wxImage, wxObject)
78 #endif
79
80 wxImage::wxImage()
81 {
82 }
83
84 wxImage::wxImage( int width, int height )
85 {
86 Create( width, height );
87 }
88
89 wxImage::wxImage( const wxString& name, long type )
90 {
91 LoadFile( name, type );
92 }
93
94 wxImage::wxImage( const wxImage& image )
95 {
96 Ref(image);
97 }
98
99 wxImage::wxImage( const wxImage* image )
100 {
101 if (image) Ref(*image);
102 }
103
104 void wxImage::Create( int width, int height )
105 {
106 m_refData = new wxImageRefData();
107
108 M_IMGDATA->m_data = (unsigned char *) malloc( width*height*3 );
109 if (M_IMGDATA->m_data)
110 {
111 for (int l = 0; l < width*height*3; l++) M_IMGDATA->m_data[l] = 0;
112
113 M_IMGDATA->m_width = width;
114 M_IMGDATA->m_height = height;
115 M_IMGDATA->m_ok = TRUE;
116 }
117 else
118 {
119 UnRef();
120 }
121 }
122
123 void wxImage::Destroy()
124 {
125 UnRef();
126 }
127
128 wxImage wxImage::Scale( int width, int height )
129 {
130 wxImage image;
131
132 wxCHECK_MSG( Ok(), image, "invlaid image" );
133
134 wxCHECK_MSG( (width > 0) && (height > 0), image, "invalid image size" );
135
136 image.Create( width, height );
137
138 char unsigned *data = image.GetData();
139
140 wxCHECK_MSG( data, image, "unable to create image" );
141
142 if (M_IMGDATA->m_hasMask)
143 image.SetMaskColour( M_IMGDATA->m_maskRed, M_IMGDATA->m_maskGreen, M_IMGDATA->m_maskBlue );
144
145 double xscale = (double)width / (double)M_IMGDATA->m_width;
146 double yscale = (double)height / (double)M_IMGDATA->m_height;
147
148 for (int j = 0; j < height; j++)
149 {
150 for (int i = 0; i < width; i++)
151 {
152 int new_pos = 3*(j*width + i);
153 int old_pos = 3*((long)(j/yscale)*M_IMGDATA->m_width + (long)(i/xscale));
154 data[ new_pos ] = M_IMGDATA->m_data[ old_pos ];
155 data[ new_pos+1 ] = M_IMGDATA->m_data[ old_pos+1 ];
156 data[ new_pos+2 ] = M_IMGDATA->m_data[ old_pos+2 ];
157 }
158 }
159
160 return image;
161 }
162
163 void wxImage::SetRGB( int x, int y, unsigned char r, unsigned char g, unsigned char b )
164 {
165 wxCHECK_RET( Ok(), "invalid image" );
166
167 int w = M_IMGDATA->m_width;
168 int h = M_IMGDATA->m_height;
169
170 wxCHECK_RET( (x>=0) && (y>=0) && (x<w) && (y<h), "invalid image index" );
171
172 long pos = (y * w + x) * 3;
173
174 M_IMGDATA->m_data[ pos ] = r;
175 M_IMGDATA->m_data[ pos+1 ] = g;
176 M_IMGDATA->m_data[ pos+2 ] = b;
177 }
178
179 unsigned char wxImage::GetRed( int x, int y )
180 {
181 wxCHECK_MSG( Ok(), 0, "invalid image" );
182
183 int w = M_IMGDATA->m_width;
184 int h = M_IMGDATA->m_height;
185
186 wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, "invalid image index" );
187
188 long pos = (y * w + x) * 3;
189
190 return M_IMGDATA->m_data[pos];
191 }
192
193 unsigned char wxImage::GetGreen( int x, int y )
194 {
195 wxCHECK_MSG( Ok(), 0, "invalid image" );
196
197 int w = M_IMGDATA->m_width;
198 int h = M_IMGDATA->m_height;
199
200 wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, "invalid image index" );
201
202 long pos = (y * w + x) * 3;
203
204 return M_IMGDATA->m_data[pos+1];
205 }
206
207 unsigned char wxImage::GetBlue( int x, int y )
208 {
209 wxCHECK_MSG( Ok(), 0, "invalid image" );
210
211 int w = M_IMGDATA->m_width;
212 int h = M_IMGDATA->m_height;
213
214 wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, "invalid image index" );
215
216 long pos = (y * w + x) * 3;
217
218 return M_IMGDATA->m_data[pos+2];
219 }
220
221 bool wxImage::Ok() const
222 {
223 return (M_IMGDATA && M_IMGDATA->m_ok);
224 }
225
226 char unsigned *wxImage::GetData() const
227 {
228 wxCHECK_MSG( Ok(), (char unsigned *)NULL, "invalid image" );
229
230 return M_IMGDATA->m_data;
231 }
232
233 void wxImage::SetData( char unsigned *WXUNUSED(data) )
234 {
235 wxCHECK_RET( Ok(), "invalid image" );
236 }
237
238 void wxImage::SetMaskColour( unsigned char r, unsigned char g, unsigned char b )
239 {
240 wxCHECK_RET( Ok(), "invalid image" );
241
242 M_IMGDATA->m_maskRed = r;
243 M_IMGDATA->m_maskGreen = g;
244 M_IMGDATA->m_maskBlue = b;
245 M_IMGDATA->m_hasMask = TRUE;
246 }
247
248 unsigned char wxImage::GetMaskRed() const
249 {
250 wxCHECK_MSG( Ok(), 0, "invalid image" );
251
252 return M_IMGDATA->m_maskRed;
253 }
254
255 unsigned char wxImage::GetMaskGreen() const
256 {
257 wxCHECK_MSG( Ok(), 0, "invalid image" );
258
259 return M_IMGDATA->m_maskGreen;
260 }
261
262 unsigned char wxImage::GetMaskBlue() const
263 {
264 wxCHECK_MSG( Ok(), 0, "invalid image" );
265
266 return M_IMGDATA->m_maskBlue;
267 }
268
269 void wxImage::SetMask( bool mask )
270 {
271 wxCHECK_RET( Ok(), "invalid image" );
272
273 M_IMGDATA->m_hasMask = mask;
274 }
275
276 bool wxImage::HasMask() const
277 {
278 wxCHECK_MSG( Ok(), FALSE, "invalid image" );
279
280 return M_IMGDATA->m_hasMask;
281 }
282
283 int wxImage::GetWidth() const
284 {
285 wxCHECK_MSG( Ok(), 0, "invalid image" );
286
287 return M_IMGDATA->m_width;
288 }
289
290 int wxImage::GetHeight() const
291 {
292 wxCHECK_MSG( Ok(), 0, "invalid image" );
293
294 return M_IMGDATA->m_height;
295 }
296
297 bool wxImage::LoadFile( const wxString& filename, long type )
298 {
299 UnRef();
300
301 if (!wxFileExists(filename))
302 {
303 wxLogWarning( "Image file does not exist." );
304
305 return FALSE;
306 }
307
308 m_refData = new wxImageRefData;
309
310 wxImageHandler *handler = FindHandler(type);
311
312 if (handler == NULL)
313 {
314 wxLogWarning( "No image handler for type %d defined.", type );
315
316 return FALSE;
317 }
318
319 return handler->LoadFile( this, filename );
320 }
321
322 bool wxImage::SaveFile( const wxString& filename, int type )
323 {
324 wxCHECK_MSG( Ok(), FALSE, "invalid image" );
325
326 wxImageHandler *handler = FindHandler(type);
327
328 if (handler == NULL)
329 {
330 wxLogWarning( "No image handler for type %d defined.", type );
331
332 return FALSE;
333 }
334
335 return handler->SaveFile( this, filename );
336 }
337
338 void wxImage::AddHandler( wxImageHandler *handler )
339 {
340 sm_handlers.Append( handler );
341 }
342
343 void wxImage::InsertHandler( wxImageHandler *handler )
344 {
345 sm_handlers.Insert( handler );
346 }
347
348 bool wxImage::RemoveHandler( const wxString& name )
349 {
350 wxImageHandler *handler = FindHandler(name);
351 if (handler)
352 {
353 sm_handlers.DeleteObject(handler);
354 return TRUE;
355 }
356 else
357 return FALSE;
358 }
359
360 wxImageHandler *wxImage::FindHandler( const wxString& name )
361 {
362 wxNode *node = sm_handlers.First();
363 while (node)
364 {
365 wxImageHandler *handler = (wxImageHandler*)node->Data();
366 if (handler->GetName() == name) return handler;
367 node = node->Next();
368 }
369 return (wxImageHandler *)NULL;
370 }
371
372 wxImageHandler *wxImage::FindHandler( const wxString& extension, long bitmapType )
373 {
374 wxNode *node = sm_handlers.First();
375 while (node)
376 {
377 wxImageHandler *handler = (wxImageHandler*)node->Data();
378 if ( handler->GetExtension() == extension &&
379 (bitmapType == -1 || handler->GetType() == bitmapType) )
380 return handler;
381 node = node->Next();
382 }
383 return (wxImageHandler*)NULL;
384 }
385
386 wxImageHandler *wxImage::FindHandler( long bitmapType )
387 {
388 wxNode *node = sm_handlers.First();
389 while (node)
390 {
391 wxImageHandler *handler = (wxImageHandler *)node->Data();
392 if (handler->GetType() == bitmapType) return handler;
393 node = node->Next();
394 }
395 return NULL;
396 }
397
398 void wxImage::InitStandardHandlers()
399 {
400 AddHandler( new wxBMPHandler );
401 #ifdef wxUSE_LIBPNG
402 AddHandler( new wxPNGHandler );
403 #endif
404 }
405
406 void wxImage::CleanUpHandlers()
407 {
408 wxNode *node = sm_handlers.First();
409 while (node)
410 {
411 wxImageHandler *handler = (wxImageHandler *)node->Data();
412 wxNode *next = node->Next();
413 delete handler;
414 delete node;
415 node = next;
416 }
417 }
418
419 //-----------------------------------------------------------------------------
420 // wxImageHandler
421 //-----------------------------------------------------------------------------
422
423 #if !USE_SHARED_LIBRARIES
424 IMPLEMENT_DYNAMIC_CLASS(wxImageHandler,wxObject)
425 #endif
426
427 bool wxImageHandler::LoadFile( wxImage *WXUNUSED(image), const wxString& WXUNUSED(name) )
428 {
429 return FALSE;
430 }
431
432 bool wxImageHandler::SaveFile( wxImage *WXUNUSED(image), const wxString& WXUNUSED(name) )
433 {
434 return FALSE;
435 }
436
437 //-----------------------------------------------------------------------------
438 // wxPNGHandler
439 //-----------------------------------------------------------------------------
440
441 #ifdef wxUSE_LIBPNG
442
443 #if !USE_SHARED_LIBRARIES
444 IMPLEMENT_DYNAMIC_CLASS(wxPNGHandler,wxImageHandler)
445 #endif
446
447 bool wxPNGHandler::LoadFile( wxImage *image, const wxString& name )
448 {
449 FILE *f;
450 png_structp png_ptr;
451 png_infop info_ptr;
452 unsigned char *ptr, **lines, *ptr2;
453 int transp,bit_depth,color_type,interlace_type;
454 png_uint_32 width, height;
455 unsigned int i;
456
457 image->Destroy();
458
459 transp = 0;
460 png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
461 if (!png_ptr) return FALSE;
462
463 info_ptr = png_create_info_struct( png_ptr );
464 if (!info_ptr)
465 {
466 png_destroy_read_struct( &png_ptr, NULL, NULL );
467 return FALSE;
468 }
469
470 if (setjmp(png_ptr->jmpbuf))
471 {
472 png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
473 return FALSE;
474 }
475
476 if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
477 {
478 png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
479 return FALSE;
480 }
481
482 f = fopen( name, "rb" );
483 png_init_io( png_ptr, f );
484
485 png_read_info( png_ptr, info_ptr );
486 png_get_IHDR( png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL );
487
488 if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_expand( png_ptr );
489
490 png_set_strip_16( png_ptr );
491 png_set_packing( png_ptr );
492 if (png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand( png_ptr );
493 png_set_filler( png_ptr, 0xff, PNG_FILLER_AFTER );
494
495 image->Create( width, height );
496
497 if (!image->Ok())
498 {
499 png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
500 return FALSE;
501 }
502
503 lines = (unsigned char **)malloc( height * sizeof(unsigned char *) );
504 if (lines == NULL)
505 {
506 image->Destroy();
507 png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
508 return FALSE;
509 }
510
511 for (i = 0; i < height; i++)
512 {
513 if ((lines[i] = (unsigned char *)malloc(width * (sizeof(unsigned char) * 4))) == NULL)
514 {
515 image->Destroy();
516 for (unsigned int n = 0; n < i; n++) free( lines[n] );
517 free( lines );
518 png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
519 return FALSE;
520 }
521 }
522
523 png_read_image( png_ptr, lines );
524 png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
525 ptr = image->GetData();
526 if ((color_type == PNG_COLOR_TYPE_GRAY) ||
527 (color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
528 {
529 for (unsigned int y = 0; y < height; y++)
530 {
531 ptr2 = lines[y];
532 for (unsigned int x = 0; x < width; x++)
533 {
534 unsigned char r = *ptr2++;
535 unsigned char a = *ptr2++;
536 if (a < 128)
537 {
538 *ptr++ = 255;
539 *ptr++ = 0;
540 *ptr++ = 255;
541 transp = 1;
542 }
543 else
544 {
545 *ptr++ = r;
546 *ptr++ = r;
547 *ptr++ = r;
548 }
549 }
550 }
551 }
552 else
553 {
554 for (unsigned int y = 0; y < height; y++)
555 {
556 ptr2 = lines[y];
557 for (unsigned int x = 0; x < width; x++)
558 {
559 unsigned char r = *ptr2++;
560 unsigned char g = *ptr2++;
561 unsigned char b = *ptr2++;
562 unsigned char a = *ptr2++;
563 if (a < 128)
564 {
565 *ptr++ = 255;
566 *ptr++ = 0;
567 *ptr++ = 255;
568 transp = 1;
569 }
570 else
571 {
572 if ((r == 255) && (g == 0) && (b == 255)) r = 254;
573 *ptr++ = r;
574 *ptr++ = g;
575 *ptr++ = b;
576 }
577 }
578 }
579 }
580 for (i = 0; i < height; i++) free( lines[i] );
581 free( lines );
582 if (transp)
583 image->SetMaskColour( 255, 0, 255 );
584 else
585 image->SetMask( FALSE );
586
587 return TRUE;
588 }
589
590
591 bool wxPNGHandler::SaveFile( wxImage *image, const wxString& name )
592 {
593 FILE *f = fopen( name, "wb" );
594 if (f)
595 {
596 png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
597 if (!png_ptr)
598 {
599 fclose( f );
600 return FALSE;
601 }
602
603 png_infop info_ptr = png_create_info_struct(png_ptr);
604 if (info_ptr == NULL)
605 {
606 fclose(f);
607 png_destroy_write_struct( &png_ptr, (png_infopp)NULL );
608 return FALSE;
609 }
610
611 if (setjmp(png_ptr->jmpbuf))
612 {
613 fclose( f );
614 png_destroy_write_struct( &png_ptr, (png_infopp)NULL );
615 return FALSE;
616 }
617
618 png_init_io( png_ptr, f );
619 png_set_IHDR( png_ptr, info_ptr, image->GetWidth(), image->GetHeight(), 8,
620 PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
621 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
622
623 png_color_8 sig_bit;
624 sig_bit.red = 8;
625 sig_bit.green = 8;
626 sig_bit.blue = 8;
627 sig_bit.alpha = 8;
628 png_set_sBIT( png_ptr, info_ptr, &sig_bit );
629 png_write_info( png_ptr, info_ptr );
630 png_set_shift( png_ptr, &sig_bit );
631 png_set_packing( png_ptr );
632
633 unsigned char *data = (unsigned char *)malloc( image->GetWidth()*4 );
634 if (!data)
635 {
636 fclose( f );
637 png_destroy_write_struct( &png_ptr, (png_infopp)NULL );
638 return FALSE;
639 }
640
641 for (int y = 0; y < image->GetHeight(); y++)
642 {
643 unsigned char *ptr = image->GetData() + (y * image->GetWidth() * 3);
644 for (int x = 0; x < image->GetWidth(); x++)
645 {
646 data[(x << 2) + 0] = *ptr++;
647 data[(x << 2) + 1] = *ptr++;
648 data[(x << 2) + 2] = *ptr++;
649 if ((data[(x << 2) + 0] == image->GetMaskRed()) &&
650 (data[(x << 2) + 1] == image->GetMaskGreen()) &&
651 (data[(x << 2) + 2] == image->GetMaskBlue()))
652 data[(x << 2) + 3] = 0;
653 else
654 data[(x << 2) + 3] = 255;
655 }
656 png_bytep row_ptr = data;
657 png_write_rows( png_ptr, &row_ptr, 1 );
658 }
659 free(data);
660 png_write_end( png_ptr, info_ptr );
661 png_destroy_write_struct( &png_ptr, (png_infopp)NULL );
662
663 fclose(f);
664 }
665 return TRUE;
666 }
667
668 #endif
669
670 // wxUSE_LIBPNG
671
672 //-----------------------------------------------------------------------------
673 // wxBMPHandler
674 //-----------------------------------------------------------------------------
675
676 #if !USE_SHARED_LIBRARIES
677 IMPLEMENT_DYNAMIC_CLASS(wxBMPHandler,wxImageHandler)
678 #endif
679
680 bool wxBMPHandler::LoadFile( wxImage *image, const wxString& name )
681 {
682 FILE *file;
683 unsigned char *data, *ptr;
684 int done, i, bpp, planes, comp, ncolors, line, column,
685 linesize, linepos, rshift = 0, gshift = 0, bshift = 0;
686 unsigned char aByte;
687 short int word;
688 long int dbuf[4], dword, rmask = 0, gmask = 0, bmask = 0, offset,
689 size;
690 signed char bbuf[4];
691 struct _cmap
692 {
693 unsigned char r, g, b;
694 }
695 *cmap = NULL;
696 #ifndef BI_RGB
697 #define BI_RGB 0
698 #define BI_RLE8 1
699 #define BI_RLE4 2
700 #endif
701
702 #ifndef BI_BITFIELDS
703 #define BI_BITFIELDS 3
704 #endif
705
706 image->Destroy();
707
708 file = fopen(name, "r");
709 if (!file)
710 return NULL;
711
712 done = 0;
713 /*
714 * Reading the bmp header
715 */
716
717 fread(&bbuf, 1, 2, file);
718
719 fread(dbuf, 4, 4, file);
720
721 size = dbuf[0];
722 offset = dbuf[2];
723
724 fread(dbuf, 4, 2, file);
725 int width = (int)dbuf[0];
726 int height = (int)dbuf[1];
727 if (width > 32767)
728 {
729 wxLogError( "Image width > 32767 pixels for file\n" );
730 fclose(file);
731 return FALSE;
732 }
733 if (height > 32767)
734 {
735 wxLogError( "Image height > 32767 pixels for file\n" );
736 fclose(file);
737 return FALSE;
738 }
739 fread(&word, 2, 1, file);
740 planes = (int)word;
741 fread(&word, 2, 1, file);
742 bpp = (int)word;
743 if (bpp != 1 && bpp != 4 && bpp != 8 && bpp && 16 && bpp != 24 && bpp != 32)
744 {
745 wxLogError( "unknown bitdepth in file\n" );
746 fclose(file);
747 return FALSE;
748 }
749 fread(dbuf, 4, 4, file);
750 comp = (int)dbuf[0];
751 if (comp != BI_RGB && comp != BI_RLE4 && comp != BI_RLE8 && comp != BI_BITFIELDS)
752 {
753 wxLogError( "unknown encoding in Windows BMP file\n" );
754 fclose(file);
755 return FALSE;
756 }
757 fread(dbuf, 4, 2, file);
758 ncolors = (int)dbuf[0];
759 if (ncolors == 0)
760 ncolors = 1 << bpp;
761 /* some more sanity checks */
762 if (((comp == BI_RLE4) && (bpp != 4)) || ((comp == BI_RLE8) && (bpp != 8)) || ((comp == BI_BITFIELDS) && (bpp != 16 && bpp != 32)))
763 {
764 wxLogError( "encoding of BMP doesn't match bitdepth\n" );
765 fclose(file);
766 return FALSE;
767 }
768 if (bpp < 16)
769 {
770 cmap = (struct _cmap *)malloc(sizeof(struct _cmap) * ncolors);
771
772 if (!cmap)
773 {
774 wxLogError( "Cannot allocate RAM for color map in BMP file\n" );
775 fclose(file);
776 return FALSE;
777 }
778 }
779 else
780 cmap = NULL;
781
782 image->Create( width, height );
783 ptr = image->GetData();
784 if (!ptr)
785 {
786 wxLogError( "Cannot allocate RAM for RGB data in file\n" );
787 fclose(file);
788 if (cmap)
789 free(cmap);
790 return FALSE;
791 }
792
793 /*
794 * Reading the palette, if it exists.
795 */
796 if (bpp < 16 && ncolors != 0)
797 {
798 for (i = 0; i < ncolors; i++)
799 {
800 fread(bbuf, 1, 4, file);
801 cmap[i].b = bbuf[0];
802 cmap[i].g = bbuf[1];
803 cmap[i].r = bbuf[2];
804 }
805 }
806 else if (bpp == 16 || bpp == 32)
807 {
808 if (comp == BI_BITFIELDS)
809 {
810 int bit = 0;
811
812 fread(dbuf, 4, 3, file);
813 bmask = dbuf[0];
814 gmask = dbuf[1];
815 rmask = dbuf[2];
816 /* find shift amount.. ugly, but i can't think of a better way */
817 for (bit = 0; bit < bpp; bit++)
818 {
819 if (bmask & (1 << bit))
820 bshift = bit;
821 if (gmask & (1 << bit))
822 gshift = bit;
823 if (rmask & (1 << bit))
824 rshift = bit;
825 }
826 }
827 else if (bpp == 16)
828 {
829 rmask = 0x7C00;
830 gmask = 0x03E0;
831 bmask = 0x001F;
832 rshift = 10;
833 gshift = 5;
834 bshift = 0;
835 }
836 else if (bpp == 32)
837 {
838 rmask = 0x00FF0000;
839 gmask = 0x0000FF00;
840 bmask = 0x000000FF;
841 rshift = 16;
842 gshift = 8;
843 bshift = 0;
844 }
845 }
846
847 /*
848 * REading the image data
849 */
850 fseek(file, offset, SEEK_SET);
851 data = ptr;
852
853 /* set the whole image to the background color */
854 if (bpp < 16 && (comp == BI_RLE4 || comp == BI_RLE8))
855 {
856 for (i = 0; i < width * height; i++)
857 {
858 *ptr++ = cmap[0].r;
859 *ptr++ = cmap[0].g;
860 *ptr++ = cmap[0].b;
861 }
862 ptr = data;
863 }
864 line = 0;
865 column = 0;
866 #define poffset (line * width * 3 + column * 3)
867
868 /*
869 * BMPs are stored upside down... hmmmmmmmmmm....
870 */
871
872 linesize = ((width * bpp + 31) / 32) * 4;
873 for (line = (height - 1); line >= 0; line--)
874 {
875 linepos = 0;
876 for (column = 0; column < width;)
877 {
878 if (bpp < 16)
879 {
880 int index;
881
882 linepos++;
883 aByte = getc(file);
884 if (bpp == 1)
885 {
886 int bit = 0;
887
888 for (bit = 0; bit < 8; bit++)
889 {
890 index = ((aByte & (0x80 >> bit)) ? 1 : 0);
891 ptr[poffset] = cmap[index].r;
892 ptr[poffset + 1] = cmap[index].g;
893 ptr[poffset + 2] = cmap[index].b;
894 column++;
895 }
896 }
897 else if (bpp == 4)
898 {
899 if (comp == BI_RLE4)
900 {
901 wxLogError( "can't deal with 4bit encoded yet.\n");
902 image->Destroy();
903 free(cmap);
904 return FALSE;
905 }
906 else
907 {
908 int nibble = 0;
909
910 for (nibble = 0; nibble < 2; nibble++)
911 {
912 index = ((aByte & (0xF0 >> nibble * 4)) >> (!nibble * 4));
913 if (index >= 16)
914 index = 15;
915 ptr[poffset] = cmap[index].r;
916 ptr[poffset + 1] = cmap[index].g;
917 ptr[poffset + 2] = cmap[index].b;
918 column++;
919 }
920 }
921 }
922 else if (bpp == 8)
923 {
924 if (comp == BI_RLE8)
925 {
926 unsigned char first;
927
928 first = aByte;
929 aByte = getc(file);
930 if (first == 0)
931 {
932 if (aByte == 0)
933 {
934 /* column = width; */
935 }
936 else if (aByte == 1)
937 {
938 column = width;
939 line = -1;
940 }
941 else if (aByte == 2)
942 {
943 aByte = getc(file);
944 column += aByte;
945 linepos = column * bpp / 8;
946 aByte = getc(file);
947 line += aByte;
948 }
949 else
950 {
951 int absolute = aByte;
952
953 for (i = 0; i < absolute; i++)
954 {
955 linepos++;
956 aByte = getc(file);
957 ptr[poffset] = cmap[aByte].r;
958 ptr[poffset + 1] = cmap[aByte].g;
959 ptr[poffset + 2] = cmap[aByte].b;
960 column++;
961 }
962 if (absolute & 0x01)
963 aByte = getc(file);
964 }
965 }
966 else
967 {
968 for (i = 0; i < first; i++)
969 {
970 ptr[poffset] = cmap[aByte].r;
971 ptr[poffset + 1] = cmap[aByte].g;
972 ptr[poffset + 2] = cmap[aByte].b;
973 column++;
974 linepos++;
975 }
976 }
977 }
978 else
979 {
980 ptr[poffset] = cmap[aByte].r;
981 ptr[poffset + 1] = cmap[aByte].g;
982 ptr[poffset + 2] = cmap[aByte].b;
983 column++;
984 linepos += size;
985 }
986 }
987 }
988 else if (bpp == 24)
989 {
990 linepos += fread(&bbuf, 1, 3, file);
991 ptr[poffset] = (unsigned char)bbuf[2];
992 ptr[poffset + 1] = (unsigned char)bbuf[1];
993 ptr[poffset + 2] = (unsigned char)bbuf[0];
994 column++;
995 }
996 else if (bpp == 16)
997 {
998 unsigned char temp;
999
1000 linepos += fread(&word, 2, 1, file);
1001 temp = (word & rmask) >> rshift;
1002 ptr[poffset] = temp;
1003 temp = (word & gmask) >> gshift;
1004 ptr[poffset + 1] = temp;
1005 temp = (word & bmask) >> gshift;
1006 ptr[poffset + 2] = temp;
1007 column++;
1008 }
1009 else
1010 {
1011 unsigned char temp;
1012
1013 linepos += fread(&dword, 4, 1, file);
1014 temp = (dword & rmask) >> rshift;
1015 ptr[poffset] = temp;
1016 temp = (dword & gmask) >> gshift;
1017 ptr[poffset + 1] = temp;
1018 temp = (dword & bmask) >> bshift;
1019 ptr[poffset + 2] = temp;
1020 column++;
1021 }
1022 }
1023 while ((linepos < linesize) && (comp != 1) && (comp != 2))
1024 {
1025 int temp = fread(&aByte, 1, 1, file);
1026
1027 linepos += temp;
1028 if (!temp)
1029 break;
1030 }
1031 }
1032 if (cmap) free(cmap);
1033
1034 image->SetMask( FALSE );
1035
1036 fclose(file);
1037 return TRUE;
1038 }
1039
1040 #ifdef __WXMSW__
1041
1042 wxBitmap wxImage::ConvertToBitmap() const
1043 {
1044
1045 wxBitmap bitmap;
1046 wxCHECK_MSG( Ok(), bitmap, "invalid image" );
1047 int width = GetWidth();
1048 int height = GetHeight();
1049 bitmap.SetWidth( width );
1050 bitmap.SetHeight( height );
1051 bitmap.SetDepth( wxDisplayDepth() );
1052
1053 int headersize = sizeof(BITMAPINFOHEADER);
1054 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
1055 wxCHECK_MSG( lpDIBh, bitmap, "could not allocate memory for DIB header" );
1056
1057 // Fill in the DIB header
1058 lpDIBh->bmiHeader.biSize = headersize;
1059 lpDIBh->bmiHeader.biWidth = width;
1060 lpDIBh->bmiHeader.biHeight = -height;
1061 lpDIBh->bmiHeader.biSizeImage = width * height * 3;
1062
1063 lpDIBh->bmiHeader.biPlanes = 1;
1064 lpDIBh->bmiHeader.biBitCount = 24;
1065 lpDIBh->bmiHeader.biCompression = BI_RGB;
1066 lpDIBh->bmiHeader.biClrUsed = 0;
1067
1068 // These seem not needed for our purpose here.
1069 // lpDIBh->bmiHeader.biClrImportant = 0;
1070 // lpDIBh->bmiHeader.biXPelsPerMeter = 0;
1071 // lpDIBh->bmiHeader.biYPelsPerMeter = 0;
1072
1073 unsigned char *lpBits = (unsigned char *) malloc( width*height*3 );
1074 if( !lpBits )
1075 {
1076 wxFAIL_MSG( "could not allocate memory for DIB" );
1077 free( lpDIBh );
1078 return bitmap;
1079 }
1080
1081 unsigned char *data = GetData();
1082
1083 unsigned char *ptdata = data, *ptbits = lpBits;
1084 for( int i=0; i<width*height; i++ )
1085 {
1086 *(ptbits++) = *(ptdata+2);
1087 *(ptbits++) = *(ptdata+1);
1088 *(ptbits++) = *(ptdata );
1089 ptdata += 3;
1090 }
1091
1092 HDC hdc = ::GetDC(NULL);
1093
1094 HBITMAP hbitmap;
1095 hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
1096
1097 // The above line is equivalent to the following two lines.
1098 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
1099 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
1100 // or the following lines
1101 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
1102 // HDC memdc = ::CreateCompatibleDC( hdc );
1103 // ::SelectObject( memdc, hbitmap);
1104 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
1105 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
1106 // ::SelectObject( memdc, 0 );
1107 // ::DeleteDC( memdc );
1108
1109 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
1110
1111 if( HasMask() )
1112 {
1113 unsigned char r = GetMaskRed();
1114 unsigned char g = GetMaskGreen();
1115 unsigned char b = GetMaskBlue();
1116 unsigned char zero = 0, one = 255;
1117 ptdata = data;
1118 ptbits = lpBits;
1119 for( int i=0; i<width*height; i++ )
1120 {
1121 if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
1122 {
1123 *(ptbits++) = one;
1124 *(ptbits++) = one;
1125 *(ptbits++) = one;
1126 }
1127 else
1128 {
1129 *(ptbits++) = zero;
1130 *(ptbits++) = zero;
1131 *(ptbits++) = zero;
1132 }
1133 }
1134 hbitmap = ::CreateBitmap( (WORD)width, (WORD)height, 1, 1, NULL );
1135 ::SetDIBits( hdc, hbitmap, 0, (WORD)height, lpBits, lpDIBh, DIB_RGB_COLORS);
1136 wxMask *mask = new wxMask();
1137 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
1138 bitmap.SetMask( mask );
1139
1140 /* The following can also be used but is slow to run
1141 wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
1142 wxMask *mask = new wxMask( bitmap, colour );
1143 bitmap.SetMask( mask );
1144 */
1145 }
1146
1147 ::ReleaseDC(NULL, hdc);
1148 free(lpDIBh);
1149 free(lpBits);
1150
1151 if( bitmap.GetHBITMAP() )
1152 bitmap.SetOk( TRUE );
1153 else
1154 bitmap.SetOk( FALSE );
1155
1156 return bitmap;
1157 }
1158
1159
1160 wxImage::wxImage( const wxBitmap &bitmap )
1161 {
1162 if( !bitmap.Ok() )
1163 {
1164 wxFAIL_MSG( "invalid bitmap" );
1165 return;
1166 }
1167
1168 int width = bitmap.GetWidth();
1169 int height = bitmap.GetHeight();
1170 Create( width, height );
1171 unsigned char *data = GetData();
1172 if( !data )
1173 {
1174 wxFAIL_MSG( "could not allocate data for image" );
1175 return;
1176 }
1177
1178 int headersize = sizeof(BITMAPINFOHEADER);
1179 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
1180 if( !lpDIBh )
1181 {
1182 wxFAIL_MSG( "could not allocate data for DIB header" );
1183 free( data );
1184 return;
1185 }
1186
1187 // Fill in the DIB header
1188 lpDIBh->bmiHeader.biSize = headersize;
1189 lpDIBh->bmiHeader.biWidth = width;
1190 lpDIBh->bmiHeader.biHeight = -height;
1191 lpDIBh->bmiHeader.biSizeImage = width * height * 3;
1192
1193 lpDIBh->bmiHeader.biPlanes = 1;
1194 lpDIBh->bmiHeader.biBitCount = 24;
1195 lpDIBh->bmiHeader.biCompression = BI_RGB;
1196 lpDIBh->bmiHeader.biClrUsed = 0;
1197
1198 // These seem not needed for our purpose here.
1199 // lpDIBh->bmiHeader.biClrImportant = 0;
1200 // lpDIBh->bmiHeader.biXPelsPerMeter = 0;
1201 // lpDIBh->bmiHeader.biYPelsPerMeter = 0;
1202
1203 unsigned char *lpBits = (unsigned char *) malloc( width*height*3 );
1204 if( !lpBits )
1205 {
1206 wxFAIL_MSG( "could not allocate data for DIB" );
1207 free( data );
1208 free( lpDIBh );
1209 return;
1210 }
1211
1212 HBITMAP hbitmap;
1213 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
1214 HDC hdc = ::GetDC(NULL);
1215 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1216
1217 unsigned char *ptdata = data, *ptbits = lpBits;
1218 for( int i=0; i<width*height; i++ )
1219 {
1220 *(ptdata++) = *(ptbits+2);
1221 *(ptdata++) = *(ptbits+1);
1222 *(ptdata++) = *(ptbits );
1223 ptbits += 3;
1224 }
1225
1226 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
1227 {
1228 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
1229 HDC memdc = ::CreateCompatibleDC( hdc );
1230 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
1231 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
1232 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1233 ::DeleteDC( memdc );
1234 unsigned char r=16, g=16, b=16; // background set to RGB(16,16,16)
1235 ptdata = data;
1236 ptbits = lpBits;
1237 for( int i=0; i<width*height; i++ )
1238 {
1239 if( *ptbits != 0 )
1240 {
1241 *(ptdata++) = r;
1242 *(ptdata++) = g;
1243 *(ptdata++) = b;
1244 }
1245 ptbits += 3;
1246 }
1247 SetMaskColour( r, g, b );
1248 }
1249
1250 ::ReleaseDC(NULL, hdc);
1251 free(lpDIBh);
1252 free(lpBits);
1253 }
1254
1255 #endif
1256
1257 #ifdef __WXGTK__
1258
1259 #include "gtk/gtk.h"
1260 #include "gdk/gdk.h"
1261 #include "gdk/gdkx.h"
1262
1263 wxBitmap wxImage::ConvertToBitmap() const
1264 {
1265 wxBitmap bitmap;
1266
1267 wxCHECK_MSG( Ok(), bitmap, "invalid image" );
1268
1269 int width = GetWidth();
1270 int height = GetHeight();
1271
1272 bitmap.SetHeight( height );
1273 bitmap.SetWidth( width );
1274
1275 // Create picture
1276
1277 GdkImage *data_image =
1278 gdk_image_new( GDK_IMAGE_FASTEST, gdk_visual_get_system(), width, height );
1279
1280 bitmap.SetPixmap( gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, -1 ) );
1281
1282 // Create mask
1283
1284 GdkImage *mask_image = (GdkImage*) NULL;
1285
1286 if (HasMask())
1287 {
1288 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1289
1290 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1291
1292 wxMask *mask = new wxMask();
1293 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1294
1295 bitmap.SetMask( mask );
1296 }
1297
1298 // Retrieve depth
1299
1300 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
1301 if (visual == NULL) visual = gdk_window_get_visual( (GdkWindow*) &gdk_root_parent );
1302 int bpp = visual->depth;
1303
1304 bitmap.SetDepth( bpp );
1305
1306 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
1307 if (bpp < 8) bpp = 8;
1308
1309 // Render
1310
1311 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1312 byte_order b_o = RGB;
1313
1314 if (bpp >= 24)
1315 {
1316 GdkVisual *visual = gdk_visual_get_system();
1317 if ((visual->red_mask > visual->green_mask) && (visual->green_mask > visual->blue_mask)) b_o = RGB;
1318 else if ((visual->red_mask > visual->blue_mask) && (visual->blue_mask > visual->green_mask)) b_o = RGB;
1319 else if ((visual->blue_mask > visual->red_mask) && (visual->red_mask > visual->green_mask)) b_o = BRG;
1320 else if ((visual->blue_mask > visual->green_mask) && (visual->green_mask > visual->red_mask)) b_o = BGR;
1321 else if ((visual->green_mask > visual->red_mask) && (visual->red_mask > visual->blue_mask)) b_o = GRB;
1322 else if ((visual->green_mask > visual->blue_mask) && (visual->blue_mask > visual->red_mask)) b_o = GBR;
1323 }
1324
1325 int r_mask = GetMaskRed();
1326 int g_mask = GetMaskGreen();
1327 int b_mask = GetMaskBlue();
1328
1329 unsigned char* data = GetData();
1330
1331 int index = 0;
1332 for (int y = 0; y < height; y++)
1333 {
1334 for (int x = 0; x < width; x++)
1335 {
1336 int r = data[index];
1337 index++;
1338 int g = data[index];
1339 index++;
1340 int b = data[index];
1341 index++;
1342
1343 if (HasMask())
1344 {
1345 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1346 gdk_image_put_pixel( mask_image, x, y, 1 );
1347 else
1348 gdk_image_put_pixel( mask_image, x, y, 0 );
1349 }
1350
1351 switch (bpp)
1352 {
1353 case 8:
1354 {
1355 GdkColormap *cmap = gtk_widget_get_default_colormap();
1356 GdkColor *colors = cmap->colors;
1357 int max = 3 * (65536);
1358 int index = -1;
1359
1360 for (int i = 0; i < cmap->size; i++)
1361 {
1362 int rdiff = (r << 8) - colors[i].red;
1363 int gdiff = (g << 8) - colors[i].green;
1364 int bdiff = (b << 8) - colors[i].blue;
1365 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1366 if (sum < max) { index = i; max = sum; }
1367 }
1368
1369 gdk_image_put_pixel( data_image, x, y, index );
1370
1371 break;
1372 }
1373 case 15:
1374 {
1375 guint32 pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1376 gdk_image_put_pixel( data_image, x, y, pixel );
1377 break;
1378 }
1379 case 16:
1380 {
1381 guint32 pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1382 gdk_image_put_pixel( data_image, x, y, pixel );
1383 break;
1384 }
1385 case 32:
1386 case 24:
1387 {
1388 guint32 pixel = 0;
1389 switch (b_o)
1390 {
1391 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1392 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1393 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1394 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1395 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1396 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1397 }
1398 gdk_image_put_pixel( data_image, x, y, pixel );
1399 }
1400 default: break;
1401 }
1402 } // for
1403 } // for
1404
1405 // Blit picture
1406
1407 GdkGC *data_gc = gdk_gc_new( bitmap.GetPixmap() );
1408
1409 gdk_draw_image( bitmap.GetPixmap(), data_gc, data_image, 0, 0, 0, 0, width, height );
1410
1411 gdk_image_destroy( data_image );
1412 gdk_gc_unref( data_gc );
1413
1414 // Blit mask
1415
1416 if (HasMask())
1417 {
1418 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
1419
1420 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
1421
1422 gdk_image_destroy( mask_image );
1423 gdk_gc_unref( mask_gc );
1424 }
1425
1426 return bitmap;
1427 }
1428
1429 wxImage::wxImage( const wxBitmap &bitmap )
1430 {
1431 wxCHECK_RET( bitmap.Ok(), "invalid bitmap" );
1432
1433 GdkImage *gdk_image = gdk_image_get( bitmap.GetPixmap(),
1434 0, 0,
1435 bitmap.GetWidth(), bitmap.GetHeight() );
1436
1437 wxCHECK_RET( gdk_image, "couldn't create image" );
1438
1439 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1440 char unsigned *data = GetData();
1441
1442 if (!data)
1443 {
1444 gdk_image_destroy( gdk_image );
1445 wxFAIL_MSG( "couldn't create image" );
1446 return;
1447 }
1448
1449 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1450 if (bitmap.GetMask())
1451 {
1452 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1453 0, 0,
1454 bitmap.GetWidth(), bitmap.GetHeight() );
1455
1456 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1457 }
1458
1459 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
1460 if (visual == NULL) visual = gdk_window_get_visual( (GdkWindow*) &gdk_root_parent );
1461 int bpp = visual->depth;
1462 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
1463
1464 GdkColormap *cmap = gtk_widget_get_default_colormap();
1465
1466 long pos = 0;
1467 for (int j = 0; j < bitmap.GetHeight(); j++)
1468 {
1469 for (int i = 0; i < bitmap.GetWidth(); i++)
1470 {
1471 int pixel = gdk_image_get_pixel( gdk_image, i, j );
1472 if (bpp <= 8)
1473 {
1474 data[pos] = cmap->colors[pixel].red >> 8;
1475 data[pos+1] = cmap->colors[pixel].green >> 8;
1476 data[pos+2] = cmap->colors[pixel].blue >> 8;
1477 } else if (bpp == 15)
1478 {
1479 data[pos] = (pixel >> 7) & 0xf8;
1480 data[pos+1] = (pixel >> 2) & 0xf8;
1481 data[pos+2] = (pixel << 3) & 0xf8;
1482 } else if (bpp == 16)
1483 {
1484 data[pos] = (pixel >> 8) & 0xf8;
1485 data[pos+1] = (pixel >> 3) & 0xfc;
1486 data[pos+2] = (pixel << 3) & 0xf8;
1487 } else
1488 {
1489 data[pos] = (pixel >> 16) & 0xff;
1490 data[pos+1] = (pixel >> 8) & 0xff;
1491 data[pos+2] = pixel & 0xff;
1492 }
1493
1494 if (gdk_image_mask)
1495 {
1496 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1497 if (mask_pixel == 0)
1498 {
1499 data[pos] = 16;
1500 data[pos+1] = 16;
1501 data[pos+2] = 16;
1502 }
1503 }
1504
1505 pos += 3;
1506 }
1507 }
1508
1509 gdk_image_destroy( gdk_image );
1510 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1511 }
1512
1513 #endif