void embryo::savePNG(ostream& inStream, const Picture& inPicture) { // Setup libpng png_structp lPngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (!lPngPtr) throw Exception("Out of memory"); png_infop lInfoPtr = png_create_info_struct(lPngPtr); if (!lInfoPtr) { png_destroy_write_struct(&lPngPtr, 0); throw Exception("Out of memory"); } png_set_error_fn(lPngPtr, 0, &errorCallback, &warningCallback); png_set_write_fn(lPngPtr, &inStream, &writeDataCallback, &flushCallback); // Setup and write the picture infos png_set_IHDR(lPngPtr, lInfoPtr, inPicture.width(), inPicture.height(), 8, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info(lPngPtr, lInfoPtr); // Write the picture datas png_bytep lRasterRow = new png_byte[inPicture.width()]; const double* lSrc = inPicture.pixels(); for(size_t i = 0; i < inPicture.height(); ++i) { png_bytep lDst = lRasterRow; for(size_t j = inPicture.width(); j != 0; ++lSrc, ++lDst, --j) (*lDst) = 255.0 * (*lSrc); png_write_row(lPngPtr, lRasterRow); } png_write_end(lPngPtr, lInfoPtr); // Job done delete[] lRasterRow; png_destroy_write_struct(&lPngPtr, &lInfoPtr); }