]> git.saurik.com Git - wxWidgets.git/blame - src/common/image.cpp
Attempt to implement a bunch of wx string.h equivalents.
[wxWidgets.git] / src / common / image.cpp
CommitLineData
01111366
RR
1/////////////////////////////////////////////////////////////////////////////
2// Name: image.cpp
3// Purpose: wxImage
4// Author: Robert Roebling
5// RCS-ID: $Id$
6// Copyright: (c) Robert Roebling
7// Licence: wxWindows licence
8/////////////////////////////////////////////////////////////////////////////
9
10#ifdef __GNUG__
11#pragma implementation "image.h"
12#endif
13
0b4f9ee3
UU
14// For compilers that support precompilation, includes "wx.h".
15#include "wx/wxprec.h"
16
17#ifdef __BORLANDC__
18#pragma hdrstop
19#endif
20
01111366 21#include "wx/image.h"
99c67c77 22#include "wx/bitmap.h"
01111366
RR
23#include "wx/debug.h"
24#include "wx/log.h"
f6fcbb63 25#include "wx/app.h"
dc86cb34 26#include "wx/filefn.h"
3d05544e 27#include "wx/wfstream.h"
b75867a6 28#include "wx/intl.h"
a91b47e8 29#include "wx/module.h"
01111366 30
58a8ab88
JS
31// For memcpy
32#include <string.h>
33
a3ef5bf5
JS
34#ifdef __SALFORDC__
35#ifdef FAR
36#undef FAR
37#endif
38#endif
39
2432b92d
JS
40#ifdef __WXMSW__
41#include <windows.h>
42#endif
43
01111366
RR
44//-----------------------------------------------------------------------------
45// wxImage
46//-----------------------------------------------------------------------------
47
48class wxImageRefData: public wxObjectRefData
49{
c7abc967 50
fd0eed64 51public:
dbda9e86
JS
52 wxImageRefData(void);
53 ~wxImageRefData(void);
c7abc967 54
dbda9e86
JS
55 int m_width;
56 int m_height;
57 unsigned char *m_data;
58 bool m_hasMask;
59 unsigned char m_maskRed,m_maskGreen,m_maskBlue;
60 bool m_ok;
01111366
RR
61};
62
63wxImageRefData::wxImageRefData(void)
64{
fd0eed64
RR
65 m_width = 0;
66 m_height = 0;
67 m_data = (unsigned char*) NULL;
68 m_ok = FALSE;
69 m_maskRed = 0;
70 m_maskGreen = 0;
71 m_maskBlue = 0;
72 m_hasMask = FALSE;
01111366
RR
73}
74
75wxImageRefData::~wxImageRefData(void)
76{
fd0eed64 77 if (m_data) free( m_data );
01111366
RR
78}
79
80wxList wxImage::sm_handlers;
81
82//-----------------------------------------------------------------------------
83
84#define M_IMGDATA ((wxImageRefData *)m_refData)
85
86#if !USE_SHARED_LIBRARIES
87IMPLEMENT_DYNAMIC_CLASS(wxImage, wxObject)
88#endif
89
90wxImage::wxImage()
91{
92}
93
94wxImage::wxImage( int width, int height )
95{
fd0eed64 96 Create( width, height );
01111366
RR
97}
98
99wxImage::wxImage( const wxString& name, long type )
100{
fd0eed64 101 LoadFile( name, type );
01111366
RR
102}
103
9e9ee68e
VS
104wxImage::wxImage( const wxString& name, const wxString& mimetype )
105{
106 LoadFile( name, mimetype );
107}
108
e02afc7a 109#if wxUSE_STREAMS
3d05544e
JS
110wxImage::wxImage( wxInputStream& stream, long type )
111{
112 LoadFile( stream, type );
113}
9e9ee68e
VS
114
115wxImage::wxImage( wxInputStream& stream, const wxString& mimetype )
116{
117 LoadFile( stream, mimetype );
118}
e02afc7a 119#endif // wxUSE_STREAMS
3d05544e 120
4698648f
VZ
121wxImage::wxImage( const wxImage& image )
122{
123 Ref(image);
01111366
RR
124}
125
4698648f
VZ
126wxImage::wxImage( const wxImage* image )
127{
128 if (image) Ref(*image);
01111366
RR
129}
130
131void wxImage::Create( int width, int height )
132{
fd0eed64 133 m_refData = new wxImageRefData();
c7abc967 134
fd0eed64
RR
135 M_IMGDATA->m_data = (unsigned char *) malloc( width*height*3 );
136 if (M_IMGDATA->m_data)
137 {
138 for (int l = 0; l < width*height*3; l++) M_IMGDATA->m_data[l] = 0;
c7abc967 139
fd0eed64
RR
140 M_IMGDATA->m_width = width;
141 M_IMGDATA->m_height = height;
142 M_IMGDATA->m_ok = TRUE;
143 }
144 else
145 {
146 UnRef();
147 }
01111366
RR
148}
149
150void wxImage::Destroy()
151{
fd0eed64 152 UnRef();
01111366
RR
153}
154
4bc67cc5
RR
155wxImage wxImage::Scale( int width, int height )
156{
157 wxImage image;
c7abc967 158
50920146 159 wxCHECK_MSG( Ok(), image, _T("invalid image") );
c7abc967 160
50920146 161 wxCHECK_MSG( (width > 0) && (height > 0), image, _T("invalid image size") );
c7abc967 162
4bc67cc5 163 image.Create( width, height );
c7abc967 164
4bc67cc5 165 char unsigned *data = image.GetData();
c7abc967 166
50920146 167 wxCHECK_MSG( data, image, _T("unable to create image") );
c7abc967 168
4bc67cc5
RR
169 if (M_IMGDATA->m_hasMask)
170 image.SetMaskColour( M_IMGDATA->m_maskRed, M_IMGDATA->m_maskGreen, M_IMGDATA->m_maskBlue );
c7abc967 171
6e13c196
RR
172 long old_height = M_IMGDATA->m_height;
173 long old_width = M_IMGDATA->m_width;
c7abc967 174
6e13c196
RR
175 char unsigned *source_data = M_IMGDATA->m_data;
176 char unsigned *target_data = data;
c7abc967 177
6e13c196 178 for (long j = 0; j < height; j++)
4bc67cc5 179 {
6e13c196 180 long y_offset = (j * old_height / height) * old_width;
c7abc967 181
6e13c196 182 for (long i = 0; i < width; i++)
4698648f 183 {
c7abc967
VZ
184 memcpy( target_data,
185 source_data + 3*(y_offset + ((i * old_width )/ width)),
dbda9e86 186 3 );
6e13c196 187 target_data += 3;
4698648f 188 }
4bc67cc5 189 }
c7abc967 190
4bc67cc5
RR
191 return image;
192}
4698648f 193
ef539066
RR
194void wxImage::SetRGB( int x, int y, unsigned char r, unsigned char g, unsigned char b )
195{
50920146 196 wxCHECK_RET( Ok(), _T("invalid image") );
c7abc967 197
ef539066
RR
198 int w = M_IMGDATA->m_width;
199 int h = M_IMGDATA->m_height;
c7abc967 200
50920146 201 wxCHECK_RET( (x>=0) && (y>=0) && (x<w) && (y<h), _T("invalid image index") );
c7abc967 202
ef539066 203 long pos = (y * w + x) * 3;
c7abc967 204
ef539066
RR
205 M_IMGDATA->m_data[ pos ] = r;
206 M_IMGDATA->m_data[ pos+1 ] = g;
207 M_IMGDATA->m_data[ pos+2 ] = b;
208}
209
210unsigned char wxImage::GetRed( int x, int y )
211{
50920146 212 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
c7abc967 213
ef539066
RR
214 int w = M_IMGDATA->m_width;
215 int h = M_IMGDATA->m_height;
c7abc967 216
50920146 217 wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, _T("invalid image index") );
c7abc967 218
ef539066 219 long pos = (y * w + x) * 3;
c7abc967 220
ef539066
RR
221 return M_IMGDATA->m_data[pos];
222}
223
224unsigned char wxImage::GetGreen( int x, int y )
225{
50920146 226 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
c7abc967 227
ef539066
RR
228 int w = M_IMGDATA->m_width;
229 int h = M_IMGDATA->m_height;
c7abc967 230
50920146 231 wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, _T("invalid image index") );
c7abc967 232
ef539066 233 long pos = (y * w + x) * 3;
c7abc967 234
ef539066
RR
235 return M_IMGDATA->m_data[pos+1];
236}
237
238unsigned char wxImage::GetBlue( int x, int y )
239{
50920146 240 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
c7abc967 241
ef539066
RR
242 int w = M_IMGDATA->m_width;
243 int h = M_IMGDATA->m_height;
c7abc967 244
50920146 245 wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, _T("invalid image index") );
c7abc967 246
ef539066 247 long pos = (y * w + x) * 3;
c7abc967 248
ef539066
RR
249 return M_IMGDATA->m_data[pos+2];
250}
4698648f
VZ
251
252bool wxImage::Ok() const
253{
254 return (M_IMGDATA && M_IMGDATA->m_ok);
01111366
RR
255}
256
257char unsigned *wxImage::GetData() const
258{
50920146 259 wxCHECK_MSG( Ok(), (char unsigned *)NULL, _T("invalid image") );
c7abc967 260
fd0eed64 261 return M_IMGDATA->m_data;
01111366
RR
262}
263
58a8ab88 264void wxImage::SetData( char unsigned *data )
01111366 265{
50920146 266 wxCHECK_RET( Ok(), _T("invalid image") );
58a8ab88
JS
267
268 memcpy(M_IMGDATA->m_data, data, M_IMGDATA->m_width * M_IMGDATA->m_height * 3);
01111366
RR
269}
270
271void wxImage::SetMaskColour( unsigned char r, unsigned char g, unsigned char b )
272{
50920146 273 wxCHECK_RET( Ok(), _T("invalid image") );
c7abc967 274
fd0eed64
RR
275 M_IMGDATA->m_maskRed = r;
276 M_IMGDATA->m_maskGreen = g;
277 M_IMGDATA->m_maskBlue = b;
278 M_IMGDATA->m_hasMask = TRUE;
01111366
RR
279}
280
281unsigned char wxImage::GetMaskRed() const
282{
50920146 283 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
c7abc967 284
fd0eed64 285 return M_IMGDATA->m_maskRed;
01111366
RR
286}
287
288unsigned char wxImage::GetMaskGreen() const
289{
50920146 290 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
c7abc967 291
fd0eed64 292 return M_IMGDATA->m_maskGreen;
01111366
RR
293}
294
295unsigned char wxImage::GetMaskBlue() const
296{
50920146 297 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
c7abc967 298
fd0eed64 299 return M_IMGDATA->m_maskBlue;
01111366 300}
4698648f 301
01111366
RR
302void wxImage::SetMask( bool mask )
303{
50920146 304 wxCHECK_RET( Ok(), _T("invalid image") );
c7abc967 305
fd0eed64 306 M_IMGDATA->m_hasMask = mask;
01111366
RR
307}
308
309bool wxImage::HasMask() const
310{
50920146 311 wxCHECK_MSG( Ok(), FALSE, _T("invalid image") );
c7abc967 312
fd0eed64 313 return M_IMGDATA->m_hasMask;
01111366
RR
314}
315
4698648f
VZ
316int wxImage::GetWidth() const
317{
50920146 318 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
c7abc967 319
4698648f 320 return M_IMGDATA->m_width;
01111366
RR
321}
322
4698648f
VZ
323int wxImage::GetHeight() const
324{
50920146 325 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
c7abc967 326
4698648f 327 return M_IMGDATA->m_height;
01111366
RR
328}
329
330bool wxImage::LoadFile( const wxString& filename, long type )
331{
e02afc7a 332#if wxUSE_STREAMS
3d05544e 333 if (wxFileExists(filename))
fd0eed64 334 {
3d05544e
JS
335 wxFileInputStream stream(filename);
336 return LoadFile(stream, type);
337 }
9e9ee68e
VS
338
339 else {
50920146 340 wxLogError( _T("Can't load image from file '%s': file does not exist."), filename.c_str() );
9e9ee68e
VS
341
342 return FALSE;
343 }
344#else // !wxUSE_STREAMS
345 return FALSE;
346#endif // wxUSE_STREAMS
347}
348
349bool wxImage::LoadFile( const wxString& filename, const wxString& mimetype )
350{
351#if wxUSE_STREAMS
352 if (wxFileExists(filename))
353 {
354 wxFileInputStream stream(filename);
355 return LoadFile(stream, mimetype);
356 }
c7abc967 357
3d05544e 358 else {
50920146 359 wxLogError( _T("Can't load image from file '%s': file does not exist."), filename.c_str() );
c7abc967 360
fd0eed64
RR
361 return FALSE;
362 }
e02afc7a 363#else // !wxUSE_STREAMS
dbda9e86 364 return FALSE;
e02afc7a 365#endif // wxUSE_STREAMS
1ccbb61a
VZ
366}
367
368bool wxImage::SaveFile( const wxString& filename, int type )
369{
e02afc7a 370#if wxUSE_STREAMS
1ccbb61a 371 wxFileOutputStream stream(filename);
9e9ee68e 372
1ccbb61a
VZ
373 if ( stream.LastError() == wxStream_NOERROR )
374 return SaveFile(stream, type);
375 else
e02afc7a 376#endif // wxUSE_STREAMS
1ccbb61a 377 return FALSE;
3d05544e 378}
01111366 379
9e9ee68e
VS
380bool wxImage::SaveFile( const wxString& filename, const wxString& mimetype )
381{
382#if wxUSE_STREAMS
383 wxFileOutputStream stream(filename);
c7abc967 384
9e9ee68e
VS
385 if ( stream.LastError() == wxStream_NOERROR )
386 return SaveFile(stream, mimetype);
387 else
388#endif // wxUSE_STREAMS
389 return FALSE;
390}
391
e02afc7a 392#if wxUSE_STREAMS
3d05544e
JS
393bool wxImage::LoadFile( wxInputStream& stream, long type )
394{
395 UnRef();
c7abc967 396
fd0eed64 397 m_refData = new wxImageRefData;
c7abc967 398
fd0eed64 399 wxImageHandler *handler = FindHandler(type);
c7abc967 400
4698648f 401 if (handler == NULL)
fd0eed64 402 {
50920146 403 wxLogWarning( _T("No image handler for type %d defined."), type );
c7abc967 404
fd0eed64
RR
405 return FALSE;
406 }
c7abc967 407
3d05544e 408 return handler->LoadFile( this, stream );
01111366
RR
409}
410
9e9ee68e
VS
411bool wxImage::LoadFile( wxInputStream& stream, const wxString& mimetype )
412{
413 UnRef();
414
415 m_refData = new wxImageRefData;
416
417 wxImageHandler *handler = FindHandlerMime(mimetype);
418
419 if (handler == NULL)
420 {
50920146 421 wxLogWarning( _T("No image handler for type %s defined."), mimetype.GetData() );
9e9ee68e
VS
422
423 return FALSE;
424 }
425
426 return handler->LoadFile( this, stream );
427}
428
3d05544e 429bool wxImage::SaveFile( wxOutputStream& stream, int type )
01111366 430{
50920146 431 wxCHECK_MSG( Ok(), FALSE, _T("invalid image") );
c7abc967 432
fd0eed64 433 wxImageHandler *handler = FindHandler(type);
c7abc967 434
4698648f 435 if (handler == NULL)
fd0eed64 436 {
50920146 437 wxLogWarning( _T("No image handler for type %d defined."), type );
9e9ee68e
VS
438
439 return FALSE;
440 }
441
442 return handler->SaveFile( this, stream );
443}
444
445bool wxImage::SaveFile( wxOutputStream& stream, const wxString& mimetype )
446{
50920146 447 wxCHECK_MSG( Ok(), FALSE, _T("invalid image") );
c7abc967 448
9e9ee68e 449 wxImageHandler *handler = FindHandlerMime(mimetype);
c7abc967 450
9e9ee68e
VS
451 if (handler == NULL)
452 {
50920146 453 wxLogWarning( _T("No image handler for type %s defined."), mimetype.GetData() );
c7abc967 454
dbda9e86 455 return FALSE;
fd0eed64 456 }
c7abc967 457
3d05544e 458 return handler->SaveFile( this, stream );
01111366 459}
e02afc7a 460#endif // wxUSE_STREAMS
01111366
RR
461
462void wxImage::AddHandler( wxImageHandler *handler )
463{
4698648f
VZ
464 // make sure that the memory will be freed at the program end
465 sm_handlers.DeleteContents(TRUE);
c7abc967 466
01111366
RR
467 sm_handlers.Append( handler );
468}
469
470void wxImage::InsertHandler( wxImageHandler *handler )
471{
4698648f
VZ
472 // make sure that the memory will be freed at the program end
473 sm_handlers.DeleteContents(TRUE);
c7abc967 474
01111366
RR
475 sm_handlers.Insert( handler );
476}
477
478bool wxImage::RemoveHandler( const wxString& name )
479{
fd0eed64
RR
480 wxImageHandler *handler = FindHandler(name);
481 if (handler)
482 {
483 sm_handlers.DeleteObject(handler);
484 return TRUE;
485 }
486 else
487 return FALSE;
01111366
RR
488}
489
490wxImageHandler *wxImage::FindHandler( const wxString& name )
491{
fd0eed64
RR
492 wxNode *node = sm_handlers.First();
493 while (node)
494 {
495 wxImageHandler *handler = (wxImageHandler*)node->Data();
ce3ed50d 496 if (handler->GetName().Cmp(name) == 0) return handler;
c7abc967 497
fd0eed64
RR
498 node = node->Next();
499 }
500 return (wxImageHandler *)NULL;
01111366
RR
501}
502
503wxImageHandler *wxImage::FindHandler( const wxString& extension, long bitmapType )
504{
fd0eed64
RR
505 wxNode *node = sm_handlers.First();
506 while (node)
507 {
508 wxImageHandler *handler = (wxImageHandler*)node->Data();
ce3ed50d 509 if ( (handler->GetExtension().Cmp(extension) == 0) &&
fd0eed64 510 (bitmapType == -1 || handler->GetType() == bitmapType) )
dbda9e86 511 return handler;
fd0eed64
RR
512 node = node->Next();
513 }
514 return (wxImageHandler*)NULL;
01111366
RR
515}
516
517wxImageHandler *wxImage::FindHandler( long bitmapType )
518{
fd0eed64
RR
519 wxNode *node = sm_handlers.First();
520 while (node)
521 {
522 wxImageHandler *handler = (wxImageHandler *)node->Data();
523 if (handler->GetType() == bitmapType) return handler;
524 node = node->Next();
525 }
526 return NULL;
527}
528
9e9ee68e
VS
529wxImageHandler *wxImage::FindHandlerMime( const wxString& mimetype )
530{
531 wxNode *node = sm_handlers.First();
532 while (node)
533 {
534 wxImageHandler *handler = (wxImageHandler *)node->Data();
535 if (handler->GetMimeType().IsSameAs(mimetype, FALSE)) return handler;
536 node = node->Next();
537 }
538 return NULL;
539}
540
fd0eed64
RR
541void wxImage::InitStandardHandlers()
542{
543 AddHandler( new wxBMPHandler );
01111366
RR
544}
545
546void wxImage::CleanUpHandlers()
547{
fd0eed64
RR
548 wxNode *node = sm_handlers.First();
549 while (node)
550 {
551 wxImageHandler *handler = (wxImageHandler *)node->Data();
552 wxNode *next = node->Next();
553 delete handler;
554 delete node;
555 node = next;
556 }
01111366
RR
557}
558
559//-----------------------------------------------------------------------------
560// wxImageHandler
561//-----------------------------------------------------------------------------
562
563#if !USE_SHARED_LIBRARIES
564IMPLEMENT_DYNAMIC_CLASS(wxImageHandler,wxObject)
565#endif
566
e02afc7a 567#if wxUSE_STREAMS
3d05544e 568bool wxImageHandler::LoadFile( wxImage *WXUNUSED(image), wxInputStream& WXUNUSED(stream) )
01111366 569{
fd0eed64 570 return FALSE;
01111366
RR
571}
572
3d05544e 573bool wxImageHandler::SaveFile( wxImage *WXUNUSED(image), wxOutputStream& WXUNUSED(stream) )
01111366 574{
fd0eed64 575 return FALSE;
01111366 576}
e02afc7a 577#endif // wxUSE_STREAMS
01111366 578
01111366 579//-----------------------------------------------------------------------------
ce4169a4 580// MSW conversion routines
01111366
RR
581//-----------------------------------------------------------------------------
582
e3554471
JS
583#ifdef __WXMSW__
584
585wxBitmap wxImage::ConvertToBitmap() const
586{
dbda9e86 587 // sizeLimit is the MS upper limit for the DIB size
c7abc967
VZ
588 int sizeLimit = 1024*768*3;
589
dbda9e86 590 // width and height of the device-dependent bitmap
bba6f3bd
UA
591 int width = GetWidth();
592 int bmpHeight = GetHeight();
c7abc967 593
dbda9e86 594 // calc the number of bytes per scanline and padding
bba6f3bd
UA
595 int bytePerLine = width*3;
596 int sizeDWORD = sizeof( DWORD );
597 div_t lineBoundary = div( bytePerLine, sizeDWORD );
598 int padding = 0;
c7abc967 599 if( lineBoundary.rem > 0 )
bba6f3bd
UA
600 {
601 padding = sizeDWORD - lineBoundary.rem;
602 bytePerLine += padding;
603 }
dbda9e86 604 // calc the number of DIBs and heights of DIBs
bba6f3bd
UA
605 int numDIB = 1;
606 int hRemain = 0;
607 int height = sizeLimit/bytePerLine;
608 if( height >= bmpHeight )
c7abc967 609 height = bmpHeight;
bba6f3bd
UA
610 else
611 {
612 div_t result = div( bmpHeight, height );
613 numDIB = result.quot;
dbda9e86
JS
614 hRemain = result.rem;
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 );
810 div_t lineBoundary = div( bytePerLine, sizeDWORD );
811 int padding = 0;
c7abc967 812 if( lineBoundary.rem > 0 )
bba6f3bd
UA
813 {
814 padding = sizeDWORD - lineBoundary.rem;
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
RR
948 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
949 if (visual == NULL) visual = gdk_window_get_visual( (GdkWindow*) &gdk_root_parent );
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 =
dbda9e86 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
99c67c77 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 {
1014 GdkVisual *visual = gdk_visual_get_system();
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
VZ
1489
1490 wxCHECK_MSG( vi, wxNullBitmap, _T("no visual") );
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)