]> granicus.if.org Git - postgis/commitdiff
Addition of ST_Band functionality.
authorBborie Park <bkpark at ucdavis.edu>
Mon, 16 May 2011 19:11:21 +0000 (19:11 +0000)
committerBborie Park <bkpark at ucdavis.edu>
Mon, 16 May 2011 19:11:21 +0000 (19:11 +0000)
  - added function rt_raster_from_band to rt_core/rt_api.c and rt_api.h
- added test case to test/core/testapi.c
- added function RASTER_band to rt_pg/rt_pg.c
- added SQL functions for ST_Band to rt_pg/rtpostgis.sql.in.c
- added regression tests in test/regress

Associated ticket is #339 and attached patch st_band.3.patch

git-svn-id: http://svn.osgeo.org/postgis/trunk@7147 b70326c6-7e19-0410-871a-916f4a2858ee

raster/rt_core/rt_api.c
raster/rt_core/rt_api.h
raster/rt_pg/rt_pg.c
raster/rt_pg/rtpostgis.sql.in.c
raster/test/core/testapi.c
raster/test/regress/Makefile.in
raster/test/regress/rt_band.sql [new file with mode: 0644]
raster/test/regress/rt_band_expected [new file with mode: 0644]

index 2c06efee69ad01b90c715fc0d6d3df4aa1c95219..dd5d58309ad3e2bd7f2821386367af626bc6821e 100644 (file)
@@ -3850,3 +3850,54 @@ int32_t rt_raster_copy_band(rt_raster torast,
     return rt_raster_add_band(torast, newband, toindex);
 }
 
+/**
+ * Construct a new rt_raster from an existing rt_raster and an array
+ * of band numbers
+ *
+ * @param raster : the source raster
+ * @param bandNums : array of band numbers to extract from source raster
+ *                   and add to the new raster (0 based)
+ * @param count : number of elements in bandNums
+ *
+ * @return a new rt_raster or 0 on error
+ */
+rt_raster
+rt_raster_from_band(rt_raster raster, uint32_t *bandNums, int count) {
+       rt_raster rast = NULL;
+       int i = 0;
+       int idx;
+       int32_t flag;
+
+       assert(NULL != raster);
+       assert(NULL != bandNums);
+
+       RASTER_DEBUGF(3, "rt_raster_from_band: source raster has %d bands",
+               rt_raster_get_num_bands(raster));
+
+       /* create new raster */
+       rast = rt_raster_new(raster->width, raster->height);
+       if (!rast) {
+               rterror("rt_raster_from_band: Out of memory allocating new raster\n");
+               return 0;
+       }
+
+       /* copy bands */
+       for (i = 0; i < count; i++) {
+               idx = bandNums[i];
+               flag = rt_raster_copy_band(rast, raster, idx, i);
+
+               if (flag < 0) {
+                       rterror("rt_raster_from_band: Unable to copy band\n");
+                       rt_raster_destroy(rast);
+                       return 0;
+               }
+
+               RASTER_DEBUGF(3, "rt_raster_from_band: band created at index %d",
+                       flag);
+       }
+
+       RASTER_DEBUGF(3, "rt_raster_from_band: new raster has %d bands",
+               rt_raster_get_num_bands(rast));
+       return rast;
+}
+
index 0f33e882caa28543d0a3ad7fc2171bb4dc7f974a..9308b999ecb6fe0a4477e50ad9895c627dd7c497 100644 (file)
@@ -757,6 +757,21 @@ int rt_raster_has_no_band(rt_raster raster, int nband);
 int32_t rt_raster_copy_band(rt_raster torast,
         rt_raster fromrast, int fromindex, int toindex);
 
