]> git.saurik.com Git - wxWidgets.git/blob - src/common/image.cpp
Chnages to mono-bitmap code.
[wxWidgets.git] / src / common / image.cpp
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
14 // For compilers that support precompilation, includes "wx.h".
15 #include "wx/wxprec.h"
16
17 #ifdef __BORLANDC__
18 #pragma hdrstop
19 #endif
20
21 #include "wx/image.h"
22 #include "wx/bitmap.h"
23 #include "wx/debug.h"
24 #include "wx/log.h"
25 #include "wx/app.h"
26 #include "wx/filefn.h"
27 #include "wx/wfstream.h"
28 #include "wx/intl.h"
29 #include "wx/module.h"
30
31 // For memcpy
32 #include <string.h>
33
34 #ifdef __SALFORDC__
35 #undef FAR
36 #endif
37
38 #ifdef __WXMSW__
39 #include "wx/msw/private.h"
40 #endif
41
42 //-----------------------------------------------------------------------------
43 // wxImage
44 //-----------------------------------------------------------------------------
45
46 class wxImageRefData: public wxObjectRefData
47 {
48 public:
49 wxImageRefData();
50 ~wxImageRefData();
51
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;
58 };
59
60 wxImageRefData::wxImageRefData()
61 {
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;
70 }
71
72 wxImageRefData::~wxImageRefData()
73 {
74 if (m_data)
75 free( m_data );
76 }
77
78 wxList wxImage::sm_handlers;
79
80 //-----------------------------------------------------------------------------
81
82 #define M_IMGDATA ((wxImageRefData *)m_refData)
83
84 IMPLEMENT_DYNAMIC_CLASS(wxImage, wxObject)
85
86 wxImage::wxImage()
87 {
88 }
89
90 wxImage::wxImage( int width, int height )
91 {
92 Create( width, height );
93 }
94
95 wxImage::wxImage( const wxString& name, long type )
96 {
97 LoadFile( name, type );
98 }
99
100 wxImage::wxImage( const wxString& name, const wxString& mimetype )
101 {
102 LoadFile( name, mimetype );
103 }
104
105 #if wxUSE_STREAMS
106 wxImage::wxImage( wxInputStream& stream, long type )
107 {
108 LoadFile( stream, type );
109 }
110
111 wxImage::wxImage( wxInputStream& stream, const wxString& mimetype )
112 {
113 LoadFile( stream, mimetype );
114 }
115 #endif // wxUSE_STREAMS
116
117 wxImage::wxImage( const wxImage& image )
118 {
119 Ref(image);
120 }
121
122 wxImage::wxImage( const wxImage* image )
123 {
124 if (image) Ref(*image);
125 }
126
127 void wxImage::Create( int width, int height )
128 {
129 m_refData = new wxImageRefData();
130
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;
135
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 }
144 }
145
146 void wxImage::Destroy()
147 {
148 UnRef();
149 }
150
151 wxImage wxImage::Scale( int width, int height ) const
152 {
153 wxImage image;
154
155 wxCHECK_MSG( Ok(), image, wxT("invalid image") );
156
157 wxCHECK_MSG( (width > 0) && (height > 0), image, wxT("invalid image size") );
158
159 image.Create( width, height );
160
161 char unsigned *data = image.GetData();
162
163 wxCHECK_MSG( data, image, wxT("unable to create image") );
164
165 if (M_IMGDATA->m_hasMask)
166 image.SetMaskColour( M_IMGDATA->m_maskRed, M_IMGDATA->m_maskGreen, M_IMGDATA->m_maskBlue );
167
168 long old_height = M_IMGDATA->m_height;
169 long old_width = M_IMGDATA->m_width;
170
171 char unsigned *source_data = M_IMGDATA->m_data;
172 char unsigned *target_data = data;
173
174 for (long j = 0; j < height; j++)
175 {
176 long y_offset = (j * old_height / height) * old_width;
177
178 for (long i = 0; i < width; i++)
179 {
180 memcpy( target_data,
181 source_data + 3*(y_offset + ((i * old_width )/ width)),
182 3 );
183 target_data += 3;
184 }
185 }
186
187 return image;
188 }
189
190 wxImage wxImage::GetSubImage( const wxRect &rect ) const
191 {
192 wxImage image;
193
194 wxCHECK_MSG( Ok(), image, wxT("invalid image") );
195
196 wxCHECK_MSG( (rect.GetLeft()>=0) && (rect.GetTop()>=0) && (rect.GetRight()<=GetWidth()) && (rect.GetBottom()<=GetHeight()),
197 image, wxT("invalid subimage size") );
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
206 wxCHECK_MSG( subdata, image, wxT("unable to create image") );
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;
214
215 data+=rect.GetTop()*width+subleft;
216
217 for (long j = 0; j < subheight; ++j)
218 {
219 memcpy( subdata, data, subwidth);
220 subdata+=subwidth;
221 data+=width;
222 }
223
224 return image;
225 }
226
227 void 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
250 void wxImage::SetRGB( int x, int y, unsigned char r, unsigned char g, unsigned char b )
251 {
252 wxCHECK_RET( Ok(), wxT("invalid image") );
253
254 int w = M_IMGDATA->m_width;
255 int h = M_IMGDATA->m_height;
256
257 wxCHECK_RET( (x>=0) && (y>=0) && (x<w) && (y<h), wxT("invalid image index") );
258
259 long pos = (y * w + x) * 3;
260
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
266 unsigned char wxImage::GetRed( int x, int y )
267 {
268 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
269
270 int w = M_IMGDATA->m_width;
271 int h = M_IMGDATA->m_height;
272
273 wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, wxT("invalid image index") );
274
275 long pos = (y * w + x) * 3;
276
277 return M_IMGDATA->m_data[pos];
278 }
279
280 unsigned char wxImage::GetGreen( int x, int y )
281 {
282 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
283
284 int w = M_IMGDATA->m_width;
285 int h = M_IMGDATA->m_height;
286
287 wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, wxT("invalid image index") );
288
289 long pos = (y * w + x) * 3;
290
291 return M_IMGDATA->m_data[pos+1];
292 }
293
294 unsigned char wxImage::GetBlue( int x, int y )
295 {
296 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
297
298 int w = M_IMGDATA->m_width;
299 int h = M_IMGDATA->m_height;
300
301 wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, wxT("invalid image index") );
302
303 long pos = (y * w + x) * 3;
304
305 return M_IMGDATA->m_data[pos+2];
306 }
307
308 bool wxImage::Ok() const
309 {
310 return (M_IMGDATA && M_IMGDATA->m_ok);
311 }
312
313 char unsigned *wxImage::GetData() const
314 {
315 wxCHECK_MSG( Ok(), (char unsigned *)NULL, wxT("invalid image") );
316
317 return M_IMGDATA->m_data;
318 }
319
320 void wxImage::SetData( char unsigned *data )
321 {
322 wxCHECK_RET( Ok(), wxT("invalid image") );
323
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;
334
335 UnRef();
336
337 m_refData = newRefData;
338 }
339
340 void wxImage::SetMaskColour( unsigned char r, unsigned char g, unsigned char b )
341 {
342 wxCHECK_RET( Ok(), wxT("invalid image") );
343
344 M_IMGDATA->m_maskRed = r;
345 M_IMGDATA->m_maskGreen = g;
346 M_IMGDATA->m_maskBlue = b;
347 M_IMGDATA->m_hasMask = TRUE;
348 }
349
350 unsigned char wxImage::GetMaskRed() const
351 {
352 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
353
354 return M_IMGDATA->m_maskRed;
355 }
356
357 unsigned char wxImage::GetMaskGreen() const
358 {
359 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
360
361 return M_IMGDATA->m_maskGreen;
362 }
363
364 unsigned char wxImage::GetMaskBlue() const
365 {
366 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
367
368 return M_IMGDATA->m_maskBlue;
369 }
370
371 void wxImage::SetMask( bool mask )
372 {
373 wxCHECK_RET( Ok(), wxT("invalid image") );
374
375 M_IMGDATA->m_hasMask = mask;
376 }
377
378 bool wxImage::HasMask() const
379 {
380 wxCHECK_MSG( Ok(), FALSE, wxT("invalid image") );
381
382 return M_IMGDATA->m_hasMask;
383 }
384
385 int wxImage::GetWidth() const
386 {
387 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
388
389 return M_IMGDATA->m_width;
390 }
391
392 int wxImage::GetHeight() const
393 {
394 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
395
396 return M_IMGDATA->m_height;
397 }
398
399 bool wxImage::LoadFile( const wxString& filename, long type )
400 {
401 #if wxUSE_STREAMS
402 if (wxFileExists(filename))
403 {
404 wxFileInputStream stream(filename);
405 wxBufferedInputStream bstream( stream );
406 return LoadFile(bstream, type);
407 }
408 else
409 {
410 wxLogError( _("Can't load image from file '%s': file does not exist."), filename.c_str() );
411
412 return FALSE;
413 }
414 #else // !wxUSE_STREAMS
415 return FALSE;
416 #endif // wxUSE_STREAMS
417 }
418
419 bool wxImage::LoadFile( const wxString& filename, const wxString& mimetype )
420 {
421 #if wxUSE_STREAMS
422 if (wxFileExists(filename))
423 {
424 wxFileInputStream stream(filename);
425 wxBufferedInputStream bstream( stream );
426 return LoadFile(bstream, mimetype);
427 }
428 else
429 {
430 wxLogError( _("Can't load image from file '%s': file does not exist."), filename.c_str() );
431
432 return FALSE;
433 }
434 #else // !wxUSE_STREAMS
435 return FALSE;
436 #endif // wxUSE_STREAMS
437 }
438
439 bool wxImage::SaveFile( const wxString& filename, int type )
440 {
441 #if wxUSE_STREAMS
442 wxFileOutputStream stream(filename);
443
444 if ( stream.LastError() == wxStream_NOERROR )
445 {
446 wxBufferedOutputStream bstream( stream );
447 return SaveFile(bstream, type);
448 }
449 else
450 #endif // wxUSE_STREAMS
451 return FALSE;
452 }
453
454 bool wxImage::SaveFile( const wxString& filename, const wxString& mimetype )
455 {
456 #if wxUSE_STREAMS
457 wxFileOutputStream stream(filename);
458
459 if ( stream.LastError() == wxStream_NOERROR )
460 {
461 wxBufferedOutputStream bstream( stream );
462 return SaveFile(bstream, mimetype);
463 }
464 else
465 #endif // wxUSE_STREAMS
466 return FALSE;
467 }
468
469 bool 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
479 #if wxUSE_STREAMS
480
481 bool wxImage::CanRead( wxInputStream &stream )
482 {
483 wxList &list=GetHandlers();
484
485 for ( wxList::Node *node = list.GetFirst(); node; node = node->GetNext() )
486 {
487 wxImageHandler *handler=(wxImageHandler*)node->GetData();
488 if (handler->CanRead( stream ))
489 return TRUE;
490 }
491
492 return FALSE;
493 }
494
495 bool wxImage::LoadFile( wxInputStream& stream, long type )
496 {
497 UnRef();
498
499 m_refData = new wxImageRefData;
500
501 wxImageHandler *handler;
502
503 if (type==wxBITMAP_TYPE_ANY)
504 {
505 wxList &list=GetHandlers();
506
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 );
512
513 }
514
515 wxLogWarning( _("No handler found for image type.") );
516 return FALSE;
517 }
518
519 handler = FindHandler(type);
520
521 if (handler == NULL)
522 {
523 wxLogWarning( _("No image handler for type %d defined."), type );
524
525 return FALSE;
526 }
527
528 return handler->LoadFile( this, stream );
529 }
530
531 bool 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 {
541 wxLogWarning( _("No image handler for type %s defined."), mimetype.GetData() );
542
543 return FALSE;
544 }
545
546 return handler->LoadFile( this, stream );
547 }
548
549 bool wxImage::SaveFile( wxOutputStream& stream, int type )
550 {
551 wxCHECK_MSG( Ok(), FALSE, wxT("invalid image") );
552
553 wxImageHandler *handler = FindHandler(type);
554
555 if (handler == NULL)
556 {
557 wxLogWarning( _("No image handler for type %d defined."), type );
558
559 return FALSE;
560 }
561
562 return handler->SaveFile( this, stream );
563 }
564
565 bool wxImage::SaveFile( wxOutputStream& stream, const wxString& mimetype )
566 {
567 wxCHECK_MSG( Ok(), FALSE, wxT("invalid image") );
568
569 wxImageHandler *handler = FindHandlerMime(mimetype);
570
571 if (handler == NULL)
572 {
573 wxLogWarning( _("No image handler for type %s defined."), mimetype.GetData() );
574
575 return FALSE;
576 }
577
578 return handler->SaveFile( this, stream );
579 }
580 #endif // wxUSE_STREAMS
581
582 void wxImage::AddHandler( wxImageHandler *handler )
583 {
584 // make sure that the memory will be freed at the program end
585 sm_handlers.DeleteContents(TRUE);
586
587 sm_handlers.Append( handler );
588 }
589
590 void wxImage::InsertHandler( wxImageHandler *handler )
591 {
592 // make sure that the memory will be freed at the program end
593 sm_handlers.DeleteContents(TRUE);
594
595 sm_handlers.Insert( handler );
596 }
597
598 bool wxImage::RemoveHandler( const wxString& name )
599 {
600 wxImageHandler *handler = FindHandler(name);
601 if (handler)
602 {
603 sm_handlers.DeleteObject(handler);
604 return TRUE;
605 }
606 else
607 return FALSE;
608 }
609
610 wxImageHandler *wxImage::FindHandler( const wxString& name )
611 {
612 wxNode *node = sm_handlers.First();
613 while (node)
614 {
615 wxImageHandler *handler = (wxImageHandler*)node->Data();
616 if (handler->GetName().Cmp(name) == 0) return handler;
617
618 node = node->Next();
619 }
620 return (wxImageHandler *)NULL;
621 }
622
623 wxImageHandler *wxImage::FindHandler( const wxString& extension, long bitmapType )
624 {
625 wxNode *node = sm_handlers.First();
626 while (node)
627 {
628 wxImageHandler *handler = (wxImageHandler*)node->Data();
629 if ( (handler->GetExtension().Cmp(extension) == 0) &&
630 (bitmapType == -1 || handler->GetType() == bitmapType) )
631 return handler;
632 node = node->Next();
633 }
634 return (wxImageHandler*)NULL;
635 }
636
637 wxImageHandler *wxImage::FindHandler( long bitmapType )
638 {
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
649 wxImageHandler *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
661 void wxImage::InitStandardHandlers()
662 {
663 AddHandler( new wxBMPHandler );
664 }
665
666 void wxImage::CleanUpHandlers()
667 {
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 }
677 }
678
679 //-----------------------------------------------------------------------------
680 // wxImageHandler
681 //-----------------------------------------------------------------------------
682
683 IMPLEMENT_ABSTRACT_CLASS(wxImageHandler,wxObject)
684
685 #if wxUSE_STREAMS
686 bool wxImageHandler::LoadFile( wxImage *WXUNUSED(image), wxInputStream& WXUNUSED(stream), bool WXUNUSED(verbose), int WXUNUSED(index) )
687 {
688 return FALSE;
689 }
690
691 bool wxImageHandler::SaveFile( wxImage *WXUNUSED(image), wxOutputStream& WXUNUSED(stream), bool WXUNUSED(verbose) )
692 {
693 return FALSE;
694 }
695
696 int wxImageHandler::GetImageCount( wxInputStream& WXUNUSED(stream) )
697 {
698 return 1;
699 }
700
701 bool wxImageHandler::CanRead( const wxString& name )
702 {
703 if (wxFileExists(name))
704 {
705 wxFileInputStream stream(name);
706 return CanRead(stream);
707 }
708
709 else {
710 wxLogError( _("Can't check image format of file '%s': file does not exist."), name.c_str() );
711
712 return FALSE;
713 }
714 // return FALSE;
715 }
716
717 #endif // wxUSE_STREAMS
718
719 //-----------------------------------------------------------------------------
720 // MSW conversion routines
721 //-----------------------------------------------------------------------------
722
723 #ifdef __WXMSW__
724
725 wxBitmap wxImage::ConvertToBitmap() const
726 {
727 if ( !Ok() )
728 return wxNullBitmap;
729
730 // sizeLimit is the MS upper limit for the DIB size
731 #ifdef WIN32
732 int sizeLimit = 1024*768*3;
733 #else
734 int sizeLimit = 0x7fff ;
735 #endif
736
737 // width and height of the device-dependent bitmap
738 int width = GetWidth();
739 int bmpHeight = GetHeight();
740
741 // calc the number of bytes per scanline and padding
742 int bytePerLine = width*3;
743 int sizeDWORD = sizeof( DWORD );
744 int lineBoundary = bytePerLine % sizeDWORD;
745 int padding = 0;
746 if( lineBoundary > 0 )
747 {
748 padding = sizeDWORD - lineBoundary;
749 bytePerLine += padding;
750 }
751 // calc the number of DIBs and heights of DIBs
752 int numDIB = 1;
753 int hRemain = 0;
754 int height = sizeLimit/bytePerLine;
755 if( height >= bmpHeight )
756 height = bmpHeight;
757 else
758 {
759 numDIB = bmpHeight / height;
760 hRemain = bmpHeight % height;
761 if( hRemain >0 ) numDIB++;
762 }
763
764 // set bitmap parameters
765 wxBitmap bitmap;
766 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
767 bitmap.SetWidth( width );
768 bitmap.SetHeight( bmpHeight );
769 bitmap.SetDepth( wxDisplayDepth() );
770
771 // create a DIB header
772 int headersize = sizeof(BITMAPINFOHEADER);
773 BITMAPINFO *lpDIBh = (BITMAPINFO *) malloc( headersize );
774 wxCHECK_MSG( lpDIBh, bitmap, wxT("could not allocate memory for DIB header") );
775 // Fill in the DIB header
776 lpDIBh->bmiHeader.biSize = headersize;
777 lpDIBh->bmiHeader.biWidth = (DWORD)width;
778 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
779 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
780 // the general formula for biSizeImage:
781 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
782 lpDIBh->bmiHeader.biPlanes = 1;
783 lpDIBh->bmiHeader.biBitCount = 24;
784 lpDIBh->bmiHeader.biCompression = BI_RGB;
785 lpDIBh->bmiHeader.biClrUsed = 0;
786 // These seem not really needed for our purpose here.
787 lpDIBh->bmiHeader.biClrImportant = 0;
788 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
789 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
790 // memory for DIB data
791 unsigned char *lpBits;
792 lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
793 if( !lpBits )
794 {
795 wxFAIL_MSG( wxT("could not allocate memory for DIB") );
796 free( lpDIBh );
797 return bitmap;
798 }
799
800 // create and set the device-dependent bitmap
801 HDC hdc = ::GetDC(NULL);
802 HDC memdc = ::CreateCompatibleDC( hdc );
803 HBITMAP hbitmap;
804 hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
805 ::SelectObject( memdc, hbitmap);
806
807 // copy image data into DIB data and then into DDB (in a loop)
808 unsigned char *data = GetData();
809 int i, j, n;
810 int origin = 0;
811 unsigned char *ptdata = data;
812 unsigned char *ptbits;
813
814 for( n=0; n<numDIB; n++ )
815 {
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
820 height = hRemain;
821 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
822 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
823 }
824 ptbits = lpBits;
825
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;
834 }
835 for( i=0; i< padding; i++ ) *(ptbits++) = 0;
836 }
837 ::StretchDIBits( memdc, 0, origin, width, height,\
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 );
848 // ::SelectObject( memdc, hbitmap);
849 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
850 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
851 // ::SelectObject( memdc, 0 );
852 // ::DeleteDC( memdc );
853 }
854 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
855
856 // similarly, created an mono-bitmap for the possible mask
857 if( HasMask() )
858 {
859 hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL );
860 ::SelectObject( memdc, hbitmap);
861 if( numDIB == 1 ) height = bmpHeight;
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 {
875 // redefine height and size of the (possibly) last smaller DIB
876 // memory is not reallocated
877 height = hRemain;
878 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
879 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
880 }
881 ptbits = lpBits;
882 for( int j=0; j<height; j++ )
883 {
884 for(i=0; i<width; i++ )
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 }
899 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
900 }
901 ::StretchDIBits( memdc, 0, origin, width, height,\
902 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
903 origin += height;
904 }
905 // create a wxMask object
906 wxMask *mask = new wxMask();
907 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
908 bitmap.SetMask( mask );
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
911 wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
912 wxMask *mask = new wxMask( bitmap, colour );
913 bitmap.SetMask( mask );
914 */
915 }
916
917 // free allocated resources
918 ::SelectObject( memdc, 0 );
919 ::DeleteDC( memdc );
920 ::ReleaseDC(NULL, hdc);
921 free(lpDIBh);
922 free(lpBits);
923
924 #if WXWIN_COMPATIBILITY_2
925 // check the wxBitmap object
926 bitmap.GetBitmapData()->SetOk();
927 #endif // WXWIN_COMPATIBILITY_2
928
929 return bitmap;
930 }
931
932 wxImage::wxImage( const wxBitmap &bitmap )
933 {
934 // check the bitmap
935 if( !bitmap.Ok() )
936 {
937 wxFAIL_MSG( wxT("invalid bitmap") );
938 return;
939 }
940
941 // create an wxImage object
942 int width = bitmap.GetWidth();
943 int height = bitmap.GetHeight();
944 Create( width, height );
945 unsigned char *data = GetData();
946 if( !data )
947 {
948 wxFAIL_MSG( wxT("could not allocate data for image") );
949 return;
950 }
951
952 // calc the number of bytes per scanline and padding in the DIB
953 int bytePerLine = width*3;
954 int sizeDWORD = sizeof( DWORD );
955 int lineBoundary = bytePerLine % sizeDWORD;
956 int padding = 0;
957 if( lineBoundary > 0 )
958 {
959 padding = sizeDWORD - lineBoundary;
960 bytePerLine += padding;
961 }
962
963 // create a DIB header
964 int headersize = sizeof(BITMAPINFOHEADER);
965 BITMAPINFO *lpDIBh = (BITMAPINFO *) malloc( headersize );
966 if( !lpDIBh )
967 {
968 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
969 free( data );
970 return;
971 }
972 // Fill in the DIB header
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;
981 // These seem not really needed for our purpose here.
982 lpDIBh->bmiHeader.biClrImportant = 0;
983 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
984 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
985 // memory for DIB data
986 unsigned char *lpBits;
987 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
988 if( !lpBits )
989 {
990 wxFAIL_MSG( wxT("could not allocate data for DIB") );
991 free( data );
992 free( lpDIBh );
993 return;
994 }
995
996 // copy data from the device-dependent bitmap to the DIB
997 HDC hdc = ::GetDC(NULL);
998 HBITMAP hbitmap;
999 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
1000 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1001
1002 // copy DIB data into the wxImage object
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;
1014 }
1015 ptbits += padding;
1016 }
1017
1018 // similarly, set data according to the possible mask bitmap
1019 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
1020 {
1021 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
1022 // memory DC created, color set, data copied, and memory DC deleted
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 );
1027 ::DeleteDC( memdc );
1028 // background color set to RGB(16,16,16) in consistent with wxGTK
1029 unsigned char r=16, g=16, b=16;
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 )
1037 ptdata += 3;
1038 else
1039 {
1040 *(ptdata++) = r;
1041 *(ptdata++) = g;
1042 *(ptdata++) = b;
1043 }
1044 ptbits += 3;
1045 }
1046 ptbits += padding;
1047 }
1048 SetMaskColour( r, g, b );
1049 SetMask( TRUE );
1050 }
1051 else
1052 {
1053 SetMask( FALSE );
1054 }
1055 // free allocated resources
1056 ::ReleaseDC(NULL, hdc);
1057 free(lpDIBh);
1058 free(lpBits);
1059 }
1060
1061 #endif
1062
1063 #ifdef __WXMAC__
1064
1065 #include <PictUtils.h>
1066
1067 extern CTabHandle wxMacCreateColorTable( int numColors ) ;
1068 extern void wxMacDestroyColorTable( CTabHandle colors ) ;
1069 extern void wxMacSetColorTableEntry( CTabHandle newColors , int index , int red , int green , int blue ) ;
1070 extern GWorldPtr wxMacCreateGWorld( int height , int width , int depth ) ;
1071 extern void wxMacDestroyGWorld( GWorldPtr gw ) ;
1072
1073 wxBitmap 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
1080
1081 wxBitmap bitmap( width , height , wxDisplayDepth() ) ;
1082
1083 // Create mask
1084
1085 if (HasMask())
1086 {
1087 /*
1088 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1089
1090 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1091
1092 wxMask *mask = new wxMask();
1093 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1094
1095 bitmap.SetMask( mask );
1096 */
1097 }
1098
1099 // Render
1100
1101 int r_mask = GetMaskRed();
1102 int g_mask = GetMaskGreen();
1103 int b_mask = GetMaskBlue();
1104
1105 CGrafPtr origPort ;
1106 GDHandle origDevice ;
1107
1108 GetGWorld( &origPort , &origDevice ) ;
1109 SetGWorld( bitmap.GetHBITMAP() , NULL ) ;
1110
1111 register unsigned char* data = GetData();
1112
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++];
1128
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 ) ;
1162
1163 return bitmap;
1164
1165 }
1166
1167 wxImage::wxImage( const wxBitmap &bitmap )
1168 {
1169 // check the bitmap
1170 if( !bitmap.Ok() )
1171 {
1172 wxFAIL_MSG( "invalid bitmap" );
1173 return;
1174 }
1175
1176 // create an wxImage object
1177 int width = bitmap.GetWidth();
1178 int height = bitmap.GetHeight();
1179 Create( width, height );
1180 /*
1181 unsigned char *data = GetData();
1182 if( !data )
1183 {
1184 wxFAIL_MSG( "could not allocate data for image" );
1185 return;
1186 }
1187
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;
1193 if( lineBoundary.rem > 0 )
1194 {
1195 padding = sizeDWORD - lineBoundary.rem;
1196 bytePerLine += padding;
1197 }
1198
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 }
1231
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 );
1237
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 }
1253
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 );
1263 ::DeleteDC( memdc );
1264 // background color set to RGB(16,16,16) in consistent with wxGTK
1265 unsigned char r=16, g=16, b=16;
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;
1283 }
1284 SetMaskColour( r, g, b );
1285 SetMask( TRUE );
1286 }
1287 else
1288 {
1289 SetMask( FALSE );
1290 }
1291 // free allocated resources
1292 ::ReleaseDC(NULL, hdc);
1293 free(lpDIBh);
1294 free(lpBits);
1295 */
1296 }
1297
1298 #endif
1299
1300 //-----------------------------------------------------------------------------
1301 // GTK conversion routines
1302 //-----------------------------------------------------------------------------
1303
1304 #ifdef __WXGTK__
1305
1306 #include <gtk/gtk.h>
1307 #include <gdk/gdk.h>
1308 #include <gdk/gdkx.h>
1309
1310 #if (GTK_MINOR_VERSION > 0)
1311 #include <gdk/gdkrgb.h>
1312 #endif
1313
1314 wxBitmap wxImage::ConvertToMonoBitmap( unsigned char red, unsigned char green, unsigned char blue )
1315 {
1316 wxBitmap bitmap;
1317
1318 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
1319
1320 int width = GetWidth();
1321 int height = GetHeight();
1322
1323 bitmap.SetHeight( height );
1324 bitmap.SetWidth( width );
1325
1326 bitmap.SetBitmap( gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 ) );
1327
1328 bitmap.SetDepth( 1 );
1329
1330 // Create picture image
1331
1332 unsigned char *data_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1333
1334 GdkImage *data_image =
1335 gdk_image_new_bitmap( gdk_visual_get_system(), data_data, width, height );
1336
1337 // Create mask image
1338
1339 GdkImage *mask_image = (GdkImage*) NULL;
1340
1341 if (HasMask())
1342 {
1343 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1344
1345 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1346
1347 wxMask *mask = new wxMask();
1348 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1349
1350 bitmap.SetMask( mask );
1351 }
1352
1353 int r_mask = GetMaskRed();
1354 int g_mask = GetMaskGreen();
1355 int b_mask = GetMaskBlue();
1356
1357 unsigned char* data = GetData();
1358
1359 int index = 0;
1360 for (int y = 0; y < height; y++)
1361 {
1362 for (int x = 0; x < width; x++)
1363 {
1364 int r = data[index];
1365 index++;
1366 int g = data[index];
1367 index++;
1368 int b = data[index];
1369 index++;
1370
1371 if (HasMask())
1372 {
1373 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1374 gdk_image_put_pixel( mask_image, x, y, 1 );
1375 else
1376 gdk_image_put_pixel( mask_image, x, y, 0 );
1377 }
1378
1379 if ((r == red) && (b == blue) && (g == green))
1380 gdk_image_put_pixel( data_image, x, y, 1 );
1381 else
1382 gdk_image_put_pixel( data_image, x, y, 0 );
1383
1384 } // for
1385 } // for
1386
1387 // Blit picture
1388
1389 GdkGC *data_gc = gdk_gc_new( bitmap.GetBitmap() );
1390
1391 gdk_draw_image( bitmap.GetBitmap(), data_gc, data_image, 0, 0, 0, 0, width, height );
1392
1393 gdk_image_destroy( data_image );
1394 gdk_gc_unref( data_gc );
1395
1396 // Blit mask
1397
1398 if (HasMask())
1399 {
1400 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
1401
1402 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
1403
1404 gdk_image_destroy( mask_image );
1405 gdk_gc_unref( mask_gc );
1406 }
1407
1408 return bitmap;
1409 }
1410
1411
1412 wxBitmap wxImage::ConvertToBitmap() const
1413 {
1414 wxBitmap bitmap;
1415
1416 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
1417
1418 int width = GetWidth();
1419 int height = GetHeight();
1420
1421 bitmap.SetHeight( height );
1422 bitmap.SetWidth( width );
1423
1424 bitmap.SetPixmap( gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, -1 ) );
1425
1426 // Retrieve depth
1427
1428 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
1429 if (visual == NULL) visual = gdk_visual_get_system();
1430 int bpp = visual->depth;
1431
1432 bitmap.SetDepth( bpp );
1433
1434 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
1435 if (bpp < 8) bpp = 8;
1436
1437 #if (GTK_MINOR_VERSION > 0)
1438
1439 if (!HasMask() && (bpp > 8))
1440 {
1441 static bool s_hasInitialized = FALSE;
1442
1443 if (!s_hasInitialized)
1444 {
1445 gdk_rgb_init();
1446 s_hasInitialized = TRUE;
1447 }
1448
1449 GdkGC *gc = gdk_gc_new( bitmap.GetPixmap() );
1450
1451 gdk_draw_rgb_image( bitmap.GetPixmap(),
1452 gc,
1453 0, 0,
1454 width, height,
1455 GDK_RGB_DITHER_NONE,
1456 GetData(),
1457 width*3 );
1458
1459 gdk_gc_unref( gc );
1460
1461 return bitmap;
1462 }
1463
1464 #endif
1465
1466 // Create picture image
1467
1468 GdkImage *data_image =
1469 gdk_image_new( GDK_IMAGE_FASTEST, gdk_visual_get_system(), width, height );
1470
1471 // Create mask image
1472
1473 GdkImage *mask_image = (GdkImage*) NULL;
1474
1475 if (HasMask())
1476 {
1477 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1478
1479 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1480
1481 wxMask *mask = new wxMask();
1482 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1483
1484 bitmap.SetMask( mask );
1485 }
1486
1487 // Render
1488
1489 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1490 byte_order b_o = RGB;
1491
1492 if (bpp >= 24)
1493 {
1494 GdkVisual *visual = gdk_visual_get_system();
1495 if ((visual->red_mask > visual->green_mask) && (visual->green_mask > visual->blue_mask)) b_o = RGB;
1496 else if ((visual->red_mask > visual->blue_mask) && (visual->blue_mask > visual->green_mask)) b_o = RGB;
1497 else if ((visual->blue_mask > visual->red_mask) && (visual->red_mask > visual->green_mask)) b_o = BRG;
1498 else if ((visual->blue_mask > visual->green_mask) && (visual->green_mask > visual->red_mask)) b_o = BGR;
1499 else if ((visual->green_mask > visual->red_mask) && (visual->red_mask > visual->blue_mask)) b_o = GRB;
1500 else if ((visual->green_mask > visual->blue_mask) && (visual->blue_mask > visual->red_mask)) b_o = GBR;
1501 }
1502
1503 int r_mask = GetMaskRed();
1504 int g_mask = GetMaskGreen();
1505 int b_mask = GetMaskBlue();
1506
1507 unsigned char* data = GetData();
1508
1509 int index = 0;
1510 for (int y = 0; y < height; y++)
1511 {
1512 for (int x = 0; x < width; x++)
1513 {
1514 int r = data[index];
1515 index++;
1516 int g = data[index];
1517 index++;
1518 int b = data[index];
1519 index++;
1520
1521 if (HasMask())
1522 {
1523 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1524 gdk_image_put_pixel( mask_image, x, y, 1 );
1525 else
1526 gdk_image_put_pixel( mask_image, x, y, 0 );
1527 }
1528
1529 switch (bpp)
1530 {
1531 case 8:
1532 {
1533 int pixel = -1;
1534 if (wxTheApp->m_colorCube)
1535 {
1536 pixel = wxTheApp->m_colorCube[ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1537 }
1538 else
1539 {
1540 GdkColormap *cmap = gtk_widget_get_default_colormap();
1541 GdkColor *colors = cmap->colors;
1542 int max = 3 * (65536);
1543
1544 for (int i = 0; i < cmap->size; i++)
1545 {
1546 int rdiff = (r << 8) - colors[i].red;
1547 int gdiff = (g << 8) - colors[i].green;
1548 int bdiff = (b << 8) - colors[i].blue;
1549 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1550 if (sum < max) { pixel = i; max = sum; }
1551 }
1552 }
1553
1554 gdk_image_put_pixel( data_image, x, y, pixel );
1555
1556 break;
1557 }
1558 case 15:
1559 {
1560 guint32 pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1561 gdk_image_put_pixel( data_image, x, y, pixel );
1562 break;
1563 }
1564 case 16:
1565 {
1566 guint32 pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1567 gdk_image_put_pixel( data_image, x, y, pixel );
1568 break;
1569 }
1570 case 32:
1571 case 24:
1572 {
1573 guint32 pixel = 0;
1574 switch (b_o)
1575 {
1576 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1577 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1578 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1579 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1580 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1581 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1582 }
1583 gdk_image_put_pixel( data_image, x, y, pixel );
1584 }
1585 default: break;
1586 }
1587 } // for
1588 } // for
1589
1590 // Blit picture
1591
1592 GdkGC *data_gc = gdk_gc_new( bitmap.GetPixmap() );
1593
1594 gdk_draw_image( bitmap.GetPixmap(), data_gc, data_image, 0, 0, 0, 0, width, height );
1595
1596 gdk_image_destroy( data_image );
1597 gdk_gc_unref( data_gc );
1598
1599 // Blit mask
1600
1601 if (HasMask())
1602 {
1603 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
1604
1605 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
1606
1607 gdk_image_destroy( mask_image );
1608 gdk_gc_unref( mask_gc );
1609 }
1610
1611 return bitmap;
1612 }
1613
1614 wxImage::wxImage( const wxBitmap &bitmap )
1615 {
1616 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
1617
1618 GdkImage *gdk_image = (GdkImage*) NULL;
1619 if (bitmap.GetPixmap())
1620 {
1621 gdk_image = gdk_image_get( bitmap.GetPixmap(),
1622 0, 0,
1623 bitmap.GetWidth(), bitmap.GetHeight() );
1624 } else
1625 if (bitmap.GetBitmap())
1626 {
1627 gdk_image = gdk_image_get( bitmap.GetBitmap(),
1628 0, 0,
1629 bitmap.GetWidth(), bitmap.GetHeight() );
1630 } else
1631 {
1632 wxFAIL_MSG( wxT("Ill-formed bitmap") );
1633 }
1634
1635 wxCHECK_RET( gdk_image, wxT("couldn't create image") );
1636
1637 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1638 char unsigned *data = GetData();
1639
1640 if (!data)
1641 {
1642 gdk_image_destroy( gdk_image );
1643 wxFAIL_MSG( wxT("couldn't create image") );
1644 return;
1645 }
1646
1647 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1648 if (bitmap.GetMask())
1649 {
1650 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1651 0, 0,
1652 bitmap.GetWidth(), bitmap.GetHeight() );
1653
1654 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1655 }
1656
1657 int bpp = -1;
1658 if (bitmap.GetPixmap())
1659 {
1660 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
1661
1662 if (visual == NULL) visual = gdk_window_get_visual( (GdkWindow*) &gdk_root_parent );
1663 bpp = visual->depth;
1664 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
1665 }
1666 if (bitmap.GetBitmap())
1667 {
1668 bpp = 1;
1669 }
1670
1671 GdkColormap *cmap = gtk_widget_get_default_colormap();
1672
1673 long pos = 0;
1674 for (int j = 0; j < bitmap.GetHeight(); j++)
1675 {
1676 for (int i = 0; i < bitmap.GetWidth(); i++)
1677 {
1678 wxInt32 pixel = gdk_image_get_pixel( gdk_image, i, j );
1679 if (bpp == 1)
1680 {
1681 if (pixel == 0)
1682 {
1683 data[pos] = 0;
1684 data[pos+1] = 0;
1685 data[pos+2] = 0;
1686 }
1687 else
1688 {
1689 data[pos] = 255;
1690 data[pos+1] = 255;
1691 data[pos+2] = 255;
1692 }
1693 } else if (bpp <= 8)
1694 {
1695 data[pos] = cmap->colors[pixel].red >> 8;
1696 data[pos+1] = cmap->colors[pixel].green >> 8;
1697 data[pos+2] = cmap->colors[pixel].blue >> 8;
1698 } else if (bpp == 15)
1699 {
1700 #if (wxBYTE_ORDER == wxBIG_ENDIAN)
1701 // ?
1702 #endif
1703 data[pos] = (pixel >> 7) & 0xf8;
1704 data[pos+1] = (pixel >> 2) & 0xf8;
1705 data[pos+2] = (pixel << 3) & 0xf8;
1706 } else if (bpp == 16)
1707 {
1708 #if (wxBYTE_ORDER == wxBIG_ENDIAN)
1709 // ?
1710 #endif
1711 data[pos] = (pixel >> 8) & 0xf8;
1712 data[pos+1] = (pixel >> 3) & 0xfc;
1713 data[pos+2] = (pixel << 3) & 0xf8;
1714 } else
1715 {
1716 #if (wxBYTE_ORDER == wxBIG_ENDIAN)
1717 data[pos] = (pixel) & 0xff; // Red
1718 data[pos+1] = (pixel >> 8) & 0xff; // Green
1719 data[pos+2] = (pixel >> 16) & 0xff; // Blue
1720 #else
1721 data[pos] = (pixel >> 16) & 0xff;
1722 data[pos+1] = (pixel >> 8) & 0xff;
1723 data[pos+2] = pixel & 0xff;
1724 #endif
1725 }
1726
1727 if (gdk_image_mask)
1728 {
1729 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1730 if (mask_pixel == 0)
1731 {
1732 data[pos] = 16;
1733 data[pos+1] = 16;
1734 data[pos+2] = 16;
1735 }
1736 }
1737
1738 pos += 3;
1739 }
1740 }
1741
1742 gdk_image_destroy( gdk_image );
1743 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1744 }
1745
1746 #endif
1747
1748 //-----------------------------------------------------------------------------
1749 // Motif conversion routines
1750 //-----------------------------------------------------------------------------
1751
1752 #ifdef __WXMOTIF__
1753 #ifdef __VMS__
1754 #pragma message disable nosimpint
1755 #endif
1756 #include <Xm/Xm.h>
1757 #ifdef __VMS__
1758 #pragma message enable nosimpint
1759 #endif
1760 #include "wx/utils.h"
1761 #include <math.h>
1762
1763 /*
1764
1765 Date: Wed, 05 Jan 2000 11:45:40 +0100
1766 From: Frits Boel <boel@niob.knaw.nl>
1767 To: julian.smart@ukonline.co.uk
1768 Subject: Patch for Motif ConvertToBitmap
1769
1770 Hi Julian,
1771
1772 I've been working on a wxWin application for image processing. From the
1773 beginning, I was surprised by the (lack of) speed of ConvertToBitmap,
1774 till I looked in the source code of image.cpp. I saw that converting a
1775 wxImage to a bitmap with 8-bit pixels is done with comparing every pixel
1776 to the 256 colors of the palet. A very time-consuming piece of code!
1777
1778 Because I wanted a faster application, I've made a 'patch' for this. In
1779 short: every pixel of the image is compared to a sorted list with
1780 colors. If the color is found in the list, the palette entry is
1781 returned; if the color is not found, the color palette is searched and
1782 then the palette entry is returned and the color added to the sorted
1783 list.
1784
1785 Maybe there is another method for this, namely changing the palette
1786 itself (if the colors are known, as is the case with tiffs with a
1787 colormap). I did not look at this, maybe someone else did?
1788
1789 The code of the patch is attached, have a look on it, and maybe you will
1790 ship it with the next release of wxMotif?
1791
1792 Regards,
1793
1794 Frits Boel
1795 Software engineer at Hubrecht Laboratory, The Netherlands.
1796
1797 */
1798
1799 class wxSearchColor
1800 {
1801 public:
1802 wxSearchColor( void );
1803 wxSearchColor( int size, XColor *colors );
1804 ~wxSearchColor( void );
1805
1806 int SearchColor( int r, int g, int b );
1807 private:
1808 int AddColor( unsigned int value, int pos );
1809
1810 int size;
1811 XColor *colors;
1812 unsigned int *color;
1813 int *entry;
1814
1815 int bottom;
1816 int top;
1817 };
1818
1819 wxSearchColor::wxSearchColor( void )
1820 {
1821 this->size = 0;
1822 this->colors = (XColor*) NULL;
1823 this->color = (unsigned int *) NULL;
1824 this->entry = (int*) NULL;
1825
1826 this->bottom = 0;
1827 this->top = 0;
1828 }
1829
1830 wxSearchColor::wxSearchColor( int size, XColor *colors )
1831 {
1832 int i;
1833 this->size = size;
1834 this->colors = colors;
1835 this->color = new unsigned int[size];
1836 this->entry = new int [size];
1837
1838 for (i = 0; i < this->size; i++ ) {
1839 this->entry[i] = -1;
1840 }
1841
1842 this->bottom = this->top = ( size >> 1 );
1843 }
1844
1845 wxSearchColor::~wxSearchColor( void )
1846 {
1847 if ( this->color ) delete this->color;
1848 if ( this->entry ) delete this->entry;
1849 }
1850
1851 int wxSearchColor::SearchColor( int r, int g, int b )
1852 {
1853 unsigned int value = ( ( ( r * 256 ) + g ) * 256 ) + b;
1854 int begin = this->bottom;
1855 int end = this->top;
1856 int middle;
1857
1858 while ( begin <= end ) {
1859
1860 middle = ( begin + end ) >> 1;
1861
1862 if ( value == this->color[middle] ) {
1863 return( this->entry[middle] );
1864 } else if ( value < this->color[middle] ) {
1865 end = middle - 1;
1866 } else {
1867 begin = middle + 1;
1868 }
1869
1870 }
1871
1872 return AddColor( value, middle );
1873 }
1874
1875 int wxSearchColor::AddColor( unsigned int value, int pos )
1876 {
1877 int i;
1878 int pixel = -1;
1879 int max = 3 * (65536);
1880 for ( i = 0; i < 256; i++ ) {
1881 int rdiff = ((value >> 8) & 0xFF00 ) - colors[i].red;
1882 int gdiff = ((value ) & 0xFF00 ) - colors[i].green;
1883 int bdiff = ((value << 8) & 0xFF00 ) - colors[i].blue;
1884 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1885 if (sum < max) { pixel = i; max = sum; }
1886 }
1887
1888 if ( this->entry[pos] < 0 ) {
1889 this->color[pos] = value;
1890 this->entry[pos] = pixel;
1891 } else if ( value < this->color[pos] ) {
1892
1893 if ( this->bottom > 0 ) {
1894 for ( i = this->bottom; i < pos; i++ ) {
1895 this->color[i-1] = this->color[i];
1896 this->entry[i-1] = this->entry[i];
1897 }
1898 this->bottom--;
1899 this->color[pos-1] = value;
1900 this->entry[pos-1] = pixel;
1901 } else if ( this->top < this->size-1 ) {
1902 for ( i = this->top; i >= pos; i-- ) {
1903 this->color[i+1] = this->color[i];
1904 this->entry[i+1] = this->entry[i];
1905 }
1906 this->top++;
1907 this->color[pos] = value;
1908 this->entry[pos] = pixel;
1909 }
1910
1911 } else {
1912
1913 if ( this->top < this->size-1 ) {
1914 for ( i = this->top; i > pos; i-- ) {
1915 this->color[i+1] = this->color[i];
1916 this->entry[i+1] = this->entry[i];
1917 }
1918 this->top++;
1919 this->color[pos+1] = value;
1920 this->entry[pos+1] = pixel;
1921 } else if ( this->bottom > 0 ) {
1922 for ( i = this->bottom; i < pos; i++ ) {
1923 this->color[i-1] = this->color[i];
1924 this->entry[i-1] = this->entry[i];
1925 }
1926 this->bottom--;
1927 this->color[pos] = value;
1928 this->entry[pos] = pixel;
1929 }
1930
1931 }
1932
1933 return( pixel );
1934 }
1935
1936 wxBitmap wxImage::ConvertToBitmap() const
1937 {
1938 wxBitmap bitmap;
1939
1940 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
1941
1942 int width = GetWidth();
1943 int height = GetHeight();
1944
1945 bitmap.SetHeight( height );
1946 bitmap.SetWidth( width );
1947
1948 Display *dpy = (Display*) wxGetDisplay();
1949 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1950 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1951
1952 // Create image
1953
1954 XImage *data_image = XCreateImage( dpy, vis, bpp, ZPixmap, 0, 0, width, height, 32, 0 );
1955 data_image->data = (char*) malloc( data_image->bytes_per_line * data_image->height );
1956
1957 bitmap.Create( width, height, bpp );
1958
1959 /*
1960 // Create mask
1961
1962 GdkImage *mask_image = (GdkImage*) NULL;
1963
1964 if (HasMask())
1965 {
1966 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1967
1968 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1969
1970 wxMask *mask = new wxMask();
1971 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1972
1973 bitmap.SetMask( mask );
1974 }
1975 */
1976
1977 // Retrieve depth info
1978
1979 XVisualInfo vinfo_template;
1980 XVisualInfo *vi;
1981
1982 vinfo_template.visual = vis;
1983 vinfo_template.visualid = XVisualIDFromVisual( vis );
1984 vinfo_template.depth = bpp;
1985 int nitem = 0;
1986
1987 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1988
1989 wxCHECK_MSG( vi, wxNullBitmap, wxT("no visual") );
1990
1991 XFree( vi );
1992
1993 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1994 if (bpp < 8) bpp = 8;
1995
1996 // Render
1997
1998 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1999 byte_order b_o = RGB;
2000
2001 if (bpp >= 24)
2002 {
2003 if ((vi->red_mask > vi->green_mask) && (vi->green_mask > vi->blue_mask)) b_o = RGB;
2004 else if ((vi->red_mask > vi->blue_mask) && (vi->blue_mask > vi->green_mask)) b_o = RGB;
2005 else if ((vi->blue_mask > vi->red_mask) && (vi->red_mask > vi->green_mask)) b_o = BRG;
2006 else if ((vi->blue_mask > vi->green_mask) && (vi->green_mask > vi->red_mask)) b_o = BGR;
2007 else if ((vi->green_mask > vi->red_mask) && (vi->red_mask > vi->blue_mask)) b_o = GRB;
2008 else if ((vi->green_mask > vi->blue_mask) && (vi->blue_mask > vi->red_mask)) b_o = GBR;
2009 }
2010
2011 /*
2012 int r_mask = GetMaskRed();
2013 int g_mask = GetMaskGreen();
2014 int b_mask = GetMaskBlue();
2015 */
2016
2017 XColor colors[256];
2018 if (bpp == 8)
2019 {
2020 Colormap cmap = (Colormap) wxTheApp->GetMainColormap( dpy );
2021
2022 for (int i = 0; i < 256; i++) colors[i].pixel = i;
2023 XQueryColors( dpy, cmap, colors, 256 );
2024 }
2025
2026 wxSearchColor scolor( 256, colors );
2027 unsigned char* data = GetData();
2028
2029 int index = 0;
2030 for (int y = 0; y < height; y++)
2031 {
2032 for (int x = 0; x < width; x++)
2033 {
2034 int r = data[index];
2035 index++;
2036 int g = data[index];
2037 index++;
2038 int b = data[index];
2039 index++;
2040
2041 /*
2042 if (HasMask())
2043 {
2044 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
2045 gdk_image_put_pixel( mask_image, x, y, 1 );
2046 else
2047 gdk_image_put_pixel( mask_image, x, y, 0 );
2048 }
2049 */
2050
2051 switch (bpp)
2052 {
2053 case 8:
2054 {
2055 #if 0 // Old, slower code
2056 int pixel = -1;
2057 /*
2058 if (wxTheApp->m_colorCube)
2059 {
2060 pixel = wxTheApp->m_colorCube
2061 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
2062 }
2063 else
2064 {
2065 */
2066 int max = 3 * (65536);
2067 for (int i = 0; i < 256; i++)
2068 {
2069 int rdiff = (r << 8) - colors[i].red;
2070 int gdiff = (g << 8) - colors[i].green;
2071 int bdiff = (b << 8) - colors[i].blue;
2072 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
2073 if (sum < max) { pixel = i; max = sum; }
2074 }
2075 /*
2076 }
2077 */
2078 #endif
2079
2080 // And this is all to get the 'right' color...
2081 int pixel = scolor.SearchColor( r, g, b );
2082 XPutPixel( data_image, x, y, pixel );
2083 break;
2084 }
2085 case 15:
2086 {
2087 int pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
2088 XPutPixel( data_image, x, y, pixel );
2089 break;
2090 }
2091 case 16:
2092 {
2093 int pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
2094 XPutPixel( data_image, x, y, pixel );
2095 break;
2096 }
2097 case 32:
2098 case 24:
2099 {
2100 int pixel = 0;
2101 switch (b_o)
2102 {
2103 case RGB: pixel = (r << 16) | (g << 8) | b; break;
2104 case RBG: pixel = (r << 16) | (b << 8) | g; break;
2105 case BRG: pixel = (b << 16) | (r << 8) | g; break;
2106 case BGR: pixel = (b << 16) | (g << 8) | r; break;
2107 case GRB: pixel = (g << 16) | (r << 8) | b; break;
2108 case GBR: pixel = (g << 16) | (b << 8) | r; break;
2109 }
2110 XPutPixel( data_image, x, y, pixel );
2111 }
2112 default: break;
2113 }
2114 } // for
2115 } // for
2116
2117 // Blit picture
2118
2119 XGCValues gcvalues;
2120 gcvalues.foreground = BlackPixel( dpy, DefaultScreen( dpy ) );
2121 GC gc = XCreateGC( dpy, RootWindow ( dpy, DefaultScreen(dpy) ), GCForeground, &gcvalues );
2122 XPutImage( dpy, (Drawable)bitmap.GetPixmap(), gc, data_image, 0, 0, 0, 0, width, height );
2123
2124 XDestroyImage( data_image );
2125 XFreeGC( dpy, gc );
2126
2127 /*
2128 // Blit mask
2129
2130 if (HasMask())
2131 {
2132 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
2133
2134 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
2135
2136 gdk_image_destroy( mask_image );
2137 gdk_gc_unref( mask_gc );
2138 }
2139 */
2140
2141 return bitmap;
2142 }
2143
2144 wxImage::wxImage( const wxBitmap &bitmap )
2145 {
2146 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
2147
2148 Display *dpy = (Display*) wxGetDisplay();
2149 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
2150 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
2151
2152 XImage *ximage = XGetImage( dpy,
2153 (Drawable)bitmap.GetPixmap(),
2154 0, 0,
2155 bitmap.GetWidth(), bitmap.GetHeight(),
2156 AllPlanes, ZPixmap );
2157
2158 wxCHECK_RET( ximage, wxT("couldn't create image") );
2159
2160 Create( bitmap.GetWidth(), bitmap.GetHeight() );
2161 char unsigned *data = GetData();
2162
2163 if (!data)
2164 {
2165 XDestroyImage( ximage );
2166 wxFAIL_MSG( wxT("couldn't create image") );
2167 return;
2168 }
2169
2170 /*
2171 GdkImage *gdk_image_mask = (GdkImage*) NULL;
2172 if (bitmap.GetMask())
2173 {
2174 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
2175 0, 0,
2176 bitmap.GetWidth(), bitmap.GetHeight() );
2177
2178 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
2179 }
2180 */
2181
2182 // Retrieve depth info
2183
2184 XVisualInfo vinfo_template;
2185 XVisualInfo *vi;
2186
2187 vinfo_template.visual = vis;
2188 vinfo_template.visualid = XVisualIDFromVisual( vis );
2189 vinfo_template.depth = bpp;
2190 int nitem = 0;
2191
2192 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
2193
2194 wxCHECK_RET( vi, wxT("no visual") );
2195
2196 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
2197
2198 XFree( vi );
2199
2200 XColor colors[256];
2201 if (bpp == 8)
2202 {
2203 Colormap cmap = (Colormap)wxTheApp->GetMainColormap( dpy );
2204
2205 for (int i = 0; i < 256; i++) colors[i].pixel = i;
2206 XQueryColors( dpy, cmap, colors, 256 );
2207 }
2208
2209 long pos = 0;
2210 for (int j = 0; j < bitmap.GetHeight(); j++)
2211 {
2212 for (int i = 0; i < bitmap.GetWidth(); i++)
2213 {
2214 int pixel = XGetPixel( ximage, i, j );
2215 if (bpp <= 8)
2216 {
2217 data[pos] = colors[pixel].red >> 8;
2218 data[pos+1] = colors[pixel].green >> 8;
2219 data[pos+2] = colors[pixel].blue >> 8;
2220 } else if (bpp == 15)
2221 {
2222 data[pos] = (pixel >> 7) & 0xf8;
2223 data[pos+1] = (pixel >> 2) & 0xf8;
2224 data[pos+2] = (pixel << 3) & 0xf8;
2225 } else if (bpp == 16)
2226 {
2227 data[pos] = (pixel >> 8) & 0xf8;
2228 data[pos+1] = (pixel >> 3) & 0xfc;
2229 data[pos+2] = (pixel << 3) & 0xf8;
2230 } else
2231 {
2232 data[pos] = (pixel >> 16) & 0xff;
2233 data[pos+1] = (pixel >> 8) & 0xff;
2234 data[pos+2] = pixel & 0xff;
2235 }
2236
2237 /*
2238 if (gdk_image_mask)
2239 {
2240 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
2241 if (mask_pixel == 0)
2242 {
2243 data[pos] = 16;
2244 data[pos+1] = 16;
2245 data[pos+2] = 16;
2246 }
2247 }
2248 */
2249
2250 pos += 3;
2251 }
2252 }
2253
2254 XDestroyImage( ximage );
2255 /*
2256 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
2257 */
2258 }
2259 #endif
2260
2261 #ifdef __WXPM__
2262 // OS/2 Presentation manager conversion routings
2263
2264 wxBitmap wxImage::ConvertToBitmap() const
2265 {
2266 if ( !Ok() )
2267 return wxNullBitmap;
2268 wxBitmap bitmap; // remove
2269 // TODO:
2270 /*
2271 int sizeLimit = 1024*768*3;
2272
2273 // width and height of the device-dependent bitmap
2274 int width = GetWidth();
2275 int bmpHeight = GetHeight();
2276
2277 // calc the number of bytes per scanline and padding
2278 int bytePerLine = width*3;
2279 int sizeDWORD = sizeof( DWORD );
2280 int lineBoundary = bytePerLine % sizeDWORD;
2281 int padding = 0;
2282 if( lineBoundary > 0 )
2283 {
2284 padding = sizeDWORD - lineBoundary;
2285 bytePerLine += padding;
2286 }
2287 // calc the number of DIBs and heights of DIBs
2288 int numDIB = 1;
2289 int hRemain = 0;
2290 int height = sizeLimit/bytePerLine;
2291 if( height >= bmpHeight )
2292 height = bmpHeight;
2293 else
2294 {
2295 numDIB = bmpHeight / height;
2296 hRemain = bmpHeight % height;
2297 if( hRemain >0 ) numDIB++;
2298 }
2299
2300 // set bitmap parameters
2301 wxBitmap bitmap;
2302 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
2303 bitmap.SetWidth( width );
2304 bitmap.SetHeight( bmpHeight );
2305 bitmap.SetDepth( wxDisplayDepth() );
2306
2307 // create a DIB header
2308 int headersize = sizeof(BITMAPINFOHEADER);
2309 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
2310 wxCHECK_MSG( lpDIBh, bitmap, wxT("could not allocate memory for DIB header") );
2311 // Fill in the DIB header
2312 lpDIBh->bmiHeader.biSize = headersize;
2313 lpDIBh->bmiHeader.biWidth = (DWORD)width;
2314 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2315 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2316 // the general formula for biSizeImage:
2317 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
2318 lpDIBh->bmiHeader.biPlanes = 1;
2319 lpDIBh->bmiHeader.biBitCount = 24;
2320 lpDIBh->bmiHeader.biCompression = BI_RGB;
2321 lpDIBh->bmiHeader.biClrUsed = 0;
2322 // These seem not really needed for our purpose here.
2323 lpDIBh->bmiHeader.biClrImportant = 0;
2324 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2325 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2326 // memory for DIB data
2327 unsigned char *lpBits;
2328 lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
2329 if( !lpBits )
2330 {
2331 wxFAIL_MSG( wxT("could not allocate memory for DIB") );
2332 free( lpDIBh );
2333 return bitmap;
2334 }
2335
2336 // create and set the device-dependent bitmap
2337 HDC hdc = ::GetDC(NULL);
2338 HDC memdc = ::CreateCompatibleDC( hdc );
2339 HBITMAP hbitmap;
2340 hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
2341 ::SelectObject( memdc, hbitmap);
2342
2343 // copy image data into DIB data and then into DDB (in a loop)
2344 unsigned char *data = GetData();
2345 int i, j, n;
2346 int origin = 0;
2347 unsigned char *ptdata = data;
2348 unsigned char *ptbits;
2349
2350 for( n=0; n<numDIB; n++ )
2351 {
2352 if( numDIB > 1 && n == numDIB-1 && hRemain > 0 )
2353 {
2354 // redefine height and size of the (possibly) last smaller DIB
2355 // memory is not reallocated
2356 height = hRemain;
2357 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2358 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2359 }
2360 ptbits = lpBits;
2361
2362 for( j=0; j<height; j++ )
2363 {
2364 for( i=0; i<width; i++ )
2365 {
2366 *(ptbits++) = *(ptdata+2);
2367 *(ptbits++) = *(ptdata+1);
2368 *(ptbits++) = *(ptdata );
2369 ptdata += 3;
2370 }
2371 for( i=0; i< padding; i++ ) *(ptbits++) = 0;
2372 }
2373 ::StretchDIBits( memdc, 0, origin, width, height,\
2374 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2375 origin += height;
2376 // if numDIB = 1, lines below can also be used
2377 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
2378 // The above line is equivalent to the following two lines.
2379 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2380 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
2381 // or the following lines
2382 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2383 // HDC memdc = ::CreateCompatibleDC( hdc );
2384 // ::SelectObject( memdc, hbitmap);
2385 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
2386 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
2387 // ::SelectObject( memdc, 0 );
2388 // ::DeleteDC( memdc );
2389 }
2390 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
2391
2392 // similarly, created an mono-bitmap for the possible mask
2393 if( HasMask() )
2394 {
2395 hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL );
2396 ::SelectObject( memdc, hbitmap);
2397 if( numDIB == 1 ) height = bmpHeight;
2398 else height = sizeLimit/bytePerLine;
2399 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2400 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2401 origin = 0;
2402 unsigned char r = GetMaskRed();
2403 unsigned char g = GetMaskGreen();
2404 unsigned char b = GetMaskBlue();
2405 unsigned char zero = 0, one = 255;
2406 ptdata = data;
2407 for( n=0; n<numDIB; n++ )
2408 {
2409 if( numDIB > 1 && n == numDIB - 1 && hRemain > 0 )
2410 {
2411 // redefine height and size of the (possibly) last smaller DIB
2412 // memory is not reallocated
2413 height = hRemain;
2414 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2415 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2416 }
2417 ptbits = lpBits;
2418 for( int j=0; j<height; j++ )
2419 {
2420 for(i=0; i<width; i++ )
2421 {
2422 if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
2423 {
2424 *(ptbits++) = one;
2425 *(ptbits++) = one;
2426 *(ptbits++) = one;
2427 }
2428 else
2429 {
2430 *(ptbits++) = zero;
2431 *(ptbits++) = zero;
2432 *(ptbits++) = zero;
2433 }
2434 }
2435 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
2436 }
2437 ::StretchDIBits( memdc, 0, origin, width, height,\
2438 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2439 origin += height;
2440 }
2441 // create a wxMask object
2442 wxMask *mask = new wxMask();
2443 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
2444 bitmap.SetMask( mask );
2445 }
2446
2447 // free allocated resources
2448 ::SelectObject( memdc, 0 );
2449 ::DeleteDC( memdc );
2450 ::ReleaseDC(NULL, hdc);
2451 free(lpDIBh);
2452 free(lpBits);
2453
2454 // check the wxBitmap object
2455 if( bitmap.GetHBITMAP() )
2456 bitmap.SetOk( TRUE );
2457 else
2458 bitmap.SetOk( FALSE );
2459 */
2460 return bitmap;
2461 }
2462
2463 wxImage::wxImage( const wxBitmap &bitmap )
2464 {
2465 // check the bitmap
2466 if( !bitmap.Ok() )
2467 {
2468 wxFAIL_MSG( wxT("invalid bitmap") );
2469 return;
2470 }
2471
2472 // create an wxImage object
2473 int width = bitmap.GetWidth();
2474 int height = bitmap.GetHeight();
2475 Create( width, height );
2476 unsigned char *data = GetData();
2477 if( !data )
2478 {
2479 wxFAIL_MSG( wxT("could not allocate data for image") );
2480 return;
2481 }
2482
2483 // calc the number of bytes per scanline and padding in the DIB
2484 int bytePerLine = width*3;
2485 int sizeDWORD = sizeof( DWORD );
2486 int lineBoundary = bytePerLine % sizeDWORD;
2487 int padding = 0;
2488 if( lineBoundary > 0 )
2489 {
2490 padding = sizeDWORD - lineBoundary;
2491 bytePerLine += padding;
2492 }
2493 // TODO:
2494 /*
2495 // create a DIB header
2496 int headersize = sizeof(BITMAPINFOHEADER);
2497 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
2498 if( !lpDIBh )
2499 {
2500 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
2501 free( data );
2502 return;
2503 }
2504 // Fill in the DIB header
2505 lpDIBh->bmiHeader.biSize = headersize;
2506 lpDIBh->bmiHeader.biWidth = width;
2507 lpDIBh->bmiHeader.biHeight = -height;
2508 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
2509 lpDIBh->bmiHeader.biPlanes = 1;
2510 lpDIBh->bmiHeader.biBitCount = 24;
2511 lpDIBh->bmiHeader.biCompression = BI_RGB;
2512 lpDIBh->bmiHeader.biClrUsed = 0;
2513 // These seem not really needed for our purpose here.
2514 lpDIBh->bmiHeader.biClrImportant = 0;
2515 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2516 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2517 // memory for DIB data
2518 unsigned char *lpBits;
2519 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
2520 if( !lpBits )
2521 {
2522 wxFAIL_MSG( wxT("could not allocate data for DIB") );
2523 free( data );
2524 free( lpDIBh );
2525 return;
2526 }
2527
2528 // copy data from the device-dependent bitmap to the DIB
2529 HDC hdc = ::GetDC(NULL);
2530 HBITMAP hbitmap;
2531 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
2532 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2533
2534 // copy DIB data into the wxImage object
2535 int i, j;
2536 unsigned char *ptdata = data;
2537 unsigned char *ptbits = lpBits;
2538 for( i=0; i<height; i++ )
2539 {
2540 for( j=0; j<width; j++ )
2541 {
2542 *(ptdata++) = *(ptbits+2);
2543 *(ptdata++) = *(ptbits+1);
2544 *(ptdata++) = *(ptbits );
2545 ptbits += 3;
2546 }
2547 ptbits += padding;
2548 }
2549
2550 // similarly, set data according to the possible mask bitmap
2551 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
2552 {
2553 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
2554 // memory DC created, color set, data copied, and memory DC deleted
2555 HDC memdc = ::CreateCompatibleDC( hdc );
2556 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
2557 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
2558 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2559 ::DeleteDC( memdc );
2560 // background color set to RGB(16,16,16) in consistent with wxGTK
2561 unsigned char r=16, g=16, b=16;
2562 ptdata = data;
2563 ptbits = lpBits;
2564 for( i=0; i<height; i++ )
2565 {
2566 for( j=0; j<width; j++ )
2567 {
2568 if( *ptbits != 0 )
2569 ptdata += 3;
2570 else
2571 {
2572 *(ptdata++) = r;
2573 *(ptdata++) = g;
2574 *(ptdata++) = b;
2575 }
2576 ptbits += 3;
2577 }
2578 ptbits += padding;
2579 }
2580 SetMaskColour( r, g, b );
2581 SetMask( TRUE );
2582 }
2583 else
2584 {
2585 SetMask( FALSE );
2586 }
2587 // free allocated resources
2588 ::ReleaseDC(NULL, hdc);
2589 free(lpDIBh);
2590 free(lpBits);
2591 */
2592 }
2593
2594 #endif
2595
2596 // A module to allow wxImage initialization/cleanup
2597 // without calling these functions from app.cpp or from
2598 // the user's application.
2599
2600 class wxImageModule: public wxModule
2601 {
2602 DECLARE_DYNAMIC_CLASS(wxImageModule)
2603 public:
2604 wxImageModule() {}
2605 bool OnInit() { wxImage::InitStandardHandlers(); return TRUE; };
2606 void OnExit() { wxImage::CleanUpHandlers(); };
2607 };
2608
2609 IMPLEMENT_DYNAMIC_CLASS(wxImageModule, wxModule)
2610
2611
2612 //-----------------------------------------------------------------------------
2613
2614 // GRG, Dic/99
2615 // Counts and returns the number of different colours. Optionally stops
2616 // when it exceeds 'stopafter' different colours. This is useful, for
2617 // example, to see if the image can be saved as 8-bit (256 colour or
2618 // less, in this case it would be invoked as CountColours(256)). Default
2619 // value for stopafter is -1 (don't care).
2620 //
2621 unsigned long wxImage::CountColours( unsigned long stopafter )
2622 {
2623 wxHashTable h;
2624 wxNode *node;
2625 wxHNode *hnode;
2626 unsigned char r, g, b, *p;
2627 unsigned long size, nentries, key;
2628
2629 p = GetData();
2630 size = GetWidth() * GetHeight();
2631 nentries = 0;
2632
2633 for (unsigned long j = 0; (j < size) && (nentries <= stopafter) ; j++)
2634 {
2635 r = *(p++);
2636 g = *(p++);
2637 b = *(p++);
2638 key = (r << 16) | (g << 8) | b;
2639
2640 hnode = (wxHNode *) h.Get(key);
2641
2642 if (!hnode)
2643 {
2644 h.Put(key, (wxObject *)(new wxHNode));
2645 nentries++;
2646 }
2647 }
2648
2649 // delete all HNodes
2650 h.BeginFind();
2651 while ((node = h.Next()) != NULL)
2652 delete (wxHNode *)node->GetData();
2653
2654 return nentries;
2655 }
2656
2657
2658 // GRG, Dic/99
2659 // Computes the histogram of the image and fills a hash table, indexed
2660 // with integer keys built as 0xRRGGBB, containing wxHNode objects. Each
2661 // wxHNode contains an 'index' (useful to build a palette with the image
2662 // colours) and a 'value', which is the number of pixels in the image with
2663 // that colour.
2664 //
2665 unsigned long wxImage::ComputeHistogram( wxHashTable &h )
2666 {
2667 unsigned char r, g, b, *p;
2668 unsigned long size, nentries, key;
2669 wxHNode *hnode;
2670
2671 p = GetData();
2672 size = GetWidth() * GetHeight();
2673 nentries = 0;
2674
2675 for (unsigned long j = 0; j < size; j++)
2676 {
2677 r = *(p++);
2678 g = *(p++);
2679 b = *(p++);
2680 key = (r << 16) | (g << 8) | b;
2681
2682 hnode = (wxHNode *) h.Get(key);
2683
2684 if (hnode)
2685 hnode->value++;
2686 else
2687 {
2688 hnode = new wxHNode();
2689 hnode->index = nentries++;
2690 hnode->value = 1;
2691
2692 h.Put(key, (wxObject *)hnode);
2693 }
2694 }
2695
2696 return nentries;
2697 }
2698
2699