--- a/Makefile Tue Dec 29 16:44:48 2009 +0200
+++ b/Makefile Thu Dec 31 14:01:37 2009 +0200
@@ -16,7 +16,7 @@
all: depend lib/libpngtile.so bin/util
lib/libpngtile.so : \
- build/obj/lib/image.o build/obj/lib/cache.o build/obj/lib/error.o \
+ build/obj/lib/image.o build/obj/lib/cache.o build/obj/lib/tile.o build/obj/lib/error.o \
build/obj/shared/util.o build/obj/shared/log.o
lib/pypngtile.so : \
--- a/include/pngtile.h Tue Dec 29 16:44:48 2009 +0200
+++ b/include/pngtile.h Thu Dec 31 14:01:37 2009 +0200
@@ -100,11 +100,23 @@
int pt_image_update (struct pt_image *image);
/**
- * Render a PNG tile to a stream.
+ * Render a PNG tile to a FILE*.
*
* The PNG data will be written to the given stream, which will be flushed, but not closed.
*/
-int pt_image_tile (struct pt_image *image, const struct pt_tile_info *info, FILE *out);
+int pt_image_tile_file (struct pt_image *image, const struct pt_tile_info *info, FILE *out);
+
+/**
+ * Render a PNG tile to memory.
+ *
+ * The PNG data will be written to a malloc'd buffer.
+ *
+ * @param image render from image's cache
+ * @param info tile parameters
+ * @param buf_ptr returned heap buffer
+ * @param len_ptr returned buffer length
+ */
+int pt_image_tile_mem (struct pt_image *image, const struct pt_tile_info *info, char **buf_ptr, size_t *len_ptr);
/**
* Release the given pt_image without any clean shutdown
--- a/python/pngtile.pyx Tue Dec 29 16:44:48 2009 +0200
+++ b/python/pngtile.pyx Thu Dec 31 14:01:37 2009 +0200
@@ -1,16 +1,16 @@
-cdef extern from "stdio.h" :
- struct FILE :
- pass
-
cdef extern from "errno.h" :
extern int errno
cdef extern from "string.h" :
char* strerror (int err)
+cimport stdio
+cimport stdlib
+cimport python_string
+
cdef extern from "Python.h" :
int PyFile_Check (object p)
- FILE* PyFile_AsFile (object p)
+ stdio.FILE* PyFile_AsFile (object p)
void PyFile_IncUseCount (object p)
void PyFile_DecUseCount (object p)
@@ -41,7 +41,8 @@
int pt_image_info_func "pt_image_info" (pt_image *image, pt_image_info **info_ptr)
int pt_image_status (pt_image *image)
int pt_image_update (pt_image *image)
- int pt_image_tile (pt_image *image, pt_tile_info *info, FILE *out)
+ int pt_image_tile_file (pt_image *image, pt_tile_info *info, stdio.FILE *out)
+ int pt_image_tile_mem (pt_image *image, pt_tile_info *info, char **buf_ptr, size_t *len_ptr)
void pt_image_destroy (pt_image *image)
char* pt_strerror (int err)
@@ -89,8 +90,8 @@
pt_image_update(self.image)
)
- def tile (self, size_t width, size_t height, size_t x, size_t y, object out) :
- cdef FILE *outf
+ def tile_file (self, size_t width, size_t height, size_t x, size_t y, object out) :
+ cdef stdio.FILE *outf
cdef pt_tile_info ti
if not PyFile_Check(out) :
@@ -106,10 +107,33 @@
ti.x = x
ti.y = y
- trap_err("pt_image_tile",
- pt_image_tile(self.image, &ti, outf)
+ trap_err("pt_image_tile_file",
+ pt_image_tile_file(self.image, &ti, outf)
)
+ def tile_mem (self, size_t width, size_t height, size_t x, size_t y) :
+ cdef pt_tile_info ti
+ cdef char *buf
+ cdef size_t len
+
+ ti.width = width
+ ti.height = height
+ ti.x = x
+ ti.y = y
+
+ # render and return ptr to buffer
+ trap_err("pt_image_tile_mem",
+ pt_image_tile_mem(self.image, &ti, &buf, &len)
+ )
+
+ # copy buffer as str...
+ data = python_string.PyString_FromStringAndSize(buf, len)
+
+ # drop buffer...
+ stdlib.free(buf)
+
+ return data
+
def __dealloc__ (self) :
if self.image :
pt_image_destroy(self.image)
--- a/python/setup.py Tue Dec 29 16:44:48 2009 +0200
+++ b/python/setup.py Thu Dec 31 14:01:37 2009 +0200
@@ -6,7 +6,7 @@
name = 'pngtiles',
cmdclass = {'build_ext': build_ext},
ext_modules = [
- Extension("pngtile", ["pngtile.pyx"],
+ Extension("pypngtile", ["pngtile.pyx"],
include_dirs = ['../include'],
library_dirs = ['../lib'],
libraries = ['pngtile'],
--- a/src/lib/cache.c Tue Dec 29 16:44:48 2009 +0200
+++ b/src/lib/cache.c Thu Dec 31 14:01:37 2009 +0200
@@ -397,6 +397,7 @@
// move from .tmp to .cache
if ((err = pt_cache_create_done(cache)))
+ // XXX: pt_cache_abort?
return err;
// done!
@@ -496,15 +497,15 @@
{
int err;
+ // ensure open
+ if ((err = pt_cache_open(cache)))
+ return err;
+
// check within bounds
if (ti->x >= cache->header->width || ti->y >= cache->header->height)
// completely outside
RETURN_ERROR(PT_ERR_TILE_CLIP);
- // ensure open
- if ((err = pt_cache_open(cache)))
- return err;
-
// set basic info
png_set_IHDR(png, info, ti->width, ti->height, cache->header->bit_depth, cache->header->color_type,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT
--- a/src/lib/error.c Tue Dec 29 16:44:48 2009 +0200
+++ b/src/lib/error.c Thu Dec 31 14:01:37 2009 +0200
@@ -1,5 +1,8 @@
#include "error.h"
+/*
+ * Mapping for error codes
+ */
const char *error_names[PT_ERR_MAX] = {
[PT_SUCCESS] = "Success",
[PT_ERR_MEM] = "malloc()",
--- a/src/lib/error.h Tue Dec 29 16:44:48 2009 +0200
+++ b/src/lib/error.h Thu Dec 31 14:01:37 2009 +0200
@@ -1,6 +1,11 @@
#ifndef PNGTILE_ERROR_H
#define PNGTILE_ERROR_H
+/**
+ * @file
+ *
+ * Obtuse error handling
+ */
#include "pngtile.h"
#include <errno.h>
--- a/src/lib/image.c Tue Dec 29 16:44:48 2009 +0200
+++ b/src/lib/image.c Thu Dec 31 14:01:37 2009 +0200
@@ -1,5 +1,6 @@
#include "image.h"
#include "cache.h"
+#include "tile.h"
#include "error.h"
#include "shared/util.h"
@@ -101,6 +102,8 @@
* Update the image_info field from the given png object.
*
* Must be called under libpng-error-trap!
+ *
+ * XXX: currently this info is not used, pulled from the cache instead
*/
static int pt_image_update_info (struct pt_image *image, png_structp png, png_infop info)
{
@@ -221,36 +224,49 @@
return pt_image_update_cache(image);
}
-int pt_image_tile (struct pt_image *image, const struct pt_tile_info *tile_info, FILE *out)
+int pt_image_tile_file (struct pt_image *image, const struct pt_tile_info *info, FILE *out)
{
- png_structp png = NULL;
- png_infop info = NULL;
- int err = 0;
-
- // open PNG writer
- if ((png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL)
- JUMP_SET_ERROR(err, PT_ERR_PNG_CREATE);
-
- if ((info = png_create_info_struct(png)) == NULL)
- JUMP_SET_ERROR(err, PT_ERR_PNG_CREATE);
+ struct pt_tile tile;
+ int err;
- // libpng error trap
- if (setjmp(png_jmpbuf(png)))
- JUMP_SET_ERROR(err, PT_ERR_PNG);
-
- // setup IO
- png_init_io(png, out);
-
- // render tile
- if ((err = pt_cache_tile_png(image->cache, png, info, tile_info)))
+ // init
+ if ((err = pt_tile_init_file(&tile, info, out)))
+ return err;
+
+ // render
+ if ((err = pt_tile_render(&tile, image->cache)))
JUMP_ERROR(err);
- // done
- png_write_end(png, info);
+ // ok
+ return 0;
error:
- // cleanup
- png_destroy_write_struct(&png, &info);
+ pt_tile_abort(&tile);
+
+ return err;
+}
+
+int pt_image_tile_mem (struct pt_image *image, const struct pt_tile_info *info, char **buf_ptr, size_t *len_ptr)
+{
+ struct pt_tile tile;
+ int err;
+
+ // init
+ if ((err = pt_tile_init_mem(&tile, info)))
+ return err;
+
+ // render
+ if ((err = pt_tile_render(&tile, image->cache)))
+ JUMP_ERROR(err);
+
+ // ok
+ *buf_ptr = tile.out.mem.base;
+ *len_ptr = tile.out.mem.len;
+
+ return 0;
+
+error:
+ pt_tile_abort(&tile);
return err;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/tile.c Thu Dec 31 14:01:37 2009 +0200
@@ -0,0 +1,135 @@
+#include "tile.h"
+#include "error.h"
+#include "shared/log.h" // only FATAL
+
+#include <stdlib.h>
+
+static void pt_tile_init (struct pt_tile *tile, const struct pt_tile_info *info, enum pt_tile_output out_type)
+{
+ memset(tile, 0, sizeof(*tile));
+
+ // init
+ tile->info = *info;
+ tile->out_type = out_type;
+}
+
+
+int pt_tile_init_file (struct pt_tile *tile, const struct pt_tile_info *info, FILE *out)
+{
+ pt_tile_init(tile, info, PT_TILE_OUT_FILE);
+
+ tile->out.file = out;
+
+ return 0;
+}
+
+int pt_tile_init_mem (struct pt_tile *tile, const struct pt_tile_info *info)
+{
+ pt_tile_init(tile, info, PT_TILE_OUT_MEM);
+
+ // init buffer
+ if ((tile->out.mem.base = malloc(PT_TILE_BUF_SIZE)) == NULL)
+ RETURN_ERROR(PT_ERR_MEM);
+
+ tile->out.mem.len = PT_TILE_BUF_SIZE;
+ tile->out.mem.off = 0;
+
+ return 0;
+}
+
+static void pt_tile_mem_write (png_structp png, png_bytep data, png_size_t length)
+{
+ struct pt_tile_mem *buf = png_get_io_ptr(png);
+ size_t buf_len = buf->len;
+
+ // grow?
+ while (buf->off + length > buf_len)
+ buf_len *= 2;
+
+ if (buf_len != buf->len) {
+ char *tmp;
+
+ if ((tmp = realloc(buf->base, buf_len)) == NULL)
+ png_error(png, "pt_tile_buf_write - realloc failed");
+
+ buf->base = tmp;
+ buf->len = buf_len;
+ }
+
+ // copy
+ memcpy(buf->base + buf->off, data, length);
+
+ buf->off += length;
+}
+
+static void pt_tile_mem_flush (png_structp png_ptr)
+{
+ // no-op
+}
+
+
+int pt_tile_render (struct pt_tile *tile, struct pt_cache *cache)
+{
+ png_structp png = NULL;
+ png_infop info = NULL;
+ int err = 0;
+
+ // open PNG writer
+ if ((png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL)
+ JUMP_SET_ERROR(err, PT_ERR_PNG_CREATE);
+
+ if ((info = png_create_info_struct(png)) == NULL)
+ JUMP_SET_ERROR(err, PT_ERR_PNG_CREATE);
+
+ // libpng error trap
+ if (setjmp(png_jmpbuf(png)))
+ JUMP_SET_ERROR(err, PT_ERR_PNG);
+
+ // setup output I/O
+ switch (tile->out_type) {
+ case PT_TILE_OUT_FILE:
+ // use default FILE* operation
+ png_init_io(png, tile->out.file);
+
+ break;
+
+ case PT_TILE_OUT_MEM:
+ // use pt_tile_mem struct via pt_tile_mem_* callbacks
+ png_set_write_fn(png, &tile->out.mem, pt_tile_mem_write, pt_tile_mem_flush);
+
+ break;
+
+ default:
+ FATAL("tile->out_type: %d", tile->out_type);
+ }
+
+ // render tile
+ if ((err = pt_cache_tile_png(cache, png, info, &tile->info)))
+ JUMP_ERROR(err);
+
+ // done
+ png_write_end(png, info);
+
+error:
+ // cleanup
+ png_destroy_write_struct(&png, &info);
+
+ return err;
+}
+
+void pt_tile_abort (struct pt_tile *tile)
+{
+ // cleanup
+ switch (tile->out_type) {
+ case PT_TILE_OUT_FILE:
+ // no-op
+ break;
+
+ case PT_TILE_OUT_MEM:
+ // drop buffer
+ free(tile->out.mem.base);
+
+ break;
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/tile.h Thu Dec 31 14:01:37 2009 +0200
@@ -0,0 +1,61 @@
+#ifndef PNGTILE_TILE_H
+#define PNGTILE_TILE_H
+
+/**
+ * Generating PNG tiles from a cache
+ */
+#include "pngtile.h"
+#include "cache.h"
+
+/** Types of tile output */
+enum pt_tile_output {
+ PT_TILE_OUT_FILE,
+ PT_TILE_OUT_MEM,
+};
+
+/** Initial size of out.mem.base, 16k */
+#define PT_TILE_BUF_SIZE (16 * 1024)
+
+
+
+/** Per-tile-render state */
+struct pt_tile {
+ /** Render spec */
+ struct pt_tile_info info;
+
+ /** Output type */
+ enum pt_tile_output out_type;
+
+ union {
+ /** Output file */
+ FILE *file;
+
+ /** Output buffer */
+ struct pt_tile_mem {
+ char *base;
+ size_t off, len;
+ } mem;
+ } out;
+};
+
+/**
+ * Initialize to render with given params, writing output to given FILE*
+ */
+int pt_tile_init_file (struct pt_tile *tile, const struct pt_tile_info *info, FILE *out);
+
+/**
+ * Initialize to render with given params, writing output to a memory buffer
+ */
+int pt_tile_init_mem (struct pt_tile *tile, const struct pt_tile_info *info);
+
+/**
+ * Render PNG data from given cache according to parameters given to pt_tile_init_*
+ */
+int pt_tile_render (struct pt_tile *tile, struct pt_cache *cache);
+
+/**
+ * Abort any failed render process, cleaning up.
+ */
+void pt_tile_abort (struct pt_tile *tile);
+
+#endif
--- a/src/util/main.c Tue Dec 29 16:44:48 2009 +0200
+++ b/src/util/main.c Thu Dec 31 14:01:37 2009 +0200
@@ -151,6 +151,9 @@
}
log_info("Updated image cache");
+
+ } else {
+ log_debug("Image cache is fresh");
}
// show info
@@ -166,7 +169,7 @@
if (ti.width && ti.height) {
log_debug("Render tile %zux%zu@(%zu,%zu) -> stdout", ti.width, ti.height, ti.x, ti.y);
- if ((err = pt_image_tile(image, &ti, stdout)))
+ if ((err = pt_image_tile_file(image, &ti, stdout)))
log_errno("pt_image_tile: %s: %s", img_path, pt_strerror(err));
}