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" 
  24 #include "../png/png.h" 
  25 #include "wx/filefn.h" 
  27 //----------------------------------------------------------------------------- 
  29 //----------------------------------------------------------------------------- 
  31 class wxImageRefData
: public wxObjectRefData
 
  36   ~wxImageRefData(void); 
  40   unsigned char  *m_data
; 
  42   unsigned char   m_maskRed
,m_maskGreen
,m_maskBlue
; 
  46 wxImageRefData::wxImageRefData(void) 
  50     m_data 
= (unsigned char*) NULL
; 
  58 wxImageRefData::~wxImageRefData(void) 
  60     if (m_data
) free( m_data 
); 
  63 wxList 
wxImage::sm_handlers
; 
  65 //----------------------------------------------------------------------------- 
  67 #define M_IMGDATA ((wxImageRefData *)m_refData) 
  69 #if !USE_SHARED_LIBRARIES 
  70 IMPLEMENT_DYNAMIC_CLASS(wxImage
, wxObject
) 
  77 wxImage::wxImage( int width
, int height 
) 
  79     Create( width
, height 
); 
  82 wxImage::wxImage( const wxString
& name
, long type 
) 
  84     LoadFile( name
, type 
); 
  87 wxImage::wxImage( const wxImage
& image 
)   
  92 wxImage::wxImage( const wxImage
* image 
)   
  94     if (image
) Ref(*image
);  
  97 void wxImage::Create( int width
, int height 
) 
  99     m_refData 
= new wxImageRefData(); 
 101     M_IMGDATA
->m_data 
= (unsigned char *) malloc( width
*height
*3 ); 
 102     if (M_IMGDATA
->m_data
) 
 104         for (int l 
= 0; l 
< width
*height
*3; l
++) M_IMGDATA
->m_data
[l
] = 0; 
 106         M_IMGDATA
->m_width 
= width
; 
 107         M_IMGDATA
->m_height 
= height
; 
 108         M_IMGDATA
->m_ok 
= TRUE
; 
 116 void wxImage::Destroy() 
 121 bool wxImage::Ok() const  
 123     return (M_IMGDATA 
&& M_IMGDATA
->m_ok
);  
 126 char unsigned *wxImage::GetData() const 
 128     if (!Ok()) return (char unsigned *)NULL
; 
 130     return M_IMGDATA
->m_data
; 
 133 void wxImage::SetData( char unsigned *WXUNUSED(data
) ) 
 137 void wxImage::SetMaskColour( unsigned char r
, unsigned char g
, unsigned char b 
) 
 141     M_IMGDATA
->m_maskRed 
= r
; 
 142     M_IMGDATA
->m_maskGreen 
= g
; 
 143     M_IMGDATA
->m_maskBlue 
= b
; 
 144     M_IMGDATA
->m_hasMask 
= TRUE
; 
 147 unsigned char wxImage::GetMaskRed() const 
 151     return M_IMGDATA
->m_maskRed
; 
 154 unsigned char wxImage::GetMaskGreen() const 
 158     return M_IMGDATA
->m_maskGreen
; 
 161 unsigned char wxImage::GetMaskBlue() const 
 165     return M_IMGDATA
->m_maskBlue
; 
 168 void wxImage::SetMask( bool mask 
) 
 172     M_IMGDATA
->m_hasMask 
= mask
; 
 175 bool wxImage::HasMask() const 
 177     if (!Ok()) return FALSE
; 
 179     return M_IMGDATA
->m_hasMask
; 
 182 int wxImage::GetWidth() const  
 184     return (M_IMGDATA 
? M_IMGDATA
->m_width 
: 0);  
 187 int wxImage::GetHeight() const  
 189     return (M_IMGDATA 
? M_IMGDATA
->m_height 
: 0);  
 192 bool wxImage::LoadFile( const wxString
& filename
, long type 
) 
 196     if (!wxFileExists(filename
)) 
 198         wxLogWarning( "Image file does not exist." ); 
 203     m_refData 
= new wxImageRefData
; 
 205     wxImageHandler 
*handler 
= FindHandler(type
); 
 209         wxLogWarning( "No image handler for type %d defined.", type 
); 
 214     return handler
->LoadFile( this, filename 
); 
 217 bool wxImage::SaveFile( const wxString
& filename
, int type 
) 
 219     wxImageHandler 
*handler 
= FindHandler(type
); 
 223       wxLogWarning( "No image handler for type %d defined.", type 
); 
 228     return handler
