void SavePNG( Img const& img, RGBx const* palette, const char* filename ) { assert(img.Format()==Img::INDEXED8BIT); // TODO: set error handler to capture error msg? FILE *fp = fopen(filename, "wb"); if (!fp) { throw Wobbly( "open failed: %s", strerror(errno) ); } png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, (png_voidp)0,0,0 ); if (!png_ptr) { fclose(fp); throw Wobbly( "failed writing PNG (png_create_write() failed)" ); } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { fclose(fp); png_destroy_write_struct(&png_ptr, (png_infopp)NULL); throw Wobbly( "failed writing PNG (png_create_info_struct() failed)" ); } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); throw Wobbly( "failed writing PNG" ); } png_init_io(png_ptr, fp); png_set_IHDR( png_ptr, info_ptr, img.W(), img.H(), 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); { png_color tmp_palette[256]; int i; for(i=0;i<256;++i) { tmp_palette[i].red = palette[i].r; tmp_palette[i].green = palette[i].g; tmp_palette[i].blue = palette[i].b; } png_set_PLTE( png_ptr, info_ptr, tmp_palette, 256 ); } //png_set_bKGD( png_ptr, info_ptr, 0 ); { png_bytep row_pointers[ img.H() ]; int y; for( y=0;y<img.H();++y) row_pointers[y] = (png_bytep)img.PtrConst(0,y); png_set_rows( png_ptr, info_ptr, row_pointers ); png_write_png(png_ptr, info_ptr, 0, NULL); } png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); }