1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxImage PNG handler 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) Robert Roebling 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  11 #pragma implementation "imagpng.h" 
  14 // For compilers that support precompilation, includes "wx.h". 
  15 #include "wx/wxprec.h" 
  27 #include "wx/imagpng.h" 
  28 #include "wx/bitmap.h" 
  33 #include "wx/filefn.h" 
  34 #include "wx/wfstream.h" 
  36 #include "wx/module.h" 
  51 //----------------------------------------------------------------------------- 
  53 //----------------------------------------------------------------------------- 
  55 IMPLEMENT_DYNAMIC_CLASS(wxPNGHandler
,wxImageHandler
) 
  59 #if defined(__VISAGECPP__) 
  60 #define LINKAGEMODE _Optlink 
  65 static void LINKAGEMODE 
_PNG_stream_reader( png_structp png_ptr
, png_bytep data
, png_size_t length 
) 
  67     ((wxInputStream
*) png_get_io_ptr( png_ptr 
)) -> Read(data
, length
); 
  70 static void LINKAGEMODE 
_PNG_stream_writer( png_structp png_ptr
, png_bytep data
, png_size_t length 
) 
  72     ((wxOutputStream
*) png_get_io_ptr( png_ptr 
)) -> Write(data
, length
); 
  76 // so that the libpng doesn't send anything on stderr 
  78 LINKAGEMODE 
png_silent_error(png_structp png_ptr
, png_const_charp 
WXUNUSED(message
)) 
  80 #ifdef USE_FAR_KEYWORD 
  83       png_memcpy(jmpbuf
,png_ptr
->jmpbuf
,sizeof(jmp_buf)); 
  87    longjmp(png_ptr
->jmpbuf
, 1); 
  92 LINKAGEMODE 
png_silent_warning(png_structp 
WXUNUSED(png_ptr
), png_const_charp 
WXUNUSED(message
)) 
  96 bool wxPNGHandler::LoadFile( wxImage 
*image
, wxInputStream
& stream
, bool verbose
, int WXUNUSED(index
) ) 
  98     // VZ: as this function uses setjmp() the only fool proof error handling 
  99     //     method is to use goto (setjmp is not really C++ dtors friendly...) 
 101     unsigned char **lines
; 
 103     png_infop info_ptr 
= (png_infop
) NULL
; 
 107     png_structp png_ptr 
= png_create_read_struct( PNG_LIBPNG_VER_STRING
, 
 109         (png_error_ptr
) NULL
, 
 110         (png_error_ptr
) NULL 
); 
 114     // the file example.c explain how to guess if the stream is a png image 
 115     if (!verbose
) png_set_error_fn(png_ptr
, (png_voidp
)NULL
, png_silent_error
, png_silent_warning
); 
 117     info_ptr 
= png_create_info_struct( png_ptr 
); 
 121     if (setjmp(png_ptr
->jmpbuf
)) 
 124     if (info_ptr
->color_type 
== PNG_COLOR_TYPE_RGB_ALPHA
) 
 127     png_set_read_fn( png_ptr
, &stream
, _PNG_stream_reader
); 
 129     png_uint_32 width
,height
; 
 130     int bit_depth
,color_type
,interlace_type
; 
 132     png_read_info( png_ptr
, info_ptr 
); 
 133     png_get_IHDR( png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
, &interlace_type
, (int*) NULL
, (int*) NULL 
); 
 135     if (color_type 
== PNG_COLOR_TYPE_PALETTE
) 
 136         png_set_expand( png_ptr 
); 
 138     png_set_strip_16( png_ptr 
); 
 139     png_set_packing( png_ptr 
); 
 140     if (png_get_valid( png_ptr
, info_ptr
, PNG_INFO_tRNS
)) 
 141         png_set_expand( png_ptr 
); 
 142     png_set_filler( png_ptr
, 0xff, PNG_FILLER_AFTER 
); 
 144     image
->Create( (int)width
, (int)height 
); 
 149     lines 
= (unsigned char **)malloc( (size_t)(height 
* sizeof(unsigned char *)) ); 
 153     for (i 
= 0; i 
< height
; i
++) 
 155         if ((lines
[i
] = (unsigned char *)malloc( (size_t)(width 
* (sizeof(unsigned char) * 4)))) == NULL
) 
 157             for ( unsigned int n 
= 0; n 
< i
; n
++ ) 
 163     // loaded successfully! 
 166         png_read_image( png_ptr
, lines 
); 
 167         png_read_end( png_ptr
, info_ptr 
); 
 168         png_destroy_read_struct( &png_ptr
, &info_ptr
, (png_infopp
) NULL 
); 
 169         unsigned char *ptr 
= image
->GetData(); 
 170         if ((color_type 
== PNG_COLOR_TYPE_GRAY
) || 
 171             (color_type 
== PNG_COLOR_TYPE_GRAY_ALPHA
)) 
 173             for (unsigned int y 
= 0; y 
< height
; y
++) 
 175                 unsigned char *ptr2 
