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