->SaveFile( this, filename 
); 
 231 void wxImage::AddHandler( wxImageHandler 
*handler 
) 
 233     sm_handlers
.Append( handler 
); 
 236 void wxImage::InsertHandler( wxImageHandler 
*handler 
) 
 238     sm_handlers
.Insert( handler 
); 
 241 bool wxImage::RemoveHandler( const wxString
& name 
) 
 243     wxImageHandler 
*handler 
= FindHandler(name
); 
 246         sm_handlers
.DeleteObject(handler
); 
 253 wxImageHandler 
*wxImage::FindHandler( const wxString
& name 
) 
 255     wxNode 
*node 
= sm_handlers
.First(); 
 258         wxImageHandler 
*handler 
= (wxImageHandler
*)node
->Data(); 
 259         if (handler
->GetName() == name
) return handler
; 
 262     return (wxImageHandler 
*)NULL
; 
 265 wxImageHandler 
*wxImage::FindHandler( const wxString
& extension
, long bitmapType 
) 
 267     wxNode 
*node 
= sm_handlers
.First(); 
 270         wxImageHandler 
*handler 
= (wxImageHandler
*)node
->Data(); 
 271         if ( handler
->GetExtension() == extension 
&& 
 272             (bitmapType 
== -1 || handler
->GetType() == bitmapType
) ) 
 276     return (wxImageHandler
*)NULL
; 
 279 wxImageHandler 
*wxImage::FindHandler( long bitmapType 
) 
 281     wxNode 
*node 
= sm_handlers
.First(); 
 284         wxImageHandler 
*handler 
= (wxImageHandler 
*)node
->Data(); 
 285         if (handler
->GetType() == bitmapType
) return handler
; 
 291 void wxImage::InitStandardHandlers() 
 293     AddHandler( new wxBMPHandler 
); 
 294     AddHandler( new wxPNGHandler 
); 
 297 void wxImage::CleanUpHandlers() 
 299     wxNode 
*node 
= sm_handlers
.First(); 
 302         wxImageHandler 
*handler 
= (wxImageHandler 
*)node
->Data(); 
 303         wxNode 
*next 
= node
->Next(); 
 310 //----------------------------------------------------------------------------- 
 312 //----------------------------------------------------------------------------- 
 314 #if !USE_SHARED_LIBRARIES 
 315 IMPLEMENT_DYNAMIC_CLASS(wxImageHandler
,wxObject
) 
 318 bool wxImageHandler::LoadFile( wxImage 
*WXUNUSED(image
), const wxString
& WXUNUSED(name
) ) 
 323 bool wxImageHandler::SaveFile( wxImage 
*WXUNUSED(image
), const wxString
& WXUNUSED(name
) ) 
 328 //----------------------------------------------------------------------------- 
 330 //----------------------------------------------------------------------------- 
 332 #if !USE_SHARED_LIBRARIES 
 333 IMPLEMENT_DYNAMIC_CLASS(wxPNGHandler
,wxImageHandler
) 
 336 bool wxPNGHandler::LoadFile( wxImage 
*image
, const wxString
& name 
) 
 341    unsigned char      *ptr
, **lines
, *ptr2
; 
 342    int                 transp
,bit_depth
,color_type
,interlace_type
; 
 343    png_uint_32         width
, height
; 
 349    png_ptr 
= png_create_read_struct( PNG_LIBPNG_VER_STRING
, NULL
, NULL
, NULL 
); 
 350    if (!png_ptr
) return FALSE
; 
 352    info_ptr 
= png_create_info_struct( png_ptr 
); 
 355      png_destroy_read_struct( &png_ptr
, NULL
, NULL 
); 
 359    if (setjmp(png_ptr
->jmpbuf
)) 
 361      png_destroy_read_struct( &png_ptr
, &info_ptr
, NULL 
); 
 365    if (info_ptr
->color_type 
== PNG_COLOR_TYPE_RGB_ALPHA
) 
 367      png_destroy_read_struct( &png_ptr
, &info_ptr
, NULL 
); 
 371    f 
= fopen( name
, "rb" ); 
 372    png_init_io( png_ptr
, f 
); 
 374    png_read_info( png_ptr
, info_ptr 
); 
 375    png_get_IHDR( png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
, &interlace_type
, NULL
, NULL 
); 
 377    if (color_type 
== PNG_COLOR_TYPE_PALETTE
) png_set_expand( png_ptr 
); 
 379    png_set_strip_16( png_ptr 
); 
 380    png_set_packing( png_ptr 
); 
 381    if (png_get_valid( png_ptr
, info_ptr
, PNG_INFO_tRNS
)) png_set_expand( png_ptr 
); 
 382    png_set_filler( png_ptr
, 0xff, PNG_FILLER_AFTER 
); 
 384    image
