[postgis-commits] svn - r3608 - spike/wktraster/rt_core
postgis-commits at postgis.refractions.net
postgis-commits at postgis.refractions.net
Mon Feb 2 05:50:16 PST 2009
Author: strk
Date: 2009-02-02 05:50:15 -0800 (Mon, 02 Feb 2009)
New Revision: 3608
Added:
spike/wktraster/rt_core/check.h
Modified:
spike/wktraster/rt_core/Makefile.in
spike/wktraster/rt_core/rt_api.c
spike/wktraster/rt_core/rt_api.h
spike/wktraster/rt_core/testapi.c
Log:
Initial wkb parser test, and cleanups on testing framework
Modified: spike/wktraster/rt_core/Makefile.in
===================================================================
--- spike/wktraster/rt_core/Makefile.in 2009-02-02 07:21:51 UTC (rev 3607)
+++ spike/wktraster/rt_core/Makefile.in 2009-02-02 13:50:15 UTC (rev 3608)
@@ -26,11 +26,15 @@
rm -f testapi $(RT_OBJS)
rm -f librtcore.a
-testapi: testapi.c rt_api.h rt_api.c
+testapi: testapi.c rt_api.h rt_api.c check.h
$(CC) $(CFLAGS) -o testapi testapi.c rt_api.c -lm $(LDFLAGS)
+testwkb: testwkb.c rt_api.h rt_api.c check.h
+ $(CC) $(CFLAGS) -o testwkb testwkb.c rt_api.c -lm $(LDFLAGS)
+
librtcore.a: $(RT_OBJS) $(RT_HEADERS)
ar rs librtcore.a $(RT_OBJS)
-check: testapi
+check: testapi testwkb
./testapi
+ ./testwkb
Added: spike/wktraster/rt_core/check.h
===================================================================
--- spike/wktraster/rt_core/check.h 2009-02-02 07:21:51 UTC (rev 3607)
+++ spike/wktraster/rt_core/check.h 2009-02-02 13:50:15 UTC (rev 3608)
@@ -0,0 +1,12 @@
+#define CHECK(exp) { if ( !exp ) { \
+ fprintf(stderr, "Check failed on line %d\n", __LINE__); \
+ exit(1); } }
+
+#define CHECK_EQUALS(obt, exp) { if ( obt != exp ) { \
+ fprintf(stderr, "Check failed on line %d\n", __LINE__); \
+ exit(1); } }
+
+#define CHECK_EQUALS_FLOAT(obt, exp) { if ( fabs(obt-exp) > 0.000001 ) { \
+ fprintf(stderr, "Check failed on line %d\n", __LINE__); \
+ exit(1); } }
+
Modified: spike/wktraster/rt_core/rt_api.c
===================================================================
--- spike/wktraster/rt_core/rt_api.c 2009-02-02 07:21:51 UTC (rev 3607)
+++ spike/wktraster/rt_core/rt_api.c 2009-02-02 13:50:15 UTC (rev 3608)
@@ -179,10 +179,10 @@
/*- rt_pixeltype -----------------------------------------------------*/
-/*
- * #define TYPEALIGN(ALIGNVAL,LEN) \
- * (((long) (LEN) + ((ALIGNVAL) - 1)) & ~((long) ((ALIGNVAL) - 1)))
- */
+#ifndef TYPEALIGN
+# define TYPEALIGN(ALIGNVAL,LEN) \
+ (((long) (LEN) + ((ALIGNVAL) - 1)) & ~((long) ((ALIGNVAL) - 1)))
+#endif
int
rt_pixtype_size(rt_context ctx, rt_pixtype pixtype)
@@ -303,6 +303,12 @@
return band;
}
+int
+rt_band_is_offline(rt_context ctx, rt_band band)
+{
+ return band->offline;
+}
+
void
rt_band_destroy(rt_context ctx, rt_band band)
{
@@ -366,7 +372,7 @@
assert(8-bitOffset >= bits);
-#ifdef RT_DEBUG
+#ifdef RT_API_DEBUG
printf("ival:%d bits:%d mask:%hhx bitoffset:%d\n",
ival, bits, mask, bitOffset);
#endif
@@ -380,7 +386,7 @@
}
#endif /* RT_WARN_ON_TRUNCATION */
-#ifdef RT_DEBUG
+#ifdef RT_API_DEBUG
printf(" cleared ival:%hhx\n", ival);
#endif
@@ -388,7 +394,7 @@
* the first bit */
ival <<= (8-bitOffset-bits);
-#ifdef RT_DEBUG
+#ifdef RT_API_DEBUG
printf(" ival shifted:%hhx\n", ival);
printf(" ch:%hhx\n", *ch);
#endif
@@ -396,14 +402,14 @@
/* clear first bits of target */
*ch &= ~(mask << (8-bits-bitOffset));
-#ifdef RT_DEBUG
+#ifdef RT_API_DEBUG
printf(" ch cleared:%hhx\n", *ch);
#endif
/* Set the first bit of target */
*ch |= ival;
-#ifdef RT_DEBUG
+#ifdef RT_API_DEBUG
printf(" ch ored:%hhx\n", *ch);
#endif
@@ -959,6 +965,9 @@
*/
struct rt_raster_t {
+ uint32_t size;
+ uint16_t version;
+
/* Number of bands, all share the same dimension
* and georeference */
uint16_t numBands;
@@ -1230,19 +1239,19 @@
}
static uint8_t
-read_uint8(uint8_t** from)
+read_uint8(const uint8_t** from)
{
return *(*from)++;
}
static int8_t
-read_int8(uint8_t** from)
+read_int8(const uint8_t** from)
{
- return (int8_t)read_int8(from);
+ return (int8_t)read_uint8(from);
}
static uint16_t
-read_uint16(uint8_t** from, uint8_t littleEndian)
+read_uint16(const uint8_t** from, uint8_t littleEndian)
{
uint16_t ret;
if ( littleEndian )
@@ -1256,18 +1265,18 @@
ret = (*from)[0] << 8 |
(*from)[1];
}
- from += 2;
+ *from += 2;
return ret;
}
static int16_t
-read_int16(uint8_t** from, uint8_t littleEndian)
+read_int16(const uint8_t** from, uint8_t littleEndian)
{
return read_uint16(from, littleEndian);
}
static uint32_t
-read_uint32(uint8_t** from, uint8_t littleEndian)
+read_uint32(const uint8_t** from, uint8_t littleEndian)
{
uint32_t ret;
@@ -1287,18 +1296,18 @@
(uint32_t) ((*from)[0] & 0xff) << 24;
}
- from += 4;
+ *from += 4;
return ret;
}
static int32_t
-read_int32(uint8_t** from, uint8_t littleEndian)
+read_int32(const uint8_t** from, uint8_t littleEndian)
{
return read_uint32(from, littleEndian);
}
static float
-read_float32(uint8_t** from, uint8_t littleEndian)
+read_float32(const uint8_t** from, uint8_t littleEndian)
{
union {
float f;
@@ -1311,7 +1320,7 @@
}
static double
-read_float64(uint8_t** from, uint8_t littleEndian)
+read_float64(const uint8_t** from, uint8_t littleEndian)
{
union {
double d;
@@ -1342,7 +1351,7 @@
(uint64_t) ((*from)[0] & 0xff) << 56;
}
- from += 8;
+ *from += 8;
return ret.d;
}
@@ -1359,7 +1368,7 @@
/* Read band from WKB as at start of band */
static rt_band
rt_band_from_wkb(rt_context ctx, uint16_t width, uint16_t height,
- uint8_t** ptr, uint8_t* end,
+ const uint8_t** ptr, const uint8_t* end,
uint8_t littleEndian)
{
rt_band band;
@@ -1375,7 +1384,8 @@
}
if ( end - *ptr < 1 ) {
- ctx->err("Premature end of WKB on band reading");
+ ctx->err("Premature end of WKB on band reading (%s:%d)",
+ __FILE__, __LINE__);
return 0;
}
type = read_uint8(ptr);
@@ -1392,6 +1402,10 @@
band->width = width;
band->height = height;
+ ctx->info(" Band pixtype:%s, offline:%d",
+ rt_pixtype_name(ctx, band->pixtype),
+ band->offline);
+
/* Check there's enough bytes to read nodata value */
pixbytes = rt_pixtype_size(ctx, band->pixtype);
@@ -1486,11 +1500,15 @@
}
}
+ ctx->info(" Nodata value: %g, pixbytes: %d, ptr @ %p, end @ %p",
+ band->nodataval, pixbytes, *ptr, end);
+
if ( band->offline )
{
if (((*ptr)+1) >= end) {
ctx->err("Premature end of WKB on offline "
- "band data bandNum reading");
+ "band data bandNum reading (%s:%d)",
+ __FILE__, __LINE__);
ctx->dealloc(band);
return 0;
}
@@ -1513,9 +1531,11 @@
}
/* This is an offline band */
- sz = width*height+pixbytes;
- if (((*ptr)+sz) >= end) {
- ctx->err("Premature end of WKB on band data reading");
+ sz = width*height*pixbytes;
+ if (((*ptr)+sz) > end)
+ {
+ ctx->err("Premature end of WKB on band data reading (%s:%d)",
+ __FILE__, __LINE__);
ctx->dealloc(band);
return 0;
}
@@ -1568,11 +1588,11 @@
#define RT_WKB_HDR_SZ (sizeof(struct rt_raster_serialized_t)-4+1)
rt_raster
-rt_raster_from_wkb(rt_context ctx, uint8_t* wkb, unsigned long int wkbsize)
+rt_raster_from_wkb(rt_context ctx, const uint8_t* wkb, uint32_t wkbsize)
{
uint8_t endian;
- uint8_t *wkbend;
- uint8_t *ptr = wkb;
+ const uint8_t *wkbend;
+ const uint8_t *ptr = wkb;
uint16_t version;
rt_raster rast;
uint16_t i;
@@ -1610,28 +1630,41 @@
/* consistency checking, should have been checked before */
assert(ptr <= wkbend);
-#ifdef RT_DEBUG
- ctx->info("rt_raster_from_wkb: Raster dims: %dx%d",
- result->width, result->height);
+#ifdef RT_API_DEBUG
+ ctx->info("rt_raster_from_wkb: Raster numBands: %d",
+ rast->numBands);
ctx->info("rt_raster_from_wkb: Raster scale: %gx%g",
- result->scaleX, result->scaleY);
+ rast->scaleX, rast->scaleY);
ctx->info("rt_raster_from_wkb: Raster ip: %gx%g",
- result->ipX, result->ipY);
+ rast->ipX, rast->ipY);
ctx->info("rt_raster_from_wkb: Raster skew: %gx%g",
- result->skewX, result->skewY );
+ rast->skewX, rast->skewY );
ctx->info("rt_raster_from_wkb: Raster srid: %d",
- result->srid);
- ctx->info("rt_raster_from_hexwkb: Raster numBands: %d",
- result->numBands);
+ rast->srid);
+ ctx->info("rt_raster_from_wkb: Raster dims: %dx%d",
+ rast->width, rast->height);
#endif
+ if ( ! rast->numBands )
+ {
+ return rast;
+ }
+
/* Now read the bands */
rast->bands = (rt_band*)ctx->alloc(sizeof(rt_band)*rast->numBands);
- ptr += RT_WKB_HDR_SZ; /* should now point to start of first band */
+ if ( ! rast->bands )
+ {
+ ctx->err("Out of memory allocating bands for WKB raster decoding");
+ ctx->dealloc(rast);
+ return 0;
+ }
+
+ /* ptr should now point to start of first band */
assert ( ptr <= wkbend ); /* we should have checked this before */
for (i=0; i<rast->numBands; ++i)
{
+ ctx->info("Parsing band %d from wkb", i);
rt_band band = rt_band_from_wkb(ctx, rast->width, rast->height,
&ptr, wkbend, endian);
if ( ! band )
@@ -1660,4 +1693,227 @@
}
+rt_raster
+rt_raster_from_hexwkb(rt_context ctx, const char* hexwkb,
+ uint32_t hexwkbsize)
+{
+ uint8_t* wkb;
+ uint32_t wkbsize;
+ uint32_t i;
+
+ if ( hexwkbsize%2 )
+ {
+ ctx->err("Raster HEXWKB input must have an even number of characters");
+ return 0;
+ }
+ wkbsize = hexwkbsize/2;
+
+ wkb = ctx->alloc(wkbsize);
+ if ( ! wkb )
+ {
+ ctx->err("Out of memory allocating memory for decoding HEXWKB");
+ return 0;
+ }
+
+ for (i=0; i<wkbsize; ++i) /* parse full hex */
+ {
+ wkb[i] = parse_hex(&(hexwkb[i*2]));
+ }
+
+ return rt_raster_from_wkb(ctx, wkb, wkbsize);
+}
+
/*--------- Serializer/Deserializer --------------------------------------*/
+
+static uint32_t
+rt_raster_serialized_size(rt_context ctx, rt_raster raster)
+{
+ uint32_t size = sizeof(struct rt_raster_serialized_t);
+ uint16_t i;
+
+ for (i=0; i<raster->numBands; ++i)
+ {
+ rt_band band = raster->bands[i];
+ rt_pixtype pixtype = band->pixtype;
+ int pixbytes = rt_pixtype_size(ctx, pixtype);
+
+ if ( pixbytes < 1 ) {
+ // ERROR !
+ ctx->err("Corrupted band: unkonwn pixtype");
+ return 0;
+ }
+
+ /* Add space for band type and data padding */
+ size += pixbytes;
+
+ /* Add space for nodata value */
+ size += pixbytes;
+
+ if ( band->offline )
+ {
+ /* Add space for band number */
+ size += 1;
+
+ /* Add space for null-terminated path */
+ size += strlen(band->data.offline.path)+1;
+ }
+ else
+ {
+ /* Add space for nodata value */
+ size += pixbytes*raster->width*raster->height;
+ }
+
+
+ /* Align size to 8-bytes boundary (trailing padding) */
+ size = TYPEALIGN(size, 8);
+ }
+
+ return size;
+}
+
+void*
+rt_raster_serialize(rt_context ctx, rt_raster raster)
+{
+ uint32_t size = rt_raster_serialized_size(ctx, raster);
+ uint8_t* ret;
+ uint8_t* ptr;
+ uint16_t i;
+
+ ret = (uint8_t*)ctx->alloc(size);
+ if ( ! ret )
+ {
+ ctx->err("Out of memory allocating %d bytes for serializing a raster",
+ size);
+ return 0;
+ }
+
+ ptr = ret;
+
+ /* Set size */
+ raster->size = size;
+
+ /* Set version */
+ raster->version = 0;
+
+ /* Copy header */
+ memcpy(ptr, raster, sizeof(struct rt_raster_serialized_t));
+ ptr += sizeof(struct rt_raster_serialized_t);
+
+ /* Serialize bands now */
+ for (i=0; i<raster->numBands; ++i)
+ {
+ rt_band band = raster->bands[i];
+ rt_pixtype pixtype = band->pixtype;
+ int pixbytes = rt_pixtype_size(ctx, pixtype);
+
+ if ( pixbytes < 1 ) {
+ // ERROR !
+ ctx->err("Corrupted band: unkonwn pixtype");
+ return 0;
+ }
+
+ /* Add band type */
+ *ptr = band->pixtype;
+ if ( band->offline ) *ptr |= BANDTYPE_FLAG_OFFDB;
+ ptr += 1;
+
+ /* Add padding (if needed) */
+ if ( pixbytes > 1 ) {
+ memset(ptr, '\0', pixbytes-1);
+ ptr += pixbytes-1;
+ }
+
+ /* Consistency checking (ptr is pixbytes-aligned) */
+ assert(! (((uint64_t)ptr)%pixbytes) );
+
+ /* Add nodata value */
+ switch (pixtype)
+ {
+ default:
+ abort(); /* shoudn't happen */
+ return 0;
+ case PT_1BB:
+ case PT_2BUI:
+ case PT_4BUI:
+ case PT_8BUI:
+ {
+ uint8_t v = band->nodataval;
+ *ptr = v; ptr+=1;
+ break;
+ }
+ case PT_8BSI:
+ {
+ int8_t v = band->nodataval;
+ *ptr = v; ptr+=1;
+ break;
+ }
+
+
+ case PT_16BSI:
+ case PT_16BUI:
+ {
+ uint16_t v = band->nodataval;
+ memcpy(ptr, &v, 2); ptr+=2;
+ break;
+ }
+
+ case PT_32BSI:
+ case PT_32BUI:
+ {
+ uint32_t v = band->nodataval;
+ memcpy(ptr, &v, 4); ptr+=4;
+ break;
+ }
+
+ case PT_16BF:
+ ctx->err("16BF pixel type not supported yet");
+ break;
+
+ case PT_32BF:
+ {
+ float v = band->nodataval;
+ memcpy(ptr, &v, 4); ptr+=4;
+ break;
+ }
+
+ case PT_64BF:
+ {
+ memcpy(ptr, &band->nodataval, 8); ptr+=8;
+ break;
+ }
+ }
+
+ /* Consistency checking (ptr is pixbytes-aligned) */
+ assert(! ((uint64_t)ptr%pixbytes) );
+
+ if ( band->offline )
+ {
+ /* Write band number */
+ *ptr = band->data.offline.bandNum; ptr += 1;
+
+ /* Write path */
+ strcpy((char*)ptr, band->data.offline.path);
+ ptr += strlen(band->data.offline.path)+1;
+ }
+ else
+ {
+ /* Write data */
+ {
+ uint32_t datasize = raster->width*raster->height*pixbytes;
+ memcpy(ptr, band->data.mem, datasize);
+ ptr += datasize;
+ }
+ }
+
+ /* Pad up to 8-bytes boundary */
+ while ( (uint64_t)ptr%8 ) {
+ *ptr = 0; ++ptr;
+ }
+
+ /* Consistency checking (ptr is pixbytes-aligned) */
+ assert(! ((uint64_t)ptr%pixbytes) );
+ }
+
+ return ret;
+}
+
Modified: spike/wktraster/rt_core/rt_api.h
===================================================================
--- spike/wktraster/rt_core/rt_api.h 2009-02-02 07:21:51 UTC (rev 3607)
+++ spike/wktraster/rt_core/rt_api.h 2009-02-02 13:50:15 UTC (rev 3608)
@@ -239,10 +239,24 @@
* malformed WKB).
*
*/
-rt_raster rt_raster_from_wkb(rt_context ctx, uint8_t* wkb,
- unsigned long int wkbsize);
+rt_raster rt_raster_from_wkb(rt_context ctx, const uint8_t* wkb,
+ uint32_t wkbsize);
/**
+ * Construct an rt_raster from a text HEXWKB representation
+ *
+ * @param ctx : context, for thread safety
+ * @param hexwkb : an hex-encoded stream
+ * @param hexwkbsize : size (in bytes) of the hexwkb stream
+ *
+ * @return an rt_raster or 0 on error (out of memory or
+ * malformed WKB).
+ *
+ */
+rt_raster rt_raster_from_hexwkb(rt_context ctx, const char* hexwkb,
+ uint32_t hexwkbsize);
+
+/**
* Release memory associated to a raster
*
* Note that this will not release data
@@ -421,4 +435,12 @@
*/
LWPOLY* rt_raster_get_envelope(rt_context ctx, rt_raster raster);
+/**
+ * Return this raster in serialized form.
+ *
+ * Serialized form is documented in doc/RFC1-SerializedFormat.
+ *
+ */
+void* rt_raster_serialize(rt_context ctx, rt_raster raster);
+
#endif /* RT_API_H */
Modified: spike/wktraster/rt_core/testapi.c
===================================================================
--- spike/wktraster/rt_core/testapi.c 2009-02-02 07:21:51 UTC (rev 3607)
+++ spike/wktraster/rt_core/testapi.c 2009-02-02 13:50:15 UTC (rev 3608)
@@ -4,23 +4,12 @@
#include <math.h> /* for fabs */
#include "rt_api.h"
+#include "check.h"
static rt_band addBand(rt_context ctx, rt_raster raster, rt_pixtype pixtype);
static void deepRelease(rt_context ctx, rt_raster raster);
static void testBand1BB(rt_context ctx, rt_band band);
-#define CHECK(exp) { if ( !exp ) { \
- fprintf(stderr, "Check failed on line %d\n", __LINE__); \
- exit(1); } }
-
-#define CHECK_EQUALS(obt, exp) { if ( obt != exp ) { \
- fprintf(stderr, "Check failed on line %d\n", __LINE__); \
- exit(1); } }
-
-#define CHECK_EQUALS_FLOAT(obt, exp) { if ( fabs(obt-exp) > 0.000001 ) { \
- fprintf(stderr, "Check failed on line %d\n", __LINE__); \
- exit(1); } }
-
static rt_band
addBand(rt_context ctx, rt_raster raster, rt_pixtype pixtype)
{
More information about the postgis-commits
mailing list