]> git.saurik.com Git - wxWidgets.git/blame - src/common/image.cpp
Set RADIOBTN_PARENT_IS_RADIOBOX to 0 (sorry, but...); fixed a
[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 885 {
8208e181
SC
886 // was causing a code gen bug in cw : if( ( cr !=r) || (cg!=g) || (cb!=b) )
887 unsigned char cr = (*(ptdata++)) ;
888 unsigned char cg = (*(ptdata++)) ;
889 unsigned char cb = (*(ptdata++)) ;
890
891 if( ( cr !=r) || (cg!=g) || (cb!=b) )
bba6f3bd
UA
892 {
893 *(ptbits++) = one;
894 *(ptbits++) = one;
895 *(ptbits++) = one;
896 }
897 else
898 {
899 *(ptbits++) = zero;
900 *(ptbits++) = zero;
901 *(ptbits++) = zero;
902 }
903 }
dbda9e86 904 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
bba6f3bd
UA
905 }
906 ::StretchDIBits( memdc, 0, origin, width, height,\
dbda9e86
JS
907 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
908 origin += height;
909 }
910 // create a wxMask object
bba6f3bd
UA
911 wxMask *mask = new wxMask();
912 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
913 bitmap.SetMask( mask );
dbda9e86
JS
914 // It will be deleted when the wxBitmap object is deleted (as of 01/1999)
915 /* The following can also be used but is slow to run
bba6f3bd
UA
916 wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
917 wxMask *mask = new wxMask( bitmap, colour );
918 bitmap.SetMask( mask );
dbda9e86 919 */
bba6f3bd 920 }
c7abc967
VZ
921
922 // free allocated resources
923 ::SelectObject( memdc, 0 );
924 ::DeleteDC( memdc );
925 ::ReleaseDC(NULL, hdc);
bba6f3bd
UA
926 free(lpDIBh);
927 free(lpBits);
c7abc967 928
6d167489 929#if WXWIN_COMPATIBILITY_2
dbda9e86 930 // check the wxBitmap object
6d167489
VZ
931 bitmap.GetBitmapData()->SetOk();
932#endif // WXWIN_COMPATIBILITY_2
c7abc967 933
bba6f3bd 934 return bitmap;
e3554471
JS
935}
936
e3554471
JS
937wxImage::wxImage( const wxBitmap &bitmap )
938{
dbda9e86 939 // check the bitmap
bba6f3bd
UA
940 if( !bitmap.Ok() )
941 {
223d09f6 942 wxFAIL_MSG( wxT("invalid bitmap") );
bba6f3bd
UA
943 return;
944 }
c7abc967 945
dbda9e86 946 // create an wxImage object
bba6f3bd
UA
947 int width = bitmap.GetWidth();
948 int height = bitmap.GetHeight();
c7abc967 949 Create( width, height );
bba6f3bd
UA
950 unsigned char *data = GetData();
951 if( !data )
952 {
223d09f6 953 wxFAIL_MSG( wxT("could not allocate data for image") );
bba6f3bd
UA
954 return;
955 }
c7abc967 956
dbda9e86 957 // calc the number of bytes per scanline and padding in the DIB
bba6f3bd
UA
958 int bytePerLine = width*3;
959 int sizeDWORD = sizeof( DWORD );
bae41ce1 960 int lineBoundary = bytePerLine % sizeDWORD;
bba6f3bd 961 int padding = 0;
bae41ce1 962 if( lineBoundary > 0 )
bba6f3bd 963 {
bae41ce1 964 padding = sizeDWORD - lineBoundary;
bba6f3bd
UA
965 bytePerLine += padding;
966 }
c7abc967 967
dbda9e86 968 // create a DIB header
bba6f3bd 969 int headersize = sizeof(BITMAPINFOHEADER);
8f177c8e 970 BITMAPINFO *lpDIBh = (BITMAPINFO *) malloc( headersize );
bba6f3bd
UA
971 if( !lpDIBh )
972 {
223d09f6 973 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
bba6f3bd
UA
974 free( data );
975 return;
976 }
dbda9e86 977 // Fill in the DIB header
bba6f3bd
UA
978 lpDIBh->bmiHeader.biSize = headersize;
979 lpDIBh->bmiHeader.biWidth = width;
980 lpDIBh->bmiHeader.biHeight = -height;
981 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
982 lpDIBh->bmiHeader.biPlanes = 1;
983 lpDIBh->bmiHeader.biBitCount = 24;
984 lpDIBh->bmiHeader.biCompression = BI_RGB;
985 lpDIBh->bmiHeader.biClrUsed = 0;
dbda9e86 986 // These seem not really needed for our purpose here.
bba6f3bd
UA
987 lpDIBh->bmiHeader.biClrImportant = 0;
988 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
989 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
dbda9e86 990 // memory for DIB data
bba6f3bd
UA
991 unsigned char *lpBits;
992 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
993 if( !lpBits )
e3554471 994 {
223d09f6 995 wxFAIL_MSG( wxT("could not allocate data for DIB") );
bba6f3bd
UA
996 free( data );
997 free( lpDIBh );
998 return;
4698648f 999 }
c7abc967 1000
dbda9e86 1001 // copy data from the device-dependent bitmap to the DIB
bba6f3bd
UA
1002 HDC hdc = ::GetDC(NULL);
1003 HBITMAP hbitmap;
1004 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
1005 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
c7abc967 1006
dbda9e86 1007 // copy DIB data into the wxImage object
bba6f3bd
UA
1008 int i, j;
1009 unsigned char *ptdata = data;
1010 unsigned char *ptbits = lpBits;
1011 for( i=0; i<height; i++ )
1012 {
1013 for( j=0; j<width; j++ )
1014 {
1015 *(ptdata++) = *(ptbits+2);
1016 *(ptdata++) = *(ptbits+1);
1017 *(ptdata++) = *(ptbits );
1018 ptbits += 3;
dbda9e86 1019 }
bba6f3bd 1020 ptbits += padding;
c7abc967
VZ
1021 }
1022
dbda9e86 1023 // similarly, set data according to the possible mask bitmap
bba6f3bd
UA
1024 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
1025 {
1026 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
dbda9e86 1027 // memory DC created, color set, data copied, and memory DC deleted
bba6f3bd
UA
1028 HDC memdc = ::CreateCompatibleDC( hdc );
1029 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
1030 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
1031 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
c7abc967 1032 ::DeleteDC( memdc );
dbda9e86 1033 // background color set to RGB(16,16,16) in consistent with wxGTK
c7abc967 1034 unsigned char r=16, g=16, b=16;
bba6f3bd
UA
1035 ptdata = data;
1036 ptbits = lpBits;
1037 for( i=0; i<height; i++ )
1038 {
1039 for( j=0; j<width; j++ )
1040 {
1041 if( *ptbits != 0 )
dbda9e86
JS
1042 ptdata += 3;
1043 else
bba6f3bd
UA
1044 {
1045 *(ptdata++) = r;
1046 *(ptdata++) = g;
1047 *(ptdata++) = b;
dbda9e86 1048 }
bba6f3bd
UA
1049 ptbits += 3;
1050 }
1051 ptbits += padding;
c7abc967 1052 }
bba6f3bd
UA
1053 SetMaskColour( r, g, b );
1054 SetMask( TRUE );
c7abc967 1055 }
bba6f3bd
UA
1056 else
1057 {
1058 SetMask( FALSE );
c7abc967
VZ
1059 }
1060 // free allocated resources
1061 ::ReleaseDC(NULL, hdc);
bba6f3bd
UA
1062 free(lpDIBh);
1063 free(lpBits);
e3554471
JS
1064}
1065
1066#endif
1067
7c74e7fe
SC
1068#ifdef __WXMAC__
1069
1070#include <PictUtils.h>
1071
1072extern CTabHandle wxMacCreateColorTable( int numColors ) ;
1073extern void wxMacDestroyColorTable( CTabHandle colors ) ;
1074extern void wxMacSetColorTableEntry( CTabHandle newColors , int index , int red , int green , int blue ) ;
1075extern GWorldPtr wxMacCreateGWorld( int height , int width , int depth ) ;
1076extern void wxMacDestroyGWorld( GWorldPtr gw ) ;
1077
1078wxBitmap wxImage::ConvertToBitmap() const
1079{
1080 // width and height of the device-dependent bitmap
1081 int width = GetWidth();
1082 int height = GetHeight();
1083
1084 // Create picture
97fdfcc9 1085
7c74e7fe 1086 wxBitmap bitmap( width , height , wxDisplayDepth() ) ;
97fdfcc9 1087
7c74e7fe 1088 // Create mask
97fdfcc9 1089
7c74e7fe
SC
1090 if (HasMask())
1091 {
1092 /*
1093 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
97fdfcc9 1094
7c74e7fe 1095 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
97fdfcc9 1096
7c74e7fe
SC
1097 wxMask *mask = new wxMask();
1098 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
97fdfcc9 1099
7c74e7fe
SC
1100 bitmap.SetMask( mask );
1101 */
1102 }
97fdfcc9 1103
7c74e7fe 1104 // Render
97fdfcc9 1105
7c74e7fe
SC
1106 int r_mask = GetMaskRed();
1107 int g_mask = GetMaskGreen();
1108 int b_mask = GetMaskBlue();
97fdfcc9 1109
7c74e7fe
SC
1110 CGrafPtr origPort ;
1111 GDHandle origDevice ;
1112
1113 GetGWorld( &origPort , &origDevice ) ;
1114 SetGWorld( bitmap.GetHBITMAP() , NULL ) ;
1115
1116 register unsigned char* data = GetData();
97fdfcc9 1117
7c74e7fe
SC
1118 int index = 0;
1119 for (int y = 0; y < height; y++)
1120 {
7c74e7fe
SC
1121 for (int x = 0; x < width; x++)
1122 {
1123 unsigned char r = data[index++];
1124 unsigned char g = data[index++];
1125 unsigned char b = data[index++];
1126 RGBColor color ;
1127 color.red = ( r << 8 ) + r ;
1128 color.green = ( g << 8 ) + g ;
1129 color.blue = ( b << 8 ) + b ;
1130 SetCPixel( x , y , &color ) ;
1131 }
7c74e7fe
SC
1132 } // for height
1133
1134 SetGWorld( origPort , origDevice ) ;
97fdfcc9 1135
8208e181
SC
1136 if ( HasMask() )
1137 {
1138 wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
1139 wxMask *mask = new wxMask( bitmap, colour );
1140 bitmap.SetMask( mask );
1141 }
7c74e7fe 1142 return bitmap;
97fdfcc9 1143
7c74e7fe
SC
1144}
1145
1146wxImage::wxImage( const wxBitmap &bitmap )
1147{
1148 // check the bitmap
1149 if( !bitmap.Ok() )
1150 {
1151 wxFAIL_MSG( "invalid bitmap" );
1152 return;
1153 }
97fdfcc9 1154
7c74e7fe
SC
1155 // create an wxImage object
1156 int width = bitmap.GetWidth();
1157 int height = bitmap.GetHeight();
97fdfcc9 1158 Create( width, height );
7c74e7fe
SC
1159 /*
1160 unsigned char *data = GetData();
1161 if( !data )
1162 {
1163 wxFAIL_MSG( "could not allocate data for image" );
1164 return;
1165 }
97fdfcc9 1166
7c74e7fe
SC
1167 // calc the number of bytes per scanline and padding in the DIB
1168 int bytePerLine = width*3;
1169 int sizeDWORD = sizeof( DWORD );
1170 div_t lineBoundary = div( bytePerLine, sizeDWORD );
1171 int padding = 0;
97fdfcc9 1172 if( lineBoundary.rem > 0 )
7c74e7fe
SC
1173 {
1174 padding = sizeDWORD - lineBoundary.rem;
1175 bytePerLine += padding;
1176 }
97fdfcc9 1177
7c74e7fe
SC
1178 // create a DIB header
1179 int headersize = sizeof(BITMAPINFOHEADER);
1180 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
1181 if( !lpDIBh )
1182 {
1183 wxFAIL_MSG( "could not allocate data for DIB header" );
1184 free( data );
1185 return;
1186 }
1187 // Fill in the DIB header
1188 lpDIBh->bmiHeader.biSize = headersize;
1189 lpDIBh->bmiHeader.biWidth = width;
1190 lpDIBh->bmiHeader.biHeight = -height;
1191 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
1192 lpDIBh->bmiHeader.biPlanes = 1;
1193 lpDIBh->bmiHeader.biBitCount = 24;
1194 lpDIBh->bmiHeader.biCompression = BI_RGB;
1195 lpDIBh->bmiHeader.biClrUsed = 0;
1196 // These seem not really needed for our purpose here.
1197 lpDIBh->bmiHeader.biClrImportant = 0;
1198 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
1199 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
1200 // memory for DIB data
1201 unsigned char *lpBits;
1202 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
1203 if( !lpBits )
1204 {
1205 wxFAIL_MSG( "could not allocate data for DIB" );
1206 free( data );
1207 free( lpDIBh );
1208 return;
1209 }
97fdfcc9 1210
7c74e7fe
SC
1211 // copy data from the device-dependent bitmap to the DIB
1212 HDC hdc = ::GetDC(NULL);
1213 HBITMAP hbitmap;
1214 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
1215 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
97fdfcc9 1216
7c74e7fe
SC
1217 // copy DIB data into the wxImage object
1218 int i, j;
1219 unsigned char *ptdata = data;
1220 unsigned char *ptbits = lpBits;
1221 for( i=0; i<height; i++ )
1222 {
1223 for( j=0; j<width; j++ )
1224 {
1225 *(ptdata++) = *(ptbits+2);
1226 *(ptdata++) = *(ptbits+1);
1227 *(ptdata++) = *(ptbits );
1228 ptbits += 3;
1229 }
1230 ptbits += padding;
1231 }
97fdfcc9 1232
7c74e7fe
SC
1233 // similarly, set data according to the possible mask bitmap
1234 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
1235 {
1236 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
1237 // memory DC created, color set, data copied, and memory DC deleted
1238 HDC memdc = ::CreateCompatibleDC( hdc );
1239 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
1240 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
1241 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
97fdfcc9 1242 ::DeleteDC( memdc );
7c74e7fe 1243 // background color set to RGB(16,16,16) in consistent with wxGTK
97fdfcc9 1244 unsigned char r=16, g=16, b=16;
7c74e7fe
SC
1245 ptdata = data;
1246 ptbits = lpBits;
1247 for( i=0; i<height; i++ )
1248 {
1249 for( j=0; j<width; j++ )
1250 {
1251 if( *ptbits != 0 )
1252 ptdata += 3;
1253 else
1254 {
1255 *(ptdata++) = r;
1256 *(ptdata++) = g;
1257 *(ptdata++) = b;
1258 }
1259 ptbits += 3;
1260 }
1261 ptbits += padding;
97fdfcc9 1262 }
7c74e7fe
SC
1263 SetMaskColour( r, g, b );
1264 SetMask( TRUE );
8f177c8e 1265 }
7c74e7fe
SC
1266 else
1267 {
1268 SetMask( FALSE );
8f177c8e 1269 }
97fdfcc9
DW
1270 // free allocated resources
1271 ::ReleaseDC(NULL, hdc);
7c74e7fe
SC
1272 free(lpDIBh);
1273 free(lpBits);
1274 */
1275}
1276
1277#endif
1278
ce4169a4
RR
1279//-----------------------------------------------------------------------------
1280// GTK conversion routines
1281//-----------------------------------------------------------------------------
1282
99c67c77
RR
1283#ifdef __WXGTK__
1284
20e05ffb
RR
1285#include <gtk/gtk.h>
1286#include <gdk/gdk.h>
1287#include <gdk/gdkx.h>
83624f79 1288
ba0730de 1289#if (GTK_MINOR_VERSION > 0)
20e05ffb 1290#include <gdk/gdkrgb.h>
ba0730de
RR
1291#endif
1292
82ea63e6
RR
1293wxBitmap wxImage::ConvertToMonoBitmap( unsigned char red, unsigned char green, unsigned char blue )
1294{
1295 wxBitmap bitmap;
1296
1297 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
1298
1299 int width = GetWidth();
1300 int height = GetHeight();
1301
1302 bitmap.SetHeight( height );
1303 bitmap.SetWidth( width );
1304
1305 bitmap.SetBitmap( gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 ) );
1306
1307 bitmap.SetDepth( 1 );
1308
1309 // Create picture image
1310
1311 unsigned char *data_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1312
1313 GdkImage *data_image =
1314 gdk_image_new_bitmap( gdk_visual_get_system(), data_data, width, height );
1315
1316 // Create mask image
1317
1318 GdkImage *mask_image = (GdkImage*) NULL;
1319
1320 if (HasMask())
1321 {
1322 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1323
1324 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1325
1326 wxMask *mask = new wxMask();
1327 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1328
1329 bitmap.SetMask( mask );
1330 }
1331
1332 int r_mask = GetMaskRed();
1333 int g_mask = GetMaskGreen();
1334 int b_mask = GetMaskBlue();
1335
1336 unsigned char* data = GetData();
1337
1338 int index = 0;
1339 for (int y = 0; y < height; y++)
1340 {
1341 for (int x = 0; x < width; x++)
1342 {
1343 int r = data[index];
1344 index++;
1345 int g = data[index];
1346 index++;
1347 int b = data[index];
1348 index++;
1349
1350 if (HasMask())
1351 {
1352 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1353 gdk_image_put_pixel( mask_image, x, y, 1 );
1354 else
1355 gdk_image_put_pixel( mask_image, x, y, 0 );
1356 }
1357
1358 if ((r == red) && (b == blue) && (g == green))
1359 gdk_image_put_pixel( data_image, x, y, 1 );
1360 else
1361 gdk_image_put_pixel( data_image, x, y, 0 );
1362
1363 } // for
1364 } // for
1365
1366 // Blit picture
1367
1368 GdkGC *data_gc = gdk_gc_new( bitmap.GetBitmap() );
1369
1370 gdk_draw_image( bitmap.GetBitmap(), data_gc, data_image, 0, 0, 0, 0, width, height );
1371
1372 gdk_image_destroy( data_image );
1373 gdk_gc_unref( data_gc );
1374
1375 // Blit mask
1376
1377 if (HasMask())
1378 {
1379 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
1380
1381 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
1382
1383 gdk_image_destroy( mask_image );
1384 gdk_gc_unref( mask_gc );
1385 }
1386
1387 return bitmap;
1388}
1389
1390
99c67c77
RR
1391wxBitmap wxImage::ConvertToBitmap() const
1392{
1393 wxBitmap bitmap;
c7abc967 1394
223d09f6 1395 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
c7abc967 1396
99c67c77
RR
1397 int width = GetWidth();
1398 int height = GetHeight();
c7abc967 1399
99c67c77
RR
1400 bitmap.SetHeight( height );
1401 bitmap.SetWidth( width );
c7abc967 1402
ba0730de
RR
1403 bitmap.SetPixmap( gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, -1 ) );
1404
1405 // Retrieve depth
c7abc967 1406
ba0730de 1407 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
b134516c 1408 if (visual == NULL) visual = gdk_visual_get_system();
ba0730de 1409 int bpp = visual->depth;
c7abc967 1410
ba0730de 1411 bitmap.SetDepth( bpp );
c7abc967 1412
ba0730de
RR
1413 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
1414 if (bpp < 8) bpp = 8;
c7abc967 1415
ba0730de
RR
1416#if (GTK_MINOR_VERSION > 0)
1417
1418 if (!HasMask() && (bpp > 8))
1419 {
1420 static bool s_hasInitialized = FALSE;
c7abc967 1421
995612e2
VZ
1422 if (!s_hasInitialized)
1423 {
1424 gdk_rgb_init();
1425 s_hasInitialized = TRUE;
1426 }
c7abc967 1427
ba0730de 1428 GdkGC *gc = gdk_gc_new( bitmap.GetPixmap() );
c7abc967 1429
995612e2
VZ
1430 gdk_draw_rgb_image( bitmap.GetPixmap(),
1431 gc,
1432 0, 0,
1433 width, height,
1434 GDK_RGB_DITHER_NONE,
1435 GetData(),
1436 width*3 );
c7abc967 1437
ba0730de 1438 gdk_gc_unref( gc );
c7abc967 1439
995612e2 1440 return bitmap;
ba0730de 1441 }
c7abc967 1442
ba0730de 1443#endif
c7abc967 1444
ba0730de 1445 // Create picture image
c7abc967 1446
99c67c77 1447 GdkImage *data_image =
b134516c 1448 gdk_image_new( GDK_IMAGE_FASTEST, gdk_visual_get_system(), width, height );
c7abc967 1449
ba0730de 1450 // Create mask image
c7abc967 1451
99c67c77 1452 GdkImage *mask_image = (GdkImage*) NULL;
c7abc967 1453
99c67c77
RR
1454 if (HasMask())
1455 {
1456 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
c7abc967 1457
b134516c 1458 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
c7abc967 1459
4698648f
VZ
1460 wxMask *mask = new wxMask();
1461 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
c7abc967 1462
4698648f 1463 bitmap.SetMask( mask );
99c67c77 1464 }
c7abc967 1465
99c67c77 1466 // Render
c7abc967 1467
99c67c77
RR
1468 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1469 byte_order b_o = RGB;
c7abc967 1470
99c67c77
RR
1471 if (bpp >= 24)
1472 {
b134516c 1473 GdkVisual *visual = gdk_visual_get_system();
99c67c77
RR
1474 if ((visual->red_mask > visual->green_mask) && (visual->green_mask > visual->blue_mask)) b_o = RGB;
1475 else if ((visual->red_mask > visual->blue_mask) && (visual->blue_mask > visual->green_mask)) b_o = RGB;
1476 else if ((visual->blue_mask > visual->red_mask) && (visual->red_mask > visual->green_mask)) b_o = BRG;
1477 else if ((visual->blue_mask > visual->green_mask) && (visual->green_mask > visual->red_mask)) b_o = BGR;
1478 else if ((visual->green_mask > visual->red_mask) && (visual->red_mask > visual->blue_mask)) b_o = GRB;
1479 else if ((visual->green_mask > visual->blue_mask) && (visual->blue_mask > visual->red_mask)) b_o = GBR;
1480 }
c7abc967 1481
99c67c77
RR
1482 int r_mask = GetMaskRed();
1483 int g_mask = GetMaskGreen();
1484 int b_mask = GetMaskBlue();
c7abc967 1485
99c67c77 1486 unsigned char* data = GetData();
c7abc967 1487
99c67c77
RR
1488 int index = 0;
1489 for (int y = 0; y < height; y++)
1490 {
1491 for (int x = 0; x < width; x++)
1492 {
1493 int r = data[index];
4698648f 1494 index++;
99c67c77 1495 int g = data[index];
4698648f 1496 index++;
99c67c77 1497 int b = data[index];
4698648f 1498 index++;
c7abc967 1499
4698648f
VZ
1500 if (HasMask())
1501 {
1502 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1503 gdk_image_put_pixel( mask_image, x, y, 1 );
1504 else
1505 gdk_image_put_pixel( mask_image, x, y, 0 );
1506 }
c7abc967 1507
4698648f
VZ
1508 switch (bpp)
1509 {
dbda9e86 1510 case 8:
4698648f 1511 {
f6fcbb63 1512 int pixel = -1;
4698648f
VZ
1513 if (wxTheApp->m_colorCube)
1514 {
38274997 1515 pixel = wxTheApp->m_colorCube[ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
4698648f 1516 }
f6fcbb63 1517 else
4698648f
VZ
1518 {
1519 GdkColormap *cmap = gtk_widget_get_default_colormap();
f6fcbb63
RR
1520 GdkColor *colors = cmap->colors;
1521 int max = 3 * (65536);
c7abc967 1522
f6fcbb63
RR
1523 for (int i = 0; i < cmap->size; i++)
1524 {
1525 int rdiff = (r << 8) - colors[i].red;
1526 int gdiff = (g << 8) - colors[i].green;
1527 int bdiff = (b << 8) - colors[i].blue;
1528 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1529 if (sum < max) { pixel = i; max = sum; }
4698648f 1530 }
99c67c77 1531 }
c7abc967 1532
4698648f 1533 gdk_image_put_pixel( data_image, x, y, pixel );
c7abc967 1534
4698648f
VZ
1535 break;
1536 }
dbda9e86 1537 case 15:
4698648f
VZ
1538 {
1539 guint32 pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1540 gdk_image_put_pixel( data_image, x, y, pixel );
1541 break;
1542 }
dbda9e86 1543 case 16:
4698648f
VZ
1544 {
1545 guint32 pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1546 gdk_image_put_pixel( data_image, x, y, pixel );
1547 break;
1548 }
dbda9e86
JS
1549 case 32:
1550 case 24:
4698648f
VZ
1551 {
1552 guint32 pixel = 0;
1553 switch (b_o)
1554 {
dbda9e86
JS
1555 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1556 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1557 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1558 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1559 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1560 case GBR: pixel = (g << 16) | (b << 8) | r; break;
4698648f
VZ
1561 }
1562 gdk_image_put_pixel( data_image, x, y, pixel );
1563 }
dbda9e86 1564 default: break;
4698648f 1565 }
99c67c77
RR
1566 } // for
1567 } // for
c7abc967 1568
99c67c77 1569 // Blit picture
c7abc967 1570
99c67c77 1571 GdkGC *data_gc = gdk_gc_new( bitmap.GetPixmap() );
c7abc967 1572
99c67c77 1573 gdk_draw_image( bitmap.GetPixmap(), data_gc, data_image, 0, 0, 0, 0, width, height );
c7abc967 1574
99c67c77
RR
1575 gdk_image_destroy( data_image );
1576 gdk_gc_unref( data_gc );
c7abc967 1577
99c67c77 1578 // Blit mask
c7abc967 1579
99c67c77
RR
1580 if (HasMask())
1581 {
1582 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
c7abc967 1583
99c67c77 1584 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
c7abc967 1585
99c67c77
RR
1586 gdk_image_destroy( mask_image );
1587 gdk_gc_unref( mask_gc );
1588 }
c7abc967 1589
99c67c77
RR
1590 return bitmap;
1591}
1592
1593wxImage::wxImage( const wxBitmap &bitmap )
1594{
223d09f6 1595 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
c7abc967 1596
c6d73ef6
RR
1597 GdkImage *gdk_image = (GdkImage*) NULL;
1598 if (bitmap.GetPixmap())
1599 {
1600 gdk_image = gdk_image_get( bitmap.GetPixmap(),
1601 0, 0,
1602 bitmap.GetWidth(), bitmap.GetHeight() );
1603 } else
1604 if (bitmap.GetBitmap())
1605 {
1606 gdk_image = gdk_image_get( bitmap.GetBitmap(),
1607 0, 0,
1608 bitmap.GetWidth(), bitmap.GetHeight() );
1609 } else
1610 {
1611 wxFAIL_MSG( wxT("Ill-formed bitmap") );
1612 }
c7abc967 1613
223d09f6 1614 wxCHECK_RET( gdk_image, wxT("couldn't create image") );
c7abc967 1615
99c67c77
RR
1616 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1617 char unsigned *data = GetData();
c7abc967 1618
99c67c77
RR
1619 if (!data)
1620 {
1621 gdk_image_destroy( gdk_image );
223d09f6 1622 wxFAIL_MSG( wxT("couldn't create image") );
4698648f 1623 return;
99c67c77 1624 }
c7abc967 1625
99c67c77
RR
1626 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1627 if (bitmap.GetMask())
1628 {
1629 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
dbda9e86
JS
1630 0, 0,
1631 bitmap.GetWidth(), bitmap.GetHeight() );
c7abc967 1632
4698648f 1633 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
99c67c77 1634 }
c7abc967 1635
be25e480 1636 int bpp = -1;
c6d73ef6 1637 if (bitmap.GetPixmap())
be25e480
RR
1638 {
1639 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
c6d73ef6 1640
be25e480
RR
1641 if (visual == NULL) visual = gdk_window_get_visual( (GdkWindow*) &gdk_root_parent );
1642 bpp = visual->depth;
1643 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
1644 }
1645 if (bitmap.GetBitmap())
1646 {
1647 bpp = 1;
1648 }
c7abc967 1649
99c67c77 1650 GdkColormap *cmap = gtk_widget_get_default_colormap();
c7abc967 1651
99c67c77
RR
1652 long pos = 0;
1653 for (int j = 0; j < bitmap.GetHeight(); j++)
1654 {
1655 for (int i = 0; i < bitmap.GetWidth(); i++)
1656 {
4cb122de 1657 wxInt32 pixel = gdk_image_get_pixel( gdk_image, i, j );
be25e480
RR
1658 if (bpp == 1)
1659 {
1660 if (pixel == 0)
1661 {
1662 data[pos] = 0;
1663 data[pos+1] = 0;
1664 data[pos+2] = 0;
1665 }
1666 else
1667 {
1668 data[pos] = 255;
1669 data[pos+1] = 255;
1670 data[pos+2] = 255;
1671 }
1672 } else if (bpp <= 8)
99c67c77
RR
1673 {
1674 data[pos] = cmap->colors[pixel].red >> 8;
1675 data[pos+1] = cmap->colors[pixel].green >> 8;
1676 data[pos+2] = cmap->colors[pixel].blue >> 8;
1677 } else if (bpp == 15)
1678 {
848bc5ba
RR
1679#if (wxBYTE_ORDER == wxBIG_ENDIAN)
1680 // ?
1681#endif
99c67c77
RR
1682 data[pos] = (pixel >> 7) & 0xf8;
1683 data[pos+1] = (pixel >> 2) & 0xf8;
1684 data[pos+2] = (pixel << 3) & 0xf8;
1685 } else if (bpp == 16)
1686 {
848bc5ba
RR
1687#if (wxBYTE_ORDER == wxBIG_ENDIAN)
1688 // ?
1689#endif
99c67c77
RR
1690 data[pos] = (pixel >> 8) & 0xf8;
1691 data[pos+1] = (pixel >> 3) & 0xfc;
1692 data[pos+2] = (pixel << 3) & 0xf8;
1693 } else
1694 {
848bc5ba
RR
1695#if (wxBYTE_ORDER == wxBIG_ENDIAN)
1696 data[pos] = (pixel) & 0xff; // Red
1697 data[pos+1] = (pixel >> 8) & 0xff; // Green
1698 data[pos+2] = (pixel >> 16) & 0xff; // Blue
1699#else
99c67c77
RR
1700 data[pos] = (pixel >> 16) & 0xff;
1701 data[pos+1] = (pixel >> 8) & 0xff;
1702 data[pos+2] = pixel & 0xff;
848bc5ba 1703#endif
99c67c77 1704 }
c7abc967 1705
4698648f
VZ
1706 if (gdk_image_mask)
1707 {
1708 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1709 if (mask_pixel == 0)
1710 {
99c67c77
RR
1711 data[pos] = 16;
1712 data[pos+1] = 16;
1713 data[pos+2] = 16;
dbda9e86 1714 }
4698648f 1715 }
c7abc967 1716
99c67c77
RR
1717 pos += 3;
1718 }
1719 }
c7abc967 1720
99c67c77
RR
1721 gdk_image_destroy( gdk_image );
1722 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1723}
1724
1725#endif
ee4c6942 1726
ce4169a4
RR
1727//-----------------------------------------------------------------------------
1728// Motif conversion routines
1729//-----------------------------------------------------------------------------
1730
ee4c6942 1731#ifdef __WXMOTIF__
338dd992
JJ
1732#ifdef __VMS__
1733#pragma message disable nosimpint
1734#endif
b75867a6 1735#include <Xm/Xm.h>
338dd992
JJ
1736#ifdef __VMS__
1737#pragma message enable nosimpint
1738#endif
b75867a6 1739#include "wx/utils.h"
38274997 1740#include <math.h>
b75867a6 1741
88195b2b
JS
1742/*
1743
1744Date: Wed, 05 Jan 2000 11:45:40 +0100
1745From: Frits Boel <boel@niob.knaw.nl>
1746To: julian.smart@ukonline.co.uk
1747Subject: Patch for Motif ConvertToBitmap
1748
1749Hi Julian,
1750
1751I've been working on a wxWin application for image processing. From the
1752beginning, I was surprised by the (lack of) speed of ConvertToBitmap,
1753till I looked in the source code of image.cpp. I saw that converting a
1754wxImage to a bitmap with 8-bit pixels is done with comparing every pixel
1755to the 256 colors of the palet. A very time-consuming piece of code!
1756
1757Because I wanted a faster application, I've made a 'patch' for this. In
1758short: every pixel of the image is compared to a sorted list with
1759colors. If the color is found in the list, the palette entry is
1760returned; if the color is not found, the color palette is searched and
1761then the palette entry is returned and the color added to the sorted
1762list.
1763
1764Maybe there is another method for this, namely changing the palette
1765itself (if the colors are known, as is the case with tiffs with a
1766colormap). I did not look at this, maybe someone else did?
1767
1768The code of the patch is attached, have a look on it, and maybe you will
1769ship it with the next release of wxMotif?
1770
1771Regards,
1772
1773Frits Boel
1774Software engineer at Hubrecht Laboratory, The Netherlands.
1775
1776*/
1777
1778class wxSearchColor
1779{
1780public:
1781 wxSearchColor( void );
1782 wxSearchColor( int size, XColor *colors );
1783 ~wxSearchColor( void );
1784
1785 int SearchColor( int r, int g, int b );
1786private:
1787 int AddColor( unsigned int value, int pos );
1788
1789 int size;
1790 XColor *colors;
1791 unsigned int *color;
1792 int *entry;
1793
1794 int bottom;
1795 int top;
1796};
1797
1798wxSearchColor::wxSearchColor( void )
1799{
1800 this->size = 0;
1801 this->colors = (XColor*) NULL;
1802 this->color = (unsigned int *) NULL;
1803 this->entry = (int*) NULL;
1804
1805 this->bottom = 0;
1806 this->top = 0;
1807}
1808
1809wxSearchColor::wxSearchColor( int size, XColor *colors )
1810{
1811 int i;
1812 this->size = size;
1813 this->colors = colors;
1814 this->color = new unsigned int[size];
1815 this->entry = new int [size];
1816
1817 for (i = 0; i < this->size; i++ ) {
1818 this->entry[i] = -1;
1819 }
1820
1821 this->bottom = this->top = ( size >> 1 );
1822}
1823
1824wxSearchColor::~wxSearchColor( void )
1825{
1826 if ( this->color ) delete this->color;
1827 if ( this->entry ) delete this->entry;
1828}
1829
1830int wxSearchColor::SearchColor( int r, int g, int b )
1831{
1832 unsigned int value = ( ( ( r * 256 ) + g ) * 256 ) + b;
1833 int begin = this->bottom;
1834 int end = this->top;
1835 int middle;
1836
1837 while ( begin <= end ) {
1838
1839 middle = ( begin + end ) >> 1;
1840
1841 if ( value == this->color[middle] ) {
1842 return( this->entry[middle] );
1843 } else if ( value < this->color[middle] ) {
1844 end = middle - 1;
1845 } else {
1846 begin = middle + 1;
1847 }
1848
1849 }
1850
1851 return AddColor( value, middle );
1852}
1853
1854int wxSearchColor::AddColor( unsigned int value, int pos )
1855{
1856 int i;
1857 int pixel = -1;
1858 int max = 3 * (65536);
1859 for ( i = 0; i < 256; i++ ) {
1860 int rdiff = ((value >> 8) & 0xFF00 ) - colors[i].red;
1861 int gdiff = ((value ) & 0xFF00 ) - colors[i].green;
1862 int bdiff = ((value << 8) & 0xFF00 ) - colors[i].blue;
1863 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1864 if (sum < max) { pixel = i; max = sum; }
1865 }
1866
1867 if ( this->entry[pos] < 0 ) {
1868 this->color[pos] = value;
1869 this->entry[pos] = pixel;
1870 } else if ( value < this->color[pos] ) {
1871
1872 if ( this->bottom > 0 ) {
1873 for ( i = this->bottom; i < pos; i++ ) {
1874 this->color[i-1] = this->color[i];
1875 this->entry[i-1] = this->entry[i];
1876 }
1877 this->bottom--;
1878 this->color[pos-1] = value;
1879 this->entry[pos-1] = pixel;
1880 } else if ( this->top < this->size-1 ) {
1881 for ( i = this->top; i >= pos; i-- ) {
1882 this->color[i+1] = this->color[i];
1883 this->entry[i+1] = this->entry[i];
1884 }
1885 this->top++;
1886 this->color[pos] = value;
1887 this->entry[pos] = pixel;
1888 }
1889
1890 } else {
1891
1892 if ( this->top < this->size-1 ) {
1893 for ( i = this->top; i > pos; i-- ) {
1894 this->color[i+1] = this->color[i];
1895 this->entry[i+1] = this->entry[i];
1896 }
1897 this->top++;
1898 this->color[pos+1] = value;
1899 this->entry[pos+1] = pixel;
1900 } else if ( this->bottom > 0 ) {
1901 for ( i = this->bottom; i < pos; i++ ) {
1902 this->color[i-1] = this->color[i];
1903 this->entry[i-1] = this->entry[i];
1904 }
1905 this->bottom--;
1906 this->color[pos] = value;
1907 this->entry[pos] = pixel;
1908 }
1909
1910 }
1911
1912 return( pixel );
1913}
1914
ee4c6942
JS
1915wxBitmap wxImage::ConvertToBitmap() const
1916{
b75867a6 1917 wxBitmap bitmap;
c7abc967 1918
223d09f6 1919 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
a91b47e8 1920
b75867a6
RR
1921 int width = GetWidth();
1922 int height = GetHeight();
c7abc967 1923
b75867a6
RR
1924 bitmap.SetHeight( height );
1925 bitmap.SetWidth( width );
c7abc967 1926
b75867a6
RR
1927 Display *dpy = (Display*) wxGetDisplay();
1928 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1929 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
c7abc967 1930
b75867a6 1931 // Create image
c7abc967 1932
b75867a6 1933 XImage *data_image = XCreateImage( dpy, vis, bpp, ZPixmap, 0, 0, width, height, 32, 0 );
a91b47e8 1934 data_image->data = (char*) malloc( data_image->bytes_per_line * data_image->height );
c7abc967 1935
b75867a6 1936 bitmap.Create( width, height, bpp );
a91b47e8 1937
dbda9e86 1938 /*
b75867a6 1939 // Create mask
c7abc967 1940
dbda9e86 1941 GdkImage *mask_image = (GdkImage*) NULL;
c7abc967 1942
dbda9e86
JS
1943 if (HasMask())
1944 {
b75867a6 1945 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
c7abc967 1946
dbda9e86 1947 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
c7abc967 1948
dbda9e86
JS
1949 wxMask *mask = new wxMask();
1950 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
c7abc967 1951
dbda9e86
JS
1952 bitmap.SetMask( mask );
1953 }
1954 */
c7abc967 1955
b75867a6 1956 // Retrieve depth info
c7abc967 1957
b75867a6
RR
1958 XVisualInfo vinfo_template;
1959 XVisualInfo *vi;
c7abc967 1960
b75867a6
RR
1961 vinfo_template.visual = vis;
1962 vinfo_template.visualid = XVisualIDFromVisual( vis );
1963 vinfo_template.depth = bpp;
1964 int nitem = 0;
c7abc967 1965
b75867a6 1966 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
c7abc967 1967
223d09f6 1968 wxCHECK_MSG( vi, wxNullBitmap, wxT("no visual") );
c7abc967 1969
38274997 1970 XFree( vi );
a91b47e8 1971
b75867a6
RR
1972 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1973 if (bpp < 8) bpp = 8;
c7abc967 1974
b75867a6 1975 // Render
c7abc967 1976
b75867a6
RR
1977 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1978 byte_order b_o = RGB;
c7abc967 1979
b75867a6
RR
1980 if (bpp >= 24)
1981 {
1982 if ((vi->red_mask > vi->green_mask) && (vi->green_mask > vi->blue_mask)) b_o = RGB;
1983 else if ((vi->red_mask > vi->blue_mask) && (vi->blue_mask > vi->green_mask)) b_o = RGB;
1984 else if ((vi->blue_mask > vi->red_mask) && (vi->red_mask > vi->green_mask)) b_o = BRG;
1985 else if ((vi->blue_mask > vi->green_mask) && (vi->green_mask > vi->red_mask)) b_o = BGR;
1986 else if ((vi->green_mask > vi->red_mask) && (vi->red_mask > vi->blue_mask)) b_o = GRB;
1987 else if ((vi->green_mask > vi->blue_mask) && (vi->blue_mask > vi->red_mask)) b_o = GBR;
1988 }
c7abc967 1989
dbda9e86 1990 /*
b75867a6
RR
1991 int r_mask = GetMaskRed();
1992 int g_mask = GetMaskGreen();
1993 int b_mask = GetMaskBlue();
dbda9e86 1994 */
c7abc967 1995
38274997
RR
1996 XColor colors[256];
1997 if (bpp == 8)
1998 {
dbda9e86 1999 Colormap cmap = (Colormap) wxTheApp->GetMainColormap( dpy );
c7abc967 2000
38274997 2001 for (int i = 0; i < 256; i++) colors[i].pixel = i;
dbda9e86 2002 XQueryColors( dpy, cmap, colors, 256 );
38274997 2003 }
c7abc967 2004
88195b2b 2005 wxSearchColor scolor( 256, colors );
b75867a6 2006 unsigned char* data = GetData();
c7abc967 2007
b75867a6
RR
2008 int index = 0;
2009 for (int y = 0; y < height; y++)
2010 {
2011 for (int x = 0; x < width; x++)
2012 {
2013 int r = data[index];
dbda9e86 2014 index++;
b75867a6 2015 int g = data[index];
dbda9e86 2016 index++;
b75867a6 2017 int b = data[index];
dbda9e86 2018 index++;
c7abc967 2019
dbda9e86
JS
2020 /*
2021 if (HasMask())
2022 {
2023 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
2024 gdk_image_put_pixel( mask_image, x, y, 1 );
2025 else
2026 gdk_image_put_pixel( mask_image, x, y, 0 );
2027 }
2028 */
c7abc967 2029
dbda9e86
JS
2030 switch (bpp)
2031 {
2032 case 8:
2033 {
88195b2b 2034#if 0 // Old, slower code
b75867a6 2035 int pixel = -1;
dbda9e86
JS
2036 /*
2037 if (wxTheApp->m_colorCube)
2038 {
2039 pixel = wxTheApp->m_colorCube
c7abc967
VZ
2040 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
2041 }
b75867a6 2042 else
dbda9e86
JS
2043 {
2044 */
2045 int max = 3 * (65536);
2046 for (int i = 0; i < 256; i++)
2047 {
2048 int rdiff = (r << 8) - colors[i].red;
2049 int gdiff = (g << 8) - colors[i].green;
2050 int bdiff = (b << 8) - colors[i].blue;
2051 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
2052 if (sum < max) { pixel = i; max = sum; }
2053 }
2054 /*
2055 }
2056 */
88195b2b
JS
2057#endif
2058
2059 // And this is all to get the 'right' color...
2060 int pixel = scolor.SearchColor( r, g, b );
dbda9e86
JS
2061 XPutPixel( data_image, x, y, pixel );
2062 break;
2063 }
2064 case 15:
2065 {
2066 int pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
2067 XPutPixel( data_image, x, y, pixel );
2068 break;
2069 }
2070 case 16:
2071 {
2072 int pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
2073 XPutPixel( data_image, x, y, pixel );
2074 break;
2075 }
2076 case 32:
2077 case 24:
2078 {
2079 int pixel = 0;
2080 switch (b_o)
2081 {
2082 case RGB: pixel = (r << 16) | (g << 8) | b; break;
2083 case RBG: pixel = (r << 16) | (b << 8) | g; break;
2084 case BRG: pixel = (b << 16) | (r << 8) | g; break;
2085 case BGR: pixel = (b << 16) | (g << 8) | r; break;
2086 case GRB: pixel = (g << 16) | (r << 8) | b; break;
2087 case GBR: pixel = (g << 16) | (b << 8) | r; break;
2088 }
2089 XPutPixel( data_image, x, y, pixel );
2090 }
2091 default: break;
2092 }
b75867a6
RR
2093 } // for
2094 } // for
c7abc967 2095
b75867a6 2096 // Blit picture
c7abc967 2097
b75867a6
RR
2098 XGCValues gcvalues;
2099 gcvalues.foreground = BlackPixel( dpy, DefaultScreen( dpy ) );
2100 GC gc = XCreateGC( dpy, RootWindow ( dpy, DefaultScreen(dpy) ), GCForeground, &gcvalues );
2101 XPutImage( dpy, (Drawable)bitmap.GetPixmap(), gc, data_image, 0, 0, 0, 0, width, height );
c7abc967 2102
b75867a6
RR
2103 XDestroyImage( data_image );
2104 XFreeGC( dpy, gc );
c7abc967 2105
dbda9e86 2106 /*
b75867a6 2107 // Blit mask
c7abc967 2108
dbda9e86
JS
2109 if (HasMask())
2110 {
2111 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
c7abc967 2112
b75867a6 2113 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
c7abc967 2114
dbda9e86
JS
2115 gdk_image_destroy( mask_image );
2116 gdk_gc_unref( mask_gc );
2117 }
2118 */
c7abc967 2119
b75867a6 2120 return bitmap;
ee4c6942
JS
2121}
2122
2123wxImage::wxImage( const wxBitmap &bitmap )
2124{
223d09f6 2125 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
c7abc967 2126
38274997
RR
2127 Display *dpy = (Display*) wxGetDisplay();
2128 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
2129 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
c7abc967 2130
38274997 2131 XImage *ximage = XGetImage( dpy,
dbda9e86
JS
2132 (Drawable)bitmap.GetPixmap(),
2133 0, 0,
2134 bitmap.GetWidth(), bitmap.GetHeight(),
2135 AllPlanes, ZPixmap );
c7abc967 2136
223d09f6 2137 wxCHECK_RET( ximage, wxT("couldn't create image") );
c7abc967 2138
38274997
RR
2139 Create( bitmap.GetWidth(), bitmap.GetHeight() );
2140 char unsigned *data = GetData();
c7abc967 2141
38274997
RR
2142 if (!data)
2143 {
2144 XDestroyImage( ximage );
223d09f6 2145 wxFAIL_MSG( wxT("couldn't create image") );
38274997
RR
2146 return;
2147 }
c7abc967 2148
dbda9e86 2149 /*
38274997
RR
2150 GdkImage *gdk_image_mask = (GdkImage*) NULL;
2151 if (bitmap.GetMask())
2152 {
dbda9e86
JS
2153 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
2154 0, 0,
2155 bitmap.GetWidth(), bitmap.GetHeight() );
c7abc967 2156
dbda9e86
JS
2157 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
2158 }
2159 */
c7abc967 2160
38274997 2161 // Retrieve depth info
c7abc967 2162
38274997
RR
2163 XVisualInfo vinfo_template;
2164 XVisualInfo *vi;
c7abc967 2165
38274997
RR
2166 vinfo_template.visual = vis;
2167 vinfo_template.visualid = XVisualIDFromVisual( vis );
2168 vinfo_template.depth = bpp;
2169 int nitem = 0;
c7abc967 2170
38274997 2171 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
c7abc967 2172
223d09f6 2173 wxCHECK_RET( vi, wxT("no visual") );
c7abc967 2174
38274997 2175 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
c7abc967 2176
38274997 2177 XFree( vi );
c7abc967 2178
38274997
RR
2179 XColor colors[256];
2180 if (bpp == 8)
2181 {
dbda9e86 2182 Colormap cmap = (Colormap)wxTheApp->GetMainColormap( dpy );
c7abc967 2183
38274997 2184 for (int i = 0; i < 256; i++) colors[i].pixel = i;
dbda9e86 2185 XQueryColors( dpy, cmap, colors, 256 );
38274997 2186 }
c7abc967 2187
38274997
RR
2188 long pos = 0;
2189 for (int j = 0; j < bitmap.GetHeight(); j++)
2190 {
2191 for (int i = 0; i < bitmap.GetWidth(); i++)
2192 {
dbda9e86 2193 int pixel = XGetPixel( ximage, i, j );
38274997
RR
2194 if (bpp <= 8)
2195 {
2196 data[pos] = colors[pixel].red >> 8;
2197 data[pos+1] = colors[pixel].green >> 8;
2198 data[pos+2] = colors[pixel].blue >> 8;
2199 } else if (bpp == 15)
2200 {
2201 data[pos] = (pixel >> 7) & 0xf8;
2202 data[pos+1] = (pixel >> 2) & 0xf8;
2203 data[pos+2] = (pixel << 3) & 0xf8;
2204 } else if (bpp == 16)
2205 {
2206 data[pos] = (pixel >> 8) & 0xf8;
2207 data[pos+1] = (pixel >> 3) & 0xfc;
2208 data[pos+2] = (pixel << 3) & 0xf8;
2209 } else
2210 {
2211 data[pos] = (pixel >> 16) & 0xff;
2212 data[pos+1] = (pixel >> 8) & 0xff;
2213 data[pos+2] = pixel & 0xff;
2214 }
c7abc967 2215
dbda9e86 2216 /*
38274997
RR
2217 if (gdk_image_mask)
2218 {
dbda9e86
JS
2219 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
2220 if (mask_pixel == 0)
2221 {
2222 data[pos] = 16;
2223 data[pos+1] = 16;
2224 data[pos+2] = 16;
38274997 2225 }
dbda9e86
JS
2226 }
2227 */
c7abc967 2228
38274997
RR
2229 pos += 3;
2230 }
2231 }
c7abc967 2232
38274997 2233 XDestroyImage( ximage );
dbda9e86 2234 /*
38274997 2235 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
dbda9e86 2236 */
ee4c6942
JS
2237}
2238#endif
a91b47e8 2239
004fd0c8
DW
2240#ifdef __WXPM__
2241// OS/2 Presentation manager conversion routings
2242
2243wxBitmap wxImage::ConvertToBitmap() const
2244{
2245 if ( !Ok() )
2246 return wxNullBitmap;
2247 wxBitmap bitmap; // remove
2248// TODO:
2249/*
2250 int sizeLimit = 1024*768*3;
2251
2252 // width and height of the device-dependent bitmap
2253 int width = GetWidth();
2254 int bmpHeight = GetHeight();
2255
2256 // calc the number of bytes per scanline and padding
2257 int bytePerLine = width*3;
2258 int sizeDWORD = sizeof( DWORD );
2259 int lineBoundary = bytePerLine % sizeDWORD;
2260 int padding = 0;
2261 if( lineBoundary > 0 )
2262 {
2263 padding = sizeDWORD - lineBoundary;
2264 bytePerLine += padding;
2265 }
2266 // calc the number of DIBs and heights of DIBs
2267 int numDIB = 1;
2268 int hRemain = 0;
2269 int height = sizeLimit/bytePerLine;
2270 if( height >= bmpHeight )
2271 height = bmpHeight;
2272 else
2273 {
2274 numDIB = bmpHeight / height;
2275 hRemain = bmpHeight % height;
2276 if( hRemain >0 ) numDIB++;
2277 }
2278
2279 // set bitmap parameters
2280 wxBitmap bitmap;
2281 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
2282 bitmap.SetWidth( width );
2283 bitmap.SetHeight( bmpHeight );
2284 bitmap.SetDepth( wxDisplayDepth() );
2285
2286 // create a DIB header
2287 int headersize = sizeof(BITMAPINFOHEADER);
2288 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
2289 wxCHECK_MSG( lpDIBh, bitmap, wxT("could not allocate memory for DIB header") );
2290 // Fill in the DIB header
2291 lpDIBh->bmiHeader.biSize = headersize;
2292 lpDIBh->bmiHeader.biWidth = (DWORD)width;
2293 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2294 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2295 // the general formula for biSizeImage:
2296 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
2297 lpDIBh->bmiHeader.biPlanes = 1;
2298 lpDIBh->bmiHeader.biBitCount = 24;
2299 lpDIBh->bmiHeader.biCompression = BI_RGB;
2300 lpDIBh->bmiHeader.biClrUsed = 0;
2301 // These seem not really needed for our purpose here.
2302 lpDIBh->bmiHeader.biClrImportant = 0;
2303 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2304 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2305 // memory for DIB data
2306 unsigned char *lpBits;
2307 lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
2308 if( !lpBits )
2309 {
2310 wxFAIL_MSG( wxT("could not allocate memory for DIB") );
2311 free( lpDIBh );
2312 return bitmap;
2313 }
2314
2315 // create and set the device-dependent bitmap
2316 HDC hdc = ::GetDC(NULL);
2317 HDC memdc = ::CreateCompatibleDC( hdc );
2318 HBITMAP hbitmap;
2319 hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
2320 ::SelectObject( memdc, hbitmap);
2321
2322 // copy image data into DIB data and then into DDB (in a loop)
2323 unsigned char *data = GetData();
2324 int i, j, n;
2325 int origin = 0;
2326 unsigned char *ptdata = data;
2327 unsigned char *ptbits;
2328
2329 for( n=0; n<numDIB; n++ )
2330 {
2331 if( numDIB > 1 && n == numDIB-1 && hRemain > 0 )
2332 {
2333 // redefine height and size of the (possibly) last smaller DIB
2334 // memory is not reallocated
2335 height = hRemain;
2336 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2337 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2338 }
2339 ptbits = lpBits;
2340
2341 for( j=0; j<height; j++ )
2342 {
2343 for( i=0; i<width; i++ )
2344 {
2345 *(ptbits++) = *(ptdata+2);
2346 *(ptbits++) = *(ptdata+1);
2347 *(ptbits++) = *(ptdata );
2348 ptdata += 3;
2349 }
2350 for( i=0; i< padding; i++ ) *(ptbits++) = 0;
2351 }
2352 ::StretchDIBits( memdc, 0, origin, width, height,\
2353 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2354 origin += height;
2355 // if numDIB = 1, lines below can also be used
2356 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
2357 // The above line is equivalent to the following two lines.
2358 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2359 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
2360 // or the following lines
2361 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2362 // HDC memdc = ::CreateCompatibleDC( hdc );
2363 // ::SelectObject( memdc, hbitmap);
2364 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
2365 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
2366 // ::SelectObject( memdc, 0 );
2367 // ::DeleteDC( memdc );
2368 }
2369 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
2370
2371 // similarly, created an mono-bitmap for the possible mask
2372 if( HasMask() )
2373 {
2374 hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL );
2375 ::SelectObject( memdc, hbitmap);
2376 if( numDIB == 1 ) height = bmpHeight;
2377 else height = sizeLimit/bytePerLine;
2378 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2379 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2380 origin = 0;
2381 unsigned char r = GetMaskRed();
2382 unsigned char g = GetMaskGreen();
2383 unsigned char b = GetMaskBlue();
2384 unsigned char zero = 0, one = 255;
2385 ptdata = data;
2386 for( n=0; n<numDIB; n++ )
2387 {
2388 if( numDIB > 1 && n == numDIB - 1 && hRemain > 0 )
2389 {
2390 // redefine height and size of the (possibly) last smaller DIB
2391 // memory is not reallocated
2392 height = hRemain;
2393 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2394 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2395 }
2396 ptbits = lpBits;
2397 for( int j=0; j<height; j++ )
2398 {
2399 for(i=0; i<width; i++ )
2400 {
2401 if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
2402 {
2403 *(ptbits++) = one;
2404 *(ptbits++) = one;
2405 *(ptbits++) = one;
2406 }
2407 else
2408 {
2409 *(ptbits++) = zero;
2410 *(ptbits++) = zero;
2411 *(ptbits++) = zero;
2412 }
2413 }
2414 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
2415 }
2416 ::StretchDIBits( memdc, 0, origin, width, height,\
2417 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2418 origin += height;
2419 }
2420 // create a wxMask object
2421 wxMask *mask = new wxMask();
2422 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
2423 bitmap.SetMask( mask );
2424 }
2425
2426 // free allocated resources
2427 ::SelectObject( memdc, 0 );
2428 ::DeleteDC( memdc );
2429 ::ReleaseDC(NULL, hdc);
2430 free(lpDIBh);
2431 free(lpBits);
2432
2433 // check the wxBitmap object
2434 if( bitmap.GetHBITMAP() )
2435 bitmap.SetOk( TRUE );
2436 else
2437 bitmap.SetOk( FALSE );
2438*/
2439 return bitmap;
2440}
2441
2442wxImage::wxImage( const wxBitmap &bitmap )
2443{
2444 // check the bitmap
2445 if( !bitmap.Ok() )
2446 {
2447 wxFAIL_MSG( wxT("invalid bitmap") );
2448 return;
2449 }
2450
2451 // create an wxImage object
2452 int width = bitmap.GetWidth();
2453 int height = bitmap.GetHeight();
2454 Create( width, height );
2455 unsigned char *data = GetData();
2456 if( !data )
2457 {
2458 wxFAIL_MSG( wxT("could not allocate data for image") );
2459 return;
2460 }
2461
2462 // calc the number of bytes per scanline and padding in the DIB
2463 int bytePerLine = width*3;
2464 int sizeDWORD = sizeof( DWORD );
2465 int lineBoundary = bytePerLine % sizeDWORD;
2466 int padding = 0;
2467 if( lineBoundary > 0 )
2468 {
2469 padding = sizeDWORD - lineBoundary;
2470 bytePerLine += padding;
2471 }
2472// TODO:
2473/*
2474 // create a DIB header
2475 int headersize = sizeof(BITMAPINFOHEADER);
2476 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
2477 if( !lpDIBh )
2478 {
2479 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
2480 free( data );
2481 return;
2482 }
2483 // Fill in the DIB header
2484 lpDIBh->bmiHeader.biSize = headersize;
2485 lpDIBh->bmiHeader.biWidth = width;
2486 lpDIBh->bmiHeader.biHeight = -height;
2487 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
2488 lpDIBh->bmiHeader.biPlanes = 1;
2489 lpDIBh->bmiHeader.biBitCount = 24;
2490 lpDIBh->bmiHeader.biCompression = BI_RGB;
2491 lpDIBh->bmiHeader.biClrUsed = 0;
2492 // These seem not really needed for our purpose here.
2493 lpDIBh->bmiHeader.biClrImportant = 0;
2494 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2495 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2496 // memory for DIB data
2497 unsigned char *lpBits;
2498 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
2499 if( !lpBits )
2500 {
2501 wxFAIL_MSG( wxT("could not allocate data for DIB") );
2502 free( data );
2503 free( lpDIBh );
2504 return;
2505 }
2506
2507 // copy data from the device-dependent bitmap to the DIB
2508 HDC hdc = ::GetDC(NULL);
2509 HBITMAP hbitmap;
2510 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
2511 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2512
2513 // copy DIB data into the wxImage object
2514 int i, j;
2515 unsigned char *ptdata = data;
2516 unsigned char *ptbits = lpBits;
2517 for( i=0; i<height; i++ )
2518 {
2519 for( j=0; j<width; j++ )
2520 {
2521 *(ptdata++) = *(ptbits+2);
2522 *(ptdata++) = *(ptbits+1);
2523 *(ptdata++) = *(ptbits );
2524 ptbits += 3;
2525 }
2526 ptbits += padding;
2527 }
2528
2529 // similarly, set data according to the possible mask bitmap
2530 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
2531 {
2532 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
2533 // memory DC created, color set, data copied, and memory DC deleted
2534 HDC memdc = ::CreateCompatibleDC( hdc );
2535 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
2536 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
2537 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2538 ::DeleteDC( memdc );
2539 // background color set to RGB(16,16,16) in consistent with wxGTK
2540 unsigned char r=16, g=16, b=16;
2541 ptdata = data;
2542 ptbits = lpBits;
2543 for( i=0; i<height; i++ )
2544 {
2545 for( j=0; j<width; j++ )
2546 {
2547 if( *ptbits != 0 )
2548 ptdata += 3;
2549 else
2550 {
2551 *(ptdata++) = r;
2552 *(ptdata++) = g;
2553 *(ptdata++) = b;
2554 }
2555 ptbits += 3;
2556 }
2557 ptbits += padding;
2558 }
2559 SetMaskColour( r, g, b );
2560 SetMask( TRUE );
2561 }
2562 else
2563 {
2564 SetMask( FALSE );
2565 }
2566 // free allocated resources
2567 ::ReleaseDC(NULL, hdc);
2568 free(lpDIBh);
2569 free(lpBits);
2570*/
2571}
2572
2573#endif
2574
a91b47e8
JS
2575// A module to allow wxImage initialization/cleanup
2576// without calling these functions from app.cpp or from
2577// the user's application.
2578
2579class wxImageModule: public wxModule
2580{
2581DECLARE_DYNAMIC_CLASS(wxImageModule)
2582public:
2583 wxImageModule() {}
2584 bool OnInit() { wxImage::InitStandardHandlers(); return TRUE; };
2585 void OnExit() { wxImage::CleanUpHandlers(); };
2586};
2587
2588IMPLEMENT_DYNAMIC_CLASS(wxImageModule, wxModule)
c9d01afd
GRG
2589
2590
2591//-----------------------------------------------------------------------------
2592
89d00456
GRG
2593// GRG, Dic/99
2594// Counts and returns the number of different colours. Optionally stops
cc9f7d79
GRG
2595// when it exceeds 'stopafter' different colours. This is useful, for
2596// example, to see if the image can be saved as 8-bit (256 colour or
2597// less, in this case it would be invoked as CountColours(256)). Default
2598// value for stopafter is -1 (don't care).
89d00456 2599//
cc9f7d79 2600unsigned long wxImage::CountColours( unsigned long stopafter )
89d00456
GRG
2601{
2602 wxHashTable h;
2603 wxNode *node;
2604 wxHNode *hnode;
2605 unsigned char r, g, b, *p;
2606 unsigned long size, nentries, key;
2607
2608 p = GetData();
2609 size = GetWidth() * GetHeight();
2610 nentries = 0;
2611
cc9f7d79 2612 for (unsigned long j = 0; (j < size) && (nentries <= stopafter) ; j++)
89d00456
GRG
2613 {
2614 r = *(p++);
2615 g = *(p++);
2616 b = *(p++);
2617 key = (r << 16) | (g << 8) | b;
2618
2619 hnode = (wxHNode *) h.Get(key);
2620
2621 if (!hnode)
2622 {
2623 h.Put(key, (wxObject *)(new wxHNode));
2624 nentries++;
2625 }
2626 }
2627
2628 // delete all HNodes
2629 h.BeginFind();
2630 while ((node = h.Next()) != NULL)
2631 delete (wxHNode *)node->GetData();
2632
2633 return nentries;
2634}
2635
2636
c9d01afd
GRG
2637// GRG, Dic/99
2638// Computes the histogram of the image and fills a hash table, indexed
2639// with integer keys built as 0xRRGGBB, containing wxHNode objects. Each
2640// wxHNode contains an 'index' (useful to build a palette with the image
2641// colours) and a 'value', which is the number of pixels in the image with
2642// that colour.
89d00456 2643//
c9d01afd
GRG
2644unsigned long wxImage::ComputeHistogram( wxHashTable &h )
2645{
2646 unsigned char r, g, b, *p;
2647 unsigned long size, nentries, key;
2648 wxHNode *hnode;
2649
2650 p = GetData();
2651 size = GetWidth() * GetHeight();
2652 nentries = 0;
2653
2654 for (unsigned long j = 0; j < size; j++)
2655 {
2656 r = *(p++);
2657 g = *(p++);
2658 b = *(p++);
2659 key = (r << 16) | (g << 8) | b;
2660
2661 hnode = (wxHNode *) h.Get(key);
2662
2663 if (hnode)
2664 hnode->value++;
2665 else
2666 {
2667 hnode = new wxHNode();
97fdfcc9 2668 hnode->index = nentries++;
c9d01afd
GRG
2669 hnode->value = 1;
2670
2671 h.Put(key, (wxObject *)hnode);
2672 }
2673 }
2674
2675 return nentries;
2676}
2677
2678