]> git.saurik.com Git - wxWidgets.git/blob - src/common/image.cpp
Added a few #if wxUSE_XXX
[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 #ifdef FAR
36 #undef FAR
37 #endif
38 #endif
39
40 #ifdef __WXMSW__
41 #include <windows.h>
42 #endif
43
44 //-----------------------------------------------------------------------------
45 // wxImage
46 //-----------------------------------------------------------------------------
47
48 class wxImageRefData: public wxObjectRefData
49 {
50
51 public:
52 wxImageRefData(void);
53 ~wxImageRefData(void);
54
55 int m_width;
56 int m_height;
57 unsigned char *m_data;
58 bool m_hasMask;
59 unsigned char m_maskRed,m_maskGreen,m_maskBlue;
60 bool m_ok;
61 };
62
63 wxImageRefData::wxImageRefData(void)
64 {
65 m_width = 0;
66 m_height = 0;
67 m_data = (unsigned char*) NULL;
68 m_ok = FALSE;
69 m_maskRed = 0;
70 m_maskGreen = 0;
71 m_maskBlue = 0;
72 m_hasMask = FALSE;
73 }
74
75 wxImageRefData::~wxImageRefData(void)
76 {
77 if (m_data) free( m_data );
78 }
79
80 wxList wxImage::sm_handlers;
81
82 //-----------------------------------------------------------------------------
83
84 #define M_IMGDATA ((wxImageRefData *)m_refData)
85
86 #if !USE_SHARED_LIBRARIES
87 IMPLEMENT_DYNAMIC_CLASS(wxImage, wxObject)
88 #endif
89
90 wxImage::wxImage()
91 {
92 }
93
94 wxImage::wxImage( int width, int height )
95 {
96 Create( width, height );
97 }
98
99 wxImage::wxImage( const wxString& name, long type )
100 {
101 LoadFile( name, type );
102 }
103
104 wxImage::wxImage( const wxString& name, const wxString& mimetype )
105 {
106 LoadFile( name, mimetype );
107 }
108
109 #if wxUSE_STREAMS
110 wxImage::wxImage( wxInputStream& stream, long type )
111 {
112 LoadFile( stream, type );
113 }
114
115 wxImage::wxImage( wxInputStream& stream, const wxString& mimetype )
116 {
117 LoadFile( stream, mimetype );
118 }
119 #endif // wxUSE_STREAMS
120
121 wxImage::wxImage( const wxImage& image )
122 {
123 Ref(image);
124 }
125
126 wxImage::wxImage( const wxImage* image )
127 {
128 if (image) Ref(*image);
129 }
130
131 void wxImage::Create( int width, int height )
132 {
133 m_refData = new wxImageRefData();
134
135 M_IMGDATA->m_data = (unsigned char *) malloc( width*height*3 );
136 if (M_IMGDATA->m_data)
137 {
138 for (int l = 0; l < width*height*3; l++) M_IMGDATA->m_data[l] = 0;
139
140 M_IMGDATA->m_width = width;
141 M_IMGDATA->m_height = height;
142 M_IMGDATA->m_ok = TRUE;
143 }
144 else
145 {
146 UnRef();
147 }
148 }
149
150 void wxImage::Destroy()
151 {
152 UnRef();
153 }
154
155 wxImage wxImage::Scale( int width, int height )
156 {
157 wxImage image;
158
159 wxCHECK_MSG( Ok(), image, _T("invalid image") );
160
161 wxCHECK_MSG( (width > 0) && (height > 0), image, _T("invalid image size") );
162
163 image.Create( width, height );
164
165 char unsigned *data = image.GetData();
166
167 wxCHECK_MSG( data, image, _T("unable to create image") );
168
169 if (M_IMGDATA->m_hasMask)
170 image.SetMaskColour( M_IMGDATA->m_maskRed, M_IMGDATA->m_maskGreen, M_IMGDATA->m_maskBlue );
171
172 long old_height = M_IMGDATA->m_height;
173 long old_width = M_IMGDATA->m_width;
174
175 char unsigned *source_data = M_IMGDATA->m_data;
176 char unsigned *target_data = data;
177
178 for (long j = 0; j < height; j++)
179 {
180 long y_offset = (j * old_height / height) * old_width;
181
182 for (long i = 0; i < width; i++)
183 {
184 memcpy( target_data,
185 source_data + 3*(y_offset + ((i * old_width )/ width)),
186 3 );
187 target_data += 3;
188 }
189 }
190
191 return image;
192 }
193
194 void wxImage::SetRGB( int x, int y, unsigned char r, unsigned char g, unsigned char b )
195 {
196 wxCHECK_RET( Ok(), _T("invalid image") );
197
198 int w = M_IMGDATA->m_width;
199 int h = M_IMGDATA->m_height;
200
201 wxCHECK_RET( (x>=0) && (y>=0) && (x<w) && (y<h), _T("invalid image index") );
202
203 long pos = (y * w + x) * 3;
204
205 M_IMGDATA->m_data[ pos ] = r;
206 M_IMGDATA->m_data[ pos+1 ] = g;
207 M_IMGDATA->m_data[ pos+2 ] = b;
208 }
209
210 unsigned char wxImage::GetRed( int x, int y )
211 {
212 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
213
214 int w = M_IMGDATA->m_width;
215 int h = M_IMGDATA->m_height;
216
217 wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, _T("invalid image index") );
218
219 long pos = (y * w + x) * 3;
220
221 return M_IMGDATA->m_data[pos];
222 }
223
224 unsigned char wxImage::GetGreen( int x, int y )
225 {
226 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
227
228 int w = M_IMGDATA->m_width;
229 int h = M_IMGDATA->m_height;
230
231 wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, _T("invalid image index") );
232
233 long pos = (y * w + x) * 3;
234
235 return M_IMGDATA->m_data[pos+1];
236 }
237
238 unsigned char wxImage::GetBlue( int x, int y )
239 {
240 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
241
242 int w = M_IMGDATA->m_width;
243 int h = M_IMGDATA->m_height;
244
245 wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, _T("invalid image index") );
246
247 long pos = (y * w + x) * 3;
248
249 return M_IMGDATA->m_data[pos+2];
250 }
251
252 bool wxImage::Ok() const
253 {
254 return (M_IMGDATA && M_IMGDATA->m_ok);
255 }
256
257 char unsigned *wxImage::GetData() const
258 {
259 wxCHECK_MSG( Ok(), (char unsigned *)NULL, _T("invalid image") );
260
261 return M_IMGDATA->m_data;
262 }
263
264 void wxImage::SetData( char unsigned *data )
265 {
266 wxCHECK_RET( Ok(), _T("invalid image") );
267
268 memcpy(M_IMGDATA->m_data, data, M_IMGDATA->m_width * M_IMGDATA->m_height * 3);
269 }
270
271 void wxImage::SetMaskColour( unsigned char r, unsigned char g, unsigned char b )
272 {
273 wxCHECK_RET( Ok(), _T("invalid image") );
274
275 M_IMGDATA->m_maskRed = r;
276 M_IMGDATA->m_maskGreen = g;
277 M_IMGDATA->m_maskBlue = b;
278 M_IMGDATA->m_hasMask = TRUE;
279 }
280
281 unsigned char wxImage::GetMaskRed() const
282 {
283 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
284
285 return M_IMGDATA->m_maskRed;
286 }
287
288 unsigned char wxImage::GetMaskGreen() const
289 {
290 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
291
292 return M_IMGDATA->m_maskGreen;
293 }
294
295 unsigned char wxImage::GetMaskBlue() const
296 {
297 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
298
299 return M_IMGDATA->m_maskBlue;
300 }
301
302 void wxImage::SetMask( bool mask )
303 {
304 wxCHECK_RET( Ok(), _T("invalid image") );
305
306 M_IMGDATA->m_hasMask = mask;
307 }
308
309 bool wxImage::HasMask() const
310 {
311 wxCHECK_MSG( Ok(), FALSE, _T("invalid image") );
312
313 return M_IMGDATA->m_hasMask;
314 }
315
316 int wxImage::GetWidth() const
317 {
318 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
319
320 return M_IMGDATA->m_width;
321 }
322
323 int wxImage::GetHeight() const
324 {
325 wxCHECK_MSG( Ok(), 0, _T("invalid image") );
326
327 return M_IMGDATA->m_height;
328 }
329
330 bool wxImage::LoadFile( const wxString& filename, long type )
331 {
332 #if wxUSE_STREAMS
333 if (wxFileExists(filename))
334 {
335 wxFileInputStream stream(filename);
336 return LoadFile(stream, type);
337 }
338
339 else {
340 wxLogError( _T("Can't load image from file '%s': file does not exist."), filename.c_str() );
341
342 return FALSE;
343 }
344 #else // !wxUSE_STREAMS
345 return FALSE;
346 #endif // wxUSE_STREAMS
347 }
348
349 bool wxImage::LoadFile( const wxString& filename, const wxString& mimetype )
350 {
351 #if wxUSE_STREAMS
352 if (wxFileExists(filename))
353 {
354 wxFileInputStream stream(filename);
355 return LoadFile(stream, mimetype);
356 }
357
358 else {
359 wxLogError( _T("Can't load image from file '%s': file does not exist."), filename.c_str() );
360
361 return FALSE;
362 }
363 #else // !wxUSE_STREAMS
364 return FALSE;
365 #endif // wxUSE_STREAMS
366 }
367
368 bool wxImage::SaveFile( const wxString& filename, int type )
369 {
370 #if wxUSE_STREAMS
371 wxFileOutputStream stream(filename);
372
373 if ( stream.LastError() == wxStream_NOERROR )
374 return SaveFile(stream, type);
375 else
376 #endif // wxUSE_STREAMS
377 return FALSE;
378 }
379
380 bool wxImage::SaveFile( const wxString& filename, const wxString& mimetype )
381 {
382 #if wxUSE_STREAMS
383 wxFileOutputStream stream(filename);
384
385 if ( stream.LastError() == wxStream_NOERROR )
386 return SaveFile(stream, mimetype);
387 else
388 #endif // wxUSE_STREAMS
389 return FALSE;
390 }
391
392 #if wxUSE_STREAMS
393 bool wxImage::LoadFile( wxInputStream& stream, long type )
394 {
395 UnRef();
396
397 m_refData = new wxImageRefData;
398
399 wxImageHandler *handler = FindHandler(type);
400
401 if (handler == NULL)
402 {
403 wxLogWarning( _T("No image handler for type %d defined."), type );
404
405 return FALSE;
406 }
407
408 return handler->LoadFile( this, stream );
409 }
410
411 bool wxImage::LoadFile( wxInputStream& stream, const wxString& mimetype )
412 {
413 UnRef();
414
415 m_refData = new wxImageRefData;
416
417 wxImageHandler *handler = FindHandlerMime(mimetype);
418
419 if (handler == NULL)
420 {
421 wxLogWarning( _T("No image handler for type %s defined."), mimetype.GetData() );
422
423 return FALSE;
424 }
425
426 return handler->LoadFile( this, stream );
427 }
428
429 bool wxImage::SaveFile( wxOutputStream& stream, int type )
430 {
431 wxCHECK_MSG( Ok(), FALSE, _T("invalid image") );
432
433 wxImageHandler *handler = FindHandler(type);
434
435 if (handler == NULL)
436 {
437 wxLogWarning( _T("No image handler for type %d defined."), type );
438
439 return FALSE;
440 }
441
442 return handler->SaveFile( this, stream );
443 }
444
445 bool wxImage::SaveFile( wxOutputStream& stream, const wxString& mimetype )
446 {
447 wxCHECK_MSG( Ok(), FALSE, _T("invalid image") );
448
449 wxImageHandler *handler = FindHandlerMime(mimetype);
450
451 if (handler == NULL)
452 {
453 wxLogWarning( _T("No image handler for type %s defined."), mimetype.GetData() );
454
455 return FALSE;
456 }
457
458 return handler->SaveFile( this, stream );
459 }
460 #endif // wxUSE_STREAMS
461
462 void wxImage::AddHandler( wxImageHandler *handler )
463 {
464 // make sure that the memory will be freed at the program end
465 sm_handlers.DeleteContents(TRUE);
466
467 sm_handlers.Append( handler );
468 }
469
470 void wxImage::InsertHandler( wxImageHandler *handler )
471 {
472 // make sure that the memory will be freed at the program end
473 sm_handlers.DeleteContents(TRUE);
474
475 sm_handlers.Insert( handler );
476 }
477
478 bool wxImage::RemoveHandler( const wxString& name )
479 {
480 wxImageHandler *handler = FindHandler(name);
481 if (handler)
482 {
483 sm_handlers.DeleteObject(handler);
484 return TRUE;
485 }
486 else
487 return FALSE;
488 }
489
490 wxImageHandler *wxImage::FindHandler( const wxString& name )
491 {
492 wxNode *node = sm_handlers.First();
493 while (node)
494 {
495 wxImageHandler *handler = (wxImageHandler*)node->Data();
496 if (handler->GetName().Cmp(name) == 0) return handler;
497
498 node = node->Next();
499 }
500 return (wxImageHandler *)NULL;
501 }
502
503 wxImageHandler *wxImage::FindHandler( const wxString& extension, long bitmapType )
504 {
505 wxNode *node = sm_handlers.First();
506 while (node)
507 {
508 wxImageHandler *handler = (wxImageHandler*)node->Data();
509 if ( (handler->GetExtension().Cmp(extension) == 0) &&
510 (bitmapType == -1 || handler->GetType() == bitmapType) )
511 return handler;
512 node = node->Next();
513 }
514 return (wxImageHandler*)NULL;
515 }
516
517 wxImageHandler *wxImage::FindHandler( long bitmapType )
518 {
519 wxNode *node = sm_handlers.First();
520 while (node)
521 {
522 wxImageHandler *handler = (wxImageHandler *)node->Data();
523 if (handler->GetType() == bitmapType) return handler;
524 node = node->Next();
525 }
526 return NULL;
527 }
528
529 wxImageHandler *wxImage::FindHandlerMime( const wxString& mimetype )
530 {
531 wxNode *node = sm_handlers.First();
532 while (node)
533 {
534 wxImageHandler *handler = (wxImageHandler *)node->Data();
535 if (handler->GetMimeType().IsSameAs(mimetype, FALSE)) return handler;
536 node = node->Next();
537 }
538 return NULL;
539 }
540
541 void wxImage::InitStandardHandlers()
542 {
543 AddHandler( new wxBMPHandler );
544 }
545
546 void wxImage::CleanUpHandlers()
547 {
548 wxNode *node = sm_handlers.First();
549 while (node)
550 {
551 wxImageHandler *handler = (wxImageHandler *)node->Data();
552 wxNode *next = node->Next();
553 delete handler;
554 delete node;
555 node = next;
556 }
557 }
558
559 //-----------------------------------------------------------------------------
560 // wxImageHandler
561 //-----------------------------------------------------------------------------
562
563 #if !USE_SHARED_LIBRARIES
564 IMPLEMENT_DYNAMIC_CLASS(wxImageHandler,wxObject)
565 #endif
566
567 #if wxUSE_STREAMS
568 bool wxImageHandler::LoadFile( wxImage *WXUNUSED(image), wxInputStream& WXUNUSED(stream) )
569 {
570 return FALSE;
571 }
572
573 bool wxImageHandler::SaveFile( wxImage *WXUNUSED(image), wxOutputStream& WXUNUSED(stream) )
574 {
575 return FALSE;
576 }
577 #endif // wxUSE_STREAMS
578
579 //-----------------------------------------------------------------------------
580 // MSW conversion routines
581 //-----------------------------------------------------------------------------
582
583 #ifdef __WXMSW__
584
585 wxBitmap wxImage::ConvertToBitmap() const
586 {
587 // sizeLimit is the MS upper limit for the DIB size
588 int sizeLimit = 1024*768*3;
589
590 // width and height of the device-dependent bitmap
591 int width = GetWidth();
592 int bmpHeight = GetHeight();
593
594 // calc the number of bytes per scanline and padding
595 int bytePerLine = width*3;
596 int sizeDWORD = sizeof( DWORD );
597 div_t lineBoundary = div( bytePerLine, sizeDWORD );
598 int padding = 0;
599 if( lineBoundary.rem > 0 )
600 {
601 padding = sizeDWORD - lineBoundary.rem;
602 bytePerLine += padding;
603 }
604 // calc the number of DIBs and heights of DIBs
605 int numDIB = 1;
606 int hRemain = 0;
607 int height = sizeLimit/bytePerLine;
608 if( height >= bmpHeight )
609 height = bmpHeight;
610 else
611 {
612 div_t result = div( bmpHeight, height );
613 numDIB = result.quot;
614 hRemain = result.rem;
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 div_t lineBoundary = div( bytePerLine, sizeDWORD );
811 int padding = 0;
812 if( lineBoundary.rem > 0 )
813 {
814 padding = sizeDWORD - lineBoundary.rem;
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_window_get_visual( (GdkWindow*) &gdk_root_parent );
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 int pixel = gdk_image_get_pixel( gdk_image, i, j );
1185 if (bpp <= 8)
1186 {
1187 data[pos] = cmap->colors[pixel].red >> 8;
1188 data[pos+1] = cmap->colors[pixel].green >> 8;
1189 data[pos+2] = cmap->colors[pixel].blue >> 8;
1190 } else if (bpp == 15)
1191 {
1192 data[pos] = (pixel >> 7) & 0xf8;
1193 data[pos+1] = (pixel >> 2) & 0xf8;
1194 data[pos+2] = (pixel << 3) & 0xf8;
1195 } else if (bpp == 16)
1196 {
1197 data[pos] = (pixel >> 8) & 0xf8;
1198 data[pos+1] = (pixel >> 3) & 0xfc;
1199 data[pos+2] = (pixel << 3) & 0xf8;
1200 } else
1201 {
1202 data[pos] = (pixel >> 16) & 0xff;
1203 data[pos+1] = (pixel >> 8) & 0xff;
1204 data[pos+2] = pixel & 0xff;
1205 }
1206
1207 if (gdk_image_mask)
1208 {
1209 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1210 if (mask_pixel == 0)
1211 {
1212 data[pos] = 16;
1213 data[pos+1] = 16;
1214 data[pos+2] = 16;
1215 }
1216 }
1217
1218 pos += 3;
1219 }
1220 }
1221
1222 gdk_image_destroy( gdk_image );
1223 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1224 }
1225
1226 #endif
1227
1228 //-----------------------------------------------------------------------------
1229 // Motif conversion routines
1230 //-----------------------------------------------------------------------------
1231
1232 #ifdef __WXMOTIF__
1233
1234 #include <Xm/Xm.h>
1235 #include "wx/utils.h"
1236 #include <math.h>
1237
1238 wxBitmap wxImage::ConvertToBitmap() const
1239 {
1240 wxBitmap bitmap;
1241
1242 wxCHECK_MSG( Ok(), bitmap, _T("invalid image") );
1243
1244 int width = GetWidth();
1245 int height = GetHeight();
1246
1247 bitmap.SetHeight( height );
1248 bitmap.SetWidth( width );
1249
1250 Display *dpy = (Display*) wxGetDisplay();
1251 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1252 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1253
1254 // Create image
1255
1256 XImage *data_image = XCreateImage( dpy, vis, bpp, ZPixmap, 0, 0, width, height, 32, 0 );
1257 data_image->data = (char*) malloc( data_image->bytes_per_line * data_image->height );
1258
1259 bitmap.Create( width, height, bpp );
1260
1261 /*
1262 // Create mask
1263
1264 GdkImage *mask_image = (GdkImage*) NULL;
1265
1266 if (HasMask())
1267 {
1268 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1269
1270 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1271
1272 wxMask *mask = new wxMask();
1273 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1274
1275 bitmap.SetMask( mask );
1276 }
1277 */
1278
1279 // Retrieve depth info
1280
1281 XVisualInfo vinfo_template;
1282 XVisualInfo *vi;
1283
1284 vinfo_template.visual = vis;
1285 vinfo_template.visualid = XVisualIDFromVisual( vis );
1286 vinfo_template.depth = bpp;
1287 int nitem = 0;
1288
1289 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1290
1291 wxCHECK_MSG( vi, wxNullBitmap, _T("no visual") );
1292
1293 XFree( vi );
1294
1295 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1296 if (bpp < 8) bpp = 8;
1297
1298 // Render
1299
1300 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1301 byte_order b_o = RGB;
1302
1303 if (bpp >= 24)
1304 {
1305 if ((vi->red_mask > vi->green_mask) && (vi->green_mask > vi->blue_mask)) b_o = RGB;
1306 else if ((vi->red_mask > vi->blue_mask) && (vi->blue_mask > vi->green_mask)) b_o = RGB;
1307 else if ((vi->blue_mask > vi->red_mask) && (vi->red_mask > vi->green_mask)) b_o = BRG;
1308 else if ((vi->blue_mask > vi->green_mask) && (vi->green_mask > vi->red_mask)) b_o = BGR;
1309 else if ((vi->green_mask > vi->red_mask) && (vi->red_mask > vi->blue_mask)) b_o = GRB;
1310 else if ((vi->green_mask > vi->blue_mask) && (vi->blue_mask > vi->red_mask)) b_o = GBR;
1311 }
1312
1313 /*
1314 int r_mask = GetMaskRed();
1315 int g_mask = GetMaskGreen();
1316 int b_mask = GetMaskBlue();
1317 */
1318
1319 XColor colors[256];
1320 if (bpp == 8)
1321 {
1322 Colormap cmap = (Colormap) wxTheApp->GetMainColormap( dpy );
1323
1324 for (int i = 0; i < 256; i++) colors[i].pixel = i;
1325 XQueryColors( dpy, cmap, colors, 256 );
1326 }
1327
1328 unsigned char* data = GetData();
1329
1330 int index = 0;
1331 for (int y = 0; y < height; y++)
1332 {
1333 for (int x = 0; x < width; x++)
1334 {
1335 int r = data[index];
1336 index++;
1337 int g = data[index];
1338 index++;
1339 int b = data[index];
1340 index++;
1341
1342 /*
1343 if (HasMask())
1344 {
1345 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1346 gdk_image_put_pixel( mask_image, x, y, 1 );
1347 else
1348 gdk_image_put_pixel( mask_image, x, y, 0 );
1349 }
1350 */
1351
1352 switch (bpp)
1353 {
1354 case 8:
1355 {
1356 int pixel = -1;
1357 /*
1358 if (wxTheApp->m_colorCube)
1359 {
1360 pixel = wxTheApp->m_colorCube
1361 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1362 }
1363 else
1364 {
1365 */
1366 int max = 3 * (65536);
1367 for (int i = 0; i < 256; i++)
1368 {
1369 int rdiff = (r << 8) - colors[i].red;
1370 int gdiff = (g << 8) - colors[i].green;
1371 int bdiff = (b << 8) - colors[i].blue;
1372 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1373 if (sum < max) { pixel = i; max = sum; }
1374 }
1375 /*
1376 }
1377 */
1378 XPutPixel( data_image, x, y, pixel );
1379 break;
1380 }
1381 case 15:
1382 {
1383 int pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1384 XPutPixel( data_image, x, y, pixel );
1385 break;
1386 }
1387 case 16:
1388 {
1389 int pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1390 XPutPixel( data_image, x, y, pixel );
1391 break;
1392 }
1393 case 32:
1394 case 24:
1395 {
1396 int pixel = 0;
1397 switch (b_o)
1398 {
1399 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1400 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1401 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1402 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1403 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1404 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1405 }
1406 XPutPixel( data_image, x, y, pixel );
1407 }
1408 default: break;
1409 }
1410 } // for
1411 } // for
1412
1413 // Blit picture
1414
1415 XGCValues gcvalues;
1416 gcvalues.foreground = BlackPixel( dpy, DefaultScreen( dpy ) );
1417 GC gc = XCreateGC( dpy, RootWindow ( dpy, DefaultScreen(dpy) ), GCForeground, &gcvalues );
1418 XPutImage( dpy, (Drawable)bitmap.GetPixmap(), gc, data_image, 0, 0, 0, 0, width, height );
1419
1420 XDestroyImage( data_image );
1421 XFreeGC( dpy, gc );
1422
1423 /*
1424 // Blit mask
1425
1426 if (HasMask())
1427 {
1428 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
1429
1430 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
1431
1432 gdk_image_destroy( mask_image );
1433 gdk_gc_unref( mask_gc );
1434 }
1435 */
1436
1437 return bitmap;
1438 }
1439
1440 wxImage::wxImage( const wxBitmap &bitmap )
1441 {
1442 wxCHECK_RET( bitmap.Ok(), _T("invalid bitmap") );
1443
1444 Display *dpy = (Display*) wxGetDisplay();
1445 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1446 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1447
1448 XImage *ximage = XGetImage( dpy,
1449 (Drawable)bitmap.GetPixmap(),
1450 0, 0,
1451 bitmap.GetWidth(), bitmap.GetHeight(),
1452 AllPlanes, ZPixmap );
1453
1454 wxCHECK_RET( ximage, _T("couldn't create image") );
1455
1456 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1457 char unsigned *data = GetData();
1458
1459 if (!data)
1460 {
1461 XDestroyImage( ximage );
1462 wxFAIL_MSG( _T("couldn't create image") );
1463 return;
1464 }
1465
1466 /*
1467 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1468 if (bitmap.GetMask())
1469 {
1470 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1471 0, 0,
1472 bitmap.GetWidth(), bitmap.GetHeight() );
1473
1474 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1475 }
1476 */
1477
1478 // Retrieve depth info
1479
1480 XVisualInfo vinfo_template;
1481 XVisualInfo *vi;
1482
1483 vinfo_template.visual = vis;
1484 vinfo_template.visualid = XVisualIDFromVisual( vis );
1485 vinfo_template.depth = bpp;
1486 int nitem = 0;
1487
1488 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1489
1490 wxCHECK_MSG( vi, wxNullBitmap, _T("no visual") );
1491
1492 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1493
1494 XFree( vi );
1495
1496 XColor colors[256];
1497 if (bpp == 8)
1498 {
1499 Colormap cmap = (Colormap)wxTheApp->GetMainColormap( dpy );
1500
1501 for (int i = 0; i < 256; i++) colors[i].pixel = i;
1502 XQueryColors( dpy, cmap, colors, 256 );
1503 }
1504
1505 long pos = 0;
1506 for (int j = 0; j < bitmap.GetHeight(); j++)
1507 {
1508 for (int i = 0; i < bitmap.GetWidth(); i++)
1509 {
1510 int pixel = XGetPixel( ximage, i, j );
1511 if (bpp <= 8)
1512 {
1513 data[pos] = colors[pixel].red >> 8;
1514 data[pos+1] = colors[pixel].green >> 8;
1515 data[pos+2] = colors[pixel].blue >> 8;
1516 } else if (bpp == 15)
1517 {
1518 data[pos] = (pixel >> 7) & 0xf8;
1519 data[pos+1] = (pixel >> 2) & 0xf8;
1520 data[pos+2] = (pixel << 3) & 0xf8;
1521 } else if (bpp == 16)
1522 {
1523 data[pos] = (pixel >> 8) & 0xf8;
1524 data[pos+1] = (pixel >> 3) & 0xfc;
1525 data[pos+2] = (pixel << 3) & 0xf8;
1526 } else
1527 {
1528 data[pos] = (pixel >> 16) & 0xff;
1529 data[pos+1] = (pixel >> 8) & 0xff;
1530 data[pos+2] = pixel & 0xff;
1531 }
1532
1533 /*
1534 if (gdk_image_mask)
1535 {
1536 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1537 if (mask_pixel == 0)
1538 {
1539 data[pos] = 16;
1540 data[pos+1] = 16;
1541 data[pos+2] = 16;
1542 }
1543 }
1544 */
1545
1546 pos += 3;
1547 }
1548 }
1549
1550 XDestroyImage( ximage );
1551 /*
1552 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1553 */
1554 }
1555 #endif
1556
1557 // A module to allow wxImage initialization/cleanup
1558 // without calling these functions from app.cpp or from
1559 // the user's application.
1560
1561 class wxImageModule: public wxModule
1562 {
1563 DECLARE_DYNAMIC_CLASS(wxImageModule)
1564 public:
1565 wxImageModule() {}
1566 bool OnInit() { wxImage::InitStandardHandlers(); return TRUE; };
1567 void OnExit() { wxImage::CleanUpHandlers(); };
1568 };
1569
1570 IMPLEMENT_DYNAMIC_CLASS(wxImageModule, wxModule)