Ticket #339: st_band.patch

File st_band.patch, 14.9 KB (added by dustymugs, 13 months ago)

Adds ST_Band support. Includes core and regression tests

  • raster/test/core/testapi.c

     
    972972    CHECK_EQUALS(flag, 1); 
    973973} 
    974974 
     975static void testRasterFromBand(rt_context ctx, rt_raster raster) { 
     976        uint32_t bandNums[] = {1,3}; 
     977        int lenBandNums = 2; 
     978        rt_raster rast; 
     979 
     980        rast = rt_raster_from_band(ctx, raster, bandNums, lenBandNums); 
     981        assert(rast); 
     982 
     983        CHECK(rast); 
     984        CHECK(!rt_raster_is_empty(ctx, rast)); 
     985        CHECK(!rt_raster_has_no_band(ctx, rast, 1)); 
     986 
     987        rt_raster_destroy(ctx, rast); 
     988} 
     989 
    975990int 
    976991main() 
    977992{ 
     
    12821297    printf("Testing band hasnodata flag\n"); 
    12831298    testBandHasNoData(ctx, band_64BF); 
    12841299 
     1300                printf("Testing rt_raster_from_band\n"); 
     1301                testRasterFromBand(ctx, raster); 
     1302                printf("Successfully tested rt_raster_from_band\n"); 
     1303 
    12851304    deepRelease(ctx, raster); 
    12861305    rt_context_destroy(ctx); 
    12871306 
  • raster/test/regress/Makefile.in

     
    4141        create_rt_box2d_test.sql \ 
    4242        rt_box2d.sql \ 
    4343        rt_addband.sql \ 
     44        rt_band.sql \ 
    4445        $(NULL) 
    4546 
    4647TEST_PROPS = \ 
  • raster/test/regress/rt_band_expected

     
     1123.4567 
     21234.567 
     31234.567 
     41234.5678 
     5987.654321 
     69876.54321 
     71234.5678 
     8987.654321 
     99876.54321 
     101234.5678 
     111234.5678 
     129876.54321 
     13987.654321 
     141234.5678 
     154 
     163 
     172 
     181 
     191 
     201 
  • raster/test/regress/rt_band.sql

     
     1SELECT 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); 
     2SELECT 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); 
     3SELECT ST_Value(ST_Band(ST_AddBand(ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0, -1), 1, '64BF', 1234.567, NULL)), 3, 3); 
     4SELECT ST_Value( 
     5        ST_Band( 
     6                ST_AddBand( 
     7                        ST_AddBand( 
     8                                ST_AddBand( 
     9                                        ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1) 
     10                                        , 1, '64BF', 1234.5678, NULL 
     11                                ) 
     12                                , '64BF', 987.654321, NULL 
     13                        ) 
     14                        , '64BF', 9876.54321, NULL 
     15                ), 
     16                ARRAY[1] 
     17        ), 
     183, 3); 
     19SELECT ST_Value( 
     20        ST_Band( 
     21                ST_AddBand( 
     22                        ST_AddBand( 
     23                                ST_AddBand( 
     24                                        ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1) 
     25                                        , 1, '64BF', 1234.5678, NULL 
     26                                ) 
     27                                , '64BF', 987.654321, NULL 
     28                        ) 
     29                        , '64BF', 9876.54321, NULL 
     30                ), 
     31                ARRAY[2] 
     32        ), 
     333, 3); 
     34SELECT ST_Value( 
     35        ST_Band( 
     36                ST_AddBand( 
     37                        ST_AddBand( 
     38                                ST_AddBand( 
     39                                        ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1) 
     40                                        , 1, '64BF', 1234.5678, NULL 
     41                                ) 
     42                                , '64BF', 987.654321, NULL 
     43                        ) 
     44                        , '64BF', 9876.54321, NULL 
     45                ), 
     46                ARRAY[3] 
     47        ), 
     483, 3); 
     49SELECT ST_Value( 
     50        ST_Band( 
     51                ST_AddBand( 
     52                        ST_AddBand( 
     53                                ST_AddBand( 
     54                                        ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1) 
     55                                        , 1, '64BF', 1234.5678, NULL 
     56                                ) 
     57                                , '64BF', 987.654321, NULL 
     58                        ) 
     59                        , '64BF', 9876.54321, NULL 
     60                ), 
     61                1 
     62        ), 
     633, 3); 
     64SELECT ST_Value( 
     65        ST_Band( 
     66                ST_AddBand( 
     67                        ST_AddBand( 
     68                                ST_AddBand( 
     69                                        ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1) 
     70                                        , 1, '64BF', 1234.5678, NULL 
     71                                ) 
     72                                , '64BF', 987.654321, NULL 
     73                        ) 
     74                        , '64BF', 9876.54321, NULL 
     75                ), 
     76                2 
     77        ), 
     783, 3); 
     79SELECT ST_Value( 
     80        ST_Band( 
     81                ST_AddBand( 
     82                        ST_AddBand( 
     83                                ST_AddBand( 
     84                                        ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1) 
     85                                        , 1, '64BF', 1234.5678, NULL 
     86                                ) 
     87                                , '64BF', 987.654321, NULL 
     88                        ) 
     89                        , '64BF', 9876.54321, NULL 
     90                ), 
     91                3 
     92        ), 
     933, 3); 
     94SELECT ST_Value( 
     95        ST_Band( 
     96                ST_AddBand( 
     97                        ST_AddBand( 
     98                                ST_AddBand( 
     99                                        ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1) 
     100                                        , 1, '64BF', 1234.5678, NULL 
     101                                ) 
     102                                , '64BF', 987.654321, NULL 
     103                        ) 
     104                        , '64BF', 9876.54321, NULL 
     105                ) 
     106        ), 
     1073, 3); 
     108SELECT ST_Value( 
     109        ST_Band( 
     110                ST_AddBand( 
     111                        ST_AddBand( 
     112                                ST_AddBand( 
     113                                        ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1) 
     114                                        , 1, '64BF', 1234.5678, NULL 
     115                                ) 
     116                                , '64BF', 987.654321, NULL 
     117                        ) 
     118                        , '64BF', 9876.54321, NULL 
     119                ), 
     120                ARRAY[1,3] 
     121        ), 
     1221, 3, 3); 
     123SELECT ST_Value( 
     124        ST_Band( 
     125                ST_AddBand( 
     126                        ST_AddBand( 
     127                                ST_AddBand( 
     128                                        ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1) 
     129                                        , 1, '64BF', 1234.5678, NULL 
     130                                ) 
     131                                , '64BF', 987.654321, NULL 
     132                        ) 
     133                        , '64BF', 9876.54321, NULL 
     134                ), 
     135                ARRAY[1,3] 
     136        ), 
     1372, 3, 3); 
     138SELECT ST_Value( 
     139        ST_Band( 
     140                ST_AddBand( 
     141                        ST_AddBand( 
     142                                ST_AddBand( 
     143                                        ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1) 
     144                                        , 1, '64BF', 1234.5678, NULL 
     145                                ) 
     146                                , '64BF', 987.654321, NULL 
     147                        ) 
     148                        , '64BF', 9876.54321, NULL 
     149                ), 
     150                ARRAY[2,3] 
     151        ), 
     1521, 3, 3); 
     153SELECT ST_Value( 
     154        ST_Band( 
     155                ST_AddBand( 
     156                        ST_AddBand( 
     157                                ST_AddBand( 
     158                                        ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1) 
     159                                        , 1, '64BF', 1234.5678, NULL 
     160                                ) 
     161                                , '64BF', 987.654321, NULL 
     162                        ) 
     163                        , '64BF', 9876.54321, NULL 
     164                ), 
     165                ARRAY[1,1] 
     166        ), 
     1672, 3, 3); 
     168SELECT ST_NumBands( 
     169        ST_Band( 
     170                ST_AddBand( 
     171                        ST_AddBand( 
     172                                ST_AddBand( 
     173                                        ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1) 
     174                                        , 1, '64BF', 1234.5678, NULL 
     175                                ) 
     176                                , '64BF', 987.654321, NULL 
     177                        ) 
     178                        , '64BF', 9876.54321, NULL 
     179                ), 
     180                ARRAY[1,1,3,3] 
     181        ) 
     182); 
     183SELECT ST_NumBands( 
     184        ST_Band( 
     185                ST_AddBand( 
     186                        ST_AddBand( 
     187                                ST_AddBand( 
     188                                        ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1) 
     189                                        , 1, '64BF', 1234.5678, NULL 
     190                                ) 
     191                                , '64BF', 987.654321, NULL 
     192                        ) 
     193                        , '64BF', 9876.54321, NULL 
     194                ), 
     195                ARRAY[1,1,3] 
     196        ) 
     197); 
     198SELECT ST_NumBands( 
     199        ST_Band( 
     200                ST_AddBand( 
     201                        ST_AddBand( 
     202                                ST_AddBand( 
     203                                        ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1) 
     204                                        , 1, '64BF', 1234.5678, NULL 
     205                                ) 
     206                                , '64BF', 987.654321, NULL 
     207                        ) 
     208                        , '64BF', 9876.54321, NULL 
     209                ), 
     210                ARRAY[1,2] 
     211        ) 
     212); 
     213SELECT ST_NumBands( 
     214        ST_Band( 
     215                ST_AddBand( 
     216                        ST_AddBand( 
     217                                ST_AddBand( 
     218                                        ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1) 
     219                                        , 1, '64BF', 1234.5678, NULL 
     220                                ) 
     221                                , '64BF', 987.654321, NULL 
     222                        ) 
     223                        , '64BF', 9876.54321, NULL 
     224                ), 
     225                ARRAY[3] 
     226        ) 
     227); 
     228SELECT ST_NumBands( 
     229        ST_Band( 
     230                ST_AddBand( 
     231                        ST_AddBand( 
     232                                ST_AddBand( 
     233                                        ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1) 
     234                                        , 1, '64BF', 1234.5678, NULL 
     235                                ) 
     236                                , '64BF', 987.654321, NULL 
     237                        ) 
     238                        , '64BF', 9876.54321, NULL 
     239                ), 
     240                2 
     241        ) 
     242); 
     243SELECT ST_NumBands( 
     244        ST_Band( 
     245                ST_AddBand( 
     246                        ST_AddBand( 
     247                                ST_AddBand( 
     248                                        ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1) 
     249                                        , 1, '64BF', 1234.5678, NULL 
     250                                ) 
     251                                , '64BF', 987.654321, NULL 
     252                        ) 
     253                        , '64BF', 9876.54321, NULL 
     254                ) 
     255        ) 
     256); 
  • raster/rt_pg/rtpostgis.sql.in.c

     
    229229    LANGUAGE 'SQL' IMMUTABLE STRICT; 
    230230 
    231231----------------------------------------------------------------------- 
     232-- Constructor ST_Band 
     233----------------------------------------------------------------------- 
     234CREATE OR REPLACE FUNCTION st_band(rast raster, nbands int[]) 
     235        RETURNS RASTER 
     236        AS 'MODULE_PATHNAME', 'RASTER_band' 
     237        LANGUAGE 'C' IMMUTABLE STRICT; 
     238 
     239CREATE OR REPLACE FUNCTION st_band(rast raster, nband int) 
     240        RETURNS RASTER 
     241        AS $$ SELECT st_band($1, ARRAY[$2]) $$ 
     242        LANGUAGE 'SQL' IMMUTABLE STRICT; 
     243 
     244CREATE OR REPLACE FUNCTION st_band(rast raster, nbands text) 
     245        RETURNS RASTER 
     246        AS $$ SELECT st_band($1, regexp_split_to_array(regexp_replace($2, '[[:space:]]', '', 'g'), ',')::int[]) $$ 
     247        LANGUAGE 'SQL' IMMUTABLE STRICT; 
     248 
     249CREATE OR REPLACE FUNCTION st_band(rast raster, nbands text, delimiter char) 
     250        RETURNS RASTER 
     251        AS $$ SELECT st_band($1, regexp_split_to_array(regexp_replace($2, '[[:space:]]', '', 'g'), $3)::int[]) $$ 
     252        LANGUAGE 'SQL' IMMUTABLE STRICT; 
     253 
     254CREATE OR REPLACE FUNCTION st_band(rast raster) 
     255        RETURNS RASTER 
     256        AS $$ SELECT st_band($1, ARRAY[1]) $$ 
     257        LANGUAGE 'SQL' IMMUTABLE STRICT; 
     258 
     259----------------------------------------------------------------------- 
    232260-- MapAlgebra 
    233261----------------------------------------------------------------------- 
    234262-- This function can not be STRICT, because nodatavalueexpr can be NULL (could be just '' though) 
  • raster/rt_pg/rt_pg.c

     
    4949#include "rt_api.h" 
    5050#include "../raster_config.h" 
    5151 
     52#include <utils/lsyscache.h> /* for get_typlenbyvalalign */ 
     53#include <utils/array.h> /* for ArrayType */ 
     54#include <catalog/pg_type.h> /* for INT2OID, INT4OID and TEXTOID */ 
     55 
    5256#define POSTGIS_RASTER_WARN_ON_TRUNCATION 
    5357 
    5458/* 
     
    158162/* Raster analysis */ 
    159163Datum RASTER_mapAlgebra(PG_FUNCTION_ARGS); 
    160164 
     165/* create new raster from existing raster's bands */ 
     166Datum RASTER_band(PG_FUNCTION_ARGS); 
    161167 
     168 
    162169/* Replace function taken from http://ubuntuforums.org/showthread.php?s=aa6f015109fd7e4c7e30d2fd8b717497&t=141670&page=3 */ 
    163170/* --------------------------------------------------------------------------- 
    164171  Name       : replace - Search & replace a substring by another one. 
     
    26772684    PG_RETURN_POINTER(pgraster); 
    26782685} 
    26792686 
     2687/** 
     2688 * Return new raster from selected bands of existing raster through ST_Band. 
     2689 * second argument is an array of band numbers (1 based) 
     2690 */ 
     2691PG_FUNCTION_INFO_V1(RASTER_band); 
     2692Datum RASTER_band(PG_FUNCTION_ARGS) 
     2693{ 
     2694        rt_pgraster *pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); 
     2695        rt_pgraster *pgrast; 
     2696        rt_raster raster; 
     2697        rt_raster rast; 
     2698        rt_context ctx = get_rt_context(fcinfo); 
     2699 
     2700        ArrayType *array; 
     2701        Oid etype; 
     2702        Datum *e; 
     2703        bool *nulls; 
     2704        int16 typlen; 
     2705        bool typbyval; 
     2706        char typalign; 
     2707        int ndims = 1; 
     2708        int *dims; 
     2709        int *lbs; 
     2710 
     2711        uint32_t *bandNums; 
     2712        uint32 idx = 0; 
     2713        int n; 
     2714        int i = 0; 
     2715        int j = 0; 
     2716 
     2717        raster = rt_raster_deserialize(ctx, pgraster); 
     2718        if (!raster) { 
     2719                elog(ERROR, "RASTER_band: Could not deserialize raster"); 
     2720                rt_context_destroy(ctx);         
     2721                PG_RETURN_NULL(); 
     2722        } 
     2723 
     2724        /* process bandNums */ 
     2725        if (PG_ARGISNULL(1)) { 
     2726                elog(ERROR, "RASTER_band: Band number must be provided"); 
     2727                rt_raster_destroy(ctx, raster); 
     2728                rt_context_destroy(ctx);         
     2729                PG_RETURN_NULL(); 
     2730        } 
     2731 
     2732        array = PG_GETARG_ARRAYTYPE_P(1); 
     2733        etype = ARR_ELEMTYPE(array); 
     2734        get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign); 
     2735 
     2736        switch (etype) { 
     2737                case INT2OID: 
     2738                case INT4OID: 
     2739                        break; 
     2740                default: 
     2741                        elog(ERROR, "RASTER_band: Invalid data type for band numbers"); 
     2742                        rt_raster_destroy(ctx, raster); 
     2743                        rt_context_destroy(ctx);         
     2744                        PG_RETURN_NULL(); 
     2745                        break; 
     2746        } 
     2747 
     2748        ndims = ARR_NDIM(array); 
     2749        dims = ARR_DIMS(array); 
     2750        lbs = ARR_LBOUND(array); 
     2751 
     2752        deconstruct_array(array, etype, typlen, typbyval, typalign, &e, 
     2753                &nulls, &n); 
     2754 
     2755        bandNums = (uint32_t *) palloc(sizeof(uint32_t) * n); 
     2756        for (i = 0, j = 0; i < n; i++) { 
     2757                if (nulls[i]) 
     2758                        continue; 
     2759 
     2760                switch (etype) { 
     2761                        case INT2OID: 
     2762                                idx = (uint32_t) DatumGetInt16(e[i]); 
     2763                                break; 
     2764                        case INT4OID: 
     2765                                idx = (uint32_t) DatumGetInt32(e[i]); 
     2766                                break; 
     2767                } 
     2768 
     2769                POSTGIS_RT_DEBUGF(3, "band idx (before): %d", idx); 
     2770                if (idx > pgraster->numBands || idx < 1) { 
     2771                        pfree(bandNums); 
     2772                        elog(ERROR, "RASTER_band: Invalid band number provided"); 
     2773                        rt_raster_destroy(ctx, raster); 
     2774                        rt_context_destroy(ctx);         
     2775                        PG_RETURN_NULL(); 
     2776                } 
     2777 
     2778                bandNums[j] = idx - 1; 
     2779                POSTGIS_RT_DEBUGF(3, "bandNums[%d] = %d", j, bandNums[j]); 
     2780                j++; 
     2781        } 
     2782 
     2783        rast = rt_raster_from_band(ctx, raster, bandNums, j); 
     2784        pfree(bandNums); 
     2785        rt_raster_destroy(ctx, raster); 
     2786        if (!rast) { 
     2787                elog(ERROR, "RASTER_band: Could not create new raster"); 
     2788                rt_context_destroy(ctx);         
     2789                PG_RETURN_NULL(); 
     2790        } 
     2791 
     2792        pgrast = rt_raster_serialize(ctx, rast); 
     2793        rt_context_destroy(ctx);         
     2794        if (!pgrast) 
     2795                PG_RETURN_NULL(); 
     2796 
     2797        SET_VARSIZE(pgrast, pgrast->size); 
     2798        PG_RETURN_POINTER(pgrast); 
     2799} 
     2800 
    26802801/* ---------------------------------------------------------------- */ 
    26812802/*  Memory allocation / error reporting hooks                       */ 
    26822803/* ---------------------------------------------------------------- */ 
  • raster/rt_core/rt_api.c

     
    36183618    return rt_raster_add_band(ctx, torast, newband, toindex); 
    36193619} 
    36203620 
     3621/** 
     3622 * Construct a new rt_raster from an existing rt_raster and an array 
     3623 * of band numbers 
     3624 * 
     3625 * @param ctx : context, for thread safety 
     3626 * @param raster : the source raster 
     3627 * @param bandNums : array of band numbers to extract from source raster 
     3628 *                   and add to the new raster (0 based) 
     3629 * @param count : number of elements in bandNums 
     3630 * @return a new rt_raster or 0 on error 
     3631 * 
     3632 */ 
     3633rt_raster 
     3634rt_raster_from_band(rt_context ctx, rt_raster raster, 
     3635                uint32_t *bandNums, int count) { 
     3636        rt_raster rast = NULL; 
     3637        int i = 0; 
     3638        int idx; 
     3639        int32_t flag; 
     3640 
     3641        assert(NULL != ctx); 
     3642        assert(NULL != raster); 
     3643        assert(NULL != bandNums); 
     3644 
     3645        RASTER_DEBUGF(3, "rt_raster_from_band: source raster has %d bands", 
     3646                rt_raster_get_num_bands(ctx, raster)); 
     3647 
     3648        /* create new raster */ 
     3649        rast = rt_raster_new(ctx, raster->width, raster->height); 
     3650        if (!rast) { 
     3651                ctx->err("rt_raster_from_band: Out of memory allocating new raster\n"); 
     3652                return 0; 
     3653        } 
     3654 
     3655        /* copy bands */ 
     3656        for (i = 0; i < count; i++) { 
     3657                idx = bandNums[i]; 
     3658                flag = rt_raster_copy_band(ctx, rast, raster, idx, i); 
     3659 
     3660                if (flag < 0) { 
     3661                        ctx->err("rt_raster_from_band: Unable to copy band\n"); 
     3662                        rt_raster_destroy(ctx, rast); 
     3663                        return 0; 
     3664                } 
     3665 
     3666                RASTER_DEBUGF(3, "rt_raster_from_band: band created at index %d", 
     3667                        flag); 
     3668        } 
     3669 
     3670        RASTER_DEBUGF(3, "rt_raster_from_band: new raster has %d bands", 
     3671                rt_raster_get_num_bands(ctx, rast)); 
     3672        return rast; 
     3673} 
  • raster/rt_core/rt_api.h

     
    737737int32_t rt_raster_copy_band(rt_context ctx, rt_raster torast, 
    738738        rt_raster fromrast, int fromindex, int toindex); 
    739739 
     740/** 
     741 * Construct a new rt_raster from an existing rt_raster and an array 
     742 * of band numbers 
     743 * 
     744 * @param ctx : context, for thread safety 
     745 * @param raster : the source raster 
     746 * @param bandNums : array of band numbers to extract from source raster 
     747 *                   and add to the new raster (0 based) 
     748 * @param count : number of elements in bandNums 
     749 * @return a new rt_raster or 0 on error 
     750 * 
     751 */ 
     752rt_raster rt_raster_from_band(rt_context ctx, rt_raster raster, 
     753        uint32_t *bandNums, int count); 
     754 
    740755/*- utilities -------------------------------------------------------*/ 
    741756 
    742757/* Set of functions to clamp double to int of different size