]> git.saurik.com Git - wxWidgets.git/blame - src/common/image.cpp
suppressed compiler warning about unitialised umask value
[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{
dbda9e86 50
fd0eed64 51public:
dbda9e86
JS
52 wxImageRefData(void);
53 ~wxImageRefData(void);
54
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();
dbda9e86 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;
dbda9e86 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;
dbda9e86 158
50920146 159 wxCHECK_MSG( Ok(), image, _T("invalid image") );
dbda9e86 160
50920146 161 wxCHECK_MSG( (width > 0) && (height > 0), image, _T("invalid image size") );
dbda9e86 162
4bc67cc5 163 image.Create( width, height );
dbda9e86 164
4bc67cc5 165 char unsigned *data = image.GetData();
dbda9e86 166
50920146 167 wxCHECK_MSG( data, image, _T("unable to create image") );
dbda9e86 168
4bc67cc5
RR
169 if (M_IMGDATA->m_hasMask)
170 image.SetMaskColour( M_IMGDATA->m_maskRed, M_IMGDATA->m_maskGreen, M_IMGDATA->m_maskBlue );
dbda9e86 171
6e13c196
RR
172 long old_height = M_IMGDATA->m_height;
173 long old_width = M_IMGDATA->m_width;
dbda9e86 174
6e13c196
RR
175 char unsigned *source_data = M_IMGDATA->m_data;
176 char unsigned *target_data = data;
dbda9e86 177
6e13c196 178 for (long j = 0; j < height; j++)
4bc67cc5 179 {
6e13c196 180 long y_offset = (j * old_height / height) * old_width;
dbda9e86 181
6e13c196 182 for (long i = 0; i < width; i++)
4698648f 183 {
dbda9e86
JS
184 memcpy( target_data,
185 source_data + 3*(y_offset + ((i * old_width )/ width)),
186 3 );
6e13c196 187 target_data += 3;
4698648f 188 }
4bc67cc5 189 }
dbda9e86 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") );
dbda9e86 197
ef539066
RR
198 int w = M_IMGDATA->m_width;
199 int h = M_IMGDATA->m_height;
dbda9e86 200
50920146 201 wxCHECK_RET( (x>=0) && (y>=0) && (x<w) && (y<h), _T("invalid image index") );
dbda9e86 202
ef539066 203 long pos = (y * w + x) * 3;
dbda9e86 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") );
dbda9e86 213
ef539066
RR
214 int w = M_IMGDATA->m_width;
215 int h = M_IMGDATA->m_height;
dbda9e86 216
50920146 217 wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, _T("invalid image index") );
dbda9e86 218
ef539066 219 long pos = (y * w + x) * 3;
dbda9e86 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") );
dbda9e86 227
ef539066
RR
228 int w = M_IMGDATA->m_width;
229 int h = M_IMGDATA->m_height;
dbda9e86 230
50920146 231 wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, _T("invalid image index") );
dbda9e86 232
ef539066 233 long pos = (y * w + x) * 3;
dbda9e86 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") );
dbda9e86 241
ef539066
RR
242 int w = M_IMGDATA->m_width;
243 int h = M_IMGDATA->m_height;
dbda9e86 244
50920146 245 wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, _T("invalid image index") );
dbda9e86 246
ef539066 247 long pos = (y * w + x) * 3;
dbda9e86 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") );
dbda9e86 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") );
dbda9e86 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") );
dbda9e86 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") );
dbda9e86 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") );
dbda9e86 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") );
dbda9e86 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") );
dbda9e86 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") );
dbda9e86 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") );
dbda9e86 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 }
dbda9e86 357
3d05544e 358 else {
50920146 359 wxLogError( _T("Can't load image from file '%s': file does not exist."), filename.c_str() );
dbda9e86 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);
384
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();
dbda9e86 396
fd0eed64 397 m_refData = new wxImageRefData;
dbda9e86 398
fd0eed64 399 wxImageHandler *handler = FindHandler(type);
dbda9e86 400
4698648f 401 if (handler == NULL)
fd0eed64 402 {
50920146 403 wxLogWarning( _T("No image handler for type %d defined."), type );
dbda9e86 404
fd0eed64
RR
405 return FALSE;
406 }
dbda9e86 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
OK
431 wxCHECK_MSG( Ok(), FALSE, _T("invalid image") );
432
fd0eed64 433 wxImageHandler *handler = FindHandler(type);
50920146 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") );
9e9ee68e
VS
448
449 wxImageHandler *handler = FindHandlerMime(mimetype);
450
451 if (handler == NULL)
452 {
50920146 453 wxLogWarning( _T("No image handler for type %s defined."), mimetype.GetData() );
dbda9e86
JS
454
455 return FALSE;
fd0eed64 456 }
dbda9e86 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);
dbda9e86 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);
dbda9e86 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;
dbda9e86 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
3d05544e 588bool wxBMPHandler::LoadFile( wxImage *image, wxInputStream& stream )
01111366 589{
dbda9e86
JS
590 unsigned char *data, *ptr;
591 int done, i, bpp, planes, comp, ncolors, line, column,
592 linesize, linepos, rshift = 0, gshift = 0, bshift = 0;
593 unsigned char aByte;
594 short int word;
595 long int dbuf[4], dword, rmask = 0, gmask = 0, bmask = 0, offset,
596 size;
597 off_t start_offset = stream.TellI();
598 signed char bbuf[4];
599 struct _cmap
600 {
4698648f 601 unsigned char r, g, b;
dbda9e86
JS
602 }
603 *cmap = NULL;
0b4f9ee3 604#ifndef BI_RGB
01111366
RR
605#define BI_RGB 0
606#define BI_RLE8 1
607#define BI_RLE4 2
62448488 608#endif
dbda9e86 609
62448488 610#ifndef BI_BITFIELDS
01111366 611#define BI_BITFIELDS 3
0b4f9ee3 612#endif
dbda9e86
JS
613
614 image->Destroy();
615
616 done = 0;
617 /*
4698648f 618 * Reading the bmp header
01111366 619 */
dbda9e86
JS
620
621 stream.Read(&bbuf, 2);
622
623 stream.Read(dbuf, 4 * 4);
624
625 size = dbuf[0];
626 offset = dbuf[2];
627
628 stream.Read(dbuf, 4 * 2);
629 int width = (int)dbuf[0];
630 int height = (int)dbuf[1];
631 if (width > 32767)
632 {
50920146 633 wxLogError( _T("Image width > 32767 pixels for file\n") );
4698648f 634 return FALSE;
dbda9e86
JS
635 }
636 if (height > 32767)
637 {
50920146 638 wxLogError( _T("Image height > 32767 pixels for file\n") );
4698648f 639 return FALSE;
dbda9e86
JS
640 }
641 stream.Read(&word, 2);
642 planes = (int)word;
643 stream.Read(&word, 2);
644 bpp = (int)word;
645 if (bpp != 1 && bpp != 4 && bpp != 8 && bpp && 16 && bpp != 24 && bpp != 32)
646 {
50920146 647 wxLogError( _T("unknown bitdepth in file\n") );
4698648f 648 return FALSE;
dbda9e86
JS
649 }
650 stream.Read(dbuf, 4 * 4);
651 comp = (int)dbuf[0];
652 if (comp != BI_RGB && comp != BI_RLE4 && comp != BI_RLE8 && comp != BI_BITFIELDS)
653 {
50920146 654 wxLogError( _T("unknown encoding in Windows BMP file\n") );
4698648f 655 return FALSE;
dbda9e86
JS
656 }
657 stream.Read(dbuf, 4 * 2);
658 ncolors = (int)dbuf[0];
659 if (ncolors == 0)
660 ncolors = 1 << bpp;
661 /* some more sanity checks */
662 if (((comp == BI_RLE4) && (bpp != 4)) || ((comp == BI_RLE8) && (bpp != 8)) || ((comp == BI_BITFIELDS) && (bpp != 16 && bpp != 32)))
663 {
50920146 664 wxLogError( _T("encoding of BMP doesn't match bitdepth\n") );
4698648f 665 return FALSE;
dbda9e86
JS
666 }
667 if (bpp < 16)
668 {
4698648f 669 cmap = (struct _cmap *)malloc(sizeof(struct _cmap) * ncolors);
dbda9e86 670
4698648f 671 if (!cmap)
dbda9e86 672 {
50920146 673 wxLogError( _T("Cannot allocate RAM for color map in BMP file\n") );
dbda9e86
JS
674 return FALSE;
675 }
676 }
677 else
678 cmap = NULL;
679
680 image->Create( width, height );
681 ptr = image->GetData();
682 if (!ptr)
683 {
50920146 684 wxLogError( _T("Cannot allocate RAM for RGB data in file\n") );
4698648f 685 if (cmap)
dbda9e86 686 free(cmap);
4698648f 687 return FALSE;
dbda9e86
JS
688 }
689
690 /*
01111366
RR
691 * Reading the palette, if it exists.
692 */
dbda9e86
JS
693 if (bpp < 16 && ncolors != 0)
694 {
4698648f 695 for (i = 0; i < ncolors; i++)
dbda9e86
JS
696 {
697 stream.Read(bbuf, 4);
698 cmap[i].b = bbuf[0];
699 cmap[i].g = bbuf[1];
700 cmap[i].r = bbuf[2];
701 }
702 }
703 else if (bpp == 16 || bpp == 32)
704 {
4698648f 705 if (comp == BI_BITFIELDS)
dbda9e86
JS
706 {
707 int bit = 0;
708
709 stream.Read(dbuf, 4 * 3);
710 bmask = dbuf[0];
711 gmask = dbuf[1];
712 rmask = dbuf[2];
713 /* find shift amount.. ugly, but i can't think of a better way */
714 for (bit = 0; bit < bpp; bit++)
715 {
716 if (bmask & (1 << bit))
717 bshift = bit;
718 if (gmask & (1 << bit))
719 gshift = bit;
720 if (rmask & (1 << bit))
721 rshift = bit;
722 }
723 }
4698648f 724 else if (bpp == 16)
dbda9e86
JS
725 {
726 rmask = 0x7C00;
727 gmask = 0x03E0;
728 bmask = 0x001F;
729 rshift = 10;
730 gshift = 5;
731 bshift = 0;
732 }
4698648f 733 else if (bpp == 32)
dbda9e86
JS
734 {
735 rmask = 0x00FF0000;
736 gmask = 0x0000FF00;
737 bmask = 0x000000FF;
738 rshift = 16;
739 gshift = 8;
740 bshift = 0;
741 }
742 }
743
744 /*
bbe0af5b 745 * Reading the image data
01111366 746 */
dbda9e86
JS
747 stream.SeekI(start_offset + offset);
748 data = ptr;
749
750 /* set the whole image to the background color */
751 if (bpp < 16 && (comp == BI_RLE4 || comp == BI_RLE8))
752 {
4698648f 753 for (i = 0; i < width * height; i++)
dbda9e86
JS
754 {
755 *ptr++ = cmap[0].r;
756 *ptr++ = cmap[0].g;
757 *ptr++ = cmap[0].b;
758 }
4698648f 759 ptr = data;
dbda9e86
JS
760 }
761 line = 0;
762 column = 0;
01111366 763#define poffset (line * width * 3 + column * 3)
dbda9e86
JS
764
765 /*
01111366
RR
766 * BMPs are stored upside down... hmmmmmmmmmm....
767 */
dbda9e86
JS
768
769 linesize = ((width * bpp + 31) / 32) * 4;
770 for (line = (height - 1); line >= 0; line--)
771 {
4698648f
VZ
772 linepos = 0;
773 for (column = 0; column < width;)
dbda9e86
JS
774 {
775 if (bpp < 16)
776 {
777 int index;
778
779 linepos++;
780 aByte = stream.GetC();
781 if (bpp == 1)
782 {
783 int bit = 0;
784
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 {
50920146 798 wxLogError( _T("can't deal with 4bit encoded yet.\n") );
dbda9e86
JS
799 image->Destroy();
800 free(cmap);
801 return FALSE;
802 }
803 else
804 {
805 int nibble = 0;
806
807 for (nibble = 0; nibble < 2; nibble++)
808 {
809 index = ((aByte & (0xF0 >> nibble * 4)) >> (!nibble * 4));
810 if (index >= 16)
811 index = 15;
4698648f
VZ
812 ptr[poffset] = cmap[index].r;
813 ptr[poffset + 1] = cmap[index].g;
814 ptr[poffset + 2] = cmap[index].b;
815 column++;
dbda9e86 816 }
4698648f 817 }
dbda9e86
JS
818 }
819 else if (bpp == 8)
820 {
821 if (comp == BI_RLE8)
4698648f 822 {
dbda9e86
JS
823 unsigned char first;
824
825 first = aByte;
826 aByte = stream.GetC();
827 if (first == 0)
828 {
829 if (aByte == 0)
830 {
831 /* column = width; */
832 }
833 else if (aByte == 1)
834 {
835 column = width;
836 line = -1;
837 }
838 else if (aByte == 2)
839 {
840 aByte = stream.GetC();
841 column += aByte;
842 linepos = column * bpp / 8;
843 aByte = stream.GetC();
844 line += aByte;
845 }
846 else
847 {
848 int absolute = aByte;
849
850 for (i = 0; i < absolute; i++)
851 {
852 linepos++;
853 aByte = stream.GetC();
854 ptr[poffset] = cmap[aByte].r;
855 ptr[poffset + 1] = cmap[aByte].g;
856 ptr[poffset + 2] = cmap[aByte].b;
857 column++;
858 }
859 if (absolute & 0x01)
860 aByte = stream.GetC();
861 }
862 }
863 else
864 {
865 for (i = 0; i < first; i++)
866 {
867 ptr[poffset] = cmap[aByte].r;
868 ptr[poffset + 1] = cmap[aByte].g;
869 ptr[poffset + 2] = cmap[aByte].b;
870 column++;
871 linepos++;
872 }
873 }
4698648f 874 }
dbda9e86 875 else
4698648f 876 {
dbda9e86
JS
877 ptr[poffset] = cmap[aByte].r;
878 ptr[poffset + 1] = cmap[aByte].g;
879 ptr[poffset + 2] = cmap[aByte].b;
880 column++;
881 linepos += size;
4698648f 882 }
dbda9e86 883 }
4698648f 884 }
dbda9e86 885 else if (bpp == 24)
4698648f 886 {
dbda9e86
JS
887 stream.Read(&bbuf, 3);
888 linepos += 3;
889 ptr[poffset] = (unsigned char)bbuf[2];
890 ptr[poffset + 1] = (unsigned char)bbuf[1];
891 ptr[poffset + 2] = (unsigned char)bbuf[0];
892 column++;
4698648f 893 }
dbda9e86 894 else if (bpp == 16)
4698648f 895 {
dbda9e86
JS
896 unsigned char temp;
897
898 stream.Read(&word, 2);
899 linepos += 2;
900 temp = (word & rmask) >> rshift;
901 ptr[poffset] = temp;
902 temp = (word & gmask) >> gshift;
903 ptr[poffset + 1] = temp;
904 temp = (word & bmask) >> gshift;
905 ptr[poffset + 2] = temp;
906 column++;
4698648f 907 }
dbda9e86 908 else
4698648f 909 {
dbda9e86
JS
910 unsigned char temp;
911
912 stream.Read(&dword, 4);
913 linepos += 4;
914 temp = (dword & rmask) >> rshift;
915 ptr[poffset] = temp;
916 temp = (dword & gmask) >> gshift;
917 ptr[poffset + 1] = temp;
918 temp = (dword & bmask) >> bshift;
919 ptr[poffset + 2] = temp;
920 column++;
4698648f
VZ
921 }
922 }
dbda9e86 923 while ((linepos < linesize) && (comp != 1) && (comp != 2))
4698648f 924 {
dbda9e86
JS
925 stream.Read(&aByte, 1);
926 linepos += 1;
927 if (stream.LastError() != wxStream_NOERROR)
928 break;
4698648f 929 }
01111366 930 }
dbda9e86
JS
931 if (cmap) free(cmap);
932
933 image->SetMask( FALSE );
934
935 return TRUE;
01111366 936}
e02afc7a 937#endif // wxUSE_STREAMS
01111366 938
e3554471
JS
939#ifdef __WXMSW__
940
941wxBitmap wxImage::ConvertToBitmap() const
942{
dbda9e86 943 // sizeLimit is the MS upper limit for the DIB size
bba6f3bd 944 int sizeLimit = 1024*768*3;
dbda9e86
JS
945
946 // width and height of the device-dependent bitmap
bba6f3bd
UA
947 int width = GetWidth();
948 int bmpHeight = GetHeight();
dbda9e86
JS
949
950 // calc the number of bytes per scanline and padding
bba6f3bd
UA
951 int bytePerLine = width*3;
952 int sizeDWORD = sizeof( DWORD );
953 div_t lineBoundary = div( bytePerLine, sizeDWORD );
954 int padding = 0;
955 if( lineBoundary.rem > 0 )
956 {
957 padding = sizeDWORD - lineBoundary.rem;
958 bytePerLine += padding;
959 }
dbda9e86 960 // calc the number of DIBs and heights of DIBs
bba6f3bd
UA
961 int numDIB = 1;
962 int hRemain = 0;
963 int height = sizeLimit/bytePerLine;
964 if( height >= bmpHeight )
965 height = bmpHeight;
966 else
967 {
968 div_t result = div( bmpHeight, height );
969 numDIB = result.quot;
dbda9e86
JS
970 hRemain = result.rem;
971 if( hRemain >0 ) numDIB++;
bba6f3bd 972 }
dbda9e86
JS
973
974 // set bitmap parameters
bba6f3bd 975 wxBitmap bitmap;
50920146 976 wxCHECK_MSG( Ok(), bitmap, _T("invalid image") );
bba6f3bd
UA
977 bitmap.SetWidth( width );
978 bitmap.SetHeight( bmpHeight );
979 bitmap.SetDepth( wxDisplayDepth() );
dbda9e86
JS
980
981 // create a DIB header
bba6f3bd
UA
982 int headersize = sizeof(BITMAPINFOHEADER);
983 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
50920146 984 wxCHECK_MSG( lpDIBh, bitmap, _T("could not allocate memory for DIB header") );
dbda9e86 985 // Fill in the DIB header
bba6f3bd
UA
986 lpDIBh->bmiHeader.biSize = headersize;
987 lpDIBh->bmiHeader.biWidth = (DWORD)width;
988 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
989 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
dbda9e86
JS
990 // the general formula for biSizeImage:
991 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
bba6f3bd
UA
992 lpDIBh->bmiHeader.biPlanes = 1;
993 lpDIBh->bmiHeader.biBitCount = 24;
994 lpDIBh->bmiHeader.biCompression = BI_RGB;
995 lpDIBh->bmiHeader.biClrUsed = 0;
dbda9e86 996 // These seem not really needed for our purpose here.
bba6f3bd
UA
997 lpDIBh->bmiHeader.biClrImportant = 0;
998 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
999 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
dbda9e86 1000 // memory for DIB data
bba6f3bd
UA
1001 unsigned char *lpBits;
1002 lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
1003 if( !lpBits )
1004 {
50920146 1005 wxFAIL_MSG( _T("could not allocate memory for DIB") );
bba6f3bd
UA
1006 free( lpDIBh );
1007 return bitmap;
1008 }
dbda9e86
JS
1009
1010 // create and set the device-dependent bitmap
bba6f3bd
UA
1011 HDC hdc = ::GetDC(NULL);
1012 HDC memdc = ::CreateCompatibleDC( hdc );
1013 HBITMAP hbitmap;
1014 hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
1015 ::SelectObject( memdc, hbitmap);
dbda9e86
JS
1016
1017 // copy image data into DIB data and then into DDB (in a loop)
bba6f3bd
UA
1018 unsigned char *data = GetData();
1019 int i, j, n;
1020 int origin = 0;
1021 unsigned char *ptdata = data;
1022 unsigned char *ptbits;
dbda9e86 1023
bba6f3bd
UA
1024 for( n=0; n<numDIB; n++ )
1025 {
dbda9e86
JS
1026 if( numDIB > 1 && n == numDIB-1 && hRemain > 0 )
1027 {
1028 // redefine height and size of the (possibly) last smaller DIB
1029 // memory is not reallocated
1030 height = hRemain;
bba6f3bd
UA
1031 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
1032 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
dbda9e86 1033 }
bba6f3bd 1034 ptbits = lpBits;
dbda9e86 1035
bba6f3bd
UA
1036 for( j=0; j<height; j++ )
1037 {
1038 for( i=0; i<width; i++ )
1039 {
1040 *(ptbits++) = *(ptdata+2);
1041 *(ptbits++) = *(ptdata+1);
1042 *(ptbits++) = *(ptdata );
1043 ptdata += 3;
dbda9e86
JS
1044 }
1045 for( i=0; i< padding; i++ ) *(ptbits++) = 0;
bba6f3bd
UA
1046 }
1047 ::StretchDIBits( memdc, 0, origin, width, height,\
dbda9e86
JS
1048 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
1049 origin += height;
1050 // if numDIB = 1, lines below can also be used
1051 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
1052 // The above line is equivalent to the following two lines.
1053 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
1054 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
1055 // or the following lines
1056 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
1057 // HDC memdc = ::CreateCompatibleDC( hdc );
1058 // ::SelectObject( memdc, hbitmap);
1059 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
1060 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
1061 // ::SelectObject( memdc, 0 );
1062 // ::DeleteDC( memdc );
e3554471 1063 }
bba6f3bd 1064 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
dbda9e86
JS
1065
1066 // similarly, created an mono-bitmap for the possible mask
bba6f3bd
UA
1067 if( HasMask() )
1068 {
1069 hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL );
1070 ::SelectObject( memdc, hbitmap);
1071 if( numDIB == 1 ) height = bmpHeight;
1072 else height = sizeLimit/bytePerLine;
1073 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
1074 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
1075 origin = 0;
1076 unsigned char r = GetMaskRed();
1077 unsigned char g = GetMaskGreen();
1078 unsigned char b = GetMaskBlue();
1079 unsigned char zero = 0, one = 255;
1080 ptdata = data;
1081 for( n=0; n<numDIB; n++ )
1082 {
1083 if( numDIB > 1 && n == numDIB - 1 && hRemain > 0 )
1084 {
dbda9e86
JS
1085 // redefine height and size of the (possibly) last smaller DIB
1086 // memory is not reallocated
1087 height = hRemain;
bba6f3bd
UA
1088 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
1089 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
dbda9e86 1090 }
bba6f3bd
UA
1091 ptbits = lpBits;
1092 for( int j=0; j<height; j++ )
1093 {
dbda9e86 1094 for(i=0; i<width; i++ )
bba6f3bd
UA
1095 {
1096 if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
1097 {
1098 *(ptbits++) = one;
1099 *(ptbits++) = one;
1100 *(ptbits++) = one;
1101 }
1102 else
1103 {
1104 *(ptbits++) = zero;
1105 *(ptbits++) = zero;
1106 *(ptbits++) = zero;
1107 }
1108 }
dbda9e86 1109 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
bba6f3bd
UA
1110 }
1111 ::StretchDIBits( memdc, 0, origin, width, height,\
dbda9e86
JS
1112 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
1113 origin += height;
1114 }
1115 // create a wxMask object
bba6f3bd
UA
1116 wxMask *mask = new wxMask();
1117 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
1118 bitmap.SetMask( mask );
dbda9e86
JS
1119 // It will be deleted when the wxBitmap object is deleted (as of 01/1999)
1120 /* The following can also be used but is slow to run
bba6f3bd
UA
1121 wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
1122 wxMask *mask = new wxMask( bitmap, colour );
1123 bitmap.SetMask( mask );
dbda9e86 1124 */
bba6f3bd 1125 }
dbda9e86
JS
1126
1127 // free allocated resources
bba6f3bd
UA
1128 ::SelectObject( memdc, 0 );
1129 ::DeleteDC( memdc );
1130 ::ReleaseDC(NULL, hdc);
1131 free(lpDIBh);
1132 free(lpBits);
dbda9e86
JS
1133
1134 // check the wxBitmap object
bba6f3bd
UA
1135 if( bitmap.GetHBITMAP() )
1136 bitmap.SetOk( TRUE );
1137 else
1138 bitmap.SetOk( FALSE );
dbda9e86 1139
bba6f3bd 1140 return bitmap;
e3554471
JS
1141}
1142
e3554471
JS
1143wxImage::wxImage( const wxBitmap &bitmap )
1144{
dbda9e86 1145 // check the bitmap
bba6f3bd
UA
1146 if( !bitmap.Ok() )
1147 {
50920146 1148 wxFAIL_MSG( _T("invalid bitmap") );
bba6f3bd
UA
1149 return;
1150 }
dbda9e86
JS
1151
1152 // create an wxImage object
bba6f3bd
UA
1153 int width = bitmap.GetWidth();
1154 int height = bitmap.GetHeight();
1155 Create( width, height );
1156 unsigned char *data = GetData();
1157 if( !data )
1158 {
50920146 1159 wxFAIL_MSG( _T("could not allocate data for image") );
bba6f3bd
UA
1160 return;
1161 }
dbda9e86
JS
1162
1163 // calc the number of bytes per scanline and padding in the DIB
bba6f3bd
UA
1164 int bytePerLine = width*3;
1165 int sizeDWORD = sizeof( DWORD );
1166 div_t lineBoundary = div( bytePerLine, sizeDWORD );
1167 int padding = 0;
1168 if( lineBoundary.rem > 0 )
1169 {
1170 padding = sizeDWORD - lineBoundary.rem;
1171 bytePerLine += padding;
1172 }
dbda9e86
JS
1173
1174 // create a DIB header
bba6f3bd
UA
1175 int headersize = sizeof(BITMAPINFOHEADER);
1176 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
1177 if( !lpDIBh )
1178 {
50920146 1179 wxFAIL_MSG( _T("could not allocate data for DIB header") );
bba6f3bd
UA
1180 free( data );
1181 return;
1182 }
dbda9e86 1183 // Fill in the DIB header
bba6f3bd
UA
1184 lpDIBh->bmiHeader.biSize = headersize;
1185 lpDIBh->bmiHeader.biWidth = width;
1186 lpDIBh->bmiHeader.biHeight = -height;
1187 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
1188 lpDIBh->bmiHeader.biPlanes = 1;
1189 lpDIBh->bmiHeader.biBitCount = 24;
1190 lpDIBh->bmiHeader.biCompression = BI_RGB;
1191 lpDIBh->bmiHeader.biClrUsed = 0;
dbda9e86 1192 // These seem not really needed for our purpose here.
bba6f3bd
UA
1193 lpDIBh->bmiHeader.biClrImportant = 0;
1194 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
1195 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
dbda9e86 1196 // memory for DIB data
bba6f3bd
UA
1197 unsigned char *lpBits;
1198 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
1199 if( !lpBits )
e3554471 1200 {
50920146 1201 wxFAIL_MSG( _T("could not allocate data for DIB") );
bba6f3bd
UA
1202 free( data );
1203 free( lpDIBh );
1204 return;
4698648f 1205 }
bba6f3bd 1206
dbda9e86 1207 // copy data from the device-dependent bitmap to the DIB
bba6f3bd
UA
1208 HDC hdc = ::GetDC(NULL);
1209 HBITMAP hbitmap;
1210 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
1211 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
dbda9e86
JS
1212
1213 // copy DIB data into the wxImage object
bba6f3bd
UA
1214 int i, j;
1215 unsigned char *ptdata = data;
1216 unsigned char *ptbits = lpBits;
1217 for( i=0; i<height; i++ )
1218 {
1219 for( j=0; j<width; j++ )
1220 {
1221 *(ptdata++) = *(ptbits+2);
1222 *(ptdata++) = *(ptbits+1);
1223 *(ptdata++) = *(ptbits );
1224 ptbits += 3;
dbda9e86 1225 }
bba6f3bd
UA
1226 ptbits += padding;
1227 }
dbda9e86
JS
1228
1229 // similarly, set data according to the possible mask bitmap
bba6f3bd
UA
1230 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
1231 {
1232 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
dbda9e86 1233 // memory DC created, color set, data copied, and memory DC deleted
bba6f3bd
UA
1234 HDC memdc = ::CreateCompatibleDC( hdc );
1235 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
1236 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
1237 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1238 ::DeleteDC( memdc );
dbda9e86 1239 // background color set to RGB(16,16,16) in consistent with wxGTK
bba6f3bd
UA
1240 unsigned char r=16, g=16, b=16;
1241 ptdata = data;
1242 ptbits = lpBits;
1243 for( i=0; i<height; i++ )
1244 {
1245 for( j=0; j<width; j++ )
1246 {
1247 if( *ptbits != 0 )
dbda9e86
JS
1248 ptdata += 3;
1249 else
bba6f3bd
UA
1250 {
1251 *(ptdata++) = r;
1252 *(ptdata++) = g;
1253 *(ptdata++) = b;
dbda9e86 1254 }
bba6f3bd
UA
1255 ptbits += 3;
1256 }
1257 ptbits += padding;
1258 }
1259 SetMaskColour( r, g, b );
1260 SetMask( TRUE );
1261 }
1262 else
1263 {
1264 SetMask( FALSE );
1265 }
dbda9e86 1266 // free allocated resources
bba6f3bd
UA
1267 ::ReleaseDC(NULL, hdc);
1268 free(lpDIBh);
1269 free(lpBits);
e3554471
JS
1270}
1271
1272#endif
1273
99c67c77
RR
1274#ifdef __WXGTK__
1275
83624f79
RR
1276#include "gtk/gtk.h"
1277#include "gdk/gdk.h"
1278#include "gdk/gdkx.h"
1279
ba0730de
RR
1280#if (GTK_MINOR_VERSION > 0)
1281#include "gdk/gdkrgb.h"
1282#endif
1283
99c67c77
RR
1284wxBitmap wxImage::ConvertToBitmap() const
1285{
1286 wxBitmap bitmap;
dbda9e86 1287
50920146 1288 wxCHECK_MSG( Ok(), bitmap, _T("invalid image") );
dbda9e86 1289
99c67c77
RR
1290 int width = GetWidth();
1291 int height = GetHeight();
dbda9e86 1292
99c67c77
RR
1293 bitmap.SetHeight( height );
1294 bitmap.SetWidth( width );
dbda9e86 1295
ba0730de
RR
1296 bitmap.SetPixmap( gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, -1 ) );
1297
1298 // Retrieve depth
1299
1300 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
1301 if (visual == NULL) visual = gdk_window_get_visual( (GdkWindow*) &gdk_root_parent );
1302 int bpp = visual->depth;
1303
1304 bitmap.SetDepth( bpp );
1305
1306 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
1307 if (bpp < 8) bpp = 8;
1308
1309#if (GTK_MINOR_VERSION > 0)
1310
1311 if (!HasMask() && (bpp > 8))
1312 {
1313 static bool s_hasInitialized = FALSE;
1314
1315 if (!s_hasInitialized)
1316 {
1317 gdk_rgb_init();
1318 s_hasInitialized = TRUE;
1319 }
1320
1321 GdkGC *gc = gdk_gc_new( bitmap.GetPixmap() );
1322
1323 gdk_draw_rgb_image( bitmap.GetPixmap(),
1324 gc,
1325 0, 0,
1326 width, height,
1327 GDK_RGB_DITHER_NONE,
1328 GetData(),
1329 width*3 );
1330
1331 gdk_gc_unref( gc );
1332
1333 return bitmap;
1334 }
1335
1336#endif
1337
1338 // Create picture image
dbda9e86 1339
99c67c77 1340 GdkImage *data_image =
dbda9e86
JS
1341 gdk_image_new( GDK_IMAGE_FASTEST, gdk_visual_get_system(), width, height );
1342
ba0730de 1343 // Create mask image
dbda9e86 1344
99c67c77 1345 GdkImage *mask_image = (GdkImage*) NULL;
dbda9e86 1346
99c67c77
RR
1347 if (HasMask())
1348 {
1349 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
dbda9e86 1350
99c67c77 1351 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
dbda9e86 1352
4698648f
VZ
1353 wxMask *mask = new wxMask();
1354 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
dbda9e86 1355
4698648f 1356 bitmap.SetMask( mask );
99c67c77 1357 }
dbda9e86 1358
99c67c77 1359 // Render
dbda9e86 1360
99c67c77
RR
1361 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1362 byte_order b_o = RGB;
dbda9e86 1363
99c67c77
RR
1364 if (bpp >= 24)
1365 {
1366 GdkVisual *visual = gdk_visual_get_system();
1367 if ((visual->red_mask > visual->green_mask) && (visual->green_mask > visual->blue_mask)) b_o = RGB;
1368 else if ((visual->red_mask > visual->blue_mask) && (visual->blue_mask > visual->green_mask)) b_o = RGB;
1369 else if ((visual->blue_mask > visual->red_mask) && (visual->red_mask > visual->green_mask)) b_o = BRG;
1370 else if ((visual->blue_mask > visual->green_mask) && (visual->green_mask > visual->red_mask)) b_o = BGR;
1371 else if ((visual->green_mask > visual->red_mask) && (visual->red_mask > visual->blue_mask)) b_o = GRB;
1372 else if ((visual->green_mask > visual->blue_mask) && (visual->blue_mask > visual->red_mask)) b_o = GBR;
1373 }
dbda9e86 1374
99c67c77
RR
1375 int r_mask = GetMaskRed();
1376 int g_mask = GetMaskGreen();
1377 int b_mask = GetMaskBlue();
dbda9e86 1378
99c67c77 1379 unsigned char* data = GetData();
dbda9e86 1380
99c67c77
RR
1381 int index = 0;
1382 for (int y = 0; y < height; y++)
1383 {
1384 for (int x = 0; x < width; x++)
1385 {
1386 int r = data[index];
4698648f 1387 index++;
99c67c77 1388 int g = data[index];
4698648f 1389 index++;
99c67c77 1390 int b = data[index];
4698648f 1391 index++;
dbda9e86 1392
4698648f
VZ
1393 if (HasMask())
1394 {
1395 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1396 gdk_image_put_pixel( mask_image, x, y, 1 );
1397 else
1398 gdk_image_put_pixel( mask_image, x, y, 0 );
1399 }
dbda9e86 1400
4698648f
VZ
1401 if (HasMask())
1402 {
1403 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1404 gdk_image_put_pixel( mask_image, x, y, 1 );
1405 else
1406 gdk_image_put_pixel( mask_image, x, y, 0 );
1407 }
dbda9e86 1408
4698648f
VZ
1409 switch (bpp)
1410 {
dbda9e86 1411 case 8:
4698648f 1412 {
f6fcbb63 1413 int pixel = -1;
4698648f
VZ
1414 if (wxTheApp->m_colorCube)
1415 {
38274997 1416 pixel = wxTheApp->m_colorCube[ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
4698648f 1417 }
f6fcbb63 1418 else
4698648f
VZ
1419 {
1420 GdkColormap *cmap = gtk_widget_get_default_colormap();
f6fcbb63
RR
1421 GdkColor *colors = cmap->colors;
1422 int max = 3 * (65536);
dbda9e86 1423
f6fcbb63
RR
1424 for (int i = 0; i < cmap->size; i++)
1425 {
1426 int rdiff = (r << 8) - colors[i].red;
1427 int gdiff = (g << 8) - colors[i].green;
1428 int bdiff = (b << 8) - colors[i].blue;
1429 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1430 if (sum < max) { pixel = i; max = sum; }
4698648f 1431 }
99c67c77 1432 }
dbda9e86 1433
4698648f 1434 gdk_image_put_pixel( data_image, x, y, pixel );
dbda9e86 1435
4698648f
VZ
1436 break;
1437 }
dbda9e86 1438 case 15:
4698648f
VZ
1439 {
1440 guint32 pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1441 gdk_image_put_pixel( data_image, x, y, pixel );
1442 break;
1443 }
dbda9e86 1444 case 16:
4698648f
VZ
1445 {
1446 guint32 pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1447 gdk_image_put_pixel( data_image, x, y, pixel );
1448 break;
1449 }
dbda9e86
JS
1450 case 32:
1451 case 24:
4698648f
VZ
1452 {
1453 guint32 pixel = 0;
1454 switch (b_o)
1455 {
dbda9e86
JS
1456 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1457 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1458 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1459 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1460 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1461 case GBR: pixel = (g << 16) | (b << 8) | r; break;
4698648f
VZ
1462 }
1463 gdk_image_put_pixel( data_image, x, y, pixel );
1464 }
dbda9e86 1465 default: break;
4698648f 1466 }
99c67c77
RR
1467 } // for
1468 } // for
dbda9e86 1469
99c67c77 1470 // Blit picture
dbda9e86 1471
99c67c77 1472 GdkGC *data_gc = gdk_gc_new( bitmap.GetPixmap() );
dbda9e86 1473
99c67c77 1474 gdk_draw_image( bitmap.GetPixmap(), data_gc, data_image, 0, 0, 0, 0, width, height );
dbda9e86 1475
99c67c77
RR
1476 gdk_image_destroy( data_image );
1477 gdk_gc_unref( data_gc );
dbda9e86 1478
99c67c77 1479 // Blit mask
dbda9e86 1480
99c67c77
RR
1481 if (HasMask())
1482 {
1483 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
dbda9e86 1484
99c67c77 1485 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
dbda9e86 1486
99c67c77
RR
1487 gdk_image_destroy( mask_image );
1488 gdk_gc_unref( mask_gc );
1489 }
dbda9e86 1490
99c67c77
RR
1491 return bitmap;
1492}
1493
1494wxImage::wxImage( const wxBitmap &bitmap )
1495{
50920146 1496 wxCHECK_RET( bitmap.Ok(), _T("invalid bitmap") );
dbda9e86 1497
99c67c77 1498 GdkImage *gdk_image = gdk_image_get( bitmap.GetPixmap(),
dbda9e86
JS
1499 0, 0,
1500 bitmap.GetWidth(), bitmap.GetHeight() );
1501
50920146 1502 wxCHECK_RET( gdk_image, _T("couldn't create image") );
dbda9e86 1503
99c67c77
RR
1504 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1505 char unsigned *data = GetData();
dbda9e86 1506
99c67c77
RR
1507 if (!data)
1508 {
1509 gdk_image_destroy( gdk_image );
50920146 1510 wxFAIL_MSG( _T("couldn't create image") );
4698648f 1511 return;
99c67c77 1512 }
dbda9e86 1513
99c67c77
RR
1514 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1515 if (bitmap.GetMask())
1516 {
1517 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
dbda9e86
JS
1518 0, 0,
1519 bitmap.GetWidth(), bitmap.GetHeight() );
1520
4698648f 1521 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
99c67c77 1522 }
dbda9e86 1523
99c67c77
RR
1524 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
1525 if (visual == NULL) visual = gdk_window_get_visual( (GdkWindow*) &gdk_root_parent );
1526 int bpp = visual->depth;
1527 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
dbda9e86 1528
99c67c77 1529 GdkColormap *cmap = gtk_widget_get_default_colormap();
dbda9e86 1530
99c67c77
RR
1531 long pos = 0;
1532 for (int j = 0; j < bitmap.GetHeight(); j++)
1533 {
1534 for (int i = 0; i < bitmap.GetWidth(); i++)
1535 {
1536 int pixel = gdk_image_get_pixel( gdk_image, i, j );
1537 if (bpp <= 8)
1538 {
1539 data[pos] = cmap->colors[pixel].red >> 8;
1540 data[pos+1] = cmap->colors[pixel].green >> 8;
1541 data[pos+2] = cmap->colors[pixel].blue >> 8;
1542 } else if (bpp == 15)
1543 {
1544 data[pos] = (pixel >> 7) & 0xf8;
1545 data[pos+1] = (pixel >> 2) & 0xf8;
1546 data[pos+2] = (pixel << 3) & 0xf8;
1547 } else if (bpp == 16)
1548 {
1549 data[pos] = (pixel >> 8) & 0xf8;
1550 data[pos+1] = (pixel >> 3) & 0xfc;
1551 data[pos+2] = (pixel << 3) & 0xf8;
1552 } else
1553 {
1554 data[pos] = (pixel >> 16) & 0xff;
1555 data[pos+1] = (pixel >> 8) & 0xff;
1556 data[pos+2] = pixel & 0xff;
1557 }
dbda9e86 1558
4698648f
VZ
1559 if (gdk_image_mask)
1560 {
1561 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1562 if (mask_pixel == 0)
1563 {
99c67c77
RR
1564 data[pos] = 16;
1565 data[pos+1] = 16;
1566 data[pos+2] = 16;
dbda9e86 1567 }
4698648f 1568 }
dbda9e86 1569
99c67c77
RR
1570 pos += 3;
1571 }
1572 }
dbda9e86 1573
99c67c77
RR
1574 gdk_image_destroy( gdk_image );
1575 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1576}
1577
1578#endif
ee4c6942 1579
ee4c6942 1580#ifdef __WXMOTIF__
b75867a6
RR
1581
1582#include <Xm/Xm.h>
1583#include "wx/utils.h"
38274997 1584#include <math.h>
b75867a6 1585
ee4c6942
JS
1586wxBitmap wxImage::ConvertToBitmap() const
1587{
b75867a6 1588 wxBitmap bitmap;
dbda9e86 1589
50920146 1590 wxCHECK_MSG( Ok(), bitmap, _T("invalid image") );
a91b47e8 1591
b75867a6
RR
1592 int width = GetWidth();
1593 int height = GetHeight();
dbda9e86 1594
b75867a6
RR
1595 bitmap.SetHeight( height );
1596 bitmap.SetWidth( width );
dbda9e86 1597
b75867a6
RR
1598 Display *dpy = (Display*) wxGetDisplay();
1599 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1600 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
dbda9e86 1601
b75867a6
RR
1602 // Create image
1603
1604 XImage *data_image = XCreateImage( dpy, vis, bpp, ZPixmap, 0, 0, width, height, 32, 0 );
a91b47e8 1605 data_image->data = (char*) malloc( data_image->bytes_per_line * data_image->height );
dbda9e86 1606
b75867a6 1607 bitmap.Create( width, height, bpp );
a91b47e8 1608
dbda9e86 1609 /*
b75867a6 1610 // Create mask
dbda9e86
JS
1611
1612 GdkImage *mask_image = (GdkImage*) NULL;
1613
1614 if (HasMask())
1615 {
b75867a6 1616 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
dbda9e86
JS
1617
1618 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1619
1620 wxMask *mask = new wxMask();
1621 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1622
1623 bitmap.SetMask( mask );
1624 }
1625 */
1626
b75867a6
RR
1627 // Retrieve depth info
1628
1629 XVisualInfo vinfo_template;
1630 XVisualInfo *vi;
1631
1632 vinfo_template.visual = vis;
1633 vinfo_template.visualid = XVisualIDFromVisual( vis );
1634 vinfo_template.depth = bpp;
1635 int nitem = 0;
1636
1637 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1638
1639 if (!vi)
1640 {
1641 printf("no visual.\n" );
1642 return wxNullBitmap;
1643 }
dbda9e86 1644
38274997 1645 XFree( vi );
a91b47e8 1646
b75867a6
RR
1647 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1648 if (bpp < 8) bpp = 8;
dbda9e86 1649
b75867a6 1650 // Render
dbda9e86 1651
b75867a6
RR
1652 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1653 byte_order b_o = RGB;
dbda9e86 1654
b75867a6
RR
1655 if (bpp >= 24)
1656 {
1657 if ((vi->red_mask > vi->green_mask) && (vi->green_mask > vi->blue_mask)) b_o = RGB;
1658 else if ((vi->red_mask > vi->blue_mask) && (vi->blue_mask > vi->green_mask)) b_o = RGB;
1659 else if ((vi->blue_mask > vi->red_mask) && (vi->red_mask > vi->green_mask)) b_o = BRG;
1660 else if ((vi->blue_mask > vi->green_mask) && (vi->green_mask > vi->red_mask)) b_o = BGR;
1661 else if ((vi->green_mask > vi->red_mask) && (vi->red_mask > vi->blue_mask)) b_o = GRB;
1662 else if ((vi->green_mask > vi->blue_mask) && (vi->blue_mask > vi->red_mask)) b_o = GBR;
1663 }
dbda9e86
JS
1664
1665 /*
b75867a6
RR
1666 int r_mask = GetMaskRed();
1667 int g_mask = GetMaskGreen();
1668 int b_mask = GetMaskBlue();
dbda9e86
JS
1669 */
1670
38274997
RR
1671 XColor colors[256];
1672 if (bpp == 8)
1673 {
dbda9e86
JS
1674 Colormap cmap = (Colormap) wxTheApp->GetMainColormap( dpy );
1675
38274997 1676 for (int i = 0; i < 256; i++) colors[i].pixel = i;
dbda9e86 1677 XQueryColors( dpy, cmap, colors, 256 );
38274997 1678 }
dbda9e86 1679
b75867a6 1680 unsigned char* data = GetData();
dbda9e86 1681
b75867a6
RR
1682 int index = 0;
1683 for (int y = 0; y < height; y++)
1684 {
1685 for (int x = 0; x < width; x++)
1686 {
1687 int r = data[index];
dbda9e86 1688 index++;
b75867a6 1689 int g = data[index];
dbda9e86 1690 index++;
b75867a6 1691 int b = data[index];
dbda9e86
JS
1692 index++;
1693
1694 /*
1695 if (HasMask())
1696 {
1697 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1698 gdk_image_put_pixel( mask_image, x, y, 1 );
1699 else
1700 gdk_image_put_pixel( mask_image, x, y, 0 );
1701 }
1702 */
1703
1704 switch (bpp)
1705 {
1706 case 8:
1707 {
b75867a6 1708 int pixel = -1;
dbda9e86
JS
1709 /*
1710 if (wxTheApp->m_colorCube)
1711 {
1712 pixel = wxTheApp->m_colorCube
1713 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
b75867a6
RR
1714 }
1715 else
dbda9e86
JS
1716 {
1717 */
1718 int max = 3 * (65536);
1719 for (int i = 0; i < 256; i++)
1720 {
1721 int rdiff = (r << 8) - colors[i].red;
1722 int gdiff = (g << 8) - colors[i].green;
1723 int bdiff = (b << 8) - colors[i].blue;
1724 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1725 if (sum < max) { pixel = i; max = sum; }
1726 }
1727 /*
1728 }
1729 */
1730 XPutPixel( data_image, x, y, pixel );
1731 break;
1732 }
1733 case 15:
1734 {
1735 int pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1736 XPutPixel( data_image, x, y, pixel );
1737 break;
1738 }
1739 case 16:
1740 {
1741 int pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1742 XPutPixel( data_image, x, y, pixel );
1743 break;
1744 }
1745 case 32:
1746 case 24:
1747 {
1748 int pixel = 0;
1749 switch (b_o)
1750 {
1751 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1752 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1753 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1754 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1755 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1756 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1757 }
1758 XPutPixel( data_image, x, y, pixel );
1759 }
1760 default: break;
1761 }
b75867a6
RR
1762 } // for
1763 } // for
dbda9e86 1764
b75867a6 1765 // Blit picture
dbda9e86 1766
b75867a6
RR
1767 XGCValues gcvalues;
1768 gcvalues.foreground = BlackPixel( dpy, DefaultScreen( dpy ) );
1769 GC gc = XCreateGC( dpy, RootWindow ( dpy, DefaultScreen(dpy) ), GCForeground, &gcvalues );
1770 XPutImage( dpy, (Drawable)bitmap.GetPixmap(), gc, data_image, 0, 0, 0, 0, width, height );
dbda9e86 1771
b75867a6
RR
1772 XDestroyImage( data_image );
1773 XFreeGC( dpy, gc );
dbda9e86
JS
1774
1775 /*
b75867a6 1776 // Blit mask
dbda9e86
JS
1777
1778 if (HasMask())
1779 {
1780 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
1781
b75867a6 1782 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
dbda9e86
JS
1783
1784 gdk_image_destroy( mask_image );
1785 gdk_gc_unref( mask_gc );
1786 }
1787 */
1788
b75867a6 1789 return bitmap;
ee4c6942
JS
1790}
1791
1792wxImage::wxImage( const wxBitmap &bitmap )
1793{
50920146 1794 wxCHECK_RET( bitmap.Ok(), _T("invalid bitmap") );
dbda9e86 1795
38274997
RR
1796 Display *dpy = (Display*) wxGetDisplay();
1797 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1798 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1799
1800 XImage *ximage = XGetImage( dpy,
dbda9e86
JS
1801 (Drawable)bitmap.GetPixmap(),
1802 0, 0,
1803 bitmap.GetWidth(), bitmap.GetHeight(),
1804 AllPlanes, ZPixmap );
1805
50920146 1806 wxCHECK_RET( ximage, _T("couldn't create image") );
dbda9e86 1807
38274997
RR
1808 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1809 char unsigned *data = GetData();
dbda9e86 1810
38274997
RR
1811 if (!data)
1812 {
1813 XDestroyImage( ximage );
50920146 1814 wxFAIL_MSG( _T("couldn't create image") );
38274997
RR
1815 return;
1816 }
dbda9e86
JS
1817
1818 /*
38274997
RR
1819 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1820 if (bitmap.GetMask())
1821 {
dbda9e86
JS
1822 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1823 0, 0,
1824 bitmap.GetWidth(), bitmap.GetHeight() );
1825
1826 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1827 }
1828 */
1829
38274997
RR
1830 // Retrieve depth info
1831
1832 XVisualInfo vinfo_template;
1833 XVisualInfo *vi;
1834
1835 vinfo_template.visual = vis;
1836 vinfo_template.visualid = XVisualIDFromVisual( vis );
1837 vinfo_template.depth = bpp;
1838 int nitem = 0;
1839
1840 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1841
1842 if (!vi)
1843 {
1844 printf("no visual.\n" );
1845 return;
1846 }
dbda9e86 1847
38274997
RR
1848 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1849
1850 XFree( vi );
dbda9e86 1851
38274997
RR
1852 XColor colors[256];
1853 if (bpp == 8)
1854 {
dbda9e86
JS
1855 Colormap cmap = (Colormap)wxTheApp->GetMainColormap( dpy );
1856
38274997 1857 for (int i = 0; i < 256; i++) colors[i].pixel = i;
dbda9e86 1858 XQueryColors( dpy, cmap, colors, 256 );
38274997 1859 }
dbda9e86 1860
38274997
RR
1861 long pos = 0;
1862 for (int j = 0; j < bitmap.GetHeight(); j++)
1863 {
1864 for (int i = 0; i < bitmap.GetWidth(); i++)
1865 {
dbda9e86 1866 int pixel = XGetPixel( ximage, i, j );
38274997
RR
1867 if (bpp <= 8)
1868 {
1869 data[pos] = colors[pixel].red >> 8;
1870 data[pos+1] = colors[pixel].green >> 8;
1871 data[pos+2] = colors[pixel].blue >> 8;
1872 } else if (bpp == 15)
1873 {
1874 data[pos] = (pixel >> 7) & 0xf8;
1875 data[pos+1] = (pixel >> 2) & 0xf8;
1876 data[pos+2] = (pixel << 3) & 0xf8;
1877 } else if (bpp == 16)
1878 {
1879 data[pos] = (pixel >> 8) & 0xf8;
1880 data[pos+1] = (pixel >> 3) & 0xfc;
1881 data[pos+2] = (pixel << 3) & 0xf8;
1882 } else
1883 {
1884 data[pos] = (pixel >> 16) & 0xff;
1885 data[pos+1] = (pixel >> 8) & 0xff;
1886 data[pos+2] = pixel & 0xff;
1887 }
dbda9e86
JS
1888
1889 /*
38274997
RR
1890 if (gdk_image_mask)
1891 {
dbda9e86
JS
1892 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1893 if (mask_pixel == 0)
1894 {
1895 data[pos] = 16;
1896 data[pos+1] = 16;
1897 data[pos+2] = 16;
38274997 1898 }
dbda9e86
JS
1899 }
1900 */
1901
38274997
RR
1902 pos += 3;
1903 }
1904 }
dbda9e86 1905
38274997 1906 XDestroyImage( ximage );
dbda9e86 1907 /*
38274997 1908 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
dbda9e86 1909 */
ee4c6942
JS
1910}
1911#endif
a91b47e8
JS
1912
1913// A module to allow wxImage initialization/cleanup
1914// without calling these functions from app.cpp or from
1915// the user's application.
1916
1917class wxImageModule: public wxModule
1918{
1919DECLARE_DYNAMIC_CLASS(wxImageModule)
1920public:
1921 wxImageModule() {}
1922 bool OnInit() { wxImage::InitStandardHandlers(); return TRUE; };
1923 void OnExit() { wxImage::CleanUpHandlers(); };
1924};
1925
1926IMPLEMENT_DYNAMIC_CLASS(wxImageModule, wxModule)