diff options
author | Tavian Barnes <tavianator@gmail.com> | 2009-06-22 05:32:11 +0000 |
---|---|---|
committer | Tavian Barnes <tavianator@gmail.com> | 2009-06-22 05:32:11 +0000 |
commit | e32e140ef7a07037a785f18d48ae679ca941487a (patch) | |
tree | b5a7a490b4a2d9318752b31267adb2d7326d4b72 | |
parent | d23bff8a2eee13eec0724aabe5d9a86b126c4b2c (diff) | |
download | dimension-e32e140ef7a07037a785f18d48ae679ca941487a.tar.xz |
New asynchronous PNG interface.
-rw-r--r-- | libdimension/dimension/png.h | 12 | ||||
-rw-r--r-- | libdimension/png.c | 122 |
2 files changed, 122 insertions, 12 deletions
diff --git a/libdimension/dimension/png.h b/libdimension/dimension/png.h index 9ee55c3..8c18bcb 100644 --- a/libdimension/dimension/png.h +++ b/libdimension/dimension/png.h @@ -24,20 +24,14 @@ #include <dimension.h> #include <stdio.h> -#ifdef __cplusplus -/* We've been included from a C++ file; mark everything here as extern "C" */ -extern "C" { -#endif - /* Write canvas to file in PNG format. Returns 0 on success, nonzero on failure */ int dmnsn_png_write_canvas(const dmnsn_canvas *canvas, FILE *file); +dmnsn_progress *dmnsn_png_write_canvas_async(const dmnsn_canvas *canvas, + FILE *file); /* Read a canvas from a PNG file. Returns NULL on failure. */ dmnsn_canvas *dmnsn_png_read_canvas(FILE *file); - -#ifdef __cplusplus -} -#endif +dmnsn_progress *dmnsn_png_read_canvas_async(dmnsn_canvas **canvas, FILE *file); #endif /* DIMENSION_PNG_H */ diff --git a/libdimension/png.c b/libdimension/png.c index 5f45011..551bac8 100644 --- a/libdimension/png.c +++ b/libdimension/png.c @@ -19,16 +19,121 @@ *************************************************************************/ #include "dimension.h" +#include <pthread.h> #include <png.h> #include <setjmp.h> #include <arpa/inet.h> #include <stdlib.h> +typedef struct { + dmnsn_progress *progress; + const dmnsn_canvas *canvas; + FILE *file; +} dmnsn_png_write_payload; + +typedef struct { + dmnsn_progress *progress; + dmnsn_canvas **canvas; + FILE *file; +} dmnsn_png_read_payload; + +static void *dmnsn_png_write_canvas_thread(void *ptr); +static int dmnsn_png_write_canvas_impl(const dmnsn_canvas *canvas, FILE *file); + +static void *dmnsn_png_read_canvas_thread(void *ptr); +static dmnsn_canvas *dmnsn_png_read_canvas_impl(FILE *file); + /* Write a canvas to a png file, using libpng. Return 0 on success, nonzero on failure. */ int dmnsn_png_write_canvas(const dmnsn_canvas *canvas, FILE *file) { + dmnsn_progress *progress = dmnsn_png_write_canvas_async(canvas, file); + return dmnsn_finish_progress(progress); +} + +/* Write a canvas to a png file in the background */ +dmnsn_progress * +dmnsn_png_write_canvas_async(const dmnsn_canvas *canvas, FILE *file) +{ + dmnsn_progress *progress = dmnsn_new_progress(); + dmnsn_png_write_payload *payload; + + if (progress) { + payload = malloc(sizeof(dmnsn_png_write_payload)); + if (!payload) { + dmnsn_delete_progress(progress); + return NULL; + } + + payload->progress = progress; + payload->canvas = canvas; + payload->file = file; + + if (pthread_create(&progress->thread, NULL, &dmnsn_png_write_canvas_thread, + payload) + != 0) { + dmnsn_error(DMNSN_SEVERITY_MEDIUM, + "Creating png writing worker thread failed."); + } + } + + return progress; +} + +/* Read a canvas from the PNG file `file'. Return NULL on error. */ +dmnsn_canvas * +dmnsn_png_read_canvas(FILE *file) +{ + dmnsn_canvas *canvas; + dmnsn_progress *progress = dmnsn_png_read_canvas_async(&canvas, file); + dmnsn_finish_progress(progress); + return canvas; +} + +/* Read a canvas from a png file in the background */ +dmnsn_progress * +dmnsn_png_read_canvas_async(dmnsn_canvas **canvas, FILE *file) +{ + dmnsn_progress *progress = dmnsn_new_progress(); + dmnsn_png_read_payload *payload; + + if (progress) { + payload = malloc(sizeof(dmnsn_png_write_payload)); + if (!payload) { + dmnsn_delete_progress(progress); + return NULL; + } + + payload->progress = progress; + payload->canvas = canvas; + payload->file = file; + + if (pthread_create(&progress->thread, NULL, &dmnsn_png_read_canvas_thread, + payload) + != 0) { + dmnsn_error(DMNSN_SEVERITY_MEDIUM, + "Creating png writing worker thread failed."); + } + } + + return progress; +} + +static void * +dmnsn_png_write_canvas_thread(void *ptr) +{ + dmnsn_png_write_payload *payload = ptr; + int *retval = malloc(sizeof(int)); + if (retval) { + *retval = dmnsn_png_write_canvas_impl(payload->canvas, payload->file); + } + return retval; +} + +static int +dmnsn_png_write_canvas_impl(const dmnsn_canvas *canvas, FILE *file) +{ png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height; @@ -136,9 +241,20 @@ dmnsn_png_write_canvas(const dmnsn_canvas *canvas, FILE *file) return 0; } -/* Read a canvas from the PNG file `file'. Return NULL on error. */ -dmnsn_canvas * -dmnsn_png_read_canvas(FILE *file) +static void * +dmnsn_png_read_canvas_thread(void *ptr) +{ + dmnsn_png_read_payload *payload = ptr; + int *retval = malloc(sizeof(int)); + if (retval) { + *payload->canvas = dmnsn_png_read_canvas_impl(payload->file); + *retval = payload->canvas ? 1 : 0; + } + return retval; +} + +static dmnsn_canvas * +dmnsn_png_read_canvas_impl(FILE *file) { dmnsn_canvas *canvas; png_byte header[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; |