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