--- /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 <stdlib.h>
+
+#include <png.h>
+
+#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;
+}
+