]> git.saurik.com Git - wxWidgets.git/blob - src/common/image.cpp
no message
[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 image->Destroy();
450
451 png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING,
452 (voidp) NULL, (png_error_ptr) NULL, (png_error_ptr) NULL );
453 if (!png_ptr) return FALSE;
454
455 png_infop info_ptr = png_create_info_struct( png_ptr );
456 if (!info_ptr)
457 {
458 png_destroy_read_struct( &png_ptr, (png_infopp) NULL, (png_infopp) NULL );
459 return FALSE;
460 }
461
462 if (setjmp(png_ptr->jmpbuf))
463 {
464 png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL );
465 return FALSE;
466 }
467
468 if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
469 {
470 png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL );
471 return FALSE;
472 }
473
474 FILE *f = fopen( name, "rb" );
475 png_init_io( png_ptr, f );
476
477 png_uint_32 width,height;
478 int bit_depth,color_type,interlace_type;
479
480 png_read_info( png_ptr, info_ptr );
481 png_get_IHDR( png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, (int*) NULL, (int*) NULL );
482
483 if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_expand( png_ptr );
484
485 png_set_strip_16( png_ptr );
486 png_set_packing( png_ptr );
487 if (png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand( png_ptr );
488 png_set_filler( png_ptr, 0xff, PNG_FILLER_AFTER );
489
490 image->Create( width, height );
491
492 if (!image->Ok())
493 {
494 png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL );
495 return FALSE;
496 }
497
498 unsigned char **lines = (unsigned char **)malloc( height * sizeof(unsigned char *) );
499 if (lines == NULL)
500 {
501 image->Destroy();
502 png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL );
503 return FALSE;
504 }
505
506 for (unsigned int i = 0; i < height; i++)
507 {
508 if ((lines[i] = (unsigned char *)malloc(width * (sizeof(unsigned char) * 4))) == NULL)
509 {
510 image->Destroy();
511 for (unsigned int n = 0; n < i; n++) free( lines[n] );
512 free( lines );
513 png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL );
514 return FALSE;
515 }
516 }
517
518
519 int transp = 0;
520 png_read_image( png_ptr, lines );
521 png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL );
522 unsigned char *ptr = image->GetData();
523 if ((color_type == PNG_COLOR_TYPE_GRAY) ||
524 (color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
525 {
526 for (unsigned int y = 0; y < height; y++)
527 {
528 unsigned char *ptr2 = lines[y];
529 for (unsigned int x = 0; x < width; x++)
530 {
531 unsigned char r = *ptr2++;
532 unsigned char a = *ptr2++;
533 if (a < 128)
534 {
535 *ptr++ = 255;
536 *ptr++ = 0;
537 *ptr++ = 255;
538 transp = 1;
539 }
540 else
541 {
542 *ptr++ = r;
543 *ptr++ = r;
544 *ptr++ = r;
545 }
546 }
547 }
548 }
549 else
550 {
551 for (unsigned int y = 0; y < height; y++)
552 {
553 unsigned char *ptr2 = lines[y];
554 for (unsigned int x = 0; x < width; x++)
555 {
556 unsigned char r = *ptr2++;
557 unsigned char g = *ptr2++;
558 unsigned char b = *ptr2++;
559 unsigned char a = *ptr2++;
560 if (a < 128)
561 {
562 *ptr++ = 255;
563 *ptr++ = 0;
564 *ptr++ = 255;
565 transp = 1;
566 }
567 else
568 {
569 if ((r == 255) && (g == 0) && (b == 255)) r = 254;
570 *ptr++ = r;
571 *ptr++ = g;
572 *ptr++ = b;
573 }
574 }
575 }
576 }
577
578 for (unsigned int j = 0; j < height; j++) free( lines[j] );
579 free( lines );
580
581 if (transp)
582 {
583 image->SetMaskColour( 255, 0, 255 );
584 }
585 else
586 {
587 image->SetMask( FALSE );
588 }
589
590 return TRUE;
591 }
592
593
594 bool wxPNGHandler::SaveFile( wxImage *image, const wxString& name )
595 {
596 FILE *f = fopen( name, "wb" );
597 if (!f) return FALSE;
598
599 png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING,
600 (voidp) NULL, (png_error_ptr) NULL, (png_error_ptr) NULL);
601 if (!png_ptr)
602 {
603 fclose( f );
604 return FALSE;
605 }
606
607 png_infop info_ptr = png_create_info_struct(png_ptr);
608 if (info_ptr == NULL)
609 {
610 fclose(f);
611 png_destroy_write_struct( &png_ptr, (png_infopp) NULL );
612 return FALSE;
613 }
614
615 if (setjmp(png_ptr->jmpbuf))
616 {
617 fclose( f );
618 png_destroy_write_struct( &png_ptr, (png_infopp) NULL );
619 return FALSE;
620 }
621
622 png_init_io( png_ptr, f );
623 png_set_IHDR( png_ptr, info_ptr, image->GetWidth(), image->GetHeight(), 8,
624 PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
625 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
626
627 png_color_8 sig_bit;
628 sig_bit.red = 8;
629 sig_bit.green = 8;
630 sig_bit.blue = 8;
631 sig_bit.alpha = 8;
632 png_set_sBIT( png_ptr, info_ptr, &sig_bit );
633 png_write_info( png_ptr, info_ptr );
634 png_set_shift( png_ptr, &sig_bit );
635 png_set_packing( png_ptr );
636
637 unsigned char *data = (unsigned char *)malloc( image->GetWidth()*4 );
638 if (!data)
639 {
640 fclose( f );
641 png_destroy_write_struct( &png_ptr, (png_infopp) NULL );
642 return FALSE;
643 }
644
645 for (int y = 0; y < image->GetHeight(); y++)
646 {
647 unsigned char *ptr = image->GetData() + (y * image->GetWidth() * 3);
648 for (int x = 0; x < image->GetWidth(); x++)
649 {
650 data[(x << 2) + 0] = *ptr++;
651 data[(x << 2) + 1] = *ptr++;
652 data[(x << 2) + 2] = *ptr++;
653 if ((data[(x << 2) + 0] == image->GetMaskRed()) &&
654 (data[(x << 2) + 1] == image->GetMaskGreen()) &&
655 (data[(x << 2) + 2] == image->GetMaskBlue()))
656 {
657 data[(x << 2) + 3] = 0;
658 }
659 else
660 {
661 data[(x << 2) + 3] = 255;
662 }
663 }
664 png_bytep row_ptr = data;
665 png_write_rows( png_ptr, &row_ptr, 1 );
666 }
667
668 free(data);
669 png_write_end( png_ptr, info_ptr );
670 png_destroy_write_struct( &png_ptr, (png_infopp) NULL );
671
672 fclose(f);
673
674 return TRUE;
675 }
676
677 #endif
678
679 // wxUSE_LIBPNG
680
681 //-----------------------------------------------------------------------------
682 // wxBMPHandler
683 //-----------------------------------------------------------------------------
684
685 #if !USE_SHARED_LIBRARIES
686 IMPLEMENT_DYNAMIC_CLASS(wxBMPHandler,wxImageHandler)
687 #endif
688
689 bool wxBMPHandler::LoadFile( wxImage *image, const wxString& name )
690 {
691 FILE *file;
692 unsigned char *data, *ptr;
693 int done, i, bpp, planes, comp, ncolors, line, column,
694 linesize, linepos, rshift = 0, gshift = 0, bshift = 0;
695 unsigned char aByte;
696 short int word;
697 long int dbuf[4], dword, rmask = 0, gmask = 0, bmask = 0, offset,
698 size;
699 signed char bbuf[4];
700 struct _cmap
701 {
702 unsigned char r, g, b;
703 }
704 *cmap = NULL;
705 #ifndef BI_RGB
706 #define BI_RGB 0
707 #define BI_RLE8 1
708 #define BI_RLE4 2
709 #endif
710
711 #ifndef BI_BITFIELDS
712 #define BI_BITFIELDS 3
713 #endif
714
715 image->Destroy();
716
717 file = fopen(name, "r");
718 if (!file)
719 return NULL;
720
721 done = 0;
722 /*
723 * Reading the bmp header
724 */
725
726 fread(&bbuf, 1, 2, file);
727
728 fread(dbuf, 4, 4, file);
729
730 size = dbuf[0];
731 offset = dbuf[2];
732
733 fread(dbuf, 4, 2, file);
734 int width = (int)dbuf[0];
735 int height = (int)dbuf[1];
736 if (width > 32767)
737 {
738 wxLogError( "Image width > 32767 pixels for file\n" );
739 fclose(file);
740 return FALSE;
741 }
742 if (height > 32767)
743 {
744 wxLogError( "Image height > 32767 pixels for file\n" );
745 fclose(file);
746 return FALSE;
747 }
748 fread(&word, 2, 1, file);
749 planes = (int)word;
750 fread(&word, 2, 1, file);
751 bpp = (int)word;
752 if (bpp != 1 && bpp != 4 && bpp != 8 && bpp && 16 && bpp != 24 && bpp != 32)
753 {
754 wxLogError( "unknown bitdepth in file\n" );
755 fclose(file);
756 return FALSE;
757 }
758 fread(dbuf, 4, 4, file);
759 comp = (int)dbuf[0];
760 if (comp != BI_RGB && comp != BI_RLE4 && comp != BI_RLE8 && comp != BI_BITFIELDS)
761 {
762 wxLogError( "unknown encoding in Windows BMP file\n" );
763 fclose(file);
764 return FALSE;
765 }
766 fread(dbuf, 4, 2, file);
767 ncolors = (int)dbuf[0];
768 if (ncolors == 0)
769 ncolors = 1 << bpp;
770 /* some more sanity checks */
771 if (((comp == BI_RLE4) && (bpp != 4)) || ((comp == BI_RLE8) && (bpp != 8)) || ((comp == BI_BITFIELDS) && (bpp != 16 && bpp != 32)))
772 {
773 wxLogError( "encoding of BMP doesn't match bitdepth\n" );
774 fclose(file);
775 return FALSE;
776 }
777 if (bpp < 16)
778 {
779 cmap = (struct _cmap *)malloc(sizeof(struct _cmap) * ncolors);
780
781 if (!cmap)
782 {
783 wxLogError( "Cannot allocate RAM for color map in BMP file\n" );
784 fclose(file);
785 return FALSE;
786 }
787 }
788 else
789 cmap = NULL;
790
791 image->Create( width, height );
792 ptr = image->GetData();
793 if (!ptr)
794 {
795 wxLogError( "Cannot allocate RAM for RGB data in file\n" );
796 fclose(file);
797 if (cmap)
798 free(cmap);
799 return FALSE;
800 }
801
802 /*
803 * Reading the palette, if it exists.
804 */
805 if (bpp < 16 && ncolors != 0)
806 {
807 for (i = 0; i < ncolors; i++)
808 {
809 fread(bbuf, 1, 4, file);
810 cmap[i].b = bbuf[0];
811 cmap[i].g = bbuf[1];
812 cmap[i].r = bbuf[2];
813 }
814 }
815 else if (bpp == 16 || bpp == 32)
816 {
817 if (comp == BI_BITFIELDS)
818 {
819 int bit = 0;
820
821 fread(dbuf, 4, 3, file);
822 bmask = dbuf[0];
823 gmask = dbuf[1];
824 rmask = dbuf[2];
825 /* find shift amount.. ugly, but i can't think of a better way */
826 for (bit = 0; bit < bpp; bit++)
827 {
828 if (bmask & (1 << bit))
829 bshift = bit;
830 if (gmask & (1 << bit))
831 gshift = bit;
832 if (rmask & (1 << bit))
833 rshift = bit;
834 }
835 }
836 else if (bpp == 16)
837 {
838 rmask = 0x7C00;
839 gmask = 0x03E0;
840 bmask = 0x001F;
841 rshift = 10;
842 gshift = 5;
843 bshift = 0;
844 }
845 else if (bpp == 32)
846 {
847 rmask = 0x00FF0000;
848 gmask = 0x0000FF00;
849 bmask = 0x000000FF;
850 rshift = 16;
851 gshift = 8;
852 bshift = 0;
853 }
854 }
855
856 /*
857 * REading the image data
858 */
859 fseek(file, offset, SEEK_SET);
860 data = ptr;
861
862 /* set the whole image to the background color */
863 if (bpp < 16 && (comp == BI_RLE4 || comp == BI_RLE8))
864 {
865 for (i = 0; i < width * height; i++)
866 {
867 *ptr++ = cmap[0].r;
868 *ptr++ = cmap[0].g;
869 *ptr++ = cmap[0].b;
870 }
871 ptr = data;
872 }
873 line = 0;
874 column = 0;
875 #define poffset (line * width * 3 + column * 3)
876
877 /*
878 * BMPs are stored upside down... hmmmmmmmmmm....
879 */
880
881 linesize = ((width * bpp + 31) / 32) * 4;
882 for (line = (height - 1); line >= 0; line--)
883 {
884 linepos = 0;
885 for (column = 0; column < width;)
886 {
887 if (bpp < 16)
888 {
889 int index;
890
891 linepos++;
892 aByte = getc(file);
893 if (bpp == 1)
894 {
895 int bit = 0;
896
897 for (bit = 0; bit < 8; bit++)
898 {
899 index = ((aByte & (0x80 >> bit)) ? 1 : 0);
900 ptr[poffset] = cmap[index].r;
901 ptr[poffset + 1] = cmap[index].g;
902 ptr[poffset + 2] = cmap[index].b;
903 column++;
904 }
905 }
906 else if (bpp == 4)
907 {
908 if (comp == BI_RLE4)
909 {
910 wxLogError( "can't deal with 4bit encoded yet.\n");
911 image->Destroy();
912 free(cmap);
913 return FALSE;
914 }
915 else
916 {
917 int nibble = 0;
918
919 for (nibble = 0; nibble < 2; nibble++)
920 {
921 index = ((aByte & (0xF0 >> nibble * 4)) >> (!nibble * 4));
922 if (index >= 16)
923 index = 15;
924 ptr[poffset] = cmap[index].r;
925 ptr[poffset + 1] = cmap[index].g;
926 ptr[poffset + 2] = cmap[index].b;
927 column++;
928 }
929 }
930 }
931 else if (bpp == 8)
932 {
933 if (comp == BI_RLE8)
934 {
935 unsigned char first;
936
937 first = aByte;
938 aByte = getc(file);
939 if (first == 0)
940 {
941 if (aByte == 0)
942 {
943 /* column = width; */
944 }
945 else if (aByte == 1)
946 {
947 column = width;
948 line = -1;
949 }
950 else if (aByte == 2)
951 {
952 aByte = getc(file);
953 column += aByte;
954 linepos = column * bpp / 8;
955 aByte = getc(file);
956 line += aByte;
957 }
958 else
959 {
960 int absolute = aByte;
961
962 for (i = 0; i < absolute; i++)
963 {
964 linepos++;
965 aByte = getc(file);
966 ptr[poffset] = cmap[aByte].r;
967 ptr[poffset + 1] = cmap[aByte].g;
968 ptr[poffset + 2] = cmap[aByte].b;
969 column++;
970 }
971 if (absolute & 0x01)
972 aByte = getc(file);
973 }
974 }
975 else
976 {
977 for (i = 0; i < first; i++)
978 {
979 ptr[poffset] = cmap[aByte].r;
980 ptr[poffset + 1] = cmap[aByte].g;
981 ptr[poffset + 2] = cmap[aByte].b;
982 column++;
983 linepos++;
984 }
985 }
986 }
987 else
988 {
989 ptr[poffset] = cmap[aByte].r;
990 ptr[poffset + 1] = cmap[aByte].g;
991 ptr[poffset + 2] = cmap[aByte].b;
992 column++;
993 linepos += size;
994 }
995 }
996 }
997 else if (bpp == 24)
998 {
999 linepos += fread(&bbuf, 1, 3, file);
1000 ptr[poffset] = (unsigned char)bbuf[2];
1001 ptr[poffset + 1] = (unsigned char)bbuf[1];
1002 ptr[poffset + 2] = (unsigned char)bbuf[0];
1003 column++;
1004 }
1005 else if (bpp == 16)
1006 {
1007 unsigned char temp;
1008
1009 linepos += fread(&word, 2, 1, file);
1010 temp = (word & rmask) >> rshift;
1011 ptr[poffset] = temp;
1012 temp = (word & gmask) >> gshift;
1013 ptr[poffset + 1] = temp;
1014 temp = (word & bmask) >> gshift;
1015 ptr[poffset + 2] = temp;
1016 column++;
1017 }
1018 else
1019 {
1020 unsigned char temp;
1021
1022 linepos += fread(&dword, 4, 1, file);
1023 temp = (dword & rmask) >> rshift;
1024 ptr[poffset] = temp;
1025 temp = (dword & gmask) >> gshift;
1026 ptr[poffset + 1] = temp;
1027 temp = (dword & bmask) >> bshift;
1028 ptr[poffset + 2] = temp;
1029 column++;
1030 }
1031 }
1032 while ((linepos < linesize) && (comp != 1) && (comp != 2))
1033 {
1034 int temp = fread(&aByte, 1, 1, file);
1035
1036 linepos += temp;
1037 if (!temp)
1038 break;
1039 }
1040 }
1041 if (cmap) free(cmap);
1042
1043 image->SetMask( FALSE );
1044
1045 fclose(file);
1046 return TRUE;
1047 }
1048
1049 #ifdef __WXMSW__
1050
1051 wxBitmap wxImage::ConvertToBitmap() const
1052 {
1053
1054 wxBitmap bitmap;
1055 wxCHECK_MSG( Ok(), bitmap, "invalid image" );
1056 int width = GetWidth();
1057 int height = GetHeight();
1058 bitmap.SetWidth( width );
1059 bitmap.SetHeight( height );
1060 bitmap.SetDepth( wxDisplayDepth() );
1061
1062 int headersize = sizeof(BITMAPINFOHEADER);
1063 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
1064 wxCHECK_MSG( lpDIBh, bitmap, "could not allocate memory for DIB header" );
1065
1066 // Fill in the DIB header
1067 lpDIBh->bmiHeader.biSize = headersize;
1068 lpDIBh->bmiHeader.biWidth = width;
1069 lpDIBh->bmiHeader.biHeight = -height;
1070 lpDIBh->bmiHeader.biSizeImage = width * height * 3;
1071
1072 lpDIBh->bmiHeader.biPlanes = 1;
1073 lpDIBh->bmiHeader.biBitCount = 24;
1074 lpDIBh->bmiHeader.biCompression = BI_RGB;
1075 lpDIBh->bmiHeader.biClrUsed = 0;
1076
1077 // These seem not needed for our purpose here.
1078 // lpDIBh->bmiHeader.biClrImportant = 0;
1079 // lpDIBh->bmiHeader.biXPelsPerMeter = 0;
1080 // lpDIBh->bmiHeader.biYPelsPerMeter = 0;
1081
1082 unsigned char *lpBits = (unsigned char *) malloc( width*height*3 );
1083 if( !lpBits )
1084 {
1085 wxFAIL_MSG( "could not allocate memory for DIB" );
1086 free( lpDIBh );
1087 return bitmap;
1088 }
1089
1090 unsigned char *data = GetData();
1091
1092 unsigned char *ptdata = data, *ptbits = lpBits;
1093 for( int i=0; i<width*height; i++ )
1094 {
1095 *(ptbits++) = *(ptdata+2);
1096 *(ptbits++) = *(ptdata+1);
1097 *(ptbits++) = *(ptdata );
1098 ptdata += 3;
1099 }
1100
1101 HDC hdc = ::GetDC(NULL);
1102
1103 HBITMAP hbitmap;
1104 hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
1105
1106 // The above line is equivalent to the following two lines.
1107 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
1108 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
1109 // or the following lines
1110 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
1111 // HDC memdc = ::CreateCompatibleDC( hdc );
1112 // ::SelectObject( memdc, hbitmap);
1113 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
1114 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
1115 // ::SelectObject( memdc, 0 );
1116 // ::DeleteDC( memdc );
1117
1118 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
1119
1120 if( HasMask() )
1121 {
1122 unsigned char r = GetMaskRed();
1123 unsigned char g = GetMaskGreen();
1124 unsigned char b = GetMaskBlue();
1125 unsigned char zero = 0, one = 255;
1126 ptdata = data;
1127 ptbits = lpBits;
1128 for( int i=0; i<width*height; i++ )
1129 {
1130 if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
1131 {
1132 *(ptbits++) = one;
1133 *(ptbits++) = one;
1134 *(ptbits++) = one;
1135 }
1136 else
1137 {
1138 *(ptbits++) = zero;
1139 *(ptbits++) = zero;
1140 *(ptbits++) = zero;
1141 }
1142 }
1143 hbitmap = ::CreateBitmap( (WORD)width, (WORD)height, 1, 1, NULL );
1144 ::SetDIBits( hdc, hbitmap, 0, (WORD)height, lpBits, lpDIBh, DIB_RGB_COLORS);
1145 wxMask *mask = new wxMask();
1146 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
1147 bitmap.SetMask( mask );
1148
1149 /* The following can also be used but is slow to run
1150 wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
1151 wxMask *mask = new wxMask( bitmap, colour );
1152 bitmap.SetMask( mask );
1153 */
1154 }
1155
1156 ::ReleaseDC(NULL, hdc);
1157 free(lpDIBh);
1158 free(lpBits);
1159
1160 if( bitmap.GetHBITMAP() )
1161 bitmap.SetOk( TRUE );
1162 else
1163 bitmap.SetOk( FALSE );
1164
1165 return bitmap;
1166 }
1167
1168
1169 wxImage::wxImage( const wxBitmap &bitmap )
1170 {
1171 if( !bitmap.Ok() )
1172 {
1173 wxFAIL_MSG( "invalid bitmap" );
1174 return;
1175 }
1176
1177 int width = bitmap.GetWidth();
1178 int height = bitmap.GetHeight();
1179 Create( width, height );
1180 unsigned char *data = GetData();
1181 if( !data )
1182 {
1183 wxFAIL_MSG( "could not allocate data for image" );
1184 return;
1185 }
1186
1187 int headersize = sizeof(BITMAPINFOHEADER);
1188 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
1189 if( !lpDIBh )
1190 {
1191 wxFAIL_MSG( "could not allocate data for DIB header" );
1192 free( data );
1193 return;
1194 }
1195
1196 // Fill in the DIB header
1197 lpDIBh->bmiHeader.biSize = headersize;
1198 lpDIBh->bmiHeader.biWidth = width;
1199 lpDIBh->bmiHeader.biHeight = -height;
1200 lpDIBh->bmiHeader.biSizeImage = width * height * 3;
1201
1202 lpDIBh->bmiHeader.biPlanes = 1;
1203 lpDIBh->bmiHeader.biBitCount = 24;
1204 lpDIBh->bmiHeader.biCompression = BI_RGB;
1205 lpDIBh->bmiHeader.biClrUsed = 0;
1206
1207 // These seem not needed for our purpose here.
1208 // lpDIBh->bmiHeader.biClrImportant = 0;
1209 // lpDIBh->bmiHeader.biXPelsPerMeter = 0;
1210 // lpDIBh->bmiHeader.biYPelsPerMeter = 0;
1211
1212 unsigned char *lpBits = (unsigned char *) malloc( width*height*3 );
1213 if( !lpBits )
1214 {
1215 wxFAIL_MSG( "could not allocate data for DIB" );
1216 free( data );
1217 free( lpDIBh );
1218 return;
1219 }
1220
1221 HBITMAP hbitmap;
1222 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
1223 HDC hdc = ::GetDC(NULL);
1224 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1225
1226 unsigned char *ptdata = data, *ptbits = lpBits;
1227 for( int i=0; i<width*height; i++ )
1228 {
1229 *(ptdata++) = *(ptbits+2);
1230 *(ptdata++) = *(ptbits+1);
1231 *(ptdata++) = *(ptbits );
1232 ptbits += 3;
1233 }
1234
1235 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
1236 {
1237 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
1238 HDC memdc = ::CreateCompatibleDC( hdc );
1239 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
1240 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
1241 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1242 ::DeleteDC( memdc );
1243 unsigned char r=16, g=16, b=16; // background set to RGB(16,16,16)
1244 ptdata = data;
1245 ptbits = lpBits;
1246 for( int i=0; i<width*height; i++ )
1247 {
1248 if( *ptbits != 0 )
1249 {
1250 *(ptdata++) = r;
1251 *(ptdata++) = g;
1252 *(ptdata++) = b;
1253 }
1254 ptbits += 3;
1255 }
1256 SetMaskColour( r, g, b );
1257 }
1258
1259 ::ReleaseDC(NULL, hdc);
1260 free(lpDIBh);
1261 free(lpBits);
1262 }
1263
1264 #endif
1265
1266 #ifdef __WXGTK__
1267
1268 #include "gtk/gtk.h"
1269 #include "gdk/gdk.h"
1270 #include "gdk/gdkx.h"
1271
1272 wxBitmap wxImage::ConvertToBitmap() const
1273 {
1274 wxBitmap bitmap;
1275
1276 wxCHECK_MSG( Ok(), bitmap, "invalid image" );
1277
1278 int width = GetWidth();
1279 int height = GetHeight();
1280
1281 bitmap.SetHeight( height );
1282 bitmap.SetWidth( width );
1283
1284 // Create picture
1285
1286 GdkImage *data_image =
1287 gdk_image_new( GDK_IMAGE_FASTEST, gdk_visual_get_system(), width, height );
1288
1289 bitmap.SetPixmap( gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, -1 ) );
1290
1291 // Create mask
1292
1293 GdkImage *mask_image = (GdkImage*) NULL;
1294
1295 if (HasMask())
1296 {
1297 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1298
1299 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1300
1301 wxMask *mask = new wxMask();
1302 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1303
1304 bitmap.SetMask( mask );
1305 }
1306
1307 // Retrieve depth
1308
1309 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
1310 if (visual == NULL) visual = gdk_window_get_visual( (GdkWindow*) &gdk_root_parent );
1311 int bpp = visual->depth;
1312
1313 bitmap.SetDepth( bpp );
1314
1315 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
1316 if (bpp < 8) bpp = 8;
1317
1318 // Render
1319
1320 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1321 byte_order b_o = RGB;
1322
1323 if (bpp >= 24)
1324 {
1325 GdkVisual *visual = gdk_visual_get_system();
1326 if ((visual->red_mask > visual->green_mask) && (visual->green_mask > visual->blue_mask)) b_o = RGB;
1327 else if ((visual->red_mask > visual->blue_mask) && (visual->blue_mask > visual->green_mask)) b_o = RGB;
1328 else if ((visual->blue_mask > visual->red_mask) && (visual->red_mask > visual->green_mask)) b_o = BRG;
1329 else if ((visual->blue_mask > visual->green_mask) && (visual->green_mask > visual->red_mask)) b_o = BGR;
1330 else if ((visual->green_mask > visual->red_mask) && (visual->red_mask > visual->blue_mask)) b_o = GRB;
1331 else if ((visual->green_mask > visual->blue_mask) && (visual->blue_mask > visual->red_mask)) b_o = GBR;
1332 }
1333
1334 int r_mask = GetMaskRed();
1335 int g_mask = GetMaskGreen();
1336 int b_mask = GetMaskBlue();
1337
1338 unsigned char* data = GetData();
1339
1340 int index = 0;
1341 for (int y = 0; y < height; y++)
1342 {
1343 for (int x = 0; x < width; x++)
1344 {
1345 int r = data[index];
1346 index++;
1347 int g = data[index];
1348 index++;
1349 int b = data[index];
1350 index++;
1351
1352 if (HasMask())
1353 {
1354 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1355 gdk_image_put_pixel( mask_image, x, y, 1 );
1356 else
1357 gdk_image_put_pixel( mask_image, x, y, 0 );
1358 }
1359
1360 switch (bpp)
1361 {
1362 case 8:
1363 {
1364 GdkColormap *cmap = gtk_widget_get_default_colormap();
1365 GdkColor *colors = cmap->colors;
1366 int max = 3 * (65536);
1367 int index = -1;
1368
1369 for (int i = 0; i < cmap->size; i++)
1370 {
1371 int rdiff = (r << 8) - colors[i].red;
1372 int gdiff = (g << 8) - colors[i].green;
1373 int bdiff = (b << 8) - colors[i].blue;
1374 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1375 if (sum < max) { index = i; max = sum; }
1376 }
1377
1378 gdk_image_put_pixel( data_image, x, y, index );
1379
1380 break;
1381 }
1382 case 15:
1383 {
1384 guint32 pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1385 gdk_image_put_pixel( data_image, x, y, pixel );
1386 break;
1387 }
1388 case 16:
1389 {
1390 guint32 pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1391 gdk_image_put_pixel( data_image, x, y, pixel );
1392 break;
1393 }
1394 case 32:
1395 case 24:
1396 {
1397 guint32 pixel = 0;
1398 switch (b_o)
1399 {
1400 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1401 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1402 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1403 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1404 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1405 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1406 }
1407 gdk_image_put_pixel( data_image, x, y, pixel );
1408 }
1409 default: break;
1410 }
1411 } // for
1412 } // for
1413
1414 // Blit picture
1415
1416 GdkGC *data_gc = gdk_gc_new( bitmap.GetPixmap() );
1417
1418 gdk_draw_image( bitmap.GetPixmap(), data_gc, data_image, 0, 0, 0, 0, width, height );
1419
1420 gdk_image_destroy( data_image );
1421 gdk_gc_unref( data_gc );
1422
1423 // Blit mask
1424
1425 if (HasMask())
1426 {
1427 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
1428
1429 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
1430
1431 gdk_image_destroy( mask_image );
1432 gdk_gc_unref( mask_gc );
1433 }
1434
1435 return bitmap;
1436 }
1437
1438 wxImage::wxImage( const wxBitmap &bitmap )
1439 {
1440 wxCHECK_RET( bitmap.Ok(), "invalid bitmap" );
1441
1442 GdkImage *gdk_image = gdk_image_get( bitmap.GetPixmap(),
1443 0, 0,
1444 bitmap.GetWidth(), bitmap.GetHeight() );
1445
1446 wxCHECK_RET( gdk_image, "couldn't create image" );
1447
1448 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1449 char unsigned *data = GetData();
1450
1451 if (!data)
1452 {
1453 gdk_image_destroy( gdk_image );
1454 wxFAIL_MSG( "couldn't create image" );
1455 return;
1456 }
1457
1458 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1459 if (bitmap.GetMask())
1460 {
1461 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1462 0, 0,
1463 bitmap.GetWidth(), bitmap.GetHeight() );
1464
1465 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1466 }
1467
1468 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
1469 if (visual == NULL) visual = gdk_window_get_visual( (GdkWindow*) &gdk_root_parent );
1470 int bpp = visual->depth;
1471 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
1472
1473 GdkColormap *cmap = gtk_widget_get_default_colormap();
1474
1475 long pos = 0;
1476 for (int j = 0; j < bitmap.GetHeight(); j++)
1477 {
1478 for (int i = 0; i < bitmap.GetWidth(); i++)
1479 {
1480 int pixel = gdk_image_get_pixel( gdk_image, i, j );
1481 if (bpp <= 8)
1482 {
1483 data[pos] = cmap->colors[pixel].red >> 8;
1484 data[pos+1] = cmap->colors[pixel].green >> 8;
1485 data[pos+2] = cmap->colors[pixel].blue >> 8;
1486 } else if (bpp == 15)
1487 {
1488 data[pos] = (pixel >> 7) & 0xf8;
1489 data[pos+1] = (pixel >> 2) & 0xf8;
1490 data[pos+2] = (pixel << 3) & 0xf8;
1491 } else if (bpp == 16)
1492 {
1493 data[pos] = (pixel >> 8) & 0xf8;
1494 data[pos+1] = (pixel >> 3) & 0xfc;
1495 data[pos+2] = (pixel << 3) & 0xf8;
1496 } else
1497 {
1498 data[pos] = (pixel >> 16) & 0xff;
1499 data[pos+1] = (pixel >> 8) & 0xff;
1500 data[pos+2] = pixel & 0xff;
1501 }
1502
1503 if (gdk_image_mask)
1504 {
1505 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1506 if (mask_pixel == 0)
1507 {
1508 data[pos] = 16;
1509 data[pos+1] = 16;
1510 data[pos+2] = 16;
1511 }
1512 }
1513
1514 pos += 3;
1515 }
1516 }
1517
1518 gdk_image_destroy( gdk_image );
1519 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1520 }
1521
1522 #endif