]> git.saurik.com Git - wxWidgets.git/blame - src/common/image.cpp
added #if wxUSE_CLIPBOARD
[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{
fd0eed64 48public:
edccf428
VZ
49 wxImageRefData();
50 ~wxImageRefData();
c7abc967 51
dbda9e86
JS
52 int m_width;
53 int m_height;
54 unsigned char *m_data;
55 bool m_hasMask;
56 unsigned char m_maskRed,m_maskGreen,m_maskBlue;
57 bool m_ok;
01111366
RR
58};
59
edccf428 60wxImageRefData::wxImageRefData()
01111366 61{
fd0eed64
RR
62 m_width = 0;
63 m_height = 0;
64 m_data = (unsigned char*) NULL;
65 m_ok = FALSE;
66 m_maskRed = 0;
67 m_maskGreen = 0;
68 m_maskBlue = 0;
69 m_hasMask = FALSE;
01111366
RR
70}
71
edccf428 72wxImageRefData::~wxImageRefData()
01111366 73{
58c837a4
RR
74 if (m_data)
75 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 197
58c837a4
RR
198 wxCHECK_MSG( (rect.GetLeft()>=0) && (rect.GetTop()>=0) && (rect.GetRight()<=GetWidth()) && (rect.GetBottom()<=GetHeight()),
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 383 wxFileInputStream stream(filename);
1b055864
RR
384 wxBufferedInputStream bstream( stream );
385 return LoadFile(bstream, type);
3d05544e 386 }
58c837a4
RR
387 else
388 {
389 wxLogError( _("Can't load image from file '%s': file does not exist."), filename.c_str() );
9e9ee68e
VS
390
391 return FALSE;
392 }
393#else // !wxUSE_STREAMS
394 return FALSE;
395#endif // wxUSE_STREAMS
396}
397
398bool wxImage::LoadFile( const wxString& filename, const wxString& mimetype )
399{
400#if wxUSE_STREAMS
401 if (wxFileExists(filename))
402 {
403 wxFileInputStream stream(filename);
1b055864
RR
404 wxBufferedInputStream bstream( stream );
405 return LoadFile(bstream, mimetype);
9e9ee68e 406 }
58c837a4
RR
407 else
408 {
409 wxLogError( _("Can't load image from file '%s': file does not exist."), filename.c_str() );
c7abc967 410
fd0eed64
RR
411 return FALSE;
412 }
e02afc7a 413#else // !wxUSE_STREAMS
dbda9e86 414 return FALSE;
e02afc7a 415#endif // wxUSE_STREAMS
1ccbb61a
VZ
416}
417
418bool wxImage::SaveFile( const wxString& filename, int type )
419{
e02afc7a 420#if wxUSE_STREAMS
1ccbb61a 421 wxFileOutputStream stream(filename);
9e9ee68e 422
1ccbb61a 423 if ( stream.LastError() == wxStream_NOERROR )
1b055864
RR
424 {
425 wxBufferedOutputStream bstream( stream );
426 return SaveFile(bstream, type);
427 }
1ccbb61a 428 else
e02afc7a 429#endif // wxUSE_STREAMS
1ccbb61a 430 return FALSE;
3d05544e 431}
01111366 432
9e9ee68e
VS
433bool wxImage::SaveFile( const wxString& filename, const wxString& mimetype )
434{
435#if wxUSE_STREAMS
436 wxFileOutputStream stream(filename);
c7abc967 437
9e9ee68e 438 if ( stream.LastError() == wxStream_NOERROR )
1b055864
RR
439 {
440 wxBufferedOutputStream bstream( stream );
441 return SaveFile(bstream, mimetype);
442 }
9e9ee68e
VS
443 else
444#endif // wxUSE_STREAMS
445 return FALSE;
446}
447
87202f78
SB
448bool wxImage::CanRead( const wxString &name )
449{
450#if wxUSE_STREAMS
451 wxFileInputStream stream(name);
452 return CanRead(stream);
453#else
454 return FALSE;
455#endif
456}
457
e02afc7a 458#if wxUSE_STREAMS
deb2fec0 459
87202f78
SB
460bool wxImage::CanRead( wxInputStream &stream )
461{
462 wxList &list=GetHandlers();
004fd0c8 463
87202f78 464 for ( wxList::Node *node = list.GetFirst(); node; node = node->GetNext() )
004fd0c8 465 {
87202f78
SB
466 wxImageHandler *handler=(wxImageHandler*)node->GetData();
467 if (handler->CanRead( stream ))
468 return TRUE;
469 }
470
471 return FALSE;
472}
473
3d05544e
JS
474bool wxImage::LoadFile( wxInputStream& stream, long type )
475{
476 UnRef();
c7abc967 477
fd0eed64 478 m_refData = new wxImageRefData;
c7abc967 479
deb2fec0
SB
480 wxImageHandler *handler;
481
482 if (type==wxBITMAP_TYPE_ANY)
483 {
995612e2 484 wxList &list=GetHandlers();
deb2fec0 485
995612e2
VZ
486 for ( wxList::Node *node = list.GetFirst(); node; node = node->GetNext() )
487 {
488 handler=(wxImageHandler*)node->GetData();
489 if (handler->CanRead( stream ))
490 return handler->LoadFile( this, stream );
7b2471a0 491
995612e2 492 }
deb2fec0 493
58c837a4 494 wxLogWarning( _("No handler found for image type.") );
995612e2 495 return FALSE;
deb2fec0
SB
496 }
497
498 handler = FindHandler(type);
c7abc967 499
4698648f 500 if (handler == NULL)
fd0eed64 501 {
58c837a4 502 wxLogWarning( _("No image handler for type %d defined."), type );
c7abc967 503
fd0eed64
RR
504 return FALSE;
505 }
c7abc967 506
3d05544e 507 return handler->LoadFile( this, stream );
01111366
RR
508}
509
9e9ee68e
VS
510bool wxImage::LoadFile( wxInputStream& stream, const wxString& mimetype )
511{
512 UnRef();
513
514 m_refData = new wxImageRefData;
515
516 wxImageHandler *handler = FindHandlerMime(mimetype);
517
518 if (handler == NULL)
519 {
58c837a4 520 wxLogWarning( _("No image handler for type %s defined."), mimetype.GetData() );
9e9ee68e
VS
521
522 return FALSE;
523 }
524
525 return handler->LoadFile( this, stream );
526}
527
3d05544e 528bool wxImage::SaveFile( wxOutputStream& stream, int type )
01111366 529{
223d09f6 530 wxCHECK_MSG( Ok(), FALSE, wxT("invalid image") );
c7abc967 531
fd0eed64 532 wxImageHandler *handler = FindHandler(type);
c7abc967 533
4698648f 534 if (handler == NULL)
fd0eed64 535 {
58c837a4 536 wxLogWarning( _("No image handler for type %d defined."), type );
9e9ee68e
VS
537
538 return FALSE;
539 }
540
541 return handler->SaveFile( this, stream );
542}
543
544bool wxImage::SaveFile( wxOutputStream& stream, const wxString& mimetype )
545{
223d09f6 546 wxCHECK_MSG( Ok(), FALSE, wxT("invalid image") );
c7abc967 547
9e9ee68e 548 wxImageHandler *handler = FindHandlerMime(mimetype);
c7abc967 549
9e9ee68e
VS
550 if (handler == NULL)
551 {
58c837a4 552 wxLogWarning( _("No image handler for type %s defined."), mimetype.GetData() );
c7abc967 553
dbda9e86 554 return FALSE;
fd0eed64 555 }
c7abc967 556
3d05544e 557 return handler->SaveFile( this, stream );
01111366 558}
e02afc7a 559#endif // wxUSE_STREAMS
01111366
RR
560
561void wxImage::AddHandler( 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.Append( handler );
567}
568
569void wxImage::InsertHandler( wxImageHandler *handler )
570{
4698648f
VZ
571 // make sure that the memory will be freed at the program end
572 sm_handlers.DeleteContents(TRUE);
c7abc967 573
01111366
RR
574 sm_handlers.Insert( handler );
575}
576
577bool wxImage::RemoveHandler( const wxString& name )
578{
fd0eed64
RR
579 wxImageHandler *handler = FindHandler(name);
580 if (handler)
581 {
582 sm_handlers.DeleteObject(handler);
583 return TRUE;
584 }
585 else
586 return FALSE;
01111366
RR
587}
588
589wxImageHandler *wxImage::FindHandler( const wxString& name )
590{
fd0eed64
RR
591 wxNode *node = sm_handlers.First();
592 while (node)
593 {
594 wxImageHandler *handler = (wxImageHandler*)node->Data();
ce3ed50d 595 if (handler->GetName().Cmp(name) == 0) return handler;
c7abc967 596
fd0eed64
RR
597 node = node->Next();
598 }
599 return (wxImageHandler *)NULL;
01111366
RR
600}
601
602wxImageHandler *wxImage::FindHandler( const wxString& extension, long bitmapType )
603{
fd0eed64
RR
604 wxNode *node = sm_handlers.First();
605 while (node)
606 {
607 wxImageHandler *handler = (wxImageHandler*)node->Data();
ce3ed50d 608 if ( (handler->GetExtension().Cmp(extension) == 0) &&
fd0eed64 609 (bitmapType == -1 || handler->GetType() == bitmapType) )
dbda9e86 610 return handler;
fd0eed64
RR
611 node = node->Next();
612 }
613 return (wxImageHandler*)NULL;
01111366
RR
614}
615
616wxImageHandler *wxImage::FindHandler( long bitmapType )
617{
fd0eed64
RR
618 wxNode *node = sm_handlers.First();
619 while (node)
620 {
621 wxImageHandler *handler = (wxImageHandler *)node->Data();
622 if (handler->GetType() == bitmapType) return handler;
623 node = node->Next();
624 }
625 return NULL;
626}
627
9e9ee68e
VS
628wxImageHandler *wxImage::FindHandlerMime( const wxString& mimetype )
629{
630 wxNode *node = sm_handlers.First();
631 while (node)
632 {
633 wxImageHandler *handler = (wxImageHandler *)node->Data();
634 if (handler->GetMimeType().IsSameAs(mimetype, FALSE)) return handler;
635 node = node->Next();
636 }
637 return NULL;
638}
639
fd0eed64
RR
640void wxImage::InitStandardHandlers()
641{
deb2fec0 642 AddHandler( new wxBMPHandler );
01111366
RR
643}
644
645void wxImage::CleanUpHandlers()
646{
fd0eed64
RR
647 wxNode *node = sm_handlers.First();
648 while (node)
649 {
650 wxImageHandler *handler = (wxImageHandler *)node->Data();
651 wxNode *next = node->Next();
652 delete handler;
653 delete node;
654 node = next;
655 }
01111366
RR
656}
657
658//-----------------------------------------------------------------------------
659// wxImageHandler
660//-----------------------------------------------------------------------------
661
662#if !USE_SHARED_LIBRARIES
63d963a1 663IMPLEMENT_ABSTRACT_CLASS(wxImageHandler,wxObject)
01111366
RR
664#endif
665
e02afc7a 666#if wxUSE_STREAMS
700ec454 667bool wxImageHandler::LoadFile( wxImage *WXUNUSED(image), wxInputStream& WXUNUSED(stream), bool WXUNUSED(verbose), int WXUNUSED(index) )
01111366 668{
fd0eed64 669 return FALSE;
01111366
RR
670}
671
deb2fec0 672bool wxImageHandler::SaveFile( wxImage *WXUNUSED(image), wxOutputStream& WXUNUSED(stream), bool WXUNUSED(verbose) )
01111366 673{
fd0eed64 674 return FALSE;
01111366 675}
0828c087 676
700ec454
RR
677int wxImageHandler::GetImageCount( wxInputStream& WXUNUSED(stream) )
678{
679 return 1;
680}
681
0828c087
VS
682bool wxImageHandler::CanRead( const wxString& name )
683{
0828c087
VS
684 if (wxFileExists(name))
685 {
686 wxFileInputStream stream(name);
687 return CanRead(stream);
688 }
689
690 else {
58c837a4 691 wxLogError( _("Can't check image format of file '%s': file does not exist."), name.c_str() );
0828c087
VS
692
693 return FALSE;
694 }
68874acf 695// return FALSE;
0828c087
VS
696}
697
e02afc7a 698#endif // wxUSE_STREAMS
01111366 699
01111366 700//-----------------------------------------------------------------------------
ce4169a4 701// MSW conversion routines
01111366
RR
702//-----------------------------------------------------------------------------
703
e3554471
JS
704#ifdef __WXMSW__
705
706wxBitmap wxImage::ConvertToBitmap() const
707{
0655ad29
VZ
708 if ( !Ok() )
709 return wxNullBitmap;
710
dbda9e86 711 // sizeLimit is the MS upper limit for the DIB size
48c12cb1 712#ifdef WIN32
c7abc967 713 int sizeLimit = 1024*768*3;
48c12cb1
PA
714#else
715 int sizeLimit = 0x7fff ;
716#endif
c7abc967 717
dbda9e86 718 // width and height of the device-dependent bitmap
bba6f3bd
UA
719 int width = GetWidth();
720 int bmpHeight = GetHeight();
c7abc967 721
dbda9e86 722 // calc the number of bytes per scanline and padding
bba6f3bd
UA
723 int bytePerLine = width*3;
724 int sizeDWORD = sizeof( DWORD );
bae41ce1 725 int lineBoundary = bytePerLine % sizeDWORD;
bba6f3bd 726 int padding = 0;
bae41ce1 727 if( lineBoundary > 0 )
bba6f3bd 728 {
bae41ce1 729 padding = sizeDWORD - lineBoundary;
bba6f3bd
UA
730 bytePerLine += padding;
731 }
dbda9e86 732 // calc the number of DIBs and heights of DIBs
bba6f3bd
UA
733 int numDIB = 1;
734 int hRemain = 0;
735 int height = sizeLimit/bytePerLine;
736 if( height >= bmpHeight )
c7abc967 737 height = bmpHeight;
bba6f3bd
UA
738 else
739 {
bae41ce1
UA
740 numDIB = bmpHeight / height;
741 hRemain = bmpHeight % height;
dbda9e86 742 if( hRemain >0 ) numDIB++;
bba6f3bd 743 }
c7abc967 744
dbda9e86 745 // set bitmap parameters
bba6f3bd 746 wxBitmap bitmap;
223d09f6 747 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
bba6f3bd
UA
748 bitmap.SetWidth( width );
749 bitmap.SetHeight( bmpHeight );
750 bitmap.SetDepth( wxDisplayDepth() );
c7abc967 751
dbda9e86 752 // create a DIB header
bba6f3bd
UA
753 int headersize = sizeof(BITMAPINFOHEADER);
754 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
223d09f6 755 wxCHECK_MSG( lpDIBh, bitmap, wxT("could not allocate memory for DIB header") );
dbda9e86 756 // Fill in the DIB header
bba6f3bd
UA
757 lpDIBh->bmiHeader.biSize = headersize;
758 lpDIBh->bmiHeader.biWidth = (DWORD)width;
759 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
760 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
dbda9e86
JS
761 // the general formula for biSizeImage:
762 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
bba6f3bd
UA
763 lpDIBh->bmiHeader.biPlanes = 1;
764 lpDIBh->bmiHeader.biBitCount = 24;
765 lpDIBh->bmiHeader.biCompression = BI_RGB;
766 lpDIBh->bmiHeader.biClrUsed = 0;
dbda9e86 767 // These seem not really needed for our purpose here.
bba6f3bd
UA
768 lpDIBh->bmiHeader.biClrImportant = 0;
769 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
770 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
dbda9e86 771 // memory for DIB data
bba6f3bd
UA
772 unsigned char *lpBits;
773 lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
774 if( !lpBits )
775 {
223d09f6 776 wxFAIL_MSG( wxT("could not allocate memory for DIB") );
bba6f3bd
UA
777 free( lpDIBh );
778 return bitmap;
779 }
c7abc967 780
dbda9e86 781 // create and set the device-dependent bitmap
bba6f3bd
UA
782 HDC hdc = ::GetDC(NULL);
783 HDC memdc = ::CreateCompatibleDC( hdc );
784 HBITMAP hbitmap;
785 hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
c7abc967
VZ
786 ::SelectObject( memdc, hbitmap);
787
dbda9e86 788 // copy image data into DIB data and then into DDB (in a loop)
bba6f3bd
UA
789 unsigned char *data = GetData();
790 int i, j, n;
791 int origin = 0;
792 unsigned char *ptdata = data;
793 unsigned char *ptbits;
c7abc967 794
bba6f3bd
UA
795 for( n=0; n<numDIB; n++ )
796 {
dbda9e86
JS
797 if( numDIB > 1 && n == numDIB-1 && hRemain > 0 )
798 {
799 // redefine height and size of the (possibly) last smaller DIB
800 // memory is not reallocated
c7abc967 801 height = hRemain;
bba6f3bd
UA
802 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
803 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
dbda9e86 804 }
bba6f3bd 805 ptbits = lpBits;
c7abc967 806
bba6f3bd
UA
807 for( j=0; j<height; j++ )
808 {
809 for( i=0; i<width; i++ )
810 {
811 *(ptbits++) = *(ptdata+2);
812 *(ptbits++) = *(ptdata+1);
813 *(ptbits++) = *(ptdata );
814 ptdata += 3;
dbda9e86
JS
815 }
816 for( i=0; i< padding; i++ ) *(ptbits++) = 0;
bba6f3bd
UA
817 }
818 ::StretchDIBits( memdc, 0, origin, width, height,\
dbda9e86
JS
819 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
820 origin += height;
821 // if numDIB = 1, lines below can also be used
822 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
823 // The above line is equivalent to the following two lines.
824 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
825 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
826 // or the following lines
827 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
828 // HDC memdc = ::CreateCompatibleDC( hdc );
c7abc967 829 // ::SelectObject( memdc, hbitmap);
dbda9e86 830 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
995612e2 831 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
c7abc967
VZ
832 // ::SelectObject( memdc, 0 );
833 // ::DeleteDC( memdc );
e3554471 834 }
bba6f3bd 835 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
c7abc967 836
dbda9e86 837 // similarly, created an mono-bitmap for the possible mask
bba6f3bd
UA
838 if( HasMask() )
839 {
840 hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL );
c7abc967
VZ
841 ::SelectObject( memdc, hbitmap);
842 if( numDIB == 1 ) height = bmpHeight;
bba6f3bd
UA
843 else height = sizeLimit/bytePerLine;
844 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
845 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
846 origin = 0;
847 unsigned char r = GetMaskRed();
848 unsigned char g = GetMaskGreen();
849 unsigned char b = GetMaskBlue();
850 unsigned char zero = 0, one = 255;
851 ptdata = data;
852 for( n=0; n<numDIB; n++ )
853 {
854 if( numDIB > 1 && n == numDIB - 1 && hRemain > 0 )
855 {
dbda9e86
JS
856 // redefine height and size of the (possibly) last smaller DIB
857 // memory is not reallocated
c7abc967 858 height = hRemain;
bba6f3bd
UA
859 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
860 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
dbda9e86 861 }
bba6f3bd
UA
862 ptbits = lpBits;
863 for( int j=0; j<height; j++ )
864 {
dbda9e86 865 for(i=0; i<width; i++ )
bba6f3bd
UA
866 {
867 if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
868 {
869 *(ptbits++) = one;
870 *(ptbits++) = one;
871 *(ptbits++) = one;
872 }
873 else
874 {
875 *(ptbits++) = zero;
876 *(ptbits++) = zero;
877 *(ptbits++) = zero;
878 }
879 }
dbda9e86 880 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
bba6f3bd
UA
881 }
882 ::StretchDIBits( memdc, 0, origin, width, height,\
dbda9e86
JS
883 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
884 origin += height;
885 }
886 // create a wxMask object
bba6f3bd
UA
887 wxMask *mask = new wxMask();
888 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
889 bitmap.SetMask( mask );
dbda9e86
JS
890 // It will be deleted when the wxBitmap object is deleted (as of 01/1999)
891 /* The following can also be used but is slow to run
bba6f3bd
UA
892 wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
893 wxMask *mask = new wxMask( bitmap, colour );
894 bitmap.SetMask( mask );
dbda9e86 895 */
bba6f3bd 896 }
c7abc967
VZ
897
898 // free allocated resources
899 ::SelectObject( memdc, 0 );
900 ::DeleteDC( memdc );
901 ::ReleaseDC(NULL, hdc);
bba6f3bd
UA
902 free(lpDIBh);
903 free(lpBits);
c7abc967 904
6d167489 905#if WXWIN_COMPATIBILITY_2
dbda9e86 906 // check the wxBitmap object
6d167489
VZ
907 bitmap.GetBitmapData()->SetOk();
908#endif // WXWIN_COMPATIBILITY_2
c7abc967 909
bba6f3bd 910 return bitmap;
e3554471
JS
911}
912
e3554471
JS
913wxImage::wxImage( const wxBitmap &bitmap )
914{
dbda9e86 915 // check the bitmap
bba6f3bd
UA
916 if( !bitmap.Ok() )
917 {
223d09f6 918 wxFAIL_MSG( wxT("invalid bitmap") );
bba6f3bd
UA
919 return;
920 }
c7abc967 921
dbda9e86 922 // create an wxImage object
bba6f3bd
UA
923 int width = bitmap.GetWidth();
924 int height = bitmap.GetHeight();
c7abc967 925 Create( width, height );
bba6f3bd
UA
926 unsigned char *data = GetData();
927 if( !data )
928 {
223d09f6 929 wxFAIL_MSG( wxT("could not allocate data for image") );
bba6f3bd
UA
930 return;
931 }
c7abc967 932
dbda9e86 933 // calc the number of bytes per scanline and padding in the DIB
bba6f3bd
UA
934 int bytePerLine = width*3;
935 int sizeDWORD = sizeof( DWORD );
bae41ce1 936 int lineBoundary = bytePerLine % sizeDWORD;
bba6f3bd 937 int padding = 0;
bae41ce1 938 if( lineBoundary > 0 )
bba6f3bd 939 {
bae41ce1 940 padding = sizeDWORD - lineBoundary;
bba6f3bd
UA
941 bytePerLine += padding;
942 }
c7abc967 943
dbda9e86 944 // create a DIB header
bba6f3bd
UA
945 int headersize = sizeof(BITMAPINFOHEADER);
946 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
947 if( !lpDIBh )
948 {
223d09f6 949 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
bba6f3bd
UA
950 free( data );
951 return;
952 }
dbda9e86 953 // Fill in the DIB header
bba6f3bd
UA
954 lpDIBh->bmiHeader.biSize = headersize;
955 lpDIBh->bmiHeader.biWidth = width;
956 lpDIBh->bmiHeader.biHeight = -height;
957 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
958 lpDIBh->bmiHeader.biPlanes = 1;
959 lpDIBh->bmiHeader.biBitCount = 24;
960 lpDIBh->bmiHeader.biCompression = BI_RGB;
961 lpDIBh->bmiHeader.biClrUsed = 0;
dbda9e86 962 // These seem not really needed for our purpose here.
bba6f3bd
UA
963 lpDIBh->bmiHeader.biClrImportant = 0;
964 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
965 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
dbda9e86 966 // memory for DIB data
bba6f3bd
UA
967 unsigned char *lpBits;
968 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
969 if( !lpBits )
e3554471 970 {
223d09f6 971 wxFAIL_MSG( wxT("could not allocate data for DIB") );
bba6f3bd
UA
972 free( data );
973 free( lpDIBh );
974 return;
4698648f 975 }
c7abc967 976
dbda9e86 977 // copy data from the device-dependent bitmap to the DIB
bba6f3bd
UA
978 HDC hdc = ::GetDC(NULL);
979 HBITMAP hbitmap;
980 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
981 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
c7abc967 982
dbda9e86 983 // copy DIB data into the wxImage object
bba6f3bd
UA
984 int i, j;
985 unsigned char *ptdata = data;
986 unsigned char *ptbits = lpBits;
987 for( i=0; i<height; i++ )
988 {
989 for( j=0; j<width; j++ )
990 {
991 *(ptdata++) = *(ptbits+2);
992 *(ptdata++) = *(ptbits+1);
993 *(ptdata++) = *(ptbits );
994 ptbits += 3;
dbda9e86 995 }
bba6f3bd 996 ptbits += padding;
c7abc967
VZ
997 }
998
dbda9e86 999 // similarly, set data according to the possible mask bitmap
bba6f3bd
UA
1000 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
1001 {
1002 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
dbda9e86 1003 // memory DC created, color set, data copied, and memory DC deleted
bba6f3bd
UA
1004 HDC memdc = ::CreateCompatibleDC( hdc );
1005 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
1006 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
1007 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
c7abc967 1008 ::DeleteDC( memdc );
dbda9e86 1009 // background color set to RGB(16,16,16) in consistent with wxGTK
c7abc967 1010 unsigned char r=16, g=16, b=16;
bba6f3bd
UA
1011 ptdata = data;
1012 ptbits = lpBits;
1013 for( i=0; i<height; i++ )
1014 {
1015 for( j=0; j<width; j++ )
1016 {
1017 if( *ptbits != 0 )
dbda9e86
JS
1018 ptdata += 3;
1019 else
bba6f3bd
UA
1020 {
1021 *(ptdata++) = r;
1022 *(ptdata++) = g;
1023 *(ptdata++) = b;
dbda9e86 1024 }
bba6f3bd
UA
1025 ptbits += 3;
1026 }
1027 ptbits += padding;
c7abc967 1028 }
bba6f3bd
UA
1029 SetMaskColour( r, g, b );
1030 SetMask( TRUE );
c7abc967 1031 }
bba6f3bd
UA
1032 else
1033 {
1034 SetMask( FALSE );
c7abc967
VZ
1035 }
1036 // free allocated resources
1037 ::ReleaseDC(NULL, hdc);
bba6f3bd
UA
1038 free(lpDIBh);
1039 free(lpBits);
e3554471
JS
1040}
1041
1042#endif
1043
7c74e7fe
SC
1044#ifdef __WXMAC__
1045
1046#include <PictUtils.h>
1047
1048extern CTabHandle wxMacCreateColorTable( int numColors ) ;
1049extern void wxMacDestroyColorTable( CTabHandle colors ) ;
1050extern void wxMacSetColorTableEntry( CTabHandle newColors , int index , int red , int green , int blue ) ;
1051extern GWorldPtr wxMacCreateGWorld( int height , int width , int depth ) ;
1052extern void wxMacDestroyGWorld( GWorldPtr gw ) ;
1053
1054wxBitmap wxImage::ConvertToBitmap() const
1055{
1056 // width and height of the device-dependent bitmap
1057 int width = GetWidth();
1058 int height = GetHeight();
1059
1060 // Create picture
1061
1062 wxBitmap bitmap( width , height , wxDisplayDepth() ) ;
1063
1064 // Create mask
1065
1066 if (HasMask())
1067 {
1068 /*
1069 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1070
1071 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1072
1073 wxMask *mask = new wxMask();
1074 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1075
1076 bitmap.SetMask( mask );
1077 */
1078 }
1079
1080 // Render
1081
1082 int r_mask = GetMaskRed();
1083 int g_mask = GetMaskGreen();
1084 int b_mask = GetMaskBlue();
1085
1086 CGrafPtr origPort ;
1087 GDHandle origDevice ;
1088
1089 GetGWorld( &origPort , &origDevice ) ;
1090 SetGWorld( bitmap.GetHBITMAP() , NULL ) ;
1091
1092 register unsigned char* data = GetData();
1093
1094 int index = 0;
1095 for (int y = 0; y < height; y++)
1096 {
1097#if 0
1098 unsigned char lastr = 0 ;
1099 unsigned char lastg = 0 ;
1100 unsigned char lastb = 0 ;
1101 RGBColor lastcolor ;
1102
1103 MoveTo( 0 , y ) ;
1104 for (int x = 0; x < width; x++)
1105 {
1106 unsigned char r = data[index++];
1107 unsigned char g = data[index++];
1108 unsigned char b = data[index++];
1109
1110 if ( r != lastr || g != lastg || b != lastb )
1111 {
1112 lastcolor.red = ( lastr << 8 ) + lastr ;
1113 lastcolor.green = ( lastg << 8 ) + lastg ;
1114 lastcolor.blue = ( lastb << 8 ) + lastb ;
1115 RGBForeColor( &lastcolor ) ;
1116 LineTo( x , y ) ;
1117 lastr = r ;
1118 lastg = g ;
1119 lastb = b ;
1120 }
1121 } // for width
1122 lastcolor.red = ( lastr << 8 ) + lastr ;
1123 lastcolor.green = ( lastg << 8 ) + lastg ;
1124 lastcolor.blue = ( lastb << 8 ) + lastb ;
1125 RGBForeColor( &lastcolor ) ;
1126 LineTo( width - 1 , y ) ;
1127#else
1128 for (int x = 0; x < width; x++)
1129 {
1130 unsigned char r = data[index++];
1131 unsigned char g = data[index++];
1132 unsigned char b = data[index++];
1133 RGBColor color ;
1134 color.red = ( r << 8 ) + r ;
1135 color.green = ( g << 8 ) + g ;
1136 color.blue = ( b << 8 ) + b ;
1137 SetCPixel( x , y , &color ) ;
1138 }
1139#endif
1140 } // for height
1141
1142 SetGWorld( origPort , origDevice ) ;
1143
1144 return bitmap;
1145
1146}
1147
1148wxImage::wxImage( const wxBitmap &bitmap )
1149{
1150 // check the bitmap
1151 if( !bitmap.Ok() )
1152 {
1153 wxFAIL_MSG( "invalid bitmap" );
1154 return;
1155 }
1156
1157 // create an wxImage object
1158 int width = bitmap.GetWidth();
1159 int height = bitmap.GetHeight();
1160 Create( width, height );
1161 /*
1162 unsigned char *data = GetData();
1163 if( !data )
1164 {
1165 wxFAIL_MSG( "could not allocate data for image" );
1166 return;
1167 }
1168
1169 // calc the number of bytes per scanline and padding in the DIB
1170 int bytePerLine = width*3;
1171 int sizeDWORD = sizeof( DWORD );
1172 div_t lineBoundary = div( bytePerLine, sizeDWORD );
1173 int padding = 0;
1174 if( lineBoundary.rem > 0 )
1175 {
1176 padding = sizeDWORD - lineBoundary.rem;
1177 bytePerLine += padding;
1178 }
1179
1180 // create a DIB header
1181 int headersize = sizeof(BITMAPINFOHEADER);
1182 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
1183 if( !lpDIBh )
1184 {
1185 wxFAIL_MSG( "could not allocate data for DIB header" );
1186 free( data );
1187 return;
1188 }
1189 // Fill in the DIB header
1190 lpDIBh->bmiHeader.biSize = headersize;
1191 lpDIBh->bmiHeader.biWidth = width;
1192 lpDIBh->bmiHeader.biHeight = -height;
1193 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
1194 lpDIBh->bmiHeader.biPlanes = 1;
1195 lpDIBh->bmiHeader.biBitCount = 24;
1196 lpDIBh->bmiHeader.biCompression = BI_RGB;
1197 lpDIBh->bmiHeader.biClrUsed = 0;
1198 // These seem not really needed for our purpose here.
1199 lpDIBh->bmiHeader.biClrImportant = 0;
1200 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
1201 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
1202 // memory for DIB data
1203 unsigned char *lpBits;
1204 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
1205 if( !lpBits )
1206 {
1207 wxFAIL_MSG( "could not allocate data for DIB" );
1208 free( data );
1209 free( lpDIBh );
1210 return;
1211 }
1212
1213 // copy data from the device-dependent bitmap to the DIB
1214 HDC hdc = ::GetDC(NULL);
1215 HBITMAP hbitmap;
1216 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
1217 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1218
1219 // copy DIB data into the wxImage object
1220 int i, j;
1221 unsigned char *ptdata = data;
1222 unsigned char *ptbits = lpBits;
1223 for( i=0; i<height; i++ )
1224 {
1225 for( j=0; j<width; j++ )
1226 {
1227 *(ptdata++) = *(ptbits+2);
1228 *(ptdata++) = *(ptbits+1);
1229 *(ptdata++) = *(ptbits );
1230 ptbits += 3;
1231 }
1232 ptbits += padding;
1233 }
1234
1235 // similarly, set data according to the possible mask bitmap
1236 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
1237 {
1238 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
1239 // memory DC created, color set, data copied, and memory DC deleted
1240 HDC memdc = ::CreateCompatibleDC( hdc );
1241 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
1242 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
1243 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1244 ::DeleteDC( memdc );
1245 // background color set to RGB(16,16,16) in consistent with wxGTK
1246 unsigned char r=16, g=16, b=16;
1247 ptdata = data;
1248 ptbits = lpBits;
1249 for( i=0; i<height; i++ )
1250 {
1251 for( j=0; j<width; j++ )
1252 {
1253 if( *ptbits != 0 )
1254 ptdata += 3;
1255 else
1256 {
1257 *(ptdata++) = r;
1258 *(ptdata++) = g;
1259 *(ptdata++) = b;
1260 }
1261 ptbits += 3;
1262 }
1263 ptbits += padding;
1264 }
1265 SetMaskColour( r, g, b );
1266 SetMask( TRUE );
1267 }
1268 else
1269 {
1270 SetMask( FALSE );
1271 }
1272 // free allocated resources
1273 ::ReleaseDC(NULL, hdc);
1274 free(lpDIBh);
1275 free(lpBits);
1276 */
1277}
1278
1279#endif
1280
ce4169a4
RR
1281//-----------------------------------------------------------------------------
1282// GTK conversion routines
1283//-----------------------------------------------------------------------------
1284
99c67c77
RR
1285#ifdef __WXGTK__
1286
20e05ffb
RR
1287#include <gtk/gtk.h>
1288#include <gdk/gdk.h>
1289#include <gdk/gdkx.h>
83624f79 1290
ba0730de 1291#if (GTK_MINOR_VERSION > 0)
20e05ffb 1292#include <gdk/gdkrgb.h>
ba0730de
RR
1293#endif
1294
99c67c77
RR
1295wxBitmap wxImage::ConvertToBitmap() const
1296{
1297 wxBitmap bitmap;
c7abc967 1298
223d09f6 1299 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
c7abc967 1300
99c67c77
RR
1301 int width = GetWidth();
1302 int height = GetHeight();
c7abc967 1303
99c67c77
RR
1304 bitmap.SetHeight( height );
1305 bitmap.SetWidth( width );
c7abc967 1306
ba0730de
RR
1307 bitmap.SetPixmap( gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, -1 ) );
1308
1309 // Retrieve depth
c7abc967 1310
ba0730de 1311 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
b134516c 1312 if (visual == NULL) visual = gdk_visual_get_system();
ba0730de 1313 int bpp = visual->depth;
c7abc967 1314
ba0730de 1315 bitmap.SetDepth( bpp );
c7abc967 1316
ba0730de
RR
1317 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
1318 if (bpp < 8) bpp = 8;
c7abc967 1319
ba0730de
RR
1320#if (GTK_MINOR_VERSION > 0)
1321
1322 if (!HasMask() && (bpp > 8))
1323 {
1324 static bool s_hasInitialized = FALSE;
c7abc967 1325
995612e2
VZ
1326 if (!s_hasInitialized)
1327 {
1328 gdk_rgb_init();
1329 s_hasInitialized = TRUE;
1330 }
c7abc967 1331
ba0730de 1332 GdkGC *gc = gdk_gc_new( bitmap.GetPixmap() );
c7abc967 1333
995612e2
VZ
1334 gdk_draw_rgb_image( bitmap.GetPixmap(),
1335 gc,
1336 0, 0,
1337 width, height,
1338 GDK_RGB_DITHER_NONE,
1339 GetData(),
1340 width*3 );
c7abc967 1341
ba0730de 1342 gdk_gc_unref( gc );
c7abc967 1343
995612e2 1344 return bitmap;
ba0730de 1345 }
c7abc967 1346
ba0730de 1347#endif
c7abc967 1348
ba0730de 1349 // Create picture image
c7abc967 1350
99c67c77 1351 GdkImage *data_image =
b134516c 1352 gdk_image_new( GDK_IMAGE_FASTEST, gdk_visual_get_system(), width, height );
c7abc967 1353
ba0730de 1354 // Create mask image
c7abc967 1355
99c67c77 1356 GdkImage *mask_image = (GdkImage*) NULL;
c7abc967 1357
99c67c77
RR
1358 if (HasMask())
1359 {
1360 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
c7abc967 1361
b134516c 1362 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
c7abc967 1363
4698648f
VZ
1364 wxMask *mask = new wxMask();
1365 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
c7abc967 1366
4698648f 1367 bitmap.SetMask( mask );
99c67c77 1368 }
c7abc967 1369
99c67c77 1370 // Render
c7abc967 1371
99c67c77
RR
1372 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1373 byte_order b_o = RGB;
c7abc967 1374
99c67c77
RR
1375 if (bpp >= 24)
1376 {
b134516c 1377 GdkVisual *visual = gdk_visual_get_system();
99c67c77
RR
1378 if ((visual->red_mask > visual->green_mask) && (visual->green_mask > visual->blue_mask)) b_o = RGB;
1379 else if ((visual->red_mask > visual->blue_mask) && (visual->blue_mask > visual->green_mask)) b_o = RGB;
1380 else if ((visual->blue_mask > visual->red_mask) && (visual->red_mask > visual->green_mask)) b_o = BRG;
1381 else if ((visual->blue_mask > visual->green_mask) && (visual->green_mask > visual->red_mask)) b_o = BGR;
1382 else if ((visual->green_mask > visual->red_mask) && (visual->red_mask > visual->blue_mask)) b_o = GRB;
1383 else if ((visual->green_mask > visual->blue_mask) && (visual->blue_mask > visual->red_mask)) b_o = GBR;
1384 }
c7abc967 1385
99c67c77
RR
1386 int r_mask = GetMaskRed();
1387 int g_mask = GetMaskGreen();
1388 int b_mask = GetMaskBlue();
c7abc967 1389
99c67c77 1390 unsigned char* data = GetData();
c7abc967 1391
99c67c77
RR
1392 int index = 0;
1393 for (int y = 0; y < height; y++)
1394 {
1395 for (int x = 0; x < width; x++)
1396 {
1397 int r = data[index];
4698648f 1398 index++;
99c67c77 1399 int g = data[index];
4698648f 1400 index++;
99c67c77 1401 int b = data[index];
4698648f 1402 index++;
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 if (HasMask())
1413 {
1414 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1415 gdk_image_put_pixel( mask_image, x, y, 1 );
1416 else
1417 gdk_image_put_pixel( mask_image, x, y, 0 );
1418 }
c7abc967 1419
4698648f
VZ
1420 switch (bpp)
1421 {
dbda9e86 1422 case 8:
4698648f 1423 {
f6fcbb63 1424 int pixel = -1;
4698648f
VZ
1425 if (wxTheApp->m_colorCube)
1426 {
38274997 1427 pixel = wxTheApp->m_colorCube[ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
4698648f 1428 }
f6fcbb63 1429 else
4698648f
VZ
1430 {
1431 GdkColormap *cmap = gtk_widget_get_default_colormap();
f6fcbb63
RR
1432 GdkColor *colors = cmap->colors;
1433 int max = 3 * (65536);
c7abc967 1434
f6fcbb63
RR
1435 for (int i = 0; i < cmap->size; i++)
1436 {
1437 int rdiff = (r << 8) - colors[i].red;
1438 int gdiff = (g << 8) - colors[i].green;
1439 int bdiff = (b << 8) - colors[i].blue;
1440 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1441 if (sum < max) { pixel = i; max = sum; }
4698648f 1442 }
99c67c77 1443 }
c7abc967 1444
4698648f 1445 gdk_image_put_pixel( data_image, x, y, pixel );
c7abc967 1446
4698648f
VZ
1447 break;
1448 }
dbda9e86 1449 case 15:
4698648f
VZ
1450 {
1451 guint32 pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1452 gdk_image_put_pixel( data_image, x, y, pixel );
1453 break;
1454 }
dbda9e86 1455 case 16:
4698648f
VZ
1456 {
1457 guint32 pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1458 gdk_image_put_pixel( data_image, x, y, pixel );
1459 break;
1460 }
dbda9e86
JS
1461 case 32:
1462 case 24:
4698648f
VZ
1463 {
1464 guint32 pixel = 0;
1465 switch (b_o)
1466 {
dbda9e86
JS
1467 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1468 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1469 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1470 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1471 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1472 case GBR: pixel = (g << 16) | (b << 8) | r; break;
4698648f
VZ
1473 }
1474 gdk_image_put_pixel( data_image, x, y, pixel );
1475 }
dbda9e86 1476 default: break;
4698648f 1477 }
99c67c77
RR
1478 } // for
1479 } // for
c7abc967 1480
99c67c77 1481 // Blit picture
c7abc967 1482
99c67c77 1483 GdkGC *data_gc = gdk_gc_new( bitmap.GetPixmap() );
c7abc967 1484
99c67c77 1485 gdk_draw_image( bitmap.GetPixmap(), data_gc, data_image, 0, 0, 0, 0, width, height );
c7abc967 1486
99c67c77
RR
1487 gdk_image_destroy( data_image );
1488 gdk_gc_unref( data_gc );
c7abc967 1489
99c67c77 1490 // Blit mask
c7abc967 1491
99c67c77
RR
1492 if (HasMask())
1493 {
1494 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
c7abc967 1495
99c67c77 1496 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
c7abc967 1497
99c67c77
RR
1498 gdk_image_destroy( mask_image );
1499 gdk_gc_unref( mask_gc );
1500 }
c7abc967 1501
99c67c77
RR
1502 return bitmap;
1503}
1504
1505wxImage::wxImage( const wxBitmap &bitmap )
1506{
223d09f6 1507 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
c7abc967 1508
c6d73ef6
RR
1509 GdkImage *gdk_image = (GdkImage*) NULL;
1510 if (bitmap.GetPixmap())
1511 {
1512 gdk_image = gdk_image_get( bitmap.GetPixmap(),
1513 0, 0,
1514 bitmap.GetWidth(), bitmap.GetHeight() );
1515 } else
1516 if (bitmap.GetBitmap())
1517 {
1518 gdk_image = gdk_image_get( bitmap.GetBitmap(),
1519 0, 0,
1520 bitmap.GetWidth(), bitmap.GetHeight() );
1521 } else
1522 {
1523 wxFAIL_MSG( wxT("Ill-formed bitmap") );
1524 }
c7abc967 1525
223d09f6 1526 wxCHECK_RET( gdk_image, wxT("couldn't create image") );
c7abc967 1527
99c67c77
RR
1528 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1529 char unsigned *data = GetData();
c7abc967 1530
99c67c77
RR
1531 if (!data)
1532 {
1533 gdk_image_destroy( gdk_image );
223d09f6 1534 wxFAIL_MSG( wxT("couldn't create image") );
4698648f 1535 return;
99c67c77 1536 }
c7abc967 1537
99c67c77
RR
1538 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1539 if (bitmap.GetMask())
1540 {
1541 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
dbda9e86
JS
1542 0, 0,
1543 bitmap.GetWidth(), bitmap.GetHeight() );
c7abc967 1544
4698648f 1545 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
99c67c77 1546 }
c7abc967 1547
c6d73ef6
RR
1548 GdkVisual *visual = (GdkVisual*) NULL;
1549 if (bitmap.GetPixmap())
1550 visual = gdk_window_get_visual( bitmap.GetPixmap() );
1551 else
1552 visual = gdk_window_get_visual( bitmap.GetBitmap() );
1553
99c67c77
RR
1554 if (visual == NULL) visual = gdk_window_get_visual( (GdkWindow*) &gdk_root_parent );
1555 int bpp = visual->depth;
1556 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
c7abc967 1557
99c67c77 1558 GdkColormap *cmap = gtk_widget_get_default_colormap();
c7abc967 1559
99c67c77
RR
1560 long pos = 0;
1561 for (int j = 0; j < bitmap.GetHeight(); j++)
1562 {
1563 for (int i = 0; i < bitmap.GetWidth(); i++)
1564 {
4cb122de 1565 wxInt32 pixel = gdk_image_get_pixel( gdk_image, i, j );
99c67c77
RR
1566 if (bpp <= 8)
1567 {
1568 data[pos] = cmap->colors[pixel].red >> 8;
1569 data[pos+1] = cmap->colors[pixel].green >> 8;
1570 data[pos+2] = cmap->colors[pixel].blue >> 8;
1571 } else if (bpp == 15)
1572 {
848bc5ba
RR
1573#if (wxBYTE_ORDER == wxBIG_ENDIAN)
1574 // ?
1575#endif
99c67c77
RR
1576 data[pos] = (pixel >> 7) & 0xf8;
1577 data[pos+1] = (pixel >> 2) & 0xf8;
1578 data[pos+2] = (pixel << 3) & 0xf8;
1579 } else if (bpp == 16)
1580 {
848bc5ba
RR
1581#if (wxBYTE_ORDER == wxBIG_ENDIAN)
1582 // ?
1583#endif
99c67c77
RR
1584 data[pos] = (pixel >> 8) & 0xf8;
1585 data[pos+1] = (pixel >> 3) & 0xfc;
1586 data[pos+2] = (pixel << 3) & 0xf8;
1587 } else
1588 {
848bc5ba
RR
1589#if (wxBYTE_ORDER == wxBIG_ENDIAN)
1590 data[pos] = (pixel) & 0xff; // Red
1591 data[pos+1] = (pixel >> 8) & 0xff; // Green
1592 data[pos+2] = (pixel >> 16) & 0xff; // Blue
1593#else
99c67c77
RR
1594 data[pos] = (pixel >> 16) & 0xff;
1595 data[pos+1] = (pixel >> 8) & 0xff;
1596 data[pos+2] = pixel & 0xff;
848bc5ba 1597#endif
99c67c77 1598 }
c7abc967 1599
4698648f
VZ
1600 if (gdk_image_mask)
1601 {
1602 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1603 if (mask_pixel == 0)
1604 {
99c67c77
RR
1605 data[pos] = 16;
1606 data[pos+1] = 16;
1607 data[pos+2] = 16;
dbda9e86 1608 }
4698648f 1609 }
c7abc967 1610
99c67c77
RR
1611 pos += 3;
1612 }
1613 }
c7abc967 1614
99c67c77
RR
1615 gdk_image_destroy( gdk_image );
1616 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1617}
1618
1619#endif
ee4c6942 1620
ce4169a4
RR
1621//-----------------------------------------------------------------------------
1622// Motif conversion routines
1623//-----------------------------------------------------------------------------
1624
ee4c6942 1625#ifdef __WXMOTIF__
338dd992
JJ
1626#ifdef __VMS__
1627#pragma message disable nosimpint
1628#endif
b75867a6 1629#include <Xm/Xm.h>
338dd992
JJ
1630#ifdef __VMS__
1631#pragma message enable nosimpint
1632#endif
b75867a6 1633#include "wx/utils.h"
38274997 1634#include <math.h>
b75867a6 1635
ee4c6942
JS
1636wxBitmap wxImage::ConvertToBitmap() const
1637{
b75867a6 1638 wxBitmap bitmap;
c7abc967 1639
223d09f6 1640 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
a91b47e8 1641
b75867a6
RR
1642 int width = GetWidth();
1643 int height = GetHeight();
c7abc967 1644
b75867a6
RR
1645 bitmap.SetHeight( height );
1646 bitmap.SetWidth( width );
c7abc967 1647
b75867a6
RR
1648 Display *dpy = (Display*) wxGetDisplay();
1649 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1650 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
c7abc967 1651
b75867a6 1652 // Create image
c7abc967 1653
b75867a6 1654 XImage *data_image = XCreateImage( dpy, vis, bpp, ZPixmap, 0, 0, width, height, 32, 0 );
a91b47e8 1655 data_image->data = (char*) malloc( data_image->bytes_per_line * data_image->height );
c7abc967 1656
b75867a6 1657 bitmap.Create( width, height, bpp );
a91b47e8 1658
dbda9e86 1659 /*
b75867a6 1660 // Create mask
c7abc967 1661
dbda9e86 1662 GdkImage *mask_image = (GdkImage*) NULL;
c7abc967 1663
dbda9e86
JS
1664 if (HasMask())
1665 {
b75867a6 1666 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
c7abc967 1667
dbda9e86 1668 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
c7abc967 1669
dbda9e86
JS
1670 wxMask *mask = new wxMask();
1671 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
c7abc967 1672
dbda9e86
JS
1673 bitmap.SetMask( mask );
1674 }
1675 */
c7abc967 1676
b75867a6 1677 // Retrieve depth info
c7abc967 1678
b75867a6
RR
1679 XVisualInfo vinfo_template;
1680 XVisualInfo *vi;
c7abc967 1681
b75867a6
RR
1682 vinfo_template.visual = vis;
1683 vinfo_template.visualid = XVisualIDFromVisual( vis );
1684 vinfo_template.depth = bpp;
1685 int nitem = 0;
c7abc967 1686
b75867a6 1687 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
c7abc967 1688
223d09f6 1689 wxCHECK_MSG( vi, wxNullBitmap, wxT("no visual") );
c7abc967 1690
38274997 1691 XFree( vi );
a91b47e8 1692
b75867a6
RR
1693 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1694 if (bpp < 8) bpp = 8;
c7abc967 1695
b75867a6 1696 // Render
c7abc967 1697
b75867a6
RR
1698 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1699 byte_order b_o = RGB;
c7abc967 1700
b75867a6
RR
1701 if (bpp >= 24)
1702 {
1703 if ((vi->red_mask > vi->green_mask) && (vi->green_mask > vi->blue_mask)) b_o = RGB;
1704 else if ((vi->red_mask > vi->blue_mask) && (vi->blue_mask > vi->green_mask)) b_o = RGB;
1705 else if ((vi->blue_mask > vi->red_mask) && (vi->red_mask > vi->green_mask)) b_o = BRG;
1706 else if ((vi->blue_mask > vi->green_mask) && (vi->green_mask > vi->red_mask)) b_o = BGR;
1707 else if ((vi->green_mask > vi->red_mask) && (vi->red_mask > vi->blue_mask)) b_o = GRB;
1708 else if ((vi->green_mask > vi->blue_mask) && (vi->blue_mask > vi->red_mask)) b_o = GBR;
1709 }
c7abc967 1710
dbda9e86 1711 /*
b75867a6
RR
1712 int r_mask = GetMaskRed();
1713 int g_mask = GetMaskGreen();
1714 int b_mask = GetMaskBlue();
dbda9e86 1715 */
c7abc967 1716
38274997
RR
1717 XColor colors[256];
1718 if (bpp == 8)
1719 {
dbda9e86 1720 Colormap cmap = (Colormap) wxTheApp->GetMainColormap( dpy );
c7abc967 1721
38274997 1722 for (int i = 0; i < 256; i++) colors[i].pixel = i;
dbda9e86 1723 XQueryColors( dpy, cmap, colors, 256 );
38274997 1724 }
c7abc967 1725
b75867a6 1726 unsigned char* data = GetData();
c7abc967 1727
b75867a6
RR
1728 int index = 0;
1729 for (int y = 0; y < height; y++)
1730 {
1731 for (int x = 0; x < width; x++)
1732 {
1733 int r = data[index];
dbda9e86 1734 index++;
b75867a6 1735 int g = data[index];
dbda9e86 1736 index++;
b75867a6 1737 int b = data[index];
dbda9e86 1738 index++;
c7abc967 1739
dbda9e86
JS
1740 /*
1741 if (HasMask())
1742 {
1743 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1744 gdk_image_put_pixel( mask_image, x, y, 1 );
1745 else
1746 gdk_image_put_pixel( mask_image, x, y, 0 );
1747 }
1748 */
c7abc967 1749
dbda9e86
JS
1750 switch (bpp)
1751 {
1752 case 8:
1753 {
b75867a6 1754 int pixel = -1;
dbda9e86
JS
1755 /*
1756 if (wxTheApp->m_colorCube)
1757 {
1758 pixel = wxTheApp->m_colorCube
c7abc967
VZ
1759 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1760 }
b75867a6 1761 else
dbda9e86
JS
1762 {
1763 */
1764 int max = 3 * (65536);
1765 for (int i = 0; i < 256; i++)
1766 {
1767 int rdiff = (r << 8) - colors[i].red;
1768 int gdiff = (g << 8) - colors[i].green;
1769 int bdiff = (b << 8) - colors[i].blue;
1770 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1771 if (sum < max) { pixel = i; max = sum; }
1772 }
1773 /*
1774 }
1775 */
1776 XPutPixel( data_image, x, y, pixel );
1777 break;
1778 }
1779 case 15:
1780 {
1781 int pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1782 XPutPixel( data_image, x, y, pixel );
1783 break;
1784 }
1785 case 16:
1786 {
1787 int pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1788 XPutPixel( data_image, x, y, pixel );
1789 break;
1790 }
1791 case 32:
1792 case 24:
1793 {
1794 int pixel = 0;
1795 switch (b_o)
1796 {
1797 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1798 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1799 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1800 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1801 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1802 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1803 }
1804 XPutPixel( data_image, x, y, pixel );
1805 }
1806 default: break;
1807 }
b75867a6
RR
1808 } // for
1809 } // for
c7abc967 1810
b75867a6 1811 // Blit picture
c7abc967 1812
b75867a6
RR
1813 XGCValues gcvalues;
1814 gcvalues.foreground = BlackPixel( dpy, DefaultScreen( dpy ) );
1815 GC gc = XCreateGC( dpy, RootWindow ( dpy, DefaultScreen(dpy) ), GCForeground, &gcvalues );
1816 XPutImage( dpy, (Drawable)bitmap.GetPixmap(), gc, data_image, 0, 0, 0, 0, width, height );
c7abc967 1817
b75867a6
RR
1818 XDestroyImage( data_image );
1819 XFreeGC( dpy, gc );
c7abc967 1820
dbda9e86 1821 /*
b75867a6 1822 // Blit mask
c7abc967 1823
dbda9e86
JS
1824 if (HasMask())
1825 {
1826 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
c7abc967 1827
b75867a6 1828 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
c7abc967 1829
dbda9e86
JS
1830 gdk_image_destroy( mask_image );
1831 gdk_gc_unref( mask_gc );
1832 }
1833 */
c7abc967 1834
b75867a6 1835 return bitmap;
ee4c6942
JS
1836}
1837
1838wxImage::wxImage( const wxBitmap &bitmap )
1839{
223d09f6 1840 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
c7abc967 1841
38274997
RR
1842 Display *dpy = (Display*) wxGetDisplay();
1843 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1844 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
c7abc967 1845
38274997 1846 XImage *ximage = XGetImage( dpy,
dbda9e86
JS
1847 (Drawable)bitmap.GetPixmap(),
1848 0, 0,
1849 bitmap.GetWidth(), bitmap.GetHeight(),
1850 AllPlanes, ZPixmap );
c7abc967 1851
223d09f6 1852 wxCHECK_RET( ximage, wxT("couldn't create image") );
c7abc967 1853
38274997
RR
1854 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1855 char unsigned *data = GetData();
c7abc967 1856
38274997
RR
1857 if (!data)
1858 {
1859 XDestroyImage( ximage );
223d09f6 1860 wxFAIL_MSG( wxT("couldn't create image") );
38274997
RR
1861 return;
1862 }
c7abc967 1863
dbda9e86 1864 /*
38274997
RR
1865 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1866 if (bitmap.GetMask())
1867 {
dbda9e86
JS
1868 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1869 0, 0,
1870 bitmap.GetWidth(), bitmap.GetHeight() );
c7abc967 1871
dbda9e86
JS
1872 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1873 }
1874 */
c7abc967 1875
38274997 1876 // Retrieve depth info
c7abc967 1877
38274997
RR
1878 XVisualInfo vinfo_template;
1879 XVisualInfo *vi;
c7abc967 1880
38274997
RR
1881 vinfo_template.visual = vis;
1882 vinfo_template.visualid = XVisualIDFromVisual( vis );
1883 vinfo_template.depth = bpp;
1884 int nitem = 0;
c7abc967 1885
38274997 1886 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
c7abc967 1887
223d09f6 1888 wxCHECK_RET( vi, wxT("no visual") );
c7abc967 1889
38274997 1890 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
c7abc967 1891
38274997 1892 XFree( vi );
c7abc967 1893
38274997
RR
1894 XColor colors[256];
1895 if (bpp == 8)
1896 {
dbda9e86 1897 Colormap cmap = (Colormap)wxTheApp->GetMainColormap( dpy );
c7abc967 1898
38274997 1899 for (int i = 0; i < 256; i++) colors[i].pixel = i;
dbda9e86 1900 XQueryColors( dpy, cmap, colors, 256 );
38274997 1901 }
c7abc967 1902
38274997
RR
1903 long pos = 0;
1904 for (int j = 0; j < bitmap.GetHeight(); j++)
1905 {
1906 for (int i = 0; i < bitmap.GetWidth(); i++)
1907 {
dbda9e86 1908 int pixel = XGetPixel( ximage, i, j );
38274997
RR
1909 if (bpp <= 8)
1910 {
1911 data[pos] = colors[pixel].red >> 8;
1912 data[pos+1] = colors[pixel].green >> 8;
1913 data[pos+2] = colors[pixel].blue >> 8;
1914 } else if (bpp == 15)
1915 {
1916 data[pos] = (pixel >> 7) & 0xf8;
1917 data[pos+1] = (pixel >> 2) & 0xf8;
1918 data[pos+2] = (pixel << 3) & 0xf8;
1919 } else if (bpp == 16)
1920 {
1921 data[pos] = (pixel >> 8) & 0xf8;
1922 data[pos+1] = (pixel >> 3) & 0xfc;
1923 data[pos+2] = (pixel << 3) & 0xf8;
1924 } else
1925 {
1926 data[pos] = (pixel >> 16) & 0xff;
1927 data[pos+1] = (pixel >> 8) & 0xff;
1928 data[pos+2] = pixel & 0xff;
1929 }
c7abc967 1930
dbda9e86 1931 /*
38274997
RR
1932 if (gdk_image_mask)
1933 {
dbda9e86
JS
1934 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1935 if (mask_pixel == 0)
1936 {
1937 data[pos] = 16;
1938 data[pos+1] = 16;
1939 data[pos+2] = 16;
38274997 1940 }
dbda9e86
JS
1941 }
1942 */
c7abc967 1943
38274997
RR
1944 pos += 3;
1945 }
1946 }
c7abc967 1947
38274997 1948 XDestroyImage( ximage );
dbda9e86 1949 /*
38274997 1950 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
dbda9e86 1951 */
ee4c6942
JS
1952}
1953#endif
a91b47e8 1954
004fd0c8
DW
1955#ifdef __WXPM__
1956// OS/2 Presentation manager conversion routings
1957
1958wxBitmap wxImage::ConvertToBitmap() const
1959{
1960 if ( !Ok() )
1961 return wxNullBitmap;
1962 wxBitmap bitmap; // remove
1963// TODO:
1964/*
1965 int sizeLimit = 1024*768*3;
1966
1967 // width and height of the device-dependent bitmap
1968 int width = GetWidth();
1969 int bmpHeight = GetHeight();
1970
1971 // calc the number of bytes per scanline and padding
1972 int bytePerLine = width*3;
1973 int sizeDWORD = sizeof( DWORD );
1974 int lineBoundary = bytePerLine % sizeDWORD;
1975 int padding = 0;
1976 if( lineBoundary > 0 )
1977 {
1978 padding = sizeDWORD - lineBoundary;
1979 bytePerLine += padding;
1980 }
1981 // calc the number of DIBs and heights of DIBs
1982 int numDIB = 1;
1983 int hRemain = 0;
1984 int height = sizeLimit/bytePerLine;
1985 if( height >= bmpHeight )
1986 height = bmpHeight;
1987 else
1988 {
1989 numDIB = bmpHeight / height;
1990 hRemain = bmpHeight % height;
1991 if( hRemain >0 ) numDIB++;
1992 }
1993
1994 // set bitmap parameters
1995 wxBitmap bitmap;
1996 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
1997 bitmap.SetWidth( width );
1998 bitmap.SetHeight( bmpHeight );
1999 bitmap.SetDepth( wxDisplayDepth() );
2000
2001 // create a DIB header
2002 int headersize = sizeof(BITMAPINFOHEADER);
2003 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
2004 wxCHECK_MSG( lpDIBh, bitmap, wxT("could not allocate memory for DIB header") );
2005 // Fill in the DIB header
2006 lpDIBh->bmiHeader.biSize = headersize;
2007 lpDIBh->bmiHeader.biWidth = (DWORD)width;
2008 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2009 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2010 // the general formula for biSizeImage:
2011 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
2012 lpDIBh->bmiHeader.biPlanes = 1;
2013 lpDIBh->bmiHeader.biBitCount = 24;
2014 lpDIBh->bmiHeader.biCompression = BI_RGB;
2015 lpDIBh->bmiHeader.biClrUsed = 0;
2016 // These seem not really needed for our purpose here.
2017 lpDIBh->bmiHeader.biClrImportant = 0;
2018 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2019 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2020 // memory for DIB data
2021 unsigned char *lpBits;
2022 lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
2023 if( !lpBits )
2024 {
2025 wxFAIL_MSG( wxT("could not allocate memory for DIB") );
2026 free( lpDIBh );
2027 return bitmap;
2028 }
2029
2030 // create and set the device-dependent bitmap
2031 HDC hdc = ::GetDC(NULL);
2032 HDC memdc = ::CreateCompatibleDC( hdc );
2033 HBITMAP hbitmap;
2034 hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
2035 ::SelectObject( memdc, hbitmap);
2036
2037 // copy image data into DIB data and then into DDB (in a loop)
2038 unsigned char *data = GetData();
2039 int i, j, n;
2040 int origin = 0;
2041 unsigned char *ptdata = data;
2042 unsigned char *ptbits;
2043
2044 for( n=0; n<numDIB; n++ )
2045 {
2046 if( numDIB > 1 && n == numDIB-1 && hRemain > 0 )
2047 {
2048 // redefine height and size of the (possibly) last smaller DIB
2049 // memory is not reallocated
2050 height = hRemain;
2051 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2052 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2053 }
2054 ptbits = lpBits;
2055
2056 for( j=0; j<height; j++ )
2057 {
2058 for( i=0; i<width; i++ )
2059 {
2060 *(ptbits++) = *(ptdata+2);
2061 *(ptbits++) = *(ptdata+1);
2062 *(ptbits++) = *(ptdata );
2063 ptdata += 3;
2064 }
2065 for( i=0; i< padding; i++ ) *(ptbits++) = 0;
2066 }
2067 ::StretchDIBits( memdc, 0, origin, width, height,\
2068 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2069 origin += height;
2070 // if numDIB = 1, lines below can also be used
2071 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
2072 // The above line is equivalent to the following two lines.
2073 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2074 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
2075 // or the following lines
2076 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2077 // HDC memdc = ::CreateCompatibleDC( hdc );
2078 // ::SelectObject( memdc, hbitmap);
2079 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
2080 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
2081 // ::SelectObject( memdc, 0 );
2082 // ::DeleteDC( memdc );
2083 }
2084 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
2085
2086 // similarly, created an mono-bitmap for the possible mask
2087 if( HasMask() )
2088 {
2089 hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL );
2090 ::SelectObject( memdc, hbitmap);
2091 if( numDIB == 1 ) height = bmpHeight;
2092 else height = sizeLimit/bytePerLine;
2093 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2094 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2095 origin = 0;
2096 unsigned char r = GetMaskRed();
2097 unsigned char g = GetMaskGreen();
2098 unsigned char b = GetMaskBlue();
2099 unsigned char zero = 0, one = 255;
2100 ptdata = data;
2101 for( n=0; n<numDIB; n++ )
2102 {
2103 if( numDIB > 1 && n == numDIB - 1 && hRemain > 0 )
2104 {
2105 // redefine height and size of the (possibly) last smaller DIB
2106 // memory is not reallocated
2107 height = hRemain;
2108 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2109 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2110 }
2111 ptbits = lpBits;
2112 for( int j=0; j<height; j++ )
2113 {
2114 for(i=0; i<width; i++ )
2115 {
2116 if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
2117 {
2118 *(ptbits++) = one;
2119 *(ptbits++) = one;
2120 *(ptbits++) = one;
2121 }
2122 else
2123 {
2124 *(ptbits++) = zero;
2125 *(ptbits++) = zero;
2126 *(ptbits++) = zero;
2127 }
2128 }
2129 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
2130 }
2131 ::StretchDIBits( memdc, 0, origin, width, height,\
2132 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2133 origin += height;
2134 }
2135 // create a wxMask object
2136 wxMask *mask = new wxMask();
2137 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
2138 bitmap.SetMask( mask );
2139 }
2140
2141 // free allocated resources
2142 ::SelectObject( memdc, 0 );
2143 ::DeleteDC( memdc );
2144 ::ReleaseDC(NULL, hdc);
2145 free(lpDIBh);
2146 free(lpBits);
2147
2148 // check the wxBitmap object
2149 if( bitmap.GetHBITMAP() )
2150 bitmap.SetOk( TRUE );
2151 else
2152 bitmap.SetOk( FALSE );
2153*/
2154 return bitmap;
2155}
2156
2157wxImage::wxImage( const wxBitmap &bitmap )
2158{
2159 // check the bitmap
2160 if( !bitmap.Ok() )
2161 {
2162 wxFAIL_MSG( wxT("invalid bitmap") );
2163 return;
2164 }
2165
2166 // create an wxImage object
2167 int width = bitmap.GetWidth();
2168 int height = bitmap.GetHeight();
2169 Create( width, height );
2170 unsigned char *data = GetData();
2171 if( !data )
2172 {
2173 wxFAIL_MSG( wxT("could not allocate data for image") );
2174 return;
2175 }
2176
2177 // calc the number of bytes per scanline and padding in the DIB
2178 int bytePerLine = width*3;
2179 int sizeDWORD = sizeof( DWORD );
2180 int lineBoundary = bytePerLine % sizeDWORD;
2181 int padding = 0;
2182 if( lineBoundary > 0 )
2183 {
2184 padding = sizeDWORD - lineBoundary;
2185 bytePerLine += padding;
2186 }
2187// TODO:
2188/*
2189 // create a DIB header
2190 int headersize = sizeof(BITMAPINFOHEADER);
2191 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
2192 if( !lpDIBh )
2193 {
2194 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
2195 free( data );
2196 return;
2197 }
2198 // Fill in the DIB header
2199 lpDIBh->bmiHeader.biSize = headersize;
2200 lpDIBh->bmiHeader.biWidth = width;
2201 lpDIBh->bmiHeader.biHeight = -height;
2202 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
2203 lpDIBh->bmiHeader.biPlanes = 1;
2204 lpDIBh->bmiHeader.biBitCount = 24;
2205 lpDIBh->bmiHeader.biCompression = BI_RGB;
2206 lpDIBh->bmiHeader.biClrUsed = 0;
2207 // These seem not really needed for our purpose here.
2208 lpDIBh->bmiHeader.biClrImportant = 0;
2209 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2210 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2211 // memory for DIB data
2212 unsigned char *lpBits;
2213 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
2214 if( !lpBits )
2215 {
2216 wxFAIL_MSG( wxT("could not allocate data for DIB") );
2217 free( data );
2218 free( lpDIBh );
2219 return;
2220 }
2221
2222 // copy data from the device-dependent bitmap to the DIB
2223 HDC hdc = ::GetDC(NULL);
2224 HBITMAP hbitmap;
2225 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
2226 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2227
2228 // copy DIB data into the wxImage object
2229 int i, j;
2230 unsigned char *ptdata = data;
2231 unsigned char *ptbits = lpBits;
2232 for( i=0; i<height; i++ )
2233 {
2234 for( j=0; j<width; j++ )
2235 {
2236 *(ptdata++) = *(ptbits+2);
2237 *(ptdata++) = *(ptbits+1);
2238 *(ptdata++) = *(ptbits );
2239 ptbits += 3;
2240 }
2241 ptbits += padding;
2242 }
2243
2244 // similarly, set data according to the possible mask bitmap
2245 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
2246 {
2247 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
2248 // memory DC created, color set, data copied, and memory DC deleted
2249 HDC memdc = ::CreateCompatibleDC( hdc );
2250 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
2251 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
2252 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2253 ::DeleteDC( memdc );
2254 // background color set to RGB(16,16,16) in consistent with wxGTK
2255 unsigned char r=16, g=16, b=16;
2256 ptdata = data;
2257 ptbits = lpBits;
2258 for( i=0; i<height; i++ )
2259 {
2260 for( j=0; j<width; j++ )
2261 {
2262 if( *ptbits != 0 )
2263 ptdata += 3;
2264 else
2265 {
2266 *(ptdata++) = r;
2267 *(ptdata++) = g;
2268 *(ptdata++) = b;
2269 }
2270 ptbits += 3;
2271 }
2272 ptbits += padding;
2273 }
2274 SetMaskColour( r, g, b );
2275 SetMask( TRUE );
2276 }
2277 else
2278 {
2279 SetMask( FALSE );
2280 }
2281 // free allocated resources
2282 ::ReleaseDC(NULL, hdc);
2283 free(lpDIBh);
2284 free(lpBits);
2285*/
2286}
2287
2288#endif
2289
a91b47e8
JS
2290// A module to allow wxImage initialization/cleanup
2291// without calling these functions from app.cpp or from
2292// the user's application.
2293
2294class wxImageModule: public wxModule
2295{
2296DECLARE_DYNAMIC_CLASS(wxImageModule)
2297public:
2298 wxImageModule() {}
2299 bool OnInit() { wxImage::InitStandardHandlers(); return TRUE; };
2300 void OnExit() { wxImage::CleanUpHandlers(); };
2301};
2302
2303IMPLEMENT_DYNAMIC_CLASS(wxImageModule, wxModule)