/* This file is placed into public domain. There is no warranty of any kind for any purpose. Read http://z0b.kapsi.fi/snippets.php before using this code. Thank you. */ /* Saves a 24/32-bit PNG image, returns false if fails. 'bpp' must be either 3 (for RGB) or 4 (for RGBA) image. */ bool savePNG(const char *fileName, const uint32_t w, const uint32_t h, const uint8_t bpp, const uint8_t *data) { // sanity checks if (!fileName || !data || w < 1 || h < 1 || (bpp != 3 && bpp != 4)) return false; FILE *f = fopen(fileName, "wb"); if (!f) return false; // initialize writing structures png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { fclose(f); return false; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, NULL); fclose(f); return false; } // setup error handling if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); fclose(f); return false; } // initialize output png_init_io(png_ptr, f); // this is optional, set the zlib compression level png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); // set the image properties png_set_IHDR(png_ptr, info_ptr, w, h, 8, (bpp == 3) ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info(png_ptr, info_ptr); // write the image data (one scanline at a time, it can be customized easily // and we don't have to mess with row pointers) const uint32_t stride = w * bpp; png_byte *row = (png_byte *)data; for (uint32_t y = 0; y < h; y++) { png_write_row(png_ptr, row); row += stride; } // done png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); fclose(f); return true; }