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