]> git.saurik.com Git - wxWidgets.git/blob - src/common/image.cpp
wxSetlocale() doesn't always return NULL
[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 #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 else
387 {
388 wxLogError( _("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 else
406 {
407 wxLogError( _("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( _("No handler found for image type.") );
487 return FALSE;
488 }
489
490 handler = FindHandler(type);
491
492 if (handler == NULL)
493 {
494 wxLogWarning( _("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( _("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( _("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( _("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), int WXUNUSED(index) )
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 int wxImageHandler::GetImageCount( wxInputStream& WXUNUSED(stream) )
670 {
671 return 1;
672 }
673
674 bool wxImageHandler::CanRead( const wxString& name )
675 {
676 if (wxFileExists(name))
677 {
678 wxFileInputStream stream(name);
679 return CanRead(stream);
680 }
681
682 else {
683 wxLogError( _("Can't check image format of file '%s': file does not exist."), name.c_str() );
684
685 return FALSE;
686 }
687 return FALSE;
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 if (bpp <= 8)
1559 {
1560 data[pos] = cmap->colors[pixel].red >> 8;
1561 data[pos+1] = cmap->colors[pixel].green >> 8;
1562 data[pos+2] = cmap->colors[pixel].blue >> 8;
1563 } else if (bpp == 15)
1564 {
1565 #if (wxBYTE_ORDER == wxBIG_ENDIAN)
1566 // ?
1567 #endif
1568 data[pos] = (pixel >> 7) & 0xf8;
1569 data[pos+1] = (pixel >> 2) & 0xf8;
1570 data[pos+2] = (pixel << 3) & 0xf8;
1571 } else if (bpp == 16)
1572 {
1573 #if (wxBYTE_ORDER == wxBIG_ENDIAN)
1574 // ?
1575 #endif
1576 data[pos] = (pixel >> 8) & 0xf8;
1577 data[pos+1] = (pixel >> 3) & 0xfc;
1578 data[pos+2] = (pixel << 3) & 0xf8;
1579 } else
1580 {
1581 #if (wxBYTE_ORDER == wxBIG_ENDIAN)
1582 data[pos] = (pixel) & 0xff; // Red
1583 data[pos+1] = (pixel >> 8) & 0xff; // Green
1584 data[pos+2] = (pixel >> 16) & 0xff; // Blue
1585 #else
1586 data[pos] = (pixel >> 16) & 0xff;
1587 data[pos+1] = (pixel >> 8) & 0xff;
1588 data[pos+2] = pixel & 0xff;
1589 #endif
1590 }
1591
1592 if (gdk_image_mask)
1593 {
1594 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1595 if (mask_pixel == 0)
1596 {
1597 data[pos] = 16;
1598 data[pos+1] = 16;
1599 data[pos+2] = 16;
1600 }
1601 }
1602
1603 pos += 3;
1604 }
1605 }
1606
1607 gdk_image_destroy( gdk_image );
1608 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1609 }
1610
1611 #endif
1612
1613 //-----------------------------------------------------------------------------
1614 // Motif conversion routines
1615 //-----------------------------------------------------------------------------
1616
1617 #ifdef __WXMOTIF__
1618 #ifdef __VMS__
1619 #pragma message disable nosimpint
1620 #endif
1621 #include <Xm/Xm.h>
1622 #ifdef __VMS__
1623 #pragma message enable nosimpint
1624 #endif
1625 #include "wx/utils.h"
1626 #include <math.h>
1627
1628 wxBitmap wxImage::ConvertToBitmap() const
1629 {
1630 wxBitmap bitmap;
1631
1632 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
1633
1634 int width = GetWidth();
1635 int height = GetHeight();
1636
1637 bitmap.SetHeight( height );
1638 bitmap.SetWidth( width );
1639
1640 Display *dpy = (Display*) wxGetDisplay();
1641 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1642 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1643
1644 // Create image
1645
1646 XImage *data_image = XCreateImage( dpy, vis, bpp, ZPixmap, 0, 0, width, height, 32, 0 );
1647 data_image->data = (char*) malloc( data_image->bytes_per_line * data_image->height );
1648
1649 bitmap.Create( width, height, bpp );
1650
1651 /*
1652 // Create mask
1653
1654 GdkImage *mask_image = (GdkImage*) NULL;
1655
1656 if (HasMask())
1657 {
1658 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1659
1660 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1661
1662 wxMask *mask = new wxMask();
1663 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1664
1665 bitmap.SetMask( mask );
1666 }
1667 */
1668
1669 // Retrieve depth info
1670
1671 XVisualInfo vinfo_template;
1672 XVisualInfo *vi;
1673
1674 vinfo_template.visual = vis;
1675 vinfo_template.visualid = XVisualIDFromVisual( vis );
1676 vinfo_template.depth = bpp;
1677 int nitem = 0;
1678
1679 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1680
1681 wxCHECK_MSG( vi, wxNullBitmap, wxT("no visual") );
1682
1683 XFree( vi );
1684
1685 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1686 if (bpp < 8) bpp = 8;
1687
1688 // Render
1689
1690 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1691 byte_order b_o = RGB;
1692
1693 if (bpp >= 24)
1694 {
1695 if ((vi->red_mask > vi->green_mask) && (vi->green_mask > vi->blue_mask)) b_o = RGB;
1696 else if ((vi->red_mask > vi->blue_mask) && (vi->blue_mask > vi->green_mask)) b_o = RGB;
1697 else if ((vi->blue_mask > vi->red_mask) && (vi->red_mask > vi->green_mask)) b_o = BRG;
1698 else if ((vi->blue_mask > vi->green_mask) && (vi->green_mask > vi->red_mask)) b_o = BGR;
1699 else if ((vi->green_mask > vi->red_mask) && (vi->red_mask > vi->blue_mask)) b_o = GRB;
1700 else if ((vi->green_mask > vi->blue_mask) && (vi->blue_mask > vi->red_mask)) b_o = GBR;
1701 }
1702
1703 /*
1704 int r_mask = GetMaskRed();
1705 int g_mask = GetMaskGreen();
1706 int b_mask = GetMaskBlue();
1707 */
1708
1709 XColor colors[256];
1710 if (bpp == 8)
1711 {
1712 Colormap cmap = (Colormap) wxTheApp->GetMainColormap( dpy );
1713
1714 for (int i = 0; i < 256; i++) colors[i].pixel = i;
1715 XQueryColors( dpy, cmap, colors, 256 );
1716 }
1717
1718 unsigned char* data = GetData();
1719
1720 int index = 0;
1721 for (int y = 0; y < height; y++)
1722 {
1723 for (int x = 0; x < width; x++)
1724 {
1725 int r = data[index];
1726 index++;
1727 int g = data[index];
1728 index++;
1729 int b = data[index];
1730 index++;
1731
1732 /*
1733 if (HasMask())
1734 {
1735 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1736 gdk_image_put_pixel( mask_image, x, y, 1 );
1737 else
1738 gdk_image_put_pixel( mask_image, x, y, 0 );
1739 }
1740 */
1741
1742 switch (bpp)
1743 {
1744 case 8:
1745 {
1746 int pixel = -1;
1747 /*
1748 if (wxTheApp->m_colorCube)
1749 {
1750 pixel = wxTheApp->m_colorCube
1751 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1752 }
1753 else
1754 {
1755 */
1756 int max = 3 * (65536);
1757 for (int i = 0; i < 256; i++)
1758 {
1759 int rdiff = (r << 8) - colors[i].red;
1760 int gdiff = (g << 8) - colors[i].green;
1761 int bdiff = (b << 8) - colors[i].blue;
1762 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1763 if (sum < max) { pixel = i; max = sum; }
1764 }
1765 /*
1766 }
1767 */
1768 XPutPixel( data_image, x, y, pixel );
1769 break;
1770 }
1771 case 15:
1772 {
1773 int pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1774 XPutPixel( data_image, x, y, pixel );
1775 break;
1776 }
1777 case 16:
1778 {
1779 int pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1780 XPutPixel( data_image, x, y, pixel );
1781 break;
1782 }
1783 case 32:
1784 case 24:
1785 {
1786 int pixel = 0;
1787 switch (b_o)
1788 {
1789 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1790 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1791 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1792 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1793 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1794 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1795 }
1796 XPutPixel( data_image, x, y, pixel );
1797 }
1798 default: break;
1799 }
1800 } // for
1801 } // for
1802
1803 // Blit picture
1804
1805 XGCValues gcvalues;
1806 gcvalues.foreground = BlackPixel( dpy, DefaultScreen( dpy ) );
1807 GC gc = XCreateGC( dpy, RootWindow ( dpy, DefaultScreen(dpy) ), GCForeground, &gcvalues );
1808 XPutImage( dpy, (Drawable)bitmap.GetPixmap(), gc, data_image, 0, 0, 0, 0, width, height );
1809
1810 XDestroyImage( data_image );
1811 XFreeGC( dpy, gc );
1812
1813 /*
1814 // Blit mask
1815
1816 if (HasMask())
1817 {
1818 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
1819
1820 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
1821
1822 gdk_image_destroy( mask_image );
1823 gdk_gc_unref( mask_gc );
1824 }
1825 */
1826
1827 return bitmap;
1828 }
1829
1830 wxImage::wxImage( const wxBitmap &bitmap )
1831 {
1832 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
1833
1834 Display *dpy = (Display*) wxGetDisplay();
1835 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1836 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1837
1838 XImage *ximage = XGetImage( dpy,
1839 (Drawable)bitmap.GetPixmap(),
1840 0, 0,
1841 bitmap.GetWidth(), bitmap.GetHeight(),
1842 AllPlanes, ZPixmap );
1843
1844 wxCHECK_RET( ximage, wxT("couldn't create image") );
1845
1846 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1847 char unsigned *data = GetData();
1848
1849 if (!data)
1850 {
1851 XDestroyImage( ximage );
1852 wxFAIL_MSG( wxT("couldn't create image") );
1853 return;
1854 }
1855
1856 /*
1857 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1858 if (bitmap.GetMask())
1859 {
1860 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1861 0, 0,
1862 bitmap.GetWidth(), bitmap.GetHeight() );
1863
1864 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1865 }
1866 */
1867
1868 // Retrieve depth info
1869
1870 XVisualInfo vinfo_template;
1871 XVisualInfo *vi;
1872
1873 vinfo_template.visual = vis;
1874 vinfo_template.visualid = XVisualIDFromVisual( vis );
1875 vinfo_template.depth = bpp;
1876 int nitem = 0;
1877
1878 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1879
1880 wxCHECK_RET( vi, wxT("no visual") );
1881
1882 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1883
1884 XFree( vi );
1885
1886 XColor colors[256];
1887 if (bpp == 8)
1888 {
1889 Colormap cmap = (Colormap)wxTheApp->GetMainColormap( dpy );
1890
1891 for (int i = 0; i < 256; i++) colors[i].pixel = i;
1892 XQueryColors( dpy, cmap, colors, 256 );
1893 }
1894
1895 long pos = 0;
1896 for (int j = 0; j < bitmap.GetHeight(); j++)
1897 {
1898 for (int i = 0; i < bitmap.GetWidth(); i++)
1899 {
1900 int pixel = XGetPixel( ximage, i, j );
1901 if (bpp <= 8)
1902 {
1903 data[pos] = colors[pixel].red >> 8;
1904 data[pos+1] = colors[pixel].green >> 8;
1905 data[pos+2] = colors[pixel].blue >> 8;
1906 } else if (bpp == 15)
1907 {
1908 data[pos] = (pixel >> 7) & 0xf8;
1909 data[pos+1] = (pixel >> 2) & 0xf8;
1910 data[pos+2] = (pixel << 3) & 0xf8;
1911 } else if (bpp == 16)
1912 {
1913 data[pos] = (pixel >> 8) & 0xf8;
1914 data[pos+1] = (pixel >> 3) & 0xfc;
1915 data[pos+2] = (pixel << 3) & 0xf8;
1916 } else
1917 {
1918 data[pos] = (pixel >> 16) & 0xff;
1919 data[pos+1] = (pixel >> 8) & 0xff;
1920 data[pos+2] = pixel & 0xff;
1921 }
1922
1923 /*
1924 if (gdk_image_mask)
1925 {
1926 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1927 if (mask_pixel == 0)
1928 {
1929 data[pos] = 16;
1930 data[pos+1] = 16;
1931 data[pos+2] = 16;
1932 }
1933 }
1934 */
1935
1936 pos += 3;
1937 }
1938 }
1939
1940 XDestroyImage( ximage );
1941 /*
1942 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1943 */
1944 }
1945 #endif
1946
1947 #ifdef __WXPM__
1948 // OS/2 Presentation manager conversion routings
1949
1950 wxBitmap wxImage::ConvertToBitmap() const
1951 {
1952 if ( !Ok() )
1953 return wxNullBitmap;
1954 wxBitmap bitmap; // remove
1955 // TODO:
1956 /*
1957 int sizeLimit = 1024*768*3;
1958
1959 // width and height of the device-dependent bitmap
1960 int width = GetWidth();
1961 int bmpHeight = GetHeight();
1962
1963 // calc the number of bytes per scanline and padding
1964 int bytePerLine = width*3;
1965 int sizeDWORD = sizeof( DWORD );
1966 int lineBoundary = bytePerLine % sizeDWORD;
1967 int padding = 0;
1968 if( lineBoundary > 0 )
1969 {
1970 padding = sizeDWORD - lineBoundary;
1971 bytePerLine += padding;
1972 }
1973 // calc the number of DIBs and heights of DIBs
1974 int numDIB = 1;
1975 int hRemain = 0;
1976 int height = sizeLimit/bytePerLine;
1977 if( height >= bmpHeight )
1978 height = bmpHeight;
1979 else
1980 {
1981 numDIB = bmpHeight / height;
1982 hRemain = bmpHeight % height;
1983 if( hRemain >0 ) numDIB++;
1984 }
1985
1986 // set bitmap parameters
1987 wxBitmap bitmap;
1988 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
1989 bitmap.SetWidth( width );
1990 bitmap.SetHeight( bmpHeight );
1991 bitmap.SetDepth( wxDisplayDepth() );
1992
1993 // create a DIB header
1994 int headersize = sizeof(BITMAPINFOHEADER);
1995 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
1996 wxCHECK_MSG( lpDIBh, bitmap, wxT("could not allocate memory for DIB header") );
1997 // Fill in the DIB header
1998 lpDIBh->bmiHeader.biSize = headersize;
1999 lpDIBh->bmiHeader.biWidth = (DWORD)width;
2000 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2001 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2002 // the general formula for biSizeImage:
2003 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
2004 lpDIBh->bmiHeader.biPlanes = 1;
2005 lpDIBh->bmiHeader.biBitCount = 24;
2006 lpDIBh->bmiHeader.biCompression = BI_RGB;
2007 lpDIBh->bmiHeader.biClrUsed = 0;
2008 // These seem not really needed for our purpose here.
2009 lpDIBh->bmiHeader.biClrImportant = 0;
2010 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2011 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2012 // memory for DIB data
2013 unsigned char *lpBits;
2014 lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
2015 if( !lpBits )
2016 {
2017 wxFAIL_MSG( wxT("could not allocate memory for DIB") );
2018 free( lpDIBh );
2019 return bitmap;
2020 }
2021
2022 // create and set the device-dependent bitmap
2023 HDC hdc = ::GetDC(NULL);
2024 HDC memdc = ::CreateCompatibleDC( hdc );
2025 HBITMAP hbitmap;
2026 hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
2027 ::SelectObject( memdc, hbitmap);
2028
2029 // copy image data into DIB data and then into DDB (in a loop)
2030 unsigned char *data = GetData();
2031 int i, j, n;
2032 int origin = 0;
2033 unsigned char *ptdata = data;
2034 unsigned char *ptbits;
2035
2036 for( n=0; n<numDIB; n++ )
2037 {
2038 if( numDIB > 1 && n == numDIB-1 && hRemain > 0 )
2039 {
2040 // redefine height and size of the (possibly) last smaller DIB
2041 // memory is not reallocated
2042 height = hRemain;
2043 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2044 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2045 }
2046 ptbits = lpBits;
2047
2048 for( j=0; j<height; j++ )
2049 {
2050 for( i=0; i<width; i++ )
2051 {
2052 *(ptbits++) = *(ptdata+2);
2053 *(ptbits++) = *(ptdata+1);
2054 *(ptbits++) = *(ptdata );
2055 ptdata += 3;
2056 }
2057 for( i=0; i< padding; i++ ) *(ptbits++) = 0;
2058 }
2059 ::StretchDIBits( memdc, 0, origin, width, height,\
2060 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2061 origin += height;
2062 // if numDIB = 1, lines below can also be used
2063 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
2064 // The above line is equivalent to the following two lines.
2065 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2066 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
2067 // or the following lines
2068 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2069 // HDC memdc = ::CreateCompatibleDC( hdc );
2070 // ::SelectObject( memdc, hbitmap);
2071 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
2072 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
2073 // ::SelectObject( memdc, 0 );
2074 // ::DeleteDC( memdc );
2075 }
2076 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
2077
2078 // similarly, created an mono-bitmap for the possible mask
2079 if( HasMask() )
2080 {
2081 hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL );
2082 ::SelectObject( memdc, hbitmap);
2083 if( numDIB == 1 ) height = bmpHeight;
2084 else height = sizeLimit/bytePerLine;
2085 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2086 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2087 origin = 0;
2088 unsigned char r = GetMaskRed();
2089 unsigned char g = GetMaskGreen();
2090 unsigned char b = GetMaskBlue();
2091 unsigned char zero = 0, one = 255;
2092 ptdata = data;
2093 for( n=0; n<numDIB; n++ )
2094 {
2095 if( numDIB > 1 && n == numDIB - 1 && hRemain > 0 )
2096 {
2097 // redefine height and size of the (possibly) last smaller DIB
2098 // memory is not reallocated
2099 height = hRemain;
2100 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2101 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2102 }
2103 ptbits = lpBits;
2104 for( int j=0; j<height; j++ )
2105 {
2106 for(i=0; i<width; i++ )
2107 {
2108 if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
2109 {
2110 *(ptbits++) = one;
2111 *(ptbits++) = one;
2112 *(ptbits++) = one;
2113 }
2114 else
2115 {
2116 *(ptbits++) = zero;
2117 *(ptbits++) = zero;
2118 *(ptbits++) = zero;
2119 }
2120 }
2121 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
2122 }
2123 ::StretchDIBits( memdc, 0, origin, width, height,\
2124 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2125 origin += height;
2126 }
2127 // create a wxMask object
2128 wxMask *mask = new wxMask();
2129 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
2130 bitmap.SetMask( mask );
2131 }
2132
2133 // free allocated resources
2134 ::SelectObject( memdc, 0 );
2135 ::DeleteDC( memdc );
2136 ::ReleaseDC(NULL, hdc);
2137 free(lpDIBh);
2138 free(lpBits);
2139
2140 // check the wxBitmap object
2141 if( bitmap.GetHBITMAP() )
2142 bitmap.SetOk( TRUE );
2143 else
2144 bitmap.SetOk( FALSE );
2145 */
2146 return bitmap;
2147 }
2148
2149 wxImage::wxImage( const wxBitmap &bitmap )
2150 {
2151 // check the bitmap
2152 if( !bitmap.Ok() )
2153 {
2154 wxFAIL_MSG( wxT("invalid bitmap") );
2155 return;
2156 }
2157
2158 // create an wxImage object
2159 int width = bitmap.GetWidth();
2160 int height = bitmap.GetHeight();
2161 Create( width, height );
2162 unsigned char *data = GetData();
2163 if( !data )
2164 {
2165 wxFAIL_MSG( wxT("could not allocate data for image") );
2166 return;
2167 }
2168
2169 // calc the number of bytes per scanline and padding in the DIB
2170 int bytePerLine = width*3;
2171 int sizeDWORD = sizeof( DWORD );
2172 int lineBoundary = bytePerLine % sizeDWORD;
2173 int padding = 0;
2174 if( lineBoundary > 0 )
2175 {
2176 padding = sizeDWORD - lineBoundary;
2177 bytePerLine += padding;
2178 }
2179 // TODO:
2180 /*
2181 // create a DIB header
2182 int headersize = sizeof(BITMAPINFOHEADER);
2183 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
2184 if( !lpDIBh )
2185 {
2186 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
2187 free( data );
2188 return;
2189 }
2190 // Fill in the DIB header
2191 lpDIBh->bmiHeader.biSize = headersize;
2192 lpDIBh->bmiHeader.biWidth = width;
2193 lpDIBh->bmiHeader.biHeight = -height;
2194 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
2195 lpDIBh->bmiHeader.biPlanes = 1;
2196 lpDIBh->bmiHeader.biBitCount = 24;
2197 lpDIBh->bmiHeader.biCompression = BI_RGB;
2198 lpDIBh->bmiHeader.biClrUsed = 0;
2199 // These seem not really needed for our purpose here.
2200 lpDIBh->bmiHeader.biClrImportant = 0;
2201 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2202 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2203 // memory for DIB data
2204 unsigned char *lpBits;
2205 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
2206 if( !lpBits )
2207 {
2208 wxFAIL_MSG( wxT("could not allocate data for DIB") );
2209 free( data );
2210 free( lpDIBh );
2211 return;
2212 }
2213
2214 // copy data from the device-dependent bitmap to the DIB
2215 HDC hdc = ::GetDC(NULL);
2216 HBITMAP hbitmap;
2217 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
2218 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2219
2220 // copy DIB data into the wxImage object
2221 int i, j;
2222 unsigned char *ptdata = data;
2223 unsigned char *ptbits = lpBits;
2224 for( i=0; i<height; i++ )
2225 {
2226 for( j=0; j<width; j++ )
2227 {
2228 *(ptdata++) = *(ptbits+2);
2229 *(ptdata++) = *(ptbits+1);
2230 *(ptdata++) = *(ptbits );
2231 ptbits += 3;
2232 }
2233 ptbits += padding;
2234 }
2235
2236 // similarly, set data according to the possible mask bitmap
2237 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
2238 {
2239 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
2240 // memory DC created, color set, data copied, and memory DC deleted
2241 HDC memdc = ::CreateCompatibleDC( hdc );
2242 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
2243 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
2244 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2245 ::DeleteDC( memdc );
2246 // background color set to RGB(16,16,16) in consistent with wxGTK
2247 unsigned char r=16, g=16, b=16;
2248 ptdata = data;
2249 ptbits = lpBits;
2250 for( i=0; i<height; i++ )
2251 {
2252 for( j=0; j<width; j++ )
2253 {
2254 if( *ptbits != 0 )
2255 ptdata += 3;
2256 else
2257 {
2258 *(ptdata++) = r;
2259 *(ptdata++) = g;
2260 *(ptdata++) = b;
2261 }
2262 ptbits += 3;
2263 }
2264 ptbits += padding;
2265 }
2266 SetMaskColour( r, g, b );
2267 SetMask( TRUE );
2268 }
2269 else
2270 {
2271 SetMask( FALSE );
2272 }
2273 // free allocated resources
2274 ::ReleaseDC(NULL, hdc);
2275 free(lpDIBh);
2276 free(lpBits);
2277 */
2278 }
2279
2280 #endif
2281
2282 // A module to allow wxImage initialization/cleanup
2283 // without calling these functions from app.cpp or from
2284 // the user's application.
2285
2286 class wxImageModule: public wxModule
2287 {
2288 DECLARE_DYNAMIC_CLASS(wxImageModule)
2289 public:
2290 wxImageModule() {}
2291 bool OnInit() { wxImage::InitStandardHandlers(); return TRUE; };
2292 void OnExit() { wxImage::CleanUpHandlers(); };
2293 };
2294
2295 IMPLEMENT_DYNAMIC_CLASS(wxImageModule, wxModule)