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