+// temporarily disable the warning C4611 (interaction between '_setjmp' and
+// C++ object destruction is non-portable) - I don't see any dtors here
+#ifdef __VISUALC__
+ #pragma warning(disable:4611)
+#endif /* VC++ */
+
+bool
+wxPNGHandler::LoadFile(wxImage *image,
+ wxInputStream& stream,
+ bool verbose,
+ int WXUNUSED(index))
+{
+ // VZ: as this function uses setjmp() the only fool-proof error handling
+ // method is to use goto (setjmp is not really C++ dtors friendly...)
+
+ unsigned char **lines = NULL;
+ png_infop info_ptr = (png_infop) NULL;
+ wxPNGInfoStruct wxinfo;
+
+ png_uint_32 i, width, height = 0;
+ int bit_depth, color_type, interlace_type;
+
+ wxinfo.verbose = verbose;
+ wxinfo.stream.in = &stream;
+
+ image->Destroy();
+
+ png_structp png_ptr = png_create_read_struct
+ (
+ PNG_LIBPNG_VER_STRING,
+ (voidp) NULL,
+ wx_png_error,
+ wx_png_warning
+ );
+ if (!png_ptr)
+ goto error;
+
+ // NB: please see the comment near wxPNGInfoStruct declaration for
+ // explanation why this line is mandatory
+ png_set_read_fn( png_ptr, &wxinfo, wx_PNG_stream_reader);
+
+ info_ptr = png_create_info_struct( png_ptr );
+ if (!info_ptr)
+ goto error;
+
+ if (setjmp(wxinfo.jmpbuf))
+ goto error;
+
+ png_read_info( png_ptr, info_ptr );
+ png_get_IHDR( png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL );
+
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ png_set_expand( png_ptr );
+
+ // Fix for Bug [ 439207 ] Monochrome PNG images come up black
+ if (bit_depth < 8)
+ png_set_expand( png_ptr );
+
+ png_set_strip_16( png_ptr );
+ png_set_packing( png_ptr );
+ if (png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS))
+ png_set_expand( png_ptr );
+ png_set_filler( png_ptr, 0xff, PNG_FILLER_AFTER );
+
+ image->Create((int)width, (int)height, (bool) false /* no need to init pixels */);
+
+ if (!image->Ok())
+ goto error;
+
+ // initialize all line pointers to NULL to ensure that they can be safely
+ // free()d if an error occurs before all of them could be allocated
+ lines = (unsigned char **)calloc(height, sizeof(unsigned char *));
+ if ( !lines )
+ goto error;
+
+ for (i = 0; i < height; i++)
+ {
+ if ((lines[i] = (unsigned char *)malloc( (size_t)(width * (sizeof(unsigned char) * 4)))) == NULL)
+ goto error;
+ }
+
+ png_read_image( png_ptr, lines );
+ png_read_end( png_ptr, info_ptr );
+
+#if wxUSE_PALETTE
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ const size_t ncolors = info_ptr->num_palette;
+ unsigned char* r = new unsigned char[ncolors];
+ unsigned char* g = new unsigned char[ncolors];
+ unsigned char* b = new unsigned char[ncolors];
+
+ for (size_t j = 0; j < ncolors; j++)