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