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