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