= lines
[y
]; 
 176                 for (unsigned int x 
= 0; x 
< width
; x
++) 
 178                     unsigned char r 
= *ptr2
++; 
 179                     unsigned char a 
= *ptr2
++; 
 198             for (unsigned int y 
= 0; y 
< height
; y
++) 
 200                 unsigned char *ptr2 
= lines
[y
]; 
 201                 for (unsigned int x 
= 0; x 
< width
; x
++) 
 203                     unsigned char r 
= *ptr2
++; 
 204                     unsigned char g 
= *ptr2
++; 
 205                     unsigned char b 
= *ptr2
++; 
 206                     unsigned char a 
= *ptr2
++; 
 216                         if ((r 
== 255) && (g 
== 0) && (b 
== 255)) r 
= 254; 
 225         for ( unsigned int j 
= 0; j 
< height
; j
++ ) 
 231             image
->SetMaskColour( 255, 0, 255 ); 
 235             image
->SetMask( FALSE 
); 
 242     lines 
= NULL
; // called from before it was set 
 245        wxLogError(_("Couldn't load a PNG image - file is corrupted or not enough memory.")); 
 261             png_destroy_read_struct( &png_ptr
, &info_ptr
, (png_infopp
) NULL 
); 
 265             png_destroy_read_struct( &png_ptr
, (png_infopp
) NULL
, (png_infopp
) NULL 
); 
 271 bool wxPNGHandler::SaveFile( wxImage 
*image
, wxOutputStream
& stream
, bool verbose 
) 
 274         png_structp png_ptr 
= png_create_write_struct( PNG_LIBPNG_VER_STRING
, NULL
, NULL
, NULL
); 
 280         if (!verbose
) png_set_error_fn(png_ptr
, (png_voidp
)NULL
, png_silent_error
, png_silent_warning
); 
 282         png_infop info_ptr 
= png_create_info_struct(png_ptr
); 
 283         if (info_ptr 
== NULL
) 
 285             png_destroy_write_struct( &png_ptr
, (png_infopp
)NULL 
); 
 289         if (setjmp(png_ptr
->jmpbuf
)) 
 291             png_destroy_write_struct( &png_ptr
, (png_infopp
)NULL 
); 
 295         png_set_write_fn( png_ptr
, &stream
, _PNG_stream_writer
, NULL
); 
 297         png_set_IHDR( png_ptr
, info_ptr
, image
->GetWidth(), image
->GetHeight(), 8, 
 298             PNG_COLOR_TYPE_RGB_ALPHA
, PNG_INTERLACE_NONE
, 
 299             PNG_COMPRESSION_TYPE_BASE
, PNG_FILTER_TYPE_BASE
); 
 306         png_set_sBIT( png_ptr
, info_ptr
, &sig_bit 
); 
 307         png_write_info( png_ptr
, info_ptr 
); 
 308         png_set_shift( png_ptr
, &sig_bit 
); 
 309         png_set_packing( png_ptr 
); 
 311         unsigned char *data 
= (unsigned char *)malloc( image
->GetWidth()*4 ); 
 314             png_destroy_write_struct( &png_ptr
, (png_infopp
)NULL 
); 
 318         for (int y 
= 0; y 
< image
->GetHeight(); y
++) 
 320             unsigned char *ptr 
= image
->GetData() + (y 
* image
->GetWidth() * 3); 
 321             for (int x 
= 0; x 
< image
->GetWidth(); x
++) 
 323                 data
[(x 
<< 2) + 0] = *ptr
++; 
 324                 data
[(x 
<< 2) + 1] = *ptr
++; 
 325                 data
[(x 
<< 2) + 2] = *ptr
++; 
 326                 if (( !image
->HasMask() ) || \
 
 327                     (data
[(x 
<< 2) + 0] != image
->GetMaskRed()) || \
 
 328                     (data
[(x 
<< 2) + 1] != image
->GetMaskGreen()) || \
 
 329                     (data
[(x 
<< 2) + 2] != image
->GetMaskBlue())) 
 331                     data
[(x 
<< 2) + 3] = 255; 
 335                     data
[(x 
<< 2) + 3] = 0; 
 338             png_bytep row_ptr 
= data
; 
 339             png_write_rows( png_ptr
, &row_ptr
, 1 ); 
 343         png_write_end( png_ptr
, info_ptr 
); 
 344         png_destroy_write_struct( &png_ptr
, (png_infopp
)&info_ptr 
); 
 349 bool wxPNGHandler::DoCanRead( wxInputStream
& stream 
) 
 351     unsigned char hdr
[4]; 
 353     stream
.Read(&hdr
, 4); 
 354     stream
.SeekI(-4, wxFromCurrent
); 
 355     return (hdr
[0] == 0x89 && hdr
[1] == 'P' && hdr
[2] == 'N' && hdr
[3] == 'G'); 
 358 #endif  // wxUSE_STREAMS 
 360 #endif  // wxUSE_LIBPNG