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