]> git.saurik.com Git - wxWidgets.git/blame - src/common/image.cpp
no message
[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 29
2432b92d
JS
30#ifdef __WXMSW__
31#include <windows.h>
32#endif
33
01111366
RR
34//-----------------------------------------------------------------------------
35// wxImage
36//-----------------------------------------------------------------------------
37
38class wxImageRefData: public wxObjectRefData
39{
fd0eed64
RR
40
41public:
42 wxImageRefData(void);
43 ~wxImageRefData(void);
01111366 44
fd0eed64
RR
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;
01111366
RR
51};
52
53wxImageRefData::wxImageRefData(void)
54{
fd0eed64
RR
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;
01111366
RR
63}
64
65wxImageRefData::~wxImageRefData(void)
66{
fd0eed64 67 if (m_data) free( m_data );
01111366
RR
68}
69
70wxList wxImage::sm_handlers;
71
72//-----------------------------------------------------------------------------
73
74#define M_IMGDATA ((wxImageRefData *)m_refData)
75
76#if !USE_SHARED_LIBRARIES
77IMPLEMENT_DYNAMIC_CLASS(wxImage, wxObject)
78#endif
79
80wxImage::wxImage()
81{
82}
83
84wxImage::wxImage( int width, int height )
85{
fd0eed64 86 Create( width, height );
01111366
RR
87}
88
89wxImage::wxImage( const wxString& name, long type )
90{
fd0eed64 91 LoadFile( name, type );
01111366
RR
92}
93
94wxImage::wxImage( const wxImage& image )
95{
fd0eed64 96 Ref(image);
01111366
RR
97}
98
99wxImage::wxImage( const wxImage* image )
100{
fd0eed64 101 if (image) Ref(*image);
01111366
RR
102}
103
104void wxImage::Create( int width, int height )
105{
fd0eed64 106 m_refData = new wxImageRefData();
01111366 107
fd0eed64
RR
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;
01111366 112
fd0eed64
RR
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 }
01111366
RR
121}
122
123void wxImage::Destroy()
124{
fd0eed64 125 UnRef();
01111366
RR
126}
127
4bc67cc5
RR
128wxImage 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
ef539066
RR
163void 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
179unsigned 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
193unsigned 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
207unsigned 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
01111366
RR
221bool wxImage::Ok() const
222{
fd0eed64 223 return (M_IMGDATA && M_IMGDATA->m_ok);
01111366
RR
224}
225
226char unsigned *wxImage::GetData() const
227{
4bc67cc5 228 wxCHECK_MSG( Ok(), (char unsigned *)NULL, "invalid image" );
01111366 229
fd0eed64 230 return M_IMGDATA->m_data;
01111366
RR
231}
232
233void wxImage::SetData( char unsigned *WXUNUSED(data) )
234{
4bc67cc5 235 wxCHECK_RET( Ok(), "invalid image" );
01111366
RR
236}
237
238void wxImage::SetMaskColour( unsigned char r, unsigned char g, unsigned char b )
239{
4bc67cc5 240 wxCHECK_RET( Ok(), "invalid image" );
01111366 241
fd0eed64
RR
242 M_IMGDATA->m_maskRed = r;
243 M_IMGDATA->m_maskGreen = g;
244 M_IMGDATA->m_maskBlue = b;
245 M_IMGDATA->m_hasMask = TRUE;
01111366
RR
246}
247
248unsigned char wxImage::GetMaskRed() const
249{
4bc67cc5 250 wxCHECK_MSG( Ok(), 0, "invalid image" );
01111366 251
fd0eed64 252 return M_IMGDATA->m_maskRed;
01111366
RR
253}
254
255unsigned char wxImage::GetMaskGreen() const
256{
4bc67cc5 257 wxCHECK_MSG( Ok(), 0, "invalid image" );
fd0eed64
RR
258
259 return M_IMGDATA->m_maskGreen;
01111366
RR
260}
261
262unsigned char wxImage::GetMaskBlue() const
263{
4bc67cc5 264 wxCHECK_MSG( Ok(), 0, "invalid image" );
01111366 265
fd0eed64 266 return M_IMGDATA->m_maskBlue;
01111366
RR
267}
268
269void wxImage::SetMask( bool mask )
270{
4bc67cc5 271 wxCHECK_RET( Ok(), "invalid image" );
01111366 272
fd0eed64 273 M_IMGDATA->m_hasMask = mask;
01111366
RR
274}
275
276bool wxImage::HasMask() const
277{
4bc67cc5 278 wxCHECK_MSG( Ok(), FALSE, "invalid image" );
01111366 279
fd0eed64 280 return M_IMGDATA->m_hasMask;
01111366
RR
281}
282
283int wxImage::GetWidth() const
284{
4bc67cc5
RR
285 wxCHECK_MSG( Ok(), 0, "invalid image" );
286
287 return M_IMGDATA->m_width;
01111366
RR
288}
289
290int wxImage::GetHeight() const
291{
4bc67cc5
RR
292 wxCHECK_MSG( Ok(), 0, "invalid image" );
293
294 return M_IMGDATA->m_height;
01111366
RR
295}
296
297bool wxImage::LoadFile( const wxString& filename, long type )
298{
fd0eed64 299 UnRef();
dc86cb34 300
fd0eed64
RR
301 if (!wxFileExists(filename))
302 {
303 wxLogWarning( "Image file does not exist." );
dc86cb34 304
fd0eed64
RR
305 return FALSE;
306 }
01111366 307
fd0eed64 308 m_refData = new wxImageRefData;
01111366 309
fd0eed64 310 wxImageHandler *handler = FindHandler(type);
01111366 311
fd0eed64
RR
312 if (handler == NULL)
313 {
314 wxLogWarning( "No image handler for type %d defined.", type );
01111366 315
fd0eed64
RR
316 return FALSE;
317 }
01111366 318
fd0eed64 319 return handler->LoadFile( this, filename );
01111366
RR
320}
321
322bool wxImage::SaveFile( const wxString& filename, int type )
323{
4bc67cc5
RR
324 wxCHECK_MSG( Ok(), FALSE, "invalid image" );
325
fd0eed64 326 wxImageHandler *handler = FindHandler(type);
01111366 327
fd0eed64
RR
328 if (handler == NULL)
329 {
330 wxLogWarning( "No image handler for type %d defined.", type );
01111366 331
fd0eed64
RR
332 return FALSE;
333 }
01111366 334
fd0eed64 335 return handler->SaveFile( this, filename );
01111366
RR
336}
337
338void wxImage::AddHandler( wxImageHandler *handler )
339{
340 sm_handlers.Append( handler );
341}
342
343void wxImage::InsertHandler( wxImageHandler *handler )
344{
345 sm_handlers.Insert( handler );
346}
347
348bool wxImage::RemoveHandler( const wxString& name )
349{
fd0eed64
RR
350 wxImageHandler *handler = FindHandler(name);
351 if (handler)
352 {
353 sm_handlers.DeleteObject(handler);
354 return TRUE;
355 }
356 else
357 return FALSE;
01111366
RR
358}
359
360wxImageHandler *wxImage::FindHandler( const wxString& name )
361{
fd0eed64
RR
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;
01111366
RR
370}
371
372wxImageHandler *wxImage::FindHandler( const wxString& extension, long bitmapType )
373{
fd0eed64
RR
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;
01111366
RR
384}
385
386wxImageHandler *wxImage::FindHandler( long bitmapType )
387{
fd0eed64
RR
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
398void wxImage::InitStandardHandlers()
399{
400 AddHandler( new wxBMPHandler );
ac57418f 401#ifdef wxUSE_LIBPNG
fd0eed64 402 AddHandler( new wxPNGHandler );
ac57418f 403#endif
01111366
RR
404}
405
406void wxImage::CleanUpHandlers()
407{
fd0eed64
RR
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 }
01111366
RR
417}
418
419//-----------------------------------------------------------------------------
420// wxImageHandler
421//-----------------------------------------------------------------------------
422
423#if !USE_SHARED_LIBRARIES
424IMPLEMENT_DYNAMIC_CLASS(wxImageHandler,wxObject)
425#endif
426
427bool wxImageHandler::LoadFile( wxImage *WXUNUSED(image), const wxString& WXUNUSED(name) )
428{
fd0eed64 429 return FALSE;
01111366
RR
430}
431
432bool wxImageHandler::SaveFile( wxImage *WXUNUSED(image), const wxString& WXUNUSED(name) )
433{
fd0eed64 434 return FALSE;
01111366
RR
435}
436
437//-----------------------------------------------------------------------------
438// wxPNGHandler
439//-----------------------------------------------------------------------------
440
ac57418f
RR
441#ifdef wxUSE_LIBPNG
442
01111366
RR
443#if !USE_SHARED_LIBRARIES
444IMPLEMENT_DYNAMIC_CLASS(wxPNGHandler,wxImageHandler)
445#endif
446
447bool wxPNGHandler::LoadFile( wxImage *image, const wxString& name )
448{
702ca7c0 449 image->Destroy();
01111366 450
702ca7c0
RR
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 }
01111366 473
702ca7c0
RR
474 FILE *f = fopen( name, "rb" );
475 png_init_io( png_ptr, f );
01111366 476
702ca7c0
RR
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 );
01111366 482
702ca7c0 483 if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_expand( png_ptr );
01111366 484
702ca7c0
RR
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 );
01111366 489
702ca7c0 490 image->Create( width, height );
01111366 491
702ca7c0
RR
492 if (!image->Ok())
493 {
494 png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL );
495 return FALSE;
496 }
01111366 497
702ca7c0
RR
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 }
01111366 505
702ca7c0
RR
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 }
01111366 517
702ca7c0
RR
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 {
01111366 526 for (unsigned int y = 0; y < height; y++)
702ca7c0
RR
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 {
01111366 551 for (unsigned int y = 0; y < height; y++)
702ca7c0
RR
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 i = 0; i < height; i++) free( lines[i] );
579 free( lines );
580
581 if (transp)
582 {
583 image->SetMaskColour( 255, 0, 255 );
584 }
585 else
586 {
587 image->SetMask( FALSE );
588 }
01111366 589
702ca7c0 590 return TRUE;
01111366
RR
591}
592
593
594bool wxPNGHandler::SaveFile( wxImage *image, const wxString& name )
595{
702ca7c0
RR
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);
01111366
RR
601 if (!png_ptr)
602 {
702ca7c0
RR
603 fclose( f );
604 return FALSE;
01111366
RR
605 }
606
607 png_infop info_ptr = png_create_info_struct(png_ptr);
608 if (info_ptr == NULL)
609 {
702ca7c0
RR
610 fclose(f);
611 png_destroy_write_struct( &png_ptr, (png_infopp) NULL );
612 return FALSE;
01111366
RR
613 }
614
615 if (setjmp(png_ptr->jmpbuf))
616 {
702ca7c0
RR
617 fclose( f );
618 png_destroy_write_struct( &png_ptr, (png_infopp) NULL );
619 return FALSE;
01111366
RR
620 }
621
622 png_init_io( png_ptr, f );
623 png_set_IHDR( png_ptr, info_ptr, image->GetWidth(), image->GetHeight(), 8,
702ca7c0 624 PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
01111366 625 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
702ca7c0 626
01111366
RR
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 {
702ca7c0
RR
640 fclose( f );
641 png_destroy_write_struct( &png_ptr, (png_infopp) NULL );
642 return FALSE;
01111366
RR
643 }
644
645 for (int y = 0; y < image->GetHeight(); y++)
646 {
702ca7c0
RR
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 );
01111366 666 }
702ca7c0 667
01111366
RR
668 free(data);
669 png_write_end( png_ptr, info_ptr );
702ca7c0 670 png_destroy_write_struct( &png_ptr, (png_infopp) NULL );
01111366
RR
671
672 fclose(f);
702ca7c0
RR
673
674 return TRUE;
01111366
RR
675}
676
ac57418f
RR
677#endif
678
679 // wxUSE_LIBPNG
680
01111366
RR
681//-----------------------------------------------------------------------------
682// wxBMPHandler
683//-----------------------------------------------------------------------------
684
685#if !USE_SHARED_LIBRARIES
686IMPLEMENT_DYNAMIC_CLASS(wxBMPHandler,wxImageHandler)
687#endif
688
689bool 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;
e3554471 695 unsigned char aByte;
01111366
RR
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;
0b4f9ee3 705#ifndef BI_RGB
01111366
RR
706#define BI_RGB 0
707#define BI_RLE8 1
708#define BI_RLE4 2
62448488
JS
709#endif
710
711#ifndef BI_BITFIELDS
01111366 712#define BI_BITFIELDS 3
0b4f9ee3 713#endif
01111366
RR
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 {
06cfab17 738 wxLogError( "Image width > 32767 pixels for file\n" );
01111366
RR
739 fclose(file);
740 return FALSE;
741 }
742 if (height > 32767)
743 {
06cfab17 744 wxLogError( "Image height > 32767 pixels for file\n" );
01111366
RR
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 {
06cfab17 754 wxLogError( "unknown bitdepth in file\n" );
01111366
RR
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 {
06cfab17 762 wxLogError( "unknown encoding in Windows BMP file\n" );
01111366
RR
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 {
06cfab17 773 wxLogError( "encoding of BMP doesn't match bitdepth\n" );
01111366
RR
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 {
06cfab17 783 wxLogError( "Cannot allocate RAM for color map in BMP file\n" );
01111366
RR
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 {
06cfab17 795 wxLogError( "Cannot allocate RAM for RGB data in file\n" );
01111366
RR
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++;
e3554471 892 aByte = getc(file);
01111366
RR
893 if (bpp == 1)
894 {
895 int bit = 0;
896
897 for (bit = 0; bit < 8; bit++)
898 {
e3554471 899 index = ((aByte & (0x80 >> bit)) ? 1 : 0);
01111366
RR
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 {
06cfab17 910 wxLogError( "can't deal with 4bit encoded yet.\n");
01111366
RR
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 {
e3554471 921 index = ((aByte & (0xF0 >> nibble * 4)) >> (!nibble * 4));
01111366
RR
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
e3554471
JS
937 first = aByte;
938 aByte = getc(file);
01111366
RR
939 if (first == 0)
940 {
e3554471 941 if (aByte == 0)
01111366
RR
942 {
943/* column = width; */
944 }
e3554471 945 else if (aByte == 1)
01111366
RR
946 {
947 column = width;
948 line = -1;
949 }
e3554471 950 else if (aByte == 2)
01111366 951 {
e3554471
JS
952 aByte = getc(file);
953 column += aByte;
01111366 954 linepos = column * bpp / 8;
e3554471
JS
955 aByte = getc(file);
956 line += aByte;
01111366
RR
957 }
958 else
959 {
e3554471 960 int absolute = aByte;
01111366
RR
961
962 for (i = 0; i < absolute; i++)
963 {
df875e59 964 linepos++;
e3554471
JS
965 aByte = getc(file);
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 }
971 if (absolute & 0x01)
e3554471 972 aByte = getc(file);
01111366
RR
973 }
974 }
975 else
976 {
977 for (i = 0; i < first; i++)
978 {
e3554471
JS
979 ptr[poffset] = cmap[aByte].r;
980 ptr[poffset + 1] = cmap[aByte].g;
981 ptr[poffset + 2] = cmap[aByte].b;
01111366
RR
982 column++;
983 linepos++;
984 }
985 }
986 }
987 else
988 {
e3554471
JS
989 ptr[poffset] = cmap[aByte].r;
990 ptr[poffset + 1] = cmap[aByte].g;
991 ptr[poffset + 2] = cmap[aByte].b;
01111366
RR
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 {
e3554471 1034 int temp = fread(&aByte, 1, 1, file);
01111366
RR
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
e3554471
JS
1049#ifdef __WXMSW__
1050
1051wxBitmap 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) )
e3554471
JS
1131 {
1132 *(ptbits++) = one;
1133 *(ptbits++) = one;
1134 *(ptbits++) = one;
1135 }
650368d0
UA
1136 else
1137 {
1138 *(ptbits++) = zero;
1139 *(ptbits++) = zero;
1140 *(ptbits++) = zero;
1141 }
e3554471
JS
1142 }
1143 hbitmap = ::CreateBitmap( (WORD)width, (WORD)height, 1, 1, NULL );
1144 ::SetDIBits( hdc, hbitmap, 0, (WORD)height, lpBits, lpDIBh, DIB_RGB_COLORS);
650368d0
UA
1145 wxMask *mask = new wxMask();
1146 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
1147 bitmap.SetMask( mask );
e3554471
JS
1148
1149/* The following can also be used but is slow to run
1150 wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
650368d0
UA
1151 wxMask *mask = new wxMask( bitmap, colour );
1152 bitmap.SetMask( mask );
e3554471
JS
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
1169wxImage::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
99c67c77
RR
1266#ifdef __WXGTK__
1267
83624f79
RR
1268#include "gtk/gtk.h"
1269#include "gdk/gdk.h"
1270#include "gdk/gdkx.h"
1271
99c67c77
RR
1272wxBitmap 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;
06cfab17
RR
1312
1313 bitmap.SetDepth( bpp );
1314
99c67c77
RR
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
1438wxImage::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