]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/image.cpp
1. corrected (but the fix is ugly) the multiple def button problem
[wxWidgets.git] / src / common / image.cpp
... / ...
CommitLineData
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
46class wxImageRefData: public wxObjectRefData
47{
48
49public:
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
61wxImageRefData::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
73wxImageRefData::~wxImageRefData()
74{
75 if (m_data) free( m_data );
76}
77
78wxList 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
88wxImage::wxImage()
89{
90}
91
92wxImage::wxImage( int width, int height )
93{
94 Create( width, height );
95}
96
97wxImage::wxImage( const wxString& name, long type )
98{
99 LoadFile( name, type );
100}
101
102wxImage::wxImage( const wxString& name, const wxString& mimetype )
103{
104 LoadFile( name, mimetype );
105}
106
107#if wxUSE_STREAMS
108wxImage::wxImage( wxInputStream& stream, long type )
109{
110 LoadFile( stream, type );
111}
112
113wxImage::wxImage( wxInputStream& stream, const wxString& mimetype )
114{
115 LoadFile( stream, mimetype );
116}
117#endif // wxUSE_STREAMS
118
119wxImage::wxImage( const wxImage& image )
120{
121 Ref(image);
122}
123
124wxImage::wxImage( const wxImage* image )
125{
126 if (image) Ref(*image);
127}
128
129void 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
148void wxImage::Destroy()
149{
150 UnRef();
151}
152
153wxImage 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
192wxImage 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
229void 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
245unsigned 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
259unsigned 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
273unsigned 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
287bool wxImage::Ok() const
288{
289 return (M_IMGDATA && M_IMGDATA->m_ok);
290}
291
292char unsigned *wxImage::GetData() const
293{
294 wxCHECK_MSG( Ok(), (char unsigned *)NULL, wxT("invalid image") );
295
296 return M_IMGDATA->m_data;
297}
298
299void 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
319void 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
329unsigned char wxImage::GetMaskRed() const
330{
331 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
332
333 return M_IMGDATA->m_maskRed;
334}
335
336unsigned char wxImage::GetMaskGreen() const
337{
338 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
339
340 return M_IMGDATA->m_maskGreen;
341}
342
343unsigned char wxImage::GetMaskBlue() const
344{
345 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
346
347 return M_IMGDATA->m_maskBlue;
348}
349
350void wxImage::SetMask( bool mask )
351{
352 wxCHECK_RET( Ok(), wxT("invalid image") );
353
354 M_IMGDATA->m_hasMask = mask;
355}
356
357bool wxImage::HasMask() const
358{
359 wxCHECK_MSG( Ok(), FALSE, wxT("invalid image") );
360
361 return M_IMGDATA->m_hasMask;
362}
363
364int wxImage::GetWidth() const
365{
366 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
367
368 return M_IMGDATA->m_width;
369}
370
371int wxImage::GetHeight() const
372{
373 wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
374
375 return M_IMGDATA->m_height;
376}
377
378bool 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
397bool 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
416bool 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
428bool 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
440bool wxImage::CanRead( const wxString &name )
441{
442#if wxUSE_STREAMS
443 wxFileInputStream stream(name);
444 return CanRead(stream);
445#else
446 return FALSE;
447#endif
448}
449
450#if wxUSE_STREAMS
451
452bool wxImage::CanRead( wxInputStream &stream )
453{
454 wxList &list=GetHandlers();
455
456 for ( wxList::Node *node = list.GetFirst(); node; node = node->GetNext() )
457 {
458 wxImageHandler *handler=(wxImageHandler*)node->GetData();
459 if (handler->CanRead( stream ))
460 return TRUE;
461 }
462
463 return FALSE;
464}
465
466bool wxImage::LoadFile( wxInputStream& stream, long type )
467{
468 UnRef();
469
470 m_refData = new wxImageRefData;
471
472 wxImageHandler *handler;
473
474 if (type==wxBITMAP_TYPE_ANY)
475 {
476 wxList &list=GetHandlers();
477
478 for ( wxList::Node *node = list.GetFirst(); node; node = node->GetNext() )
479 {
480 handler=(wxImageHandler*)node->GetData();
481 if (handler->CanRead( stream ))
482 return handler->LoadFile( this, stream );
483
484 }
485
486 wxLogWarning( wxT("No handler found for this image.") );
487 return FALSE;
488 }
489
490 handler = FindHandler(type);
491
492 if (handler == NULL)
493 {
494 wxLogWarning( wxT("No image handler for type %d defined."), type );
495
496 return FALSE;
497 }
498
499 return handler->LoadFile( this, stream );
500}
501
502bool wxImage::LoadFile( wxInputStream& stream, const wxString& mimetype )
503{
504 UnRef();
505
506 m_refData = new wxImageRefData;
507
508 wxImageHandler *handler = FindHandlerMime(mimetype);
509
510 if (handler == NULL)
511 {
512 wxLogWarning( wxT("No image handler for type %s defined."), mimetype.GetData() );
513
514 return FALSE;
515 }
516
517 return handler->LoadFile( this, stream );
518}
519
520bool wxImage::SaveFile( wxOutputStream& stream, int type )
521{
522 wxCHECK_MSG( Ok(), FALSE, wxT("invalid image") );
523
524 wxImageHandler *handler = FindHandler(type);
525
526 if (handler == NULL)
527 {
528 wxLogWarning( wxT("No image handler for type %d defined."), type );
529
530 return FALSE;
531 }
532
533 return handler->SaveFile( this, stream );
534}
535
536bool wxImage::SaveFile( wxOutputStream& stream, const wxString& mimetype )
537{
538 wxCHECK_MSG( Ok(), FALSE, wxT("invalid image") );
539
540 wxImageHandler *handler = FindHandlerMime(mimetype);
541
542 if (handler == NULL)
543 {
544 wxLogWarning( wxT("No image handler for type %s defined."), mimetype.GetData() );
545
546 return FALSE;
547 }
548
549 return handler->SaveFile( this, stream );
550}
551#endif // wxUSE_STREAMS
552
553void wxImage::AddHandler( wxImageHandler *handler )
554{
555 // make sure that the memory will be freed at the program end
556 sm_handlers.DeleteContents(TRUE);
557
558 sm_handlers.Append( handler );
559}
560
561void wxImage::InsertHandler( wxImageHandler *handler )
562{
563 // make sure that the memory will be freed at the program end
564 sm_handlers.DeleteContents(TRUE);
565
566 sm_handlers.Insert( handler );
567}
568
569bool wxImage::RemoveHandler( const wxString& name )
570{
571 wxImageHandler *handler = FindHandler(name);
572 if (handler)
573 {
574 sm_handlers.DeleteObject(handler);
575 return TRUE;
576 }
577 else
578 return FALSE;
579}
580
581wxImageHandler *wxImage::FindHandler( const wxString& name )
582{
583 wxNode *node = sm_handlers.First();
584 while (node)
585 {
586 wxImageHandler *handler = (wxImageHandler*)node->Data();
587 if (handler->GetName().Cmp(name) == 0) return handler;
588
589 node = node->Next();
590 }
591 return (wxImageHandler *)NULL;
592}
593
594wxImageHandler *wxImage::FindHandler( const wxString& extension, long bitmapType )
595{
596 wxNode *node = sm_handlers.First();
597 while (node)
598 {
599 wxImageHandler *handler = (wxImageHandler*)node->Data();
600 if ( (handler->GetExtension().Cmp(extension) == 0) &&
601 (bitmapType == -1 || handler->GetType() == bitmapType) )
602 return handler;
603 node = node->Next();
604 }
605 return (wxImageHandler*)NULL;
606}
607
608wxImageHandler *wxImage::FindHandler( long bitmapType )
609{
610 wxNode *node = sm_handlers.First();
611 while (node)
612 {
613 wxImageHandler *handler = (wxImageHandler *)node->Data();
614 if (handler->GetType() == bitmapType) return handler;
615 node = node->Next();
616 }
617 return NULL;
618}
619
620wxImageHandler *wxImage::FindHandlerMime( const wxString& mimetype )
621{
622 wxNode *node = sm_handlers.First();
623 while (node)
624 {
625 wxImageHandler *handler = (wxImageHandler *)node->Data();
626 if (handler->GetMimeType().IsSameAs(mimetype, FALSE)) return handler;
627 node = node->Next();
628 }
629 return NULL;
630}
631
632void wxImage::InitStandardHandlers()
633{
634 AddHandler( new wxBMPHandler );
635}
636
637void wxImage::CleanUpHandlers()
638{
639 wxNode *node = sm_handlers.First();
640 while (node)
641 {
642 wxImageHandler *handler = (wxImageHandler *)node->Data();
643 wxNode *next = node->Next();
644 delete handler;
645 delete node;
646 node = next;
647 }
648}
649
650//-----------------------------------------------------------------------------
651// wxImageHandler
652//-----------------------------------------------------------------------------
653
654#if !USE_SHARED_LIBRARIES
655IMPLEMENT_ABSTRACT_CLASS(wxImageHandler,wxObject)
656#endif
657
658#if wxUSE_STREAMS
659bool wxImageHandler::LoadFile( wxImage *WXUNUSED(image), wxInputStream& WXUNUSED(stream), bool WXUNUSED(verbose) )
660{
661 return FALSE;
662}
663
664bool wxImageHandler::SaveFile( wxImage *WXUNUSED(image), wxOutputStream& WXUNUSED(stream), bool WXUNUSED(verbose) )
665{
666 return FALSE;
667}
668
669bool wxImageHandler::CanRead( const wxString& name )
670{
671#if wxUSE_STREAMS
672 if (wxFileExists(name))
673 {
674 wxFileInputStream stream(name);
675 return CanRead(stream);
676 }
677
678 else {
679 wxLogError( wxT("Can't check image format of file '%s': file does not exist."), name.c_str() );
680
681 return FALSE;
682 }
683#else // !wxUSE_STREAMS
684 return FALSE;
685#endif // wxUSE_STREAMS
686}
687
688
689
690#endif // wxUSE_STREAMS
691
692//-----------------------------------------------------------------------------
693// MSW conversion routines
694//-----------------------------------------------------------------------------
695
696#ifdef __WXMSW__
697
698wxBitmap wxImage::ConvertToBitmap() const
699{
700 if ( !Ok() )
701 return wxNullBitmap;
702
703 // sizeLimit is the MS upper limit for the DIB size
704#ifdef WIN32
705 int sizeLimit = 1024*768*3;
706#else
707 int sizeLimit = 0x7fff ;
708#endif
709
710 // width and height of the device-dependent bitmap
711 int width = GetWidth();
712 int bmpHeight = GetHeight();
713
714 // calc the number of bytes per scanline and padding
715 int bytePerLine = width*3;
716 int sizeDWORD = sizeof( DWORD );
717 int lineBoundary = bytePerLine % sizeDWORD;
718 int padding = 0;
719 if( lineBoundary > 0 )
720 {
721 padding = sizeDWORD - lineBoundary;
722 bytePerLine += padding;
723 }
724 // calc the number of DIBs and heights of DIBs
725 int numDIB = 1;
726 int hRemain = 0;
727 int height = sizeLimit/bytePerLine;
728 if( height >= bmpHeight )
729 height = bmpHeight;
730 else
731 {
732 numDIB = bmpHeight / height;
733 hRemain = bmpHeight % height;
734 if( hRemain >0 ) numDIB++;
735 }
736
737 // set bitmap parameters
738 wxBitmap bitmap;
739 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
740 bitmap.SetWidth( width );
741 bitmap.SetHeight( bmpHeight );
742 bitmap.SetDepth( wxDisplayDepth() );
743
744 // create a DIB header
745 int headersize = sizeof(BITMAPINFOHEADER);
746 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
747 wxCHECK_MSG( lpDIBh, bitmap, wxT("could not allocate memory for DIB header") );
748 // Fill in the DIB header
749 lpDIBh->bmiHeader.biSize = headersize;
750 lpDIBh->bmiHeader.biWidth = (DWORD)width;
751 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
752 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
753 // the general formula for biSizeImage:
754 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
755 lpDIBh->bmiHeader.biPlanes = 1;
756 lpDIBh->bmiHeader.biBitCount = 24;
757 lpDIBh->bmiHeader.biCompression = BI_RGB;
758 lpDIBh->bmiHeader.biClrUsed = 0;
759 // These seem not really needed for our purpose here.
760 lpDIBh->bmiHeader.biClrImportant = 0;
761 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
762 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
763 // memory for DIB data
764 unsigned char *lpBits;
765 lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
766 if( !lpBits )
767 {
768 wxFAIL_MSG( wxT("could not allocate memory for DIB") );
769 free( lpDIBh );
770 return bitmap;
771 }
772
773 // create and set the device-dependent bitmap
774 HDC hdc = ::GetDC(NULL);
775 HDC memdc = ::CreateCompatibleDC( hdc );
776 HBITMAP hbitmap;
777 hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
778 ::SelectObject( memdc, hbitmap);
779
780 // copy image data into DIB data and then into DDB (in a loop)
781 unsigned char *data = GetData();
782 int i, j, n;
783 int origin = 0;
784 unsigned char *ptdata = data;
785 unsigned char *ptbits;
786
787 for( n=0; n<numDIB; n++ )
788 {
789 if( numDIB > 1 && n == numDIB-1 && hRemain > 0 )
790 {
791 // redefine height and size of the (possibly) last smaller DIB
792 // memory is not reallocated
793 height = hRemain;
794 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
795 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
796 }
797 ptbits = lpBits;
798
799 for( j=0; j<height; j++ )
800 {
801 for( i=0; i<width; i++ )
802 {
803 *(ptbits++) = *(ptdata+2);
804 *(ptbits++) = *(ptdata+1);
805 *(ptbits++) = *(ptdata );
806 ptdata += 3;
807 }
808 for( i=0; i< padding; i++ ) *(ptbits++) = 0;
809 }
810 ::StretchDIBits( memdc, 0, origin, width, height,\
811 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
812 origin += height;
813 // if numDIB = 1, lines below can also be used
814 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
815 // The above line is equivalent to the following two lines.
816 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
817 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
818 // or the following lines
819 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
820 // HDC memdc = ::CreateCompatibleDC( hdc );
821 // ::SelectObject( memdc, hbitmap);
822 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
823 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
824 // ::SelectObject( memdc, 0 );
825 // ::DeleteDC( memdc );
826 }
827 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
828
829 // similarly, created an mono-bitmap for the possible mask
830 if( HasMask() )
831 {
832 hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL );
833 ::SelectObject( memdc, hbitmap);
834 if( numDIB == 1 ) height = bmpHeight;
835 else height = sizeLimit/bytePerLine;
836 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
837 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
838 origin = 0;
839 unsigned char r = GetMaskRed();
840 unsigned char g = GetMaskGreen();
841 unsigned char b = GetMaskBlue();
842 unsigned char zero = 0, one = 255;
843 ptdata = data;
844 for( n=0; n<numDIB; n++ )
845 {
846 if( numDIB > 1 && n == numDIB - 1 && hRemain > 0 )
847 {
848 // redefine height and size of the (possibly) last smaller DIB
849 // memory is not reallocated
850 height = hRemain;
851 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
852 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
853 }
854 ptbits = lpBits;
855 for( int j=0; j<height; j++ )
856 {
857 for(i=0; i<width; i++ )
858 {
859 if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
860 {
861 *(ptbits++) = one;
862 *(ptbits++) = one;
863 *(ptbits++) = one;
864 }
865 else
866 {
867 *(ptbits++) = zero;
868 *(ptbits++) = zero;
869 *(ptbits++) = zero;
870 }
871 }
872 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
873 }
874 ::StretchDIBits( memdc, 0, origin, width, height,\
875 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
876 origin += height;
877 }
878 // create a wxMask object
879 wxMask *mask = new wxMask();
880 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
881 bitmap.SetMask( mask );
882 // It will be deleted when the wxBitmap object is deleted (as of 01/1999)
883 /* The following can also be used but is slow to run
884 wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
885 wxMask *mask = new wxMask( bitmap, colour );
886 bitmap.SetMask( mask );
887 */
888 }
889
890 // free allocated resources
891 ::SelectObject( memdc, 0 );
892 ::DeleteDC( memdc );
893 ::ReleaseDC(NULL, hdc);
894 free(lpDIBh);
895 free(lpBits);
896
897 // check the wxBitmap object
898 if( bitmap.GetHBITMAP() )
899 bitmap.SetOk( TRUE );
900 else
901 bitmap.SetOk( FALSE );
902
903 return bitmap;
904}
905
906wxImage::wxImage( const wxBitmap &bitmap )
907{
908 // check the bitmap
909 if( !bitmap.Ok() )
910 {
911 wxFAIL_MSG( wxT("invalid bitmap") );
912 return;
913 }
914
915 // create an wxImage object
916 int width = bitmap.GetWidth();
917 int height = bitmap.GetHeight();
918 Create( width, height );
919 unsigned char *data = GetData();
920 if( !data )
921 {
922 wxFAIL_MSG( wxT("could not allocate data for image") );
923 return;
924 }
925
926 // calc the number of bytes per scanline and padding in the DIB
927 int bytePerLine = width*3;
928 int sizeDWORD = sizeof( DWORD );
929 int lineBoundary = bytePerLine % sizeDWORD;
930 int padding = 0;
931 if( lineBoundary > 0 )
932 {
933 padding = sizeDWORD - lineBoundary;
934 bytePerLine += padding;
935 }
936
937 // create a DIB header
938 int headersize = sizeof(BITMAPINFOHEADER);
939 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
940 if( !lpDIBh )
941 {
942 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
943 free( data );
944 return;
945 }
946 // Fill in the DIB header
947 lpDIBh->bmiHeader.biSize = headersize;
948 lpDIBh->bmiHeader.biWidth = width;
949 lpDIBh->bmiHeader.biHeight = -height;
950 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
951 lpDIBh->bmiHeader.biPlanes = 1;
952 lpDIBh->bmiHeader.biBitCount = 24;
953 lpDIBh->bmiHeader.biCompression = BI_RGB;
954 lpDIBh->bmiHeader.biClrUsed = 0;
955 // These seem not really needed for our purpose here.
956 lpDIBh->bmiHeader.biClrImportant = 0;
957 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
958 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
959 // memory for DIB data
960 unsigned char *lpBits;
961 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
962 if( !lpBits )
963 {
964 wxFAIL_MSG( wxT("could not allocate data for DIB") );
965 free( data );
966 free( lpDIBh );
967 return;
968 }
969
970 // copy data from the device-dependent bitmap to the DIB
971 HDC hdc = ::GetDC(NULL);
972 HBITMAP hbitmap;
973 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
974 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
975
976 // copy DIB data into the wxImage object
977 int i, j;
978 unsigned char *ptdata = data;
979 unsigned char *ptbits = lpBits;
980 for( i=0; i<height; i++ )
981 {
982 for( j=0; j<width; j++ )
983 {
984 *(ptdata++) = *(ptbits+2);
985 *(ptdata++) = *(ptbits+1);
986 *(ptdata++) = *(ptbits );
987 ptbits += 3;
988 }
989 ptbits += padding;
990 }
991
992 // similarly, set data according to the possible mask bitmap
993 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
994 {
995 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
996 // memory DC created, color set, data copied, and memory DC deleted
997 HDC memdc = ::CreateCompatibleDC( hdc );
998 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
999 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
1000 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1001 ::DeleteDC( memdc );
1002 // background color set to RGB(16,16,16) in consistent with wxGTK
1003 unsigned char r=16, g=16, b=16;
1004 ptdata = data;
1005 ptbits = lpBits;
1006 for( i=0; i<height; i++ )
1007 {
1008 for( j=0; j<width; j++ )
1009 {
1010 if( *ptbits != 0 )
1011 ptdata += 3;
1012 else
1013 {
1014 *(ptdata++) = r;
1015 *(ptdata++) = g;
1016 *(ptdata++) = b;
1017 }
1018 ptbits += 3;
1019 }
1020 ptbits += padding;
1021 }
1022 SetMaskColour( r, g, b );
1023 SetMask( TRUE );
1024 }
1025 else
1026 {
1027 SetMask( FALSE );
1028 }
1029 // free allocated resources
1030 ::ReleaseDC(NULL, hdc);
1031 free(lpDIBh);
1032 free(lpBits);
1033}
1034
1035#endif
1036
1037//-----------------------------------------------------------------------------
1038// GTK conversion routines
1039//-----------------------------------------------------------------------------
1040
1041#ifdef __WXGTK__
1042
1043#include "gtk/gtk.h"
1044#include "gdk/gdk.h"
1045#include "gdk/gdkx.h"
1046
1047#if (GTK_MINOR_VERSION > 0)
1048#include "gdk/gdkrgb.h"
1049#endif
1050
1051wxBitmap wxImage::ConvertToBitmap() const
1052{
1053 wxBitmap bitmap;
1054
1055 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
1056
1057 int width = GetWidth();
1058 int height = GetHeight();
1059
1060 bitmap.SetHeight( height );
1061 bitmap.SetWidth( width );
1062
1063 bitmap.SetPixmap( gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, -1 ) );
1064
1065 // Retrieve depth
1066
1067 GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
1068 if (visual == NULL) visual = gdk_visual_get_system();
1069 int bpp = visual->depth;
1070
1071 bitmap.SetDepth( bpp );
1072
1073 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
1074 if (bpp < 8) bpp = 8;
1075
1076#if (GTK_MINOR_VERSION > 0)
1077
1078 if (!HasMask() && (bpp > 8))
1079 {
1080 static bool s_hasInitialized = FALSE;
1081
1082 if (!s_hasInitialized)
1083 {
1084 gdk_rgb_init();
1085 s_hasInitialized = TRUE;
1086 }
1087
1088 GdkGC *gc = gdk_gc_new( bitmap.GetPixmap() );
1089
1090 gdk_draw_rgb_image( bitmap.GetPixmap(),
1091 gc,
1092 0, 0,
1093 width, height,
1094 GDK_RGB_DITHER_NONE,
1095 GetData(),
1096 width*3 );
1097
1098 gdk_gc_unref( gc );
1099
1100 return bitmap;
1101 }
1102
1103#endif
1104
1105 // Create picture image
1106
1107 GdkImage *data_image =
1108 gdk_image_new( GDK_IMAGE_FASTEST, gdk_visual_get_system(), width, height );
1109
1110 // Create mask image
1111
1112 GdkImage *mask_image = (GdkImage*) NULL;
1113
1114 if (HasMask())
1115 {
1116 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1117
1118 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1119
1120 wxMask *mask = new wxMask();
1121 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1122
1123 bitmap.SetMask( mask );
1124 }
1125
1126 // Render
1127
1128 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1129 byte_order b_o = RGB;
1130
1131 if (bpp >= 24)
1132 {
1133 GdkVisual *visual = gdk_visual_get_system();
1134 if ((visual->red_mask > visual->green_mask) && (visual->green_mask > visual->blue_mask)) b_o = RGB;
1135 else if ((visual->red_mask > visual->blue_mask) && (visual->blue_mask > visual->green_mask)) b_o = RGB;
1136 else if ((visual->blue_mask > visual->red_mask) && (visual->red_mask > visual->green_mask)) b_o = BRG;
1137 else if ((visual->blue_mask > visual->green_mask) && (visual->green_mask > visual->red_mask)) b_o = BGR;
1138 else if ((visual->green_mask > visual->red_mask) && (visual->red_mask > visual->blue_mask)) b_o = GRB;
1139 else if ((visual->green_mask > visual->blue_mask) && (visual->blue_mask > visual->red_mask)) b_o = GBR;
1140 }
1141
1142 int r_mask = GetMaskRed();
1143 int g_mask = GetMaskGreen();
1144 int b_mask = GetMaskBlue();
1145
1146 unsigned char* data = GetData();
1147
1148 int index = 0;
1149 for (int y = 0; y < height; y++)
1150 {
1151 for (int x = 0; x < width; x++)
1152 {
1153 int r = data[index];
1154 index++;
1155 int g = data[index];
1156 index++;
1157 int b = data[index];
1158 index++;
1159
1160 if (HasMask())
1161 {
1162 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1163 gdk_image_put_pixel( mask_image, x, y, 1 );
1164 else
1165 gdk_image_put_pixel( mask_image, x, y, 0 );
1166 }
1167
1168 if (HasMask())
1169 {
1170 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1171 gdk_image_put_pixel( mask_image, x, y, 1 );
1172 else
1173 gdk_image_put_pixel( mask_image, x, y, 0 );
1174 }
1175
1176 switch (bpp)
1177 {
1178 case 8:
1179 {
1180 int pixel = -1;
1181 if (wxTheApp->m_colorCube)
1182 {
1183 pixel = wxTheApp->m_colorCube[ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1184 }
1185 else
1186 {
1187 GdkColormap *cmap = gtk_widget_get_default_colormap();
1188 GdkColor *colors = cmap->colors;
1189 int max = 3 * (65536);
1190
1191 for (int i = 0; i < cmap->size; i++)
1192 {
1193 int rdiff = (r << 8) - colors[i].red;
1194 int gdiff = (g << 8) - colors[i].green;
1195 int bdiff = (b << 8) - colors[i].blue;
1196 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1197 if (sum < max) { pixel = i; max = sum; }
1198 }
1199 }
1200
1201 gdk_image_put_pixel( data_image, x, y, pixel );
1202
1203 break;
1204 }
1205 case 15:
1206 {
1207 guint32 pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1208 gdk_image_put_pixel( data_image, x, y, pixel );
1209 break;
1210 }
1211 case 16:
1212 {
1213 guint32 pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1214 gdk_image_put_pixel( data_image, x, y, pixel );
1215 break;
1216 }
1217 case 32:
1218 case 24:
1219 {
1220 guint32 pixel = 0;
1221 switch (b_o)
1222 {
1223 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1224 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1225 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1226 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1227 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1228 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1229 }
1230 gdk_image_put_pixel( data_image, x, y, pixel );
1231 }
1232 default: break;
1233 }
1234 } // for
1235 } // for
1236
1237 // Blit picture
1238
1239 GdkGC *data_gc = gdk_gc_new( bitmap.GetPixmap() );
1240
1241 gdk_draw_image( bitmap.GetPixmap(), data_gc, data_image, 0, 0, 0, 0, width, height );
1242
1243 gdk_image_destroy( data_image );
1244 gdk_gc_unref( data_gc );
1245
1246 // Blit mask
1247
1248 if (HasMask())
1249 {
1250 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
1251
1252 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
1253
1254 gdk_image_destroy( mask_image );
1255 gdk_gc_unref( mask_gc );
1256 }
1257
1258 return bitmap;
1259}
1260
1261wxImage::wxImage( const wxBitmap &bitmap )
1262{
1263 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
1264
1265 GdkImage *gdk_image = (GdkImage*) NULL;
1266 if (bitmap.GetPixmap())
1267 {
1268 gdk_image = gdk_image_get( bitmap.GetPixmap(),
1269 0, 0,
1270 bitmap.GetWidth(), bitmap.GetHeight() );
1271 } else
1272 if (bitmap.GetBitmap())
1273 {
1274 gdk_image = gdk_image_get( bitmap.GetBitmap(),
1275 0, 0,
1276 bitmap.GetWidth(), bitmap.GetHeight() );
1277 } else
1278 {
1279 wxFAIL_MSG( wxT("Ill-formed bitmap") );
1280 }
1281
1282 wxCHECK_RET( gdk_image, wxT("couldn't create image") );
1283
1284 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1285 char unsigned *data = GetData();
1286
1287 if (!data)
1288 {
1289 gdk_image_destroy( gdk_image );
1290 wxFAIL_MSG( wxT("couldn't create image") );
1291 return;
1292 }
1293
1294 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1295 if (bitmap.GetMask())
1296 {
1297 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1298 0, 0,
1299 bitmap.GetWidth(), bitmap.GetHeight() );
1300
1301 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1302 }
1303
1304 GdkVisual *visual = (GdkVisual*) NULL;
1305 if (bitmap.GetPixmap())
1306 visual = gdk_window_get_visual( bitmap.GetPixmap() );
1307 else
1308 visual = gdk_window_get_visual( bitmap.GetBitmap() );
1309
1310 if (visual == NULL) visual = gdk_window_get_visual( (GdkWindow*) &gdk_root_parent );
1311 int bpp = visual->depth;
1312 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
1313
1314 GdkColormap *cmap = gtk_widget_get_default_colormap();
1315
1316 long pos = 0;
1317 for (int j = 0; j < bitmap.GetHeight(); j++)
1318 {
1319 for (int i = 0; i < bitmap.GetWidth(); i++)
1320 {
1321 wxInt32 pixel = gdk_image_get_pixel( gdk_image, i, j );
1322 // pixel = wxINT32_SWAP_ON_BE( pixel );
1323 if (bpp <= 8)
1324 {
1325 data[pos] = cmap->colors[pixel].red >> 8;
1326 data[pos+1] = cmap->colors[pixel].green >> 8;
1327 data[pos+2] = cmap->colors[pixel].blue >> 8;
1328 } else if (bpp == 15)
1329 {
1330 data[pos] = (pixel >> 7) & 0xf8;
1331 data[pos+1] = (pixel >> 2) & 0xf8;
1332 data[pos+2] = (pixel << 3) & 0xf8;
1333 } else if (bpp == 16)
1334 {
1335 data[pos] = (pixel >> 8) & 0xf8;
1336 data[pos+1] = (pixel >> 3) & 0xfc;
1337 data[pos+2] = (pixel << 3) & 0xf8;
1338 } else
1339 {
1340 data[pos] = (pixel >> 16) & 0xff;
1341 data[pos+1] = (pixel >> 8) & 0xff;
1342 data[pos+2] = pixel & 0xff;
1343 }
1344
1345 if (gdk_image_mask)
1346 {
1347 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1348 if (mask_pixel == 0)
1349 {
1350 data[pos] = 16;
1351 data[pos+1] = 16;
1352 data[pos+2] = 16;
1353 }
1354 }
1355
1356 pos += 3;
1357 }
1358 }
1359
1360 gdk_image_destroy( gdk_image );
1361 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1362}
1363
1364#endif
1365
1366//-----------------------------------------------------------------------------
1367// Motif conversion routines
1368//-----------------------------------------------------------------------------
1369
1370#ifdef __WXMOTIF__
1371
1372#include <Xm/Xm.h>
1373#include "wx/utils.h"
1374#include <math.h>
1375
1376wxBitmap wxImage::ConvertToBitmap() const
1377{
1378 wxBitmap bitmap;
1379
1380 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
1381
1382 int width = GetWidth();
1383 int height = GetHeight();
1384
1385 bitmap.SetHeight( height );
1386 bitmap.SetWidth( width );
1387
1388 Display *dpy = (Display*) wxGetDisplay();
1389 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1390 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1391
1392 // Create image
1393
1394 XImage *data_image = XCreateImage( dpy, vis, bpp, ZPixmap, 0, 0, width, height, 32, 0 );
1395 data_image->data = (char*) malloc( data_image->bytes_per_line * data_image->height );
1396
1397 bitmap.Create( width, height, bpp );
1398
1399 /*
1400 // Create mask
1401
1402 GdkImage *mask_image = (GdkImage*) NULL;
1403
1404 if (HasMask())
1405 {
1406 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
1407
1408 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
1409
1410 wxMask *mask = new wxMask();
1411 mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
1412
1413 bitmap.SetMask( mask );
1414 }
1415 */
1416
1417 // Retrieve depth info
1418
1419 XVisualInfo vinfo_template;
1420 XVisualInfo *vi;
1421
1422 vinfo_template.visual = vis;
1423 vinfo_template.visualid = XVisualIDFromVisual( vis );
1424 vinfo_template.depth = bpp;
1425 int nitem = 0;
1426
1427 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1428
1429 wxCHECK_MSG( vi, wxNullBitmap, wxT("no visual") );
1430
1431 XFree( vi );
1432
1433 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1434 if (bpp < 8) bpp = 8;
1435
1436 // Render
1437
1438 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1439 byte_order b_o = RGB;
1440
1441 if (bpp >= 24)
1442 {
1443 if ((vi->red_mask > vi->green_mask) && (vi->green_mask > vi->blue_mask)) b_o = RGB;
1444 else if ((vi->red_mask > vi->blue_mask) && (vi->blue_mask > vi->green_mask)) b_o = RGB;
1445 else if ((vi->blue_mask > vi->red_mask) && (vi->red_mask > vi->green_mask)) b_o = BRG;
1446 else if ((vi->blue_mask > vi->green_mask) && (vi->green_mask > vi->red_mask)) b_o = BGR;
1447 else if ((vi->green_mask > vi->red_mask) && (vi->red_mask > vi->blue_mask)) b_o = GRB;
1448 else if ((vi->green_mask > vi->blue_mask) && (vi->blue_mask > vi->red_mask)) b_o = GBR;
1449 }
1450
1451 /*
1452 int r_mask = GetMaskRed();
1453 int g_mask = GetMaskGreen();
1454 int b_mask = GetMaskBlue();
1455 */
1456
1457 XColor colors[256];
1458 if (bpp == 8)
1459 {
1460 Colormap cmap = (Colormap) wxTheApp->GetMainColormap( dpy );
1461
1462 for (int i = 0; i < 256; i++) colors[i].pixel = i;
1463 XQueryColors( dpy, cmap, colors, 256 );
1464 }
1465
1466 unsigned char* data = GetData();
1467
1468 int index = 0;
1469 for (int y = 0; y < height; y++)
1470 {
1471 for (int x = 0; x < width; x++)
1472 {
1473 int r = data[index];
1474 index++;
1475 int g = data[index];
1476 index++;
1477 int b = data[index];
1478 index++;
1479
1480 /*
1481 if (HasMask())
1482 {
1483 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1484 gdk_image_put_pixel( mask_image, x, y, 1 );
1485 else
1486 gdk_image_put_pixel( mask_image, x, y, 0 );
1487 }
1488 */
1489
1490 switch (bpp)
1491 {
1492 case 8:
1493 {
1494 int pixel = -1;
1495 /*
1496 if (wxTheApp->m_colorCube)
1497 {
1498 pixel = wxTheApp->m_colorCube
1499 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1500 }
1501 else
1502 {
1503 */
1504 int max = 3 * (65536);
1505 for (int i = 0; i < 256; i++)
1506 {
1507 int rdiff = (r << 8) - colors[i].red;
1508 int gdiff = (g << 8) - colors[i].green;
1509 int bdiff = (b << 8) - colors[i].blue;
1510 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1511 if (sum < max) { pixel = i; max = sum; }
1512 }
1513 /*
1514 }
1515 */
1516 XPutPixel( data_image, x, y, pixel );
1517 break;
1518 }
1519 case 15:
1520 {
1521 int pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1522 XPutPixel( data_image, x, y, pixel );
1523 break;
1524 }
1525 case 16:
1526 {
1527 int pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1528 XPutPixel( data_image, x, y, pixel );
1529 break;
1530 }
1531 case 32:
1532 case 24:
1533 {
1534 int pixel = 0;
1535 switch (b_o)
1536 {
1537 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1538 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1539 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1540 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1541 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1542 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1543 }
1544 XPutPixel( data_image, x, y, pixel );
1545 }
1546 default: break;
1547 }
1548 } // for
1549 } // for
1550
1551 // Blit picture
1552
1553 XGCValues gcvalues;
1554 gcvalues.foreground = BlackPixel( dpy, DefaultScreen( dpy ) );
1555 GC gc = XCreateGC( dpy, RootWindow ( dpy, DefaultScreen(dpy) ), GCForeground, &gcvalues );
1556 XPutImage( dpy, (Drawable)bitmap.GetPixmap(), gc, data_image, 0, 0, 0, 0, width, height );
1557
1558 XDestroyImage( data_image );
1559 XFreeGC( dpy, gc );
1560
1561 /*
1562 // Blit mask
1563
1564 if (HasMask())
1565 {
1566 GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() );
1567
1568 gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
1569
1570 gdk_image_destroy( mask_image );
1571 gdk_gc_unref( mask_gc );
1572 }
1573 */
1574
1575 return bitmap;
1576}
1577
1578wxImage::wxImage( const wxBitmap &bitmap )
1579{
1580 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
1581
1582 Display *dpy = (Display*) wxGetDisplay();
1583 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1584 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1585
1586 XImage *ximage = XGetImage( dpy,
1587 (Drawable)bitmap.GetPixmap(),
1588 0, 0,
1589 bitmap.GetWidth(), bitmap.GetHeight(),
1590 AllPlanes, ZPixmap );
1591
1592 wxCHECK_RET( ximage, wxT("couldn't create image") );
1593
1594 Create( bitmap.GetWidth(), bitmap.GetHeight() );
1595 char unsigned *data = GetData();
1596
1597 if (!data)
1598 {
1599 XDestroyImage( ximage );
1600 wxFAIL_MSG( wxT("couldn't create image") );
1601 return;
1602 }
1603
1604 /*
1605 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1606 if (bitmap.GetMask())
1607 {
1608 gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
1609 0, 0,
1610 bitmap.GetWidth(), bitmap.GetHeight() );
1611
1612 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1613 }
1614 */
1615
1616 // Retrieve depth info
1617
1618 XVisualInfo vinfo_template;
1619 XVisualInfo *vi;
1620
1621 vinfo_template.visual = vis;
1622 vinfo_template.visualid = XVisualIDFromVisual( vis );
1623 vinfo_template.depth = bpp;
1624 int nitem = 0;
1625
1626 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1627
1628 wxCHECK_RET( vi, wxT("no visual") );
1629
1630 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1631
1632 XFree( vi );
1633
1634 XColor colors[256];
1635 if (bpp == 8)
1636 {
1637 Colormap cmap = (Colormap)wxTheApp->GetMainColormap( dpy );
1638
1639 for (int i = 0; i < 256; i++) colors[i].pixel = i;
1640 XQueryColors( dpy, cmap, colors, 256 );
1641 }
1642
1643 long pos = 0;
1644 for (int j = 0; j < bitmap.GetHeight(); j++)
1645 {
1646 for (int i = 0; i < bitmap.GetWidth(); i++)
1647 {
1648 int pixel = XGetPixel( ximage, i, j );
1649 if (bpp <= 8)
1650 {
1651 data[pos] = colors[pixel].red >> 8;
1652 data[pos+1] = colors[pixel].green >> 8;
1653 data[pos+2] = colors[pixel].blue >> 8;
1654 } else if (bpp == 15)
1655 {
1656 data[pos] = (pixel >> 7) & 0xf8;
1657 data[pos+1] = (pixel >> 2) & 0xf8;
1658 data[pos+2] = (pixel << 3) & 0xf8;
1659 } else if (bpp == 16)
1660 {
1661 data[pos] = (pixel >> 8) & 0xf8;
1662 data[pos+1] = (pixel >> 3) & 0xfc;
1663 data[pos+2] = (pixel << 3) & 0xf8;
1664 } else
1665 {
1666 data[pos] = (pixel >> 16) & 0xff;
1667 data[pos+1] = (pixel >> 8) & 0xff;
1668 data[pos+2] = pixel & 0xff;
1669 }
1670
1671 /*
1672 if (gdk_image_mask)
1673 {
1674 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1675 if (mask_pixel == 0)
1676 {
1677 data[pos] = 16;
1678 data[pos+1] = 16;
1679 data[pos+2] = 16;
1680 }
1681 }
1682 */
1683
1684 pos += 3;
1685 }
1686 }
1687
1688 XDestroyImage( ximage );
1689 /*
1690 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1691 */
1692}
1693#endif
1694
1695#ifdef __WXPM__
1696// OS/2 Presentation manager conversion routings
1697
1698wxBitmap wxImage::ConvertToBitmap() const
1699{
1700 if ( !Ok() )
1701 return wxNullBitmap;
1702 wxBitmap bitmap; // remove
1703// TODO:
1704/*
1705 int sizeLimit = 1024*768*3;
1706
1707 // width and height of the device-dependent bitmap
1708 int width = GetWidth();
1709 int bmpHeight = GetHeight();
1710
1711 // calc the number of bytes per scanline and padding
1712 int bytePerLine = width*3;
1713 int sizeDWORD = sizeof( DWORD );
1714 int lineBoundary = bytePerLine % sizeDWORD;
1715 int padding = 0;
1716 if( lineBoundary > 0 )
1717 {
1718 padding = sizeDWORD - lineBoundary;
1719 bytePerLine += padding;
1720 }
1721 // calc the number of DIBs and heights of DIBs
1722 int numDIB = 1;
1723 int hRemain = 0;
1724 int height = sizeLimit/bytePerLine;
1725 if( height >= bmpHeight )
1726 height = bmpHeight;
1727 else
1728 {
1729 numDIB = bmpHeight / height;
1730 hRemain = bmpHeight % height;
1731 if( hRemain >0 ) numDIB++;
1732 }
1733
1734 // set bitmap parameters
1735 wxBitmap bitmap;
1736 wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") );
1737 bitmap.SetWidth( width );
1738 bitmap.SetHeight( bmpHeight );
1739 bitmap.SetDepth( wxDisplayDepth() );
1740
1741 // create a DIB header
1742 int headersize = sizeof(BITMAPINFOHEADER);
1743 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
1744 wxCHECK_MSG( lpDIBh, bitmap, wxT("could not allocate memory for DIB header") );
1745 // Fill in the DIB header
1746 lpDIBh->bmiHeader.biSize = headersize;
1747 lpDIBh->bmiHeader.biWidth = (DWORD)width;
1748 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
1749 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
1750 // the general formula for biSizeImage:
1751 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
1752 lpDIBh->bmiHeader.biPlanes = 1;
1753 lpDIBh->bmiHeader.biBitCount = 24;
1754 lpDIBh->bmiHeader.biCompression = BI_RGB;
1755 lpDIBh->bmiHeader.biClrUsed = 0;
1756 // These seem not really needed for our purpose here.
1757 lpDIBh->bmiHeader.biClrImportant = 0;
1758 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
1759 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
1760 // memory for DIB data
1761 unsigned char *lpBits;
1762 lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
1763 if( !lpBits )
1764 {
1765 wxFAIL_MSG( wxT("could not allocate memory for DIB") );
1766 free( lpDIBh );
1767 return bitmap;
1768 }
1769
1770 // create and set the device-dependent bitmap
1771 HDC hdc = ::GetDC(NULL);
1772 HDC memdc = ::CreateCompatibleDC( hdc );
1773 HBITMAP hbitmap;
1774 hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
1775 ::SelectObject( memdc, hbitmap);
1776
1777 // copy image data into DIB data and then into DDB (in a loop)
1778 unsigned char *data = GetData();
1779 int i, j, n;
1780 int origin = 0;
1781 unsigned char *ptdata = data;
1782 unsigned char *ptbits;
1783
1784 for( n=0; n<numDIB; n++ )
1785 {
1786 if( numDIB > 1 && n == numDIB-1 && hRemain > 0 )
1787 {
1788 // redefine height and size of the (possibly) last smaller DIB
1789 // memory is not reallocated
1790 height = hRemain;
1791 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
1792 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
1793 }
1794 ptbits = lpBits;
1795
1796 for( j=0; j<height; j++ )
1797 {
1798 for( i=0; i<width; i++ )
1799 {
1800 *(ptbits++) = *(ptdata+2);
1801 *(ptbits++) = *(ptdata+1);
1802 *(ptbits++) = *(ptdata );
1803 ptdata += 3;
1804 }
1805 for( i=0; i< padding; i++ ) *(ptbits++) = 0;
1806 }
1807 ::StretchDIBits( memdc, 0, origin, width, height,\
1808 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
1809 origin += height;
1810 // if numDIB = 1, lines below can also be used
1811 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
1812 // The above line is equivalent to the following two lines.
1813 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
1814 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
1815 // or the following lines
1816 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
1817 // HDC memdc = ::CreateCompatibleDC( hdc );
1818 // ::SelectObject( memdc, hbitmap);
1819 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
1820 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
1821 // ::SelectObject( memdc, 0 );
1822 // ::DeleteDC( memdc );
1823 }
1824 bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
1825
1826 // similarly, created an mono-bitmap for the possible mask
1827 if( HasMask() )
1828 {
1829 hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL );
1830 ::SelectObject( memdc, hbitmap);
1831 if( numDIB == 1 ) height = bmpHeight;
1832 else height = sizeLimit/bytePerLine;
1833 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
1834 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
1835 origin = 0;
1836 unsigned char r = GetMaskRed();
1837 unsigned char g = GetMaskGreen();
1838 unsigned char b = GetMaskBlue();
1839 unsigned char zero = 0, one = 255;
1840 ptdata = data;
1841 for( n=0; n<numDIB; n++ )
1842 {
1843 if( numDIB > 1 && n == numDIB - 1 && hRemain > 0 )
1844 {
1845 // redefine height and size of the (possibly) last smaller DIB
1846 // memory is not reallocated
1847 height = hRemain;
1848 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
1849 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
1850 }
1851 ptbits = lpBits;
1852 for( int j=0; j<height; j++ )
1853 {
1854 for(i=0; i<width; i++ )
1855 {
1856 if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
1857 {
1858 *(ptbits++) = one;
1859 *(ptbits++) = one;
1860 *(ptbits++) = one;
1861 }
1862 else
1863 {
1864 *(ptbits++) = zero;
1865 *(ptbits++) = zero;
1866 *(ptbits++) = zero;
1867 }
1868 }
1869 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
1870 }
1871 ::StretchDIBits( memdc, 0, origin, width, height,\
1872 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
1873 origin += height;
1874 }
1875 // create a wxMask object
1876 wxMask *mask = new wxMask();
1877 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
1878 bitmap.SetMask( mask );
1879 }
1880
1881 // free allocated resources
1882 ::SelectObject( memdc, 0 );
1883 ::DeleteDC( memdc );
1884 ::ReleaseDC(NULL, hdc);
1885 free(lpDIBh);
1886 free(lpBits);
1887
1888 // check the wxBitmap object
1889 if( bitmap.GetHBITMAP() )
1890 bitmap.SetOk( TRUE );
1891 else
1892 bitmap.SetOk( FALSE );
1893*/
1894 return bitmap;
1895}
1896
1897wxImage::wxImage( const wxBitmap &bitmap )
1898{
1899 // check the bitmap
1900 if( !bitmap.Ok() )
1901 {
1902 wxFAIL_MSG( wxT("invalid bitmap") );
1903 return;
1904 }
1905
1906 // create an wxImage object
1907 int width = bitmap.GetWidth();
1908 int height = bitmap.GetHeight();
1909 Create( width, height );
1910 unsigned char *data = GetData();
1911 if( !data )
1912 {
1913 wxFAIL_MSG( wxT("could not allocate data for image") );
1914 return;
1915 }
1916
1917 // calc the number of bytes per scanline and padding in the DIB
1918 int bytePerLine = width*3;
1919 int sizeDWORD = sizeof( DWORD );
1920 int lineBoundary = bytePerLine % sizeDWORD;
1921 int padding = 0;
1922 if( lineBoundary > 0 )
1923 {
1924 padding = sizeDWORD - lineBoundary;
1925 bytePerLine += padding;
1926 }
1927// TODO:
1928/*
1929 // create a DIB header
1930 int headersize = sizeof(BITMAPINFOHEADER);
1931 LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
1932 if( !lpDIBh )
1933 {
1934 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
1935 free( data );
1936 return;
1937 }
1938 // Fill in the DIB header
1939 lpDIBh->bmiHeader.biSize = headersize;
1940 lpDIBh->bmiHeader.biWidth = width;
1941 lpDIBh->bmiHeader.biHeight = -height;
1942 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
1943 lpDIBh->bmiHeader.biPlanes = 1;
1944 lpDIBh->bmiHeader.biBitCount = 24;
1945 lpDIBh->bmiHeader.biCompression = BI_RGB;
1946 lpDIBh->bmiHeader.biClrUsed = 0;
1947 // These seem not really needed for our purpose here.
1948 lpDIBh->bmiHeader.biClrImportant = 0;
1949 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
1950 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
1951 // memory for DIB data
1952 unsigned char *lpBits;
1953 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
1954 if( !lpBits )
1955 {
1956 wxFAIL_MSG( wxT("could not allocate data for DIB") );
1957 free( data );
1958 free( lpDIBh );
1959 return;
1960 }
1961
1962 // copy data from the device-dependent bitmap to the DIB
1963 HDC hdc = ::GetDC(NULL);
1964 HBITMAP hbitmap;
1965 hbitmap = (HBITMAP) bitmap.GetHBITMAP();
1966 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1967
1968 // copy DIB data into the wxImage object
1969 int i, j;
1970 unsigned char *ptdata = data;
1971 unsigned char *ptbits = lpBits;
1972 for( i=0; i<height; i++ )
1973 {
1974 for( j=0; j<width; j++ )
1975 {
1976 *(ptdata++) = *(ptbits+2);
1977 *(ptdata++) = *(ptbits+1);
1978 *(ptdata++) = *(ptbits );
1979 ptbits += 3;
1980 }
1981 ptbits += padding;
1982 }
1983
1984 // similarly, set data according to the possible mask bitmap
1985 if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
1986 {
1987 hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
1988 // memory DC created, color set, data copied, and memory DC deleted
1989 HDC memdc = ::CreateCompatibleDC( hdc );
1990 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
1991 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
1992 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
1993 ::DeleteDC( memdc );
1994 // background color set to RGB(16,16,16) in consistent with wxGTK
1995 unsigned char r=16, g=16, b=16;
1996 ptdata = data;
1997 ptbits = lpBits;
1998 for( i=0; i<height; i++ )
1999 {
2000 for( j=0; j<width; j++ )
2001 {
2002 if( *ptbits != 0 )
2003 ptdata += 3;
2004 else
2005 {
2006 *(ptdata++) = r;
2007 *(ptdata++) = g;
2008 *(ptdata++) = b;
2009 }
2010 ptbits += 3;
2011 }
2012 ptbits += padding;
2013 }
2014 SetMaskColour( r, g, b );
2015 SetMask( TRUE );
2016 }
2017 else
2018 {
2019 SetMask( FALSE );
2020 }
2021 // free allocated resources
2022 ::ReleaseDC(NULL, hdc);
2023 free(lpDIBh);
2024 free(lpBits);
2025*/
2026}
2027
2028#endif
2029
2030// A module to allow wxImage initialization/cleanup
2031// without calling these functions from app.cpp or from
2032// the user's application.
2033
2034class wxImageModule: public wxModule
2035{
2036DECLARE_DYNAMIC_CLASS(wxImageModule)
2037public:
2038 wxImageModule() {}
2039 bool OnInit() { wxImage::InitStandardHandlers(); return TRUE; };
2040 void OnExit() { wxImage::CleanUpHandlers(); };
2041};
2042
2043IMPLEMENT_DYNAMIC_CLASS(wxImageModule, wxModule)