]> git.saurik.com Git - wxWidgets.git/blame - src/common/image.cpp
wxWindow::Fit() infinite loop bug fixed
[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"
f6fcbb63 25#include "wx/app.h"
dc86cb34 26#include "wx/filefn.h"
3d05544e 27#include "wx/wfstream.h"
b75867a6 28#include "wx/intl.h"
a91b47e8 29#include "wx/module.h"
01111366 30
58a8ab88
JS
31// For memcpy
32#include <string.h>
33
a3ef5bf5
JS
34#ifdef __SALFORDC__
35#ifdef FAR
36#undef FAR
37#endif
38#endif
39
2432b92d
JS
40#ifdef __WXMSW__
41#include <windows.h>
42#endif
43
01111366
RR
44//-----------------------------------------------------------------------------
45// wxImage
46//-----------------------------------------------------------------------------
47
48class wxImageRefData: public wxObjectRefData
49{
c7abc967 50
fd0eed64 51public:
dbda9e86
JS
52 wxImageRefData(void);
53 ~wxImageRefData(void);
c7abc967 54
dbda9e86
JS
55 int m_width;
56 int m_height;
57 unsigned char *m_data;
58 bool m_hasMask;
59 unsigned char m_maskRed,m_maskGreen,m_maskBlue;
60 bool m_ok;
01111366
RR
61};
62
63wxImageRefData::wxImageRefData(void)
64{
fd0eed64
RR
65 m_width = 0;
66 m_height = 0;
67 m_data = (unsigned char*) NULL;
68 m_ok = FALSE;
69 m_maskRed = 0;
70 m_maskGreen = 0;
71 m_maskBlue = 0;
72 m_hasMask = FALSE;
01111366
RR
73}
74
75wxImageRefData::~wxImageRefData(void)
76{
fd0eed64 77 if (m_data) free( m_data );
01111366
RR
78}
79
80wxList wxImage::sm_handlers;
81
82//-----------------------------------------------------------------------------
83
84#define M_IMGDATA ((wxImageRefData *)m_refData)
85
86#if !USE_SHARED_LIBRARIES
87IMPLEMENT_DYNAMIC_CLASS(wxImage, wxObject)
88#endif
89
90wxImage::wxImage()
91{
92}
93
94wxImage::wxImage( int width, int height )
95{
fd0eed64 96 Create( width, height );
01111366
RR
97}
98
99wxImage::wxImage( const wxString& name, long type )
100{
fd0eed64 101 LoadFile( name, type );
01111366
RR
102}
103
9e9ee68e
VS
104wxImage::wxImage( const wxString& name, const wxString& mimetype )
105{
106 LoadFile( name, mimetype );
107}
108
e02afc7a 109#if wxUSE_STREAMS
3d05544e
JS
110wxImage::wxImage( wxInputStream& stream, long type )
111{
112 LoadFile( stream, type );
113}
9e9ee68e
VS
114
115wxImage::wxImage( wxInputStream& stream, const wxString& mimetype )
116{
117 LoadFile( stream, mimetype );
118}
e02afc7a 119#endif // wxUSE_STREAMS
3d05544e 120
4698648f
VZ
121wxImage::wxImage( const wxImage& image )
122{
123 Ref(image);
01111366
RR
124}
125
4698648f
VZ
126wxImage::wxImage( const wxImage* image )
127{
128 if (image) Ref(*image);
01111366
RR
129}
130
131void wxImage::Create( int width, int height )
132{
fd0eed64 133 m_refData = new wxImageRefData();
c7abc967 134
fd0eed64
RR
135 M_IMGDATA->m_data = (unsigned char *) malloc( width*height*3 );
136 if (M_IMGDATA->m_data)
137 {
138 for (int l = 0; l < width*height*3; l++) M_IMGDATA->m_data[l] = 0;
c7abc967 139
fd0eed64
RR
140 M_IMGDATA->m_width = width;
141 M_IMGDATA->m_height = height;
142 M_IMGDATA->m_ok = TRUE;
143 }
144 else
145 {
146 UnRef();
147 }
01111366
RR
148}
149
150void wxImage::Destroy()
151{
fd0eed64 152 UnRef();
01111366
RR
153}
154
4bc67cc5
RR
155wxImage wxImage::Scale( int width, int height )
156{
157 wxImage image;
c7abc967 158
50920146 159 wxCHECK_MSG( Ok(), image, _T("invalid image") );
c7abc967 160
50920146 161 wxCHECK_MSG( (width > 0) && (height > 0), image, _T("invalid image size") );
c7abc967 162
4bc67cc5 163 image.Create( width, height );
c7abc967 164
4bc67cc5 165 char unsigned *data = image.GetData();
c7abc967 166
50920146 167 wxCHECK_MSG( data, image, _T("unable to create image") );
c7abc967 168
4bc67cc5
RR
169 if (M_IMGDATA->m_hasMask)
170 image.SetMaskColour( M_IMGDATA->m_maskRed, M_IMGDATA->m_maskGreen, M_IMGDATA->m_maskBlue );
c7abc967 171
6e13c196
RR
172 long old_height = M_IMGDATA->m_height;
173 long old_width = M_IMGDATA->m_width;
c7abc967 174
6e13c196
RR
175 char unsigned *source_data = M_IMGDATA->m_data;
176 char unsigned *target_data = data;
c7abc967 177
6e13c196 178 for (long j = 0; j < height; j++)
4bc67cc5 179 {
6e13c196 180 long y_offset = (j * old_height / height) * old_width;
c7abc967 181
6e13c196 182 for (long i = 0; i < width; i++)
4698648f 183 {
c7abc967
VZ
184 memcpy( target_data,
185 source_data + 3*(y_offset + ((i * old_width )/ width)),
dbda9e86 186 3 );
6e13c196 187 target_data += 3;
4698648f 188 }
4bc67cc5 189 }
c7abc967 190
4bc67cc5
RR
191 return image;
192}
4698648f 193
ef539066
RR
194void wxImage::SetRGB( int x, int y, unsigned char r, unsigned char g, unsigned char b )
195{
50920146 196 wxCHECK_RET( Ok(), _T("invalid image") );
c7abc967 197
ef539066
RR
198 int w = M_IMGDATA->m_width;
199 int h = M_IMGDATA->m_height;
c7abc967 200
50920146 201 wxCHECK_RET( (x>=0) && (y>=0) && (x<w) && (y<h), _T("invalid image index") );
c7abc967 202
ef539066 203 long pos = (y * w + x) * 3;
c7abc967 204
ef539066
RR
205 M_IMGDATA->m_data[ pos ] = r;
206 M_IMGDATA->m_data[ pos+1 ] = g;
207 M_IMGDATA->m_data[ pos+2 ] = b;
208}
209
210unsigned char wxImage::GetRed( int x, int y )
211{
50920146 212 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
c7abc967 213
ef539066
RR
214 int w = M_IMGDATA->m_width;
215 int h = M_IMGDATA->m_height;
c7abc967 216
50920146 217 wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, _T("invalid image index") );
c7abc967 218
ef539066 219 long pos = (y * w + x) * 3;
c7abc967 220
ef539066
RR
221 return M_IMGDATA->m_data[pos];
222}
223
224unsigned char wxImage::GetGreen( int x, int y )
225{
50920146 226 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
c7abc967 227
ef539066
RR
228 int w = M_IMGDATA->m_width;
229 int h = M_IMGDATA->m_height;
c7abc967 230
50920146 231 wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, _T("invalid image index") );
c7abc967 232
ef539066 233 long pos = (y * w + x) * 3;
c7abc967 234
ef539066
RR
235 return M_IMGDATA->m_data[pos+1];
236}
237
238unsigned char wxImage::GetBlue( int x, int y )
239{
50920146 240 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
c7abc967 241
ef539066
RR
242 int w = M_IMGDATA->m_width;
243 int h = M_IMGDATA->m_height;
c7abc967 244
50920146 245 wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, _T("invalid image index") );
c7abc967 246
ef539066 247 long pos = (y * w + x) * 3;
c7abc967 248
ef539066
RR
249 return M_IMGDATA->m_data[pos+2];
250}
4698648f
VZ
251
252bool wxImage::Ok() const
253{
254 return (M_IMGDATA && M_IMGDATA->m_ok);
01111366
RR
255}
256
257char unsigned *wxImage::GetData() const
258{
50920146 259 wxCHECK_MSG( Ok(), (char unsigned *)NULL, _T("invalid image") );
c7abc967 260
fd0eed64 261 return M_IMGDATA->m_data;
01111366
RR
262}
263
58a8ab88 264void wxImage::SetData( char unsigned *data )
01111366 265{
50920146 266 wxCHECK_RET( Ok(), _T("invalid image") );
58a8ab88
JS
267
268 memcpy(M_IMGDATA->m_data, data, M_IMGDATA->m_width * M_IMGDATA->m_height * 3);
01111366
RR
269}
270
271void wxImage::SetMaskColour( unsigned char r, unsigned char g, unsigned char b )
272{
50920146 273 wxCHECK_RET( Ok(), _T("invalid image") );
c7abc967 274
fd0eed64
RR
275 M_IMGDATA->m_maskRed = r;
276 M_IMGDATA->m_maskGreen = g;
277 M_IMGDATA->m_maskBlue = b;
278 M_IMGDATA->m_hasMask = TRUE;
01111366
RR
279}
280
281unsigned char wxImage::GetMaskRed() const
282{
50920146 283 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
c7abc967 284
fd0eed64 285 return M_IMGDATA->m_maskRed;
01111366
RR
286}
287
288unsigned char wxImage::GetMaskGreen() const
289{
50920146 290 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
c7abc967 291
fd0eed64 292 return M_IMGDATA->m_maskGreen;
01111366
RR
293}
294
295unsigned char wxImage::GetMaskBlue() const
296{
50920146 297 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
c7abc967 298
fd0eed64 299 return M_IMGDATA->m_maskBlue;
01111366 300}
4698648f 301
01111366
RR
302void wxImage::SetMask( bool mask )
303{
50920146 304 wxCHECK_RET( Ok(), _T("invalid image") );
c7abc967 305
fd0eed64 306 M_IMGDATA->m_hasMask = mask;
01111366
RR
307}
308
309bool wxImage::HasMask() const
310{
50920146 311 wxCHECK_MSG( Ok(), FALSE, _T("invalid image") );
c7abc967 312
fd0eed64 313 return M_IMGDATA->m_hasMask;
01111366
RR
314}
315
4698648f
VZ
316int wxImage::GetWidth() const
317{
50920146 318 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
c7abc967 319
4698648f 320 return M_IMGDATA->m_width;
01111366
RR
321}
322
4698648f
VZ
323int wxImage::GetHeight() const
324{
50920146 325 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
c7abc967 326
4698648f 327 return M_IMGDATA->m_height;
01111366
RR
328}
329
330bool wxImage::LoadFile( const wxString& filename, long type )
331{
e02afc7a 332#if wxUSE_STREAMS
3d05544e 333 if (wxFileExists(filename))
fd0eed64 334 {
3d05544e
JS
335 wxFileInputStream stream(filename);
336 return LoadFile(stream, type);
337 }
9e9ee68e
VS
338
339 else {
50920146 340 wxLogError( _T("Can't load image from file '%s': file does not exist."), filename.c_str() );
9e9ee68e
VS
341
342 return FALSE;
343 }
344#else // !wxUSE_STREAMS
345 return FALSE;
346#endif // wxUSE_STREAMS
347}
348
349bool wxImage::LoadFile( const wxString& filename, const wxString& mimetype )
350{
351#if wxUSE_STREAMS
352 if (wxFileExists(filename))
353 {
354 wxFileInputStream stream(filename);
355 return LoadFile(stream, mimetype);
356 }
c7abc967 357
3d05544e 358 else {
50920146 359 wxLogError( _T("Can't load image from file '%s': file does not exist."), filename.c_str() );
c7abc967 360
fd0eed64
RR
361 return FALSE;
362 }
e02afc7a 363#else // !wxUSE_STREAMS
dbda9e86 364 return FALSE;
e02afc7a 365#endif // wxUSE_STREAMS
1ccbb61a
VZ
366}
367
368bool wxImage::SaveFile( const wxString& filename, int type )
369{
e02afc7a 370#if wxUSE_STREAMS
1ccbb61a 371 wxFileOutputStream stream(filename);
9e9ee68e 372
1ccbb61a
VZ
373 if ( stream.LastError() == wxStream_NOERROR )
374 return SaveFile(stream, type);
375 else
e02afc7a 376#endif // wxUSE_STREAMS
1ccbb61a 377 return FALSE;
3d05544e 378}
01111366 379
9e9ee68e
VS
380bool wxImage::SaveFile( const wxString& filename, const wxString& mimetype )
381{
382#if wxUSE_STREAMS
383 wxFileOutputStream stream(filename);
c7abc967 384
9e9ee68e
VS
385 if ( stream.LastError() == wxStream_NOERROR )
386 return SaveFile(stream, mimetype);
387 else
388#endif // wxUSE_STREAMS
389 return FALSE;
390}
391
e02afc7a 392#if wxUSE_STREAMS
3d05544e
JS
393bool wxImage::LoadFile( wxInputStream& stream, long type )
394{
395 UnRef();
c7abc967 396
fd0eed64 397 m_refData = new wxImageRefData;
c7abc967 398
fd0eed64 399 wxImageHandler *handler = FindHandler(type);
c7abc967 400
4698648f 401 if (handler == NULL)
fd0eed64 402 {
50920146 403 wxLogWarning( _T("No image handler for type %d defined."), type );
c7abc967 404
fd0eed64
RR
405 return FALSE;
406 }
c7abc967 407
3d05544e 408 return handler->LoadFile( this, stream );
01111366
RR
409}
410
9e9ee68e
VS
411bool wxImage::LoadFile( wxInputStream& stream, const wxString& mimetype )
412{
413 UnRef();
414
415 m_refData = new wxImageRefData;
416
417 wxImageHandler *handler = FindHandlerMime(mimetype);
418
419 if (handler == NULL)
420 {
50920146 421 wxLogWarning( _T("No image handler for type %s defined."), mimetype.GetData() );
9e9ee68e
VS
422
423 return FALSE;
424 }
425
426 return handler->LoadFile( this, stream );
427}
428
3d05544e 429bool wxImage::SaveFile( wxOutputStream& stream, int type )
01111366 430{
50920146 431 wxCHECK_MSG( Ok(), FALSE, _T("invalid image") );
c7abc967 432
fd0eed64 433 wxImageHandler *handler = FindHandler(type);
c7abc967 434
4698648f 435 if (handler == NULL)
fd0eed64 436 {
50920146 437 wxLogWarning( _T("No image handler for type %d defined."), type );
9e9ee68e
VS
438
439 return FALSE;
440 }
441
442 return handler->SaveFile( this, stream );
443}
444
445bool wxImage::SaveFile( wxOutputStream& stream, const wxString& mimetype )
446{
50920146 447 wxCHECK_MSG( Ok(), FALSE, _T("invalid image") );
c7abc967 448
9e9ee68e 449 wxImageHandler *handler = FindHandlerMime(mimetype);
c7abc967 450
9e9ee68e
VS
451 if (handler == NULL)
452 {
50920146 453 wxLogWarning( _T("No image handler for type %s defined."), mimetype.GetData() );
c7abc967 454
dbda9e86 455 return FALSE;
fd0eed64 456 }
c7abc967 457
3d05544e 458 return handler->SaveFile( this, stream );
01111366 459}
e02afc7a 460#endif // wxUSE_STREAMS
01111366
RR
461
462void wxImage::AddHandler( wxImageHandler *handler )
463{
4698648f
VZ
464 // make sure that the memory will be freed at the program end
465 sm_handlers.DeleteContents(TRUE);
c7abc967 466
01111366
RR
467 sm_handlers.Append( handler );
468}
469
470void wxImage::InsertHandler( wxImageHandler *handler )
471{
4698648f
VZ
472 // make sure that the memory will be freed at the program end
473 sm_handlers.DeleteContents(TRUE);
c7abc967 474
01111366
RR
475 sm_handlers.Insert( handler );
476}
477
478bool wxImage::RemoveHandler( const wxString& name )
479{
fd0eed64
RR
480 wxImageHandler *handler = FindHandler(name);
481 if (handler)
482 {
483 sm_handlers.DeleteObject(handler);
484 return TRUE;
485 }
486 else
487 return FALSE;
01111366
RR
488}
489
490wxImageHandler *wxImage::FindHandler( const wxString& name )
491{
fd0eed64
RR
492 wxNode *node = sm_handlers.First();
493 while (node)
494 {
495 wxImageHandler *handler = (wxImageHandler*)node->Data();
ce3ed50d 496 if (handler->GetName().Cmp(name) == 0) return handler;
c7abc967 497
fd0eed64
RR
498 node = node->Next();
499 }
500 return (wxImageHandler *)NULL;
01111366
RR
501}
502
503wxImageHandler *wxImage::FindHandler( const wxString& extension, long bitmapType )
504{
fd0eed64
RR
505 wxNode *node = sm_handlers.First();
506 while (node)
507 {
508 wxImageHandler *handler = (wxImageHandler*)node->Data();
ce3ed50d 509 if ( (handler->GetExtension().Cmp(extension) == 0) &&
fd0eed64 510 (bitmapType == -1 || handler->GetType() == bitmapType) )
dbda9e86 511 return handler;
fd0eed64
RR
512 node = node->Next();
513 }
514 return (wxImageHandler*)NULL;
01111366
RR
515}
516
517wxImageHandler *wxImage::FindHandler( long bitmapType )
518{
fd0eed64
RR
519 wxNode *node = sm_handlers.First();
520 while (node)
521 {
522 wxImageHandler *handler = (wxImageHandler *)node->Data();
523 if (handler->GetType() == bitmapType) return handler;
524 node = node->Next();
525 }
526 return NULL;
527}
528
9e9ee68e
VS
529wxImageHandler *wxImage::FindHandlerMime( const wxString& mimetype )
530{
531 wxNode *node = sm_handlers.First();
532 while (node)
533 {
534 wxImageHandler *handler = (wxImageHandler *)node->Data();
535 if (handler->GetMimeType().IsSameAs(mimetype, FALSE)) return handler;
536 node = node->Next();
537 }
538 return NULL;
539}
540
fd0eed64
RR
541void wxImage::InitStandardHandlers()
542{
543 AddHandler( new wxBMPHandler );
01111366
RR
544}
545
546void wxImage::CleanUpHandlers()
547{
fd0eed64
RR
548 wxNode *node = sm_handlers.First();
549 while (node)
550 {
551 wxImageHandler *handler = (wxImageHandler *)node->Data();
552 wxNode *next = node->Next();
553 delete handler;
554 delete node;
555 node = next;
556 }
01111366
RR
557}
558
559//-----------------------------------------------------------------------------
560// wxImageHandler
561//-----------------------------------------------------------------------------
562
563#if !USE_SHARED_LIBRARIES
564IMPLEMENT_DYNAMIC_CLASS(wxImageHandler,wxObject)
565#endif
566
e02afc7a 567#if wxUSE_STREAMS
3d05544e 568bool wxImageHandler::LoadFile( wxImage *WXUNUSED(image), wxInputStream& WXUNUSED(stream) )
01111366 569{
fd0eed64 570 return FALSE;
01111366
RR
571}
572
3d05544e 573bool wxImageHandler::SaveFile( wxImage *WXUNUSED(image), wxOutputStream& WXUNUSED(stream) )
01111366 574{
fd0eed64 575 return FALSE;
01111366 576}
e02afc7a 577#endif // wxUSE_STREAMS
01111366 578
01111366
RR
579//-----------------------------------------------------------------------------
580// wxBMPHandler
581//-----------------------------------------------------------------------------
582
583#if !USE_SHARED_LIBRARIES
584IMPLEMENT_DYNAMIC_CLASS(wxBMPHandler,wxImageHandler)
585#endif
4698648f 586
e02afc7a 587#if wxUSE_STREAMS
27933891 588
0b4f9ee3 589#ifndef BI_RGB
01111366
RR
590#define BI_RGB 0
591#define BI_RLE8 1
592#define BI_RLE4 2
62448488 593#endif
c7abc967 594
62448488 595#ifndef BI_BITFIELDS
01111366 596#define BI_BITFIELDS 3
0b4f9ee3 597#endif
c7abc967 598
27933891
RR
599#define poffset (line * width * 3 + column * 3)
600
601bool wxBMPHandler::LoadFile( wxImage *image, wxInputStream& stream )
602{
603 int rshift = 0, gshift = 0, bshift = 0;
604 wxUint8 aByte;
605 wxUint16 aWord;
606 wxInt32 dbuf[4], aDword,
607 rmask = 0, gmask = 0, bmask = 0;
608 wxInt8 bbuf[4];
609 struct _cmap {
610 unsigned char r, g, b;
611 } *cmap = NULL;
612
613 off_t start_offset = stream.TellI();
614
dbda9e86 615 image->Destroy();
c7abc967 616
dbda9e86 617 /*
27933891
RR
618 * Read the BMP header
619 */
c7abc967 620
27933891
RR
621 stream.Read( &bbuf, 2 );
622 stream.Read( dbuf, 4 * 4 );
c7abc967 623
7e2c43b8
RR
624 wxInt32 size = wxINT32_SWAP_ON_BE( dbuf[0] );
625 wxInt32 offset = wxINT32_SWAP_ON_BE( dbuf[2] );
c7abc967 626
dbda9e86 627 stream.Read(dbuf, 4 * 2);
7e2c43b8
RR
628 int width = (int)wxINT32_SWAP_ON_BE( dbuf[0] );
629 int height = (int)wxINT32_SWAP_ON_BE( dbuf[1] );
dbda9e86
JS
630 if (width > 32767)
631 {
c7abc967 632 wxLogError( _T("Image width > 32767 pixels for file.") );
4698648f 633 return FALSE;
dbda9e86
JS
634 }
635 if (height > 32767)
636 {
c7abc967 637 wxLogError( _T("Image height > 32767 pixels for file.") );
4698648f 638 return FALSE;
dbda9e86 639 }
27933891
RR
640
641 stream.Read( &aWord, 2 );
642/*
643 TODO
7e2c43b8 644 int planes = (int)wxUINT16_SWAP_ON_BE( aWord );
27933891
RR
645*/
646 stream.Read( &aWord, 2 );
7e2c43b8 647 int bpp = (int)wxUINT16_SWAP_ON_BE( aWord );
c7abc967 648 if (bpp != 1 && bpp != 4 && bpp != 8 && bpp != 16 && bpp != 24 && bpp != 32)
dbda9e86 649 {
c7abc967 650 wxLogError( _T("unknown bitdepth in file.") );
4698648f 651 return FALSE;
dbda9e86 652 }
27933891
RR
653
654 stream.Read( dbuf, 4 * 4 );
7e2c43b8 655 int comp = (int)wxINT32_SWAP_ON_BE( dbuf[0] );
dbda9e86
JS
656 if (comp != BI_RGB && comp != BI_RLE4 && comp != BI_RLE8 && comp != BI_BITFIELDS)
657 {
c7abc967 658 wxLogError( _T("unknown encoding in Windows BMP file.") );
4698648f 659 return FALSE;
dbda9e86 660 }
27933891
RR
661
662 stream.Read( dbuf, 4 * 2 );
7e2c43b8 663 int ncolors = (int)wxINT32_SWAP_ON_BE( dbuf[0] );
dbda9e86
JS
664 if (ncolors == 0)
665 ncolors = 1 << bpp;
666 /* some more sanity checks */
27933891
RR
667 if (((comp == BI_RLE4) && (bpp != 4)) ||
668 ((comp == BI_RLE8) && (bpp != 8)) ||
669 ((comp == BI_BITFIELDS) && (bpp != 16 && bpp != 32)))
dbda9e86 670 {
c7abc967 671 wxLogError( _T("encoding of BMP doesn't match bitdepth.") );
4698648f 672 return FALSE;
dbda9e86
JS
673 }
674 if (bpp < 16)
675 {
4698648f 676 cmap = (struct _cmap *)malloc(sizeof(struct _cmap) * ncolors);
4698648f 677 if (!cmap)
dbda9e86 678 {
c7abc967 679 wxLogError( _T("Cannot allocate RAM for color map in BMP file.") );
dbda9e86
JS
680 return FALSE;
681 }
682 }
683 else
684 cmap = NULL;
c7abc967 685
dbda9e86 686 image->Create( width, height );
27933891 687 unsigned char *ptr = image->GetData();
dbda9e86
JS
688 if (!ptr)
689 {
c7abc967 690 wxLogError( _T("Cannot allocate RAM for RGB data in file.") );
4698648f 691 if (cmap)
dbda9e86 692 free(cmap);
4698648f 693 return FALSE;
dbda9e86 694 }
c7abc967 695
dbda9e86 696 /*
27933891
RR
697 * Reading the palette, if it exists.
698 */
dbda9e86
JS
699 if (bpp < 16 && ncolors != 0)
700 {
27933891 701 for (int j = 0; j < ncolors; j++)
dbda9e86 702 {
27933891
RR
703 stream.Read( bbuf, 4 );
704 cmap[j].b = bbuf[0];
705 cmap[j].g = bbuf[1];
706 cmap[j].r = bbuf[2];
dbda9e86
JS
707 }
708 }
709 else if (bpp == 16 || bpp == 32)
710 {
4698648f 711 if (comp == BI_BITFIELDS)
dbda9e86 712 {
27933891
RR
713 int bit = 0;
714 stream.Read( dbuf, 4 * 3 );
7e2c43b8
RR
715 bmask = wxINT32_SWAP_ON_BE( dbuf[0] );
716 gmask = wxINT32_SWAP_ON_BE( dbuf[1] );
717 rmask = wxINT32_SWAP_ON_BE( dbuf[2] );
dbda9e86
JS
718 /* find shift amount.. ugly, but i can't think of a better way */
719 for (bit = 0; bit < bpp; bit++)
720 {
721 if (bmask & (1 << bit))
722 bshift = bit;
723 if (gmask & (1 << bit))
724 gshift = bit;
725 if (rmask & (1 << bit))
726 rshift = bit;
727 }
728 }
4698648f 729 else if (bpp == 16)
dbda9e86
JS
730 {
731 rmask = 0x7C00;
732 gmask = 0x03E0;
733 bmask = 0x001F;
734 rshift = 10;
735 gshift = 5;
736 bshift = 0;
737 }
4698648f 738 else if (bpp == 32)
dbda9e86
JS
739 {
740 rmask = 0x00FF0000;
741 gmask = 0x0000FF00;
742 bmask = 0x000000FF;
743 rshift = 16;
744 gshift = 8;
745 bshift = 0;
746 }
747 }
c7abc967 748
dbda9e86 749 /*
27933891
RR
750 * Reading the image data
751 */
752 stream.SeekI( start_offset + offset );
753 unsigned char *data = ptr;
c7abc967 754
dbda9e86
JS
755 /* set the whole image to the background color */
756 if (bpp < 16 && (comp == BI_RLE4 || comp == BI_RLE8))
757 {
27933891 758 for (int i = 0; i < width * height; i++)
dbda9e86
JS
759 {
760 *ptr++ = cmap[0].r;
761 *ptr++ = cmap[0].g;
762 *ptr++ = cmap[0].b;
763 }
4698648f 764 ptr = data;
dbda9e86 765 }
27933891
RR
766
767 int line = 0;
768 int column = 0;
769 int linesize = ((width * bpp + 31) / 32) * 4;
c7abc967 770
27933891
RR
771 /* BMPs are stored upside down */
772 for (line = (height - 1); line >= 0; line--)
dbda9e86 773 {
27933891 774 int linepos = 0;
4698648f 775 for (column = 0; column < width;)
dbda9e86
JS
776 {
777 if (bpp < 16)
778 {
27933891 779 int index = 0;
dbda9e86
JS
780 linepos++;
781 aByte = stream.GetC();
782 if (bpp == 1)
783 {
27933891 784 int bit = 0;
dbda9e86 785 for (bit = 0; bit < 8; bit++)
4698648f 786 {
dbda9e86
JS
787 index = ((aByte & (0x80 >> bit)) ? 1 : 0);
788 ptr[poffset] = cmap[index].r;
789 ptr[poffset + 1] = cmap[index].g;
790 ptr[poffset + 2] = cmap[index].b;
791 column++;
792 }
793 }
794 else if (bpp == 4)
795 {
796 if (comp == BI_RLE4)
797 {
27933891 798 wxLogError( _T("Can't deal with 4bit encoded yet.") );
dbda9e86
JS
799 image->Destroy();
800 free(cmap);
801 return FALSE;
802 }
803 else
804 {
27933891 805 int nibble = 0;
dbda9e86
JS
806 for (nibble = 0; nibble < 2; nibble++)
807 {
808 index = ((aByte & (0xF0 >> nibble * 4)) >> (!nibble * 4));
809 if (index >= 16)
810 index = 15;
4698648f
VZ
811 ptr[poffset] = cmap[index].r;
812 ptr[poffset + 1] = cmap[index].g;
813 ptr[poffset + 2] = cmap[index].b;
814 column++;
dbda9e86 815 }
4698648f 816 }
dbda9e86
JS
817 }
818 else if (bpp == 8)
819 {
820 if (comp == BI_RLE8)
4698648f 821 {
27933891 822 unsigned char first;
dbda9e86
JS
823 first = aByte;
824 aByte = stream.GetC();
825 if (first == 0)
826 {
827 if (aByte == 0)
828 {
27933891 829 /* column = width; */
dbda9e86
JS
830 }
831 else if (aByte == 1)
832 {
833 column = width;
834 line = -1;
835 }
836 else if (aByte == 2)
837 {
838 aByte = stream.GetC();
839 column += aByte;
840 linepos = column * bpp / 8;
841 aByte = stream.GetC();
842 line += aByte;
843 }
844 else
845 {
27933891
RR
846 int absolute = aByte;
847 for (int k = 0; k < absolute; k++)
dbda9e86
JS
848 {
849 linepos++;
850 aByte = stream.GetC();
27933891 851 ptr[poffset ] = cmap[aByte].r;
dbda9e86
JS
852 ptr[poffset + 1] = cmap[aByte].g;
853 ptr[poffset + 2] = cmap[aByte].b;
854 column++;
855 }
856 if (absolute & 0x01)
857 aByte = stream.GetC();
858 }
859 }
860 else
861 {
27933891 862 for (int l = 0; l < first; l++)
dbda9e86 863 {
27933891 864 ptr[poffset ] = cmap[aByte].r;
dbda9e86
JS
865 ptr[poffset + 1] = cmap[aByte].g;
866 ptr[poffset + 2] = cmap[aByte].b;
867 column++;
868 linepos++;
869 }
870 }
4698648f 871 }
dbda9e86 872 else
4698648f 873 {
27933891 874 ptr[poffset ] = cmap[aByte].r;
dbda9e86
JS
875 ptr[poffset + 1] = cmap[aByte].g;
876 ptr[poffset + 2] = cmap[aByte].b;
877 column++;
878 linepos += size;
4698648f 879 }
dbda9e86 880 }
4698648f 881 }
dbda9e86 882 else if (bpp == 24)
4698648f 883 {
27933891 884 stream.Read( &bbuf, 3 );
dbda9e86 885 linepos += 3;
27933891 886 ptr[poffset ] = (unsigned char)bbuf[2];
dbda9e86
JS
887 ptr[poffset + 1] = (unsigned char)bbuf[1];
888 ptr[poffset + 2] = (unsigned char)bbuf[0];
889 column++;
4698648f 890 }
dbda9e86 891 else if (bpp == 16)
4698648f 892 {
27933891
RR
893 unsigned char temp;
894 stream.Read( &aWord, 2 );
7e2c43b8 895 aWord = wxUINT16_SWAP_ON_BE( aWord );
dbda9e86 896 linepos += 2;
27933891 897 temp = (aWord & rmask) >> rshift;
dbda9e86 898 ptr[poffset] = temp;
27933891 899 temp = (aWord & gmask) >> gshift;
dbda9e86 900 ptr[poffset + 1] = temp;
27933891 901 temp = (aWord & bmask) >> gshift;
dbda9e86
JS
902 ptr[poffset + 2] = temp;
903 column++;
4698648f 904 }
dbda9e86 905 else
4698648f 906 {
27933891
RR
907 unsigned char temp;
908 stream.Read( &aDword, 4 );
7e2c43b8 909 aDword = wxINT32_SWAP_ON_BE( aDword );
dbda9e86 910 linepos += 4;
27933891 911 temp = (aDword & rmask) >> rshift;
dbda9e86 912 ptr[poffset] = temp;
27933891 913 temp = (aDword & gmask) >> gshift;
dbda9e86 914 ptr[poffset + 1] = temp;
27933891 915 temp = (aDword & bmask) >> bshift;
dbda9e86
JS
916 ptr[poffset + 2] = temp;
917 column++;
4698648f
VZ
918 }
919 }
dbda9e86 920 while ((linepos < linesize) && (comp != 1) && (comp != 2))
4698648f 921 {
27933891 922 stream.Read( &aByte, 1 );
dbda9e86
JS
923 linepos += 1;
924 if (stream.LastError() != wxStream_NOERROR)
925 break;
4698648f 926 }
01111366 927 }
27933891
RR
928 if (cmap)
929 free(cmap);
c7abc967 930
dbda9e86 931 image->SetMask( FALSE );
c7abc967 932
dbda9e86 933 return TRUE;
01111366 934}
e02afc7a 935#endif // wxUSE_STREAMS
01111366 936
e3554471
JS
937#ifdef __WXMSW__
938
939wxBitmap wxImage::ConvertToBitmap() const
940{
dbda9e86 941 // sizeLimit is the MS upper limit for the DIB size
c7abc967
VZ
942 int sizeLimit = 1024*768*3;
943
dbda9e86 944 // width and height of the device-dependent bitmap
bba6f3bd
UA
945 int width = GetWidth();
946 int bmpHeight = GetHeight();
c7abc967 947
dbda9e86 948 // calc the number of bytes per scanline and padding
bba6f3bd
UA
949 int bytePerLine = width*3;
950 int sizeDWORD = sizeof( DWORD );
951 div_t lineBoundary = div( bytePerLine, sizeDWORD );
952 int padding = 0;
c7abc967 953 if( lineBoundary.rem > 0 )
bba6f3bd
UA
954 {
955 padding = sizeDWORD - lineBoundary.rem;
956 bytePerLine += padding;
957 }
dbda9e86 958 // calc the number of DIBs and heights of DIBs
bba6f3bd
UA
959 int numDIB = 1;
960 int hRemain = 0;
961 int height = sizeLimit/bytePerLine;
962 if( height >= bmpHeight )
c7abc967 963 height = bmpHeight;
bba6f3bd
UA
964 else
965 {
966 div_t result = div( bmpHeight, height );
967 numDIB = result.quot;
dbda9e86
JS
968 hRemain = result.rem;
969 if( hRemain >0 ) numDIB++;
bba6f3bd 970 }
c7abc967 971
dbda9e86 972 // set bitmap parameters
bba6f3bd 973 wxBitmap bitmap;
50920146 974 wxCHECK_MSG( Ok(), bitmap, _T("invalid image") );
bba6f3bd
UA
975 bitmap.SetWidth( width );
976 bitmap.SetHeight( bmpHeight );
977 bitmap.SetDepth( wxDisplayDepth() );
c7abc967 978
dbda9e86 979 // create a DIB header
bba6f3bd
UA
980 int headersize = sizeof(BITMAPINFOHEADER);
981 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
50920146 982 wxCHECK_MSG( lpDIBh, bitmap, _T("could not allocate memory for DIB header") );
dbda9e86 983 // Fill in the DIB header
bba6f3bd
UA
984 lpDIBh->bmiHeader.biSize = headersize;
985 lpDIBh->bmiHeader.biWidth = (DWORD)width;
986 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
987 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
dbda9e86
JS
988 // the general formula for biSizeImage:
989 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
bba6f3bd
UA
990 lpDIBh->bmiHeader.biPlanes = 1;
991 lpDIBh->bmiHeader.biBitCount = 24;
992 lpDIBh->bmiHeader.biCompression = BI_RGB;
993 lpDIBh->bmiHeader.biClrUsed = 0;
dbda9e86 994 // These seem not really needed for our purpose here.
bba6f3bd
UA
995 lpDIBh->bmiHeader.biClrImportant = 0;
996 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
997 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
dbda9e86 998 // memory for DIB data
bba6f3bd
UA
999 unsigned char *lpBits;
1000 lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
1001 if( !lpBits )
1002 {
50920146 1003 wxFAIL_MSG( _T("could not allocate memory for DIB") );
bba6f3bd
UA
1004 free( lpDIBh );
1005 return bitmap;
1006 }
c7abc967 1007
dbda9e86 1008 // create and set the device-dependent bitmap
bba6f3bd
UA
1009 HDC hdc = ::GetDC(NULL);
1010 HDC memdc = ::CreateCompatibleDC( hdc );
1011 HBITMAP hbitmap;
1012 hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
c7abc967
VZ
1013 ::SelectObject( memdc, hbitmap);
1014
dbda9e86 1015 // copy image data into DIB data and then into DDB (in a loop)
bba6f3bd
UA
1016 unsigned char *data = GetData();
1017 int i, j, n;
1018 int origin = 0;
1019 unsigned char *ptdata = data;
1020 unsigned char *ptbits;
c7abc967 1021
bba6f3bd
UA
1022 for( n=0; n<numDIB; n++ )
1023 {
dbda9e86
JS
1024 if( numDIB > 1 && n == numDIB-1 && hRemain > 0 )
1025 {
1026 // redefine height and size of the (possibly) last smaller DIB
1027 // memory is not reallocated
c7abc967 1028 height = hRemain;
bba6f3bd
UA
1029 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
1030 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
dbda9e86 1031 }
bba6f3bd 1032 ptbits = lpBits;
c7abc967 1033
bba6f3bd
UA
1034 for( j=0; j<height; j++ )
1035 {
1036 for( i=0; i<width; i++ )
1037 {
1038 *(ptbits++) = *(ptdata+2);
1039 *(ptbits++) = *(ptdata+1);
1040 *(ptbits++) = *(ptdata );
1041 ptdata += 3;
dbda9e86
JS
1042 }
1043 for( i=0; i< padding; i++ ) *(ptbits++) = 0;
bba6f3bd
UA
1044 }
1045 ::StretchDIBits( memdc, 0, origin, width, height,\
dbda9e86
JS
1046 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
1047 origin += height;
1048 // if numDIB = 1, lines below can also be used
1049 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
1050 // The above line is equivalent to the following two lines.
1051 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
1052 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
1053 // or the following lines
1054 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
1055 // HDC memdc = ::CreateCompatibleDC( hdc );
c7abc967 1056 // ::SelectObject( memdc, hbitmap);
dbda9e86
JS
1057 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
1058 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
c7abc967
VZ
1059 // ::SelectObject( memdc, 0 );
1060 // ::DeleteDC( memdc );
e3554471 1061 }
bba6f3bd 1062 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
c7abc967 1063
dbda9e86 1064 // similarly, created an mono-bitmap for the possible mask
bba6f3bd
UA
1065 if( HasMask() )
1066 {
1067 hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL );
c7abc967
VZ
1068 ::SelectObject( memdc, hbitmap);
1069 if( numDIB == 1 ) height = bmpHeight;
bba6f3bd
UA
1070 else height = sizeLimit/bytePerLine;
1071 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
1072 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
1073 origin = 0;
1074 unsigned char r = GetMaskRed();
1075 unsigned char g = GetMaskGreen();
1076 unsigned char b = GetMaskBlue();
1077 unsigned char zero = 0, one = 255;
1078 ptdata = data;
1079 for( n=0; n<numDIB; n++ )
1080 {
1081 if( numDIB > 1 && n == numDIB - 1 && hRemain > 0 )
1082 {
dbda9e86
JS
1083 // redefine height and size of the (possibly) last smaller DIB
1084 // memory is not reallocated
c7abc967 1085 height = hRemain;
bba6f3bd
UA
1086 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
1087 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
dbda9e86 1088 }
bba6f3bd
UA
1089 ptbits = lpBits;
1090 for( int j=0; j<height; j++ )
1091 {
dbda9e86 1092 for(i=0; i<width; i++ )
bba6f3bd
UA
1093 {
1094 if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
1095 {
1096 *(ptbits++) = one;
1097 *(ptbits++) = one;
1098 *(ptbits++) = one;
1099 }
1100 else
1101 {
1102 *(ptbits++) = zero;
1103 *(ptbits++) = zero;
1104 *(ptbits++) = zero;
1105 }
1106 }
dbda9e86 1107 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
bba6f3bd
UA
1108 }
1109 ::StretchDIBits( memdc, 0, origin, width, height,\
dbda9e86
JS
1110 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
1111 origin += height;
1112 }
1113 // create a wxMask object
bba6f3bd
UA
1114 wxMask *mask = new wxMask();
1115 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
1116 bitmap.SetMask( mask );
dbda9e86
JS
1117 // It will be deleted when the wxBitmap object is deleted (as of 01/1999)
1118 /* The following can also be used but is slow to run
bba6f3bd
UA
1119 wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
1120 wxMask *mask = new wxMask( bitmap, colour );
1121 bitmap.SetMask( mask );
dbda9e86 1122 */
bba6f3bd 1123 }
c7abc967
VZ
1124
1125 // free allocated resources
1126 ::SelectObject( memdc, 0 );
1127 ::DeleteDC( memdc );
1128 ::ReleaseDC(NULL, hdc);
bba6f3bd
UA
1129 free(lpDIBh);
1130 free(lpBits);
c7abc967 1131
dbda9e86 1132 // check the wxBitmap object
bba6f3bd
UA
1133 if( bitmap.GetHBITMAP() )
1134 bitmap.SetOk( TRUE );
1135 else
1136 bitmap.SetOk( FALSE );
c7abc967 1137
bba6f3bd 1138 return bitmap;
e3554471
JS
1139}
1140
e3554471
JS
1141wxImage::wxImage( const wxBitmap &bitmap )
1142{
dbda9e86 1143 // check the bitmap
bba6f3bd
UA
1144 if( !bitmap.Ok() )
1145 {
50920146 1146 wxFAIL_MSG( _T("invalid bitmap") );
bba6f3bd
UA
1147 return;
1148 }
c7abc967 1149
dbda9e86 1150 // create an wxImage object
bba6f3bd
UA
1151 int width = bitmap.GetWidth();
1152 int height = bitmap.GetHeight();
c7abc967 1153 Create( width, height );
bba6f3bd
UA
1154 unsigned char *data = GetData();
1155 if( !data )
1156 {
50920146 1157 wxFAIL_MSG( _T("could not allocate data for image") );
bba6f3bd
UA
1158 return;
1159 }
c7abc967 1160
dbda9e86 1161 // calc the number of bytes per scanline and padding in the DIB
bba6f3bd
UA
1162 int bytePerLine = width*3;
1163 int sizeDWORD = sizeof( DWORD );
1164 div_t lineBoundary = div( bytePerLine, sizeDWORD );
1165 int padding = 0;
c7abc967 1166 if( lineBoundary.rem > 0 )
bba6f3bd
UA
1167 {
1168 padding = sizeDWORD - lineBoundary.rem;
1169 bytePerLine += padding;
1170 }
c7abc967 1171
dbda9e86 1172 // create a DIB header
bba6f3bd
UA
1173 int headersize = sizeof(BITMAPINFOHEADER);
1174 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
1175 if( !lpDIBh )
1176 {
50920146 1177 wxFAIL_MSG( _T("could not allocate data for DIB header") );
bba6f3bd
UA
1178 free( data );
1179 return;
1180 }
dbda9e86 1181 // Fill in the DIB header
bba6f3bd
UA
1182 lpDIBh->bmiHeader.biSize = headersize;
1183 lpDIBh->bmiHeader.biWidth = width;
1184 lpDIBh->bmiHeader.biHeight = -height;
1185 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
1186 lpDIBh->bmiHeader.biPlanes = 1;
1187 lpDIBh->bmiHeader.biBitCount = 24;
1188 lpDIBh->bmiHeader.biCompression = BI_RGB;
1189 lpDIBh->bmiHeader.biClrUsed = 0;
dbda9e86 1190 // These seem not really needed for our purpose here.
bba6f3bd
UA
1191 lpDIBh->bmiHeader.biClrImportant = 0;
1192 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
1193 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
dbda9e86 1194 // memory for DIB data
bba6f3bd
UA
1195 unsigned char *lpBits;
1196 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
1197 if( !lpBits )
e3554471 1198 {
50920146 1199 wxFAIL_MSG( _T("could not allocate data for DIB") );
bba6f3bd
UA
1200 free( data );
1201 free( lpDIBh );
1202 return;
4698648f 1203 }
c7abc967 1204
dbda9e86 1205 // copy data from the device-dependent bitmap to the DIB
bba6f3bd
UA
1206 HDC hdc = ::GetDC(NULL);
1207 HBITMAP hbitmap;
1208 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
1209 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
c7abc967 1210
dbda9e86 1211 // copy DIB data into the wxImage object
bba6f3bd
UA
1212 int i, j;
1213 unsigned char *ptdata = data;
1214 unsigned char *ptbits = lpBits;
1215 for( i=0; i<height; i++ )
1216 {
1217 for( j=0; j<width; j++ )
1218 {
1219 *(ptdata++) = *(ptbits+2);
1220 *(ptdata++) = *(ptbits+1);
1221 *(ptdata++) = *(ptbits );
1222 ptbits += 3;
dbda9e86 1223 }
bba6f3bd 1224 ptbits += padding;
c7abc967
VZ
1225 }
1226
dbda9e86 1227 // similarly, set data according to the possible mask bitmap
bba6f3bd
UA
1228 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
1229 {
1230 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
dbda9e86 1231 // memory DC created, color set, data copied, and memory DC deleted
bba6f3bd
UA
1232 HDC memdc = ::CreateCompatibleDC( hdc );
1233 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
1234 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
1235 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
c7abc967 1236 ::DeleteDC( memdc );
dbda9e86 1237 // background color set to RGB(16,16,16) in consistent with wxGTK
c7abc967 1238 unsigned char r=16, g=16, b=16;
bba6f3bd
UA
1239 ptdata = data;
1240 ptbits = lpBits;
1241 for( i=0; i<height; i++ )
1242 {
1243 for( j=0; j<width; j++ )
1244 {
1245 if( *ptbits != 0 )
dbda9e86
JS
1246 ptdata += 3;
1247 else
bba6f3bd
UA
1248 {
1249 *(ptdata++) = r;
1250 *(ptdata++) = g;
1251 *(ptdata++) = b;
dbda9e86 1252 }
bba6f3bd
UA
1253 ptbits += 3;
1254 }
1255 ptbits += padding;
c7abc967 1256 }
bba6f3bd
UA
1257 SetMaskColour( r, g, b );
1258 SetMask( TRUE );
c7abc967 1259 }
bba6f3bd
UA
1260 else
1261 {
1262 SetMask( FALSE );
c7abc967
VZ
1263 }
1264 // free allocated resources
1265 ::ReleaseDC(NULL, hdc);
bba6f3bd
UA
1266 free(lpDIBh);
1267 free(lpBits);
e3554471
JS
1268}
1269
1270#endif
1271
99c67c77
RR
1272#ifdef __WXGTK__
1273
83624f79
RR
1274#include "gtk/gtk.h"
1275#include "gdk/gdk.h"
1276#include "gdk/gdkx.h"
1277
ba0730de
RR
1278#if (GTK_MINOR_VERSION > 0)
1279#include "gdk/gdkrgb.h"
1280#endif
1281
99c67c77
RR
1282wxBitmap wxImage::ConvertToBitmap() const
1283{
1284 wxBitmap bitmap;
c7abc967 1285
50920146 1286 wxCHECK_MSG( Ok(), bitmap, _T("invalid image") );
c7abc967 1287
99c67c77
RR
1288 int width = GetWidth();
1289 int height = GetHeight();
c7abc967 1290
99c67c77
RR
1291 bitmap.SetHeight( height );
1292 bitmap.SetWidth( width );
c7abc967 1293
ba0730de
RR
1294 bitmap.SetPixmap( gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, -1 ) );
1295
1296 // Retrieve depth
c7abc967 1297
ba0730de
RR
1298 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
1299 if (visual == NULL) visual = gdk_window_get_visual( (GdkWindow*) &gdk_root_parent );
1300 int bpp = visual->depth;
c7abc967 1301
ba0730de 1302 bitmap.SetDepth( bpp );
c7abc967 1303
ba0730de
RR
1304 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
1305 if (bpp < 8) bpp = 8;
c7abc967 1306
ba0730de
RR
1307#if (GTK_MINOR_VERSION > 0)
1308
1309 if (!HasMask() && (bpp > 8))
1310 {
1311 static bool s_hasInitialized = FALSE;
c7abc967 1312
ba0730de
RR
1313 if (!s_hasInitialized)
1314 {
1315 gdk_rgb_init();
1316 s_hasInitialized = TRUE;
1317 }
c7abc967 1318
ba0730de 1319 GdkGC *gc = gdk_gc_new( bitmap.GetPixmap() );
c7abc967 1320
ba0730de
RR
1321 gdk_draw_rgb_image( bitmap.GetPixmap(),
1322 gc,
1323 0, 0,
1324 width, height,
1325 GDK_RGB_DITHER_NONE,
1326 GetData(),
1327 width*3 );
c7abc967 1328
ba0730de 1329 gdk_gc_unref( gc );
c7abc967 1330
ba0730de
RR
1331 return bitmap;
1332 }
c7abc967 1333
ba0730de 1334#endif
c7abc967 1335
ba0730de 1336 // Create picture image
c7abc967 1337
99c67c77 1338 GdkImage *data_image =
dbda9e86 1339 gdk_image_new( GDK_IMAGE_FASTEST, gdk_visual_get_system(), width, height );
c7abc967 1340
ba0730de 1341 // Create mask image
c7abc967 1342
99c67c77 1343 GdkImage *mask_image = (GdkImage*) NULL;
c7abc967 1344
99c67c77
RR
1345 if (HasMask())
1346 {
1347 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
c7abc967 1348
99c67c77 1349 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
c7abc967 1350
4698648f
VZ
1351 wxMask *mask = new wxMask();
1352 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
c7abc967 1353
4698648f 1354 bitmap.SetMask( mask );
99c67c77 1355 }
c7abc967 1356
99c67c77 1357 // Render
c7abc967 1358
99c67c77
RR
1359 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1360 byte_order b_o = RGB;
c7abc967 1361
99c67c77
RR
1362 if (bpp >= 24)
1363 {
1364 GdkVisual *visual = gdk_visual_get_system();
1365 if ((visual->red_mask > visual->green_mask) && (visual->green_mask > visual->blue_mask)) b_o = RGB;
1366 else if ((visual->red_mask > visual->blue_mask) && (visual->blue_mask > visual->green_mask)) b_o = RGB;
1367 else if ((visual->blue_mask > visual->red_mask) && (visual->red_mask > visual->green_mask)) b_o = BRG;
1368 else if ((visual->blue_mask > visual->green_mask) && (visual->green_mask > visual->red_mask)) b_o = BGR;
1369 else if ((visual->green_mask > visual->red_mask) && (visual->red_mask > visual->blue_mask)) b_o = GRB;
1370 else if ((visual->green_mask > visual->blue_mask) && (visual->blue_mask > visual->red_mask)) b_o = GBR;
1371 }
c7abc967 1372
99c67c77
RR
1373 int r_mask = GetMaskRed();
1374 int g_mask = GetMaskGreen();
1375 int b_mask = GetMaskBlue();
c7abc967 1376
99c67c77 1377 unsigned char* data = GetData();
c7abc967 1378
99c67c77
RR
1379 int index = 0;
1380 for (int y = 0; y < height; y++)
1381 {
1382 for (int x = 0; x < width; x++)
1383 {
1384 int r = data[index];
4698648f 1385 index++;
99c67c77 1386 int g = data[index];
4698648f 1387 index++;
99c67c77 1388 int b = data[index];
4698648f 1389 index++;
c7abc967 1390
4698648f
VZ
1391 if (HasMask())
1392 {
1393 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1394 gdk_image_put_pixel( mask_image, x, y, 1 );
1395 else
1396 gdk_image_put_pixel( mask_image, x, y, 0 );
1397 }
c7abc967 1398
4698648f
VZ
1399 if (HasMask())
1400 {
1401 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1402 gdk_image_put_pixel( mask_image, x, y, 1 );
1403 else
1404 gdk_image_put_pixel( mask_image, x, y, 0 );
1405 }
c7abc967 1406
4698648f
VZ
1407 switch (bpp)
1408 {
dbda9e86 1409 case 8:
4698648f 1410 {
f6fcbb63 1411 int pixel = -1;
4698648f
VZ
1412 if (wxTheApp->m_colorCube)
1413 {
38274997 1414 pixel = wxTheApp->m_colorCube[ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
4698648f 1415 }
f6fcbb63 1416 else
4698648f
VZ
1417 {
1418 GdkColormap *cmap = gtk_widget_get_default_colormap();
f6fcbb63
RR
1419 GdkColor *colors = cmap->colors;
1420 int max = 3 * (65536);
c7abc967 1421
f6fcbb63
RR
1422 for (int i = 0; i < cmap->size; i++)
1423 {
1424 int rdiff = (r << 8) - colors[i].red;
1425 int gdiff = (g << 8) - colors[i].green;
1426 int bdiff = (b << 8) - colors[i].blue;
1427 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1428 if (sum < max) { pixel = i; max = sum; }
4698648f 1429 }
99c67c77 1430 }
c7abc967 1431
4698648f 1432 gdk_image_put_pixel( data_image, x, y, pixel );
c7abc967 1433
4698648f
VZ
1434 break;
1435 }
dbda9e86 1436 case 15:
4698648f
VZ
1437 {
1438 guint32 pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1439 gdk_image_put_pixel( data_image, x, y, pixel );
1440 break;
1441 }
dbda9e86 1442 case 16:
4698648f
VZ
1443 {
1444 guint32 pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1445 gdk_image_put_pixel( data_image, x, y, pixel );
1446 break;
1447 }
dbda9e86
JS
1448 case 32:
1449 case 24:
4698648f
VZ
1450 {
1451 guint32 pixel = 0;
1452 switch (b_o)
1453 {
dbda9e86
JS
1454 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1455 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1456 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1457 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1458 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1459 case GBR: pixel = (g << 16) | (b << 8) | r; break;
4698648f
VZ
1460 }
1461 gdk_image_put_pixel( data_image, x, y, pixel );
1462 }
dbda9e86 1463 default: break;
4698648f 1464 }
99c67c77
RR
1465 } // for
1466 } // for
c7abc967 1467
99c67c77 1468 // Blit picture
c7abc967 1469
99c67c77 1470 GdkGC *data_gc = gdk_gc_new( bitmap.GetPixmap() );
c7abc967 1471
99c67c77 1472 gdk_draw_image( bitmap.GetPixmap(), data_gc, data_image, 0, 0, 0, 0, width, height );
c7abc967 1473
99c67c77
RR
1474 gdk_image_destroy( data_image );
1475 gdk_gc_unref( data_gc );
c7abc967 1476
99c67c77 1477 // Blit mask
c7abc967 1478
99c67c77
RR
1479 if (HasMask())
1480 {
1481 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
c7abc967 1482
99c67c77 1483 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
c7abc967 1484
99c67c77
RR
1485 gdk_image_destroy( mask_image );
1486 gdk_gc_unref( mask_gc );
1487 }
c7abc967 1488
99c67c77
RR
1489 return bitmap;
1490}
1491
1492wxImage::wxImage( const wxBitmap &bitmap )
1493{
50920146 1494 wxCHECK_RET( bitmap.Ok(), _T("invalid bitmap") );
c7abc967 1495
99c67c77 1496 GdkImage *gdk_image = gdk_image_get( bitmap.GetPixmap(),
dbda9e86
JS
1497 0, 0,
1498 bitmap.GetWidth(), bitmap.GetHeight() );
c7abc967 1499
50920146 1500 wxCHECK_RET( gdk_image, _T("couldn't create image") );
c7abc967 1501
99c67c77
RR
1502 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1503 char unsigned *data = GetData();
c7abc967 1504
99c67c77
RR
1505 if (!data)
1506 {
1507 gdk_image_destroy( gdk_image );
50920146 1508 wxFAIL_MSG( _T("couldn't create image") );
4698648f 1509 return;
99c67c77 1510 }
c7abc967 1511
99c67c77
RR
1512 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1513 if (bitmap.GetMask())
1514 {
1515 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
dbda9e86
JS
1516 0, 0,
1517 bitmap.GetWidth(), bitmap.GetHeight() );
c7abc967 1518
4698648f 1519 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
99c67c77 1520 }
c7abc967 1521
99c67c77
RR
1522 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
1523 if (visual == NULL) visual = gdk_window_get_visual( (GdkWindow*) &gdk_root_parent );
1524 int bpp = visual->depth;
1525 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
c7abc967 1526
99c67c77 1527 GdkColormap *cmap = gtk_widget_get_default_colormap();
c7abc967 1528
99c67c77
RR
1529 long pos = 0;
1530 for (int j = 0; j < bitmap.GetHeight(); j++)
1531 {
1532 for (int i = 0; i < bitmap.GetWidth(); i++)
1533 {
1534 int pixel = gdk_image_get_pixel( gdk_image, i, j );
1535 if (bpp <= 8)
1536 {
1537 data[pos] = cmap->colors[pixel].red >> 8;
1538 data[pos+1] = cmap->colors[pixel].green >> 8;
1539 data[pos+2] = cmap->colors[pixel].blue >> 8;
1540 } else if (bpp == 15)
1541 {
1542 data[pos] = (pixel >> 7) & 0xf8;
1543 data[pos+1] = (pixel >> 2) & 0xf8;
1544 data[pos+2] = (pixel << 3) & 0xf8;
1545 } else if (bpp == 16)
1546 {
1547 data[pos] = (pixel >> 8) & 0xf8;
1548 data[pos+1] = (pixel >> 3) & 0xfc;
1549 data[pos+2] = (pixel << 3) & 0xf8;
1550 } else
1551 {
1552 data[pos] = (pixel >> 16) & 0xff;
1553 data[pos+1] = (pixel >> 8) & 0xff;
1554 data[pos+2] = pixel & 0xff;
1555 }
c7abc967 1556
4698648f
VZ
1557 if (gdk_image_mask)
1558 {
1559 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1560 if (mask_pixel == 0)
1561 {
99c67c77
RR
1562 data[pos] = 16;
1563 data[pos+1] = 16;
1564 data[pos+2] = 16;
dbda9e86 1565 }
4698648f 1566 }
c7abc967 1567
99c67c77
RR
1568 pos += 3;
1569 }
1570 }
c7abc967 1571
99c67c77
RR
1572 gdk_image_destroy( gdk_image );
1573 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1574}
1575
1576#endif
ee4c6942 1577
ee4c6942 1578#ifdef __WXMOTIF__
b75867a6
RR
1579
1580#include <Xm/Xm.h>
1581#include "wx/utils.h"
38274997 1582#include <math.h>
b75867a6 1583
ee4c6942
JS
1584wxBitmap wxImage::ConvertToBitmap() const
1585{
b75867a6 1586 wxBitmap bitmap;
c7abc967 1587
50920146 1588 wxCHECK_MSG( Ok(), bitmap, _T("invalid image") );
a91b47e8 1589
b75867a6
RR
1590 int width = GetWidth();
1591 int height = GetHeight();
c7abc967 1592
b75867a6
RR
1593 bitmap.SetHeight( height );
1594 bitmap.SetWidth( width );
c7abc967 1595
b75867a6
RR
1596 Display *dpy = (Display*) wxGetDisplay();
1597 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1598 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
c7abc967 1599
b75867a6 1600 // Create image
c7abc967 1601
b75867a6 1602 XImage *data_image = XCreateImage( dpy, vis, bpp, ZPixmap, 0, 0, width, height, 32, 0 );
a91b47e8 1603 data_image->data = (char*) malloc( data_image->bytes_per_line * data_image->height );
c7abc967 1604
b75867a6 1605 bitmap.Create( width, height, bpp );
a91b47e8 1606
dbda9e86 1607 /*
b75867a6 1608 // Create mask
c7abc967 1609
dbda9e86 1610 GdkImage *mask_image = (GdkImage*) NULL;
c7abc967 1611
dbda9e86
JS
1612 if (HasMask())
1613 {
b75867a6 1614 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
c7abc967 1615
dbda9e86 1616 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
c7abc967 1617
dbda9e86
JS
1618 wxMask *mask = new wxMask();
1619 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
c7abc967 1620
dbda9e86
JS
1621 bitmap.SetMask( mask );
1622 }
1623 */
c7abc967 1624
b75867a6 1625 // Retrieve depth info
c7abc967 1626
b75867a6
RR
1627 XVisualInfo vinfo_template;
1628 XVisualInfo *vi;
c7abc967 1629
b75867a6
RR
1630 vinfo_template.visual = vis;
1631 vinfo_template.visualid = XVisualIDFromVisual( vis );
1632 vinfo_template.depth = bpp;
1633 int nitem = 0;
c7abc967 1634
b75867a6 1635 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
c7abc967
VZ
1636
1637 wxCHECK_MSG( vi, wxNullBitmap, _T("no visual") );
1638
38274997 1639 XFree( vi );
a91b47e8 1640
b75867a6
RR
1641 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1642 if (bpp < 8) bpp = 8;
c7abc967 1643
b75867a6 1644 // Render
c7abc967 1645
b75867a6
RR
1646 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1647 byte_order b_o = RGB;
c7abc967 1648
b75867a6
RR
1649 if (bpp >= 24)
1650 {
1651 if ((vi->red_mask > vi->green_mask) && (vi->green_mask > vi->blue_mask)) b_o = RGB;
1652 else if ((vi->red_mask > vi->blue_mask) && (vi->blue_mask > vi->green_mask)) b_o = RGB;
1653 else if ((vi->blue_mask > vi->red_mask) && (vi->red_mask > vi->green_mask)) b_o = BRG;
1654 else if ((vi->blue_mask > vi->green_mask) && (vi->green_mask > vi->red_mask)) b_o = BGR;
1655 else if ((vi->green_mask > vi->red_mask) && (vi->red_mask > vi->blue_mask)) b_o = GRB;
1656 else if ((vi->green_mask > vi->blue_mask) && (vi->blue_mask > vi->red_mask)) b_o = GBR;
1657 }
c7abc967 1658
dbda9e86 1659 /*
b75867a6
RR
1660 int r_mask = GetMaskRed();
1661 int g_mask = GetMaskGreen();
1662 int b_mask = GetMaskBlue();
dbda9e86 1663 */
c7abc967 1664
38274997
RR
1665 XColor colors[256];
1666 if (bpp == 8)
1667 {
dbda9e86 1668 Colormap cmap = (Colormap) wxTheApp->GetMainColormap( dpy );
c7abc967 1669
38274997 1670 for (int i = 0; i < 256; i++) colors[i].pixel = i;
dbda9e86 1671 XQueryColors( dpy, cmap, colors, 256 );
38274997 1672 }
c7abc967 1673
b75867a6 1674 unsigned char* data = GetData();
c7abc967 1675
b75867a6
RR
1676 int index = 0;
1677 for (int y = 0; y < height; y++)
1678 {
1679 for (int x = 0; x < width; x++)
1680 {
1681 int r = data[index];
dbda9e86 1682 index++;
b75867a6 1683 int g = data[index];
dbda9e86 1684 index++;
b75867a6 1685 int b = data[index];
dbda9e86 1686 index++;
c7abc967 1687
dbda9e86
JS
1688 /*
1689 if (HasMask())
1690 {
1691 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1692 gdk_image_put_pixel( mask_image, x, y, 1 );
1693 else
1694 gdk_image_put_pixel( mask_image, x, y, 0 );
1695 }
1696 */
c7abc967 1697
dbda9e86
JS
1698 switch (bpp)
1699 {
1700 case 8:
1701 {
b75867a6 1702 int pixel = -1;
dbda9e86
JS
1703 /*
1704 if (wxTheApp->m_colorCube)
1705 {
1706 pixel = wxTheApp->m_colorCube
c7abc967
VZ
1707 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1708 }
b75867a6 1709 else
dbda9e86
JS
1710 {
1711 */
1712 int max = 3 * (65536);
1713 for (int i = 0; i < 256; i++)
1714 {
1715 int rdiff = (r << 8) - colors[i].red;
1716 int gdiff = (g << 8) - colors[i].green;
1717 int bdiff = (b << 8) - colors[i].blue;
1718 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1719 if (sum < max) { pixel = i; max = sum; }
1720 }
1721 /*
1722 }
1723 */
1724 XPutPixel( data_image, x, y, pixel );
1725 break;
1726 }
1727 case 15:
1728 {
1729 int pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1730 XPutPixel( data_image, x, y, pixel );
1731 break;
1732 }
1733 case 16:
1734 {
1735 int pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1736 XPutPixel( data_image, x, y, pixel );
1737 break;
1738 }
1739 case 32:
1740 case 24:
1741 {
1742 int pixel = 0;
1743 switch (b_o)
1744 {
1745 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1746 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1747 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1748 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1749 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1750 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1751 }
1752 XPutPixel( data_image, x, y, pixel );
1753 }
1754 default: break;
1755 }
b75867a6
RR
1756 } // for
1757 } // for
c7abc967 1758
b75867a6 1759 // Blit picture
c7abc967 1760
b75867a6
RR
1761 XGCValues gcvalues;
1762 gcvalues.foreground = BlackPixel( dpy, DefaultScreen( dpy ) );
1763 GC gc = XCreateGC( dpy, RootWindow ( dpy, DefaultScreen(dpy) ), GCForeground, &gcvalues );
1764 XPutImage( dpy, (Drawable)bitmap.GetPixmap(), gc, data_image, 0, 0, 0, 0, width, height );
c7abc967 1765
b75867a6
RR
1766 XDestroyImage( data_image );
1767 XFreeGC( dpy, gc );
c7abc967 1768
dbda9e86 1769 /*
b75867a6 1770 // Blit mask
c7abc967 1771
dbda9e86
JS
1772 if (HasMask())
1773 {
1774 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
c7abc967 1775
b75867a6 1776 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
c7abc967 1777
dbda9e86
JS
1778 gdk_image_destroy( mask_image );
1779 gdk_gc_unref( mask_gc );
1780 }
1781 */
c7abc967 1782
b75867a6 1783 return bitmap;
ee4c6942
JS
1784}
1785
1786wxImage::wxImage( const wxBitmap &bitmap )
1787{
50920146 1788 wxCHECK_RET( bitmap.Ok(), _T("invalid bitmap") );
c7abc967 1789
38274997
RR
1790 Display *dpy = (Display*) wxGetDisplay();
1791 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1792 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
c7abc967 1793
38274997 1794 XImage *ximage = XGetImage( dpy,
dbda9e86
JS
1795 (Drawable)bitmap.GetPixmap(),
1796 0, 0,
1797 bitmap.GetWidth(), bitmap.GetHeight(),
1798 AllPlanes, ZPixmap );
c7abc967 1799
50920146 1800 wxCHECK_RET( ximage, _T("couldn't create image") );
c7abc967 1801
38274997
RR
1802 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1803 char unsigned *data = GetData();
c7abc967 1804
38274997
RR
1805 if (!data)
1806 {
1807 XDestroyImage( ximage );
50920146 1808 wxFAIL_MSG( _T("couldn't create image") );
38274997
RR
1809 return;
1810 }
c7abc967 1811
dbda9e86 1812 /*
38274997
RR
1813 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1814 if (bitmap.GetMask())
1815 {
dbda9e86
JS
1816 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1817 0, 0,
1818 bitmap.GetWidth(), bitmap.GetHeight() );
c7abc967 1819
dbda9e86
JS
1820 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1821 }
1822 */
c7abc967 1823
38274997 1824 // Retrieve depth info
c7abc967 1825
38274997
RR
1826 XVisualInfo vinfo_template;
1827 XVisualInfo *vi;
c7abc967 1828
38274997
RR
1829 vinfo_template.visual = vis;
1830 vinfo_template.visualid = XVisualIDFromVisual( vis );
1831 vinfo_template.depth = bpp;
1832 int nitem = 0;
c7abc967 1833
38274997 1834 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
c7abc967
VZ
1835
1836 wxCHECK_MSG( vi, wxNullBitmap, _T("no visual") );
1837
38274997 1838 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
c7abc967 1839
38274997 1840 XFree( vi );
c7abc967 1841
38274997
RR
1842 XColor colors[256];
1843 if (bpp == 8)
1844 {
dbda9e86 1845 Colormap cmap = (Colormap)wxTheApp->GetMainColormap( dpy );
c7abc967 1846
38274997 1847 for (int i = 0; i < 256; i++) colors[i].pixel = i;
dbda9e86 1848 XQueryColors( dpy, cmap, colors, 256 );
38274997 1849 }
c7abc967 1850
38274997
RR
1851 long pos = 0;
1852 for (int j = 0; j < bitmap.GetHeight(); j++)
1853 {
1854 for (int i = 0; i < bitmap.GetWidth(); i++)
1855 {
dbda9e86 1856 int pixel = XGetPixel( ximage, i, j );
38274997
RR
1857 if (bpp <= 8)
1858 {
1859 data[pos] = colors[pixel].red >> 8;
1860 data[pos+1] = colors[pixel].green >> 8;
1861 data[pos+2] = colors[pixel].blue >> 8;
1862 } else if (bpp == 15)
1863 {
1864 data[pos] = (pixel >> 7) & 0xf8;
1865 data[pos+1] = (pixel >> 2) & 0xf8;
1866 data[pos+2] = (pixel << 3) & 0xf8;
1867 } else if (bpp == 16)
1868 {
1869 data[pos] = (pixel >> 8) & 0xf8;
1870 data[pos+1] = (pixel >> 3) & 0xfc;
1871 data[pos+2] = (pixel << 3) & 0xf8;
1872 } else
1873 {
1874 data[pos] = (pixel >> 16) & 0xff;
1875 data[pos+1] = (pixel >> 8) & 0xff;
1876 data[pos+2] = pixel & 0xff;
1877 }
c7abc967 1878
dbda9e86 1879 /*
38274997
RR
1880 if (gdk_image_mask)
1881 {
dbda9e86
JS
1882 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1883 if (mask_pixel == 0)
1884 {
1885 data[pos] = 16;
1886 data[pos+1] = 16;
1887 data[pos+2] = 16;
38274997 1888 }
dbda9e86
JS
1889 }
1890 */
c7abc967 1891
38274997
RR
1892 pos += 3;
1893 }
1894 }
c7abc967 1895
38274997 1896 XDestroyImage( ximage );
dbda9e86 1897 /*
38274997 1898 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
dbda9e86 1899 */
ee4c6942
JS
1900}
1901#endif
a91b47e8
JS
1902
1903// A module to allow wxImage initialization/cleanup
1904// without calling these functions from app.cpp or from
1905// the user's application.
1906
1907class wxImageModule: public wxModule
1908{
1909DECLARE_DYNAMIC_CLASS(wxImageModule)
1910public:
1911 wxImageModule() {}
1912 bool OnInit() { wxImage::InitStandardHandlers(); return TRUE; };
1913 void OnExit() { wxImage::CleanUpHandlers(); };
1914};
1915
1916IMPLEMENT_DYNAMIC_CLASS(wxImageModule, wxModule)