# HG changeset patch # User Tero Marttila # Date 1262260897 -7200 # Node ID f92a24ab046e066a2ca7db112f67ab8c4ad08659 # Parent baf3fe7c6354ce452292257174fb52d8c79678c5 add missing lib/tile.* diff -r baf3fe7c6354 -r f92a24ab046e Makefile --- 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 : \ diff -r baf3fe7c6354 -r f92a24ab046e include/pngtile.h --- 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 diff -r baf3fe7c6354 -r f92a24ab046e python/pngtile.pyx --- 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) diff -r baf3fe7c6354 -r f92a24ab046e python/setup.py --- 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'], diff -r baf3fe7c6354 -r f92a24ab046e src/lib/cache.c --- 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 diff -r baf3fe7c6354 -r f92a24ab046e src/lib/error.c --- 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()", diff -r baf3fe7c6354 -r f92a24ab046e src/lib/error.h --- 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 diff -r baf3fe7c6354 -r f92a24ab046e src/lib/image.c --- 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; } diff -r baf3fe7c6354 -r f92a24ab046e src/lib/tile.c --- /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 + +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; + } +} + diff -r baf3fe7c6354 -r f92a24ab046e src/lib/tile.h --- /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 diff -r baf3fe7c6354 -r f92a24ab046e src/util/main.c --- 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)); }