]> git.saurik.com Git - wxWidgets.git/blame - src/common/image.cpp
1. more warnings fixes in gtk/region.cpp and common/tbarsmpl.cpp
[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
88195b2b
JS
1673/*
1674
1675Date: Wed, 05 Jan 2000 11:45:40 +0100
1676From: Frits Boel <boel@niob.knaw.nl>
1677To: julian.smart@ukonline.co.uk
1678Subject: Patch for Motif ConvertToBitmap
1679
1680Hi Julian,
1681
1682I've been working on a wxWin application for image processing. From the
1683beginning, I was surprised by the (lack of) speed of ConvertToBitmap,
1684till I looked in the source code of image.cpp. I saw that converting a
1685wxImage to a bitmap with 8-bit pixels is done with comparing every pixel
1686to the 256 colors of the palet. A very time-consuming piece of code!
1687
1688Because I wanted a faster application, I've made a 'patch' for this. In
1689short: every pixel of the image is compared to a sorted list with
1690colors. If the color is found in the list, the palette entry is
1691returned; if the color is not found, the color palette is searched and
1692then the palette entry is returned and the color added to the sorted
1693list.
1694
1695Maybe there is another method for this, namely changing the palette
1696itself (if the colors are known, as is the case with tiffs with a
1697colormap). I did not look at this, maybe someone else did?
1698
1699The code of the patch is attached, have a look on it, and maybe you will
1700ship it with the next release of wxMotif?
1701
1702Regards,
1703
1704Frits Boel
1705Software engineer at Hubrecht Laboratory, The Netherlands.
1706
1707*/
1708
1709class wxSearchColor
1710{
1711public:
1712 wxSearchColor( void );
1713 wxSearchColor( int size, XColor *colors );
1714 ~wxSearchColor( void );
1715
1716 int SearchColor( int r, int g, int b );
1717private:
1718 int AddColor( unsigned int value, int pos );
1719
1720 int size;
1721 XColor *colors;
1722 unsigned int *color;
1723 int *entry;
1724
1725 int bottom;
1726 int top;
1727};
1728
1729wxSearchColor::wxSearchColor( void )
1730{
1731 this->size = 0;
1732 this->colors = (XColor*) NULL;
1733 this->color = (unsigned int *) NULL;
1734 this->entry = (int*) NULL;
1735
1736 this->bottom = 0;
1737 this->top = 0;
1738}
1739
1740wxSearchColor::wxSearchColor( int size, XColor *colors )
1741{
1742 int i;
1743 this->size = size;
1744 this->colors = colors;
1745 this->color = new unsigned int[size];
1746 this->entry = new int [size];
1747
1748 for (i = 0; i < this->size; i++ ) {
1749 this->entry[i] = -1;
1750 }
1751
1752 this->bottom = this->top = ( size >> 1 );
1753}
1754
1755wxSearchColor::~wxSearchColor( void )
1756{
1757 if ( this->color ) delete this->color;
1758 if ( this->entry ) delete this->entry;
1759}
1760
1761int wxSearchColor::SearchColor( int r, int g, int b )
1762{
1763 unsigned int value = ( ( ( r * 256 ) + g ) * 256 ) + b;
1764 int begin = this->bottom;
1765 int end = this->top;
1766 int middle;
1767
1768 while ( begin <= end ) {
1769
1770 middle = ( begin + end ) >> 1;
1771
1772 if ( value == this->color[middle] ) {
1773 return( this->entry[middle] );
1774 } else if ( value < this->color[middle] ) {
1775 end = middle - 1;
1776 } else {
1777 begin = middle + 1;
1778 }
1779
1780 }
1781
1782 return AddColor( value, middle );
1783}
1784
1785int wxSearchColor::AddColor( unsigned int value, int pos )
1786{
1787 int i;
1788 int pixel = -1;
1789 int max = 3 * (65536);
1790 for ( i = 0; i < 256; i++ ) {
1791 int rdiff = ((value >> 8) & 0xFF00 ) - colors[i].red;
1792 int gdiff = ((value ) & 0xFF00 ) - colors[i].green;
1793 int bdiff = ((value << 8) & 0xFF00 ) - colors[i].blue;
1794 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1795 if (sum < max) { pixel = i; max = sum; }
1796 }
1797
1798 if ( this->entry[pos] < 0 ) {
1799 this->color[pos] = value;
1800 this->entry[pos] = pixel;
1801 } else if ( value < this->color[pos] ) {
1802
1803 if ( this->bottom > 0 ) {
1804 for ( i = this->bottom; i < pos; i++ ) {
1805 this->color[i-1] = this->color[i];
1806 this->entry[i-1] = this->entry[i];
1807 }
1808 this->bottom--;
1809 this->color[pos-1] = value;
1810 this->entry[pos-1] = pixel;
1811 } else if ( this->top < this->size-1 ) {
1812 for ( i = this->top; i >= pos; i-- ) {
1813 this->color[i+1] = this->color[i];
1814 this->entry[i+1] = this->entry[i];
1815 }
1816 this->top++;
1817 this->color[pos] = value;
1818 this->entry[pos] = pixel;
1819 }
1820
1821 } else {
1822
1823 if ( this->top < this->size-1 ) {
1824 for ( i = this->top; i > pos; i-- ) {
1825 this->color[i+1] = this->color[i];
1826 this->entry[i+1] = this->entry[i];
1827 }
1828 this->top++;
1829 this->color[pos+1] = value;
1830 this->entry[pos+1] = pixel;
1831 } else if ( this->bottom > 0 ) {
1832 for ( i = this->bottom; i < pos; i++ ) {
1833 this->color[i-1] = this->color[i];
1834 this->entry[i-1] = this->entry[i];
1835 }
1836 this->bottom--;
1837 this->color[pos] = value;
1838 this->entry[pos] = pixel;
1839 }
1840
1841 }
1842
1843 return( pixel );
1844}
1845
ee4c6942
JS
1846wxBitmap wxImage::ConvertToBitmap() const
1847{
b75867a6 1848 wxBitmap bitmap;
c7abc967 1849
223d09f6 1850 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
a91b47e8 1851
b75867a6
RR
1852 int width = GetWidth();
1853 int height = GetHeight();
c7abc967 1854
b75867a6
RR
1855 bitmap.SetHeight( height );
1856 bitmap.SetWidth( width );
c7abc967 1857
b75867a6
RR
1858 Display *dpy = (Display*) wxGetDisplay();
1859 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1860 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
c7abc967 1861
b75867a6 1862 // Create image
c7abc967 1863
b75867a6 1864 XImage *data_image = XCreateImage( dpy, vis, bpp, ZPixmap, 0, 0, width, height, 32, 0 );
a91b47e8 1865 data_image->data = (char*) malloc( data_image->bytes_per_line * data_image->height );
c7abc967 1866
b75867a6 1867 bitmap.Create( width, height, bpp );
a91b47e8 1868
dbda9e86 1869 /*
b75867a6 1870 // Create mask
c7abc967 1871
dbda9e86 1872 GdkImage *mask_image = (GdkImage*) NULL;
c7abc967 1873
dbda9e86
JS
1874 if (HasMask())
1875 {
b75867a6 1876 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
c7abc967 1877
dbda9e86 1878 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
c7abc967 1879
dbda9e86
JS
1880 wxMask *mask = new wxMask();
1881 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
c7abc967 1882
dbda9e86
JS
1883 bitmap.SetMask( mask );
1884 }
1885 */
c7abc967 1886
b75867a6 1887 // Retrieve depth info
c7abc967 1888
b75867a6
RR
1889 XVisualInfo vinfo_template;
1890 XVisualInfo *vi;
c7abc967 1891
b75867a6
RR
1892 vinfo_template.visual = vis;
1893 vinfo_template.visualid = XVisualIDFromVisual( vis );
1894 vinfo_template.depth = bpp;
1895 int nitem = 0;
c7abc967 1896
b75867a6 1897 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
c7abc967 1898
223d09f6 1899 wxCHECK_MSG( vi, wxNullBitmap, wxT("no visual") );
c7abc967 1900
38274997 1901 XFree( vi );
a91b47e8 1902
b75867a6
RR
1903 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1904 if (bpp < 8) bpp = 8;
c7abc967 1905
b75867a6 1906 // Render
c7abc967 1907
b75867a6
RR
1908 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1909 byte_order b_o = RGB;
c7abc967 1910
b75867a6
RR
1911 if (bpp >= 24)
1912 {
1913 if ((vi->red_mask > vi->green_mask) && (vi->green_mask > vi->blue_mask)) b_o = RGB;
1914 else if ((vi->red_mask > vi->blue_mask) && (vi->blue_mask > vi->green_mask)) b_o = RGB;
1915 else if ((vi->blue_mask > vi->red_mask) && (vi->red_mask > vi->green_mask)) b_o = BRG;
1916 else if ((vi->blue_mask > vi->green_mask) && (vi->green_mask > vi->red_mask)) b_o = BGR;
1917 else if ((vi->green_mask > vi->red_mask) && (vi->red_mask > vi->blue_mask)) b_o = GRB;
1918 else if ((vi->green_mask > vi->blue_mask) && (vi->blue_mask > vi->red_mask)) b_o = GBR;
1919 }
c7abc967 1920
dbda9e86 1921 /*
b75867a6
RR
1922 int r_mask = GetMaskRed();
1923 int g_mask = GetMaskGreen();
1924 int b_mask = GetMaskBlue();
dbda9e86 1925 */
c7abc967 1926
38274997
RR
1927 XColor colors[256];
1928 if (bpp == 8)
1929 {
dbda9e86 1930 Colormap cmap = (Colormap) wxTheApp->GetMainColormap( dpy );
c7abc967 1931
38274997 1932 for (int i = 0; i < 256; i++) colors[i].pixel = i;
dbda9e86 1933 XQueryColors( dpy, cmap, colors, 256 );
38274997 1934 }
c7abc967 1935
88195b2b 1936 wxSearchColor scolor( 256, colors );
b75867a6 1937 unsigned char* data = GetData();
c7abc967 1938
b75867a6
RR
1939 int index = 0;
1940 for (int y = 0; y < height; y++)
1941 {
1942 for (int x = 0; x < width; x++)
1943 {
1944 int r = data[index];
dbda9e86 1945 index++;
b75867a6 1946 int g = data[index];
dbda9e86 1947 index++;
b75867a6 1948 int b = data[index];
dbda9e86 1949 index++;
c7abc967 1950
dbda9e86
JS
1951 /*
1952 if (HasMask())
1953 {
1954 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1955 gdk_image_put_pixel( mask_image, x, y, 1 );
1956 else
1957 gdk_image_put_pixel( mask_image, x, y, 0 );
1958 }
1959 */
c7abc967 1960
dbda9e86
JS
1961 switch (bpp)
1962 {
1963 case 8:
1964 {
88195b2b 1965#if 0 // Old, slower code
b75867a6 1966 int pixel = -1;
dbda9e86
JS
1967 /*
1968 if (wxTheApp->m_colorCube)
1969 {
1970 pixel = wxTheApp->m_colorCube
c7abc967
VZ
1971 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1972 }
b75867a6 1973 else
dbda9e86
JS
1974 {
1975 */
1976 int max = 3 * (65536);
1977 for (int i = 0; i < 256; i++)
1978 {
1979 int rdiff = (r << 8) - colors[i].red;
1980 int gdiff = (g << 8) - colors[i].green;
1981 int bdiff = (b << 8) - colors[i].blue;
1982 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1983 if (sum < max) { pixel = i; max = sum; }
1984 }
1985 /*
1986 }
1987 */
88195b2b
JS
1988#endif
1989
1990 // And this is all to get the 'right' color...
1991 int pixel = scolor.SearchColor( r, g, b );
dbda9e86
JS
1992 XPutPixel( data_image, x, y, pixel );
1993 break;
1994 }
1995 case 15:
1996 {
1997 int pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1998 XPutPixel( data_image, x, y, pixel );
1999 break;
2000 }
2001 case 16:
2002 {
2003 int pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
2004 XPutPixel( data_image, x, y, pixel );
2005 break;
2006 }
2007 case 32:
2008 case 24:
2009 {
2010 int pixel = 0;
2011 switch (b_o)
2012 {
2013 case RGB: pixel = (r << 16) | (g << 8) | b; break;
2014 case RBG: pixel = (r << 16) | (b << 8) | g; break;
2015 case BRG: pixel = (b << 16) | (r << 8) | g; break;
2016 case BGR: pixel = (b << 16) | (g << 8) | r; break;
2017 case GRB: pixel = (g << 16) | (r << 8) | b; break;
2018 case GBR: pixel = (g << 16) | (b << 8) | r; break;
2019 }
2020 XPutPixel( data_image, x, y, pixel );
2021 }
2022 default: break;
2023 }
b75867a6
RR
2024 } // for
2025 } // for
c7abc967 2026
b75867a6 2027 // Blit picture
c7abc967 2028
b75867a6
RR
2029 XGCValues gcvalues;
2030 gcvalues.foreground = BlackPixel( dpy, DefaultScreen( dpy ) );
2031 GC gc = XCreateGC( dpy, RootWindow ( dpy, DefaultScreen(dpy) ), GCForeground, &gcvalues );
2032 XPutImage( dpy, (Drawable)bitmap.GetPixmap(), gc, data_image, 0, 0, 0, 0, width, height );
c7abc967 2033
b75867a6
RR
2034 XDestroyImage( data_image );
2035 XFreeGC( dpy, gc );
c7abc967 2036
dbda9e86 2037 /*
b75867a6 2038 // Blit mask
c7abc967 2039
dbda9e86
JS
2040 if (HasMask())
2041 {
2042 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
c7abc967 2043
b75867a6 2044 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
c7abc967 2045
dbda9e86
JS
2046 gdk_image_destroy( mask_image );
2047 gdk_gc_unref( mask_gc );
2048 }
2049 */
c7abc967 2050
b75867a6 2051 return bitmap;
ee4c6942
JS
2052}
2053
2054wxImage::wxImage( const wxBitmap &bitmap )
2055{
223d09f6 2056 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
c7abc967 2057
38274997
RR
2058 Display *dpy = (Display*) wxGetDisplay();
2059 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
2060 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
c7abc967 2061
38274997 2062 XImage *ximage = XGetImage( dpy,
dbda9e86
JS
2063 (Drawable)bitmap.GetPixmap(),
2064 0, 0,
2065 bitmap.GetWidth(), bitmap.GetHeight(),
2066 AllPlanes, ZPixmap );
c7abc967 2067
223d09f6 2068 wxCHECK_RET( ximage, wxT("couldn't create image") );
c7abc967 2069
38274997
RR
2070 Create( bitmap.GetWidth(), bitmap.GetHeight() );
2071 char unsigned *data = GetData();
c7abc967 2072
38274997
RR
2073 if (!data)
2074 {
2075 XDestroyImage( ximage );
223d09f6 2076 wxFAIL_MSG( wxT("couldn't create image") );
38274997
RR
2077 return;
2078 }
c7abc967 2079
dbda9e86 2080 /*
38274997
RR
2081 GdkImage *gdk_image_mask = (GdkImage*) NULL;
2082 if (bitmap.GetMask())
2083 {
dbda9e86
JS
2084 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
2085 0, 0,
2086 bitmap.GetWidth(), bitmap.GetHeight() );
c7abc967 2087
dbda9e86
JS
2088 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
2089 }
2090 */
c7abc967 2091
38274997 2092 // Retrieve depth info
c7abc967 2093
38274997
RR
2094 XVisualInfo vinfo_template;
2095 XVisualInfo *vi;
c7abc967 2096
38274997
RR
2097 vinfo_template.visual = vis;
2098 vinfo_template.visualid = XVisualIDFromVisual( vis );
2099 vinfo_template.depth = bpp;
2100 int nitem = 0;
c7abc967 2101
38274997 2102 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
c7abc967 2103
223d09f6 2104 wxCHECK_RET( vi, wxT("no visual") );
c7abc967 2105
38274997 2106 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
c7abc967 2107
38274997 2108 XFree( vi );
c7abc967 2109
38274997
RR
2110 XColor colors[256];
2111 if (bpp == 8)
2112 {
dbda9e86 2113 Colormap cmap = (Colormap)wxTheApp->GetMainColormap( dpy );
c7abc967 2114
38274997 2115 for (int i = 0; i < 256; i++) colors[i].pixel = i;
dbda9e86 2116 XQueryColors( dpy, cmap, colors, 256 );
38274997 2117 }
c7abc967 2118
38274997
RR
2119 long pos = 0;
2120 for (int j = 0; j < bitmap.GetHeight(); j++)
2121 {
2122 for (int i = 0; i < bitmap.GetWidth(); i++)
2123 {
dbda9e86 2124 int pixel = XGetPixel( ximage, i, j );
38274997
RR
2125 if (bpp <= 8)
2126 {
2127 data[pos] = colors[pixel].red >> 8;
2128 data[pos+1] = colors[pixel].green >> 8;
2129 data[pos+2] = colors[pixel].blue >> 8;
2130 } else if (bpp == 15)
2131 {
2132 data[pos] = (pixel >> 7) & 0xf8;
2133 data[pos+1] = (pixel >> 2) & 0xf8;
2134 data[pos+2] = (pixel << 3) & 0xf8;
2135 } else if (bpp == 16)
2136 {
2137 data[pos] = (pixel >> 8) & 0xf8;
2138 data[pos+1] = (pixel >> 3) & 0xfc;
2139 data[pos+2] = (pixel << 3) & 0xf8;
2140 } else
2141 {
2142 data[pos] = (pixel >> 16) & 0xff;
2143 data[pos+1] = (pixel >> 8) & 0xff;
2144 data[pos+2] = pixel & 0xff;
2145 }
c7abc967 2146
dbda9e86 2147 /*
38274997
RR
2148 if (gdk_image_mask)
2149 {
dbda9e86
JS
2150 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
2151 if (mask_pixel == 0)
2152 {
2153 data[pos] = 16;
2154 data[pos+1] = 16;
2155 data[pos+2] = 16;
38274997 2156 }
dbda9e86
JS
2157 }
2158 */
c7abc967 2159
38274997
RR
2160 pos += 3;
2161 }
2162 }
c7abc967 2163
38274997 2164 XDestroyImage( ximage );
dbda9e86 2165 /*
38274997 2166 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
dbda9e86 2167 */
ee4c6942
JS
2168}
2169#endif
a91b47e8 2170
004fd0c8
DW
2171#ifdef __WXPM__
2172// OS/2 Presentation manager conversion routings
2173
2174wxBitmap wxImage::ConvertToBitmap() const
2175{
2176 if ( !Ok() )
2177 return wxNullBitmap;
2178 wxBitmap bitmap; // remove
2179// TODO:
2180/*
2181 int sizeLimit = 1024*768*3;
2182
2183 // width and height of the device-dependent bitmap
2184 int width = GetWidth();
2185 int bmpHeight = GetHeight();
2186
2187 // calc the number of bytes per scanline and padding
2188 int bytePerLine = width*3;
2189 int sizeDWORD = sizeof( DWORD );
2190 int lineBoundary = bytePerLine % sizeDWORD;
2191 int padding = 0;
2192 if( lineBoundary > 0 )
2193 {
2194 padding = sizeDWORD - lineBoundary;
2195 bytePerLine += padding;
2196 }
2197 // calc the number of DIBs and heights of DIBs
2198 int numDIB = 1;
2199 int hRemain = 0;
2200 int height = sizeLimit/bytePerLine;
2201 if( height >= bmpHeight )
2202 height = bmpHeight;
2203 else
2204 {
2205 numDIB = bmpHeight / height;
2206 hRemain = bmpHeight % height;
2207 if( hRemain >0 ) numDIB++;
2208 }
2209
2210 // set bitmap parameters
2211 wxBitmap bitmap;
2212 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
2213 bitmap.SetWidth( width );
2214 bitmap.SetHeight( bmpHeight );
2215 bitmap.SetDepth( wxDisplayDepth() );
2216
2217 // create a DIB header
2218 int headersize = sizeof(BITMAPINFOHEADER);
2219 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
2220 wxCHECK_MSG( lpDIBh, bitmap, wxT("could not allocate memory for DIB header") );
2221 // Fill in the DIB header
2222 lpDIBh->bmiHeader.biSize = headersize;
2223 lpDIBh->bmiHeader.biWidth = (DWORD)width;
2224 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2225 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2226 // the general formula for biSizeImage:
2227 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
2228 lpDIBh->bmiHeader.biPlanes = 1;
2229 lpDIBh->bmiHeader.biBitCount = 24;
2230 lpDIBh->bmiHeader.biCompression = BI_RGB;
2231 lpDIBh->bmiHeader.biClrUsed = 0;
2232 // These seem not really needed for our purpose here.
2233 lpDIBh->bmiHeader.biClrImportant = 0;
2234 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2235 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2236 // memory for DIB data
2237 unsigned char *lpBits;
2238 lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
2239 if( !lpBits )
2240 {
2241 wxFAIL_MSG( wxT("could not allocate memory for DIB") );
2242 free( lpDIBh );
2243 return bitmap;
2244 }
2245
2246 // create and set the device-dependent bitmap
2247 HDC hdc = ::GetDC(NULL);
2248 HDC memdc = ::CreateCompatibleDC( hdc );
2249 HBITMAP hbitmap;
2250 hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
2251 ::SelectObject( memdc, hbitmap);
2252
2253 // copy image data into DIB data and then into DDB (in a loop)
2254 unsigned char *data = GetData();
2255 int i, j, n;
2256 int origin = 0;
2257 unsigned char *ptdata = data;
2258 unsigned char *ptbits;
2259
2260 for( n=0; n<numDIB; n++ )
2261 {
2262 if( numDIB > 1 && n == numDIB-1 && hRemain > 0 )
2263 {
2264 // redefine height and size of the (possibly) last smaller DIB
2265 // memory is not reallocated
2266 height = hRemain;
2267 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2268 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2269 }
2270 ptbits = lpBits;
2271
2272 for( j=0; j<height; j++ )
2273 {
2274 for( i=0; i<width; i++ )
2275 {
2276 *(ptbits++) = *(ptdata+2);
2277 *(ptbits++) = *(ptdata+1);
2278 *(ptbits++) = *(ptdata );
2279 ptdata += 3;
2280 }
2281 for( i=0; i< padding; i++ ) *(ptbits++) = 0;
2282 }
2283 ::StretchDIBits( memdc, 0, origin, width, height,\
2284 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2285 origin += height;
2286 // if numDIB = 1, lines below can also be used
2287 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
2288 // The above line is equivalent to the following two lines.
2289 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2290 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
2291 // or the following lines
2292 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2293 // HDC memdc = ::CreateCompatibleDC( hdc );
2294 // ::SelectObject( memdc, hbitmap);
2295 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
2296 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
2297 // ::SelectObject( memdc, 0 );
2298 // ::DeleteDC( memdc );
2299 }
2300 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
2301
2302 // similarly, created an mono-bitmap for the possible mask
2303 if( HasMask() )
2304 {
2305 hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL );
2306 ::SelectObject( memdc, hbitmap);
2307 if( numDIB == 1 ) height = bmpHeight;
2308 else height = sizeLimit/bytePerLine;
2309 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2310 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2311 origin = 0;
2312 unsigned char r = GetMaskRed();
2313 unsigned char g = GetMaskGreen();
2314 unsigned char b = GetMaskBlue();
2315 unsigned char zero = 0, one = 255;
2316 ptdata = data;
2317 for( n=0; n<numDIB; n++ )
2318 {
2319 if( numDIB > 1 && n == numDIB - 1 && hRemain > 0 )
2320 {
2321 // redefine height and size of the (possibly) last smaller DIB
2322 // memory is not reallocated
2323 height = hRemain;
2324 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2325 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2326 }
2327 ptbits = lpBits;
2328 for( int j=0; j<height; j++ )
2329 {
2330 for(i=0; i<width; i++ )
2331 {
2332 if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
2333 {
2334 *(ptbits++) = one;
2335 *(ptbits++) = one;
2336 *(ptbits++) = one;
2337 }
2338 else
2339 {
2340 *(ptbits++) = zero;
2341 *(ptbits++) = zero;
2342 *(ptbits++) = zero;
2343 }
2344 }
2345 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
2346 }
2347 ::StretchDIBits( memdc, 0, origin, width, height,\
2348 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2349 origin += height;
2350 }
2351 // create a wxMask object
2352 wxMask *mask = new wxMask();
2353 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
2354 bitmap.SetMask( mask );
2355 }
2356
2357 // free allocated resources
2358 ::SelectObject( memdc, 0 );
2359 ::DeleteDC( memdc );
2360 ::ReleaseDC(NULL, hdc);
2361 free(lpDIBh);
2362 free(lpBits);
2363
2364 // check the wxBitmap object
2365 if( bitmap.GetHBITMAP() )
2366 bitmap.SetOk( TRUE );
2367 else
2368 bitmap.SetOk( FALSE );
2369*/
2370 return bitmap;
2371}
2372
2373wxImage::wxImage( const wxBitmap &bitmap )
2374{
2375 // check the bitmap
2376 if( !bitmap.Ok() )
2377 {
2378 wxFAIL_MSG( wxT("invalid bitmap") );
2379 return;
2380 }
2381
2382 // create an wxImage object
2383 int width = bitmap.GetWidth();
2384 int height = bitmap.GetHeight();
2385 Create( width, height );
2386 unsigned char *data = GetData();
2387 if( !data )
2388 {
2389 wxFAIL_MSG( wxT("could not allocate data for image") );
2390 return;
2391 }
2392
2393 // calc the number of bytes per scanline and padding in the DIB
2394 int bytePerLine = width*3;
2395 int sizeDWORD = sizeof( DWORD );
2396 int lineBoundary = bytePerLine % sizeDWORD;
2397 int padding = 0;
2398 if( lineBoundary > 0 )
2399 {
2400 padding = sizeDWORD - lineBoundary;
2401 bytePerLine += padding;
2402 }
2403// TODO:
2404/*
2405 // create a DIB header
2406 int headersize = sizeof(BITMAPINFOHEADER);
2407 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
2408 if( !lpDIBh )
2409 {
2410 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
2411 free( data );
2412 return;
2413 }
2414 // Fill in the DIB header
2415 lpDIBh->bmiHeader.biSize = headersize;
2416 lpDIBh->bmiHeader.biWidth = width;
2417 lpDIBh->bmiHeader.biHeight = -height;
2418 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
2419 lpDIBh->bmiHeader.biPlanes = 1;
2420 lpDIBh->bmiHeader.biBitCount = 24;
2421 lpDIBh->bmiHeader.biCompression = BI_RGB;
2422 lpDIBh->bmiHeader.biClrUsed = 0;
2423 // These seem not really needed for our purpose here.
2424 lpDIBh->bmiHeader.biClrImportant = 0;
2425 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2426 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2427 // memory for DIB data
2428 unsigned char *lpBits;
2429 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
2430 if( !lpBits )
2431 {
2432 wxFAIL_MSG( wxT("could not allocate data for DIB") );
2433 free( data );
2434 free( lpDIBh );
2435 return;
2436 }
2437
2438 // copy data from the device-dependent bitmap to the DIB
2439 HDC hdc = ::GetDC(NULL);
2440 HBITMAP hbitmap;
2441 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
2442 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2443
2444 // copy DIB data into the wxImage object
2445 int i, j;
2446 unsigned char *ptdata = data;
2447 unsigned char *ptbits = lpBits;
2448 for( i=0; i<height; i++ )
2449 {
2450 for( j=0; j<width; j++ )
2451 {
2452 *(ptdata++) = *(ptbits+2);
2453 *(ptdata++) = *(ptbits+1);
2454 *(ptdata++) = *(ptbits );
2455 ptbits += 3;
2456 }
2457 ptbits += padding;
2458 }
2459
2460 // similarly, set data according to the possible mask bitmap
2461 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
2462 {
2463 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
2464 // memory DC created, color set, data copied, and memory DC deleted
2465 HDC memdc = ::CreateCompatibleDC( hdc );
2466 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
2467 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
2468 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2469 ::DeleteDC( memdc );
2470 // background color set to RGB(16,16,16) in consistent with wxGTK
2471 unsigned char r=16, g=16, b=16;
2472 ptdata = data;
2473 ptbits = lpBits;
2474 for( i=0; i<height; i++ )
2475 {
2476 for( j=0; j<width; j++ )
2477 {
2478 if( *ptbits != 0 )
2479 ptdata += 3;
2480 else
2481 {
2482 *(ptdata++) = r;
2483 *(ptdata++) = g;
2484 *(ptdata++) = b;
2485 }
2486 ptbits += 3;
2487 }
2488 ptbits += padding;
2489 }
2490 SetMaskColour( r, g, b );
2491 SetMask( TRUE );
2492 }
2493 else
2494 {
2495 SetMask( FALSE );
2496 }
2497 // free allocated resources
2498 ::ReleaseDC(NULL, hdc);
2499 free(lpDIBh);
2500 free(lpBits);
2501*/
2502}
2503
2504#endif
2505
a91b47e8
JS
2506// A module to allow wxImage initialization/cleanup
2507// without calling these functions from app.cpp or from
2508// the user's application.
2509
2510class wxImageModule: public wxModule
2511{
2512DECLARE_DYNAMIC_CLASS(wxImageModule)
2513public:
2514 wxImageModule() {}
2515 bool OnInit() { wxImage::InitStandardHandlers(); return TRUE; };
2516 void OnExit() { wxImage::CleanUpHandlers(); };
2517};
2518
2519IMPLEMENT_DYNAMIC_CLASS(wxImageModule, wxModule)
c9d01afd
GRG
2520
2521
2522//-----------------------------------------------------------------------------
2523
89d00456
GRG
2524// GRG, Dic/99
2525// Counts and returns the number of different colours. Optionally stops
cc9f7d79
GRG
2526// when it exceeds 'stopafter' different colours. This is useful, for
2527// example, to see if the image can be saved as 8-bit (256 colour or
2528// less, in this case it would be invoked as CountColours(256)). Default
2529// value for stopafter is -1 (don't care).
89d00456 2530//
cc9f7d79 2531unsigned long wxImage::CountColours( unsigned long stopafter )
89d00456
GRG
2532{
2533 wxHashTable h;
2534 wxNode *node;
2535 wxHNode *hnode;
2536 unsigned char r, g, b, *p;
2537 unsigned long size, nentries, key;
2538
2539 p = GetData();
2540 size = GetWidth() * GetHeight();
2541 nentries = 0;
2542
cc9f7d79 2543 for (unsigned long j = 0; (j < size) && (nentries <= stopafter) ; j++)
89d00456
GRG
2544 {
2545 r = *(p++);
2546 g = *(p++);
2547 b = *(p++);
2548 key = (r << 16) | (g << 8) | b;
2549
2550 hnode = (wxHNode *) h.Get(key);
2551
2552 if (!hnode)
2553 {
2554 h.Put(key, (wxObject *)(new wxHNode));
2555 nentries++;
2556 }
2557 }
2558
2559 // delete all HNodes
2560 h.BeginFind();
2561 while ((node = h.Next()) != NULL)
2562 delete (wxHNode *)node->GetData();
2563
2564 return nentries;
2565}
2566
2567
c9d01afd
GRG
2568// GRG, Dic/99
2569// Computes the histogram of the image and fills a hash table, indexed
2570// with integer keys built as 0xRRGGBB, containing wxHNode objects. Each
2571// wxHNode contains an 'index' (useful to build a palette with the image
2572// colours) and a 'value', which is the number of pixels in the image with
2573// that colour.
89d00456 2574//
c9d01afd
GRG
2575unsigned long wxImage::ComputeHistogram( wxHashTable &h )
2576{
2577 unsigned char r, g, b, *p;
2578 unsigned long size, nentries, key;
2579 wxHNode *hnode;
2580
2581 p = GetData();
2582 size = GetWidth() * GetHeight();
2583 nentries = 0;
2584
2585 for (unsigned long j = 0; j < size; j++)
2586 {
2587 r = *(p++);
2588 g = *(p++);
2589 b = *(p++);
2590 key = (r << 16) | (g << 8) | b;
2591
2592 hnode = (wxHNode *) h.Get(key);
2593
2594 if (hnode)
2595 hnode->value++;
2596 else
2597 {
2598 hnode = new wxHNode();
97fdfcc9 2599 hnode->index = nentries++;
c9d01afd
GRG
2600 hnode->value = 1;
2601
2602 h.Put(key, (wxObject *)hnode);
2603 }
2604 }
2605
2606 return nentries;
2607}
2608
2609