From 37531005905d9a8723abbabb172eb852ae2cd0fc Mon Sep 17 00:00:00 2001 From: anatashkin <79263256394@ya.ru> Date: Thu, 10 Sep 2015 15:32:15 +0300 Subject: [PATCH 1/6] Add metatile generation support --- mapnik_c_api.cpp | 28 ++++++++++++++++++++++------ mapnik_c_api.h | 2 +- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/mapnik_c_api.cpp b/mapnik_c_api.cpp index 9dc3db2..02c0904 100644 --- a/mapnik_c_api.cpp +++ b/mapnik_c_api.cpp @@ -9,14 +9,14 @@ #include #if MAPNIK_VERSION >= 300000 -#include -#define mapnik_image_type mapnik::image_rgba8 + #include + #define mapnik_image_type mapnik::image_rgba8 + #include #else -#include -#define mapnik_image_type mapnik::image_32 + #include + #define mapnik_image_type mapnik::image_32 #endif - #include "mapnik_c_api.h" #include @@ -136,7 +136,6 @@ int mapnik_map_render_to_file(mapnik_map_t * m, const char* filepath) { return -1; } - void mapnik_map_resize(mapnik_map_t *m, unsigned int width, unsigned int height) { if (m&& m->m) { m->m->resize(width, height); @@ -255,6 +254,23 @@ mapnik_image_blob_t * mapnik_image_to_png_blob(mapnik_image_t * i) { return blob; } +mapnik_image_blob_t * mapnik_image_view_to_png_blob(mapnik_image_t * i, unsigned int xx, unsigned int yy, unsigned int xsize, unsigned int ysize) { + mapnik_image_blob_t * blob = new mapnik_image_blob_t; + blob->ptr = NULL; + blob->len = 0; + if (i && i->i) { +#if MAPNIK_VERSION >= 300000 + mapnik::image_view_any vw(mapnik::image_view>(xx, yy, xsize, ysize, *(i->i))); +#else + mapnik::image_view vw(xx, yy, xsize, ysize, i->i->data()); +#endif + std::string s = save_to_string(vw, "png256"); + blob->len = s.length(); + blob->ptr = new char[blob->len]; + memcpy(blob->ptr, s.c_str(), blob->len); + } + return blob; +} #ifdef __cplusplus } diff --git a/mapnik_c_api.h b/mapnik_c_api.h index 8a60a5e..0ef33c0 100644 --- a/mapnik_c_api.h +++ b/mapnik_c_api.h @@ -52,7 +52,7 @@ MAPNIKCAPICALL void mapnik_image_blob_free(mapnik_image_blob_t * b); MAPNIKCAPICALL mapnik_image_blob_t * mapnik_image_to_png_blob(mapnik_image_t * i); - +MAPNIKCAPICALL mapnik_image_blob_t * mapnik_image_view_to_png_blob(mapnik_image_t * i, unsigned int xx, unsigned int yy, unsigned int xlen, unsigned int ylen); // Map typedef struct _mapnik_map_t mapnik_map_t; From 92efc6cfbd6525d193b8857d4c12debdb30df117 Mon Sep 17 00:00:00 2001 From: anatashkin <79263256394@ya.ru> Date: Thu, 10 Sep 2015 15:34:59 +0300 Subject: [PATCH 2/6] Add lua test for metatile generation --- test/lua-api-test-metatile.lua | 58 ++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 test/lua-api-test-metatile.lua diff --git a/test/lua-api-test-metatile.lua b/test/lua-api-test-metatile.lua new file mode 100644 index 0000000..59476ea --- /dev/null +++ b/test/lua-api-test-metatile.lua @@ -0,0 +1,58 @@ +local ffi = require("ffi") + +ffi.cdef[[ +int mapnik_register_datasources(const char* path); + +// Opaque class structure +typedef struct _mapnik_map_t mapnik_map_t; + +mapnik_map_t * mapnik_map( unsigned int width, unsigned int height ); + +void mapnik_map_free(mapnik_map_t * m); + +const char * mapnik_map_get_srs(mapnik_map_t * m); + +int mapnik_map_set_srs(mapnik_map_t * m, const char* srs); + +int mapnik_map_load(mapnik_map_t * m, const char* stylesheet); + +int mapnik_map_zoom_all(mapnik_map_t * m); + +int mapnik_map_render_to_file(mapnik_map_t * m, const char* filepath); + +typedef struct _mapnik_image_t mapnik_image_t; + +void mapnik_image_free(mapnik_image_t * i); + +typedef struct _mapnik_image_blob_t { + char *ptr; + unsigned int len; +} mapnik_image_blob_t; + +void mapnik_image_blob_free(mapnik_image_blob_t * b); + +mapnik_image_blob_t * mapnik_image_to_png_blob(mapnik_image_t * i); + +mapnik_image_blob_t * mapnik_image_view_to_png_blob(mapnik_image_t * i, unsigned int xx, unsigned int yy, unsigned int xlen, unsigned int ylen); + +mapnik_image_t * mapnik_map_render_to_image(mapnik_map_t * m); + +]] + +local m = ffi.load("../libmapnik_c.so") + +m.mapnik_register_datasources("/usr/local/lib/mapnik/input") + +local map = m.mapnik_map(256*8,256*8) +m.mapnik_map_load(map,"/etc/mapnik-osm-carto-data/moscow.xml") +m.mapnik_map_zoom_all(map) +local image = m.mapnik_map_render_to_image(map) +local png_blob = m.mapnik_image_view_to_png_blob(image, 256*6, 256*4, 256, 256) +--local png_blob = m.mapnik_image_to_png_blob(image) +m.mapnik_image_free(image) +local png_file = io.open("lua-test.png", "w") +png_file:write(ffi.string(png_blob.ptr, png_blob.len)) +png_file:close() +m.mapnik_image_blob_free(png_blob) + +m.mapnik_map_free(map) \ No newline at end of file From 52d3c7b37f74608873156c537ef6f5905a2680c9 Mon Sep 17 00:00:00 2001 From: anatashkin <79263256394@ya.ru> Date: Tue, 15 Sep 2015 10:43:17 +0300 Subject: [PATCH 3/6] Add generating metatile blob --- mapnik-c-api.config | 1 + mapnik-c-api.creator | 1 + mapnik-c-api.files | 5 +++++ mapnik-c-api.includes | 1 + 4 files changed, 8 insertions(+) create mode 100644 mapnik-c-api.config create mode 100644 mapnik-c-api.creator create mode 100644 mapnik-c-api.files create mode 100644 mapnik-c-api.includes diff --git a/mapnik-c-api.config b/mapnik-c-api.config new file mode 100644 index 0000000..8cec188 --- /dev/null +++ b/mapnik-c-api.config @@ -0,0 +1 @@ +// ADD PREDEFINED MACROS HERE! diff --git a/mapnik-c-api.creator b/mapnik-c-api.creator new file mode 100644 index 0000000..e94cbbd --- /dev/null +++ b/mapnik-c-api.creator @@ -0,0 +1 @@ +[General] diff --git a/mapnik-c-api.files b/mapnik-c-api.files new file mode 100644 index 0000000..36aaca2 --- /dev/null +++ b/mapnik-c-api.files @@ -0,0 +1,5 @@ +test/c-api-c99-test.c +test/c-api-test.cpp +catch.hpp +mapnik_c_api.cpp +mapnik_c_api.h \ No newline at end of file diff --git a/mapnik-c-api.includes b/mapnik-c-api.includes new file mode 100644 index 0000000..945c9b4 --- /dev/null +++ b/mapnik-c-api.includes @@ -0,0 +1 @@ +. \ No newline at end of file From 4d8091fc0b52b52e02724f5caac29033e8286145 Mon Sep 17 00:00:00 2001 From: anatashkin <79263256394@ya.ru> Date: Tue, 15 Sep 2015 10:55:06 +0300 Subject: [PATCH 4/6] remove qt-creator project files --- mapnik-c-api.config | 1 - mapnik-c-api.creator | 1 - mapnik-c-api.files | 5 ----- mapnik-c-api.includes | 1 - 4 files changed, 8 deletions(-) delete mode 100644 mapnik-c-api.config delete mode 100644 mapnik-c-api.creator delete mode 100644 mapnik-c-api.files delete mode 100644 mapnik-c-api.includes diff --git a/mapnik-c-api.config b/mapnik-c-api.config deleted file mode 100644 index 8cec188..0000000 --- a/mapnik-c-api.config +++ /dev/null @@ -1 +0,0 @@ -// ADD PREDEFINED MACROS HERE! diff --git a/mapnik-c-api.creator b/mapnik-c-api.creator deleted file mode 100644 index e94cbbd..0000000 --- a/mapnik-c-api.creator +++ /dev/null @@ -1 +0,0 @@ -[General] diff --git a/mapnik-c-api.files b/mapnik-c-api.files deleted file mode 100644 index 36aaca2..0000000 --- a/mapnik-c-api.files +++ /dev/null @@ -1,5 +0,0 @@ -test/c-api-c99-test.c -test/c-api-test.cpp -catch.hpp -mapnik_c_api.cpp -mapnik_c_api.h \ No newline at end of file diff --git a/mapnik-c-api.includes b/mapnik-c-api.includes deleted file mode 100644 index 945c9b4..0000000 --- a/mapnik-c-api.includes +++ /dev/null @@ -1 +0,0 @@ -. \ No newline at end of file From bc0c161cf38e2b7e98f0adf9596e61472e1b93fd Mon Sep 17 00:00:00 2001 From: anatashkin <79263256394@ya.ru> Date: Tue, 15 Sep 2015 10:58:37 +0300 Subject: [PATCH 5/6] Add generation metatile blob for saving to file such as mod_tile prepared metatile --- mapnik_c_api.cpp | 84 ++++++++++++++++++++++++++++++++++++++++++++++++ mapnik_c_api.h | 2 ++ 2 files changed, 86 insertions(+) diff --git a/mapnik_c_api.cpp b/mapnik_c_api.cpp index 02c0904..732d399 100644 --- a/mapnik_c_api.cpp +++ b/mapnik_c_api.cpp @@ -21,11 +21,25 @@ #include +#define META_MAGIC "META" +#define MIN(x,y) ((x)<(y)?(x):(y)) + #ifdef __cplusplus extern "C" { #endif +struct entry { + unsigned int offset; + unsigned int size; +}; + +struct meta_layout { + char magic[4]; + unsigned int count; // METATILE ^ 2 + unsigned int x, y, z; // lowest x,y of this metatile, plus z +}; + int mapnik_register_datasources(const char* path, char** err) { try { #if MAPNIK_VERSION >= 200200 @@ -272,6 +286,76 @@ mapnik_image_blob_t * mapnik_image_view_to_png_blob(mapnik_image_t * i, unsigned return blob; } +int xyz_to_meta_offset(unsigned int x, unsigned int y, unsigned int z) { + unsigned char mask = 7; + return (x & mask) * 8 + (y & mask); +} + +mapnik_image_blob_t * mapnik_image_to_metatile(mapnik_map_t *map, mapnik_image_t * i, unsigned int z_, unsigned int x_, unsigned int y_, unsigned int ms) { + int ox, oy, limit; + ssize_t offset; + struct meta_layout m; + struct entry *offsets = new entry[ms*ms]; + mapnik_image_blob_t **tile = (mapnik_image_blob_t**)malloc((ms*ms)*sizeof(mapnik_image_blob_t*)); + mapnik_image_blob_t * blob = new mapnik_image_blob_t; + blob->ptr = NULL; + blob->len = 0; + + mapnik_map_reset_last_error(map); + + memset(&m, 0, sizeof(m)); + + // Create and write header + m.count = ms * ms; + memcpy(m.magic, META_MAGIC, strlen(META_MAGIC)); + m.x = x_; + m.y = y_; + m.z = z_; + + offset = sizeof(meta_layout) + ms*ms*sizeof(entry); + limit = ms; + memset(offsets, 0, ms*ms*sizeof(entry)); + + // Generate offset table + for (ox=0; ox < limit; ox++) { + for (oy=0; oy < limit; oy++) { + int mt = xyz_to_meta_offset(x_ + ox, y_ + oy, z_); + offsets[mt].offset = offset; + tile[mt] = mapnik_image_view_to_png_blob(i, ox*256, oy*256, 256, 256); + if(tile[mt]->ptr == NULL){ + map->err = new std::string("Cannot get image view from image"); + return NULL; + } + offsets[mt].size = tile[mt]->len; + printf("offsets[%d].offset=%ld, offsets[%d].size=%u\n", mt, offset, mt, offsets[mt].size); + offset += offsets[mt].size; + } + } + + blob->ptr = new char[offset]; + if (blob->ptr == 0) { + map->err = new std::string("Failed to write metatile. Out of memory"); + return NULL; + } + memset(blob->ptr, 0, offset); + memcpy(blob->ptr,&m,sizeof(m)); + memcpy(blob->ptr + sizeof(m), offsets, ms*ms*sizeof(entry)); + + // Write tiles + for (ox=0; ox < limit; ox++) { + for (oy=0; oy < limit; oy++) { + int mt = xyz_to_meta_offset(x_ + ox, y_ + oy, z_); + memcpy(blob->ptr + offsets[mt].offset, tile[mt]->ptr, tile[mt]->len); + mapnik_image_blob_free(tile[mt]); + } + } + delete [] offsets; + free(tile); + blob->len = offset; + + return blob; +} + #ifdef __cplusplus } #endif diff --git a/mapnik_c_api.h b/mapnik_c_api.h index 0ef33c0..f8451a6 100644 --- a/mapnik_c_api.h +++ b/mapnik_c_api.h @@ -83,6 +83,8 @@ MAPNIKCAPICALL mapnik_projection_t * mapnik_map_projection(mapnik_map_t *m); MAPNIKCAPICALL mapnik_image_t * mapnik_map_render_to_image(mapnik_map_t * m); +MAPNIKCAPICALL mapnik_image_blob_t * mapnik_image_to_metatile(mapnik_map_t *map, mapnik_image_t * i, unsigned int z, unsigned int x, unsigned int y, unsigned int ms); + #ifdef __cplusplus } #endif From fc58852287991e40e814629386e83dfae9f0342c Mon Sep 17 00:00:00 2001 From: anatashkin <79263256394@ya.ru> Date: Tue, 15 Sep 2015 11:04:04 +0300 Subject: [PATCH 6/6] Add C and Lua tests for metatile generating --- test/c-api-c99-test-metatile.c | 31 +++++++++++++++++++++++++++++ test/lua-api-test-metatile.lua | 36 ++++++++++++++++++++-------------- 2 files changed, 52 insertions(+), 15 deletions(-) create mode 100644 test/c-api-c99-test-metatile.c diff --git a/test/c-api-c99-test-metatile.c b/test/c-api-c99-test-metatile.c new file mode 100644 index 0000000..2a1ebee --- /dev/null +++ b/test/c-api-c99-test-metatile.c @@ -0,0 +1,31 @@ + +#include +#include "mapnik_c_api.h" +#include "test/c-api-test-cfg.h" + +int main() { + mapnik_map_t * map; + mapnik_image_t * image; + mapnik_image_blob_t * metatile; + FILE * mf; + map = mapnik_map(8*256,8*256); + mapnik_register_datasources(MAPNIK_PLUGINDIR, NULL); + mapnik_map_load(map,"../sample/stylesheet.xml"); + mapnik_map_zoom_all(map); + + image = mapnik_map_render_to_image(map); + metatile = mapnik_image_to_metatile(map, image, 3, 2, 1, 8); + if( metatile == NULL || metatile->ptr == NULL) { + printf("error: %s\n", mapnik_map_last_error(map)); + return -1; + } + mf = fopen("./mapnik-c-api-c99-test-metatile.meta", "wb"); + fwrite(metatile->ptr, sizeof(char), metatile->len, mf); + fclose(mf); + printf("\x1b[1;32m ✓ (%s)\x1b[0m\n", "./mapnik-c-api-c99-test-metatile.meta"); + mapnik_image_free(image); + mapnik_image_blob_free(metatile); + mapnik_map_free(map); + printf("c99 test works\n"); + return 0; +} diff --git a/test/lua-api-test-metatile.lua b/test/lua-api-test-metatile.lua index 59476ea..50feb28 100644 --- a/test/lua-api-test-metatile.lua +++ b/test/lua-api-test-metatile.lua @@ -37,22 +37,28 @@ mapnik_image_blob_t * mapnik_image_view_to_png_blob(mapnik_image_t * i, unsigned mapnik_image_t * mapnik_map_render_to_image(mapnik_map_t * m); +mapnik_image_blob_t * mapnik_image_to_metatile(mapnik_map_t * m, mapnik_image_t * i, unsigned int z, unsigned int x, unsigned int y, unsigned int ms); + ]] local m = ffi.load("../libmapnik_c.so") -m.mapnik_register_datasources("/usr/local/lib/mapnik/input") - -local map = m.mapnik_map(256*8,256*8) -m.mapnik_map_load(map,"/etc/mapnik-osm-carto-data/moscow.xml") -m.mapnik_map_zoom_all(map) -local image = m.mapnik_map_render_to_image(map) -local png_blob = m.mapnik_image_view_to_png_blob(image, 256*6, 256*4, 256, 256) ---local png_blob = m.mapnik_image_to_png_blob(image) -m.mapnik_image_free(image) -local png_file = io.open("lua-test.png", "w") -png_file:write(ffi.string(png_blob.ptr, png_blob.len)) -png_file:close() -m.mapnik_image_blob_free(png_blob) - -m.mapnik_map_free(map) \ No newline at end of file +if m.mapnik_register_datasources("/usr/local/lib/mapnik/input") ~= 0 then + print("mapnik_image_to_metatile error:"..ffi.string(m.mapnik_map_last_error(map))) +else + local map = m.mapnik_map(256*8,256*8) + m.mapnik_map_load(map,"../sample/stylesheet.xml") + m.mapnik_map_zoom_all(map) + local image = m.mapnik_map_render_to_image(map) + local metatile = m.mapnik_image_to_metatile(map, image, 3, 0, 0, 8) + if metatile and metatile.ptr then + local metatile_file = io.open("lua-test-metatile.meta", "w") + metatile_file:write(ffi.string(metatile.ptr, metatile.len)) + metatile_file:close() + m.mapnik_image_blob_free(metatile) + else + print("mapnik_image_to_metatile error:"..ffi.string(m.mapnik_map_last_error(map))) + end + m.mapnik_image_free(image) + m.mapnik_map_free(map) +end