->Create( width
, height 
); 
 388      png_destroy_read_struct( &png_ptr
, &info_ptr
, NULL 
); 
 392    lines 
= (unsigned char **)malloc( height 
* sizeof(unsigned char *) ); 
 396      png_destroy_read_struct( &png_ptr
, &info_ptr
, NULL 
); 
 400    for (i 
= 0; i 
< height
; i
++) 
 402      if ((lines
[i
] = (unsigned char *)malloc(width 
* (sizeof(unsigned char) * 4))) == NULL
) 
 405        for (unsigned int n 
= 0; n 
< i
; n
++) free( lines
[n
] ); 
 407        png_destroy_read_struct( &png_ptr
, &info_ptr
, NULL 
); 
 412    png_read_image( png_ptr
, lines 
); 
 413    png_destroy_read_struct( &png_ptr
, &info_ptr
, NULL 
); 
 414    ptr 
= image
->GetData(); 
 415    if ((color_type 
== PNG_COLOR_TYPE_GRAY
) || 
 416        (color_type 
== PNG_COLOR_TYPE_GRAY_ALPHA
)) 
 418         for (unsigned int y 
= 0; y 
< height
; y
++) 
 421              for (unsigned int x 
= 0; x 
< width
; x
++) 
 423                   unsigned char r 
= *ptr2
++; 
 424                   unsigned char a 
= *ptr2
++; 
 443         for (unsigned int y 
= 0; y 
< height
; y
++) 
 446              for (unsigned int x 
= 0; x 
< width
; x
++) 
 448                   unsigned char r 
= *ptr2
++; 
 449                   unsigned char g 
= *ptr2
++; 
 450                   unsigned char b 
= *ptr2
++; 
 451                   unsigned char a 
= *ptr2
++; 
 461                        if ((r 
== 255) && (g 
== 0) && (b 
== 255)) r 
= 254; 
 469    for (i 
= 0; i 
< height
; i
++) free( lines
[i
] ); 
 472      image
->SetMaskColour( 255, 0, 255 ); 
 474      image
->SetMask( FALSE 
); 
 480 bool wxPNGHandler::SaveFile( wxImage 
*image
, const wxString
& name 
) 
 482   FILE *f 
= fopen( name
, "wb" ); 
 485     png_structp png_ptr 
= png_create_write_struct( PNG_LIBPNG_VER_STRING
, NULL
, NULL
, NULL
); 
 492     png_infop info_ptr 
= png_create_info_struct(png_ptr
); 
 493     if (info_ptr 
== NULL
) 
 496       png_destroy_write_struct( &png_ptr
, (png_infopp
)NULL 
); 
 500     if (setjmp(png_ptr
->jmpbuf
)) 
 503       png_destroy_write_struct( &png_ptr
, (png_infopp
)NULL 
); 
 507     png_init_io( png_ptr
, f 
); 
 508     png_set_IHDR( png_ptr
, info_ptr
, image
->GetWidth(), image
->GetHeight(), 8, 
 509                   PNG_COLOR_TYPE_RGB_ALPHA
, PNG_INTERLACE_NONE
, 
 510                   PNG_COMPRESSION_TYPE_BASE
, PNG_FILTER_TYPE_BASE
); 
 517     png_set_sBIT( png_ptr
, info_ptr
, &sig_bit 
); 
 518     png_write_info( png_ptr
, info_ptr 
); 
 519     png_set_shift( png_ptr
, &sig_bit 
); 
 520     png_set_packing( png_ptr 
); 
 522     unsigned char *data 
= (unsigned char *)malloc( image
->GetWidth()*4 ); 
 526       png_destroy_write_struct( &png_ptr
, (png_infopp
)NULL 
); 
 530     for (int y 
= 0; y 
< image
->GetHeight(); y
++) 
 532       unsigned char *ptr 
= image
->GetData() + (y 
* image
->GetWidth() * 3); 
 533       for (int x 
= 0; x 
< image
->GetWidth(); x
++) 
 535         data
[(x 
<< 2) + 0] = *ptr
++; 
 536         data
