]> git.saurik.com Git - wxWidgets.git/blame - src/common/image.cpp
Committing in .
[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();
004fd0c8 455
87202f78 456 for ( wxList::Node *node = list.GetFirst(); node; node = node->GetNext() )
004fd0c8 457 {
87202f78
SB
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
7c74e7fe
SC
1037#ifdef __WXMAC__
1038
1039#include <PictUtils.h>
1040
1041extern CTabHandle wxMacCreateColorTable( int numColors ) ;
1042extern void wxMacDestroyColorTable( CTabHandle colors ) ;
1043extern void wxMacSetColorTableEntry( CTabHandle newColors , int index , int red , int green , int blue ) ;
1044extern GWorldPtr wxMacCreateGWorld( int height , int width , int depth ) ;
1045extern void wxMacDestroyGWorld( GWorldPtr gw ) ;
1046
1047wxBitmap wxImage::ConvertToBitmap() const
1048{
1049 // width and height of the device-dependent bitmap
1050 int width = GetWidth();
1051 int height = GetHeight();
1052
1053 // Create picture
1054
1055 wxBitmap bitmap( width , height , wxDisplayDepth() ) ;
1056
1057 // Create mask
1058
1059 if (HasMask())
1060 {
1061 /*
1062 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1063
1064 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1065
1066 wxMask *mask = new wxMask();
1067 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1068
1069 bitmap.SetMask( mask );
1070 */
1071 }
1072
1073 // Render
1074
1075 int r_mask = GetMaskRed();
1076 int g_mask = GetMaskGreen();
1077 int b_mask = GetMaskBlue();
1078
1079 CGrafPtr origPort ;
1080 GDHandle origDevice ;
1081
1082 GetGWorld( &origPort , &origDevice ) ;
1083 SetGWorld( bitmap.GetHBITMAP() , NULL ) ;
1084
1085 register unsigned char* data = GetData();
1086
1087 int index = 0;
1088 for (int y = 0; y < height; y++)
1089 {
1090#if 0
1091 unsigned char lastr = 0 ;
1092 unsigned char lastg = 0 ;
1093 unsigned char lastb = 0 ;
1094 RGBColor lastcolor ;
1095
1096 MoveTo( 0 , y ) ;
1097 for (int x = 0; x < width; x++)
1098 {
1099 unsigned char r = data[index++];
1100 unsigned char g = data[index++];
1101 unsigned char b = data[index++];
1102
1103 if ( r != lastr || g != lastg || b != lastb )
1104 {
1105 lastcolor.red = ( lastr << 8 ) + lastr ;
1106 lastcolor.green = ( lastg << 8 ) + lastg ;
1107 lastcolor.blue = ( lastb << 8 ) + lastb ;
1108 RGBForeColor( &lastcolor ) ;
1109 LineTo( x , y ) ;
1110 lastr = r ;
1111 lastg = g ;
1112 lastb = b ;
1113 }
1114 } // for width
1115 lastcolor.red = ( lastr << 8 ) + lastr ;
1116 lastcolor.green = ( lastg << 8 ) + lastg ;
1117 lastcolor.blue = ( lastb << 8 ) + lastb ;
1118 RGBForeColor( &lastcolor ) ;
1119 LineTo( width - 1 , y ) ;
1120#else
1121 for (int x = 0; x < width; x++)
1122 {
1123 unsigned char r = data[index++];
1124 unsigned char g = data[index++];
1125 unsigned char b = data[index++];
1126 RGBColor color ;
1127 color.red = ( r << 8 ) + r ;
1128 color.green = ( g << 8 ) + g ;
1129 color.blue = ( b << 8 ) + b ;
1130 SetCPixel( x , y , &color ) ;
1131 }
1132#endif
1133 } // for height
1134
1135 SetGWorld( origPort , origDevice ) ;
1136
1137 return bitmap;
1138
1139}
1140
1141wxImage::wxImage( const wxBitmap &bitmap )
1142{
1143 // check the bitmap
1144 if( !bitmap.Ok() )
1145 {
1146 wxFAIL_MSG( "invalid bitmap" );
1147 return;
1148 }
1149
1150 // create an wxImage object
1151 int width = bitmap.GetWidth();
1152 int height = bitmap.GetHeight();
1153 Create( width, height );
1154 /*
1155 unsigned char *data = GetData();
1156 if( !data )
1157 {
1158 wxFAIL_MSG( "could not allocate data for image" );
1159 return;
1160 }
1161
1162 // calc the number of bytes per scanline and padding in the DIB
1163 int bytePerLine = width*3;
1164 int sizeDWORD = sizeof( DWORD );
1165 div_t lineBoundary = div( bytePerLine, sizeDWORD );
1166 int padding = 0;
1167 if( lineBoundary.rem > 0 )
1168 {
1169 padding = sizeDWORD - lineBoundary.rem;
1170 bytePerLine += padding;
1171 }
1172
1173 // create a DIB header
1174 int headersize = sizeof(BITMAPINFOHEADER);
1175 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
1176 if( !lpDIBh )
1177 {
1178 wxFAIL_MSG( "could not allocate data for DIB header" );
1179 free( data );
1180 return;
1181 }
1182 // Fill in the DIB header
1183 lpDIBh->bmiHeader.biSize = headersize;
1184 lpDIBh->bmiHeader.biWidth = width;
1185 lpDIBh->bmiHeader.biHeight = -height;
1186 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
1187 lpDIBh->bmiHeader.biPlanes = 1;
1188 lpDIBh->bmiHeader.biBitCount = 24;
1189 lpDIBh->bmiHeader.biCompression = BI_RGB;
1190 lpDIBh->bmiHeader.biClrUsed = 0;
1191 // These seem not really needed for our purpose here.
1192 lpDIBh->bmiHeader.biClrImportant = 0;
1193 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
1194 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
1195 // memory for DIB data
1196 unsigned char *lpBits;
1197 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
1198 if( !lpBits )
1199 {
1200 wxFAIL_MSG( "could not allocate data for DIB" );
1201 free( data );
1202 free( lpDIBh );
1203 return;
1204 }
1205
1206 // copy data from the device-dependent bitmap to the DIB
1207 HDC hdc = ::GetDC(NULL);
1208 HBITMAP hbitmap;
1209 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
1210 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1211
1212 // copy DIB data into the wxImage object
1213 int i, j;
1214 unsigned char *ptdata = data;
1215 unsigned char *ptbits = lpBits;
1216 for( i=0; i<height; i++ )
1217 {
1218 for( j=0; j<width; j++ )
1219 {
1220 *(ptdata++) = *(ptbits+2);
1221 *(ptdata++) = *(ptbits+1);
1222 *(ptdata++) = *(ptbits );
1223 ptbits += 3;
1224 }
1225 ptbits += padding;
1226 }
1227
1228 // similarly, set data according to the possible mask bitmap
1229 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
1230 {
1231 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
1232 // memory DC created, color set, data copied, and memory DC deleted
1233 HDC memdc = ::CreateCompatibleDC( hdc );
1234 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
1235 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
1236 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1237 ::DeleteDC( memdc );
1238 // background color set to RGB(16,16,16) in consistent with wxGTK
1239 unsigned char r=16, g=16, b=16;
1240 ptdata = data;
1241 ptbits = lpBits;
1242 for( i=0; i<height; i++ )
1243 {
1244 for( j=0; j<width; j++ )
1245 {
1246 if( *ptbits != 0 )
1247 ptdata += 3;
1248 else
1249 {
1250 *(ptdata++) = r;
1251 *(ptdata++) = g;
1252 *(ptdata++) = b;
1253 }
1254 ptbits += 3;
1255 }
1256 ptbits += padding;
1257 }
1258 SetMaskColour( r, g, b );
1259 SetMask( TRUE );
1260 }
1261 else
1262 {
1263 SetMask( FALSE );
1264 }
1265 // free allocated resources
1266 ::ReleaseDC(NULL, hdc);
1267 free(lpDIBh);
1268 free(lpBits);
1269 */
1270}
1271
1272#endif
1273
ce4169a4
RR
1274//-----------------------------------------------------------------------------
1275// GTK conversion routines
1276//-----------------------------------------------------------------------------
1277
99c67c77
RR
1278#ifdef __WXGTK__
1279
83624f79
RR
1280#include "gtk/gtk.h"
1281#include "gdk/gdk.h"
1282#include "gdk/gdkx.h"
1283
ba0730de
RR
1284#if (GTK_MINOR_VERSION > 0)
1285#include "gdk/gdkrgb.h"
1286#endif
1287
99c67c77
RR
1288wxBitmap wxImage::ConvertToBitmap() const
1289{
1290 wxBitmap bitmap;
c7abc967 1291
223d09f6 1292 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
c7abc967 1293
99c67c77
RR
1294 int width = GetWidth();
1295 int height = GetHeight();
c7abc967 1296
99c67c77
RR
1297 bitmap.SetHeight( height );
1298 bitmap.SetWidth( width );
c7abc967 1299
ba0730de
RR
1300 bitmap.SetPixmap( gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, -1 ) );
1301
1302 // Retrieve depth
c7abc967 1303
ba0730de 1304 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
b134516c 1305 if (visual == NULL) visual = gdk_visual_get_system();
ba0730de 1306 int bpp = visual->depth;
c7abc967 1307
ba0730de 1308 bitmap.SetDepth( bpp );
c7abc967 1309
ba0730de
RR
1310 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
1311 if (bpp < 8) bpp = 8;
c7abc967 1312
ba0730de
RR
1313#if (GTK_MINOR_VERSION > 0)
1314
1315 if (!HasMask() && (bpp > 8))
1316 {
1317 static bool s_hasInitialized = FALSE;
c7abc967 1318
995612e2
VZ
1319 if (!s_hasInitialized)
1320 {
1321 gdk_rgb_init();
1322 s_hasInitialized = TRUE;
1323 }
c7abc967 1324
ba0730de 1325 GdkGC *gc = gdk_gc_new( bitmap.GetPixmap() );
c7abc967 1326
995612e2
VZ
1327 gdk_draw_rgb_image( bitmap.GetPixmap(),
1328 gc,
1329 0, 0,
1330 width, height,
1331 GDK_RGB_DITHER_NONE,
1332 GetData(),
1333 width*3 );
c7abc967 1334
ba0730de 1335 gdk_gc_unref( gc );
c7abc967 1336
995612e2 1337 return bitmap;
ba0730de 1338 }
c7abc967 1339
ba0730de 1340#endif
c7abc967 1341
ba0730de 1342 // Create picture image
c7abc967 1343
99c67c77 1344 GdkImage *data_image =
b134516c 1345 gdk_image_new( GDK_IMAGE_FASTEST, gdk_visual_get_system(), width, height );
c7abc967 1346
ba0730de 1347 // Create mask image
c7abc967 1348
99c67c77 1349 GdkImage *mask_image = (GdkImage*) NULL;
c7abc967 1350
99c67c77
RR
1351 if (HasMask())
1352 {
1353 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
c7abc967 1354
b134516c 1355 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
c7abc967 1356
4698648f
VZ
1357 wxMask *mask = new wxMask();
1358 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
c7abc967 1359
4698648f 1360 bitmap.SetMask( mask );
99c67c77 1361 }
c7abc967 1362
99c67c77 1363 // Render
c7abc967 1364
99c67c77
RR
1365 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1366 byte_order b_o = RGB;
c7abc967 1367
99c67c77
RR
1368 if (bpp >= 24)
1369 {
b134516c 1370 GdkVisual *visual = gdk_visual_get_system();
99c67c77
RR
1371 if ((visual->red_mask > visual->green_mask) && (visual->green_mask > visual->blue_mask)) b_o = RGB;
1372 else if ((visual->red_mask > visual->blue_mask) && (visual->blue_mask > visual->green_mask)) b_o = RGB;
1373 else if ((visual->blue_mask > visual->red_mask) && (visual->red_mask > visual->green_mask)) b_o = BRG;
1374 else if ((visual->blue_mask > visual->green_mask) && (visual->green_mask > visual->red_mask)) b_o = BGR;
1375 else if ((visual->green_mask > visual->red_mask) && (visual->red_mask > visual->blue_mask)) b_o = GRB;
1376 else if ((visual->green_mask > visual->blue_mask) && (visual->blue_mask > visual->red_mask)) b_o = GBR;
1377 }
c7abc967 1378
99c67c77
RR
1379 int r_mask = GetMaskRed();
1380 int g_mask = GetMaskGreen();
1381 int b_mask = GetMaskBlue();
c7abc967 1382
99c67c77 1383 unsigned char* data = GetData();
c7abc967 1384
99c67c77
RR
1385 int index = 0;
1386 for (int y = 0; y < height; y++)
1387 {
1388 for (int x = 0; x < width; x++)
1389 {
1390 int r = data[index];
4698648f 1391 index++;
99c67c77 1392 int g = data[index];
4698648f 1393 index++;
99c67c77 1394 int b = data[index];
4698648f 1395 index++;
c7abc967 1396
4698648f
VZ
1397 if (HasMask())
1398 {
1399 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1400 gdk_image_put_pixel( mask_image, x, y, 1 );
1401 else
1402 gdk_image_put_pixel( mask_image, x, y, 0 );
1403 }
c7abc967 1404
4698648f
VZ
1405 if (HasMask())
1406 {
1407 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1408 gdk_image_put_pixel( mask_image, x, y, 1 );
1409 else
1410 gdk_image_put_pixel( mask_image, x, y, 0 );
1411 }
c7abc967 1412
4698648f
VZ
1413 switch (bpp)
1414 {
dbda9e86 1415 case 8:
4698648f 1416 {
f6fcbb63 1417 int pixel = -1;
4698648f
VZ
1418 if (wxTheApp->m_colorCube)
1419 {
38274997 1420 pixel = wxTheApp->m_colorCube[ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
4698648f 1421 }
f6fcbb63 1422 else
4698648f
VZ
1423 {
1424 GdkColormap *cmap = gtk_widget_get_default_colormap();
f6fcbb63
RR
1425 GdkColor *colors = cmap->colors;
1426 int max = 3 * (65536);
c7abc967 1427
f6fcbb63
RR
1428 for (int i = 0; i < cmap->size; i++)
1429 {
1430 int rdiff = (r << 8) - colors[i].red;
1431 int gdiff = (g << 8) - colors[i].green;
1432 int bdiff = (b << 8) - colors[i].blue;
1433 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1434 if (sum < max) { pixel = i; max = sum; }
4698648f 1435 }
99c67c77 1436 }
c7abc967 1437
4698648f 1438 gdk_image_put_pixel( data_image, x, y, pixel );
c7abc967 1439
4698648f
VZ
1440 break;
1441 }
dbda9e86 1442 case 15:
4698648f
VZ
1443 {
1444 guint32 pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1445 gdk_image_put_pixel( data_image, x, y, pixel );
1446 break;
1447 }
dbda9e86 1448 case 16:
4698648f
VZ
1449 {
1450 guint32 pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1451 gdk_image_put_pixel( data_image, x, y, pixel );
1452 break;
1453 }
dbda9e86
JS
1454 case 32:
1455 case 24:
4698648f
VZ
1456 {
1457 guint32 pixel = 0;
1458 switch (b_o)
1459 {
dbda9e86
JS
1460 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1461 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1462 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1463 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1464 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1465 case GBR: pixel = (g << 16) | (b << 8) | r; break;
4698648f
VZ
1466 }
1467 gdk_image_put_pixel( data_image, x, y, pixel );
1468 }
dbda9e86 1469 default: break;
4698648f 1470 }
99c67c77
RR
1471 } // for
1472 } // for
c7abc967 1473
99c67c77 1474 // Blit picture
c7abc967 1475
99c67c77 1476 GdkGC *data_gc = gdk_gc_new( bitmap.GetPixmap() );
c7abc967 1477
99c67c77 1478 gdk_draw_image( bitmap.GetPixmap(), data_gc, data_image, 0, 0, 0, 0, width, height );
c7abc967 1479
99c67c77
RR
1480 gdk_image_destroy( data_image );
1481 gdk_gc_unref( data_gc );
c7abc967 1482
99c67c77 1483 // Blit mask
c7abc967 1484
99c67c77
RR
1485 if (HasMask())
1486 {
1487 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
c7abc967 1488
99c67c77 1489 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
c7abc967 1490
99c67c77
RR
1491 gdk_image_destroy( mask_image );
1492 gdk_gc_unref( mask_gc );
1493 }
c7abc967 1494
99c67c77
RR
1495 return bitmap;
1496}
1497
1498wxImage::wxImage( const wxBitmap &bitmap )
1499{
223d09f6 1500 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
c7abc967 1501
c6d73ef6
RR
1502 GdkImage *gdk_image = (GdkImage*) NULL;
1503 if (bitmap.GetPixmap())
1504 {
1505 gdk_image = gdk_image_get( bitmap.GetPixmap(),
1506 0, 0,
1507 bitmap.GetWidth(), bitmap.GetHeight() );
1508 } else
1509 if (bitmap.GetBitmap())
1510 {
1511 gdk_image = gdk_image_get( bitmap.GetBitmap(),
1512 0, 0,
1513 bitmap.GetWidth(), bitmap.GetHeight() );
1514 } else
1515 {
1516 wxFAIL_MSG( wxT("Ill-formed bitmap") );
1517 }
c7abc967 1518
223d09f6 1519 wxCHECK_RET( gdk_image, wxT("couldn't create image") );
c7abc967 1520
99c67c77
RR
1521 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1522 char unsigned *data = GetData();
c7abc967 1523
99c67c77
RR
1524 if (!data)
1525 {
1526 gdk_image_destroy( gdk_image );
223d09f6 1527 wxFAIL_MSG( wxT("couldn't create image") );
4698648f 1528 return;
99c67c77 1529 }
c7abc967 1530
99c67c77
RR
1531 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1532 if (bitmap.GetMask())
1533 {
1534 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
dbda9e86
JS
1535 0, 0,
1536 bitmap.GetWidth(), bitmap.GetHeight() );
c7abc967 1537
4698648f 1538 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
99c67c77 1539 }
c7abc967 1540
c6d73ef6
RR
1541 GdkVisual *visual = (GdkVisual*) NULL;
1542 if (bitmap.GetPixmap())
1543 visual = gdk_window_get_visual( bitmap.GetPixmap() );
1544 else
1545 visual = gdk_window_get_visual( bitmap.GetBitmap() );
1546
99c67c77
RR
1547 if (visual == NULL) visual = gdk_window_get_visual( (GdkWindow*) &gdk_root_parent );
1548 int bpp = visual->depth;
1549 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
c7abc967 1550
99c67c77 1551 GdkColormap *cmap = gtk_widget_get_default_colormap();
c7abc967 1552
99c67c77
RR
1553 long pos = 0;
1554 for (int j = 0; j < bitmap.GetHeight(); j++)
1555 {
1556 for (int i = 0; i < bitmap.GetWidth(); i++)
1557 {
4cb122de 1558 wxInt32 pixel = gdk_image_get_pixel( gdk_image, i, j );
c6d73ef6 1559 // pixel = wxINT32_SWAP_ON_BE( pixel );
99c67c77
RR
1560 if (bpp <= 8)
1561 {
1562 data[pos] = cmap->colors[pixel].red >> 8;
1563 data[pos+1] = cmap->colors[pixel].green >> 8;
1564 data[pos+2] = cmap->colors[pixel].blue >> 8;
1565 } else if (bpp == 15)
1566 {
1567 data[pos] = (pixel >> 7) & 0xf8;
1568 data[pos+1] = (pixel >> 2) & 0xf8;
1569 data[pos+2] = (pixel << 3) & 0xf8;
1570 } else if (bpp == 16)
1571 {
1572 data[pos] = (pixel >> 8) & 0xf8;
1573 data[pos+1] = (pixel >> 3) & 0xfc;
1574 data[pos+2] = (pixel << 3) & 0xf8;
1575 } else
1576 {
1577 data[pos] = (pixel >> 16) & 0xff;
1578 data[pos+1] = (pixel >> 8) & 0xff;
1579 data[pos+2] = pixel & 0xff;
1580 }
c7abc967 1581
4698648f
VZ
1582 if (gdk_image_mask)
1583 {
1584 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1585 if (mask_pixel == 0)
1586 {
99c67c77
RR
1587 data[pos] = 16;
1588 data[pos+1] = 16;
1589 data[pos+2] = 16;
dbda9e86 1590 }
4698648f 1591 }
c7abc967 1592
99c67c77
RR
1593 pos += 3;
1594 }
1595 }
c7abc967 1596
99c67c77
RR
1597 gdk_image_destroy( gdk_image );
1598 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1599}
1600
1601#endif
ee4c6942 1602
ce4169a4
RR
1603//-----------------------------------------------------------------------------
1604// Motif conversion routines
1605//-----------------------------------------------------------------------------
1606
ee4c6942 1607#ifdef __WXMOTIF__
b75867a6
RR
1608
1609#include <Xm/Xm.h>
1610#include "wx/utils.h"
38274997 1611#include <math.h>
b75867a6 1612
ee4c6942
JS
1613wxBitmap wxImage::ConvertToBitmap() const
1614{
b75867a6 1615 wxBitmap bitmap;
c7abc967 1616
223d09f6 1617 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
a91b47e8 1618
b75867a6
RR
1619 int width = GetWidth();
1620 int height = GetHeight();
c7abc967 1621
b75867a6
RR
1622 bitmap.SetHeight( height );
1623 bitmap.SetWidth( width );
c7abc967 1624
b75867a6
RR
1625 Display *dpy = (Display*) wxGetDisplay();
1626 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1627 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
c7abc967 1628
b75867a6 1629 // Create image
c7abc967 1630
b75867a6 1631 XImage *data_image = XCreateImage( dpy, vis, bpp, ZPixmap, 0, 0, width, height, 32, 0 );
a91b47e8 1632 data_image->data = (char*) malloc( data_image->bytes_per_line * data_image->height );
c7abc967 1633
b75867a6 1634 bitmap.Create( width, height, bpp );
a91b47e8 1635
dbda9e86 1636 /*
b75867a6 1637 // Create mask
c7abc967 1638
dbda9e86 1639 GdkImage *mask_image = (GdkImage*) NULL;
c7abc967 1640
dbda9e86
JS
1641 if (HasMask())
1642 {
b75867a6 1643 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
c7abc967 1644
dbda9e86 1645 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
c7abc967 1646
dbda9e86
JS
1647 wxMask *mask = new wxMask();
1648 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
c7abc967 1649
dbda9e86
JS
1650 bitmap.SetMask( mask );
1651 }
1652 */
c7abc967 1653
b75867a6 1654 // Retrieve depth info
c7abc967 1655
b75867a6
RR
1656 XVisualInfo vinfo_template;
1657 XVisualInfo *vi;
c7abc967 1658
b75867a6
RR
1659 vinfo_template.visual = vis;
1660 vinfo_template.visualid = XVisualIDFromVisual( vis );
1661 vinfo_template.depth = bpp;
1662 int nitem = 0;
c7abc967 1663
b75867a6 1664 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
c7abc967 1665
223d09f6 1666 wxCHECK_MSG( vi, wxNullBitmap, wxT("no visual") );
c7abc967 1667
38274997 1668 XFree( vi );
a91b47e8 1669
b75867a6
RR
1670 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1671 if (bpp < 8) bpp = 8;
c7abc967 1672
b75867a6 1673 // Render
c7abc967 1674
b75867a6
RR
1675 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1676 byte_order b_o = RGB;
c7abc967 1677
b75867a6
RR
1678 if (bpp >= 24)
1679 {
1680 if ((vi->red_mask > vi->green_mask) && (vi->green_mask > vi->blue_mask)) b_o = RGB;
1681 else if ((vi->red_mask > vi->blue_mask) && (vi->blue_mask > vi->green_mask)) b_o = RGB;
1682 else if ((vi->blue_mask > vi->red_mask) && (vi->red_mask > vi->green_mask)) b_o = BRG;
1683 else if ((vi->blue_mask > vi->green_mask) && (vi->green_mask > vi->red_mask)) b_o = BGR;
1684 else if ((vi->green_mask > vi->red_mask) && (vi->red_mask > vi->blue_mask)) b_o = GRB;
1685 else if ((vi->green_mask > vi->blue_mask) && (vi->blue_mask > vi->red_mask)) b_o = GBR;
1686 }
c7abc967 1687
dbda9e86 1688 /*
b75867a6
RR
1689 int r_mask = GetMaskRed();
1690 int g_mask = GetMaskGreen();
1691 int b_mask = GetMaskBlue();
dbda9e86 1692 */
c7abc967 1693
38274997
RR
1694 XColor colors[256];
1695 if (bpp == 8)
1696 {
dbda9e86 1697 Colormap cmap = (Colormap) wxTheApp->GetMainColormap( dpy );
c7abc967 1698
38274997 1699 for (int i = 0; i < 256; i++) colors[i].pixel = i;
dbda9e86 1700 XQueryColors( dpy, cmap, colors, 256 );
38274997 1701 }
c7abc967 1702
b75867a6 1703 unsigned char* data = GetData();
c7abc967 1704
b75867a6
RR
1705 int index = 0;
1706 for (int y = 0; y < height; y++)
1707 {
1708 for (int x = 0; x < width; x++)
1709 {
1710 int r = data[index];
dbda9e86 1711 index++;
b75867a6 1712 int g = data[index];
dbda9e86 1713 index++;
b75867a6 1714 int b = data[index];
dbda9e86 1715 index++;
c7abc967 1716
dbda9e86
JS
1717 /*
1718 if (HasMask())
1719 {
1720 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1721 gdk_image_put_pixel( mask_image, x, y, 1 );
1722 else
1723 gdk_image_put_pixel( mask_image, x, y, 0 );
1724 }
1725 */
c7abc967 1726
dbda9e86
JS
1727 switch (bpp)
1728 {
1729 case 8:
1730 {
b75867a6 1731 int pixel = -1;
dbda9e86
JS
1732 /*
1733 if (wxTheApp->m_colorCube)
1734 {
1735 pixel = wxTheApp->m_colorCube
c7abc967
VZ
1736 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1737 }
b75867a6 1738 else
dbda9e86
JS
1739 {
1740 */
1741 int max = 3 * (65536);
1742 for (int i = 0; i < 256; i++)
1743 {
1744 int rdiff = (r << 8) - colors[i].red;
1745 int gdiff = (g << 8) - colors[i].green;
1746 int bdiff = (b << 8) - colors[i].blue;
1747 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1748 if (sum < max) { pixel = i; max = sum; }
1749 }
1750 /*
1751 }
1752 */
1753 XPutPixel( data_image, x, y, pixel );
1754 break;
1755 }
1756 case 15:
1757 {
1758 int pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1759 XPutPixel( data_image, x, y, pixel );
1760 break;
1761 }
1762 case 16:
1763 {
1764 int pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1765 XPutPixel( data_image, x, y, pixel );
1766 break;
1767 }
1768 case 32:
1769 case 24:
1770 {
1771 int pixel = 0;
1772 switch (b_o)
1773 {
1774 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1775 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1776 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1777 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1778 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1779 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1780 }
1781 XPutPixel( data_image, x, y, pixel );
1782 }
1783 default: break;
1784 }
b75867a6
RR
1785 } // for
1786 } // for
c7abc967 1787
b75867a6 1788 // Blit picture
c7abc967 1789
b75867a6
RR
1790 XGCValues gcvalues;
1791 gcvalues.foreground = BlackPixel( dpy, DefaultScreen( dpy ) );
1792 GC gc = XCreateGC( dpy, RootWindow ( dpy, DefaultScreen(dpy) ), GCForeground, &gcvalues );
1793 XPutImage( dpy, (Drawable)bitmap.GetPixmap(), gc, data_image, 0, 0, 0, 0, width, height );
c7abc967 1794
b75867a6
RR
1795 XDestroyImage( data_image );
1796 XFreeGC( dpy, gc );
c7abc967 1797
dbda9e86 1798 /*
b75867a6 1799 // Blit mask
c7abc967 1800
dbda9e86
JS
1801 if (HasMask())
1802 {
1803 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
c7abc967 1804
b75867a6 1805 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
c7abc967 1806
dbda9e86
JS
1807 gdk_image_destroy( mask_image );
1808 gdk_gc_unref( mask_gc );
1809 }
1810 */
c7abc967 1811
b75867a6 1812 return bitmap;
ee4c6942
JS
1813}
1814
1815wxImage::wxImage( const wxBitmap &bitmap )
1816{
223d09f6 1817 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
c7abc967 1818
38274997
RR
1819 Display *dpy = (Display*) wxGetDisplay();
1820 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1821 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
c7abc967 1822
38274997 1823 XImage *ximage = XGetImage( dpy,
dbda9e86
JS
1824 (Drawable)bitmap.GetPixmap(),
1825 0, 0,
1826 bitmap.GetWidth(), bitmap.GetHeight(),
1827 AllPlanes, ZPixmap );
c7abc967 1828
223d09f6 1829 wxCHECK_RET( ximage, wxT("couldn't create image") );
c7abc967 1830
38274997
RR
1831 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1832 char unsigned *data = GetData();
c7abc967 1833
38274997
RR
1834 if (!data)
1835 {
1836 XDestroyImage( ximage );
223d09f6 1837 wxFAIL_MSG( wxT("couldn't create image") );
38274997
RR
1838 return;
1839 }
c7abc967 1840
dbda9e86 1841 /*
38274997
RR
1842 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1843 if (bitmap.GetMask())
1844 {
dbda9e86
JS
1845 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1846 0, 0,
1847 bitmap.GetWidth(), bitmap.GetHeight() );
c7abc967 1848
dbda9e86
JS
1849 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1850 }
1851 */
c7abc967 1852
38274997 1853 // Retrieve depth info
c7abc967 1854
38274997
RR
1855 XVisualInfo vinfo_template;
1856 XVisualInfo *vi;
c7abc967 1857
38274997
RR
1858 vinfo_template.visual = vis;
1859 vinfo_template.visualid = XVisualIDFromVisual( vis );
1860 vinfo_template.depth = bpp;
1861 int nitem = 0;
c7abc967 1862
38274997 1863 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
c7abc967 1864
223d09f6 1865 wxCHECK_RET( vi, wxT("no visual") );
c7abc967 1866
38274997 1867 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
c7abc967 1868
38274997 1869 XFree( vi );
c7abc967 1870
38274997
RR
1871 XColor colors[256];
1872 if (bpp == 8)
1873 {
dbda9e86 1874 Colormap cmap = (Colormap)wxTheApp->GetMainColormap( dpy );
c7abc967 1875
38274997 1876 for (int i = 0; i < 256; i++) colors[i].pixel = i;
dbda9e86 1877 XQueryColors( dpy, cmap, colors, 256 );
38274997 1878 }
c7abc967 1879
38274997
RR
1880 long pos = 0;
1881 for (int j = 0; j < bitmap.GetHeight(); j++)
1882 {
1883 for (int i = 0; i < bitmap.GetWidth(); i++)
1884 {
dbda9e86 1885 int pixel = XGetPixel( ximage, i, j );
38274997
RR
1886 if (bpp <= 8)
1887 {
1888 data[pos] = colors[pixel].red >> 8;
1889 data[pos+1] = colors[pixel].green >> 8;
1890 data[pos+2] = colors[pixel].blue >> 8;
1891 } else if (bpp == 15)
1892 {
1893 data[pos] = (pixel >> 7) & 0xf8;
1894 data[pos+1] = (pixel >> 2) & 0xf8;
1895 data[pos+2] = (pixel << 3) & 0xf8;
1896 } else if (bpp == 16)
1897 {
1898 data[pos] = (pixel >> 8) & 0xf8;
1899 data[pos+1] = (pixel >> 3) & 0xfc;
1900 data[pos+2] = (pixel << 3) & 0xf8;
1901 } else
1902 {
1903 data[pos] = (pixel >> 16) & 0xff;
1904 data[pos+1] = (pixel >> 8) & 0xff;
1905 data[pos+2] = pixel & 0xff;
1906 }
c7abc967 1907
dbda9e86 1908 /*
38274997
RR
1909 if (gdk_image_mask)
1910 {
dbda9e86
JS
1911 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1912 if (mask_pixel == 0)
1913 {
1914 data[pos] = 16;
1915 data[pos+1] = 16;
1916 data[pos+2] = 16;
38274997 1917 }
dbda9e86
JS
1918 }
1919 */
c7abc967 1920
38274997
RR
1921 pos += 3;
1922 }
1923 }
c7abc967 1924
38274997 1925 XDestroyImage( ximage );
dbda9e86 1926 /*
38274997 1927 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
dbda9e86 1928 */
ee4c6942
JS
1929}
1930#endif
a91b47e8 1931
004fd0c8
DW
1932#ifdef __WXPM__
1933// OS/2 Presentation manager conversion routings
1934
1935wxBitmap wxImage::ConvertToBitmap() const
1936{
1937 if ( !Ok() )
1938 return wxNullBitmap;
1939 wxBitmap bitmap; // remove
1940// TODO:
1941/*
1942 int sizeLimit = 1024*768*3;
1943
1944 // width and height of the device-dependent bitmap
1945 int width = GetWidth();
1946 int bmpHeight = GetHeight();
1947
1948 // calc the number of bytes per scanline and padding
1949 int bytePerLine = width*3;
1950 int sizeDWORD = sizeof( DWORD );
1951 int lineBoundary = bytePerLine % sizeDWORD;
1952 int padding = 0;
1953 if( lineBoundary > 0 )
1954 {
1955 padding = sizeDWORD - lineBoundary;
1956 bytePerLine += padding;
1957 }
1958 // calc the number of DIBs and heights of DIBs
1959 int numDIB = 1;
1960 int hRemain = 0;
1961 int height = sizeLimit/bytePerLine;
1962 if( height >= bmpHeight )
1963 height = bmpHeight;
1964 else
1965 {
1966 numDIB = bmpHeight / height;
1967 hRemain = bmpHeight % height;
1968 if( hRemain >0 ) numDIB++;
1969 }
1970
1971 // set bitmap parameters
1972 wxBitmap bitmap;
1973 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
1974 bitmap.SetWidth( width );
1975 bitmap.SetHeight( bmpHeight );
1976 bitmap.SetDepth( wxDisplayDepth() );
1977
1978 // create a DIB header
1979 int headersize = sizeof(BITMAPINFOHEADER);
1980 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
1981 wxCHECK_MSG( lpDIBh, bitmap, wxT("could not allocate memory for DIB header") );
1982 // Fill in the DIB header
1983 lpDIBh->bmiHeader.biSize = headersize;
1984 lpDIBh->bmiHeader.biWidth = (DWORD)width;
1985 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
1986 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
1987 // the general formula for biSizeImage:
1988 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
1989 lpDIBh->bmiHeader.biPlanes = 1;
1990 lpDIBh->bmiHeader.biBitCount = 24;
1991 lpDIBh->bmiHeader.biCompression = BI_RGB;
1992 lpDIBh->bmiHeader.biClrUsed = 0;
1993 // These seem not really needed for our purpose here.
1994 lpDIBh->bmiHeader.biClrImportant = 0;
1995 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
1996 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
1997 // memory for DIB data
1998 unsigned char *lpBits;
1999 lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
2000 if( !lpBits )
2001 {
2002 wxFAIL_MSG( wxT("could not allocate memory for DIB") );
2003 free( lpDIBh );
2004 return bitmap;
2005 }
2006
2007 // create and set the device-dependent bitmap
2008 HDC hdc = ::GetDC(NULL);
2009 HDC memdc = ::CreateCompatibleDC( hdc );
2010 HBITMAP hbitmap;
2011 hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
2012 ::SelectObject( memdc, hbitmap);
2013
2014 // copy image data into DIB data and then into DDB (in a loop)
2015 unsigned char *data = GetData();
2016 int i, j, n;
2017 int origin = 0;
2018 unsigned char *ptdata = data;
2019 unsigned char *ptbits;
2020
2021 for( n=0; n<numDIB; n++ )
2022 {
2023 if( numDIB > 1 && n == numDIB-1 && hRemain > 0 )
2024 {
2025 // redefine height and size of the (possibly) last smaller DIB
2026 // memory is not reallocated
2027 height = hRemain;
2028 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2029 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2030 }
2031 ptbits = lpBits;
2032
2033 for( j=0; j<height; j++ )
2034 {
2035 for( i=0; i<width; i++ )
2036 {
2037 *(ptbits++) = *(ptdata+2);
2038 *(ptbits++) = *(ptdata+1);
2039 *(ptbits++) = *(ptdata );
2040 ptdata += 3;
2041 }
2042 for( i=0; i< padding; i++ ) *(ptbits++) = 0;
2043 }
2044 ::StretchDIBits( memdc, 0, origin, width, height,\
2045 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2046 origin += height;
2047 // if numDIB = 1, lines below can also be used
2048 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
2049 // The above line is equivalent to the following two lines.
2050 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2051 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
2052 // or the following lines
2053 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2054 // HDC memdc = ::CreateCompatibleDC( hdc );
2055 // ::SelectObject( memdc, hbitmap);
2056 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
2057 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
2058 // ::SelectObject( memdc, 0 );
2059 // ::DeleteDC( memdc );
2060 }
2061 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
2062
2063 // similarly, created an mono-bitmap for the possible mask
2064 if( HasMask() )
2065 {
2066 hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL );
2067 ::SelectObject( memdc, hbitmap);
2068 if( numDIB == 1 ) height = bmpHeight;
2069 else height = sizeLimit/bytePerLine;
2070 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2071 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2072 origin = 0;
2073 unsigned char r = GetMaskRed();
2074 unsigned char g = GetMaskGreen();
2075 unsigned char b = GetMaskBlue();
2076 unsigned char zero = 0, one = 255;
2077 ptdata = data;
2078 for( n=0; n<numDIB; n++ )
2079 {
2080 if( numDIB > 1 && n == numDIB - 1 && hRemain > 0 )
2081 {
2082 // redefine height and size of the (possibly) last smaller DIB
2083 // memory is not reallocated
2084 height = hRemain;
2085 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2086 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2087 }
2088 ptbits = lpBits;
2089 for( int j=0; j<height; j++ )
2090 {
2091 for(i=0; i<width; i++ )
2092 {
2093 if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
2094 {
2095 *(ptbits++) = one;
2096 *(ptbits++) = one;
2097 *(ptbits++) = one;
2098 }
2099 else
2100 {
2101 *(ptbits++) = zero;
2102 *(ptbits++) = zero;
2103 *(ptbits++) = zero;
2104 }
2105 }
2106 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
2107 }
2108 ::StretchDIBits( memdc, 0, origin, width, height,\
2109 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2110 origin += height;
2111 }
2112 // create a wxMask object
2113 wxMask *mask = new wxMask();
2114 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
2115 bitmap.SetMask( mask );
2116 }
2117
2118 // free allocated resources
2119 ::SelectObject( memdc, 0 );
2120 ::DeleteDC( memdc );
2121 ::ReleaseDC(NULL, hdc);
2122 free(lpDIBh);
2123 free(lpBits);
2124
2125 // check the wxBitmap object
2126 if( bitmap.GetHBITMAP() )
2127 bitmap.SetOk( TRUE );
2128 else
2129 bitmap.SetOk( FALSE );
2130*/
2131 return bitmap;
2132}
2133
2134wxImage::wxImage( const wxBitmap &bitmap )
2135{
2136 // check the bitmap
2137 if( !bitmap.Ok() )
2138 {
2139 wxFAIL_MSG( wxT("invalid bitmap") );
2140 return;
2141 }
2142
2143 // create an wxImage object
2144 int width = bitmap.GetWidth();
2145 int height = bitmap.GetHeight();
2146 Create( width, height );
2147 unsigned char *data = GetData();
2148 if( !data )
2149 {
2150 wxFAIL_MSG( wxT("could not allocate data for image") );
2151 return;
2152 }
2153
2154 // calc the number of bytes per scanline and padding in the DIB
2155 int bytePerLine = width*3;
2156 int sizeDWORD = sizeof( DWORD );
2157 int lineBoundary = bytePerLine % sizeDWORD;
2158 int padding = 0;
2159 if( lineBoundary > 0 )
2160 {
2161 padding = sizeDWORD - lineBoundary;
2162 bytePerLine += padding;
2163 }
2164// TODO:
2165/*
2166 // create a DIB header
2167 int headersize = sizeof(BITMAPINFOHEADER);
2168 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
2169 if( !lpDIBh )
2170 {
2171 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
2172 free( data );
2173 return;
2174 }
2175 // Fill in the DIB header
2176 lpDIBh->bmiHeader.biSize = headersize;
2177 lpDIBh->bmiHeader.biWidth = width;
2178 lpDIBh->bmiHeader.biHeight = -height;
2179 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
2180 lpDIBh->bmiHeader.biPlanes = 1;
2181 lpDIBh->bmiHeader.biBitCount = 24;
2182 lpDIBh->bmiHeader.biCompression = BI_RGB;
2183 lpDIBh->bmiHeader.biClrUsed = 0;
2184 // These seem not really needed for our purpose here.
2185 lpDIBh->bmiHeader.biClrImportant = 0;
2186 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2187 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2188 // memory for DIB data
2189 unsigned char *lpBits;
2190 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
2191 if( !lpBits )
2192 {
2193 wxFAIL_MSG( wxT("could not allocate data for DIB") );
2194 free( data );
2195 free( lpDIBh );
2196 return;
2197 }
2198
2199 // copy data from the device-dependent bitmap to the DIB
2200 HDC hdc = ::GetDC(NULL);
2201 HBITMAP hbitmap;
2202 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
2203 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2204
2205 // copy DIB data into the wxImage object
2206 int i, j;
2207 unsigned char *ptdata = data;
2208 unsigned char *ptbits = lpBits;
2209 for( i=0; i<height; i++ )
2210 {
2211 for( j=0; j<width; j++ )
2212 {
2213 *(ptdata++) = *(ptbits+2);
2214 *(ptdata++) = *(ptbits+1);
2215 *(ptdata++) = *(ptbits );
2216 ptbits += 3;
2217 }
2218 ptbits += padding;
2219 }
2220
2221 // similarly, set data according to the possible mask bitmap
2222 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
2223 {
2224 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
2225 // memory DC created, color set, data copied, and memory DC deleted
2226 HDC memdc = ::CreateCompatibleDC( hdc );
2227 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
2228 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
2229 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2230 ::DeleteDC( memdc );
2231 // background color set to RGB(16,16,16) in consistent with wxGTK
2232 unsigned char r=16, g=16, b=16;
2233 ptdata = data;
2234 ptbits = lpBits;
2235 for( i=0; i<height; i++ )
2236 {
2237 for( j=0; j<width; j++ )
2238 {
2239 if( *ptbits != 0 )
2240 ptdata += 3;
2241 else
2242 {
2243 *(ptdata++) = r;
2244 *(ptdata++) = g;
2245 *(ptdata++) = b;
2246 }
2247 ptbits += 3;
2248 }
2249 ptbits += padding;
2250 }
2251 SetMaskColour( r, g, b );
2252 SetMask( TRUE );
2253 }
2254 else
2255 {
2256 SetMask( FALSE );
2257 }
2258 // free allocated resources
2259 ::ReleaseDC(NULL, hdc);
2260 free(lpDIBh);
2261 free(lpBits);
2262*/
2263}
2264
2265#endif
2266
a91b47e8
JS
2267// A module to allow wxImage initialization/cleanup
2268// without calling these functions from app.cpp or from
2269// the user's application.
2270
2271class wxImageModule: public wxModule
2272{
2273DECLARE_DYNAMIC_CLASS(wxImageModule)
2274public:
2275 wxImageModule() {}
2276 bool OnInit() { wxImage::InitStandardHandlers(); return TRUE; };
2277 void OnExit() { wxImage::CleanUpHandlers(); };
2278};
2279
2280IMPLEMENT_DYNAMIC_CLASS(wxImageModule, wxModule)