[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