+/**
+ * Construct a new rt_raster from an existing rt_raster and an array
+ * of band numbers
+ *
+ * @param raster : the source raster
+ * @param bandNums : array of band numbers to extract from source raster
+ *                   and add to the new raster (0 based)
+ * @param count : number of elements in bandNums
+ *
+ * @return a new rt_raster or 0 on error
+ */
+rt_raster rt_raster_from_band(rt_raster raster, uint32_t *bandNums,
+       int count);
+
+
 /*- utilities -------------------------------------------------------*/
 
 /*
index 581a9ad4676e9ae5635c2cf1320bf7aefa422813..8eeea487a7a16845f7b89d2e7ca27476036b0a61 100644 (file)
 #include "rt_api.h"
 #include "../raster_config.h"
 
+#include <utils/lsyscache.h> /* for get_typlenbyvalalign */
+#include <utils/array.h> /* for ArrayType */
+#include <catalog/pg_type.h> /* for INT2OID, INT4OID, FLOAT4OID, FLOAT8OID and TEXTOID */
+
 #define POSTGIS_RASTER_WARN_ON_TRUNCATION
 
 /*
@@ -180,6 +184,9 @@ Datum RASTER_copyband(PG_FUNCTION_ARGS);
 /* Raster analysis */
 Datum RASTER_mapAlgebra(PG_FUNCTION_ARGS);
 
+/* create new raster from existing raster's bands */
+Datum RASTER_band(PG_FUNCTION_ARGS);
+
 
 /* Replace function taken from
  * http://ubuntuforums.org/showthread.php?s=aa6f015109fd7e4c7e30d2fd8b717497&t=141670&page=3
@@ -2617,6 +2624,127 @@ Datum RASTER_mapAlgebra(PG_FUNCTION_ARGS)
     PG_RETURN_POINTER(pgraster);
 }
 
+/**
+ * Return new raster from selected bands of existing raster through ST_Band.
+ * second argument is an array of band numbers (1 based)
+ */
+PG_FUNCTION_INFO_V1(RASTER_band);
+Datum RASTER_band(PG_FUNCTION_ARGS)
+{
+       rt_pgraster *pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       rt_pgraster *pgrast;
+       rt_raster raster;
+       rt_raster rast;
+
+       bool skip = FALSE;
+       ArrayType *array;
+       Oid etype;
+       Datum *e;
+       bool *nulls;
+       int16 typlen;
+       bool typbyval;
+       char typalign;
+       int ndims = 1;
+       int *dims;
+       int *lbs;
+
+       uint32_t *bandNums;
+       uint32 idx = 0;
+       int n;
+       int i = 0;
+       int j = 0;
+
+       raster = rt_raster_deserialize(pgraster);
+       if (!raster) {
+               elog(ERROR, "RASTER_band: Could not deserialize raster");
+               PG_RETURN_NULL();
+       }
+
+       /* process bandNums */
+       if (PG_ARGISNULL(1)) {
+               elog(NOTICE, "Band number(s) not provided.  Returning original raster");
+               skip = TRUE;
+       }
+       do {
+               if (skip) break;
+
+               array = PG_GETARG_ARRAYTYPE_P(1);
+               etype = ARR_ELEMTYPE(array);
+               get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
+
+               switch (etype) {
+                       case INT2OID:
+                       case INT4OID:
+                               break;
+                       default:
+                               elog(ERROR, "RASTER_band: Invalid data type for band number(s)");
+                               rt_raster_destroy(raster);
+                               PG_RETURN_NULL();
+                               break;
+               }
+
+               ndims = ARR_NDIM(array);
+               dims = ARR_DIMS(array);
+               lbs = ARR_LBOUND(array);
+
+               deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
+                       &nulls, &n);
+
+               bandNums = (uint32_t *) palloc(sizeof(uint32_t) * n);
+               for (i = 0, j = 0; i < n; i++) {
+                       if (nulls[i]) continue;
+
+                       switch (etype) {
+                               case INT2OID:
+                                       idx = (uint32_t) DatumGetInt16(e[i]);
+                                       break;
+                               case INT4OID:
+                                       idx = (uint32_t) DatumGetInt32(e[i]);
+                                       break;
+                       }
+
+                       POSTGIS_RT_DEBUGF(3, "band idx (before): %d", idx);
+                       if (idx > pgraster->numBands || idx < 1) {
+        elog(NOTICE, "Invalid band index (must use 1-based). Returning original raster");
+                               pfree(bandNums);
+                               skip = TRUE;
+                       }
+                       if (skip) break;
+
+                       bandNums[j] = idx - 1;
+                       POSTGIS_RT_DEBUGF(3, "bandNums[%d] = %d", j, bandNums[j]);
+                       j++;
+               }
+
+               if (skip || j < 1) {
+                       pfree(bandNums);
+                       skip = TRUE;
+               }
+       }
+       while (0);
+
+       if (!skip) {
+               rast = rt_raster_from_band(raster, bandNums, j);
+               pfree(bandNums);
+               rt_raster_destroy(raster);
+               if (!rast) {
+                       elog(ERROR, "RASTER_band: Could not create new raster");
+                       PG_RETURN_NULL();
+               }
+
+               pgrast = rt_raster_serialize(rast);
+       }
+       else {
+               pgrast = pgraster;
+       }
+
+       if (!pgrast)
+               PG_RETURN_NULL();
+
+       SET_VARSIZE(pgrast, pgrast->size);
+       PG_RETURN_POINTER(pgrast);
+}
+
 /* ---------------------------------------------------------------- */
 /*  Memory allocation / error reporting hooks                       */
 /* ---------------------------------------------------------------- */
