]> git.saurik.com Git - wxWidgets.git/blob - src/common/image.cpp
include "module.h"
[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::ConvertToBitmap() const
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.SetPixmap( gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, -1 ) );
1327
1328 // Retrieve depth
1329
1330 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
1331 if (visual == NULL) visual = gdk_visual_get_system();
1332 int bpp = visual->depth;
1333
1334 bitmap.SetDepth( bpp );
1335
1336 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
1337 if (bpp < 8) bpp = 8;
1338
1339 #if (GTK_MINOR_VERSION > 0)
1340
1341 if (!HasMask() && (bpp > 8))
1342 {
1343 static bool s_hasInitialized = FALSE;
1344
1345 if (!s_hasInitialized)
1346 {
1347 gdk_rgb_init();
1348 s_hasInitialized = TRUE;
1349 }
1350
1351 GdkGC *gc = gdk_gc_new( bitmap.GetPixmap() );
1352
1353 gdk_draw_rgb_image( bitmap.GetPixmap(),
1354 gc,
1355 0, 0,
1356 width, height,
1357 GDK_RGB_DITHER_NONE,
1358 GetData(),
1359 width*3 );
1360
1361 gdk_gc_unref( gc );
1362
1363 return bitmap;
1364 }
1365
1366 #endif
1367
1368 // Create picture image
1369
1370 GdkImage *data_image =
1371 gdk_image_new( GDK_IMAGE_FASTEST, gdk_visual_get_system(), width, height );
1372
1373 // Create mask image
1374
1375 GdkImage *mask_image = (GdkImage*) NULL;
1376
1377 if (HasMask())
1378 {
1379 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1380
1381 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1382
1383 wxMask *mask = new wxMask();
1384 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1385
1386 bitmap.SetMask( mask );
1387 }
1388
1389 // Render
1390
1391 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1392 byte_order b_o = RGB;
1393
1394 if (bpp >= 24)
1395 {
1396 GdkVisual *visual = gdk_visual_get_system();
1397 if ((visual->red_mask > visual->green_mask) && (visual->green_mask > visual->blue_mask)) b_o = RGB;
1398 else if ((visual->red_mask > visual->blue_mask) && (visual->blue_mask > visual->green_mask)) b_o = RGB;
1399 else if ((visual->blue_mask > visual->red_mask) && (visual->red_mask > visual->green_mask)) b_o = BRG;
1400 else if ((visual->blue_mask > visual->green_mask) && (visual->green_mask > visual->red_mask)) b_o = BGR;
1401 else if ((visual->green_mask > visual->red_mask) && (visual->red_mask > visual->blue_mask)) b_o = GRB;
1402 else if ((visual->green_mask > visual->blue_mask) && (visual->blue_mask > visual->red_mask)) b_o = GBR;
1403 }
1404
1405 int r_mask = GetMaskRed();
1406 int g_mask = GetMaskGreen();
1407 int b_mask = GetMaskBlue();
1408
1409 unsigned char* data = GetData();
1410
1411 int index = 0;
1412 for (int y = 0; y < height; y++)
1413 {
1414 for (int x = 0; x < width; x++)
1415 {
1416 int r = data[index];
1417 index++;
1418 int g = data[index];
1419 index++;
1420 int b = data[index];
1421 index++;
1422
1423 if (HasMask())
1424 {
1425 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1426 gdk_image_put_pixel( mask_image, x, y, 1 );
1427 else
1428 gdk_image_put_pixel( mask_image, x, y, 0 );
1429 }
1430
1431 if (HasMask())
1432 {
1433 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1434 gdk_image_put_pixel( mask_image, x, y, 1 );
1435 else
1436 gdk_image_put_pixel( mask_image, x, y, 0 );
1437 }
1438
1439 switch (bpp)
1440 {
1441 case 8:
1442 {
1443 int pixel = -1;
1444 if (wxTheApp->m_colorCube)
1445 {
1446 pixel = wxTheApp->m_colorCube[ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1447 }
1448 else
1449 {
1450 GdkColormap *cmap = gtk_widget_get_default_colormap();
1451 GdkColor *colors = cmap->colors;
1452 int max = 3 * (65536);
1453
1454 for (int i = 0; i < cmap->size; i++)
1455 {
1456 int rdiff = (r << 8) - colors[i].red;
1457 int gdiff = (g << 8) - colors[i].green;
1458 int bdiff = (b << 8) - colors[i].blue;
1459 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1460 if (sum < max) { pixel = i; max = sum; }
1461 }
1462 }
1463
1464 gdk_image_put_pixel( data_image, x, y, pixel );
1465
1466 break;
1467 }
1468 case 15:
1469 {
1470 guint32 pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1471 gdk_image_put_pixel( data_image, x, y, pixel );
1472 break;
1473 }
1474 case 16:
1475 {
1476 guint32 pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1477 gdk_image_put_pixel( data_image, x, y, pixel );
1478 break;
1479 }
1480 case 32:
1481 case 24:
1482 {
1483 guint32 pixel = 0;
1484 switch (b_o)
1485 {
1486 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1487 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1488 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1489 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1490 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1491 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1492 }
1493 gdk_image_put_pixel( data_image, x, y, pixel );
1494 }
1495 default: break;
1496 }
1497 } // for
1498 } // for
1499
1500 // Blit picture
1501
1502 GdkGC *data_gc = gdk_gc_new( bitmap.GetPixmap() );
1503
1504 gdk_draw_image( bitmap.GetPixmap(), data_gc, data_image, 0, 0, 0, 0, width, height );
1505
1506 gdk_image_destroy( data_image );
1507 gdk_gc_unref( data_gc );
1508
1509 // Blit mask
1510
1511 if (HasMask())
1512 {
1513 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
1514
1515 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
1516
1517 gdk_image_destroy( mask_image );
1518 gdk_gc_unref( mask_gc );
1519 }
1520
1521 return bitmap;
1522 }
1523
1524 wxImage::wxImage( const wxBitmap &bitmap )
1525 {
1526 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
1527
1528 GdkImage *gdk_image = (GdkImage*) NULL;
1529 if (bitmap.GetPixmap())
1530 {
1531 gdk_image = gdk_image_get( bitmap.GetPixmap(),
1532 0, 0,
1533 bitmap.GetWidth(), bitmap.GetHeight() );
1534 } else
1535 if (bitmap.GetBitmap())
1536 {
1537 gdk_image = gdk_image_get( bitmap.GetBitmap(),
1538 0, 0,
1539 bitmap.GetWidth(), bitmap.GetHeight() );
1540 } else
1541 {
1542 wxFAIL_MSG( wxT("Ill-formed bitmap") );
1543 }
1544
1545 wxCHECK_RET( gdk_image, wxT("couldn't create image") );
1546
1547 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1548 char unsigned *data = GetData();
1549
1550 if (!data)
1551 {
1552 gdk_image_destroy( gdk_image );
1553 wxFAIL_MSG( wxT("couldn't create image") );
1554 return;
1555 }
1556
1557 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1558 if (bitmap.GetMask())
1559 {
1560 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1561 0, 0,
1562 bitmap.GetWidth(), bitmap.GetHeight() );
1563
1564 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1565 }
1566
1567 int bpp = -1;
1568 if (bitmap.GetPixmap())
1569 {
1570 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
1571
1572 if (visual == NULL) visual = gdk_window_get_visual( (GdkWindow*) &gdk_root_parent );
1573 bpp = visual->depth;
1574 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
1575 }
1576 if (bitmap.GetBitmap())
1577 {
1578 bpp = 1;
1579 }
1580
1581 GdkColormap *cmap = gtk_widget_get_default_colormap();
1582
1583 long pos = 0;
1584 for (int j = 0; j < bitmap.GetHeight(); j++)
1585 {
1586 for (int i = 0; i < bitmap.GetWidth(); i++)
1587 {
1588 wxInt32 pixel = gdk_image_get_pixel( gdk_image, i, j );
1589 if (bpp == 1)
1590 {
1591 if (pixel == 0)
1592 {
1593 data[pos] = 0;
1594 data[pos+1] = 0;
1595 data[pos+2] = 0;
1596 }
1597 else
1598 {
1599 data[pos] = 255;
1600 data[pos+1] = 255;
1601 data[pos+2] = 255;
1602 }
1603 } else if (bpp <= 8)
1604 {
1605 data[pos] = cmap->colors[pixel].red >> 8;
1606 data[pos+1] = cmap->colors[pixel].green >> 8;
1607 data[pos+2] = cmap->colors[pixel].blue >> 8;
1608 } else if (bpp == 15)
1609 {
1610 #if (wxBYTE_ORDER == wxBIG_ENDIAN)
1611 // ?
1612 #endif
1613 data[pos] = (pixel >> 7) & 0xf8;
1614 data[pos+1] = (pixel >> 2) & 0xf8;
1615 data[pos+2] = (pixel << 3) & 0xf8;
1616 } else if (bpp == 16)
1617 {
1618 #if (wxBYTE_ORDER == wxBIG_ENDIAN)
1619 // ?
1620 #endif
1621 data[pos] = (pixel >> 8) & 0xf8;
1622 data[pos+1] = (pixel >> 3) & 0xfc;
1623 data[pos+2] = (pixel << 3) & 0xf8;
1624 } else
1625 {
1626 #if (wxBYTE_ORDER == wxBIG_ENDIAN)
1627 data[pos] = (pixel) & 0xff; // Red
1628 data[pos+1] = (pixel >> 8) & 0xff; // Green
1629 data[pos+2] = (pixel >> 16) & 0xff; // Blue
1630 #else
1631 data[pos] = (pixel >> 16) & 0xff;
1632 data[pos+1] = (pixel >> 8) & 0xff;
1633 data[pos+2] = pixel & 0xff;
1634 #endif
1635 }
1636
1637 if (gdk_image_mask)
1638 {
1639 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1640 if (mask_pixel == 0)
1641 {
1642 data[pos] = 16;
1643 data[pos+1] = 16;
1644 data[pos+2] = 16;
1645 }
1646 }
1647
1648 pos += 3;
1649 }
1650 }
1651
1652 gdk_image_destroy( gdk_image );
1653 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1654 }
1655
1656 #endif
1657
1658 //-----------------------------------------------------------------------------
1659 // Motif conversion routines
1660 //-----------------------------------------------------------------------------
1661
1662 #ifdef __WXMOTIF__
1663 #ifdef __VMS__
1664 #pragma message disable nosimpint
1665 #endif
1666 #include <Xm/Xm.h>
1667 #ifdef __VMS__
1668 #pragma message enable nosimpint
1669 #endif
1670 #include "wx/utils.h"
1671 #include <math.h>
1672
1673 wxBitmap wxImage::ConvertToBitmap() const
1674 {
1675 wxBitmap bitmap;
1676
1677 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
1678
1679 int width = GetWidth();
1680 int height = GetHeight();
1681
1682 bitmap.SetHeight( height );
1683 bitmap.SetWidth( width );
1684
1685 Display *dpy = (Display*) wxGetDisplay();
1686 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1687 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1688
1689 // Create image
1690
1691 XImage *data_image = XCreateImage( dpy, vis, bpp, ZPixmap, 0, 0, width, height, 32, 0 );
1692 data_image->data = (char*) malloc( data_image->bytes_per_line * data_image->height );
1693
1694 bitmap.Create( width, height, bpp );
1695
1696 /*
1697 // Create mask
1698
1699 GdkImage *mask_image = (GdkImage*) NULL;
1700
1701 if (HasMask())
1702 {
1703 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1704
1705 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1706
1707 wxMask *mask = new wxMask();
1708 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1709
1710 bitmap.SetMask( mask );
1711 }
1712 */
1713
1714 // Retrieve depth info
1715
1716 XVisualInfo vinfo_template;
1717 XVisualInfo *vi;
1718
1719 vinfo_template.visual = vis;
1720 vinfo_template.visualid = XVisualIDFromVisual( vis );
1721 vinfo_template.depth = bpp;
1722 int nitem = 0;
1723
1724 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1725
1726 wxCHECK_MSG( vi, wxNullBitmap, wxT("no visual") );
1727
1728 XFree( vi );
1729
1730 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1731 if (bpp < 8) bpp = 8;
1732
1733 // Render
1734
1735 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1736 byte_order b_o = RGB;
1737
1738 if (bpp >= 24)
1739 {
1740 if ((vi->red_mask > vi->green_mask) && (vi->green_mask > vi->blue_mask)) b_o = RGB;
1741 else if ((vi->red_mask > vi->blue_mask) && (vi->blue_mask > vi->green_mask)) b_o = RGB;
1742 else if ((vi->blue_mask > vi->red_mask) && (vi->red_mask > vi->green_mask)) b_o = BRG;
1743 else if ((vi->blue_mask > vi->green_mask) && (vi->green_mask > vi->red_mask)) b_o = BGR;
1744 else if ((vi->green_mask > vi->red_mask) && (vi->red_mask > vi->blue_mask)) b_o = GRB;
1745 else if ((vi->green_mask > vi->blue_mask) && (vi->blue_mask > vi->red_mask)) b_o = GBR;
1746 }
1747
1748 /*
1749 int r_mask = GetMaskRed();
1750 int g_mask = GetMaskGreen();
1751 int b_mask = GetMaskBlue();
1752 */
1753
1754 XColor colors[256];
1755 if (bpp == 8)
1756 {
1757 Colormap cmap = (Colormap) wxTheApp->GetMainColormap( dpy );
1758
1759 for (int i = 0; i < 256; i++) colors[i].pixel = i;
1760 XQueryColors( dpy, cmap, colors, 256 );
1761 }
1762
1763 unsigned char* data = GetData();
1764
1765 int index = 0;
1766 for (int y = 0; y < height; y++)
1767 {
1768 for (int x = 0; x < width; x++)
1769 {
1770 int r = data[index];
1771 index++;
1772 int g = data[index];
1773 index++;
1774 int b = data[index];
1775 index++;
1776
1777 /*
1778 if (HasMask())
1779 {
1780 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1781 gdk_image_put_pixel( mask_image, x, y, 1 );
1782 else
1783 gdk_image_put_pixel( mask_image, x, y, 0 );
1784 }
1785 */
1786
1787 switch (bpp)
1788 {
1789 case 8:
1790 {
1791 int pixel = -1;
1792 /*
1793 if (wxTheApp->m_colorCube)
1794 {
1795 pixel = wxTheApp->m_colorCube
1796 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1797 }
1798 else
1799 {
1800 */
1801 int max = 3 * (65536);
1802 for (int i = 0; i < 256; i++)
1803 {
1804 int rdiff = (r << 8) - colors[i].red;
1805 int gdiff = (g << 8) - colors[i].green;
1806 int bdiff = (b << 8) - colors[i].blue;
1807 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1808 if (sum < max) { pixel = i; max = sum; }
1809 }
1810 /*
1811 }
1812 */
1813 XPutPixel( data_image, x, y, pixel );
1814 break;
1815 }
1816 case 15:
1817 {
1818 int pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1819 XPutPixel( data_image, x, y, pixel );
1820 break;
1821 }
1822 case 16:
1823 {
1824 int pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1825 XPutPixel( data_image, x, y, pixel );
1826 break;
1827 }
1828 case 32:
1829 case 24:
1830 {
1831 int pixel = 0;
1832 switch (b_o)
1833 {
1834 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1835 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1836 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1837 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1838 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1839 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1840 }
1841 XPutPixel( data_image, x, y, pixel );
1842 }
1843 default: break;
1844 }
1845 } // for
1846 } // for
1847
1848 // Blit picture
1849
1850 XGCValues gcvalues;
1851 gcvalues.foreground = BlackPixel( dpy, DefaultScreen( dpy ) );
1852 GC gc = XCreateGC( dpy, RootWindow ( dpy, DefaultScreen(dpy) ), GCForeground, &gcvalues );
1853 XPutImage( dpy, (Drawable)bitmap.GetPixmap(), gc, data_image, 0, 0, 0, 0, width, height );
1854
1855 XDestroyImage( data_image );
1856 XFreeGC( dpy, gc );
1857
1858 /*
1859 // Blit mask
1860
1861 if (HasMask())
1862 {
1863 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
1864
1865 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
1866
1867 gdk_image_destroy( mask_image );
1868 gdk_gc_unref( mask_gc );
1869 }
1870 */
1871
1872 return bitmap;
1873 }
1874
1875 wxImage::wxImage( const wxBitmap &bitmap )
1876 {
1877 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
1878
1879 Display *dpy = (Display*) wxGetDisplay();
1880 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1881 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1882
1883 XImage *ximage = XGetImage( dpy,
1884 (Drawable)bitmap.GetPixmap(),
1885 0, 0,
1886 bitmap.GetWidth(), bitmap.GetHeight(),
1887 AllPlanes, ZPixmap );
1888
1889 wxCHECK_RET( ximage, wxT("couldn't create image") );
1890
1891 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1892 char unsigned *data = GetData();
1893
1894 if (!data)
1895 {
1896 XDestroyImage( ximage );
1897 wxFAIL_MSG( wxT("couldn't create image") );
1898 return;
1899 }
1900
1901 /*
1902 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1903 if (bitmap.GetMask())
1904 {
1905 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1906 0, 0,
1907 bitmap.GetWidth(), bitmap.GetHeight() );
1908
1909 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1910 }
1911 */
1912
1913 // Retrieve depth info
1914
1915 XVisualInfo vinfo_template;
1916 XVisualInfo *vi;
1917
1918 vinfo_template.visual = vis;
1919 vinfo_template.visualid = XVisualIDFromVisual( vis );
1920 vinfo_template.depth = bpp;
1921 int nitem = 0;
1922
1923 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1924
1925 wxCHECK_RET( vi, wxT("no visual") );
1926
1927 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1928
1929 XFree( vi );
1930
1931 XColor colors[256];
1932 if (bpp == 8)
1933 {
1934 Colormap cmap = (Colormap)wxTheApp->GetMainColormap( dpy );
1935
1936 for (int i = 0; i < 256; i++) colors[i].pixel = i;
1937 XQueryColors( dpy, cmap, colors, 256 );
1938 }
1939
1940 long pos = 0;
1941 for (int j = 0; j < bitmap.GetHeight(); j++)
1942 {
1943 for (int i = 0; i < bitmap.GetWidth(); i++)
1944 {
1945 int pixel = XGetPixel( ximage, i, j );
1946 if (bpp <= 8)
1947 {
1948 data[pos] = colors[pixel].red >> 8;
1949 data[pos+1] = colors[pixel].green >> 8;
1950 data[pos+2] = colors[pixel].blue >> 8;
1951 } else if (bpp == 15)
1952 {
1953 data[pos] = (pixel >> 7) & 0xf8;
1954 data[pos+1] = (pixel >> 2) & 0xf8;
1955 data[pos+2] = (pixel << 3) & 0xf8;
1956 } else if (bpp == 16)
1957 {
1958 data[pos] = (pixel >> 8) & 0xf8;
1959 data[pos+1] = (pixel >> 3) & 0xfc;
1960 data[pos+2] = (pixel << 3) & 0xf8;
1961 } else
1962 {
1963 data[pos] = (pixel >> 16) & 0xff;
1964 data[pos+1] = (pixel >> 8) & 0xff;
1965 data[pos+2] = pixel & 0xff;
1966 }
1967
1968 /*
1969 if (gdk_image_mask)
1970 {
1971 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1972 if (mask_pixel == 0)
1973 {
1974 data[pos] = 16;
1975 data[pos+1] = 16;
1976 data[pos+2] = 16;
1977 }
1978 }
1979 */
1980
1981 pos += 3;
1982 }
1983 }
1984
1985 XDestroyImage( ximage );
1986 /*
1987 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1988 */
1989 }
1990 #endif
1991
1992 #ifdef __WXPM__
1993 // OS/2 Presentation manager conversion routings
1994
1995 wxBitmap wxImage::ConvertToBitmap() const
1996 {
1997 if ( !Ok() )
1998 return wxNullBitmap;
1999 wxBitmap bitmap; // remove
2000 // TODO:
2001 /*
2002 int sizeLimit = 1024*768*3;
2003
2004 // width and height of the device-dependent bitmap
2005 int width = GetWidth();
2006 int bmpHeight = GetHeight();
2007
2008 // calc the number of bytes per scanline and padding
2009 int bytePerLine = width*3;
2010 int sizeDWORD = sizeof( DWORD );
2011 int lineBoundary = bytePerLine % sizeDWORD;
2012 int padding = 0;
2013 if( lineBoundary > 0 )
2014 {
2015 padding = sizeDWORD - lineBoundary;
2016 bytePerLine += padding;
2017 }
2018 // calc the number of DIBs and heights of DIBs
2019 int numDIB = 1;
2020 int hRemain = 0;
2021 int height = sizeLimit/bytePerLine;
2022 if( height >= bmpHeight )
2023 height = bmpHeight;
2024 else
2025 {
2026 numDIB = bmpHeight / height;
2027 hRemain = bmpHeight % height;
2028 if( hRemain >0 ) numDIB++;
2029 }
2030
2031 // set bitmap parameters
2032 wxBitmap bitmap;
2033 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
2034 bitmap.SetWidth( width );
2035 bitmap.SetHeight( bmpHeight );
2036 bitmap.SetDepth( wxDisplayDepth() );
2037
2038 // create a DIB header
2039 int headersize = sizeof(BITMAPINFOHEADER);
2040 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
2041 wxCHECK_MSG( lpDIBh, bitmap, wxT("could not allocate memory for DIB header") );
2042 // Fill in the DIB header
2043 lpDIBh->bmiHeader.biSize = headersize;
2044 lpDIBh->bmiHeader.biWidth = (DWORD)width;
2045 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2046 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2047 // the general formula for biSizeImage:
2048 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
2049 lpDIBh->bmiHeader.biPlanes = 1;
2050 lpDIBh->bmiHeader.biBitCount = 24;
2051 lpDIBh->bmiHeader.biCompression = BI_RGB;
2052 lpDIBh->bmiHeader.biClrUsed = 0;
2053 // These seem not really needed for our purpose here.
2054 lpDIBh->bmiHeader.biClrImportant = 0;
2055 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2056 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2057 // memory for DIB data
2058 unsigned char *lpBits;
2059 lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
2060 if( !lpBits )
2061 {
2062 wxFAIL_MSG( wxT("could not allocate memory for DIB") );
2063 free( lpDIBh );
2064 return bitmap;
2065 }
2066
2067 // create and set the device-dependent bitmap
2068 HDC hdc = ::GetDC(NULL);
2069 HDC memdc = ::CreateCompatibleDC( hdc );
2070 HBITMAP hbitmap;
2071 hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
2072 ::SelectObject( memdc, hbitmap);
2073
2074 // copy image data into DIB data and then into DDB (in a loop)
2075 unsigned char *data = GetData();
2076 int i, j, n;
2077 int origin = 0;
2078 unsigned char *ptdata = data;
2079 unsigned char *ptbits;
2080
2081 for( n=0; n<numDIB; n++ )
2082 {
2083 if( numDIB > 1 && n == numDIB-1 && hRemain > 0 )
2084 {
2085 // redefine height and size of the (possibly) last smaller DIB
2086 // memory is not reallocated
2087 height = hRemain;
2088 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2089 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2090 }
2091 ptbits = lpBits;
2092
2093 for( j=0; j<height; j++ )
2094 {
2095 for( i=0; i<width; i++ )
2096 {
2097 *(ptbits++) = *(ptdata+2);
2098 *(ptbits++) = *(ptdata+1);
2099 *(ptbits++) = *(ptdata );
2100 ptdata += 3;
2101 }
2102 for( i=0; i< padding; i++ ) *(ptbits++) = 0;
2103 }
2104 ::StretchDIBits( memdc, 0, origin, width, height,\
2105 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2106 origin += height;
2107 // if numDIB = 1, lines below can also be used
2108 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
2109 // The above line is equivalent to the following two lines.
2110 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2111 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
2112 // or the following lines
2113 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2114 // HDC memdc = ::CreateCompatibleDC( hdc );
2115 // ::SelectObject( memdc, hbitmap);
2116 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
2117 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
2118 // ::SelectObject( memdc, 0 );
2119 // ::DeleteDC( memdc );
2120 }
2121 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
2122
2123 // similarly, created an mono-bitmap for the possible mask
2124 if( HasMask() )
2125 {
2126 hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL );
2127 ::SelectObject( memdc, hbitmap);
2128 if( numDIB == 1 ) height = bmpHeight;
2129 else height = sizeLimit/bytePerLine;
2130 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2131 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2132 origin = 0;
2133 unsigned char r = GetMaskRed();
2134 unsigned char g = GetMaskGreen();
2135 unsigned char b = GetMaskBlue();
2136 unsigned char zero = 0, one = 255;
2137 ptdata = data;
2138 for( n=0; n<numDIB; n++ )
2139 {
2140 if( numDIB > 1 && n == numDIB - 1 && hRemain > 0 )
2141 {
2142 // redefine height and size of the (possibly) last smaller DIB
2143 // memory is not reallocated
2144 height = hRemain;
2145 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2146 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2147 }
2148 ptbits = lpBits;
2149 for( int j=0; j<height; j++ )
2150 {
2151 for(i=0; i<width; i++ )
2152 {
2153 if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
2154 {
2155 *(ptbits++) = one;
2156 *(ptbits++) = one;
2157 *(ptbits++) = one;
2158 }
2159 else
2160 {
2161 *(ptbits++) = zero;
2162 *(ptbits++) = zero;
2163 *(ptbits++) = zero;
2164 }
2165 }
2166 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
2167 }
2168 ::StretchDIBits( memdc, 0, origin, width, height,\
2169 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2170 origin += height;
2171 }
2172 // create a wxMask object
2173 wxMask *mask = new wxMask();
2174 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
2175 bitmap.SetMask( mask );
2176 }
2177
2178 // free allocated resources
2179 ::SelectObject( memdc, 0 );
2180 ::DeleteDC( memdc );
2181 ::ReleaseDC(NULL, hdc);
2182 free(lpDIBh);
2183 free(lpBits);
2184
2185 // check the wxBitmap object
2186 if( bitmap.GetHBITMAP() )
2187 bitmap.SetOk( TRUE );
2188 else
2189 bitmap.SetOk( FALSE );
2190 */
2191 return bitmap;
2192 }
2193
2194 wxImage::wxImage( const wxBitmap &bitmap )
2195 {
2196 // check the bitmap
2197 if( !bitmap.Ok() )
2198 {
2199 wxFAIL_MSG( wxT("invalid bitmap") );
2200 return;
2201 }
2202
2203 // create an wxImage object
2204 int width = bitmap.GetWidth();
2205 int height = bitmap.GetHeight();
2206 Create( width, height );
2207 unsigned char *data = GetData();
2208 if( !data )
2209 {
2210 wxFAIL_MSG( wxT("could not allocate data for image") );
2211 return;
2212 }
2213
2214 // calc the number of bytes per scanline and padding in the DIB
2215 int bytePerLine = width*3;
2216 int sizeDWORD = sizeof( DWORD );
2217 int lineBoundary = bytePerLine % sizeDWORD;
2218 int padding = 0;
2219 if( lineBoundary > 0 )
2220 {
2221 padding = sizeDWORD - lineBoundary;
2222 bytePerLine += padding;
2223 }
2224 // TODO:
2225 /*
2226 // create a DIB header
2227 int headersize = sizeof(BITMAPINFOHEADER);
2228 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
2229 if( !lpDIBh )
2230 {
2231 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
2232 free( data );
2233 return;
2234 }
2235 // Fill in the DIB header
2236 lpDIBh->bmiHeader.biSize = headersize;
2237 lpDIBh->bmiHeader.biWidth = width;
2238 lpDIBh->bmiHeader.biHeight = -height;
2239 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
2240 lpDIBh->bmiHeader.biPlanes = 1;
2241 lpDIBh->bmiHeader.biBitCount = 24;
2242 lpDIBh->bmiHeader.biCompression = BI_RGB;
2243 lpDIBh->bmiHeader.biClrUsed = 0;
2244 // These seem not really needed for our purpose here.
2245 lpDIBh->bmiHeader.biClrImportant = 0;
2246 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2247 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2248 // memory for DIB data
2249 unsigned char *lpBits;
2250 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
2251 if( !lpBits )
2252 {
2253 wxFAIL_MSG( wxT("could not allocate data for DIB") );
2254 free( data );
2255 free( lpDIBh );
2256 return;
2257 }
2258
2259 // copy data from the device-dependent bitmap to the DIB
2260 HDC hdc = ::GetDC(NULL);
2261 HBITMAP hbitmap;
2262 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
2263 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2264
2265 // copy DIB data into the wxImage object
2266 int i, j;
2267 unsigned char *ptdata = data;
2268 unsigned char *ptbits = lpBits;
2269 for( i=0; i<height; i++ )
2270 {
2271 for( j=0; j<width; j++ )
2272 {
2273 *(ptdata++) = *(ptbits+2);
2274 *(ptdata++) = *(ptbits+1);
2275 *(ptdata++) = *(ptbits );
2276 ptbits += 3;
2277 }
2278 ptbits += padding;
2279 }
2280
2281 // similarly, set data according to the possible mask bitmap
2282 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
2283 {
2284 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
2285 // memory DC created, color set, data copied, and memory DC deleted
2286 HDC memdc = ::CreateCompatibleDC( hdc );
2287 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
2288 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
2289 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2290 ::DeleteDC( memdc );
2291 // background color set to RGB(16,16,16) in consistent with wxGTK
2292 unsigned char r=16, g=16, b=16;
2293 ptdata = data;
2294 ptbits = lpBits;
2295 for( i=0; i<height; i++ )
2296 {
2297 for( j=0; j<width; j++ )
2298 {
2299 if( *ptbits != 0 )
2300 ptdata += 3;
2301 else
2302 {
2303 *(ptdata++) = r;
2304 *(ptdata++) = g;
2305 *(ptdata++) = b;
2306 }
2307 ptbits += 3;
2308 }
2309 ptbits += padding;
2310 }
2311 SetMaskColour( r, g, b );
2312 SetMask( TRUE );
2313 }
2314 else
2315 {
2316 SetMask( FALSE );
2317 }
2318 // free allocated resources
2319 ::ReleaseDC(NULL, hdc);
2320 free(lpDIBh);
2321 free(lpBits);
2322 */
2323 }
2324
2325 #endif
2326
2327 // A module to allow wxImage initialization/cleanup
2328 // without calling these functions from app.cpp or from
2329 // the user's application.
2330
2331 class wxImageModule: public wxModule
2332 {
2333 DECLARE_DYNAMIC_CLASS(wxImageModule)
2334 public:
2335 wxImageModule() {}
2336 bool OnInit() { wxImage::InitStandardHandlers(); return TRUE; };
2337 void OnExit() { wxImage::CleanUpHandlers(); };
2338 };
2339
2340 IMPLEMENT_DYNAMIC_CLASS(wxImageModule, wxModule)
2341
2342
2343 //-----------------------------------------------------------------------------
2344
2345 // GRG, Dic/99
2346 // Counts and returns the number of different colours. Optionally stops
2347 // when it exceeds 'stopafter' different colours. This is useful, for
2348 // example, to see if the image can be saved as 8-bit (256 colour or
2349 // less, in this case it would be invoked as CountColours(256)). Default
2350 // value for stopafter is -1 (don't care).
2351 //
2352 unsigned long wxImage::CountColours( unsigned long stopafter )
2353 {
2354 wxHashTable h;
2355 wxNode *node;
2356 wxHNode *hnode;
2357 unsigned char r, g, b, *p;
2358 unsigned long size, nentries, key;
2359
2360 p = GetData();
2361 size = GetWidth() * GetHeight();
2362 nentries = 0;
2363
2364 for (unsigned long j = 0; (j < size) && (nentries <= stopafter) ; j++)
2365 {
2366 r = *(p++);
2367 g = *(p++);
2368 b = *(p++);
2369 key = (r << 16) | (g << 8) | b;
2370
2371 hnode = (wxHNode *) h.Get(key);
2372
2373 if (!hnode)
2374 {
2375 h.Put(key, (wxObject *)(new wxHNode));
2376 nentries++;
2377 }
2378 }
2379
2380 // delete all HNodes
2381 h.BeginFind();
2382 while ((node = h.Next()) != NULL)
2383 delete (wxHNode *)node->GetData();
2384
2385 return nentries;
2386 }
2387
2388
2389 // GRG, Dic/99
2390 // Computes the histogram of the image and fills a hash table, indexed
2391 // with integer keys built as 0xRRGGBB, containing wxHNode objects. Each
2392 // wxHNode contains an 'index' (useful to build a palette with the image
2393 // colours) and a 'value', which is the number of pixels in the image with
2394 // that colour.
2395 //
2396 unsigned long wxImage::ComputeHistogram( wxHashTable &h )
2397 {
2398 unsigned char r, g, b, *p;
2399 unsigned long size, nentries, key;
2400 wxHNode *hnode;
2401
2402 p = GetData();
2403 size = GetWidth() * GetHeight();
2404 nentries = 0;
2405
2406 for (unsigned long j = 0; j < size; j++)
2407 {
2408 r = *(p++);
2409 g = *(p++);
2410 b = *(p++);
2411 key = (r << 16) | (g << 8) | b;
2412
2413 hnode = (wxHNode *) h.Get(key);
2414
2415 if (hnode)
2416 hnode->value++;
2417 else
2418 {
2419 hnode = new wxHNode();
2420 hnode->index = nentries++;
2421 hnode->value = 1;
2422
2423 h.Put(key, (wxObject *)hnode);
2424 }
2425 }
2426
2427 return nentries;
2428 }
2429
2430