[(x 
<< 2) + 1] = *ptr
++; 
 537         data
[(x 
<< 2) + 2] = *ptr
++; 
 538         if ((data
[(x 
<< 2) + 0] == image
->GetMaskRed()) && 
 539             (data
[(x 
<< 2) + 1] == image
->GetMaskGreen()) && 
 540             (data
[(x 
<< 2) + 2] == image
->GetMaskBlue())) 
 541           data
[(x 
<< 2) + 3] = 0; 
 543           data
[(x 
<< 2) + 3] = 255; 
 545       png_bytep row_ptr 
= data
; 
 546       png_write_rows( png_ptr
, &row_ptr
, 1 ); 
 549     png_write_end( png_ptr
, info_ptr 
); 
 550     png_destroy_write_struct( &png_ptr
, (png_infopp
)NULL 
); 
 557 //----------------------------------------------------------------------------- 
 559 //----------------------------------------------------------------------------- 
 561 #if !USE_SHARED_LIBRARIES 
 562 IMPLEMENT_DYNAMIC_CLASS(wxBMPHandler
,wxImageHandler
) 
 565 bool wxBMPHandler::LoadFile( wxImage 
*image
, const wxString
& name 
) 
 568    unsigned char      *data
, *ptr
; 
 569    int                 done
, i
, bpp
, planes
, comp
, ncolors
, line
, column
, 
 570                        linesize
, linepos
, rshift 
= 0, gshift 
= 0, bshift 
= 0; 
 573    long int            dbuf
[4], dword
, rmask 
= 0, gmask 
= 0, bmask 
= 0, offset
, 
 578         unsigned char       r
, g
, b
; 
 585 #define BI_BITFIELDS 3 
 590    file 
= fopen(name
, "r"); 
 596     * Reading the bmp header  
 599    fread(&bbuf
, 1, 2, file
); 
 601    fread(dbuf
, 4, 4, file
); 
 606    fread(dbuf
, 4, 2, file
); 
 607    int width 
= (int)dbuf
[0]; 
 608    int height 
= (int)dbuf
[1]; 
 611         fprintf(stderr
, "IMLIB ERROR: Image width > 32767 pixels for file\n"); 
 617         fprintf(stderr
, "IMLIB ERROR: Image height > 32767 pixels for file\n"); 
 621    fread(&word
, 2, 1, file
); 
 623    fread(&word
, 2, 1, file
); 
 625    if (bpp 
!= 1 && bpp 
!= 4 && bpp 
!= 8 && bpp 
&& 16 && bpp 
!= 24 && bpp 
!= 32) 
 627         fprintf(stderr
, "IMLIB ERROR: unknown bitdepth in file\n"); 
 631    fread(dbuf
, 4, 4, file
); 
 633    if (comp 
!= BI_RGB 
&& comp 
!= BI_RLE4 
&& comp 
!= BI_RLE8 
&& comp 
!= BI_BITFIELDS
) 
 635         fprintf(stderr
, "IMLIB ERROR: unknown encoding in Windows BMP file\n"); 
 639    fread(dbuf
, 4, 2, file
); 
 640    ncolors 
= (int)dbuf
[0]; 
 643    /* some more sanity checks */ 
 644    if (((comp 
== BI_RLE4
) && (bpp 
!= 4)) || ((comp 
== BI_RLE8
) && (bpp 
!= 8)) || ((comp 
== BI_BITFIELDS
) && (bpp 
!= 16 && bpp 
!= 32))) 
 646         fprintf(stderr
, "IMLIB ERROR: encoding of BMP doesn't match bitdepth\n"); 
 652         cmap 
= (struct _cmap 
*)malloc(sizeof(struct _cmap
) * ncolors
); 
 656              fprintf(stderr
, "IMLIB ERROR: Cannot allocate RAM for color map in BMP file\n"); 
 664    image
->Create( width
, height 
);       
 665    ptr 
