+ png_set_write_fn( png_ptr, &wxinfo, wx_PNG_stream_writer, NULL);
+
+ const int iHeight = image->GetHeight();
+ const int iWidth = image->GetWidth();
+
+ const bool bHasPngFormatOption
+ = image->HasOption(wxIMAGE_OPTION_PNG_FORMAT);
+
+ int iColorType = bHasPngFormatOption
+ ? image->GetOptionInt(wxIMAGE_OPTION_PNG_FORMAT)
+ : wxPNG_TYPE_COLOUR;
+
+ bool bHasAlpha = image->HasAlpha();
+ bool bHasMask = image->HasMask();
+
+ bool bUsePalette = iColorType == wxPNG_TYPE_PALETTE
+#if wxUSE_PALETTE
+ || (!bHasPngFormatOption && image->HasPalette() )
+#endif
+ ;
+
+ png_color_8 mask = { 0, 0, 0, 0, 0 };
+
+ if (bHasMask)
+ {
+ mask.red = image->GetMaskRed();
+ mask.green = image->GetMaskGreen();
+ mask.blue = image->GetMaskBlue();
+ }
+
+ PaletteMap palette;
+
+ if (bUsePalette)
+ {
+ png_color png_rgb [PNG_MAX_PALETTE_LENGTH];
+ png_byte png_trans[PNG_MAX_PALETTE_LENGTH];
+
+ const unsigned char *pColors = image->GetData();
+ const unsigned char* pAlpha = image->GetAlpha();
+
+ if (bHasMask && !pAlpha)
+ {
+ // Mask must be first
+ PaletteAdd(&palette, mask);
+ }
+
+ for (int y = 0; y < iHeight; y++)
+ {
+ for (int x = 0; x < iWidth; x++)
+ {
+ png_color_8 rgba;
+
+ rgba.red = *pColors++;
+ rgba.green = *pColors++;
+ rgba.blue = *pColors++;
+ rgba.gray = 0;
+ rgba.alpha = (pAlpha && !bHasMask) ? *pAlpha++ : 0;
+
+ // save in our palette
+ long index = PaletteAdd(&palette, rgba);
+
+ if (index < PNG_MAX_PALETTE_LENGTH)
+ {
+ // save in libpng's palette
+ png_rgb[index].red = rgba.red;
+ png_rgb[index].green = rgba.green;
+ png_rgb[index].blue = rgba.blue;
+ png_trans[index] = rgba.alpha;
+ }
+ else
+ {
+ bUsePalette = false;
+ break;
+ }
+ }
+ }
+
+ if (bUsePalette)
+ {
+ png_set_PLTE(png_ptr, info_ptr, png_rgb, palette.size());
+
+ if (bHasMask && !pAlpha)
+ {
+ wxASSERT(PaletteFind(palette, mask) == 0);
+ png_trans[0] = 0;
+ png_set_tRNS(png_ptr, info_ptr, png_trans, 1, NULL);
+ }
+ else if (pAlpha && !bHasMask)
+ {
+ png_set_tRNS(png_ptr, info_ptr, png_trans, palette.size(), NULL);
+ }
+ }
+ }
+
+ /*
+ If saving palettised was requested but it was decided we can't use a
+ palette then reset the colour type to RGB.
+ */
+ if (!bUsePalette && iColorType == wxPNG_TYPE_PALETTE)
+ {
+ iColorType = wxPNG_TYPE_COLOUR;
+ }
+
+ bool bUseAlpha = !bUsePalette && (bHasAlpha || bHasMask);