1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
11 #pragma implementation "image.h"
14 // For compilers that support precompilation, includes "wx.h".
15 #include "wx/wxprec.h"
22 #include "wx/bitmap.h"
26 #include "../png/png.h"
28 #include "wx/filefn.h"
30 //-----------------------------------------------------------------------------
32 //-----------------------------------------------------------------------------
34 class wxImageRefData
: public wxObjectRefData
39 ~wxImageRefData(void);
43 unsigned char *m_data
;
45 unsigned char m_maskRed
,m_maskGreen
,m_maskBlue
;
49 wxImageRefData::wxImageRefData(void)
53 m_data
= (unsigned char*) NULL
;
61 wxImageRefData::~wxImageRefData(void)
63 if (m_data
) free( m_data
);
66 wxList
wxImage::sm_handlers
;
68 //-----------------------------------------------------------------------------
70 #define M_IMGDATA ((wxImageRefData *)m_refData)
72 #if !USE_SHARED_LIBRARIES
73 IMPLEMENT_DYNAMIC_CLASS(wxImage
, wxObject
)
80 wxImage::wxImage( int width
, int height
)
82 Create( width
, height
);
85 wxImage::wxImage( const wxString
& name
, long type
)
87 LoadFile( name
, type
);
90 wxImage::wxImage( const wxImage
& image
)
95 wxImage::wxImage( const wxImage
* image
)
97 if (image
) Ref(*image
);
100 void wxImage::Create( int width
, int height
)
102 m_refData
= new wxImageRefData();
104 M_IMGDATA
->m_data
= (unsigned char *) malloc( width
*height
*3 );
105 if (M_IMGDATA
->m_data
)
107 for (int l
= 0; l
< width
*height
*3; l
++) M_IMGDATA
->m_data
[l
] = 0;
109 M_IMGDATA
->m_width
= width
;
110 M_IMGDATA
->m_height
= height
;
111 M_IMGDATA
->m_ok
= TRUE
;
119 void wxImage::Destroy()
124 wxImage
wxImage::Scale( int width
, int height
)
128 wxCHECK_MSG( Ok(), image
, "invlaid image" );
130 wxCHECK_MSG( (width
> 0) && (height
> 0), image
, "invalid image size" );
132 image
.Create( width
, height
);
134 char unsigned *data
= image
.GetData();
136 wxCHECK_MSG( data
, image
, "unable to create image" );
138 if (M_IMGDATA
->m_hasMask
)
139 image
.SetMaskColour( M_IMGDATA
->m_maskRed
, M_IMGDATA
->m_maskGreen
, M_IMGDATA
->m_maskBlue
);
141 double xscale
= (double)width
/ (double)M_IMGDATA
->m_width
;
142 double yscale
= (double)height
/ (double)M_IMGDATA
->m_height
;
144 for (int j
= 0; j
< height
; j
++)
146 for (int i
= 0; i
< width
; i
++)
148 int new_pos
= 3*(j
*width
+ i
);
149 int old_pos
= 3*((long)(j
/yscale
)*M_IMGDATA
->m_width
+ (long)(i
/xscale
));
150 data
[ new_pos
] = M_IMGDATA
->m_data
[ old_pos
];
151 data
[ new_pos
+1 ] = M_IMGDATA
->m_data
[ old_pos
+1 ];
152 data
[ new_pos
+2 ] = M_IMGDATA
->m_data
[ old_pos
+2 ];
159 void wxImage::SetRGB( int x
, int y
, unsigned char r
, unsigned char g
, unsigned char b
)
161 wxCHECK_RET( Ok(), "invalid image" );
163 int w
= M_IMGDATA
->m_width
;
164 int h
= M_IMGDATA
->m_height
;
166 wxCHECK_RET( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), "invalid image index" );
168 long pos
= (y
* w
+ x
) * 3;
170 M_IMGDATA
->m_data
[ pos
] = r
;
171 M_IMGDATA
->m_data
[ pos
+1 ] = g
;
172 M_IMGDATA
->m_data
[ pos
+2 ] = b
;
175 unsigned char wxImage::GetRed( int x
, int y
)
177 wxCHECK_MSG( Ok(), 0, "invalid image" );
179 int w
= M_IMGDATA
->m_width
;
180 int h
= M_IMGDATA
->m_height
;
182 wxCHECK_MSG( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), 0, "invalid image index" );
184 long pos
= (y
* w
+ x
) * 3;
186 return M_IMGDATA
->m_data
[pos
];
189 unsigned char wxImage::GetGreen( int x
, int y
)
191 wxCHECK_MSG( Ok(), 0, "invalid image" );
193 int w
= M_IMGDATA
->m_width
;
194 int h
= M_IMGDATA
->m_height
;
196 wxCHECK_MSG( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), 0, "invalid image index" );
198 long pos
= (y
* w
+ x
) * 3;
200 return M_IMGDATA
->m_data
[pos
+1];
203 unsigned char wxImage::GetBlue( int x
, int y
)
205 wxCHECK_MSG( Ok(), 0, "invalid image" );
207 int w
= M_IMGDATA
->m_width
;
208 int h
= M_IMGDATA
->m_height
;
210 wxCHECK_MSG( (x
>=0) && (y
>=0) && (x
<w
) && (y
<h
), 0, "invalid image index" );
212 long pos
= (y
* w
+ x
) * 3;
214 return M_IMGDATA
->m_data
[pos
+2];
217 bool wxImage::Ok() const
219 return (M_IMGDATA
&& M_IMGDATA
->m_ok
);
222 char unsigned *wxImage::GetData() const
224 wxCHECK_MSG( Ok(), (char unsigned *)NULL
, "invalid image" );
226 return M_IMGDATA
->m_data
;
229 void wxImage::SetData( char unsigned *WXUNUSED(data
) )
231 wxCHECK_RET( Ok(), "invalid image" );
234 void wxImage::SetMaskColour( unsigned char r
, unsigned char g
, unsigned char b
)
236 wxCHECK_RET( Ok(), "invalid image" );
238 M_IMGDATA
->m_maskRed
= r
;
239 M_IMGDATA
->m_maskGreen
= g
;
240 M_IMGDATA
->m_maskBlue
= b
;
241 M_IMGDATA
->m_hasMask
= TRUE
;
244 unsigned char wxImage::GetMaskRed() const
246 wxCHECK_MSG( Ok(), 0, "invalid image" );
248 return M_IMGDATA
->m_maskRed
;
251 unsigned char wxImage::GetMaskGreen() const
253 wxCHECK_MSG( Ok(), 0, "invalid image" );
255 return M_IMGDATA
->m_maskGreen
;
258 unsigned char wxImage::GetMaskBlue() const
260 wxCHECK_MSG( Ok(), 0, "invalid image" );
262 return M_IMGDATA
->m_maskBlue
;
265 void wxImage::SetMask( bool mask
)
267 wxCHECK_RET( Ok(), "invalid image" );
269 M_IMGDATA
->m_hasMask
= mask
;
272 bool wxImage::HasMask() const
274 wxCHECK_MSG( Ok(), FALSE
, "invalid image" );
276 return M_IMGDATA
->m_hasMask
;
279 int wxImage::GetWidth() const
281 wxCHECK_MSG( Ok(), 0, "invalid image" );
283 return M_IMGDATA
->m_width
;
286 int wxImage::GetHeight() const
288 wxCHECK_MSG( Ok(), 0, "invalid image" );
290 return M_IMGDATA
->m_height
;
293 bool wxImage::LoadFile( const wxString
& filename
, long type
)
297 if (!wxFileExists(filename
))
299 wxLogWarning( "Image file does not exist." );
304 m_refData
= new wxImageRefData
;
306 wxImageHandler
*handler
= FindHandler(type
);
310 wxLogWarning( "No image handler for type %d defined.", type
);
315 return handler
->LoadFile( this, filename
);
318 bool wxImage::SaveFile( const wxString
& filename
, int type
)
320 wxCHECK_MSG( Ok(), FALSE
, "invalid image" );
322 wxImageHandler
*handler
= FindHandler(type
);
326 wxLogWarning( "No image handler for type %d defined.", type
);
331 return handler
->SaveFile( this, filename
);
334 void wxImage::AddHandler( wxImageHandler
*handler
)
336 sm_handlers
.Append( handler
);
339 void wxImage::InsertHandler( wxImageHandler
*handler
)
341 sm_handlers
.Insert( handler
);
344 bool wxImage::RemoveHandler( const wxString
& name
)
346 wxImageHandler
*handler
= FindHandler(name
);
349 sm_handlers
.DeleteObject(handler
);
356 wxImageHandler
*wxImage::FindHandler( const wxString
& name
)
358 wxNode
*node
= sm_handlers
.First();
361 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
362 if (handler
->GetName() == name
) return handler
;
365 return (wxImageHandler
*)NULL
;
368 wxImageHandler
*wxImage::FindHandler( const wxString
& extension
, long bitmapType
)
370 wxNode
*node
= sm_handlers
.First();
373 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
374 if ( handler
->GetExtension() == extension
&&
375 (bitmapType
== -1 || handler
->GetType() == bitmapType
) )
379 return (wxImageHandler
*)NULL
;
382 wxImageHandler
*wxImage::FindHandler( long bitmapType
)
384 wxNode
*node
= sm_handlers
.First();
387 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
388 if (handler
->GetType() == bitmapType
) return handler
;
394 void wxImage::InitStandardHandlers()
396 AddHandler( new wxBMPHandler
);
398 AddHandler( new wxPNGHandler
);
402 void wxImage::CleanUpHandlers()
404 wxNode
*node
= sm_handlers
.First();
407 wxImageHandler
*handler
= (wxImageHandler
*)node
->Data();
408 wxNode
*next
= node
->Next();
415 //-----------------------------------------------------------------------------
417 //-----------------------------------------------------------------------------
419 #if !USE_SHARED_LIBRARIES
420 IMPLEMENT_DYNAMIC_CLASS(wxImageHandler
,wxObject
)
423 bool wxImageHandler::LoadFile( wxImage
*WXUNUSED(image
), const wxString
& WXUNUSED(name
) )
428 bool wxImageHandler::SaveFile( wxImage
*WXUNUSED(image
), const wxString
& WXUNUSED(name
) )
433 //-----------------------------------------------------------------------------
435 //-----------------------------------------------------------------------------
439 #if !USE_SHARED_LIBRARIES
440 IMPLEMENT_DYNAMIC_CLASS(wxPNGHandler
,wxImageHandler
)
443 bool wxPNGHandler::LoadFile( wxImage
*image
, const wxString
& name
)
448 unsigned char *ptr
, **lines
, *ptr2
;
449 int transp
,bit_depth
,color_type
,interlace_type
;
450 png_uint_32 width
, height
;
456 png_ptr
= png_create_read_struct( PNG_LIBPNG_VER_STRING
, NULL
, NULL
, NULL
);
457 if (!png_ptr
) return FALSE
;
459 info_ptr
= png_create_info_struct( png_ptr
);
462 png_destroy_read_struct( &png_ptr
, NULL
, NULL
);
466 if (setjmp(png_ptr
->jmpbuf
))
468 png_destroy_read_struct( &png_ptr
, &info_ptr
, NULL
);
472 if (info_ptr
->color_type
== PNG_COLOR_TYPE_RGB_ALPHA
)
474 png_destroy_read_struct( &png_ptr
, &info_ptr
, NULL
);
478 f
= fopen( name
, "rb" );
479 png_init_io( png_ptr
, f
);
481 png_read_info( png_ptr
, info_ptr
);
482 png_get_IHDR( png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
, &interlace_type
, NULL
, NULL
);
484 if (color_type
== PNG_COLOR_TYPE_PALETTE
) png_set_expand( png_ptr
);
486 png_set_strip_16( png_ptr
);
487 png_set_packing( png_ptr
);
488 if (png_get_valid( png_ptr
, info_ptr
, PNG_INFO_tRNS
)) png_set_expand( png_ptr
);
489 png_set_filler( png_ptr
, 0xff, PNG_FILLER_AFTER
);
491 image
->Create( width
, height
);
495 png_destroy_read_struct( &png_ptr
, &info_ptr
, NULL
);
499 lines
= (unsigned char **)malloc( height
* sizeof(unsigned char *) );
503 png_destroy_read_struct( &png_ptr
, &info_ptr
, NULL
);
507 for (i
= 0; i
< height
; i
++)
509 if ((lines
[i
] = (unsigned char *)malloc(width
* (sizeof(unsigned char) * 4))) == NULL
)
512 for (unsigned int n
= 0; n
< i
; n
++) free( lines
[n
] );
514 png_destroy_read_struct( &png_ptr
, &info_ptr
, NULL
);
519 png_read_image( png_ptr
, lines
);
520 png_destroy_read_struct( &png_ptr
, &info_ptr
, NULL
);
521 ptr
= image
->GetData();
522 if ((color_type
== PNG_COLOR_TYPE_GRAY
) ||
523 (color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
))
525 for (unsigned int y
= 0; y
< height
; y
++)
528 for (unsigned int x
= 0; x
< width
; x
++)
530 unsigned char r
= *ptr2
++;
531 unsigned char a
= *ptr2
++;
550 for (unsigned int y
= 0; y
< height
; y
++)
553 for (unsigned int x
= 0; x
< width
; x
++)
555 unsigned char r
= *ptr2
++;
556 unsigned char g
= *ptr2
++;
557 unsigned char b
= *ptr2
++;
558 unsigned char a
= *ptr2
++;
568 if ((r
== 255) && (g
== 0) && (b
== 255)) r
= 254;
576 for (i
= 0; i
< height
; i
++) free( lines
[i
] );
579 image
->SetMaskColour( 255, 0, 255 );
581 image
->SetMask( FALSE
);
587 bool wxPNGHandler::SaveFile( wxImage
*image
, const wxString
& name
)
589 FILE *f
= fopen( name
, "wb" );
592 png_structp png_ptr
= png_create_write_struct( PNG_LIBPNG_VER_STRING
, NULL
, NULL
, NULL
);
599 png_infop info_ptr
= png_create_info_struct(png_ptr
);
600 if (info_ptr
== NULL
)
603 png_destroy_write_struct( &png_ptr
, (png_infopp
)NULL
);
607 if (setjmp(png_ptr
->jmpbuf
))
610 png_destroy_write_struct( &png_ptr
, (png_infopp
)NULL
);
614 png_init_io( png_ptr
, f
);
615 png_set_IHDR( png_ptr
, info_ptr
, image
->GetWidth(), image
->GetHeight(), 8,
616 PNG_COLOR_TYPE_RGB_ALPHA
, PNG_INTERLACE_NONE
,
617 PNG_COMPRESSION_TYPE_BASE
, PNG_FILTER_TYPE_BASE
);
624 png_set_sBIT( png_ptr
, info_ptr
, &sig_bit
);
625 png_write_info( png_ptr
, info_ptr
);
626 png_set_shift( png_ptr
, &sig_bit
);
627 png_set_packing( png_ptr
);
629 unsigned char *data
= (unsigned char *)malloc( image
->GetWidth()*4 );
633 png_destroy_write_struct( &png_ptr
, (png_infopp
)NULL
);
637 for (int y
= 0; y
< image
->GetHeight(); y
++)
639 unsigned char *ptr
= image
->GetData() + (y
* image
->GetWidth() * 3);
640 for (int x
= 0; x
< image
->GetWidth(); x
++)
642 data
[(x
<< 2) + 0] = *ptr
++;
643 data
[(x
<< 2) + 1] = *ptr
++;
644 data
[(x
<< 2) + 2] = *ptr
++;
645 if ((data
[(x
<< 2) + 0] == image
->GetMaskRed()) &&
646 (data
[(x
<< 2) + 1] == image
->GetMaskGreen()) &&
647 (data
[(x
<< 2) + 2] == image
->GetMaskBlue()))
648 data
[(x
<< 2) + 3] = 0;
650 data
[(x
<< 2) + 3] = 255;
652 png_bytep row_ptr
= data
;
653 png_write_rows( png_ptr
, &row_ptr
, 1 );
656 png_write_end( png_ptr
, info_ptr
);
657 png_destroy_write_struct( &png_ptr
, (png_infopp
)NULL
);
668 //-----------------------------------------------------------------------------
670 //-----------------------------------------------------------------------------
672 #if !USE_SHARED_LIBRARIES
673 IMPLEMENT_DYNAMIC_CLASS(wxBMPHandler
,wxImageHandler
)
676 bool wxBMPHandler::LoadFile( wxImage
*image
, const wxString
& name
)
679 unsigned char *data
, *ptr
;
680 int done
, i
, bpp
, planes
, comp
, ncolors
, line
, column
,
681 linesize
, linepos
, rshift
= 0, gshift
= 0, bshift
= 0;
684 long int dbuf
[4], dword
, rmask
= 0, gmask
= 0, bmask
= 0, offset
,
689 unsigned char r
, g
, b
;
699 #define BI_BITFIELDS 3
704 file
= fopen(name
, "r");
710 * Reading the bmp header
713 fread(&bbuf
, 1, 2, file
);
715 fread(dbuf
, 4, 4, file
);
720 fread(dbuf
, 4, 2, file
);
721 int width
= (int)dbuf
[0];
722 int height
= (int)dbuf
[1];
725 fprintf(stderr
, "IMLIB ERROR: Image width > 32767 pixels for file\n");
731 fprintf(stderr
, "IMLIB ERROR: Image height > 32767 pixels for file\n");
735 fread(&word
, 2, 1, file
);
737 fread(&word
, 2, 1, file
);
739 if (bpp
!= 1 && bpp
!= 4 && bpp
!= 8 && bpp
&& 16 && bpp
!= 24 && bpp
!= 32)
741 fprintf(stderr
, "IMLIB ERROR: unknown bitdepth in file\n");
745 fread(dbuf
, 4, 4, file
);
747 if (comp
!= BI_RGB
&& comp
!= BI_RLE4
&& comp
!= BI_RLE8
&& comp
!= BI_BITFIELDS
)
749 fprintf(stderr
, "IMLIB ERROR: unknown encoding in Windows BMP file\n");
753 fread(dbuf
, 4, 2, file
);
754 ncolors
= (int)dbuf
[0];
757 /* some more sanity checks */
758 if (((comp
== BI_RLE4
) && (bpp
!= 4)) || ((comp
== BI_RLE8
) && (bpp
!= 8)) || ((comp
== BI_BITFIELDS
) && (bpp
!= 16 && bpp
!= 32)))
760 fprintf(stderr
, "IMLIB ERROR: encoding of BMP doesn't match bitdepth\n");
766 cmap
= (struct _cmap
*)malloc(sizeof(struct _cmap
) * ncolors
);
770 fprintf(stderr
, "IMLIB ERROR: Cannot allocate RAM for color map in BMP file\n");
778 image
->Create( width
, height
);
779 ptr
= image
->GetData();
782 fprintf(stderr
, "IMLIB ERROR: Cannot allocate RAM for RGB data in file\n");
790 * Reading the palette, if it exists.
792 if (bpp
< 16 && ncolors
!= 0)
794 for (i
= 0; i
< ncolors
; i
++)
796 fread(bbuf
, 1, 4, file
);
802 else if (bpp
== 16 || bpp
== 32)
804 if (comp
== BI_BITFIELDS
)
808 fread(dbuf
, 4, 3, file
);
812 /* find shift amount.. ugly, but i can't think of a better way */
813 for (bit
= 0; bit
< bpp
; bit
++)
815 if (bmask
& (1 << bit
))
817 if (gmask
& (1 << bit
))
819 if (rmask
& (1 << bit
))
844 * REading the image data
846 fseek(file
, offset
, SEEK_SET
);
849 /* set the whole image to the background color */
850 if (bpp
< 16 && (comp
== BI_RLE4
|| comp
== BI_RLE8
))
852 for (i
= 0; i
< width
* height
; i
++)
862 #define poffset (line * width * 3 + column * 3)
865 * BMPs are stored upside down... hmmmmmmmmmm....
868 linesize
= ((width
* bpp
+ 31) / 32) * 4;
869 for (line
= (height
- 1); line
>= 0; line
--)
872 for (column
= 0; column
< width
;)
884 for (bit
= 0; bit
< 8; bit
++)
886 index
= ((aByte
& (0x80 >> bit
)) ? 1 : 0);
887 ptr
[poffset
] = cmap
[index
].r
;
888 ptr
[poffset
+ 1] = cmap
[index
].g
;
889 ptr
[poffset
+ 2] = cmap
[index
].b
;
897 fprintf(stderr
, "can't deal with 4bit encoded yet.\n");
906 for (nibble
= 0; nibble
< 2; nibble
++)
908 index
= ((aByte
& (0xF0 >> nibble
* 4)) >> (!nibble
* 4));
911 ptr
[poffset
] = cmap
[index
].r
;
912 ptr
[poffset
+ 1] = cmap
[index
].g
;
913 ptr
[poffset
+ 2] = cmap
[index
].b
;
930 /* column = width; */
941 linepos
= column
* bpp
/ 8;
947 int absolute
= aByte
;
949 for (i
= 0; i
< absolute
; i
++)
953 ptr
[poffset
] = cmap
[aByte
].r
;
954 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
955 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
964 for (i
= 0; i
< first
; i
++)
966 ptr
[poffset
] = cmap
[aByte
].r
;
967 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
968 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
976 ptr
[poffset
] = cmap
[aByte
].r
;
977 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
978 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
986 linepos
+= fread(&bbuf
, 1, 3, file
);
987 ptr
[poffset
] = (unsigned char)bbuf
[2];
988 ptr
[poffset
+ 1] = (unsigned char)bbuf
[1];
989 ptr
[poffset
+ 2] = (unsigned char)bbuf
[0];
996 linepos
+= fread(&word
, 2, 1, file
);
997 temp
= (word
& rmask
) >> rshift
;
999 temp
= (word
& gmask
) >> gshift
;
1000 ptr
[poffset
+ 1] = temp
;
1001 temp
= (word
& bmask
) >> gshift
;
1002 ptr
[poffset
+ 2] = temp
;
1009 linepos
+= fread(&dword
, 4, 1, file
);
1010 temp
= (dword
& rmask
) >> rshift
;
1011 ptr
[poffset
] = temp
;
1012 temp
= (dword
& gmask
) >> gshift
;
1013 ptr
[poffset
+ 1] = temp
;
1014 temp
= (dword
& bmask
) >> bshift
;
1015 ptr
[poffset
+ 2] = temp
;
1019 while ((linepos
< linesize
) && (comp
!= 1) && (comp
!= 2))
1021 int temp
= fread(&aByte
, 1, 1, file
);
1028 if (cmap
) free(cmap
);
1030 image
->SetMask( FALSE
);
1038 wxBitmap
wxImage::ConvertToBitmap() const
1042 wxCHECK_MSG( Ok(), bitmap
, "invalid image" );
1043 int width
= GetWidth();
1044 int height
= GetHeight();
1045 bitmap
.SetWidth( width
);
1046 bitmap
.SetHeight( height
);
1047 bitmap
.SetDepth( wxDisplayDepth() );
1049 int headersize
= sizeof(BITMAPINFOHEADER
);
1050 LPBITMAPINFO lpDIBh
= (BITMAPINFO
*) malloc( headersize
);
1051 wxCHECK_MSG( lpDIBh
, bitmap
, "could not allocate memory for DIB header" );
1053 // Fill in the DIB header
1054 lpDIBh
->bmiHeader
.biSize
= headersize
;
1055 lpDIBh
->bmiHeader
.biWidth
= width
;
1056 lpDIBh
->bmiHeader
.biHeight
= -height
;
1057 lpDIBh
->bmiHeader
.biSizeImage
= width
* height
* 3;
1059 lpDIBh
->bmiHeader
.biPlanes
= 1;
1060 lpDIBh
->bmiHeader
.biBitCount
= 24;
1061 lpDIBh
->bmiHeader
.biCompression
= BI_RGB
;
1062 lpDIBh
->bmiHeader
.biClrUsed
= 0;
1064 // These seem not needed for our purpose here.
1065 // lpDIBh->bmiHeader.biClrImportant = 0;
1066 // lpDIBh->bmiHeader.biXPelsPerMeter = 0;
1067 // lpDIBh->bmiHeader.biYPelsPerMeter = 0;
1069 unsigned char *lpBits
= (unsigned char *) malloc( width
*height
*3 );
1072 wxFAIL_MSG( "could not allocate memory for DIB" );
1077 unsigned char *data
= GetData();
1079 unsigned char *ptdata
= data
, *ptbits
= lpBits
;
1080 for( int i
=0; i
<width
*height
; i
++ )
1082 *(ptbits
++) = *(ptdata
+2);
1083 *(ptbits
++) = *(ptdata
+1);
1084 *(ptbits
++) = *(ptdata
);
1088 HDC hdc
= ::GetDC(NULL
);
1091 hbitmap
= CreateDIBitmap( hdc
, &(lpDIBh
->bmiHeader
), CBM_INIT
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
1093 // The above line is equivalent to the following two lines.
1094 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
1095 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
1096 // or the following lines
1097 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
1098 // HDC memdc = ::CreateCompatibleDC( hdc );
1099 // ::SelectObject( memdc, hbitmap);
1100 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
1101 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
1102 // ::SelectObject( memdc, 0 );
1103 // ::DeleteDC( memdc );
1105 bitmap
.SetHBITMAP( (WXHBITMAP
) hbitmap
);
1109 unsigned char r
= GetMaskRed();
1110 unsigned char g
= GetMaskGreen();
1111 unsigned char b
= GetMaskBlue();
1112 unsigned char zero
= 0, one
= 255;
1115 for( int i
=0; i
<width
*height
; i
++ )
1117 if( (*(ptdata
++)!=r
) | (*(ptdata
++)!=g
) | (*(ptdata
++)!=b
) )
1130 hbitmap
= ::CreateBitmap( (WORD
)width
, (WORD
)height
, 1, 1, NULL
);
1131 ::SetDIBits( hdc
, hbitmap
, 0, (WORD
)height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
1132 wxMask
*mask
= new wxMask();
1133 mask
->SetMaskBitmap( (WXHBITMAP
) hbitmap
);
1134 bitmap
.SetMask( mask
);
1136 /* The following can also be used but is slow to run
1137 wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
1138 wxMask *mask = new wxMask( bitmap, colour );
1139 bitmap.SetMask( mask );
1143 ::ReleaseDC(NULL
, hdc
);
1147 if( bitmap
.GetHBITMAP() )
1148 bitmap
.SetOk( TRUE
);
1150 bitmap
.SetOk( FALSE
);
1156 wxImage::wxImage( const wxBitmap
&bitmap
)
1160 wxFAIL_MSG( "invalid bitmap" );
1164 int width
= bitmap
.GetWidth();
1165 int height
= bitmap
.GetHeight();
1166 Create( width
, height
);
1167 unsigned char *data
= GetData();
1170 wxFAIL_MSG( "could not allocate data for image" );
1174 int headersize
= sizeof(BITMAPINFOHEADER
);
1175 LPBITMAPINFO lpDIBh
= (BITMAPINFO
*) malloc( headersize
);
1178 wxFAIL_MSG( "could not allocate data for DIB header" );
1183 // Fill in the DIB header
1184 lpDIBh
->bmiHeader
.biSize
= headersize
;
1185 lpDIBh
->bmiHeader
.biWidth
= width
;
1186 lpDIBh
->bmiHeader
.biHeight
= -height
;
1187 lpDIBh
->bmiHeader
.biSizeImage
= width
* height
* 3;
1189 lpDIBh
->bmiHeader
.biPlanes
= 1;
1190 lpDIBh
->bmiHeader
.biBitCount
= 24;
1191 lpDIBh
->bmiHeader
.biCompression
= BI_RGB
;
1192 lpDIBh
->bmiHeader
.biClrUsed
= 0;
1194 // These seem not needed for our purpose here.
1195 // lpDIBh->bmiHeader.biClrImportant = 0;
1196 // lpDIBh->bmiHeader.biXPelsPerMeter = 0;
1197 // lpDIBh->bmiHeader.biYPelsPerMeter = 0;
1199 unsigned char *lpBits
= (unsigned char *) malloc( width
*height
*3 );
1202 wxFAIL_MSG( "could not allocate data for DIB" );
1209 hbitmap
= (HBITMAP
) bitmap
.GetHBITMAP();
1210 HDC hdc
= ::GetDC(NULL
);
1211 ::GetDIBits( hdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
1213 unsigned char *ptdata
= data
, *ptbits
= lpBits
;
1214 for( int i
=0; i
<width
*height
; i
++ )
1216 *(ptdata
++) = *(ptbits
+2);
1217 *(ptdata
++) = *(ptbits
+1);
1218 *(ptdata
++) = *(ptbits
);
1222 if( bitmap
.GetMask() && bitmap
.GetMask()->GetMaskBitmap() )
1224 hbitmap
= (HBITMAP
) bitmap
.GetMask()->GetMaskBitmap();
1225 HDC memdc
= ::CreateCompatibleDC( hdc
);
1226 ::SetTextColor( memdc
, RGB( 0, 0, 0 ) );
1227 ::SetBkColor( memdc
, RGB( 255, 255, 255 ) );
1228 ::GetDIBits( memdc
, hbitmap
, 0, height
, lpBits
, lpDIBh
, DIB_RGB_COLORS
);
1229 ::DeleteDC( memdc
);
1230 unsigned char r
=16, g
=16, b
=16; // background set to RGB(16,16,16)
1233 for( int i
=0; i
<width
*height
; i
++ )
1243 SetMaskColour( r
, g
, b
);
1246 ::ReleaseDC(NULL
, hdc
);
1255 #include "gtk/gtk.h"
1256 #include "gdk/gdk.h"
1257 #include "gdk/gdkx.h"
1259 wxBitmap
wxImage::ConvertToBitmap() const
1263 wxCHECK_MSG( Ok(), bitmap
, "invalid image" );
1265 int width
= GetWidth();
1266 int height
= GetHeight();
1268 bitmap
.SetHeight( height
);
1269 bitmap
.SetWidth( width
);
1273 GdkImage
*data_image
=
1274 gdk_image_new( GDK_IMAGE_FASTEST
, gdk_visual_get_system(), width
, height
);
1276 bitmap
.SetPixmap( gdk_pixmap_new( (GdkWindow
*)&gdk_root_parent
, width
, height
, -1 ) );
1280 GdkImage
*mask_image
= (GdkImage
*) NULL
;
1284 unsigned char *mask_data
= (unsigned char*)malloc( ((width
>> 3)+8) * height
);
1286 mask_image
= gdk_image_new_bitmap( gdk_visual_get_system(), mask_data
, width
, height
);
1288 wxMask
*mask
= new wxMask();
1289 mask
->m_bitmap
= gdk_pixmap_new( (GdkWindow
*)&gdk_root_parent
, width
, height
, 1 );
1291 bitmap
.SetMask( mask
);
1296 GdkVisual
*visual
= gdk_window_get_visual( bitmap
.GetPixmap() );
1297 if (visual
== NULL
) visual
= gdk_window_get_visual( (GdkWindow
*) &gdk_root_parent
);
1298 int bpp
= visual
->depth
;
1299 if ((bpp
== 16) && (visual
->red_mask
!= 0xf800)) bpp
= 15;
1300 if (bpp
< 8) bpp
= 8;
1304 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
1305 byte_order b_o
= RGB
;
1309 GdkVisual
*visual
= gdk_visual_get_system();
1310 if ((visual
->red_mask
> visual
->green_mask
) && (visual
->green_mask
> visual
->blue_mask
)) b_o
= RGB
;
1311 else if ((visual
->red_mask
> visual
->blue_mask
) && (visual
->blue_mask
> visual
->green_mask
)) b_o
= RGB
;
1312 else if ((visual
->blue_mask
> visual
->red_mask
) && (visual
->red_mask
> visual
->green_mask
)) b_o
= BRG
;
1313 else if ((visual
->blue_mask
> visual
->green_mask
) && (visual
->green_mask
> visual
->red_mask
)) b_o
= BGR
;
1314 else if ((visual
->green_mask
> visual
->red_mask
) && (visual
->red_mask
> visual
->blue_mask
)) b_o
= GRB
;
1315 else if ((visual
->green_mask
> visual
->blue_mask
) && (visual
->blue_mask
> visual
->red_mask
)) b_o
= GBR
;
1318 int r_mask
= GetMaskRed();
1319 int g_mask
= GetMaskGreen();
1320 int b_mask
= GetMaskBlue();
1322 unsigned char* data
= GetData();
1325 for (int y
= 0; y
< height
; y
++)
1327 for (int x
= 0; x
< width
; x
++)
1329 int r
= data
[index
];
1331 int g
= data
[index
];
1333 int b
= data
[index
];
1338 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
1339 gdk_image_put_pixel( mask_image
, x
, y
, 1 );
1341 gdk_image_put_pixel( mask_image
, x
, y
, 0 );
1348 GdkColormap
*cmap
= gtk_widget_get_default_colormap();
1349 GdkColor
*colors
= cmap
->colors
;
1350 int max
= 3 * (65536);
1353 for (int i
= 0; i
< cmap
->size
; i
++)
1355 int rdiff
= (r
<< 8) - colors
[i
].red
;
1356 int gdiff
= (g
<< 8) - colors
[i
].green
;
1357 int bdiff
= (b
<< 8) - colors
[i
].blue
;
1358 int sum
= ABS (rdiff
) + ABS (gdiff
) + ABS (bdiff
);
1359 if (sum
< max
) { index
= i
; max
= sum
; }
1362 gdk_image_put_pixel( data_image
, x
, y
, index
);
1368 guint32 pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
1369 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1374 guint32 pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
1375 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1384 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
1385 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
1386 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
1387 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
1388 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
1389 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
1391 gdk_image_put_pixel( data_image
, x
, y
, pixel
);
1400 GdkGC
*data_gc
= gdk_gc_new( bitmap
.GetPixmap() );
1402 gdk_draw_image( bitmap
.GetPixmap(), data_gc
, data_image
, 0, 0, 0, 0, width
, height
);
1404 gdk_image_destroy( data_image
);
1405 gdk_gc_unref( data_gc
);
1411 GdkGC
*mask_gc
= gdk_gc_new( bitmap
.GetMask()->GetBitmap() );
1413 gdk_draw_image( bitmap
.GetMask()->GetBitmap(), mask_gc
, mask_image
, 0, 0, 0, 0, width
, height
);
1415 gdk_image_destroy( mask_image
);
1416 gdk_gc_unref( mask_gc
);
1422 wxImage::wxImage( const wxBitmap
&bitmap
)
1424 wxCHECK_RET( bitmap
.Ok(), "invalid bitmap" );
1426 GdkImage
*gdk_image
= gdk_image_get( bitmap
.GetPixmap(),
1428 bitmap
.GetWidth(), bitmap
.GetHeight() );
1430 wxCHECK_RET( gdk_image
, "couldn't create image" );
1432 Create( bitmap
.GetWidth(), bitmap
.GetHeight() );
1433 char unsigned *data
= GetData();
1437 gdk_image_destroy( gdk_image
);
1438 wxFAIL_MSG( "couldn't create image" );
1442 GdkImage
*gdk_image_mask
= (GdkImage
*) NULL
;
1443 if (bitmap
.GetMask())
1445 gdk_image_mask
= gdk_image_get( bitmap
.GetMask()->GetBitmap(),
1447 bitmap
.GetWidth(), bitmap
.GetHeight() );
1449 SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1452 GdkVisual
*visual
= gdk_window_get_visual( bitmap
.GetPixmap() );
1453 if (visual
== NULL
) visual
= gdk_window_get_visual( (GdkWindow
*) &gdk_root_parent
);
1454 int bpp
= visual
->depth
;
1455 if ((bpp
== 16) && (visual
->red_mask
!= 0xf800)) bpp
= 15;
1457 GdkColormap
*cmap
= gtk_widget_get_default_colormap();
1460 for (int j
= 0; j
< bitmap
.GetHeight(); j
++)
1462 for (int i
= 0; i
< bitmap
.GetWidth(); i
++)
1464 int pixel
= gdk_image_get_pixel( gdk_image
, i
, j
);
1467 data
[pos
] = cmap
->colors
[pixel
].red
>> 8;
1468 data
[pos
+1] = cmap
->colors
[pixel
].green
>> 8;
1469 data
[pos
+2] = cmap
->colors
[pixel
].blue
>> 8;
1470 } else if (bpp
== 15)
1472 data
[pos
] = (pixel
>> 7) & 0xf8;
1473 data
[pos
+1] = (pixel
>> 2) & 0xf8;
1474 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1475 } else if (bpp
== 16)
1477 data
[pos
] = (pixel
>> 8) & 0xf8;
1478 data
[pos
+1] = (pixel
>> 3) & 0xfc;
1479 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1482 data
[pos
] = (pixel
>> 16) & 0xff;
1483 data
[pos
+1] = (pixel
>> 8) & 0xff;
1484 data
[pos
+2] = pixel
& 0xff;
1489 int mask_pixel
= gdk_image_get_pixel( gdk_image_mask
, i
, j
);
1490 if (mask_pixel
== 0)
1502 gdk_image_destroy( gdk_image
);
1503 if (gdk_image_mask
) gdk_image_destroy( gdk_image_mask
);