/*
* 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
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk