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