]> git.saurik.com Git - wxWidgets.git/blob - src/common/image.cpp
76afc83b77f2bb9b8b918501b831c955e4c97d05
[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 // sizeLimit is the MS upper limit for the DIB size
586 int sizeLimit = 1024*768*3;
587
588 // width and height of the device-dependent bitmap
589 int width = GetWidth();
590 int bmpHeight = GetHeight();
591
592 // calc the number of bytes per scanline and padding
593 int bytePerLine = width*3;
594 int sizeDWORD = sizeof( DWORD );
595 int lineBoundary = bytePerLine % sizeDWORD;
596 int padding = 0;
597 if( lineBoundary > 0 )
598 {
599 padding = sizeDWORD - lineBoundary;
600 bytePerLine += padding;
601 }
602 // calc the number of DIBs and heights of DIBs
603 int numDIB = 1;
604 int hRemain = 0;
605 int height = sizeLimit/bytePerLine;
606 if( height >= bmpHeight )
607 height = bmpHeight;
608 else
609 {
610 numDIB = bmpHeight / height;
611 hRemain = bmpHeight % height;
612 if( hRemain >0 ) numDIB++;
613 }
614
615 // set bitmap parameters
616 wxBitmap bitmap;
617 wxCHECK_MSG( Ok(), bitmap, _T("invalid image") );
618 bitmap.SetWidth( width );
619 bitmap.SetHeight( bmpHeight );
620 bitmap.SetDepth( wxDisplayDepth() );
621
622 // create a DIB header
623 int headersize = sizeof(BITMAPINFOHEADER);
624 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
625 wxCHECK_MSG( lpDIBh, bitmap, _T("could not allocate memory for DIB header") );
626 // Fill in the DIB header
627 lpDIBh->bmiHeader.biSize = headersize;
628 lpDIBh->bmiHeader.biWidth = (DWORD)width;
629 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
630 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
631 // the general formula for biSizeImage:
632 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
633 lpDIBh->bmiHeader.biPlanes = 1;
634 lpDIBh->bmiHeader.biBitCount = 24;
635 lpDIBh->bmiHeader.biCompression = BI_RGB;
636 lpDIBh->bmiHeader.biClrUsed = 0;
637 // These seem not really needed for our purpose here.
638 lpDIBh->bmiHeader.biClrImportant = 0;
639 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
640 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
641 // memory for DIB data
642 unsigned char *lpBits;
643 lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
644 if( !lpBits )
645 {
646 wxFAIL_MSG( _T("could not allocate memory for DIB") );
647 free( lpDIBh );
648 return bitmap;
649 }
650
651 // create and set the device-dependent bitmap
652 HDC hdc = ::GetDC(NULL);
653 HDC memdc = ::CreateCompatibleDC( hdc );
654 HBITMAP hbitmap;
655 hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
656 ::SelectObject( memdc, hbitmap);
657
658 // copy image data into DIB data and then into DDB (in a loop)
659 unsigned char *data = GetData();
660 int i, j, n;
661 int origin = 0;
662 unsigned char *ptdata = data;
663 unsigned char *ptbits;
664
665 for( n=0; n<numDIB; n++ )
666 {
667 if( numDIB > 1 && n == numDIB-1 && hRemain > 0 )
668 {
669 // redefine height and size of the (possibly) last smaller DIB
670 // memory is not reallocated
671 height = hRemain;
672 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
673 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
674 }
675 ptbits = lpBits;
676
677 for( j=0; j<height; j++ )
678 {
679 for( i=0; i<width; i++ )
680 {
681 *(ptbits++) = *(ptdata+2);
682 *(ptbits++) = *(ptdata+1);
683 *(ptbits++) = *(ptdata );
684 ptdata += 3;
685 }
686 for( i=0; i< padding; i++ ) *(ptbits++) = 0;
687 }
688 ::StretchDIBits( memdc, 0, origin, width, height,\
689 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
690 origin += height;
691 // if numDIB = 1, lines below can also be used
692 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
693 // The above line is equivalent to the following two lines.
694 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
695 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
696 // or the following lines
697 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
698 // HDC memdc = ::CreateCompatibleDC( hdc );
699 // ::SelectObject( memdc, hbitmap);
700 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
701 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
702 // ::SelectObject( memdc, 0 );
703 // ::DeleteDC( memdc );
704 }
705 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
706
707 // similarly, created an mono-bitmap for the possible mask
708 if( HasMask() )
709 {
710 hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL );
711 ::SelectObject( memdc, hbitmap);
712 if( numDIB == 1 ) height = bmpHeight;
713 else height = sizeLimit/bytePerLine;
714 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
715 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
716 origin = 0;
717 unsigned char r = GetMaskRed();
718 unsigned char g = GetMaskGreen();
719 unsigned char b = GetMaskBlue();
720 unsigned char zero = 0, one = 255;
721 ptdata = data;
722 for( n=0; n<numDIB; n++ )
723 {
724 if( numDIB > 1 && n == numDIB - 1 && hRemain > 0 )
725 {
726 // redefine height and size of the (possibly) last smaller DIB
727 // memory is not reallocated
728 height = hRemain;
729 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
730 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
731 }
732 ptbits = lpBits;
733 for( int j=0; j<height; j++ )
734 {
735 for(i=0; i<width; i++ )
736 {
737 if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
738 {
739 *(ptbits++) = one;
740 *(ptbits++) = one;
741 *(ptbits++) = one;
742 }
743 else
744 {
745 *(ptbits++) = zero;
746 *(ptbits++) = zero;
747 *(ptbits++) = zero;
748 }
749 }
750 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
751 }
752 ::StretchDIBits( memdc, 0, origin, width, height,\
753 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
754 origin += height;
755 }
756 // create a wxMask object
757 wxMask *mask = new wxMask();
758 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
759 bitmap.SetMask( mask );
760 // It will be deleted when the wxBitmap object is deleted (as of 01/1999)
761 /* The following can also be used but is slow to run
762 wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
763 wxMask *mask = new wxMask( bitmap, colour );
764 bitmap.SetMask( mask );
765 */
766 }
767
768 // free allocated resources
769 ::SelectObject( memdc, 0 );
770 ::DeleteDC( memdc );
771 ::ReleaseDC(NULL, hdc);
772 free(lpDIBh);
773 free(lpBits);
774
775 // check the wxBitmap object
776 if( bitmap.GetHBITMAP() )
777 bitmap.SetOk( TRUE );
778 else
779 bitmap.SetOk( FALSE );
780
781 return bitmap;
782 }
783
784 wxImage::wxImage( const wxBitmap &bitmap )
785 {
786 // check the bitmap
787 if( !bitmap.Ok() )
788 {
789 wxFAIL_MSG( _T("invalid bitmap") );
790 return;
791 }
792
793 // create an wxImage object
794 int width = bitmap.GetWidth();
795 int height = bitmap.GetHeight();
796 Create( width, height );
797 unsigned char *data = GetData();
798 if( !data )
799 {
800 wxFAIL_MSG( _T("could not allocate data for image") );
801 return;
802 }
803
804 // calc the number of bytes per scanline and padding in the DIB
805 int bytePerLine = width*3;
806 int sizeDWORD = sizeof( DWORD );
807 int lineBoundary = bytePerLine % sizeDWORD;
808 int padding = 0;
809 if( lineBoundary > 0 )
810 {
811 padding = sizeDWORD - lineBoundary;
812 bytePerLine += padding;
813 }
814
815 // create a DIB header
816 int headersize = sizeof(BITMAPINFOHEADER);
817 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
818 if( !lpDIBh )
819 {
820 wxFAIL_MSG( _T("could not allocate data for DIB header") );
821 free( data );
822 return;
823 }
824 // Fill in the DIB header
825 lpDIBh->bmiHeader.biSize = headersize;
826 lpDIBh->bmiHeader.biWidth = width;
827 lpDIBh->bmiHeader.biHeight = -height;
828 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
829 lpDIBh->bmiHeader.biPlanes = 1;
830 lpDIBh->bmiHeader.biBitCount = 24;
831 lpDIBh->bmiHeader.biCompression = BI_RGB;
832 lpDIBh->bmiHeader.biClrUsed = 0;
833 // These seem not really needed for our purpose here.
834 lpDIBh->bmiHeader.biClrImportant = 0;
835 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
836 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
837 // memory for DIB data
838 unsigned char *lpBits;
839 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
840 if( !lpBits )
841 {
842 wxFAIL_MSG( _T("could not allocate data for DIB") );
843 free( data );
844 free( lpDIBh );
845 return;
846 }
847
848 // copy data from the device-dependent bitmap to the DIB
849 HDC hdc = ::GetDC(NULL);
850 HBITMAP hbitmap;
851 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
852 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
853
854 // copy DIB data into the wxImage object
855 int i, j;
856 unsigned char *ptdata = data;
857 unsigned char *ptbits = lpBits;
858 for( i=0; i<height; i++ )
859 {
860 for( j=0; j<width; j++ )
861 {
862 *(ptdata++) = *(ptbits+2);
863 *(ptdata++) = *(ptbits+1);
864 *(ptdata++) = *(ptbits );
865 ptbits += 3;
866 }
867 ptbits += padding;
868 }
869
870 // similarly, set data according to the possible mask bitmap
871 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
872 {
873 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
874 // memory DC created, color set, data copied, and memory DC deleted
875 HDC memdc = ::CreateCompatibleDC( hdc );
876 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
877 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
878 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
879 ::DeleteDC( memdc );
880 // background color set to RGB(16,16,16) in consistent with wxGTK
881 unsigned char r=16, g=16, b=16;
882 ptdata = data;
883 ptbits = lpBits;
884 for( i=0; i<height; i++ )
885 {
886 for( j=0; j<width; j++ )
887 {
888 if( *ptbits != 0 )
889 ptdata += 3;
890 else
891 {
892 *(ptdata++) = r;
893 *(ptdata++) = g;
894 *(ptdata++) = b;
895 }
896 ptbits += 3;
897 }
898 ptbits += padding;
899 }
900 SetMaskColour( r, g, b );
901 SetMask( TRUE );
902 }
903 else
904 {
905 SetMask( FALSE );
906 }
907 // free allocated resources
908 ::ReleaseDC(NULL, hdc);
909 free(lpDIBh);
910 free(lpBits);
911 }
912
913 #endif
914
915 //-----------------------------------------------------------------------------
916 // GTK conversion routines
917 //-----------------------------------------------------------------------------
918
919 #ifdef __WXGTK__
920
921 #include "gtk/gtk.h"
922 #include "gdk/gdk.h"
923 #include "gdk/gdkx.h"
924
925 #if (GTK_MINOR_VERSION > 0)
926 #include "gdk/gdkrgb.h"
927 #endif
928
929 wxBitmap wxImage::ConvertToBitmap() const
930 {
931 wxBitmap bitmap;
932
933 wxCHECK_MSG( Ok(), bitmap, _T("invalid image") );
934
935 int width = GetWidth();
936 int height = GetHeight();
937
938 bitmap.SetHeight( height );
939 bitmap.SetWidth( width );
940
941 bitmap.SetPixmap( gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, -1 ) );
942
943 // Retrieve depth
944
945 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
946 if (visual == NULL) visual = gdk_visual_get_system();
947 int bpp = visual->depth;
948
949 bitmap.SetDepth( bpp );
950
951 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
952 if (bpp < 8) bpp = 8;
953
954 #if (GTK_MINOR_VERSION > 0)
955
956 if (!HasMask() && (bpp > 8))
957 {
958 static bool s_hasInitialized = FALSE;
959
960 if (!s_hasInitialized)
961 {
962 gdk_rgb_init();
963 s_hasInitialized = TRUE;
964 }
965
966 GdkGC *gc = gdk_gc_new( bitmap.GetPixmap() );
967
968 gdk_draw_rgb_image( bitmap.GetPixmap(),
969 gc,
970 0, 0,
971 width, height,
972 GDK_RGB_DITHER_NONE,
973 GetData(),
974 width*3 );
975
976 gdk_gc_unref( gc );
977
978 return bitmap;
979 }
980
981 #endif
982
983 // Create picture image
984
985 GdkImage *data_image =
986 gdk_image_new( GDK_IMAGE_FASTEST, gdk_visual_get_system(), width, height );
987
988 // Create mask image
989
990 GdkImage *mask_image = (GdkImage*) NULL;
991
992 if (HasMask())
993 {
994 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
995
996 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
997
998 wxMask *mask = new wxMask();
999 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1000
1001 bitmap.SetMask( mask );
1002 }
1003
1004 // Render
1005
1006 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1007 byte_order b_o = RGB;
1008
1009 if (bpp >= 24)
1010 {
1011 GdkVisual *visual = gdk_visual_get_system();
1012 if ((visual->red_mask > visual->green_mask) && (visual->green_mask > visual->blue_mask)) b_o = RGB;
1013 else if ((visual->red_mask > visual->blue_mask) && (visual->blue_mask > visual->green_mask)) b_o = RGB;
1014 else if ((visual->blue_mask > visual->red_mask) && (visual->red_mask > visual->green_mask)) b_o = BRG;
1015 else if ((visual->blue_mask > visual->green_mask) && (visual->green_mask > visual->red_mask)) b_o = BGR;
1016 else if ((visual->green_mask > visual->red_mask) && (visual->red_mask > visual->blue_mask)) b_o = GRB;
1017 else if ((visual->green_mask > visual->blue_mask) && (visual->blue_mask > visual->red_mask)) b_o = GBR;
1018 }
1019
1020 int r_mask = GetMaskRed();
1021 int g_mask = GetMaskGreen();
1022 int b_mask = GetMaskBlue();
1023
1024 unsigned char* data = GetData();
1025
1026 int index = 0;
1027 for (int y = 0; y < height; y++)
1028 {
1029 for (int x = 0; x < width; x++)
1030 {
1031 int r = data[index];
1032 index++;
1033 int g = data[index];
1034 index++;
1035 int b = data[index];
1036 index++;
1037
1038 if (HasMask())
1039 {
1040 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1041 gdk_image_put_pixel( mask_image, x, y, 1 );
1042 else
1043 gdk_image_put_pixel( mask_image, x, y, 0 );
1044 }
1045
1046 if (HasMask())
1047 {
1048 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1049 gdk_image_put_pixel( mask_image, x, y, 1 );
1050 else
1051 gdk_image_put_pixel( mask_image, x, y, 0 );
1052 }
1053
1054 switch (bpp)
1055 {
1056 case 8:
1057 {
1058 int pixel = -1;
1059 if (wxTheApp->m_colorCube)
1060 {
1061 pixel = wxTheApp->m_colorCube[ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1062 }
1063 else
1064 {
1065 GdkColormap *cmap = gtk_widget_get_default_colormap();
1066 GdkColor *colors = cmap->colors;
1067 int max = 3 * (65536);
1068
1069 for (int i = 0; i < cmap->size; i++)
1070 {
1071 int rdiff = (r << 8) - colors[i].red;
1072 int gdiff = (g << 8) - colors[i].green;
1073 int bdiff = (b << 8) - colors[i].blue;
1074 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1075 if (sum < max) { pixel = i; max = sum; }
1076 }
1077 }
1078
1079 gdk_image_put_pixel( data_image, x, y, pixel );
1080
1081 break;
1082 }
1083 case 15:
1084 {
1085 guint32 pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1086 gdk_image_put_pixel( data_image, x, y, pixel );
1087 break;
1088 }
1089 case 16:
1090 {
1091 guint32 pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1092 gdk_image_put_pixel( data_image, x, y, pixel );
1093 break;
1094 }
1095 case 32:
1096 case 24:
1097 {
1098 guint32 pixel = 0;
1099 switch (b_o)
1100 {
1101 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1102 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1103 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1104 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1105 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1106 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1107 }
1108 gdk_image_put_pixel( data_image, x, y, pixel );
1109 }
1110 default: break;
1111 }
1112 } // for
1113 } // for
1114
1115 // Blit picture
1116
1117 GdkGC *data_gc = gdk_gc_new( bitmap.GetPixmap() );
1118
1119 gdk_draw_image( bitmap.GetPixmap(), data_gc, data_image, 0, 0, 0, 0, width, height );
1120
1121 gdk_image_destroy( data_image );
1122 gdk_gc_unref( data_gc );
1123
1124 // Blit mask
1125
1126 if (HasMask())
1127 {
1128 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
1129
1130 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
1131
1132 gdk_image_destroy( mask_image );
1133 gdk_gc_unref( mask_gc );
1134 }
1135
1136 return bitmap;
1137 }
1138
1139 wxImage::wxImage( const wxBitmap &bitmap )
1140 {
1141 wxCHECK_RET( bitmap.Ok(), _T("invalid bitmap") );
1142
1143 GdkImage *gdk_image = gdk_image_get( bitmap.GetPixmap(),
1144 0, 0,
1145 bitmap.GetWidth(), bitmap.GetHeight() );
1146
1147 wxCHECK_RET( gdk_image, _T("couldn't create image") );
1148
1149 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1150 char unsigned *data = GetData();
1151
1152 if (!data)
1153 {
1154 gdk_image_destroy( gdk_image );
1155 wxFAIL_MSG( _T("couldn't create image") );
1156 return;
1157 }
1158
1159 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1160 if (bitmap.GetMask())
1161 {
1162 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1163 0, 0,
1164 bitmap.GetWidth(), bitmap.GetHeight() );
1165
1166 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1167 }
1168
1169 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
1170 if (visual == NULL) visual = gdk_window_get_visual( (GdkWindow*) &gdk_root_parent );
1171 int bpp = visual->depth;
1172 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
1173
1174 GdkColormap *cmap = gtk_widget_get_default_colormap();
1175
1176 long pos = 0;
1177 for (int j = 0; j < bitmap.GetHeight(); j++)
1178 {
1179 for (int i = 0; i < bitmap.GetWidth(); i++)
1180 {
1181 int pixel = gdk_image_get_pixel( gdk_image, i, j );
1182 if (bpp <= 8)
1183 {
1184 data[pos] = cmap->colors[pixel].red >> 8;
1185 data[pos+1] = cmap->colors[pixel].green >> 8;
1186 data[pos+2] = cmap->colors[pixel].blue >> 8;
1187 } else if (bpp == 15)
1188 {
1189 data[pos] = (pixel >> 7) & 0xf8;
1190 data[pos+1] = (pixel >> 2) & 0xf8;
1191 data[pos+2] = (pixel << 3) & 0xf8;
1192 } else if (bpp == 16)
1193 {
1194 data[pos] = (pixel >> 8) & 0xf8;
1195 data[pos+1] = (pixel >> 3) & 0xfc;
1196 data[pos+2] = (pixel << 3) & 0xf8;
1197 } else
1198 {
1199 data[pos] = (pixel >> 16) & 0xff;
1200 data[pos+1] = (pixel >> 8) & 0xff;
1201 data[pos+2] = pixel & 0xff;
1202 }
1203
1204 if (gdk_image_mask)
1205 {
1206 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1207 if (mask_pixel == 0)
1208 {
1209 data[pos] = 16;
1210 data[pos+1] = 16;
1211 data[pos+2] = 16;
1212 }
1213 }
1214
1215 pos += 3;
1216 }
1217 }
1218
1219 gdk_image_destroy( gdk_image );
1220 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1221 }
1222
1223 #endif
1224
1225 //-----------------------------------------------------------------------------
1226 // Motif conversion routines
1227 //-----------------------------------------------------------------------------
1228
1229 #ifdef __WXMOTIF__
1230
1231 #include <Xm/Xm.h>
1232 #include "wx/utils.h"
1233 #include <math.h>
1234
1235 wxBitmap wxImage::ConvertToBitmap() const
1236 {
1237 wxBitmap bitmap;
1238
1239 wxCHECK_MSG( Ok(), bitmap, _T("invalid image") );
1240
1241 int width = GetWidth();
1242 int height = GetHeight();
1243
1244 bitmap.SetHeight( height );
1245 bitmap.SetWidth( width );
1246
1247 Display *dpy = (Display*) wxGetDisplay();
1248 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1249 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1250
1251 // Create image
1252
1253 XImage *data_image = XCreateImage( dpy, vis, bpp, ZPixmap, 0, 0, width, height, 32, 0 );
1254 data_image->data = (char*) malloc( data_image->bytes_per_line * data_image->height );
1255
1256 bitmap.Create( width, height, bpp );
1257
1258 /*
1259 // Create mask
1260
1261 GdkImage *mask_image = (GdkImage*) NULL;
1262
1263 if (HasMask())
1264 {
1265 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1266
1267 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1268
1269 wxMask *mask = new wxMask();
1270 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1271
1272 bitmap.SetMask( mask );
1273 }
1274 */
1275
1276 // Retrieve depth info
1277
1278 XVisualInfo vinfo_template;
1279 XVisualInfo *vi;
1280
1281 vinfo_template.visual = vis;
1282 vinfo_template.visualid = XVisualIDFromVisual( vis );
1283 vinfo_template.depth = bpp;
1284 int nitem = 0;
1285
1286 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1287
1288 wxCHECK_MSG( vi, wxNullBitmap, _T("no visual") );
1289
1290 XFree( vi );
1291
1292 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1293 if (bpp < 8) bpp = 8;
1294
1295 // Render
1296
1297 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1298 byte_order b_o = RGB;
1299
1300 if (bpp >= 24)
1301 {
1302 if ((vi->red_mask > vi->green_mask) && (vi->green_mask > vi->blue_mask)) b_o = RGB;
1303 else if ((vi->red_mask > vi->blue_mask) && (vi->blue_mask > vi->green_mask)) b_o = RGB;
1304 else if ((vi->blue_mask > vi->red_mask) && (vi->red_mask > vi->green_mask)) b_o = BRG;
1305 else if ((vi->blue_mask > vi->green_mask) && (vi->green_mask > vi->red_mask)) b_o = BGR;
1306 else if ((vi->green_mask > vi->red_mask) && (vi->red_mask > vi->blue_mask)) b_o = GRB;
1307 else if ((vi->green_mask > vi->blue_mask) && (vi->blue_mask > vi->red_mask)) b_o = GBR;
1308 }
1309
1310 /*
1311 int r_mask = GetMaskRed();
1312 int g_mask = GetMaskGreen();
1313 int b_mask = GetMaskBlue();
1314 */
1315
1316 XColor colors[256];
1317 if (bpp == 8)
1318 {
1319 Colormap cmap = (Colormap) wxTheApp->GetMainColormap( dpy );
1320
1321 for (int i = 0; i < 256; i++) colors[i].pixel = i;
1322 XQueryColors( dpy, cmap, colors, 256 );
1323 }
1324
1325 unsigned char* data = GetData();
1326
1327 int index = 0;
1328 for (int y = 0; y < height; y++)
1329 {
1330 for (int x = 0; x < width; x++)
1331 {
1332 int r = data[index];
1333 index++;
1334 int g = data[index];
1335 index++;
1336 int b = data[index];
1337 index++;
1338
1339 /*
1340 if (HasMask())
1341 {
1342 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1343 gdk_image_put_pixel( mask_image, x, y, 1 );
1344 else
1345 gdk_image_put_pixel( mask_image, x, y, 0 );
1346 }
1347 */
1348
1349 switch (bpp)
1350 {
1351 case 8:
1352 {
1353 int pixel = -1;
1354 /*
1355 if (wxTheApp->m_colorCube)
1356 {
1357 pixel = wxTheApp->m_colorCube
1358 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1359 }
1360 else
1361 {
1362 */
1363 int max = 3 * (65536);
1364 for (int i = 0; i < 256; i++)
1365 {
1366 int rdiff = (r << 8) - colors[i].red;
1367 int gdiff = (g << 8) - colors[i].green;
1368 int bdiff = (b << 8) - colors[i].blue;
1369 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1370 if (sum < max) { pixel = i; max = sum; }
1371 }
1372 /*
1373 }
1374 */
1375 XPutPixel( data_image, x, y, pixel );
1376 break;
1377 }
1378 case 15:
1379 {
1380 int pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1381 XPutPixel( data_image, x, y, pixel );
1382 break;
1383 }
1384 case 16:
1385 {
1386 int pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1387 XPutPixel( data_image, x, y, pixel );
1388 break;
1389 }
1390 case 32:
1391 case 24:
1392 {
1393 int pixel = 0;
1394 switch (b_o)
1395 {
1396 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1397 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1398 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1399 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1400 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1401 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1402 }
1403 XPutPixel( data_image, x, y, pixel );
1404 }
1405 default: break;
1406 }
1407 } // for
1408 } // for
1409
1410 // Blit picture
1411
1412 XGCValues gcvalues;
1413 gcvalues.foreground = BlackPixel( dpy, DefaultScreen( dpy ) );
1414 GC gc = XCreateGC( dpy, RootWindow ( dpy, DefaultScreen(dpy) ), GCForeground, &gcvalues );
1415 XPutImage( dpy, (Drawable)bitmap.GetPixmap(), gc, data_image, 0, 0, 0, 0, width, height );
1416
1417 XDestroyImage( data_image );
1418 XFreeGC( dpy, gc );
1419
1420 /*
1421 // Blit mask
1422
1423 if (HasMask())
1424 {
1425 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
1426
1427 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
1428
1429 gdk_image_destroy( mask_image );
1430 gdk_gc_unref( mask_gc );
1431 }
1432 */
1433
1434 return bitmap;
1435 }
1436
1437 wxImage::wxImage( const wxBitmap &bitmap )
1438 {
1439 wxCHECK_RET( bitmap.Ok(), _T("invalid bitmap") );
1440
1441 Display *dpy = (Display*) wxGetDisplay();
1442 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1443 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1444
1445 XImage *ximage = XGetImage( dpy,
1446 (Drawable)bitmap.GetPixmap(),
1447 0, 0,
1448 bitmap.GetWidth(), bitmap.GetHeight(),
1449 AllPlanes, ZPixmap );
1450
1451 wxCHECK_RET( ximage, _T("couldn't create image") );
1452
1453 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1454 char unsigned *data = GetData();
1455
1456 if (!data)
1457 {
1458 XDestroyImage( ximage );
1459 wxFAIL_MSG( _T("couldn't create image") );
1460 return;
1461 }
1462
1463 /*
1464 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1465 if (bitmap.GetMask())
1466 {
1467 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1468 0, 0,
1469 bitmap.GetWidth(), bitmap.GetHeight() );
1470
1471 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1472 }
1473 */
1474
1475 // Retrieve depth info
1476
1477 XVisualInfo vinfo_template;
1478 XVisualInfo *vi;
1479
1480 vinfo_template.visual = vis;
1481 vinfo_template.visualid = XVisualIDFromVisual( vis );
1482 vinfo_template.depth = bpp;
1483 int nitem = 0;
1484
1485 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1486
1487 wxCHECK_RET( vi, _T("no visual") );
1488
1489 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1490
1491 XFree( vi );
1492
1493 XColor colors[256];
1494 if (bpp == 8)
1495 {
1496 Colormap cmap = (Colormap)wxTheApp->GetMainColormap( dpy );
1497
1498 for (int i = 0; i < 256; i++) colors[i].pixel = i;
1499 XQueryColors( dpy, cmap, colors, 256 );
1500 }
1501
1502 long pos = 0;
1503 for (int j = 0; j < bitmap.GetHeight(); j++)
1504 {
1505 for (int i = 0; i < bitmap.GetWidth(); i++)
1506 {
1507 int pixel = XGetPixel( ximage, i, j );
1508 if (bpp <= 8)
1509 {
1510 data[pos] = colors[pixel].red >> 8;
1511 data[pos+1] = colors[pixel].green >> 8;
1512 data[pos+2] = colors[pixel].blue >> 8;
1513 } else if (bpp == 15)
1514 {
1515 data[pos] = (pixel >> 7) & 0xf8;
1516 data[pos+1] = (pixel >> 2) & 0xf8;
1517 data[pos+2] = (pixel << 3) & 0xf8;
1518 } else if (bpp == 16)
1519 {
1520 data[pos] = (pixel >> 8) & 0xf8;
1521 data[pos+1] = (pixel >> 3) & 0xfc;
1522 data[pos+2] = (pixel << 3) & 0xf8;
1523 } else
1524 {
1525 data[pos] = (pixel >> 16) & 0xff;
1526 data[pos+1] = (pixel >> 8) & 0xff;
1527 data[pos+2] = pixel & 0xff;
1528 }
1529
1530 /*
1531 if (gdk_image_mask)
1532 {
1533 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1534 if (mask_pixel == 0)
1535 {
1536 data[pos] = 16;
1537 data[pos+1] = 16;
1538 data[pos+2] = 16;
1539 }
1540 }
1541 */
1542
1543 pos += 3;
1544 }
1545 }
1546
1547 XDestroyImage( ximage );
1548 /*
1549 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1550 */
1551 }
1552 #endif
1553
1554 // A module to allow wxImage initialization/cleanup
1555 // without calling these functions from app.cpp or from
1556 // the user's application.
1557
1558 class wxImageModule: public wxModule
1559 {
1560 DECLARE_DYNAMIC_CLASS(wxImageModule)
1561 public:
1562 wxImageModule() {}
1563 bool OnInit() { wxImage::InitStandardHandlers(); return TRUE; };
1564 void OnExit() { wxImage::CleanUpHandlers(); };
1565 };
1566
1567 IMPLEMENT_DYNAMIC_CLASS(wxImageModule, wxModule)