]> git.saurik.com Git - wxWidgets.git/blob - src/common/image.cpp
Fixed bug in function Flush().
[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, _T("invalid image") );
158
159 wxCHECK_MSG( (width > 0) && (height > 0), image, _T("invalid image size") );
160
161 image.Create( width, height );
162
163 char unsigned *data = image.GetData();
164
165 wxCHECK_MSG( data, image, _T("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 void wxImage::SetRGB( int x, int y, unsigned char r, unsigned char g, unsigned char b )
193 {
194 wxCHECK_RET( Ok(), _T("invalid image") );
195
196 int w = M_IMGDATA->m_width;
197 int h = M_IMGDATA->m_height;
198
199 wxCHECK_RET( (x>=0) && (y>=0) && (x<w) && (y<h), _T("invalid image index") );
200
201 long pos = (y * w + x) * 3;
202
203 M_IMGDATA->m_data[ pos ] = r;
204 M_IMGDATA->m_data[ pos+1 ] = g;
205 M_IMGDATA->m_data[ pos+2 ] = b;
206 }
207
208 unsigned char wxImage::GetRed( int x, int y )
209 {
210 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
211
212 int w = M_IMGDATA->m_width;
213 int h = M_IMGDATA->m_height;
214
215 wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, _T("invalid image index") );
216
217 long pos = (y * w + x) * 3;
218
219 return M_IMGDATA->m_data[pos];
220 }
221
222 unsigned char wxImage::GetGreen( int x, int y )
223 {
224 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
225
226 int w = M_IMGDATA->m_width;
227 int h = M_IMGDATA->m_height;
228
229 wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, _T("invalid image index") );
230
231 long pos = (y * w + x) * 3;
232
233 return M_IMGDATA->m_data[pos+1];
234 }
235
236 unsigned char wxImage::GetBlue( int x, int y )
237 {
238 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
239
240 int w = M_IMGDATA->m_width;
241 int h = M_IMGDATA->m_height;
242
243 wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, _T("invalid image index") );
244
245 long pos = (y * w + x) * 3;
246
247 return M_IMGDATA->m_data[pos+2];
248 }
249
250 bool wxImage::Ok() const
251 {
252 return (M_IMGDATA && M_IMGDATA->m_ok);
253 }
254
255 char unsigned *wxImage::GetData() const
256 {
257 wxCHECK_MSG( Ok(), (char unsigned *)NULL, _T("invalid image") );
258
259 return M_IMGDATA->m_data;
260 }
261
262 void wxImage::SetData( char unsigned *data )
263 {
264 wxCHECK_RET( Ok(), _T("invalid image") );
265
266 memcpy(M_IMGDATA->m_data, data, M_IMGDATA->m_width * M_IMGDATA->m_height * 3);
267 }
268
269 void wxImage::SetMaskColour( unsigned char r, unsigned char g, unsigned char b )
270 {
271 wxCHECK_RET( Ok(), _T("invalid image") );
272
273 M_IMGDATA->m_maskRed = r;
274 M_IMGDATA->m_maskGreen = g;
275 M_IMGDATA->m_maskBlue = b;
276 M_IMGDATA->m_hasMask = TRUE;
277 }
278
279 unsigned char wxImage::GetMaskRed() const
280 {
281 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
282
283 return M_IMGDATA->m_maskRed;
284 }
285
286 unsigned char wxImage::GetMaskGreen() const
287 {
288 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
289
290 return M_IMGDATA->m_maskGreen;
291 }
292
293 unsigned char wxImage::GetMaskBlue() const
294 {
295 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
296
297 return M_IMGDATA->m_maskBlue;
298 }
299
300 void wxImage::SetMask( bool mask )
301 {
302 wxCHECK_RET( Ok(), _T("invalid image") );
303
304 M_IMGDATA->m_hasMask = mask;
305 }
306
307 bool wxImage::HasMask() const
308 {
309 wxCHECK_MSG( Ok(), FALSE, _T("invalid image") );
310
311 return M_IMGDATA->m_hasMask;
312 }
313
314 int wxImage::GetWidth() const
315 {
316 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
317
318 return M_IMGDATA->m_width;
319 }
320
321 int wxImage::GetHeight() const
322 {
323 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
324
325 return M_IMGDATA->m_height;
326 }
327
328 bool wxImage::LoadFile( const wxString& filename, long type )
329 {
330 #if wxUSE_STREAMS
331 if (wxFileExists(filename))
332 {
333 wxFileInputStream stream(filename);
334 return LoadFile(stream, type);
335 }
336
337 else {
338 wxLogError( _T("Can't load image from file '%s': file does not exist."), filename.c_str() );
339
340 return FALSE;
341 }
342 #else // !wxUSE_STREAMS
343 return FALSE;
344 #endif // wxUSE_STREAMS
345 }
346
347 bool wxImage::LoadFile( const wxString& filename, const wxString& mimetype )
348 {
349 #if wxUSE_STREAMS
350 if (wxFileExists(filename))
351 {
352 wxFileInputStream stream(filename);
353 return LoadFile(stream, mimetype);
354 }
355
356 else {
357 wxLogError( _T("Can't load image from file '%s': file does not exist."), filename.c_str() );
358
359 return FALSE;
360 }
361 #else // !wxUSE_STREAMS
362 return FALSE;
363 #endif // wxUSE_STREAMS
364 }
365
366 bool wxImage::SaveFile( const wxString& filename, int type )
367 {
368 #if wxUSE_STREAMS
369 wxFileOutputStream stream(filename);
370
371 if ( stream.LastError() == wxStream_NOERROR )
372 return SaveFile(stream, type);
373 else
374 #endif // wxUSE_STREAMS
375 return FALSE;
376 }
377
378 bool wxImage::SaveFile( const wxString& filename, const wxString& mimetype )
379 {
380 #if wxUSE_STREAMS
381 wxFileOutputStream stream(filename);
382
383 if ( stream.LastError() == wxStream_NOERROR )
384 return SaveFile(stream, mimetype);
385 else
386 #endif // wxUSE_STREAMS
387 return FALSE;
388 }
389
390 #if wxUSE_STREAMS
391 bool wxImage::LoadFile( wxInputStream& stream, long type )
392 {
393 UnRef();
394
395 m_refData = new wxImageRefData;
396
397 wxImageHandler *handler = FindHandler(type);
398
399 if (handler == NULL)
400 {
401 wxLogWarning( _T("No image handler for type %d defined."), type );
402
403 return FALSE;
404 }
405
406 return handler->LoadFile( this, stream );
407 }
408
409 bool wxImage::LoadFile( wxInputStream& stream, const wxString& mimetype )
410 {
411 UnRef();
412
413 m_refData = new wxImageRefData;
414
415 wxImageHandler *handler = FindHandlerMime(mimetype);
416
417 if (handler == NULL)
418 {
419 wxLogWarning( _T("No image handler for type %s defined."), mimetype.GetData() );
420
421 return FALSE;
422 }
423
424 return handler->LoadFile( this, stream );
425 }
426
427 bool wxImage::SaveFile( wxOutputStream& stream, int type )
428 {
429 wxCHECK_MSG( Ok(), FALSE, _T("invalid image") );
430
431 wxImageHandler *handler = FindHandler(type);
432
433 if (handler == NULL)
434 {
435 wxLogWarning( _T("No image handler for type %d defined."), type );
436
437 return FALSE;
438 }
439
440 return handler->SaveFile( this, stream );
441 }
442
443 bool wxImage::SaveFile( wxOutputStream& stream, const wxString& mimetype )
444 {
445 wxCHECK_MSG( Ok(), FALSE, _T("invalid image") );
446
447 wxImageHandler *handler = FindHandlerMime(mimetype);
448
449 if (handler == NULL)
450 {
451 wxLogWarning( _T("No image handler for type %s defined."), mimetype.GetData() );
452
453 return FALSE;
454 }
455
456 return handler->SaveFile( this, stream );
457 }
458 #endif // wxUSE_STREAMS
459
460 void wxImage::AddHandler( wxImageHandler *handler )
461 {
462 // make sure that the memory will be freed at the program end
463 sm_handlers.DeleteContents(TRUE);
464
465 sm_handlers.Append( handler );
466 }
467
468 void wxImage::InsertHandler( wxImageHandler *handler )
469 {
470 // make sure that the memory will be freed at the program end
471 sm_handlers.DeleteContents(TRUE);
472
473 sm_handlers.Insert( handler );
474 }
475
476 bool wxImage::RemoveHandler( const wxString& name )
477 {
478 wxImageHandler *handler = FindHandler(name);
479 if (handler)
480 {
481 sm_handlers.DeleteObject(handler);
482 return TRUE;
483 }
484 else
485 return FALSE;
486 }
487
488 wxImageHandler *wxImage::FindHandler( const wxString& name )
489 {
490 wxNode *node = sm_handlers.First();
491 while (node)
492 {
493 wxImageHandler *handler = (wxImageHandler*)node->Data();
494 if (handler->GetName().Cmp(name) == 0) return handler;
495
496 node = node->Next();
497 }
498 return (wxImageHandler *)NULL;
499 }
500
501 wxImageHandler *wxImage::FindHandler( const wxString& extension, long bitmapType )
502 {
503 wxNode *node = sm_handlers.First();
504 while (node)
505 {
506 wxImageHandler *handler = (wxImageHandler*)node->Data();
507 if ( (handler->GetExtension().Cmp(extension) == 0) &&
508 (bitmapType == -1 || handler->GetType() == bitmapType) )
509 return handler;
510 node = node->Next();
511 }
512 return (wxImageHandler*)NULL;
513 }
514
515 wxImageHandler *wxImage::FindHandler( long bitmapType )
516 {
517 wxNode *node = sm_handlers.First();
518 while (node)
519 {
520 wxImageHandler *handler = (wxImageHandler *)node->Data();
521 if (handler->GetType() == bitmapType) return handler;
522 node = node->Next();
523 }
524 return NULL;
525 }
526
527 wxImageHandler *wxImage::FindHandlerMime( const wxString& mimetype )
528 {
529 wxNode *node = sm_handlers.First();
530 while (node)
531 {
532 wxImageHandler *handler = (wxImageHandler *)node->Data();
533 if (handler->GetMimeType().IsSameAs(mimetype, FALSE)) return handler;
534 node = node->Next();
535 }
536 return NULL;
537 }
538
539 void wxImage::InitStandardHandlers()
540 {
541 AddHandler( new wxBMPHandler );
542 }
543
544 void wxImage::CleanUpHandlers()
545 {
546 wxNode *node = sm_handlers.First();
547 while (node)
548 {
549 wxImageHandler *handler = (wxImageHandler *)node->Data();
550 wxNode *next = node->Next();
551 delete handler;
552 delete node;
553 node = next;
554 }
555 }
556
557 //-----------------------------------------------------------------------------
558 // wxImageHandler
559 //-----------------------------------------------------------------------------
560
561 #if !USE_SHARED_LIBRARIES
562 IMPLEMENT_DYNAMIC_CLASS(wxImageHandler,wxObject)
563 #endif
564
565 #if wxUSE_STREAMS
566 bool wxImageHandler::LoadFile( wxImage *WXUNUSED(image), wxInputStream& WXUNUSED(stream) )
567 {
568 return FALSE;
569 }
570
571 bool wxImageHandler::SaveFile( wxImage *WXUNUSED(image), wxOutputStream& WXUNUSED(stream) )
572 {
573 return FALSE;
574 }
575 #endif // wxUSE_STREAMS
576
577 //-----------------------------------------------------------------------------
578 // MSW conversion routines
579 //-----------------------------------------------------------------------------
580
581 #ifdef __WXMSW__
582
583 wxBitmap wxImage::ConvertToBitmap() const
584 {
585 if ( !Ok() )
586 return wxNullBitmap;
587
588 // sizeLimit is the MS upper limit for the DIB size
589 int sizeLimit = 1024*768*3;
590
591 // width and height of the device-dependent bitmap
592 int width = GetWidth();
593 int bmpHeight = GetHeight();
594
595 // calc the number of bytes per scanline and padding
596 int bytePerLine = width*3;
597 int sizeDWORD = sizeof( DWORD );
598 int lineBoundary = bytePerLine % sizeDWORD;
599 int padding = 0;
600 if( lineBoundary > 0 )
601 {
602 padding = sizeDWORD - lineBoundary;
603 bytePerLine += padding;
604 }
605 // calc the number of DIBs and heights of DIBs
606 int numDIB = 1;
607 int hRemain = 0;
608 int height = sizeLimit/bytePerLine;
609 if( height >= bmpHeight )
610 height = bmpHeight;
611 else
612 {
613 numDIB = bmpHeight / height;
614 hRemain = bmpHeight % height;
615 if( hRemain >0 ) numDIB++;
616 }
617
618 // set bitmap parameters
619 wxBitmap bitmap;
620 wxCHECK_MSG( Ok(), bitmap, _T("invalid image") );
621 bitmap.SetWidth( width );
622 bitmap.SetHeight( bmpHeight );
623 bitmap.SetDepth( wxDisplayDepth() );
624
625 // create a DIB header
626 int headersize = sizeof(BITMAPINFOHEADER);
627 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
628 wxCHECK_MSG( lpDIBh, bitmap, _T("could not allocate memory for DIB header") );
629 // Fill in the DIB header
630 lpDIBh->bmiHeader.biSize = headersize;
631 lpDIBh->bmiHeader.biWidth = (DWORD)width;
632 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
633 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
634 // the general formula for biSizeImage:
635 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
636 lpDIBh->bmiHeader.biPlanes = 1;
637 lpDIBh->bmiHeader.biBitCount = 24;
638 lpDIBh->bmiHeader.biCompression = BI_RGB;
639 lpDIBh->bmiHeader.biClrUsed = 0;
640 // These seem not really needed for our purpose here.
641 lpDIBh->bmiHeader.biClrImportant = 0;
642 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
643 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
644 // memory for DIB data
645 unsigned char *lpBits;
646 lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
647 if( !lpBits )
648 {
649 wxFAIL_MSG( _T("could not allocate memory for DIB") );
650 free( lpDIBh );
651 return bitmap;
652 }
653
654 // create and set the device-dependent bitmap
655 HDC hdc = ::GetDC(NULL);
656 HDC memdc = ::CreateCompatibleDC( hdc );
657 HBITMAP hbitmap;
658 hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
659 ::SelectObject( memdc, hbitmap);
660
661 // copy image data into DIB data and then into DDB (in a loop)
662 unsigned char *data = GetData();
663 int i, j, n;
664 int origin = 0;
665 unsigned char *ptdata = data;
666 unsigned char *ptbits;
667
668 for( n=0; n<numDIB; n++ )
669 {
670 if( numDIB > 1 && n == numDIB-1 && hRemain > 0 )
671 {
672 // redefine height and size of the (possibly) last smaller DIB
673 // memory is not reallocated
674 height = hRemain;
675 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
676 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
677 }
678 ptbits = lpBits;
679
680 for( j=0; j<height; j++ )
681 {
682 for( i=0; i<width; i++ )
683 {
684 *(ptbits++) = *(ptdata+2);
685 *(ptbits++) = *(ptdata+1);
686 *(ptbits++) = *(ptdata );
687 ptdata += 3;
688 }
689 for( i=0; i< padding; i++ ) *(ptbits++) = 0;
690 }
691 ::StretchDIBits( memdc, 0, origin, width, height,\
692 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
693 origin += height;
694 // if numDIB = 1, lines below can also be used
695 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
696 // The above line is equivalent to the following two lines.
697 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
698 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
699 // or the following lines
700 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
701 // HDC memdc = ::CreateCompatibleDC( hdc );
702 // ::SelectObject( memdc, hbitmap);
703 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
704 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
705 // ::SelectObject( memdc, 0 );
706 // ::DeleteDC( memdc );
707 }
708 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
709
710 // similarly, created an mono-bitmap for the possible mask
711 if( HasMask() )
712 {
713 hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL );
714 ::SelectObject( memdc, hbitmap);
715 if( numDIB == 1 ) height = bmpHeight;
716 else height = sizeLimit/bytePerLine;
717 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
718 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
719 origin = 0;
720 unsigned char r = GetMaskRed();
721 unsigned char g = GetMaskGreen();
722 unsigned char b = GetMaskBlue();
723 unsigned char zero = 0, one = 255;
724 ptdata = data;
725 for( n=0; n<numDIB; n++ )
726 {
727 if( numDIB > 1 && n == numDIB - 1 && hRemain > 0 )
728 {
729 // redefine height and size of the (possibly) last smaller DIB
730 // memory is not reallocated
731 height = hRemain;
732 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
733 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
734 }
735 ptbits = lpBits;
736 for( int j=0; j<height; j++ )
737 {
738 for(i=0; i<width; i++ )
739 {
740 if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
741 {
742 *(ptbits++) = one;
743 *(ptbits++) = one;
744 *(ptbits++) = one;
745 }
746 else
747 {
748 *(ptbits++) = zero;
749 *(ptbits++) = zero;
750 *(ptbits++) = zero;
751 }
752 }
753 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
754 }
755 ::StretchDIBits( memdc, 0, origin, width, height,\
756 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
757 origin += height;
758 }
759 // create a wxMask object
760 wxMask *mask = new wxMask();
761 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
762 bitmap.SetMask( mask );
763 // It will be deleted when the wxBitmap object is deleted (as of 01/1999)
764 /* The following can also be used but is slow to run
765 wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
766 wxMask *mask = new wxMask( bitmap, colour );
767 bitmap.SetMask( mask );
768 */
769 }
770
771 // free allocated resources
772 ::SelectObject( memdc, 0 );
773 ::DeleteDC( memdc );
774 ::ReleaseDC(NULL, hdc);
775 free(lpDIBh);
776 free(lpBits);
777
778 // check the wxBitmap object
779 if( bitmap.GetHBITMAP() )
780 bitmap.SetOk( TRUE );
781 else
782 bitmap.SetOk( FALSE );
783
784 return bitmap;
785 }
786
787 wxImage::wxImage( const wxBitmap &bitmap )
788 {
789 // check the bitmap
790 if( !bitmap.Ok() )
791 {
792 wxFAIL_MSG( _T("invalid bitmap") );
793 return;
794 }
795
796 // create an wxImage object
797 int width = bitmap.GetWidth();
798 int height = bitmap.GetHeight();
799 Create( width, height );
800 unsigned char *data = GetData();
801 if( !data )
802 {
803 wxFAIL_MSG( _T("could not allocate data for image") );
804 return;
805 }
806
807 // calc the number of bytes per scanline and padding in the DIB
808 int bytePerLine = width*3;
809 int sizeDWORD = sizeof( DWORD );
810 int lineBoundary = bytePerLine % sizeDWORD;
811 int padding = 0;
812 if( lineBoundary > 0 )
813 {
814 padding = sizeDWORD - lineBoundary;
815 bytePerLine += padding;
816 }
817
818 // create a DIB header
819 int headersize = sizeof(BITMAPINFOHEADER);
820 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
821 if( !lpDIBh )
822 {
823 wxFAIL_MSG( _T("could not allocate data for DIB header") );
824 free( data );
825 return;
826 }
827 // Fill in the DIB header
828 lpDIBh->bmiHeader.biSize = headersize;
829 lpDIBh->bmiHeader.biWidth = width;
830 lpDIBh->bmiHeader.biHeight = -height;
831 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
832 lpDIBh->bmiHeader.biPlanes = 1;
833 lpDIBh->bmiHeader.biBitCount = 24;
834 lpDIBh->bmiHeader.biCompression = BI_RGB;
835 lpDIBh->bmiHeader.biClrUsed = 0;
836 // These seem not really needed for our purpose here.
837 lpDIBh->bmiHeader.biClrImportant = 0;
838 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
839 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
840 // memory for DIB data
841 unsigned char *lpBits;
842 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
843 if( !lpBits )
844 {
845 wxFAIL_MSG( _T("could not allocate data for DIB") );
846 free( data );
847 free( lpDIBh );
848 return;
849 }
850
851 // copy data from the device-dependent bitmap to the DIB
852 HDC hdc = ::GetDC(NULL);
853 HBITMAP hbitmap;
854 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
855 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
856
857 // copy DIB data into the wxImage object
858 int i, j;
859 unsigned char *ptdata = data;
860 unsigned char *ptbits = lpBits;
861 for( i=0; i<height; i++ )
862 {
863 for( j=0; j<width; j++ )
864 {
865 *(ptdata++) = *(ptbits+2);
866 *(ptdata++) = *(ptbits+1);
867 *(ptdata++) = *(ptbits );
868 ptbits += 3;
869 }
870 ptbits += padding;
871 }
872
873 // similarly, set data according to the possible mask bitmap
874 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
875 {
876 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
877 // memory DC created, color set, data copied, and memory DC deleted
878 HDC memdc = ::CreateCompatibleDC( hdc );
879 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
880 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
881 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
882 ::DeleteDC( memdc );
883 // background color set to RGB(16,16,16) in consistent with wxGTK
884 unsigned char r=16, g=16, b=16;
885 ptdata = data;
886 ptbits = lpBits;
887 for( i=0; i<height; i++ )
888 {
889 for( j=0; j<width; j++ )
890 {
891 if( *ptbits != 0 )
892 ptdata += 3;
893 else
894 {
895 *(ptdata++) = r;
896 *(ptdata++) = g;
897 *(ptdata++) = b;
898 }
899 ptbits += 3;
900 }
901 ptbits += padding;
902 }
903 SetMaskColour( r, g, b );
904 SetMask( TRUE );
905 }
906 else
907 {
908 SetMask( FALSE );
909 }
910 // free allocated resources
911 ::ReleaseDC(NULL, hdc);
912 free(lpDIBh);
913 free(lpBits);
914 }
915
916 #endif
917
918 //-----------------------------------------------------------------------------
919 // GTK conversion routines
920 //-----------------------------------------------------------------------------
921
922 #ifdef __WXGTK__
923
924 #include "gtk/gtk.h"
925 #include "gdk/gdk.h"
926 #include "gdk/gdkx.h"
927
928 #if (GTK_MINOR_VERSION > 0)
929 #include "gdk/gdkrgb.h"
930 #endif
931
932 wxBitmap wxImage::ConvertToBitmap() const
933 {
934 wxBitmap bitmap;
935
936 wxCHECK_MSG( Ok(), bitmap, _T("invalid image") );
937
938 int width = GetWidth();
939 int height = GetHeight();
940
941 bitmap.SetHeight( height );
942 bitmap.SetWidth( width );
943
944 bitmap.SetPixmap( gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, -1 ) );
945
946 // Retrieve depth
947
948 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
949 if (visual == NULL) visual = gdk_visual_get_system();
950 int bpp = visual->depth;
951
952 bitmap.SetDepth( bpp );
953
954 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
955 if (bpp < 8) bpp = 8;
956
957 #if (GTK_MINOR_VERSION > 0)
958
959 if (!HasMask() && (bpp > 8))
960 {
961 static bool s_hasInitialized = FALSE;
962
963 if (!s_hasInitialized)
964 {
965 gdk_rgb_init();
966 s_hasInitialized = TRUE;
967 }
968
969 GdkGC *gc = gdk_gc_new( bitmap.GetPixmap() );
970
971 gdk_draw_rgb_image( bitmap.GetPixmap(),
972 gc,
973 0, 0,
974 width, height,
975 GDK_RGB_DITHER_NONE,
976 GetData(),
977 width*3 );
978
979 gdk_gc_unref( gc );
980
981 return bitmap;
982 }
983
984 #endif
985
986 // Create picture image
987
988 GdkImage *data_image =
989 gdk_image_new( GDK_IMAGE_FASTEST, gdk_visual_get_system(), width, height );
990
991 // Create mask image
992
993 GdkImage *mask_image = (GdkImage*) NULL;
994
995 if (HasMask())
996 {
997 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
998
999 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1000
1001 wxMask *mask = new wxMask();
1002 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1003
1004 bitmap.SetMask( mask );
1005 }
1006
1007 // Render
1008
1009 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1010 byte_order b_o = RGB;
1011
1012 if (bpp >= 24)
1013 {
1014 GdkVisual *visual = gdk_visual_get_system();
1015 if ((visual->red_mask > visual->green_mask) && (visual->green_mask > visual->blue_mask)) b_o = RGB;
1016 else if ((visual->red_mask > visual->blue_mask) && (visual->blue_mask > visual->green_mask)) b_o = RGB;
1017 else if ((visual->blue_mask > visual->red_mask) && (visual->red_mask > visual->green_mask)) b_o = BRG;
1018 else if ((visual->blue_mask > visual->green_mask) && (visual->green_mask > visual->red_mask)) b_o = BGR;
1019 else if ((visual->green_mask > visual->red_mask) && (visual->red_mask > visual->blue_mask)) b_o = GRB;
1020 else if ((visual->green_mask > visual->blue_mask) && (visual->blue_mask > visual->red_mask)) b_o = GBR;
1021 }
1022
1023 int r_mask = GetMaskRed();
1024 int g_mask = GetMaskGreen();
1025 int b_mask = GetMaskBlue();
1026
1027 unsigned char* data = GetData();
1028
1029 int index = 0;
1030 for (int y = 0; y < height; y++)
1031 {
1032 for (int x = 0; x < width; x++)
1033 {
1034 int r = data[index];
1035 index++;
1036 int g = data[index];
1037 index++;
1038 int b = data[index];
1039 index++;
1040
1041 if (HasMask())
1042 {
1043 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1044 gdk_image_put_pixel( mask_image, x, y, 1 );
1045 else
1046 gdk_image_put_pixel( mask_image, x, y, 0 );
1047 }
1048
1049 if (HasMask())
1050 {
1051 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1052 gdk_image_put_pixel( mask_image, x, y, 1 );
1053 else
1054 gdk_image_put_pixel( mask_image, x, y, 0 );
1055 }
1056
1057 switch (bpp)
1058 {
1059 case 8:
1060 {
1061 int pixel = -1;
1062 if (wxTheApp->m_colorCube)
1063 {
1064 pixel = wxTheApp->m_colorCube[ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1065 }
1066 else
1067 {
1068 GdkColormap *cmap = gtk_widget_get_default_colormap();
1069 GdkColor *colors = cmap->colors;
1070 int max = 3 * (65536);
1071
1072 for (int i = 0; i < cmap->size; i++)
1073 {
1074 int rdiff = (r << 8) - colors[i].red;
1075 int gdiff = (g << 8) - colors[i].green;
1076 int bdiff = (b << 8) - colors[i].blue;
1077 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1078 if (sum < max) { pixel = i; max = sum; }
1079 }
1080 }
1081
1082 gdk_image_put_pixel( data_image, x, y, pixel );
1083
1084 break;
1085 }
1086 case 15:
1087 {
1088 guint32 pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1089 gdk_image_put_pixel( data_image, x, y, pixel );
1090 break;
1091 }
1092 case 16:
1093 {
1094 guint32 pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1095 gdk_image_put_pixel( data_image, x, y, pixel );
1096 break;
1097 }
1098 case 32:
1099 case 24:
1100 {
1101 guint32 pixel = 0;
1102 switch (b_o)
1103 {
1104 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1105 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1106 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1107 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1108 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1109 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1110 }
1111 gdk_image_put_pixel( data_image, x, y, pixel );
1112 }
1113 default: break;
1114 }
1115 } // for
1116 } // for
1117
1118 // Blit picture
1119
1120 GdkGC *data_gc = gdk_gc_new( bitmap.GetPixmap() );
1121
1122 gdk_draw_image( bitmap.GetPixmap(), data_gc, data_image, 0, 0, 0, 0, width, height );
1123
1124 gdk_image_destroy( data_image );
1125 gdk_gc_unref( data_gc );
1126
1127 // Blit mask
1128
1129 if (HasMask())
1130 {
1131 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
1132
1133 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
1134
1135 gdk_image_destroy( mask_image );
1136 gdk_gc_unref( mask_gc );
1137 }
1138
1139 return bitmap;
1140 }
1141
1142 wxImage::wxImage( const wxBitmap &bitmap )
1143 {
1144 wxCHECK_RET( bitmap.Ok(), _T("invalid bitmap") );
1145
1146 GdkImage *gdk_image = gdk_image_get( bitmap.GetPixmap(),
1147 0, 0,
1148 bitmap.GetWidth(), bitmap.GetHeight() );
1149
1150 wxCHECK_RET( gdk_image, _T("couldn't create image") );
1151
1152 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1153 char unsigned *data = GetData();
1154
1155 if (!data)
1156 {
1157 gdk_image_destroy( gdk_image );
1158 wxFAIL_MSG( _T("couldn't create image") );
1159 return;
1160 }
1161
1162 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1163 if (bitmap.GetMask())
1164 {
1165 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1166 0, 0,
1167 bitmap.GetWidth(), bitmap.GetHeight() );
1168
1169 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1170 }
1171
1172 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
1173 if (visual == NULL) visual = gdk_window_get_visual( (GdkWindow*) &gdk_root_parent );
1174 int bpp = visual->depth;
1175 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
1176
1177 GdkColormap *cmap = gtk_widget_get_default_colormap();
1178
1179 long pos = 0;
1180 for (int j = 0; j < bitmap.GetHeight(); j++)
1181 {
1182 for (int i = 0; i < bitmap.GetWidth(); i++)
1183 {
1184 wxInt32 pixel = gdk_image_get_pixel( gdk_image, i, j );
1185 pixel = wxINT32_SWAP_ON_BE( pixel );
1186 if (bpp <= 8)
1187 {
1188 data[pos] = cmap->colors[pixel].red >> 8;
1189 data[pos+1] = cmap->colors[pixel].green >> 8;
1190 data[pos+2] = cmap->colors[pixel].blue >> 8;
1191 } else if (bpp == 15)
1192 {
1193 data[pos] = (pixel >> 7) & 0xf8;
1194 data[pos+1] = (pixel >> 2) & 0xf8;
1195 data[pos+2] = (pixel << 3) & 0xf8;
1196 } else if (bpp == 16)
1197 {
1198 data[pos] = (pixel >> 8) & 0xf8;
1199 data[pos+1] = (pixel >> 3) & 0xfc;
1200 data[pos+2] = (pixel << 3) & 0xf8;
1201 } else
1202 {
1203 data[pos] = (pixel >> 16) & 0xff;
1204 data[pos+1] = (pixel >> 8) & 0xff;
1205 data[pos+2] = pixel & 0xff;
1206 }
1207
1208 if (gdk_image_mask)
1209 {
1210 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1211 if (mask_pixel == 0)
1212 {
1213 data[pos] = 16;
1214 data[pos+1] = 16;
1215 data[pos+2] = 16;
1216 }
1217 }
1218
1219 pos += 3;
1220 }
1221 }
1222
1223 gdk_image_destroy( gdk_image );
1224 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1225 }
1226
1227 #endif
1228
1229 //-----------------------------------------------------------------------------
1230 // Motif conversion routines
1231 //-----------------------------------------------------------------------------
1232
1233 #ifdef __WXMOTIF__
1234
1235 #include <Xm/Xm.h>
1236 #include "wx/utils.h"
1237 #include <math.h>
1238
1239 wxBitmap wxImage::ConvertToBitmap() const
1240 {
1241 wxBitmap bitmap;
1242
1243 wxCHECK_MSG( Ok(), bitmap, _T("invalid image") );
1244
1245 int width = GetWidth();
1246 int height = GetHeight();
1247
1248 bitmap.SetHeight( height );
1249 bitmap.SetWidth( width );
1250
1251 Display *dpy = (Display*) wxGetDisplay();
1252 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1253 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1254
1255 // Create image
1256
1257 XImage *data_image = XCreateImage( dpy, vis, bpp, ZPixmap, 0, 0, width, height, 32, 0 );
1258 data_image->data = (char*) malloc( data_image->bytes_per_line * data_image->height );
1259
1260 bitmap.Create( width, height, bpp );
1261
1262 /*
1263 // Create mask
1264
1265 GdkImage *mask_image = (GdkImage*) NULL;
1266
1267 if (HasMask())
1268 {
1269 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1270
1271 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1272
1273 wxMask *mask = new wxMask();
1274 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1275
1276 bitmap.SetMask( mask );
1277 }
1278 */
1279
1280 // Retrieve depth info
1281
1282 XVisualInfo vinfo_template;
1283 XVisualInfo *vi;
1284
1285 vinfo_template.visual = vis;
1286 vinfo_template.visualid = XVisualIDFromVisual( vis );
1287 vinfo_template.depth = bpp;
1288 int nitem = 0;
1289
1290 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1291
1292 wxCHECK_MSG( vi, wxNullBitmap, _T("no visual") );
1293
1294 XFree( vi );
1295
1296 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1297 if (bpp < 8) bpp = 8;
1298
1299 // Render
1300
1301 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1302 byte_order b_o = RGB;
1303
1304 if (bpp >= 24)
1305 {
1306 if ((vi->red_mask > vi->green_mask) && (vi->green_mask > vi->blue_mask)) b_o = RGB;
1307 else if ((vi->red_mask > vi->blue_mask) && (vi->blue_mask > vi->green_mask)) b_o = RGB;
1308 else if ((vi->blue_mask > vi->red_mask) && (vi->red_mask > vi->green_mask)) b_o = BRG;
1309 else if ((vi->blue_mask > vi->green_mask) && (vi->green_mask > vi->red_mask)) b_o = BGR;
1310 else if ((vi->green_mask > vi->red_mask) && (vi->red_mask > vi->blue_mask)) b_o = GRB;
1311 else if ((vi->green_mask > vi->blue_mask) && (vi->blue_mask > vi->red_mask)) b_o = GBR;
1312 }
1313
1314 /*
1315 int r_mask = GetMaskRed();
1316 int g_mask = GetMaskGreen();
1317 int b_mask = GetMaskBlue();
1318 */
1319
1320 XColor colors[256];
1321 if (bpp == 8)
1322 {
1323 Colormap cmap = (Colormap) wxTheApp->GetMainColormap( dpy );
1324
1325 for (int i = 0; i < 256; i++) colors[i].pixel = i;
1326 XQueryColors( dpy, cmap, colors, 256 );
1327 }
1328
1329 unsigned char* data = GetData();
1330
1331 int index = 0;
1332 for (int y = 0; y < height; y++)
1333 {
1334 for (int x = 0; x < width; x++)
1335 {
1336 int r = data[index];
1337 index++;
1338 int g = data[index];
1339 index++;
1340 int b = data[index];
1341 index++;
1342
1343 /*
1344 if (HasMask())
1345 {
1346 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1347 gdk_image_put_pixel( mask_image, x, y, 1 );
1348 else
1349 gdk_image_put_pixel( mask_image, x, y, 0 );
1350 }
1351 */
1352
1353 switch (bpp)
1354 {
1355 case 8:
1356 {
1357 int pixel = -1;
1358 /*
1359 if (wxTheApp->m_colorCube)
1360 {
1361 pixel = wxTheApp->m_colorCube
1362 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1363 }
1364 else
1365 {
1366 */
1367 int max = 3 * (65536);
1368 for (int i = 0; i < 256; i++)
1369 {
1370 int rdiff = (r << 8) - colors[i].red;
1371 int gdiff = (g << 8) - colors[i].green;
1372 int bdiff = (b << 8) - colors[i].blue;
1373 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1374 if (sum < max) { pixel = i; max = sum; }
1375 }
1376 /*
1377 }
1378 */
1379 XPutPixel( data_image, x, y, pixel );
1380 break;
1381 }
1382 case 15:
1383 {
1384 int pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1385 XPutPixel( data_image, x, y, pixel );
1386 break;
1387 }
1388 case 16:
1389 {
1390 int pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1391 XPutPixel( data_image, x, y, pixel );
1392 break;
1393 }
1394 case 32:
1395 case 24:
1396 {
1397 int pixel = 0;
1398 switch (b_o)
1399 {
1400 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1401 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1402 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1403 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1404 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1405 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1406 }
1407 XPutPixel( data_image, x, y, pixel );
1408 }
1409 default: break;
1410 }
1411 } // for
1412 } // for
1413
1414 // Blit picture
1415
1416 XGCValues gcvalues;
1417 gcvalues.foreground = BlackPixel( dpy, DefaultScreen( dpy ) );
1418 GC gc = XCreateGC( dpy, RootWindow ( dpy, DefaultScreen(dpy) ), GCForeground, &gcvalues );
1419 XPutImage( dpy, (Drawable)bitmap.GetPixmap(), gc, data_image, 0, 0, 0, 0, width, height );
1420
1421 XDestroyImage( data_image );
1422 XFreeGC( dpy, gc );
1423
1424 /*
1425 // Blit mask
1426
1427 if (HasMask())
1428 {
1429 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
1430
1431 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
1432
1433 gdk_image_destroy( mask_image );
1434 gdk_gc_unref( mask_gc );
1435 }
1436 */
1437
1438 return bitmap;
1439 }
1440
1441 wxImage::wxImage( const wxBitmap &bitmap )
1442 {
1443 wxCHECK_RET( bitmap.Ok(), _T("invalid bitmap") );
1444
1445 Display *dpy = (Display*) wxGetDisplay();
1446 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1447 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1448
1449 XImage *ximage = XGetImage( dpy,
1450 (Drawable)bitmap.GetPixmap(),
1451 0, 0,
1452 bitmap.GetWidth(), bitmap.GetHeight(),
1453 AllPlanes, ZPixmap );
1454
1455 wxCHECK_RET( ximage, _T("couldn't create image") );
1456
1457 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1458 char unsigned *data = GetData();
1459
1460 if (!data)
1461 {
1462 XDestroyImage( ximage );
1463 wxFAIL_MSG( _T("couldn't create image") );
1464 return;
1465 }
1466
1467 /*
1468 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1469 if (bitmap.GetMask())
1470 {
1471 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1472 0, 0,
1473 bitmap.GetWidth(), bitmap.GetHeight() );
1474
1475 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1476 }
1477 */
1478
1479 // Retrieve depth info
1480
1481 XVisualInfo vinfo_template;
1482 XVisualInfo *vi;
1483
1484 vinfo_template.visual = vis;
1485 vinfo_template.visualid = XVisualIDFromVisual( vis );
1486 vinfo_template.depth = bpp;
1487 int nitem = 0;
1488
1489 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1490
1491 wxCHECK_RET( vi, _T("no visual") );
1492
1493 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1494
1495 XFree( vi );
1496
1497 XColor colors[256];
1498 if (bpp == 8)
1499 {
1500 Colormap cmap = (Colormap)wxTheApp->GetMainColormap( dpy );
1501
1502 for (int i = 0; i < 256; i++) colors[i].pixel = i;
1503 XQueryColors( dpy, cmap, colors, 256 );
1504 }
1505
1506 long pos = 0;
1507 for (int j = 0; j < bitmap.GetHeight(); j++)
1508 {
1509 for (int i = 0; i < bitmap.GetWidth(); i++)
1510 {
1511 int pixel = XGetPixel( ximage, i, j );
1512 if (bpp <= 8)
1513 {
1514 data[pos] = colors[pixel].red >> 8;
1515 data[pos+1] = colors[pixel].green >> 8;
1516 data[pos+2] = colors[pixel].blue >> 8;
1517 } else if (bpp == 15)
1518 {
1519 data[pos] = (pixel >> 7) & 0xf8;
1520 data[pos+1] = (pixel >> 2) & 0xf8;
1521 data[pos+2] = (pixel << 3) & 0xf8;
1522 } else if (bpp == 16)
1523 {
1524 data[pos] = (pixel >> 8) & 0xf8;
1525 data[pos+1] = (pixel >> 3) & 0xfc;
1526 data[pos+2] = (pixel << 3) & 0xf8;
1527 } else
1528 {
1529 data[pos] = (pixel >> 16) & 0xff;
1530 data[pos+1] = (pixel >> 8) & 0xff;
1531 data[pos+2] = pixel & 0xff;
1532 }
1533
1534 /*
1535 if (gdk_image_mask)
1536 {
1537 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1538 if (mask_pixel == 0)
1539 {
1540 data[pos] = 16;
1541 data[pos+1] = 16;
1542 data[pos+2] = 16;
1543 }
1544 }
1545 */
1546
1547 pos += 3;
1548 }
1549 }
1550
1551 XDestroyImage( ximage );
1552 /*
1553 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1554 */
1555 }
1556 #endif
1557
1558 // A module to allow wxImage initialization/cleanup
1559 // without calling these functions from app.cpp or from
1560 // the user's application.
1561
1562 class wxImageModule: public wxModule
1563 {
1564 DECLARE_DYNAMIC_CLASS(wxImageModule)
1565 public:
1566 wxImageModule() {}
1567 bool OnInit() { wxImage::InitStandardHandlers(); return TRUE; };
1568 void OnExit() { wxImage::CleanUpHandlers(); };
1569 };
1570
1571 IMPLEMENT_DYNAMIC_CLASS(wxImageModule, wxModule)