]> git.saurik.com Git - wxWidgets.git/blob - src/common/image.cpp
Committing in .
[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 // check the wxBitmap object
898 if( bitmap.GetHBITMAP() )
899 bitmap.SetOk( TRUE );
900 else
901 bitmap.SetOk( FALSE );
902
903 return bitmap;
904 }
905
906 wxImage::wxImage( const wxBitmap &bitmap )
907 {
908 // check the bitmap
909 if( !bitmap.Ok() )
910 {
911 wxFAIL_MSG( wxT("invalid bitmap") );
912 return;
913 }
914
915 // create an wxImage object
916 int width = bitmap.GetWidth();
917 int height = bitmap.GetHeight();
918 Create( width, height );
919 unsigned char *data = GetData();
920 if( !data )
921 {
922 wxFAIL_MSG( wxT("could not allocate data for image") );
923 return;
924 }
925
926 // calc the number of bytes per scanline and padding in the DIB
927 int bytePerLine = width*3;
928 int sizeDWORD = sizeof( DWORD );
929 int lineBoundary = bytePerLine % sizeDWORD;
930 int padding = 0;
931 if( lineBoundary > 0 )
932 {
933 padding = sizeDWORD - lineBoundary;
934 bytePerLine += padding;
935 }
936
937 // create a DIB header
938 int headersize = sizeof(BITMAPINFOHEADER);
939 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
940 if( !lpDIBh )
941 {
942 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
943 free( data );
944 return;
945 }
946 // Fill in the DIB header
947 lpDIBh->bmiHeader.biSize = headersize;
948 lpDIBh->bmiHeader.biWidth = width;
949 lpDIBh->bmiHeader.biHeight = -height;
950 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
951 lpDIBh->bmiHeader.biPlanes = 1;
952 lpDIBh->bmiHeader.biBitCount = 24;
953 lpDIBh->bmiHeader.biCompression = BI_RGB;
954 lpDIBh->bmiHeader.biClrUsed = 0;
955 // These seem not really needed for our purpose here.
956 lpDIBh->bmiHeader.biClrImportant = 0;
957 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
958 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
959 // memory for DIB data
960 unsigned char *lpBits;
961 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
962 if( !lpBits )
963 {
964 wxFAIL_MSG( wxT("could not allocate data for DIB") );
965 free( data );
966 free( lpDIBh );
967 return;
968 }
969
970 // copy data from the device-dependent bitmap to the DIB
971 HDC hdc = ::GetDC(NULL);
972 HBITMAP hbitmap;
973 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
974 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
975
976 // copy DIB data into the wxImage object
977 int i, j;
978 unsigned char *ptdata = data;
979 unsigned char *ptbits = lpBits;
980 for( i=0; i<height; i++ )
981 {
982 for( j=0; j<width; j++ )
983 {
984 *(ptdata++) = *(ptbits+2);
985 *(ptdata++) = *(ptbits+1);
986 *(ptdata++) = *(ptbits );
987 ptbits += 3;
988 }
989 ptbits += padding;
990 }
991
992 // similarly, set data according to the possible mask bitmap
993 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
994 {
995 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
996 // memory DC created, color set, data copied, and memory DC deleted
997 HDC memdc = ::CreateCompatibleDC( hdc );
998 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
999 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
1000 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1001 ::DeleteDC( memdc );
1002 // background color set to RGB(16,16,16) in consistent with wxGTK
1003 unsigned char r=16, g=16, b=16;
1004 ptdata = data;
1005 ptbits = lpBits;
1006 for( i=0; i<height; i++ )
1007 {
1008 for( j=0; j<width; j++ )
1009 {
1010 if( *ptbits != 0 )
1011 ptdata += 3;
1012 else
1013 {
1014 *(ptdata++) = r;
1015 *(ptdata++) = g;
1016 *(ptdata++) = b;
1017 }
1018 ptbits += 3;
1019 }
1020 ptbits += padding;
1021 }
1022 SetMaskColour( r, g, b );
1023 SetMask( TRUE );
1024 }
1025 else
1026 {
1027 SetMask( FALSE );
1028 }
1029 // free allocated resources
1030 ::ReleaseDC(NULL, hdc);
1031 free(lpDIBh);
1032 free(lpBits);
1033 }
1034
1035 #endif
1036
1037 #ifdef __WXMAC__
1038
1039 #include <PictUtils.h>
1040
1041 extern CTabHandle wxMacCreateColorTable( int numColors ) ;
1042 extern void wxMacDestroyColorTable( CTabHandle colors ) ;
1043 extern void wxMacSetColorTableEntry( CTabHandle newColors , int index , int red , int green , int blue ) ;
1044 extern GWorldPtr wxMacCreateGWorld( int height , int width , int depth ) ;
1045 extern void wxMacDestroyGWorld( GWorldPtr gw ) ;
1046
1047 wxBitmap wxImage::ConvertToBitmap() const
1048 {
1049 // width and height of the device-dependent bitmap
1050 int width = GetWidth();
1051 int height = GetHeight();
1052
1053 // Create picture
1054
1055 wxBitmap bitmap( width , height , wxDisplayDepth() ) ;
1056
1057 // Create mask
1058
1059 if (HasMask())
1060 {
1061 /*
1062 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1063
1064 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1065
1066 wxMask *mask = new wxMask();
1067 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1068
1069 bitmap.SetMask( mask );
1070 */
1071 }
1072
1073 // Render
1074
1075 int r_mask = GetMaskRed();
1076 int g_mask = GetMaskGreen();
1077 int b_mask = GetMaskBlue();
1078
1079 CGrafPtr origPort ;
1080 GDHandle origDevice ;
1081
1082 GetGWorld( &origPort , &origDevice ) ;
1083 SetGWorld( bitmap.GetHBITMAP() , NULL ) ;
1084
1085 register unsigned char* data = GetData();
1086
1087 int index = 0;
1088 for (int y = 0; y < height; y++)
1089 {
1090 #if 0
1091 unsigned char lastr = 0 ;
1092 unsigned char lastg = 0 ;
1093 unsigned char lastb = 0 ;
1094 RGBColor lastcolor ;
1095
1096 MoveTo( 0 , y ) ;
1097 for (int x = 0; x < width; x++)
1098 {
1099 unsigned char r = data[index++];
1100 unsigned char g = data[index++];
1101 unsigned char b = data[index++];
1102
1103 if ( r != lastr || g != lastg || b != lastb )
1104 {
1105 lastcolor.red = ( lastr << 8 ) + lastr ;
1106 lastcolor.green = ( lastg << 8 ) + lastg ;
1107 lastcolor.blue = ( lastb << 8 ) + lastb ;
1108 RGBForeColor( &lastcolor ) ;
1109 LineTo( x , y ) ;
1110 lastr = r ;
1111 lastg = g ;
1112 lastb = b ;
1113 }
1114 } // for width
1115 lastcolor.red = ( lastr << 8 ) + lastr ;
1116 lastcolor.green = ( lastg << 8 ) + lastg ;
1117 lastcolor.blue = ( lastb << 8 ) + lastb ;
1118 RGBForeColor( &lastcolor ) ;
1119 LineTo( width - 1 , y ) ;
1120 #else
1121 for (int x = 0; x < width; x++)
1122 {
1123 unsigned char r = data[index++];
1124 unsigned char g = data[index++];
1125 unsigned char b = data[index++];
1126 RGBColor color ;
1127 color.red = ( r << 8 ) + r ;
1128 color.green = ( g << 8 ) + g ;
1129 color.blue = ( b << 8 ) + b ;
1130 SetCPixel( x , y , &color ) ;
1131 }
1132 #endif
1133 } // for height
1134
1135 SetGWorld( origPort , origDevice ) ;
1136
1137 return bitmap;
1138
1139 }
1140
1141 wxImage::wxImage( const wxBitmap &bitmap )
1142 {
1143 // check the bitmap
1144 if( !bitmap.Ok() )
1145 {
1146 wxFAIL_MSG( "invalid bitmap" );
1147 return;
1148 }
1149
1150 // create an wxImage object
1151 int width = bitmap.GetWidth();
1152 int height = bitmap.GetHeight();
1153 Create( width, height );
1154 /*
1155 unsigned char *data = GetData();
1156 if( !data )
1157 {
1158 wxFAIL_MSG( "could not allocate data for image" );
1159 return;
1160 }
1161
1162 // calc the number of bytes per scanline and padding in the DIB
1163 int bytePerLine = width*3;
1164 int sizeDWORD = sizeof( DWORD );
1165 div_t lineBoundary = div( bytePerLine, sizeDWORD );
1166 int padding = 0;
1167 if( lineBoundary.rem > 0 )
1168 {
1169 padding = sizeDWORD - lineBoundary.rem;
1170 bytePerLine += padding;
1171 }
1172
1173 // create a DIB header
1174 int headersize = sizeof(BITMAPINFOHEADER);
1175 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
1176 if( !lpDIBh )
1177 {
1178 wxFAIL_MSG( "could not allocate data for DIB header" );
1179 free( data );
1180 return;
1181 }
1182 // Fill in the DIB header
1183 lpDIBh->bmiHeader.biSize = headersize;
1184 lpDIBh->bmiHeader.biWidth = width;
1185 lpDIBh->bmiHeader.biHeight = -height;
1186 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
1187 lpDIBh->bmiHeader.biPlanes = 1;
1188 lpDIBh->bmiHeader.biBitCount = 24;
1189 lpDIBh->bmiHeader.biCompression = BI_RGB;
1190 lpDIBh->bmiHeader.biClrUsed = 0;
1191 // These seem not really needed for our purpose here.
1192 lpDIBh->bmiHeader.biClrImportant = 0;
1193 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
1194 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
1195 // memory for DIB data
1196 unsigned char *lpBits;
1197 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
1198 if( !lpBits )
1199 {
1200 wxFAIL_MSG( "could not allocate data for DIB" );
1201 free( data );
1202 free( lpDIBh );
1203 return;
1204 }
1205
1206 // copy data from the device-dependent bitmap to the DIB
1207 HDC hdc = ::GetDC(NULL);
1208 HBITMAP hbitmap;
1209 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
1210 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1211
1212 // copy DIB data into the wxImage object
1213 int i, j;
1214 unsigned char *ptdata = data;
1215 unsigned char *ptbits = lpBits;
1216 for( i=0; i<height; i++ )
1217 {
1218 for( j=0; j<width; j++ )
1219 {
1220 *(ptdata++) = *(ptbits+2);
1221 *(ptdata++) = *(ptbits+1);
1222 *(ptdata++) = *(ptbits );
1223 ptbits += 3;
1224 }
1225 ptbits += padding;
1226 }
1227
1228 // similarly, set data according to the possible mask bitmap
1229 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
1230 {
1231 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
1232 // memory DC created, color set, data copied, and memory DC deleted
1233 HDC memdc = ::CreateCompatibleDC( hdc );
1234 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
1235 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
1236 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1237 ::DeleteDC( memdc );
1238 // background color set to RGB(16,16,16) in consistent with wxGTK
1239 unsigned char r=16, g=16, b=16;
1240 ptdata = data;
1241 ptbits = lpBits;
1242 for( i=0; i<height; i++ )
1243 {
1244 for( j=0; j<width; j++ )
1245 {
1246 if( *ptbits != 0 )
1247 ptdata += 3;
1248 else
1249 {
1250 *(ptdata++) = r;
1251 *(ptdata++) = g;
1252 *(ptdata++) = b;
1253 }
1254 ptbits += 3;
1255 }
1256 ptbits += padding;
1257 }
1258 SetMaskColour( r, g, b );
1259 SetMask( TRUE );
1260 }
1261 else
1262 {
1263 SetMask( FALSE );
1264 }
1265 // free allocated resources
1266 ::ReleaseDC(NULL, hdc);
1267 free(lpDIBh);
1268 free(lpBits);
1269 */
1270 }
1271
1272 #endif
1273
1274 //-----------------------------------------------------------------------------
1275 // GTK conversion routines
1276 //-----------------------------------------------------------------------------
1277
1278 #ifdef __WXGTK__
1279
1280 #include "gtk/gtk.h"
1281 #include "gdk/gdk.h"
1282 #include "gdk/gdkx.h"
1283
1284 #if (GTK_MINOR_VERSION > 0)
1285 #include "gdk/gdkrgb.h"
1286 #endif
1287
1288 wxBitmap wxImage::ConvertToBitmap() const
1289 {
1290 wxBitmap bitmap;
1291
1292 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
1293
1294 int width = GetWidth();
1295 int height = GetHeight();
1296
1297 bitmap.SetHeight( height );
1298 bitmap.SetWidth( width );
1299
1300 bitmap.SetPixmap( gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, -1 ) );
1301
1302 // Retrieve depth
1303
1304 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
1305 if (visual == NULL) visual = gdk_visual_get_system();
1306 int bpp = visual->depth;
1307
1308 bitmap.SetDepth( bpp );
1309
1310 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
1311 if (bpp < 8) bpp = 8;
1312
1313 #if (GTK_MINOR_VERSION > 0)
1314
1315 if (!HasMask() && (bpp > 8))
1316 {
1317 static bool s_hasInitialized = FALSE;
1318
1319 if (!s_hasInitialized)
1320 {
1321 gdk_rgb_init();
1322 s_hasInitialized = TRUE;
1323 }
1324
1325 GdkGC *gc = gdk_gc_new( bitmap.GetPixmap() );
1326
1327 gdk_draw_rgb_image( bitmap.GetPixmap(),
1328 gc,
1329 0, 0,
1330 width, height,
1331 GDK_RGB_DITHER_NONE,
1332 GetData(),
1333 width*3 );
1334
1335 gdk_gc_unref( gc );
1336
1337 return bitmap;
1338 }
1339
1340 #endif
1341
1342 // Create picture image
1343
1344 GdkImage *data_image =
1345 gdk_image_new( GDK_IMAGE_FASTEST, gdk_visual_get_system(), width, height );
1346
1347 // Create mask image
1348
1349 GdkImage *mask_image = (GdkImage*) NULL;
1350
1351 if (HasMask())
1352 {
1353 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1354
1355 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1356
1357 wxMask *mask = new wxMask();
1358 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1359
1360 bitmap.SetMask( mask );
1361 }
1362
1363 // Render
1364
1365 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1366 byte_order b_o = RGB;
1367
1368 if (bpp >= 24)
1369 {
1370 GdkVisual *visual = gdk_visual_get_system();
1371 if ((visual->red_mask > visual->green_mask) && (visual->green_mask > visual->blue_mask)) b_o = RGB;
1372 else if ((visual->red_mask > visual->blue_mask) && (visual->blue_mask > visual->green_mask)) b_o = RGB;
1373 else if ((visual->blue_mask > visual->red_mask) && (visual->red_mask > visual->green_mask)) b_o = BRG;
1374 else if ((visual->blue_mask > visual->green_mask) && (visual->green_mask > visual->red_mask)) b_o = BGR;
1375 else if ((visual->green_mask > visual->red_mask) && (visual->red_mask > visual->blue_mask)) b_o = GRB;
1376 else if ((visual->green_mask > visual->blue_mask) && (visual->blue_mask > visual->red_mask)) b_o = GBR;
1377 }
1378
1379 int r_mask = GetMaskRed();
1380 int g_mask = GetMaskGreen();
1381 int b_mask = GetMaskBlue();
1382
1383 unsigned char* data = GetData();
1384
1385 int index = 0;
1386 for (int y = 0; y < height; y++)
1387 {
1388 for (int x = 0; x < width; x++)
1389 {
1390 int r = data[index];
1391 index++;
1392 int g = data[index];
1393 index++;
1394 int b = data[index];
1395 index++;
1396
1397 if (HasMask())
1398 {
1399 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1400 gdk_image_put_pixel( mask_image, x, y, 1 );
1401 else
1402 gdk_image_put_pixel( mask_image, x, y, 0 );
1403 }
1404
1405 if (HasMask())
1406 {
1407 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1408 gdk_image_put_pixel( mask_image, x, y, 1 );
1409 else
1410 gdk_image_put_pixel( mask_image, x, y, 0 );
1411 }
1412
1413 switch (bpp)
1414 {
1415 case 8:
1416 {
1417 int pixel = -1;
1418 if (wxTheApp->m_colorCube)
1419 {
1420 pixel = wxTheApp->m_colorCube[ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1421 }
1422 else
1423 {
1424 GdkColormap *cmap = gtk_widget_get_default_colormap();
1425 GdkColor *colors = cmap->colors;
1426 int max = 3 * (65536);
1427
1428 for (int i = 0; i < cmap->size; i++)
1429 {
1430 int rdiff = (r << 8) - colors[i].red;
1431 int gdiff = (g << 8) - colors[i].green;
1432 int bdiff = (b << 8) - colors[i].blue;
1433 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1434 if (sum < max) { pixel = i; max = sum; }
1435 }
1436 }
1437
1438 gdk_image_put_pixel( data_image, x, y, pixel );
1439
1440 break;
1441 }
1442 case 15:
1443 {
1444 guint32 pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1445 gdk_image_put_pixel( data_image, x, y, pixel );
1446 break;
1447 }
1448 case 16:
1449 {
1450 guint32 pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1451 gdk_image_put_pixel( data_image, x, y, pixel );
1452 break;
1453 }
1454 case 32:
1455 case 24:
1456 {
1457 guint32 pixel = 0;
1458 switch (b_o)
1459 {
1460 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1461 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1462 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1463 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1464 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1465 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1466 }
1467 gdk_image_put_pixel( data_image, x, y, pixel );
1468 }
1469 default: break;
1470 }
1471 } // for
1472 } // for
1473
1474 // Blit picture
1475
1476 GdkGC *data_gc = gdk_gc_new( bitmap.GetPixmap() );
1477
1478 gdk_draw_image( bitmap.GetPixmap(), data_gc, data_image, 0, 0, 0, 0, width, height );
1479
1480 gdk_image_destroy( data_image );
1481 gdk_gc_unref( data_gc );
1482
1483 // Blit mask
1484
1485 if (HasMask())
1486 {
1487 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
1488
1489 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
1490
1491 gdk_image_destroy( mask_image );
1492 gdk_gc_unref( mask_gc );
1493 }
1494
1495 return bitmap;
1496 }
1497
1498 wxImage::wxImage( const wxBitmap &bitmap )
1499 {
1500 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
1501
1502 GdkImage *gdk_image = (GdkImage*) NULL;
1503 if (bitmap.GetPixmap())
1504 {
1505 gdk_image = gdk_image_get( bitmap.GetPixmap(),
1506 0, 0,
1507 bitmap.GetWidth(), bitmap.GetHeight() );
1508 } else
1509 if (bitmap.GetBitmap())
1510 {
1511 gdk_image = gdk_image_get( bitmap.GetBitmap(),
1512 0, 0,
1513 bitmap.GetWidth(), bitmap.GetHeight() );
1514 } else
1515 {
1516 wxFAIL_MSG( wxT("Ill-formed bitmap") );
1517 }
1518
1519 wxCHECK_RET( gdk_image, wxT("couldn't create image") );
1520
1521 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1522 char unsigned *data = GetData();
1523
1524 if (!data)
1525 {
1526 gdk_image_destroy( gdk_image );
1527 wxFAIL_MSG( wxT("couldn't create image") );
1528 return;
1529 }
1530
1531 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1532 if (bitmap.GetMask())
1533 {
1534 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1535 0, 0,
1536 bitmap.GetWidth(), bitmap.GetHeight() );
1537
1538 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1539 }
1540
1541 GdkVisual *visual = (GdkVisual*) NULL;
1542 if (bitmap.GetPixmap())
1543 visual = gdk_window_get_visual( bitmap.GetPixmap() );
1544 else
1545 visual = gdk_window_get_visual( bitmap.GetBitmap() );
1546
1547 if (visual == NULL) visual = gdk_window_get_visual( (GdkWindow*) &gdk_root_parent );
1548 int bpp = visual->depth;
1549 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
1550
1551 GdkColormap *cmap = gtk_widget_get_default_colormap();
1552
1553 long pos = 0;
1554 for (int j = 0; j < bitmap.GetHeight(); j++)
1555 {
1556 for (int i = 0; i < bitmap.GetWidth(); i++)
1557 {
1558 wxInt32 pixel = gdk_image_get_pixel( gdk_image, i, j );
1559 // pixel = wxINT32_SWAP_ON_BE( pixel );
1560 if (bpp <= 8)
1561 {
1562 data[pos] = cmap->colors[pixel].red >> 8;
1563 data[pos+1] = cmap->colors[pixel].green >> 8;
1564 data[pos+2] = cmap->colors[pixel].blue >> 8;
1565 } else if (bpp == 15)
1566 {
1567 data[pos] = (pixel >> 7) & 0xf8;
1568 data[pos+1] = (pixel >> 2) & 0xf8;
1569 data[pos+2] = (pixel << 3) & 0xf8;
1570 } else if (bpp == 16)
1571 {
1572 data[pos] = (pixel >> 8) & 0xf8;
1573 data[pos+1] = (pixel >> 3) & 0xfc;
1574 data[pos+2] = (pixel << 3) & 0xf8;
1575 } else
1576 {
1577 data[pos] = (pixel >> 16) & 0xff;
1578 data[pos+1] = (pixel >> 8) & 0xff;
1579 data[pos+2] = pixel & 0xff;
1580 }
1581
1582 if (gdk_image_mask)
1583 {
1584 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1585 if (mask_pixel == 0)
1586 {
1587 data[pos] = 16;
1588 data[pos+1] = 16;
1589 data[pos+2] = 16;
1590 }
1591 }
1592
1593 pos += 3;
1594 }
1595 }
1596
1597 gdk_image_destroy( gdk_image );
1598 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1599 }
1600
1601 #endif
1602
1603 //-----------------------------------------------------------------------------
1604 // Motif conversion routines
1605 //-----------------------------------------------------------------------------
1606
1607 #ifdef __WXMOTIF__
1608 #ifdef __VMS__
1609 #pragma message disable nosimpint
1610 #endif
1611 #include <Xm/Xm.h>
1612 #ifdef __VMS__
1613 #pragma message enable nosimpint
1614 #endif
1615 #include "wx/utils.h"
1616 #include <math.h>
1617
1618 wxBitmap wxImage::ConvertToBitmap() const
1619 {
1620 wxBitmap bitmap;
1621
1622 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
1623
1624 int width = GetWidth();
1625 int height = GetHeight();
1626
1627 bitmap.SetHeight( height );
1628 bitmap.SetWidth( width );
1629
1630 Display *dpy = (Display*) wxGetDisplay();
1631 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1632 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1633
1634 // Create image
1635
1636 XImage *data_image = XCreateImage( dpy, vis, bpp, ZPixmap, 0, 0, width, height, 32, 0 );
1637 data_image->data = (char*) malloc( data_image->bytes_per_line * data_image->height );
1638
1639 bitmap.Create( width, height, bpp );
1640
1641 /*
1642 // Create mask
1643
1644 GdkImage *mask_image = (GdkImage*) NULL;
1645
1646 if (HasMask())
1647 {
1648 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1649
1650 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1651
1652 wxMask *mask = new wxMask();
1653 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1654
1655 bitmap.SetMask( mask );
1656 }
1657 */
1658
1659 // Retrieve depth info
1660
1661 XVisualInfo vinfo_template;
1662 XVisualInfo *vi;
1663
1664 vinfo_template.visual = vis;
1665 vinfo_template.visualid = XVisualIDFromVisual( vis );
1666 vinfo_template.depth = bpp;
1667 int nitem = 0;
1668
1669 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1670
1671 wxCHECK_MSG( vi, wxNullBitmap, wxT("no visual") );
1672
1673 XFree( vi );
1674
1675 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1676 if (bpp < 8) bpp = 8;
1677
1678 // Render
1679
1680 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1681 byte_order b_o = RGB;
1682
1683 if (bpp >= 24)
1684 {
1685 if ((vi->red_mask > vi->green_mask) && (vi->green_mask > vi->blue_mask)) b_o = RGB;
1686 else if ((vi->red_mask > vi->blue_mask) && (vi->blue_mask > vi->green_mask)) b_o = RGB;
1687 else if ((vi->blue_mask > vi->red_mask) && (vi->red_mask > vi->green_mask)) b_o = BRG;
1688 else if ((vi->blue_mask > vi->green_mask) && (vi->green_mask > vi->red_mask)) b_o = BGR;
1689 else if ((vi->green_mask > vi->red_mask) && (vi->red_mask > vi->blue_mask)) b_o = GRB;
1690 else if ((vi->green_mask > vi->blue_mask) && (vi->blue_mask > vi->red_mask)) b_o = GBR;
1691 }
1692
1693 /*
1694 int r_mask = GetMaskRed();
1695 int g_mask = GetMaskGreen();
1696 int b_mask = GetMaskBlue();
1697 */
1698
1699 XColor colors[256];
1700 if (bpp == 8)
1701 {
1702 Colormap cmap = (Colormap) wxTheApp->GetMainColormap( dpy );
1703
1704 for (int i = 0; i < 256; i++) colors[i].pixel = i;
1705 XQueryColors( dpy, cmap, colors, 256 );
1706 }
1707
1708 unsigned char* data = GetData();
1709
1710 int index = 0;
1711 for (int y = 0; y < height; y++)
1712 {
1713 for (int x = 0; x < width; x++)
1714 {
1715 int r = data[index];
1716 index++;
1717 int g = data[index];
1718 index++;
1719 int b = data[index];
1720 index++;
1721
1722 /*
1723 if (HasMask())
1724 {
1725 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1726 gdk_image_put_pixel( mask_image, x, y, 1 );
1727 else
1728 gdk_image_put_pixel( mask_image, x, y, 0 );
1729 }
1730 */
1731
1732 switch (bpp)
1733 {
1734 case 8:
1735 {
1736 int pixel = -1;
1737 /*
1738 if (wxTheApp->m_colorCube)
1739 {
1740 pixel = wxTheApp->m_colorCube
1741 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1742 }
1743 else
1744 {
1745 */
1746 int max = 3 * (65536);
1747 for (int i = 0; i < 256; i++)
1748 {
1749 int rdiff = (r << 8) - colors[i].red;
1750 int gdiff = (g << 8) - colors[i].green;
1751 int bdiff = (b << 8) - colors[i].blue;
1752 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1753 if (sum < max) { pixel = i; max = sum; }
1754 }
1755 /*
1756 }
1757 */
1758 XPutPixel( data_image, x, y, pixel );
1759 break;
1760 }
1761 case 15:
1762 {
1763 int pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1764 XPutPixel( data_image, x, y, pixel );
1765 break;
1766 }
1767 case 16:
1768 {
1769 int pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1770 XPutPixel( data_image, x, y, pixel );
1771 break;
1772 }
1773 case 32:
1774 case 24:
1775 {
1776 int pixel = 0;
1777 switch (b_o)
1778 {
1779 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1780 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1781 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1782 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1783 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1784 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1785 }
1786 XPutPixel( data_image, x, y, pixel );
1787 }
1788 default: break;
1789 }
1790 } // for
1791 } // for
1792
1793 // Blit picture
1794
1795 XGCValues gcvalues;
1796 gcvalues.foreground = BlackPixel( dpy, DefaultScreen( dpy ) );
1797 GC gc = XCreateGC( dpy, RootWindow ( dpy, DefaultScreen(dpy) ), GCForeground, &gcvalues );
1798 XPutImage( dpy, (Drawable)bitmap.GetPixmap(), gc, data_image, 0, 0, 0, 0, width, height );
1799
1800 XDestroyImage( data_image );
1801 XFreeGC( dpy, gc );
1802
1803 /*
1804 // Blit mask
1805
1806 if (HasMask())
1807 {
1808 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
1809
1810 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
1811
1812 gdk_image_destroy( mask_image );
1813 gdk_gc_unref( mask_gc );
1814 }
1815 */
1816
1817 return bitmap;
1818 }
1819
1820 wxImage::wxImage( const wxBitmap &bitmap )
1821 {
1822 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
1823
1824 Display *dpy = (Display*) wxGetDisplay();
1825 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1826 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1827
1828 XImage *ximage = XGetImage( dpy,
1829 (Drawable)bitmap.GetPixmap(),
1830 0, 0,
1831 bitmap.GetWidth(), bitmap.GetHeight(),
1832 AllPlanes, ZPixmap );
1833
1834 wxCHECK_RET( ximage, wxT("couldn't create image") );
1835
1836 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1837 char unsigned *data = GetData();
1838
1839 if (!data)
1840 {
1841 XDestroyImage( ximage );
1842 wxFAIL_MSG( wxT("couldn't create image") );
1843 return;
1844 }
1845
1846 /*
1847 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1848 if (bitmap.GetMask())
1849 {
1850 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1851 0, 0,
1852 bitmap.GetWidth(), bitmap.GetHeight() );
1853
1854 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1855 }
1856 */
1857
1858 // Retrieve depth info
1859
1860 XVisualInfo vinfo_template;
1861 XVisualInfo *vi;
1862
1863 vinfo_template.visual = vis;
1864 vinfo_template.visualid = XVisualIDFromVisual( vis );
1865 vinfo_template.depth = bpp;
1866 int nitem = 0;
1867
1868 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1869
1870 wxCHECK_RET( vi, wxT("no visual") );
1871
1872 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1873
1874 XFree( vi );
1875
1876 XColor colors[256];
1877 if (bpp == 8)
1878 {
1879 Colormap cmap = (Colormap)wxTheApp->GetMainColormap( dpy );
1880
1881 for (int i = 0; i < 256; i++) colors[i].pixel = i;
1882 XQueryColors( dpy, cmap, colors, 256 );
1883 }
1884
1885 long pos = 0;
1886 for (int j = 0; j < bitmap.GetHeight(); j++)
1887 {
1888 for (int i = 0; i < bitmap.GetWidth(); i++)
1889 {
1890 int pixel = XGetPixel( ximage, i, j );
1891 if (bpp <= 8)
1892 {
1893 data[pos] = colors[pixel].red >> 8;
1894 data[pos+1] = colors[pixel].green >> 8;
1895 data[pos+2] = colors[pixel].blue >> 8;
1896 } else if (bpp == 15)
1897 {
1898 data[pos] = (pixel >> 7) & 0xf8;
1899 data[pos+1] = (pixel >> 2) & 0xf8;
1900 data[pos+2] = (pixel << 3) & 0xf8;
1901 } else if (bpp == 16)
1902 {
1903 data[pos] = (pixel >> 8) & 0xf8;
1904 data[pos+1] = (pixel >> 3) & 0xfc;
1905 data[pos+2] = (pixel << 3) & 0xf8;
1906 } else
1907 {
1908 data[pos] = (pixel >> 16) & 0xff;
1909 data[pos+1] = (pixel >> 8) & 0xff;
1910 data[pos+2] = pixel & 0xff;
1911 }
1912
1913 /*
1914 if (gdk_image_mask)
1915 {
1916 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1917 if (mask_pixel == 0)
1918 {
1919 data[pos] = 16;
1920 data[pos+1] = 16;
1921 data[pos+2] = 16;
1922 }
1923 }
1924 */
1925
1926 pos += 3;
1927 }
1928 }
1929
1930 XDestroyImage( ximage );
1931 /*
1932 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1933 */
1934 }
1935 #endif
1936
1937 #ifdef __WXPM__
1938 // OS/2 Presentation manager conversion routings
1939
1940 wxBitmap wxImage::ConvertToBitmap() const
1941 {
1942 if ( !Ok() )
1943 return wxNullBitmap;
1944 wxBitmap bitmap; // remove
1945 // TODO:
1946 /*
1947 int sizeLimit = 1024*768*3;
1948
1949 // width and height of the device-dependent bitmap
1950 int width = GetWidth();
1951 int bmpHeight = GetHeight();
1952
1953 // calc the number of bytes per scanline and padding
1954 int bytePerLine = width*3;
1955 int sizeDWORD = sizeof( DWORD );
1956 int lineBoundary = bytePerLine % sizeDWORD;
1957 int padding = 0;
1958 if( lineBoundary > 0 )
1959 {
1960 padding = sizeDWORD - lineBoundary;
1961 bytePerLine += padding;
1962 }
1963 // calc the number of DIBs and heights of DIBs
1964 int numDIB = 1;
1965 int hRemain = 0;
1966 int height = sizeLimit/bytePerLine;
1967 if( height >= bmpHeight )
1968 height = bmpHeight;
1969 else
1970 {
1971 numDIB = bmpHeight / height;
1972 hRemain = bmpHeight % height;
1973 if( hRemain >0 ) numDIB++;
1974 }
1975
1976 // set bitmap parameters
1977 wxBitmap bitmap;
1978 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
1979 bitmap.SetWidth( width );
1980 bitmap.SetHeight( bmpHeight );
1981 bitmap.SetDepth( wxDisplayDepth() );
1982
1983 // create a DIB header
1984 int headersize = sizeof(BITMAPINFOHEADER);
1985 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
1986 wxCHECK_MSG( lpDIBh, bitmap, wxT("could not allocate memory for DIB header") );
1987 // Fill in the DIB header
1988 lpDIBh->bmiHeader.biSize = headersize;
1989 lpDIBh->bmiHeader.biWidth = (DWORD)width;
1990 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
1991 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
1992 // the general formula for biSizeImage:
1993 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
1994 lpDIBh->bmiHeader.biPlanes = 1;
1995 lpDIBh->bmiHeader.biBitCount = 24;
1996 lpDIBh->bmiHeader.biCompression = BI_RGB;
1997 lpDIBh->bmiHeader.biClrUsed = 0;
1998 // These seem not really needed for our purpose here.
1999 lpDIBh->bmiHeader.biClrImportant = 0;
2000 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2001 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2002 // memory for DIB data
2003 unsigned char *lpBits;
2004 lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
2005 if( !lpBits )
2006 {
2007 wxFAIL_MSG( wxT("could not allocate memory for DIB") );
2008 free( lpDIBh );
2009 return bitmap;
2010 }
2011
2012 // create and set the device-dependent bitmap
2013 HDC hdc = ::GetDC(NULL);
2014 HDC memdc = ::CreateCompatibleDC( hdc );
2015 HBITMAP hbitmap;
2016 hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
2017 ::SelectObject( memdc, hbitmap);
2018
2019 // copy image data into DIB data and then into DDB (in a loop)
2020 unsigned char *data = GetData();
2021 int i, j, n;
2022 int origin = 0;
2023 unsigned char *ptdata = data;
2024 unsigned char *ptbits;
2025
2026 for( n=0; n<numDIB; n++ )
2027 {
2028 if( numDIB > 1 && n == numDIB-1 && hRemain > 0 )
2029 {
2030 // redefine height and size of the (possibly) last smaller DIB
2031 // memory is not reallocated
2032 height = hRemain;
2033 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2034 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2035 }
2036 ptbits = lpBits;
2037
2038 for( j=0; j<height; j++ )
2039 {
2040 for( i=0; i<width; i++ )
2041 {
2042 *(ptbits++) = *(ptdata+2);
2043 *(ptbits++) = *(ptdata+1);
2044 *(ptbits++) = *(ptdata );
2045 ptdata += 3;
2046 }
2047 for( i=0; i< padding; i++ ) *(ptbits++) = 0;
2048 }
2049 ::StretchDIBits( memdc, 0, origin, width, height,\
2050 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2051 origin += height;
2052 // if numDIB = 1, lines below can also be used
2053 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
2054 // The above line is equivalent to the following two lines.
2055 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2056 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
2057 // or the following lines
2058 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
2059 // HDC memdc = ::CreateCompatibleDC( hdc );
2060 // ::SelectObject( memdc, hbitmap);
2061 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
2062 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
2063 // ::SelectObject( memdc, 0 );
2064 // ::DeleteDC( memdc );
2065 }
2066 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
2067
2068 // similarly, created an mono-bitmap for the possible mask
2069 if( HasMask() )
2070 {
2071 hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL );
2072 ::SelectObject( memdc, hbitmap);
2073 if( numDIB == 1 ) height = bmpHeight;
2074 else height = sizeLimit/bytePerLine;
2075 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2076 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2077 origin = 0;
2078 unsigned char r = GetMaskRed();
2079 unsigned char g = GetMaskGreen();
2080 unsigned char b = GetMaskBlue();
2081 unsigned char zero = 0, one = 255;
2082 ptdata = data;
2083 for( n=0; n<numDIB; n++ )
2084 {
2085 if( numDIB > 1 && n == numDIB - 1 && hRemain > 0 )
2086 {
2087 // redefine height and size of the (possibly) last smaller DIB
2088 // memory is not reallocated
2089 height = hRemain;
2090 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
2091 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
2092 }
2093 ptbits = lpBits;
2094 for( int j=0; j<height; j++ )
2095 {
2096 for(i=0; i<width; i++ )
2097 {
2098 if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
2099 {
2100 *(ptbits++) = one;
2101 *(ptbits++) = one;
2102 *(ptbits++) = one;
2103 }
2104 else
2105 {
2106 *(ptbits++) = zero;
2107 *(ptbits++) = zero;
2108 *(ptbits++) = zero;
2109 }
2110 }
2111 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
2112 }
2113 ::StretchDIBits( memdc, 0, origin, width, height,\
2114 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
2115 origin += height;
2116 }
2117 // create a wxMask object
2118 wxMask *mask = new wxMask();
2119 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
2120 bitmap.SetMask( mask );
2121 }
2122
2123 // free allocated resources
2124 ::SelectObject( memdc, 0 );
2125 ::DeleteDC( memdc );
2126 ::ReleaseDC(NULL, hdc);
2127 free(lpDIBh);
2128 free(lpBits);
2129
2130 // check the wxBitmap object
2131 if( bitmap.GetHBITMAP() )
2132 bitmap.SetOk( TRUE );
2133 else
2134 bitmap.SetOk( FALSE );
2135 */
2136 return bitmap;
2137 }
2138
2139 wxImage::wxImage( const wxBitmap &bitmap )
2140 {
2141 // check the bitmap
2142 if( !bitmap.Ok() )
2143 {
2144 wxFAIL_MSG( wxT("invalid bitmap") );
2145 return;
2146 }
2147
2148 // create an wxImage object
2149 int width = bitmap.GetWidth();
2150 int height = bitmap.GetHeight();
2151 Create( width, height );
2152 unsigned char *data = GetData();
2153 if( !data )
2154 {
2155 wxFAIL_MSG( wxT("could not allocate data for image") );
2156 return;
2157 }
2158
2159 // calc the number of bytes per scanline and padding in the DIB
2160 int bytePerLine = width*3;
2161 int sizeDWORD = sizeof( DWORD );
2162 int lineBoundary = bytePerLine % sizeDWORD;
2163 int padding = 0;
2164 if( lineBoundary > 0 )
2165 {
2166 padding = sizeDWORD - lineBoundary;
2167 bytePerLine += padding;
2168 }
2169 // TODO:
2170 /*
2171 // create a DIB header
2172 int headersize = sizeof(BITMAPINFOHEADER);
2173 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
2174 if( !lpDIBh )
2175 {
2176 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
2177 free( data );
2178 return;
2179 }
2180 // Fill in the DIB header
2181 lpDIBh->bmiHeader.biSize = headersize;
2182 lpDIBh->bmiHeader.biWidth = width;
2183 lpDIBh->bmiHeader.biHeight = -height;
2184 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
2185 lpDIBh->bmiHeader.biPlanes = 1;
2186 lpDIBh->bmiHeader.biBitCount = 24;
2187 lpDIBh->bmiHeader.biCompression = BI_RGB;
2188 lpDIBh->bmiHeader.biClrUsed = 0;
2189 // These seem not really needed for our purpose here.
2190 lpDIBh->bmiHeader.biClrImportant = 0;
2191 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
2192 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
2193 // memory for DIB data
2194 unsigned char *lpBits;
2195 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
2196 if( !lpBits )
2197 {
2198 wxFAIL_MSG( wxT("could not allocate data for DIB") );
2199 free( data );
2200 free( lpDIBh );
2201 return;
2202 }
2203
2204 // copy data from the device-dependent bitmap to the DIB
2205 HDC hdc = ::GetDC(NULL);
2206 HBITMAP hbitmap;
2207 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
2208 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2209
2210 // copy DIB data into the wxImage object
2211 int i, j;
2212 unsigned char *ptdata = data;
2213 unsigned char *ptbits = lpBits;
2214 for( i=0; i<height; i++ )
2215 {
2216 for( j=0; j<width; j++ )
2217 {
2218 *(ptdata++) = *(ptbits+2);
2219 *(ptdata++) = *(ptbits+1);
2220 *(ptdata++) = *(ptbits );
2221 ptbits += 3;
2222 }
2223 ptbits += padding;
2224 }
2225
2226 // similarly, set data according to the possible mask bitmap
2227 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
2228 {
2229 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
2230 // memory DC created, color set, data copied, and memory DC deleted
2231 HDC memdc = ::CreateCompatibleDC( hdc );
2232 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
2233 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
2234 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
2235 ::DeleteDC( memdc );
2236 // background color set to RGB(16,16,16) in consistent with wxGTK
2237 unsigned char r=16, g=16, b=16;
2238 ptdata = data;
2239 ptbits = lpBits;
2240 for( i=0; i<height; i++ )
2241 {
2242 for( j=0; j<width; j++ )
2243 {
2244 if( *ptbits != 0 )
2245 ptdata += 3;
2246 else
2247 {
2248 *(ptdata++) = r;
2249 *(ptdata++) = g;
2250 *(ptdata++) = b;
2251 }
2252 ptbits += 3;
2253 }
2254 ptbits += padding;
2255 }
2256 SetMaskColour( r, g, b );
2257 SetMask( TRUE );
2258 }
2259 else
2260 {
2261 SetMask( FALSE );
2262 }
2263 // free allocated resources
2264 ::ReleaseDC(NULL, hdc);
2265 free(lpDIBh);
2266 free(lpBits);
2267 */
2268 }
2269
2270 #endif
2271
2272 // A module to allow wxImage initialization/cleanup
2273 // without calling these functions from app.cpp or from
2274 // the user's application.
2275
2276 class wxImageModule: public wxModule
2277 {
2278 DECLARE_DYNAMIC_CLASS(wxImageModule)
2279 public:
2280 wxImageModule() {}
2281 bool OnInit() { wxImage::InitStandardHandlers(); return TRUE; };
2282 void OnExit() { wxImage::CleanUpHandlers(); };
2283 };
2284
2285 IMPLEMENT_DYNAMIC_CLASS(wxImageModule, wxModule)