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