index 109f6762da0e6fb204d40ea7dd7b6acb89fb2fa5..5b8fd3210259804e2e5b0e4577a5e0cdd53f9227 100644 (file)
@@ -228,6 +228,34 @@ CREATE OR REPLACE FUNCTION st_addband(torast raster, fromrast raster)
     AS 'select st_addband($1, $2, 1, NULL)'
     LANGUAGE 'SQL' IMMUTABLE STRICT;
 
+-----------------------------------------------------------------------
+-- Constructor ST_Band
+-----------------------------------------------------------------------
+CREATE OR REPLACE FUNCTION st_band(rast raster, nbands int[])
+       RETURNS RASTER
+       AS 'MODULE_PATHNAME', 'RASTER_band'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION st_band(rast raster, nband int)
+       RETURNS RASTER
+       AS $$ SELECT st_band($1, ARRAY[$2]) $$
+       LANGUAGE 'SQL' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION st_band(rast raster, nbands text)
+       RETURNS RASTER
+       AS $$ SELECT st_band($1, regexp_split_to_array(regexp_replace($2, '[[:space:]]', '', 'g'), ',')::int[]) $$
+       LANGUAGE 'SQL' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION st_band(rast raster, nbands text, delimiter char)
+       RETURNS RASTER
+       AS $$ SELECT st_band($1, regexp_split_to_array(regexp_replace($2, '[[:space:]]', '', 'g'), $3)::int[]) $$
+       LANGUAGE 'SQL' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION st_band(rast raster)
+       RETURNS RASTER
+       AS $$ SELECT st_band($1, ARRAY[1]) $$
+       LANGUAGE 'SQL' IMMUTABLE STRICT;
+
 -----------------------------------------------------------------------
 -- MapAlgebra
 -----------------------------------------------------------------------
index 6c629db67cda396d998da84c03d153f7446e4b9b..352dceb52024f3eeb6bb207927dedebea3fde9b6 100644 (file)
@@ -972,6 +972,21 @@ static void testBandHasNoData(rt_band band)
     CHECK_EQUALS(flag, 1);
 }
 
