]> git.saurik.com Git - wxWidgets.git/blame - src/common/image.cpp
Right-o, wxConv_local does cause some weird crashes, but things
[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
99c67c77
RR
1280wxBitmap wxImage::ConvertToBitmap() const
1281{
1282 wxBitmap bitmap;
dbda9e86 1283
50920146 1284 wxCHECK_MSG( Ok(), bitmap, _T("invalid image") );
dbda9e86 1285
99c67c77
RR
1286 int width = GetWidth();
1287 int height = GetHeight();
dbda9e86 1288
99c67c77
RR
1289 bitmap.SetHeight( height );
1290 bitmap.SetWidth( width );
dbda9e86 1291
99c67c77 1292 // Create picture
dbda9e86 1293
99c67c77 1294 GdkImage *data_image =
dbda9e86
JS
1295 gdk_image_new( GDK_IMAGE_FASTEST, gdk_visual_get_system(), width, height );
1296
99c67c77 1297 bitmap.SetPixmap( gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, -1 ) );
dbda9e86 1298
99c67c77 1299 // Create mask
dbda9e86 1300
99c67c77 1301 GdkImage *mask_image = (GdkImage*) NULL;
dbda9e86 1302
99c67c77
RR
1303 if (HasMask())
1304 {
1305 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
dbda9e86 1306
99c67c77 1307 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
dbda9e86 1308
4698648f
VZ
1309 wxMask *mask = new wxMask();
1310 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
dbda9e86 1311
4698648f 1312 bitmap.SetMask( mask );
99c67c77 1313 }
dbda9e86 1314
99c67c77 1315 // Retrieve depth
dbda9e86 1316
99c67c77
RR
1317 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
1318 if (visual == NULL) visual = gdk_window_get_visual( (GdkWindow*) &gdk_root_parent );
1319 int bpp = visual->depth;
dbda9e86 1320
06cfab17 1321 bitmap.SetDepth( bpp );
dbda9e86 1322
99c67c77
RR
1323 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
1324 if (bpp < 8) bpp = 8;
dbda9e86 1325
99c67c77 1326 // Render
dbda9e86 1327
99c67c77
RR
1328 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1329 byte_order b_o = RGB;
dbda9e86 1330
99c67c77
RR
1331 if (bpp >= 24)
1332 {
1333 GdkVisual *visual = gdk_visual_get_system();
1334 if ((visual->red_mask > visual->green_mask) && (visual->green_mask > visual->blue_mask)) b_o = RGB;
1335 else if ((visual->red_mask > visual->blue_mask) && (visual->blue_mask > visual->green_mask)) b_o = RGB;
1336 else if ((visual->blue_mask > visual->red_mask) && (visual->red_mask > visual->green_mask)) b_o = BRG;
1337 else if ((visual->blue_mask > visual->green_mask) && (visual->green_mask > visual->red_mask)) b_o = BGR;
1338 else if ((visual->green_mask > visual->red_mask) && (visual->red_mask > visual->blue_mask)) b_o = GRB;
1339 else if ((visual->green_mask > visual->blue_mask) && (visual->blue_mask > visual->red_mask)) b_o = GBR;
1340 }
dbda9e86 1341
99c67c77
RR
1342 int r_mask = GetMaskRed();
1343 int g_mask = GetMaskGreen();
1344 int b_mask = GetMaskBlue();
dbda9e86 1345
99c67c77 1346 unsigned char* data = GetData();
dbda9e86 1347
99c67c77
RR
1348 int index = 0;
1349 for (int y = 0; y < height; y++)
1350 {
1351 for (int x = 0; x < width; x++)
1352 {
1353 int r = data[index];
4698648f 1354 index++;
99c67c77 1355 int g = data[index];
4698648f 1356 index++;
99c67c77 1357 int b = data[index];
4698648f 1358 index++;
dbda9e86 1359
4698648f
VZ
1360 if (HasMask())
1361 {
1362 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1363 gdk_image_put_pixel( mask_image, x, y, 1 );
1364 else
1365 gdk_image_put_pixel( mask_image, x, y, 0 );
1366 }
dbda9e86 1367
4698648f
VZ
1368 if (HasMask())
1369 {
1370 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1371 gdk_image_put_pixel( mask_image, x, y, 1 );
1372 else
1373 gdk_image_put_pixel( mask_image, x, y, 0 );
1374 }
dbda9e86 1375
4698648f
VZ
1376 switch (bpp)
1377 {
dbda9e86 1378 case 8:
4698648f 1379 {
f6fcbb63 1380 int pixel = -1;
4698648f
VZ
1381 if (wxTheApp->m_colorCube)
1382 {
38274997 1383 pixel = wxTheApp->m_colorCube[ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
4698648f 1384 }
f6fcbb63 1385 else
4698648f
VZ
1386 {
1387 GdkColormap *cmap = gtk_widget_get_default_colormap();
f6fcbb63
RR
1388 GdkColor *colors = cmap->colors;
1389 int max = 3 * (65536);
dbda9e86 1390
f6fcbb63
RR
1391 for (int i = 0; i < cmap->size; i++)
1392 {
1393 int rdiff = (r << 8) - colors[i].red;
1394 int gdiff = (g << 8) - colors[i].green;
1395 int bdiff = (b << 8) - colors[i].blue;
1396 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1397 if (sum < max) { pixel = i; max = sum; }
4698648f 1398 }
99c67c77 1399 }
dbda9e86 1400
4698648f 1401 gdk_image_put_pixel( data_image, x, y, pixel );
dbda9e86 1402
4698648f
VZ
1403 break;
1404 }
dbda9e86 1405 case 15:
4698648f
VZ
1406 {
1407 guint32 pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1408 gdk_image_put_pixel( data_image, x, y, pixel );
1409 break;
1410 }
dbda9e86 1411 case 16:
4698648f
VZ
1412 {
1413 guint32 pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1414 gdk_image_put_pixel( data_image, x, y, pixel );
1415 break;
1416 }
dbda9e86
JS
1417 case 32:
1418 case 24:
4698648f
VZ
1419 {
1420 guint32 pixel = 0;
1421 switch (b_o)
1422 {
dbda9e86
JS
1423 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1424 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1425 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1426 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1427 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1428 case GBR: pixel = (g << 16) | (b << 8) | r; break;
4698648f
VZ
1429 }
1430 gdk_image_put_pixel( data_image, x, y, pixel );
1431 }
dbda9e86 1432 default: break;
4698648f 1433 }
99c67c77
RR
1434 } // for
1435 } // for
dbda9e86 1436
99c67c77 1437 // Blit picture
dbda9e86 1438
99c67c77 1439 GdkGC *data_gc = gdk_gc_new( bitmap.GetPixmap() );
dbda9e86 1440
99c67c77 1441 gdk_draw_image( bitmap.GetPixmap(), data_gc, data_image, 0, 0, 0, 0, width, height );
dbda9e86 1442
99c67c77
RR
1443 gdk_image_destroy( data_image );
1444 gdk_gc_unref( data_gc );
dbda9e86 1445
99c67c77 1446 // Blit mask
dbda9e86 1447
99c67c77
RR
1448 if (HasMask())
1449 {
1450 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
dbda9e86 1451
99c67c77 1452 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
dbda9e86 1453
99c67c77
RR
1454 gdk_image_destroy( mask_image );
1455 gdk_gc_unref( mask_gc );
1456 }
dbda9e86 1457
99c67c77
RR
1458 return bitmap;
1459}
1460
1461wxImage::wxImage( const wxBitmap &bitmap )
1462{
50920146 1463 wxCHECK_RET( bitmap.Ok(), _T("invalid bitmap") );
dbda9e86 1464
99c67c77 1465 GdkImage *gdk_image = gdk_image_get( bitmap.GetPixmap(),
dbda9e86
JS
1466 0, 0,
1467 bitmap.GetWidth(), bitmap.GetHeight() );
1468
50920146 1469 wxCHECK_RET( gdk_image, _T("couldn't create image") );
dbda9e86 1470
99c67c77
RR
1471 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1472 char unsigned *data = GetData();
dbda9e86 1473
99c67c77
RR
1474 if (!data)
1475 {
1476 gdk_image_destroy( gdk_image );
50920146 1477 wxFAIL_MSG( _T("couldn't create image") );
4698648f 1478 return;
99c67c77 1479 }
dbda9e86 1480
99c67c77
RR
1481 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1482 if (bitmap.GetMask())
1483 {
1484 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
dbda9e86
JS
1485 0, 0,
1486 bitmap.GetWidth(), bitmap.GetHeight() );
1487
4698648f 1488 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
99c67c77 1489 }
dbda9e86 1490
99c67c77
RR
1491 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
1492 if (visual == NULL) visual = gdk_window_get_visual( (GdkWindow*) &gdk_root_parent );
1493 int bpp = visual->depth;
1494 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
dbda9e86 1495
99c67c77 1496 GdkColormap *cmap = gtk_widget_get_default_colormap();
dbda9e86 1497
99c67c77
RR
1498 long pos = 0;
1499 for (int j = 0; j < bitmap.GetHeight(); j++)
1500 {
1501 for (int i = 0; i < bitmap.GetWidth(); i++)
1502 {
1503 int pixel = gdk_image_get_pixel( gdk_image, i, j );
1504 if (bpp <= 8)
1505 {
1506 data[pos] = cmap->colors[pixel].red >> 8;
1507 data[pos+1] = cmap->colors[pixel].green >> 8;
1508 data[pos+2] = cmap->colors[pixel].blue >> 8;
1509 } else if (bpp == 15)
1510 {
1511 data[pos] = (pixel >> 7) & 0xf8;
1512 data[pos+1] = (pixel >> 2) & 0xf8;
1513 data[pos+2] = (pixel << 3) & 0xf8;
1514 } else if (bpp == 16)
1515 {
1516 data[pos] = (pixel >> 8) & 0xf8;
1517 data[pos+1] = (pixel >> 3) & 0xfc;
1518 data[pos+2] = (pixel << 3) & 0xf8;
1519 } else
1520 {
1521 data[pos] = (pixel >> 16) & 0xff;
1522 data[pos+1] = (pixel >> 8) & 0xff;
1523 data[pos+2] = pixel & 0xff;
1524 }
dbda9e86 1525
4698648f
VZ
1526 if (gdk_image_mask)
1527 {
1528 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1529 if (mask_pixel == 0)
1530 {
99c67c77
RR
1531 data[pos] = 16;
1532 data[pos+1] = 16;
1533 data[pos+2] = 16;
dbda9e86 1534 }
4698648f 1535 }
dbda9e86 1536
99c67c77
RR
1537 pos += 3;
1538 }
1539 }
dbda9e86 1540
99c67c77
RR
1541 gdk_image_destroy( gdk_image );
1542 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1543}
1544
1545#endif
ee4c6942 1546
ee4c6942 1547#ifdef __WXMOTIF__
b75867a6
RR
1548
1549#include <Xm/Xm.h>
1550#include "wx/utils.h"
38274997 1551#include <math.h>
b75867a6 1552
ee4c6942
JS
1553wxBitmap wxImage::ConvertToBitmap() const
1554{
b75867a6 1555 wxBitmap bitmap;
dbda9e86 1556
50920146 1557 wxCHECK_MSG( Ok(), bitmap, _T("invalid image") );
a91b47e8 1558
b75867a6
RR
1559 int width = GetWidth();
1560 int height = GetHeight();
dbda9e86 1561
b75867a6
RR
1562 bitmap.SetHeight( height );
1563 bitmap.SetWidth( width );
dbda9e86 1564
b75867a6
RR
1565 Display *dpy = (Display*) wxGetDisplay();
1566 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1567 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
dbda9e86 1568
b75867a6
RR
1569 // Create image
1570
1571 XImage *data_image = XCreateImage( dpy, vis, bpp, ZPixmap, 0, 0, width, height, 32, 0 );
a91b47e8 1572 data_image->data = (char*) malloc( data_image->bytes_per_line * data_image->height );
dbda9e86 1573
b75867a6 1574 bitmap.Create( width, height, bpp );
a91b47e8 1575
dbda9e86 1576 /*
b75867a6 1577 // Create mask
dbda9e86
JS
1578
1579 GdkImage *mask_image = (GdkImage*) NULL;
1580
1581 if (HasMask())
1582 {
b75867a6 1583 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
dbda9e86
JS
1584
1585 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1586
1587 wxMask *mask = new wxMask();
1588 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1589
1590 bitmap.SetMask( mask );
1591 }
1592 */
1593
b75867a6
RR
1594 // Retrieve depth info
1595
1596 XVisualInfo vinfo_template;
1597 XVisualInfo *vi;
1598
1599 vinfo_template.visual = vis;
1600 vinfo_template.visualid = XVisualIDFromVisual( vis );
1601 vinfo_template.depth = bpp;
1602 int nitem = 0;
1603
1604 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1605
1606 if (!vi)
1607 {
1608 printf("no visual.\n" );
1609 return wxNullBitmap;
1610 }
dbda9e86 1611
38274997 1612 XFree( vi );
a91b47e8 1613
b75867a6
RR
1614 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1615 if (bpp < 8) bpp = 8;
dbda9e86 1616
b75867a6 1617 // Render
dbda9e86 1618
b75867a6
RR
1619 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1620 byte_order b_o = RGB;
dbda9e86 1621
b75867a6
RR
1622 if (bpp >= 24)
1623 {
1624 if ((vi->red_mask > vi->green_mask) && (vi->green_mask > vi->blue_mask)) b_o = RGB;
1625 else if ((vi->red_mask > vi->blue_mask) && (vi->blue_mask > vi->green_mask)) b_o = RGB;
1626 else if ((vi->blue_mask > vi->red_mask) && (vi->red_mask > vi->green_mask)) b_o = BRG;
1627 else if ((vi->blue_mask > vi->green_mask) && (vi->green_mask > vi->red_mask)) b_o = BGR;
1628 else if ((vi->green_mask > vi->red_mask) && (vi->red_mask > vi->blue_mask)) b_o = GRB;
1629 else if ((vi->green_mask > vi->blue_mask) && (vi->blue_mask > vi->red_mask)) b_o = GBR;
1630 }
dbda9e86
JS
1631
1632 /*
b75867a6
RR
1633 int r_mask = GetMaskRed();
1634 int g_mask = GetMaskGreen();
1635 int b_mask = GetMaskBlue();
dbda9e86
JS
1636 */
1637
38274997
RR
1638 XColor colors[256];
1639 if (bpp == 8)
1640 {
dbda9e86
JS
1641 Colormap cmap = (Colormap) wxTheApp->GetMainColormap( dpy );
1642
38274997 1643 for (int i = 0; i < 256; i++) colors[i].pixel = i;
dbda9e86 1644 XQueryColors( dpy, cmap, colors, 256 );
38274997 1645 }
dbda9e86 1646
b75867a6 1647 unsigned char* data = GetData();
dbda9e86 1648
b75867a6
RR
1649 int index = 0;
1650 for (int y = 0; y < height; y++)
1651 {
1652 for (int x = 0; x < width; x++)
1653 {
1654 int r = data[index];
dbda9e86 1655 index++;
b75867a6 1656 int g = data[index];
dbda9e86 1657 index++;
b75867a6 1658 int b = data[index];
dbda9e86
JS
1659 index++;
1660
1661 /*
1662 if (HasMask())
1663 {
1664 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1665 gdk_image_put_pixel( mask_image, x, y, 1 );
1666 else
1667 gdk_image_put_pixel( mask_image, x, y, 0 );
1668 }
1669 */
1670
1671 switch (bpp)
1672 {
1673 case 8:
1674 {
b75867a6 1675 int pixel = -1;
dbda9e86
JS
1676 /*
1677 if (wxTheApp->m_colorCube)
1678 {
1679 pixel = wxTheApp->m_colorCube
1680 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
b75867a6
RR
1681 }
1682 else
dbda9e86
JS
1683 {
1684 */
1685 int max = 3 * (65536);
1686 for (int i = 0; i < 256; i++)
1687 {
1688 int rdiff = (r << 8) - colors[i].red;
1689 int gdiff = (g << 8) - colors[i].green;
1690 int bdiff = (b << 8) - colors[i].blue;
1691 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1692 if (sum < max) { pixel = i; max = sum; }
1693 }
1694 /*
1695 }
1696 */
1697 XPutPixel( data_image, x, y, pixel );
1698 break;
1699 }
1700 case 15:
1701 {
1702 int pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1703 XPutPixel( data_image, x, y, pixel );
1704 break;
1705 }
1706 case 16:
1707 {
1708 int pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1709 XPutPixel( data_image, x, y, pixel );
1710 break;
1711 }
1712 case 32:
1713 case 24:
1714 {
1715 int pixel = 0;
1716 switch (b_o)
1717 {
1718 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1719 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1720 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1721 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1722 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1723 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1724 }
1725 XPutPixel( data_image, x, y, pixel );
1726 }
1727 default: break;
1728 }
b75867a6
RR
1729 } // for
1730 } // for
dbda9e86 1731
b75867a6 1732 // Blit picture
dbda9e86 1733
b75867a6
RR
1734 XGCValues gcvalues;
1735 gcvalues.foreground = BlackPixel( dpy, DefaultScreen( dpy ) );
1736 GC gc = XCreateGC( dpy, RootWindow ( dpy, DefaultScreen(dpy) ), GCForeground, &gcvalues );
1737 XPutImage( dpy, (Drawable)bitmap.GetPixmap(), gc, data_image, 0, 0, 0, 0, width, height );
dbda9e86 1738
b75867a6
RR
1739 XDestroyImage( data_image );
1740 XFreeGC( dpy, gc );
dbda9e86
JS
1741
1742 /*
b75867a6 1743 // Blit mask
dbda9e86
JS
1744
1745 if (HasMask())
1746 {
1747 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
1748
b75867a6 1749 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
dbda9e86
JS
1750
1751 gdk_image_destroy( mask_image );
1752 gdk_gc_unref( mask_gc );
1753 }
1754 */
1755
b75867a6 1756 return bitmap;
ee4c6942
JS
1757}
1758
1759wxImage::wxImage( const wxBitmap &bitmap )
1760{
50920146 1761 wxCHECK_RET( bitmap.Ok(), _T("invalid bitmap") );
dbda9e86 1762
38274997
RR
1763 Display *dpy = (Display*) wxGetDisplay();
1764 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1765 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1766
1767 XImage *ximage = XGetImage( dpy,
dbda9e86
JS
1768 (Drawable)bitmap.GetPixmap(),
1769 0, 0,
1770 bitmap.GetWidth(), bitmap.GetHeight(),
1771 AllPlanes, ZPixmap );
1772
50920146 1773 wxCHECK_RET( ximage, _T("couldn't create image") );
dbda9e86 1774
38274997
RR
1775 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1776 char unsigned *data = GetData();
dbda9e86 1777
38274997
RR
1778 if (!data)
1779 {
1780 XDestroyImage( ximage );
50920146 1781 wxFAIL_MSG( _T("couldn't create image") );
38274997
RR
1782 return;
1783 }
dbda9e86
JS
1784
1785 /*
38274997
RR
1786 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1787 if (bitmap.GetMask())
1788 {
dbda9e86
JS
1789 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1790 0, 0,
1791 bitmap.GetWidth(), bitmap.GetHeight() );
1792
1793 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1794 }
1795 */
1796
38274997
RR
1797 // Retrieve depth info
1798
1799 XVisualInfo vinfo_template;
1800 XVisualInfo *vi;
1801
1802 vinfo_template.visual = vis;
1803 vinfo_template.visualid = XVisualIDFromVisual( vis );
1804 vinfo_template.depth = bpp;
1805 int nitem = 0;
1806
1807 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1808
1809 if (!vi)
1810 {
1811 printf("no visual.\n" );
1812 return;
1813 }
dbda9e86 1814
38274997
RR
1815 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1816
1817 XFree( vi );
dbda9e86 1818
38274997
RR
1819 XColor colors[256];
1820 if (bpp == 8)
1821 {
dbda9e86
JS
1822 Colormap cmap = (Colormap)wxTheApp->GetMainColormap( dpy );
1823
38274997 1824 for (int i = 0; i < 256; i++) colors[i].pixel = i;
dbda9e86 1825 XQueryColors( dpy, cmap, colors, 256 );
38274997 1826 }
dbda9e86 1827
38274997
RR
1828 long pos = 0;
1829 for (int j = 0; j < bitmap.GetHeight(); j++)
1830 {
1831 for (int i = 0; i < bitmap.GetWidth(); i++)
1832 {
dbda9e86 1833 int pixel = XGetPixel( ximage, i, j );
38274997
RR
1834 if (bpp <= 8)
1835 {
1836 data[pos] = colors[pixel].red >> 8;
1837 data[pos+1] = colors[pixel].green >> 8;
1838 data[pos+2] = colors[pixel].blue >> 8;
1839 } else if (bpp == 15)
1840 {
1841 data[pos] = (pixel >> 7) & 0xf8;
1842 data[pos+1] = (pixel >> 2) & 0xf8;
1843 data[pos+2] = (pixel << 3) & 0xf8;
1844 } else if (bpp == 16)
1845 {
1846 data[pos] = (pixel >> 8) & 0xf8;
1847 data[pos+1] = (pixel >> 3) & 0xfc;
1848 data[pos+2] = (pixel << 3) & 0xf8;
1849 } else
1850 {
1851 data[pos] = (pixel >> 16) & 0xff;
1852 data[pos+1] = (pixel >> 8) & 0xff;
1853 data[pos+2] = pixel & 0xff;
1854 }
dbda9e86
JS
1855
1856 /*
38274997
RR
1857 if (gdk_image_mask)
1858 {
dbda9e86
JS
1859 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1860 if (mask_pixel == 0)
1861 {
1862 data[pos] = 16;
1863 data[pos+1] = 16;
1864 data[pos+2] = 16;
38274997 1865 }
dbda9e86
JS
1866 }
1867 */
1868
38274997
RR
1869 pos += 3;
1870 }
1871 }
dbda9e86 1872
38274997 1873 XDestroyImage( ximage );
dbda9e86 1874 /*
38274997 1875 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
dbda9e86 1876 */
ee4c6942
JS
1877}
1878#endif
a91b47e8
JS
1879
1880// A module to allow wxImage initialization/cleanup
1881// without calling these functions from app.cpp or from
1882// the user's application.
1883
1884class wxImageModule: public wxModule
1885{
1886DECLARE_DYNAMIC_CLASS(wxImageModule)
1887public:
1888 wxImageModule() {}
1889 bool OnInit() { wxImage::InitStandardHandlers(); return TRUE; };
1890 void OnExit() { wxImage::CleanUpHandlers(); };
1891};
1892
1893IMPLEMENT_DYNAMIC_CLASS(wxImageModule, wxModule)