diff -r 9daa832ab9c4 -r 082bfaf38cf0 render_png.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/render_png.c Fri Jun 06 18:35:46 2008 +0300 @@ -0,0 +1,136 @@ +#include + +#include + +#include "common.h" +#include "render_internal.h" +#include "render_png.h" + +struct render_png { + // libpng handles + png_structp png_ptr; + png_infop info_ptr; + + // our render op, containing the I/O callbacks + struct render *render; +}; + +void _render_png_write(png_structp png_ptr, png_bytep data, png_size_t length) { + struct render_png *ctx = png_get_io_ptr(png_ptr); + + if (ctx->render->io_write_fn) + if (ctx->render->io_write_fn(data, length, ctx->render->cb_arg)) { + // error, doesn't return + png_error(png_ptr, "_render_png_write: io_write_fn"); + } +} + +void _render_png_flush(png_structp png_ptr) { + struct render_png *ctx = png_get_io_ptr(png_ptr); + + if (ctx->render->io_flush_fn) + if (ctx->render->io_flush_fn(ctx->render->cb_arg)) { + // error, doesn't return + png_error(png_ptr, "_render_png_flush: io_flush_fn"); + } +} + +void _render_png_free (struct render_png *ctx) { + if (ctx) + png_destroy_write_struct(&ctx->png_ptr, &ctx->info_ptr); + + free(ctx); +} + + +struct render_png *render_png_init (struct render *render) { + + struct render_png *ctx = NULL; + + // calloc the render_png + if (!(ctx = calloc(1, sizeof(struct render_png)))) + ERROR("calloc"); + + // store the struct render + ctx->render = render; + + // libpng initialization + if (!(ctx->png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))) + ERROR("png_create_write_struct"); + + if (!(ctx->info_ptr = png_create_info_struct(ctx->png_ptr))) + ERROR("png_create_info_struct"); + + // libpng error handling + if (setjmp(png_jmpbuf(ctx->png_ptr))) + ERROR("libpng"); + + if (render->io_stream) { + // use normal libpng I/O + // XXX: who fcloses this? + png_init_io(ctx->png_ptr, render->io_stream); + } else { + // setup our custom I/O callbacks + png_set_write_fn(ctx->png_ptr, ctx, &_render_png_write, &_render_png_flush); + } + + // some PNG metadata + png_set_IHDR(ctx->png_ptr, ctx->info_ptr, render->img_w, render->img_h, 8, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + // write out the PNG header + png_write_info(ctx->png_ptr, ctx->info_ptr); + + // success + return ctx; + +error: + _render_png_free(ctx); + return NULL; +} + +int render_png_row (struct render_png *ctx, unsigned char *rowbuf) { + // libpng error handling + if (setjmp(png_jmpbuf(ctx->png_ptr))) + ERROR("libpng"); + + // write it in + png_write_row(ctx->png_ptr, rowbuf); + + // success + return 0; + +error: + _render_png_free(ctx); + return -1; +} + +int render_png_done (struct render_png *ctx) { + // libpng error handling + if (setjmp(png_jmpbuf(ctx->png_ptr))) + ERROR("libpng"); + + // write end + png_write_end(ctx->png_ptr, ctx->info_ptr); + + // success + return 0; + +error: + _render_png_free(ctx); + return -1; +} + +int render_png_abort (struct render_png *ctx) { + // libpng error handling + if (setjmp(png_jmpbuf(ctx->png_ptr))) + ERROR("libpng"); + + _render_png_free(ctx); + + // success + return 0; + +error: + return -1; +} +