]> git.saurik.com Git - wxWidgets.git/blame - src/common/image.cpp
Whole lot of stuff for new wxFileDialog
[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
deb2fec0
SB
391//#include <stream.h>
392
3d05544e
JS
393bool wxImage::LoadFile( wxInputStream& stream, long type )
394{
395 UnRef();
c7abc967 396
fd0eed64 397 m_refData = new wxImageRefData;
c7abc967 398
deb2fec0
SB
399 wxImageHandler *handler;
400
401 if (type==wxBITMAP_TYPE_ANY)
402 {
403 // here we can try to guess the handler according the extension,
404 // but we lose the stream name !?
405 // Probably we should write methods such as
406 // bool wxImageHandler::IsAppropriate(wxString&)
407 // bool wxImageHandler::IsAppropriate(sxInputStream&&)
408 // for png : see example.c
409 wxList &list=GetHandlers();
410 off_t pos=stream.TellI();
411
412 wxLogNull prevent_log;
413
414 for ( wxList::Node *node = list.GetFirst(); node; node = node->GetNext() )
415 {
416 handler=(wxImageHandler*)node->GetData();
417 //cout << handler->GetExtension() << endl;
418 if (handler->LoadFile( this, stream, FALSE )) return TRUE;
419 stream.SeekI(pos);
420 }
421
422 return FALSE;
423 }
424
425 handler = FindHandler(type);
c7abc967 426
4698648f 427 if (handler == NULL)
fd0eed64 428 {
50920146 429 wxLogWarning( _T("No image handler for type %d defined."), type );
c7abc967 430
fd0eed64
RR
431 return FALSE;
432 }
c7abc967 433
3d05544e 434 return handler->LoadFile( this, stream );
01111366
RR
435}
436
9e9ee68e
VS
437bool wxImage::LoadFile( wxInputStream& stream, const wxString& mimetype )
438{
439 UnRef();
440
441 m_refData = new wxImageRefData;
442
443 wxImageHandler *handler = FindHandlerMime(mimetype);
444
445 if (handler == NULL)
446 {
50920146 447 wxLogWarning( _T("No image handler for type %s defined."), mimetype.GetData() );
9e9ee68e
VS
448
449 return FALSE;
450 }
451
452 return handler->LoadFile( this, stream );
453}
454
3d05544e 455bool wxImage::SaveFile( wxOutputStream& stream, int type )
01111366 456{
50920146 457 wxCHECK_MSG( Ok(), FALSE, _T("invalid image") );
c7abc967 458
fd0eed64 459 wxImageHandler *handler = FindHandler(type);
c7abc967 460
4698648f 461 if (handler == NULL)
fd0eed64 462 {
50920146 463 wxLogWarning( _T("No image handler for type %d defined."), type );
9e9ee68e
VS
464
465 return FALSE;
466 }
467
468 return handler->SaveFile( this, stream );
469}
470
471bool wxImage::SaveFile( wxOutputStream& stream, const wxString& mimetype )
472{
50920146 473 wxCHECK_MSG( Ok(), FALSE, _T("invalid image") );
c7abc967 474
9e9ee68e 475 wxImageHandler *handler = FindHandlerMime(mimetype);
c7abc967 476
9e9ee68e
VS
477 if (handler == NULL)
478 {
50920146 479 wxLogWarning( _T("No image handler for type %s defined."), mimetype.GetData() );
c7abc967 480
dbda9e86 481 return FALSE;
fd0eed64 482 }
c7abc967 483
3d05544e 484 return handler->SaveFile( this, stream );
01111366 485}
e02afc7a 486#endif // wxUSE_STREAMS
01111366
RR
487
488void wxImage::AddHandler( wxImageHandler *handler )
489{
4698648f
VZ
490 // make sure that the memory will be freed at the program end
491 sm_handlers.DeleteContents(TRUE);
c7abc967 492
01111366
RR
493 sm_handlers.Append( handler );
494}
495
496void wxImage::InsertHandler( wxImageHandler *handler )
497{
4698648f
VZ
498 // make sure that the memory will be freed at the program end
499 sm_handlers.DeleteContents(TRUE);
c7abc967 500
01111366
RR
501 sm_handlers.Insert( handler );
502}
503
504bool wxImage::RemoveHandler( const wxString& name )
505{
fd0eed64
RR
506 wxImageHandler *handler = FindHandler(name);
507 if (handler)
508 {
509 sm_handlers.DeleteObject(handler);
510 return TRUE;
511 }
512 else
513 return FALSE;
01111366
RR
514}
515
516wxImageHandler *wxImage::FindHandler( const wxString& name )
517{
fd0eed64
RR
518 wxNode *node = sm_handlers.First();
519 while (node)
520 {
521 wxImageHandler *handler = (wxImageHandler*)node->Data();
ce3ed50d 522 if (handler->GetName().Cmp(name) == 0) return handler;
c7abc967 523
fd0eed64
RR
524 node = node->Next();
525 }
526 return (wxImageHandler *)NULL;
01111366
RR
527}
528
529wxImageHandler *wxImage::FindHandler( const wxString& extension, long bitmapType )
530{
fd0eed64
RR
531 wxNode *node = sm_handlers.First();
532 while (node)
533 {
534 wxImageHandler *handler = (wxImageHandler*)node->Data();
ce3ed50d 535 if ( (handler->GetExtension().Cmp(extension) == 0) &&
fd0eed64 536 (bitmapType == -1 || handler->GetType() == bitmapType) )
dbda9e86 537 return handler;
fd0eed64
RR
538 node = node->Next();
539 }
540 return (wxImageHandler*)NULL;
01111366
RR
541}
542
543wxImageHandler *wxImage::FindHandler( long bitmapType )
544{
fd0eed64
RR
545 wxNode *node = sm_handlers.First();
546 while (node)
547 {
548 wxImageHandler *handler = (wxImageHandler *)node->Data();
549 if (handler->GetType() == bitmapType) return handler;
550 node = node->Next();
551 }
552 return NULL;
553}
554
9e9ee68e
VS
555wxImageHandler *wxImage::FindHandlerMime( const wxString& mimetype )
556{
557 wxNode *node = sm_handlers.First();
558 while (node)
559 {
560 wxImageHandler *handler = (wxImageHandler *)node->Data();
561 if (handler->GetMimeType().IsSameAs(mimetype, FALSE)) return handler;
562 node = node->Next();
563 }
564 return NULL;
565}
566
fd0eed64
RR
567void wxImage::InitStandardHandlers()
568{
deb2fec0 569 AddHandler( new wxBMPHandler );
01111366
RR
570}
571
572void wxImage::CleanUpHandlers()
573{
fd0eed64
RR
574 wxNode *node = sm_handlers.First();
575 while (node)
576 {
577 wxImageHandler *handler = (wxImageHandler *)node->Data();
578 wxNode *next = node->Next();
579 delete handler;
580 delete node;
581 node = next;
582 }
01111366
RR
583}
584
585//-----------------------------------------------------------------------------
586// wxImageHandler
587//-----------------------------------------------------------------------------
588
589#if !USE_SHARED_LIBRARIES
590IMPLEMENT_DYNAMIC_CLASS(wxImageHandler,wxObject)
591#endif
592
e02afc7a 593#if wxUSE_STREAMS
deb2fec0 594bool wxImageHandler::LoadFile( wxImage *WXUNUSED(image), wxInputStream& WXUNUSED(stream), bool WXUNUSED(verbose) )
01111366 595{
fd0eed64 596 return FALSE;
01111366
RR
597}
598
deb2fec0 599bool wxImageHandler::SaveFile( wxImage *WXUNUSED(image), wxOutputStream& WXUNUSED(stream), bool WXUNUSED(verbose) )
01111366 600{
fd0eed64 601 return FALSE;
01111366 602}
e02afc7a 603#endif // wxUSE_STREAMS
01111366 604
01111366 605//-----------------------------------------------------------------------------
ce4169a4 606// MSW conversion routines
01111366
RR
607//-----------------------------------------------------------------------------
608
e3554471
JS
609#ifdef __WXMSW__
610
611wxBitmap wxImage::ConvertToBitmap() const
612{
0655ad29
VZ
613 if ( !Ok() )
614 return wxNullBitmap;
615
dbda9e86 616 // sizeLimit is the MS upper limit for the DIB size
c7abc967
VZ
617 int sizeLimit = 1024*768*3;
618
dbda9e86 619 // width and height of the device-dependent bitmap
bba6f3bd
UA
620 int width = GetWidth();
621 int bmpHeight = GetHeight();
c7abc967 622
dbda9e86 623 // calc the number of bytes per scanline and padding
bba6f3bd
UA
624 int bytePerLine = width*3;
625 int sizeDWORD = sizeof( DWORD );
bae41ce1 626 int lineBoundary = bytePerLine % sizeDWORD;
bba6f3bd 627 int padding = 0;
bae41ce1 628 if( lineBoundary > 0 )
bba6f3bd 629 {
bae41ce1 630 padding = sizeDWORD - lineBoundary;
bba6f3bd
UA
631 bytePerLine += padding;
632 }
dbda9e86 633 // calc the number of DIBs and heights of DIBs
bba6f3bd
UA
634 int numDIB = 1;
635 int hRemain = 0;
636 int height = sizeLimit/bytePerLine;
637 if( height >= bmpHeight )
c7abc967 638 height = bmpHeight;
bba6f3bd
UA
639 else
640 {
bae41ce1
UA
641 numDIB = bmpHeight / height;
642 hRemain = bmpHeight % height;
dbda9e86 643 if( hRemain >0 ) numDIB++;
bba6f3bd 644 }
c7abc967 645
dbda9e86 646 // set bitmap parameters
bba6f3bd 647 wxBitmap bitmap;
50920146 648 wxCHECK_MSG( Ok(), bitmap, _T("invalid image") );
bba6f3bd
UA
649 bitmap.SetWidth( width );
650 bitmap.SetHeight( bmpHeight );
651 bitmap.SetDepth( wxDisplayDepth() );
c7abc967 652
dbda9e86 653 // create a DIB header
bba6f3bd
UA
654 int headersize = sizeof(BITMAPINFOHEADER);
655 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
50920146 656 wxCHECK_MSG( lpDIBh, bitmap, _T("could not allocate memory for DIB header") );
dbda9e86 657 // Fill in the DIB header
bba6f3bd
UA
658 lpDIBh->bmiHeader.biSize = headersize;
659 lpDIBh->bmiHeader.biWidth = (DWORD)width;
660 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
661 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
dbda9e86
JS
662 // the general formula for biSizeImage:
663 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
bba6f3bd
UA
664 lpDIBh->bmiHeader.biPlanes = 1;
665 lpDIBh->bmiHeader.biBitCount = 24;
666 lpDIBh->bmiHeader.biCompression = BI_RGB;
667 lpDIBh->bmiHeader.biClrUsed = 0;
dbda9e86 668 // These seem not really needed for our purpose here.
bba6f3bd
UA
669 lpDIBh->bmiHeader.biClrImportant = 0;
670 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
671 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
dbda9e86 672 // memory for DIB data
bba6f3bd
UA
673 unsigned char *lpBits;
674 lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
675 if( !lpBits )
676 {
50920146 677 wxFAIL_MSG( _T("could not allocate memory for DIB") );
bba6f3bd
UA
678 free( lpDIBh );
679 return bitmap;
680 }
c7abc967 681
dbda9e86 682 // create and set the device-dependent bitmap
bba6f3bd
UA
683 HDC hdc = ::GetDC(NULL);
684 HDC memdc = ::CreateCompatibleDC( hdc );
685 HBITMAP hbitmap;
686 hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
c7abc967
VZ
687 ::SelectObject( memdc, hbitmap);
688
dbda9e86 689 // copy image data into DIB data and then into DDB (in a loop)
bba6f3bd
UA
690 unsigned char *data = GetData();
691 int i, j, n;
692 int origin = 0;
693 unsigned char *ptdata = data;
694 unsigned char *ptbits;
c7abc967 695
bba6f3bd
UA
696 for( n=0; n<numDIB; n++ )
697 {
dbda9e86
JS
698 if( numDIB > 1 && n == numDIB-1 && hRemain > 0 )
699 {
700 // redefine height and size of the (possibly) last smaller DIB
701 // memory is not reallocated
c7abc967 702 height = hRemain;
bba6f3bd
UA
703 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
704 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
dbda9e86 705 }
bba6f3bd 706 ptbits = lpBits;
c7abc967 707
bba6f3bd
UA
708 for( j=0; j<height; j++ )
709 {
710 for( i=0; i<width; i++ )
711 {
712 *(ptbits++) = *(ptdata+2);
713 *(ptbits++) = *(ptdata+1);
714 *(ptbits++) = *(ptdata );
715 ptdata += 3;
dbda9e86
JS
716 }
717 for( i=0; i< padding; i++ ) *(ptbits++) = 0;
bba6f3bd
UA
718 }
719 ::StretchDIBits( memdc, 0, origin, width, height,\
dbda9e86
JS
720 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
721 origin += height;
722 // if numDIB = 1, lines below can also be used
723 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
724 // The above line is equivalent to the following two lines.
725 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
726 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
727 // or the following lines
728 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
729 // HDC memdc = ::CreateCompatibleDC( hdc );
c7abc967 730 // ::SelectObject( memdc, hbitmap);
dbda9e86
JS
731 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
732 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
c7abc967
VZ
733 // ::SelectObject( memdc, 0 );
734 // ::DeleteDC( memdc );
e3554471 735 }
bba6f3bd 736 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
c7abc967 737
dbda9e86 738 // similarly, created an mono-bitmap for the possible mask
bba6f3bd
UA
739 if( HasMask() )
740 {
741 hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL );
c7abc967
VZ
742 ::SelectObject( memdc, hbitmap);
743 if( numDIB == 1 ) height = bmpHeight;
bba6f3bd
UA
744 else height = sizeLimit/bytePerLine;
745 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
746 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
747 origin = 0;
748 unsigned char r = GetMaskRed();
749 unsigned char g = GetMaskGreen();
750 unsigned char b = GetMaskBlue();
751 unsigned char zero = 0, one = 255;
752 ptdata = data;
753 for( n=0; n<numDIB; n++ )
754 {
755 if( numDIB > 1 && n == numDIB - 1 && hRemain > 0 )
756 {
dbda9e86
JS
757 // redefine height and size of the (possibly) last smaller DIB
758 // memory is not reallocated
c7abc967 759 height = hRemain;
bba6f3bd
UA
760 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
761 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
dbda9e86 762 }
bba6f3bd
UA
763 ptbits = lpBits;
764 for( int j=0; j<height; j++ )
765 {
dbda9e86 766 for(i=0; i<width; i++ )
bba6f3bd
UA
767 {
768 if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
769 {
770 *(ptbits++) = one;
771 *(ptbits++) = one;
772 *(ptbits++) = one;
773 }
774 else
775 {
776 *(ptbits++) = zero;
777 *(ptbits++) = zero;
778 *(ptbits++) = zero;
779 }
780 }
dbda9e86 781 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
bba6f3bd
UA
782 }
783 ::StretchDIBits( memdc, 0, origin, width, height,\
dbda9e86
JS
784 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
785 origin += height;
786 }
787 // create a wxMask object
bba6f3bd
UA
788 wxMask *mask = new wxMask();
789 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
790 bitmap.SetMask( mask );
dbda9e86
JS
791 // It will be deleted when the wxBitmap object is deleted (as of 01/1999)
792 /* The following can also be used but is slow to run
bba6f3bd
UA
793 wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
794 wxMask *mask = new wxMask( bitmap, colour );
795 bitmap.SetMask( mask );
dbda9e86 796 */
bba6f3bd 797 }
c7abc967
VZ
798
799 // free allocated resources
800 ::SelectObject( memdc, 0 );
801 ::DeleteDC( memdc );
802 ::ReleaseDC(NULL, hdc);
bba6f3bd
UA
803 free(lpDIBh);
804 free(lpBits);
c7abc967 805
dbda9e86 806 // check the wxBitmap object
bba6f3bd
UA
807 if( bitmap.GetHBITMAP() )
808 bitmap.SetOk( TRUE );
809 else
810 bitmap.SetOk( FALSE );
c7abc967 811
bba6f3bd 812 return bitmap;
e3554471
JS
813}
814
e3554471
JS
815wxImage::wxImage( const wxBitmap &bitmap )
816{
dbda9e86 817 // check the bitmap
bba6f3bd
UA
818 if( !bitmap.Ok() )
819 {
50920146 820 wxFAIL_MSG( _T("invalid bitmap") );
bba6f3bd
UA
821 return;
822 }
c7abc967 823
dbda9e86 824 // create an wxImage object
bba6f3bd
UA
825 int width = bitmap.GetWidth();
826 int height = bitmap.GetHeight();
c7abc967 827 Create( width, height );
bba6f3bd
UA
828 unsigned char *data = GetData();
829 if( !data )
830 {
50920146 831 wxFAIL_MSG( _T("could not allocate data for image") );
bba6f3bd
UA
832 return;
833 }
c7abc967 834
dbda9e86 835 // calc the number of bytes per scanline and padding in the DIB
bba6f3bd
UA
836 int bytePerLine = width*3;
837 int sizeDWORD = sizeof( DWORD );
bae41ce1 838 int lineBoundary = bytePerLine % sizeDWORD;
bba6f3bd 839 int padding = 0;
bae41ce1 840 if( lineBoundary > 0 )
bba6f3bd 841 {
bae41ce1 842 padding = sizeDWORD - lineBoundary;
bba6f3bd
UA
843 bytePerLine += padding;
844 }
c7abc967 845
dbda9e86 846 // create a DIB header
bba6f3bd
UA
847 int headersize = sizeof(BITMAPINFOHEADER);
848 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
849 if( !lpDIBh )
850 {
50920146 851 wxFAIL_MSG( _T("could not allocate data for DIB header") );
bba6f3bd
UA
852 free( data );
853 return;
854 }
dbda9e86 855 // Fill in the DIB header
bba6f3bd
UA
856 lpDIBh->bmiHeader.biSize = headersize;
857 lpDIBh->bmiHeader.biWidth = width;
858 lpDIBh->bmiHeader.biHeight = -height;
859 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
860 lpDIBh->bmiHeader.biPlanes = 1;
861 lpDIBh->bmiHeader.biBitCount = 24;
862 lpDIBh->bmiHeader.biCompression = BI_RGB;
863 lpDIBh->bmiHeader.biClrUsed = 0;
dbda9e86 864 // These seem not really needed for our purpose here.
bba6f3bd
UA
865 lpDIBh->bmiHeader.biClrImportant = 0;
866 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
867 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
dbda9e86 868 // memory for DIB data
bba6f3bd
UA
869 unsigned char *lpBits;
870 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
871 if( !lpBits )
e3554471 872 {
50920146 873 wxFAIL_MSG( _T("could not allocate data for DIB") );
bba6f3bd
UA
874 free( data );
875 free( lpDIBh );
876 return;
4698648f 877 }
c7abc967 878
dbda9e86 879 // copy data from the device-dependent bitmap to the DIB
bba6f3bd
UA
880 HDC hdc = ::GetDC(NULL);
881 HBITMAP hbitmap;
882 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
883 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
c7abc967 884
dbda9e86 885 // copy DIB data into the wxImage object
bba6f3bd
UA
886 int i, j;
887 unsigned char *ptdata = data;
888 unsigned char *ptbits = lpBits;
889 for( i=0; i<height; i++ )
890 {
891 for( j=0; j<width; j++ )
892 {
893 *(ptdata++) = *(ptbits+2);
894 *(ptdata++) = *(ptbits+1);
895 *(ptdata++) = *(ptbits );
896 ptbits += 3;
dbda9e86 897 }
bba6f3bd 898 ptbits += padding;
c7abc967
VZ
899 }
900
dbda9e86 901 // similarly, set data according to the possible mask bitmap
bba6f3bd
UA
902 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
903 {
904 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
dbda9e86 905 // memory DC created, color set, data copied, and memory DC deleted
bba6f3bd
UA
906 HDC memdc = ::CreateCompatibleDC( hdc );
907 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
908 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
909 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
c7abc967 910 ::DeleteDC( memdc );
dbda9e86 911 // background color set to RGB(16,16,16) in consistent with wxGTK
c7abc967 912 unsigned char r=16, g=16, b=16;
bba6f3bd
UA
913 ptdata = data;
914 ptbits = lpBits;
915 for( i=0; i<height; i++ )
916 {
917 for( j=0; j<width; j++ )
918 {
919 if( *ptbits != 0 )
dbda9e86
JS
920 ptdata += 3;
921 else
bba6f3bd
UA
922 {
923 *(ptdata++) = r;
924 *(ptdata++) = g;
925 *(ptdata++) = b;
dbda9e86 926 }
bba6f3bd
UA
927 ptbits += 3;
928 }
929 ptbits += padding;
c7abc967 930 }
bba6f3bd
UA
931 SetMaskColour( r, g, b );
932 SetMask( TRUE );
c7abc967 933 }
bba6f3bd
UA
934 else
935 {
936 SetMask( FALSE );
c7abc967
VZ
937 }
938 // free allocated resources
939 ::ReleaseDC(NULL, hdc);
bba6f3bd
UA
940 free(lpDIBh);
941 free(lpBits);
e3554471
JS
942}
943
944#endif
945
ce4169a4
RR
946//-----------------------------------------------------------------------------
947// GTK conversion routines
948//-----------------------------------------------------------------------------
949
99c67c77
RR
950#ifdef __WXGTK__
951
83624f79
RR
952#include "gtk/gtk.h"
953#include "gdk/gdk.h"
954#include "gdk/gdkx.h"
955
ba0730de
RR
956#if (GTK_MINOR_VERSION > 0)
957#include "gdk/gdkrgb.h"
958#endif
959
99c67c77
RR
960wxBitmap wxImage::ConvertToBitmap() const
961{
962 wxBitmap bitmap;
c7abc967 963
50920146 964 wxCHECK_MSG( Ok(), bitmap, _T("invalid image") );
c7abc967 965
99c67c77
RR
966 int width = GetWidth();
967 int height = GetHeight();
c7abc967 968
99c67c77
RR
969 bitmap.SetHeight( height );
970 bitmap.SetWidth( width );
c7abc967 971
ba0730de
RR
972 bitmap.SetPixmap( gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, -1 ) );
973
974 // Retrieve depth
c7abc967 975
ba0730de 976 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
b134516c 977 if (visual == NULL) visual = gdk_visual_get_system();
ba0730de 978 int bpp = visual->depth;
c7abc967 979
ba0730de 980 bitmap.SetDepth( bpp );
c7abc967 981
ba0730de
RR
982 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
983 if (bpp < 8) bpp = 8;
c7abc967 984
ba0730de
RR
985#if (GTK_MINOR_VERSION > 0)
986
987 if (!HasMask() && (bpp > 8))
988 {
989 static bool s_hasInitialized = FALSE;
c7abc967 990
ba0730de
RR
991 if (!s_hasInitialized)
992 {
993 gdk_rgb_init();
994 s_hasInitialized = TRUE;
995 }
c7abc967 996
ba0730de 997 GdkGC *gc = gdk_gc_new( bitmap.GetPixmap() );
c7abc967 998
ba0730de
RR
999 gdk_draw_rgb_image( bitmap.GetPixmap(),
1000 gc,
1001 0, 0,
1002 width, height,
1003 GDK_RGB_DITHER_NONE,
1004 GetData(),
1005 width*3 );
c7abc967 1006
ba0730de 1007 gdk_gc_unref( gc );
c7abc967 1008
ba0730de
RR
1009 return bitmap;
1010 }
c7abc967 1011
ba0730de 1012#endif
c7abc967 1013
ba0730de 1014 // Create picture image
c7abc967 1015
99c67c77 1016 GdkImage *data_image =
b134516c 1017 gdk_image_new( GDK_IMAGE_FASTEST, gdk_visual_get_system(), width, height );
c7abc967 1018
ba0730de 1019 // Create mask image
c7abc967 1020
99c67c77 1021 GdkImage *mask_image = (GdkImage*) NULL;
c7abc967 1022
99c67c77
RR
1023 if (HasMask())
1024 {
1025 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
c7abc967 1026
b134516c 1027 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
c7abc967 1028
4698648f
VZ
1029 wxMask *mask = new wxMask();
1030 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
c7abc967 1031
4698648f 1032 bitmap.SetMask( mask );
99c67c77 1033 }
c7abc967 1034
99c67c77 1035 // Render
c7abc967 1036
99c67c77
RR
1037 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1038 byte_order b_o = RGB;
c7abc967 1039
99c67c77
RR
1040 if (bpp >= 24)
1041 {
b134516c 1042 GdkVisual *visual = gdk_visual_get_system();
99c67c77
RR
1043 if ((visual->red_mask > visual->green_mask) && (visual->green_mask > visual->blue_mask)) b_o = RGB;
1044 else if ((visual->red_mask > visual->blue_mask) && (visual->blue_mask > visual->green_mask)) b_o = RGB;
1045 else if ((visual->blue_mask > visual->red_mask) && (visual->red_mask > visual->green_mask)) b_o = BRG;
1046 else if ((visual->blue_mask > visual->green_mask) && (visual->green_mask > visual->red_mask)) b_o = BGR;
1047 else if ((visual->green_mask > visual->red_mask) && (visual->red_mask > visual->blue_mask)) b_o = GRB;
1048 else if ((visual->green_mask > visual->blue_mask) && (visual->blue_mask > visual->red_mask)) b_o = GBR;
1049 }
c7abc967 1050
99c67c77
RR
1051 int r_mask = GetMaskRed();
1052 int g_mask = GetMaskGreen();
1053 int b_mask = GetMaskBlue();
c7abc967 1054
99c67c77 1055 unsigned char* data = GetData();
c7abc967 1056
99c67c77
RR
1057 int index = 0;
1058 for (int y = 0; y < height; y++)
1059 {
1060 for (int x = 0; x < width; x++)
1061 {
1062 int r = data[index];
4698648f 1063 index++;
99c67c77 1064 int g = data[index];
4698648f 1065 index++;
99c67c77 1066 int b = data[index];
4698648f 1067 index++;
c7abc967 1068
4698648f
VZ
1069 if (HasMask())
1070 {
1071 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1072 gdk_image_put_pixel( mask_image, x, y, 1 );
1073 else
1074 gdk_image_put_pixel( mask_image, x, y, 0 );
1075 }
c7abc967 1076
4698648f
VZ
1077 if (HasMask())
1078 {
1079 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1080 gdk_image_put_pixel( mask_image, x, y, 1 );
1081 else
1082 gdk_image_put_pixel( mask_image, x, y, 0 );
1083 }
c7abc967 1084
4698648f
VZ
1085 switch (bpp)
1086 {
dbda9e86 1087 case 8:
4698648f 1088 {
f6fcbb63 1089 int pixel = -1;
4698648f
VZ
1090 if (wxTheApp->m_colorCube)
1091 {
38274997 1092 pixel = wxTheApp->m_colorCube[ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
4698648f 1093 }
f6fcbb63 1094 else
4698648f
VZ
1095 {
1096 GdkColormap *cmap = gtk_widget_get_default_colormap();
f6fcbb63
RR
1097 GdkColor *colors = cmap->colors;
1098 int max = 3 * (65536);
c7abc967 1099
f6fcbb63
RR
1100 for (int i = 0; i < cmap->size; i++)
1101 {
1102 int rdiff = (r << 8) - colors[i].red;
1103 int gdiff = (g << 8) - colors[i].green;
1104 int bdiff = (b << 8) - colors[i].blue;
1105 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1106 if (sum < max) { pixel = i; max = sum; }
4698648f 1107 }
99c67c77 1108 }
c7abc967 1109
4698648f 1110 gdk_image_put_pixel( data_image, x, y, pixel );
c7abc967 1111
4698648f
VZ
1112 break;
1113 }
dbda9e86 1114 case 15:
4698648f
VZ
1115 {
1116 guint32 pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1117 gdk_image_put_pixel( data_image, x, y, pixel );
1118 break;
1119 }
dbda9e86 1120 case 16:
4698648f
VZ
1121 {
1122 guint32 pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1123 gdk_image_put_pixel( data_image, x, y, pixel );
1124 break;
1125 }
dbda9e86
JS
1126 case 32:
1127 case 24:
4698648f
VZ
1128 {
1129 guint32 pixel = 0;
1130 switch (b_o)
1131 {
dbda9e86
JS
1132 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1133 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1134 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1135 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1136 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1137 case GBR: pixel = (g << 16) | (b << 8) | r; break;
4698648f
VZ
1138 }
1139 gdk_image_put_pixel( data_image, x, y, pixel );
1140 }
dbda9e86 1141 default: break;
4698648f 1142 }
99c67c77
RR
1143 } // for
1144 } // for
c7abc967 1145
99c67c77 1146 // Blit picture
c7abc967 1147
99c67c77 1148 GdkGC *data_gc = gdk_gc_new( bitmap.GetPixmap() );
c7abc967 1149
99c67c77 1150 gdk_draw_image( bitmap.GetPixmap(), data_gc, data_image, 0, 0, 0, 0, width, height );
c7abc967 1151
99c67c77
RR
1152 gdk_image_destroy( data_image );
1153 gdk_gc_unref( data_gc );
c7abc967 1154
99c67c77 1155 // Blit mask
c7abc967 1156
99c67c77
RR
1157 if (HasMask())
1158 {
1159 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
c7abc967 1160
99c67c77 1161 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
c7abc967 1162
99c67c77
RR
1163 gdk_image_destroy( mask_image );
1164 gdk_gc_unref( mask_gc );
1165 }
c7abc967 1166
99c67c77
RR
1167 return bitmap;
1168}
1169
1170wxImage::wxImage( const wxBitmap &bitmap )
1171{
50920146 1172 wxCHECK_RET( bitmap.Ok(), _T("invalid bitmap") );
c7abc967 1173
99c67c77 1174 GdkImage *gdk_image = gdk_image_get( bitmap.GetPixmap(),
dbda9e86
JS
1175 0, 0,
1176 bitmap.GetWidth(), bitmap.GetHeight() );
c7abc967 1177
50920146 1178 wxCHECK_RET( gdk_image, _T("couldn't create image") );
c7abc967 1179
99c67c77
RR
1180 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1181 char unsigned *data = GetData();
c7abc967 1182
99c67c77
RR
1183 if (!data)
1184 {
1185 gdk_image_destroy( gdk_image );
50920146 1186 wxFAIL_MSG( _T("couldn't create image") );
4698648f 1187 return;
99c67c77 1188 }
c7abc967 1189
99c67c77
RR
1190 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1191 if (bitmap.GetMask())
1192 {
1193 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
dbda9e86
JS
1194 0, 0,
1195 bitmap.GetWidth(), bitmap.GetHeight() );
c7abc967 1196
4698648f 1197 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
99c67c77 1198 }
c7abc967 1199
99c67c77
RR
1200 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
1201 if (visual == NULL) visual = gdk_window_get_visual( (GdkWindow*) &gdk_root_parent );
1202 int bpp = visual->depth;
1203 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
c7abc967 1204
99c67c77 1205 GdkColormap *cmap = gtk_widget_get_default_colormap();
c7abc967 1206
99c67c77
RR
1207 long pos = 0;
1208 for (int j = 0; j < bitmap.GetHeight(); j++)
1209 {
1210 for (int i = 0; i < bitmap.GetWidth(); i++)
1211 {
4cb122de
RR
1212 wxInt32 pixel = gdk_image_get_pixel( gdk_image, i, j );
1213 pixel = wxINT32_SWAP_ON_BE( pixel );
99c67c77
RR
1214 if (bpp <= 8)
1215 {
1216 data[pos] = cmap->colors[pixel].red >> 8;
1217 data[pos+1] = cmap->colors[pixel].green >> 8;
1218 data[pos+2] = cmap->colors[pixel].blue >> 8;
1219 } else if (bpp == 15)
1220 {
1221 data[pos] = (pixel >> 7) & 0xf8;
1222 data[pos+1] = (pixel >> 2) & 0xf8;
1223 data[pos+2] = (pixel << 3) & 0xf8;
1224 } else if (bpp == 16)
1225 {
1226 data[pos] = (pixel >> 8) & 0xf8;
1227 data[pos+1] = (pixel >> 3) & 0xfc;
1228 data[pos+2] = (pixel << 3) & 0xf8;
1229 } else
1230 {
1231 data[pos] = (pixel >> 16) & 0xff;
1232 data[pos+1] = (pixel >> 8) & 0xff;
1233 data[pos+2] = pixel & 0xff;
1234 }
c7abc967 1235
4698648f
VZ
1236 if (gdk_image_mask)
1237 {
1238 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1239 if (mask_pixel == 0)
1240 {
99c67c77
RR
1241 data[pos] = 16;
1242 data[pos+1] = 16;
1243 data[pos+2] = 16;
dbda9e86 1244 }
4698648f 1245 }
c7abc967 1246
99c67c77
RR
1247 pos += 3;
1248 }
1249 }
c7abc967 1250
99c67c77
RR
1251 gdk_image_destroy( gdk_image );
1252 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1253}
1254
1255#endif
ee4c6942 1256
ce4169a4
RR
1257//-----------------------------------------------------------------------------
1258// Motif conversion routines
1259//-----------------------------------------------------------------------------
1260
ee4c6942 1261#ifdef __WXMOTIF__
b75867a6
RR
1262
1263#include <Xm/Xm.h>
1264#include "wx/utils.h"
38274997 1265#include <math.h>
b75867a6 1266
ee4c6942
JS
1267wxBitmap wxImage::ConvertToBitmap() const
1268{
b75867a6 1269 wxBitmap bitmap;
c7abc967 1270
50920146 1271 wxCHECK_MSG( Ok(), bitmap, _T("invalid image") );
a91b47e8 1272
b75867a6
RR
1273 int width = GetWidth();
1274 int height = GetHeight();
c7abc967 1275
b75867a6
RR
1276 bitmap.SetHeight( height );
1277 bitmap.SetWidth( width );
c7abc967 1278
b75867a6
RR
1279 Display *dpy = (Display*) wxGetDisplay();
1280 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1281 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
c7abc967 1282
b75867a6 1283 // Create image
c7abc967 1284
b75867a6 1285 XImage *data_image = XCreateImage( dpy, vis, bpp, ZPixmap, 0, 0, width, height, 32, 0 );
a91b47e8 1286 data_image->data = (char*) malloc( data_image->bytes_per_line * data_image->height );
c7abc967 1287
b75867a6 1288 bitmap.Create( width, height, bpp );
a91b47e8 1289
dbda9e86 1290 /*
b75867a6 1291 // Create mask
c7abc967 1292
dbda9e86 1293 GdkImage *mask_image = (GdkImage*) NULL;
c7abc967 1294
dbda9e86
JS
1295 if (HasMask())
1296 {
b75867a6 1297 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
c7abc967 1298
dbda9e86 1299 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
c7abc967 1300
dbda9e86
JS
1301 wxMask *mask = new wxMask();
1302 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
c7abc967 1303
dbda9e86
JS
1304 bitmap.SetMask( mask );
1305 }
1306 */
c7abc967 1307
b75867a6 1308 // Retrieve depth info
c7abc967 1309
b75867a6
RR
1310 XVisualInfo vinfo_template;
1311 XVisualInfo *vi;
c7abc967 1312
b75867a6
RR
1313 vinfo_template.visual = vis;
1314 vinfo_template.visualid = XVisualIDFromVisual( vis );
1315 vinfo_template.depth = bpp;
1316 int nitem = 0;
c7abc967 1317
b75867a6 1318 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
c7abc967
VZ
1319
1320 wxCHECK_MSG( vi, wxNullBitmap, _T("no visual") );
1321
38274997 1322 XFree( vi );
a91b47e8 1323
b75867a6
RR
1324 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1325 if (bpp < 8) bpp = 8;
c7abc967 1326
b75867a6 1327 // Render
c7abc967 1328
b75867a6
RR
1329 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1330 byte_order b_o = RGB;
c7abc967 1331
b75867a6
RR
1332 if (bpp >= 24)
1333 {
1334 if ((vi->red_mask > vi->green_mask) && (vi->green_mask > vi->blue_mask)) b_o = RGB;
1335 else if ((vi->red_mask > vi->blue_mask) && (vi->blue_mask > vi->green_mask)) b_o = RGB;
1336 else if ((vi->blue_mask > vi->red_mask) && (vi->red_mask > vi->green_mask)) b_o = BRG;
1337 else if ((vi->blue_mask > vi->green_mask) && (vi->green_mask > vi->red_mask)) b_o = BGR;
1338 else if ((vi->green_mask > vi->red_mask) && (vi->red_mask > vi->blue_mask)) b_o = GRB;
1339 else if ((vi->green_mask > vi->blue_mask) && (vi->blue_mask > vi->red_mask)) b_o = GBR;
1340 }
c7abc967 1341
dbda9e86 1342 /*
b75867a6
RR
1343 int r_mask = GetMaskRed();
1344 int g_mask = GetMaskGreen();
1345 int b_mask = GetMaskBlue();
dbda9e86 1346 */
c7abc967 1347
38274997
RR
1348 XColor colors[256];
1349 if (bpp == 8)
1350 {
dbda9e86 1351 Colormap cmap = (Colormap) wxTheApp->GetMainColormap( dpy );
c7abc967 1352
38274997 1353 for (int i = 0; i < 256; i++) colors[i].pixel = i;
dbda9e86 1354 XQueryColors( dpy, cmap, colors, 256 );
38274997 1355 }
c7abc967 1356
b75867a6 1357 unsigned char* data = GetData();
c7abc967 1358
b75867a6
RR
1359 int index = 0;
1360 for (int y = 0; y < height; y++)
1361 {
1362 for (int x = 0; x < width; x++)
1363 {
1364 int r = data[index];
dbda9e86 1365 index++;
b75867a6 1366 int g = data[index];
dbda9e86 1367 index++;
b75867a6 1368 int b = data[index];
dbda9e86 1369 index++;
c7abc967 1370
dbda9e86
JS
1371 /*
1372 if (HasMask())
1373 {
1374 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1375 gdk_image_put_pixel( mask_image, x, y, 1 );
1376 else
1377 gdk_image_put_pixel( mask_image, x, y, 0 );
1378 }
1379 */
c7abc967 1380
dbda9e86
JS
1381 switch (bpp)
1382 {
1383 case 8:
1384 {
b75867a6 1385 int pixel = -1;
dbda9e86
JS
1386 /*
1387 if (wxTheApp->m_colorCube)
1388 {
1389 pixel = wxTheApp->m_colorCube
c7abc967
VZ
1390 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1391 }
b75867a6 1392 else
dbda9e86
JS
1393 {
1394 */
1395 int max = 3 * (65536);
1396 for (int i = 0; i < 256; i++)
1397 {
1398 int rdiff = (r << 8) - colors[i].red;
1399 int gdiff = (g << 8) - colors[i].green;
1400 int bdiff = (b << 8) - colors[i].blue;
1401 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1402 if (sum < max) { pixel = i; max = sum; }
1403 }
1404 /*
1405 }
1406 */
1407 XPutPixel( data_image, x, y, pixel );
1408 break;
1409 }
1410 case 15:
1411 {
1412 int pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1413 XPutPixel( data_image, x, y, pixel );
1414 break;
1415 }
1416 case 16:
1417 {
1418 int pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1419 XPutPixel( data_image, x, y, pixel );
1420 break;
1421 }
1422 case 32:
1423 case 24:
1424 {
1425 int pixel = 0;
1426 switch (b_o)
1427 {
1428 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1429 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1430 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1431 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1432 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1433 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1434 }
1435 XPutPixel( data_image, x, y, pixel );
1436 }
1437 default: break;
1438 }
b75867a6
RR
1439 } // for
1440 } // for
c7abc967 1441
b75867a6 1442 // Blit picture
c7abc967 1443
b75867a6
RR
1444 XGCValues gcvalues;
1445 gcvalues.foreground = BlackPixel( dpy, DefaultScreen( dpy ) );
1446 GC gc = XCreateGC( dpy, RootWindow ( dpy, DefaultScreen(dpy) ), GCForeground, &gcvalues );
1447 XPutImage( dpy, (Drawable)bitmap.GetPixmap(), gc, data_image, 0, 0, 0, 0, width, height );
c7abc967 1448
b75867a6
RR
1449 XDestroyImage( data_image );
1450 XFreeGC( dpy, gc );
c7abc967 1451
dbda9e86 1452 /*
b75867a6 1453 // Blit mask
c7abc967 1454
dbda9e86
JS
1455 if (HasMask())
1456 {
1457 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
c7abc967 1458
b75867a6 1459 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
c7abc967 1460
dbda9e86
JS
1461 gdk_image_destroy( mask_image );
1462 gdk_gc_unref( mask_gc );
1463 }
1464 */
c7abc967 1465
b75867a6 1466 return bitmap;
ee4c6942
JS
1467}
1468
1469wxImage::wxImage( const wxBitmap &bitmap )
1470{
50920146 1471 wxCHECK_RET( bitmap.Ok(), _T("invalid bitmap") );
c7abc967 1472
38274997
RR
1473 Display *dpy = (Display*) wxGetDisplay();
1474 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1475 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
c7abc967 1476
38274997 1477 XImage *ximage = XGetImage( dpy,
dbda9e86
JS
1478 (Drawable)bitmap.GetPixmap(),
1479 0, 0,
1480 bitmap.GetWidth(), bitmap.GetHeight(),
1481 AllPlanes, ZPixmap );
c7abc967 1482
50920146 1483 wxCHECK_RET( ximage, _T("couldn't create image") );
c7abc967 1484
38274997
RR
1485 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1486 char unsigned *data = GetData();
c7abc967 1487
38274997
RR
1488 if (!data)
1489 {
1490 XDestroyImage( ximage );
50920146 1491 wxFAIL_MSG( _T("couldn't create image") );
38274997
RR
1492 return;
1493 }
c7abc967 1494
dbda9e86 1495 /*
38274997
RR
1496 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1497 if (bitmap.GetMask())
1498 {
dbda9e86
JS
1499 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1500 0, 0,
1501 bitmap.GetWidth(), bitmap.GetHeight() );
c7abc967 1502
dbda9e86
JS
1503 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1504 }
1505 */
c7abc967 1506
38274997 1507 // Retrieve depth info
c7abc967 1508
38274997
RR
1509 XVisualInfo vinfo_template;
1510 XVisualInfo *vi;
c7abc967 1511
38274997
RR
1512 vinfo_template.visual = vis;
1513 vinfo_template.visualid = XVisualIDFromVisual( vis );
1514 vinfo_template.depth = bpp;
1515 int nitem = 0;
c7abc967 1516
38274997 1517 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
c7abc967 1518
bea74fbb 1519 wxCHECK_RET( vi, _T("no visual") );
c7abc967 1520
38274997 1521 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
c7abc967 1522
38274997 1523 XFree( vi );
c7abc967 1524
38274997
RR
1525 XColor colors[256];
1526 if (bpp == 8)
1527 {
dbda9e86 1528 Colormap cmap = (Colormap)wxTheApp->GetMainColormap( dpy );
c7abc967 1529
38274997 1530 for (int i = 0; i < 256; i++) colors[i].pixel = i;
dbda9e86 1531 XQueryColors( dpy, cmap, colors, 256 );
38274997 1532 }
c7abc967 1533
38274997
RR
1534 long pos = 0;
1535 for (int j = 0; j < bitmap.GetHeight(); j++)
1536 {
1537 for (int i = 0; i < bitmap.GetWidth(); i++)
1538 {
dbda9e86 1539 int pixel = XGetPixel( ximage, i, j );
38274997
RR
1540 if (bpp <= 8)
1541 {
1542 data[pos] = colors[pixel].red >> 8;
1543 data[pos+1] = colors[pixel].green >> 8;
1544 data[pos+2] = colors[pixel].blue >> 8;
1545 } else if (bpp == 15)
1546 {
1547 data[pos] = (pixel >> 7) & 0xf8;
1548 data[pos+1] = (pixel >> 2) & 0xf8;
1549 data[pos+2] = (pixel << 3) & 0xf8;
1550 } else if (bpp == 16)
1551 {
1552 data[pos] = (pixel >> 8) & 0xf8;
1553 data[pos+1] = (pixel >> 3) & 0xfc;
1554 data[pos+2] = (pixel << 3) & 0xf8;
1555 } else
1556 {
1557 data[pos] = (pixel >> 16) & 0xff;
1558 data[pos+1] = (pixel >> 8) & 0xff;
1559 data[pos+2] = pixel & 0xff;
1560 }
c7abc967 1561
dbda9e86 1562 /*
38274997
RR
1563 if (gdk_image_mask)
1564 {
dbda9e86
JS
1565 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1566 if (mask_pixel == 0)
1567 {
1568 data[pos] = 16;
1569 data[pos+1] = 16;
1570 data[pos+2] = 16;
38274997 1571 }
dbda9e86
JS
1572 }
1573 */
c7abc967 1574
38274997
RR
1575 pos += 3;
1576 }
1577 }
c7abc967 1578
38274997 1579 XDestroyImage( ximage );
dbda9e86 1580 /*
38274997 1581 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
dbda9e86 1582 */
ee4c6942
JS
1583}
1584#endif
a91b47e8
JS
1585
1586// A module to allow wxImage initialization/cleanup
1587// without calling these functions from app.cpp or from
1588// the user's application.
1589
1590class wxImageModule: public wxModule
1591{
1592DECLARE_DYNAMIC_CLASS(wxImageModule)
1593public:
1594 wxImageModule() {}
1595 bool OnInit() { wxImage::InitStandardHandlers(); return TRUE; };
1596 void OnExit() { wxImage::CleanUpHandlers(); };
1597};
1598
1599IMPLEMENT_DYNAMIC_CLASS(wxImageModule, wxModule)