/* * write_png.h * */ #ifndef WRITE_PNG_H_ #define WRITE_PNG_H_
extern int write_png(const char *file_name, /* Name of file to be written */ unsigned char *datap, /* pointer to image data array */ int width, /* Image width */ int height, /* Image height */ int depth /* Image depth, valid values 1(mono), 3(RGB) */ ); // return zero for success, -1 for error #endif /* WRITE_PNG_H_ */ /* * write_png.cpp * */ #include <fstream> using std::fstream; using std::ios_base; #include <stdlib.h> #include <zlib.h> #include <png.h> #include "write_png.h" typedef unsigned char uchar; //=================================================================== /* structure to store PNG image bytes */ typedef struct { uchar *buffer; size_t size; size_t size_allocated; } mem_encode; static void my_png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) { mem_encode* p=(mem_encode*)png_get_io_ptr(png_ptr); size_t nsize = p->size + length; /* allocate or grow buffer */ if(nsize > p->size_allocated){ int alloc_size = nsize * 2; if(p->buffer) p->buffer = (uchar*)realloc(p->buffer, alloc_size); else p->buffer = (uchar*)malloc(alloc_size); if(!p->buffer) { png_error(png_ptr, "Write Error"); return; } p->size_allocated = alloc_size; } /* copy new bytes to end of buffer */ memcpy(p->buffer + p->size, data, length); p->size += length; } /* This is optional but included to show how png_set_write_fn() is called */ static void my_png_flush(png_structp png_ptr){} int write_png(const char *file_name, /* Name of file to be written */ unsigned char *datap, /* pointer to image data array */ int imgw, /* Image width */ int imgh, /* Image height */ int imgd /* Image depth, valid values 1(mono), 3(RGB) */ ) { // outlen = imgw * imgh * imgd; png_structp pp; // PNG data png_infop info; // PNG image info mem_encode state; /* initialise - put this before png_write_png() call */ state.buffer = NULL; state.size = 0; state.size_allocated = 0; if( !((imgd == 1) || (imgd ==3) || (imgd ==4))) return -1; pp = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if(!pp) return -1; info = png_create_info_struct(pp); if (!info){ png_destroy_write_struct(&pp, 0); return -1; } if (setjmp(png_jmpbuf(pp))){ png_destroy_write_struct(&pp, &info); return -1; } //png_init_io(pp, fp); /* if my_png_flush() is not needed, change the arg to NULL */ png_set_write_fn(pp, &state, my_png_write_data, my_png_flush); png_set_compression_level(pp, Z_BEST_COMPRESSION); png_set_IHDR(pp, info, imgw, imgh, 8, imgd == 1 ? PNG_COLOR_TYPE_GRAY : imgd == 3 ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_set_sRGB(pp, info, PNG_sRGB_INTENT_PERCEPTUAL); png_set_sRGB_gAMA_and_cHRM(pp, info, PNG_INFO_sRGB); png_write_info(pp, info); int iwd = imgw * imgd; for (int y = 0; y < imgh; y++) { png_write_row(pp, (png_byte *)datap); datap += iwd; } png_write_end(pp, info); png_destroy_write_struct(&pp, 0); if (state.buffer && state.size) { fstream Out(file_name, ios_base::out | ios_base::binary); if (Out.good()) Out.write((const char*) state.buffer, state.size); Out.close(); } /* cleanup */ if (state.buffer) free(state.buffer); return 0; } // // End of "$Id$". // _______________________________________________ fltk mailing list fltk@easysw.com http://lists.easysw.com/mailman/listinfo/fltk