summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2009-06-22 05:32:11 +0000
committerTavian Barnes <tavianator@gmail.com>2009-06-22 05:32:11 +0000
commite32e140ef7a07037a785f18d48ae679ca941487a (patch)
treeb5a7a490b4a2d9318752b31267adb2d7326d4b72
parentd23bff8a2eee13eec0724aabe5d9a86b126c4b2c (diff)
downloaddimension-e32e140ef7a07037a785f18d48ae679ca941487a.tar.xz
New asynchronous PNG interface.
-rw-r--r--libdimension/dimension/png.h12
-rw-r--r--libdimension/png.c122
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 };