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