= image
->GetData(); 
 668         fprintf(stderr
, "IMLIB ERROR: Cannot allocate RAM for RGB data in file\n"); 
 676     * Reading the palette, if it exists. 
 678    if (bpp 
< 16 && ncolors 
!= 0) 
 680         for (i 
= 0; i 
< ncolors
; i
++) 
 682              fread(bbuf
, 1, 4, file
); 
 688    else if (bpp 
== 16 || bpp 
== 32) 
 690         if (comp 
== BI_BITFIELDS
) 
 694              fread(dbuf
, 4, 3, file
); 
 698              /* find shift amount.. ugly, but i can't think of a better way */ 
 699              for (bit 
= 0; bit 
< bpp
; bit
++) 
 701                   if (bmask 
& (1 << bit
)) 
 703                   if (gmask 
& (1 << bit
)) 
 705                   if (rmask 
& (1 << bit
)) 
 730     * REading the image data 
 732    fseek(file
, offset
, SEEK_SET
); 
 735    /* set the whole image to the background color */ 
 736    if (bpp 
< 16 && (comp 
== BI_RLE4 
|| comp 
== BI_RLE8
)) 
 738         for (i 
= 0; i 
< width 
* height
; i
++) 
 748 #define poffset (line * width * 3 + column * 3) 
 751     * BMPs are stored upside down... hmmmmmmmmmm.... 
 754    linesize 
= ((width 
* bpp 
+ 31) / 32) * 4; 
 755    for (line 
= (height 
- 1); line 
>= 0; line
--) 
 758         for (column 
= 0; column 
< width
;) 
 770                        for (bit 
= 0; bit 
< 8; bit
++) 
 772                             index 
= ((byte 
& (0x80 >> bit
)) ? 1 : 0); 
 773                             ptr
[poffset
] = cmap
[index
].r
; 
 774                             ptr
[poffset 
+ 1] = cmap
[index
].g
; 
 775                             ptr
[poffset 
+ 2] = cmap
[index
].b
; 
 783                             fprintf(stderr
, "can't deal with 4bit encoded yet.\n"); 
 792                             for (nibble 
= 0; nibble 
< 2; nibble
++) 
 794                                  index 
= ((byte 
& (0xF0 >> nibble 
* 4)) >> (!nibble 
* 4)); 
 797                                  ptr
[poffset
] = cmap
[index
].r
; 
 798                                  ptr
[poffset 
+ 1] = cmap
[index
].g
; 
 799                                  ptr
[poffset 
+ 2] = cmap
[index
].b
; 
 816 /*                                    column = width; */ 
 827                                       linepos 
= column 
* bpp 
/ 8; 
 835                                       for (i 
= 0; i 
< absolute
; i
++) 
 839                                            ptr
[poffset
] = cmap
[byte
].r
; 
 840                                            ptr
[poffset 
+ 1] = cmap
[byte
].g
; 
 841                                            ptr
[poffset 
+ 2] = cmap
[byte
].b
; 
 850                                  for (i 
= 0; i 
< first
; i
++) 
 852                                       ptr
[poffset
] = cmap
[byte
].r
; 
 853                                       ptr
[poffset 
+ 1] = cmap
[byte
].g
; 
 854                                       ptr
[poffset 
+ 2] = cmap
[byte
].b
; 
 862                             ptr
[poffset
] = cmap
[byte
].r
; 
 863                             ptr
[poffset 
+ 1] = cmap
[byte
].g
; 
 864                             ptr
[poffset 
+ 2] = cmap
[byte
].b
; 
 872                   linepos 
+= fread(&bbuf
, 1, 3, file
); 
 873                   ptr
[poffset
] = (unsigned char)bbuf
[2]; 
 874                   ptr
[poffset 
+ 1] = (unsigned char)bbuf
[1]; 
 875                   ptr
[poffset 
+ 2] = (unsigned char)bbuf
[0]; 
 882                   linepos 
+= fread(&word
, 2, 1, file
); 
 883                   temp 
= (word 
& rmask
) >> rshift
; 
 885                   temp 
= (word 
& gmask
) >> gshift
; 
 886                   ptr
[poffset 
+ 1] = temp
; 
 887                   temp 
= (word 
& bmask
) >> gshift
; 
 888                   ptr
[poffset 
+ 2] = temp
; 
 895                   linepos 
+= fread(&dword
, 4, 1, file
); 
 896                   temp 
= (dword 
& rmask
) >> rshift
; 
 898                   temp 
= (dword 
& gmask
) >> gshift
; 
 899                   ptr
[poffset 
+ 1] = temp
; 
 900                   temp 
= (dword 
& bmask
) >> bshift
; 
 901                   ptr
[poffset 
+ 2] = temp
; 
 905         while ((linepos 
< linesize
) && (comp 
!= 1) && (comp 
!= 2)) 
 907              int                 temp 
= fread(&byte
, 1, 1, file
); 
 914    if (cmap
) free(cmap
); 
 916    image
->SetMask( FALSE 
);