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