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