+static void testRasterFromBand(rt_raster raster) {
+       uint32_t bandNums[] = {1,3};
+       int lenBandNums = 2;
+       rt_raster rast;
+
+       rast = rt_raster_from_band(raster, bandNums, lenBandNums);
+       assert(rast);
+
+       CHECK(rast);
+       CHECK(!rt_raster_is_empty(rast));
+       CHECK(!rt_raster_has_no_band(rast, 1));
+
+       rt_raster_destroy(rast);
+}
+
 int
 main()
 {
@@ -1278,6 +1293,11 @@ main()
     printf("Testing band hasnodata flag\n");
     testBandHasNoData(band_64BF);
 
+               printf("Testing rt_raster_from_band\n");
+               testRasterFromBand(raster);
+               printf("Successfully tested rt_raster_from_band\n");
+
+
     deepRelease(raster);
 
     return EXIT_SUCCESS;
index 55cb78cc44775690988a409a9f31bc64ded4d841..3cb3567673a7f689b5ad2d143cc7da78c95c8a4b 100644 (file)
@@ -41,6 +41,7 @@ TEST_FUNC = \
        create_rt_box2d_test.sql \
        rt_box2d.sql \
        rt_addband.sql \
+       rt_band.sql \
        $(NULL)
 
 TEST_PROPS = \
diff --git a/raster/test/regress/rt_band.sql b/raster/test/regress/rt_band.sql
new file mode 100644 (file)
index 0000000..3f4825a
--- /dev/null
@@ -0,0 +1,256 @@
+SELECT ST_Value(ST_Band(ST_AddBand(ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0, -1), 1, '64BF', 123.4567, NULL), ARRAY[1]), 3, 3);
+SELECT ST_Value(ST_Band(ST_AddBand(ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0, -1), 1, '64BF', 1234.567, NULL), 1), 3, 3);
+SELECT ST_Value(ST_Band(ST_AddBand(ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0, -1), 1, '64BF', 1234.567, NULL)), 3, 3);
+SELECT ST_Value(
+       ST_Band(
+               ST_AddBand(
+                       ST_AddBand(
+                               ST_AddBand(
+                                       ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+                                       , 1, '64BF', 1234.5678, NULL
+                               )
+                               , '64BF', 987.654321, NULL
+                       )
+                       , '64BF', 9876.54321, NULL
+               ),
+               ARRAY[1]
+       ),
+3, 3);
+SELECT ST_Value(
+       ST_Band(
+               ST_AddBand(
+                       ST_AddBand(
+                               ST_AddBand(
+                                       ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+                                       , 1, '64BF', 1234.5678, NULL
+                               )
+                               , '64BF', 987.654321, NULL
+                       )
+                       , '64BF', 9876.54321, NULL
+               ),
+               ARRAY[2]
+       ),
+3, 3);
+SELECT ST_Value(
+       ST_Band(
+               ST_AddBand(
+                       ST_AddBand(
+                               ST_AddBand(
+                                       ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+                                       , 1, '64BF', 1234.5678, NULL
+                               )
+                               , '64BF', 987.654321, NULL
+                       )
+                       , '64BF', 9876.54321, NULL
+               ),
+               ARRAY[3]
+       ),
+3, 3);
+SELECT ST_Value(
+       ST_Band(
+               ST_AddBand(
+                       ST_AddBand(
+                               ST_AddBand(
+                                       ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+                                       , 1, '64BF', 1234.5678, NULL
+                               )
+                               , '64BF', 987.654321, NULL
+                       )
+                       , '64BF', 9876.54321, NULL
+               ),
+               1
+       ),
+3, 3);
+SELECT ST_Value(
+       ST_Band(
+               ST_AddBand(
+                       ST_AddBand(
+                               ST_AddBand(
+                                       ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+                                       , 1, '64BF', 1234.5678, NULL
+                               )
+                               , '64BF', 987.654321, NULL
+                       )
+                       , '64BF', 9876.54321, NULL
+               ),
+               2
+       ),
+3, 3);
+SELECT ST_Value(
+       ST_Band(
+               ST_AddBand(
+                       ST_AddBand(
+                               ST_AddBand(
+                                       ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+                                       , 1, '64BF', 1234.5678, NULL
+                               )
+                               , '64BF', 987.654321, NULL
+                       )
+                       , '64BF', 9876.54321, NULL
+               ),
+               3
+       ),
+3, 3);
+SELECT ST_Value(
+       ST_Band(
+               ST_AddBand(
+                       ST_AddBand(
+                               ST_AddBand(
+                                       ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+                                       , 1, '64BF', 1234.5678, NULL
+                               )
+                               , '64BF', 987.654321, NULL
+                       )
+                       , '64BF', 9876.54321, NULL
+               )
+       ),
+3, 3);
+SELECT ST_Value(
+       ST_Band(
+               ST_AddBand(
+                       ST_AddBand(
+                               ST_AddBand(
+                                       ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+                                       , 1, '64BF', 1234.5678, NULL
+                               )
+                               , '64BF', 987.654321, NULL
+                       )
+                       , '64BF', 9876.54321, NULL
+               ),
+               ARRAY[1,3]
+       ),
+1, 3, 3);
+SELECT ST_Value(
+       ST_Band(
+               ST_AddBand(
+                       ST_AddBand(
+                               ST_AddBand(
+                                       ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+                                       , 1, '64BF', 1234.5678, NULL
+                               )
+                               , '64BF', 987.654321, NULL
+                       )
+                       , '64BF', 9876.54321, NULL
+               ),
+               ARRAY[1,3]
+       ),
+2, 3, 3);
+SELECT ST_Value(
+       ST_Band(
+               ST_AddBand(
+                       ST_AddBand(
+                               ST_AddBand(
+                                       ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+                                       , 1, '64BF', 1234.5678, NULL
+                               )
+                               , '64BF', 987.654321, NULL
+                       )
+                       , '64BF', 9876.54321, NULL
+               ),
+               ARRAY[2,3]
+       ),
+1, 3, 3);
+SELECT ST_Value(
+       ST_Band(
+               ST_AddBand(
+                       ST_AddBand(
+                               ST_AddBand(
+                                       ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+                                       , 1, '64BF', 1234.5678, NULL
+                               )
+                               , '64BF', 987.654321, NULL
+                       )
+                       , '64BF', 9876.54321, NULL
+               ),
+               ARRAY[1,1]
+       ),
+2, 3, 3);
+SELECT ST_NumBands(
+       ST_Band(
+               ST_AddBand(
+                       ST_AddBand(
+                               ST_AddBand(
+                                       ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+                                       , 1, '64BF', 1234.5678, NULL
+                               )
+                               , '64BF', 987.654321, NULL
+                       )
+                       , '64BF', 9876.54321, NULL
+               ),
+               ARRAY[1,1,3,3]
+       )
+);
+SELECT ST_NumBands(
+       ST_Band(
+               ST_AddBand(
+                       ST_AddBand(
+                               ST_AddBand(
+                                       ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+                                       , 1, '64BF', 1234.5678, NULL
+                               )
+                               , '64BF', 987.654321, NULL
+                       )
+                       , '64BF', 9876.54321, NULL
+               ),
+               ARRAY[1,1,3]
+       )
+);
+SELECT ST_NumBands(
+       ST_Band(
+               ST_AddBand(
+                       ST_AddBand(
+                               ST_AddBand(
+                                       ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+                                       , 1, '64BF', 1234.5678, NULL
+                               )
+                               , '64BF', 987.654321, NULL
+                       )
+                       , '64BF', 9876.54321, NULL
+               ),
+               ARRAY[1,2]
+       )
+);
+SELECT ST_NumBands(
+       ST_Band(
+               ST_AddBand(
+                       ST_AddBand(
+                               ST_AddBand(
+                                       ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+                                       , 1, '64BF', 1234.5678, NULL
+                               )
+                               , '64BF', 987.654321, NULL
+                       )
+                       , '64BF', 9876.54321, NULL
+               ),
+               ARRAY[3]
+       )
+);
+SELECT ST_NumBands(
+       ST_Band(
+               ST_AddBand(
+                       ST_AddBand(
+                               ST_AddBand(
+                                       ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+                                       , 1, '64BF', 1234.5678, NULL
+                               )
+                               , '64BF', 987.654321, NULL
+                       )
+                       , '64BF', 9876.54321, NULL
+               ),
+               2
+       )
+);
+SELECT ST_NumBands(
+       ST_Band(
+               ST_AddBand(
+                       ST_AddBand(
+                               ST_AddBand(
+                                       ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+                                       , 1, '64BF', 1234.5678, NULL
+                               )
+                               , '64BF', 987.654321, NULL
+                       )
+                       , '64BF', 9876.54321, NULL
+               )
+       )
+);
diff --git a/raster/test/regress/rt_band_expected b/raster/test/regress/rt_band_expected
new file mode 100644 (file)
index 0000000..ed11fcc
--- /dev/null
@@ -0,0 +1,20 @@
+123.4567
+1234.567
+1234.567
+1234.5678
+987.654321
+9876.54321
+1234.5678
+987.654321
+9876.54321
+1234.5678
+1234.5678
+9876.54321
+987.654321
+1234.5678
+4
+3
+2
+1
+1
+1