Ticket #339: st_band.3.patch

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

Refactored to account for changed memory handling.

  • raster/rt_core/rt_api.c

    diff -rupN postgis-old/raster/rt_core/rt_api.c postgis-new/raster/rt_core/rt_api.c
    old new  
    38503850    return rt_raster_add_band(torast, newband, toindex); 
    38513851} 
    38523852 
     3853/** 
     3854 * Construct a new rt_raster from an existing rt_raster and an array 
     3855 * of band numbers 
     3856 * 
     3857 * @param raster : the source raster 
     3858 * @param bandNums : array of band numbers to extract from source raster 
     3859 *                   and add to the new raster (0 based) 
     3860 * @param count : number of elements in bandNums 
     3861 * 
     3862 * @return a new rt_raster or 0 on error 
     3863 */ 
     3864rt_raster 
     3865rt_raster_from_band(rt_raster raster, uint32_t *bandNums, int count) { 
     3866        rt_raster rast = NULL; 
     3867        int i = 0; 
     3868        int idx; 
     3869        int32_t flag; 
     3870 
     3871        assert(NULL != raster); 
     3872        assert(NULL != bandNums); 
     3873 
     3874        RASTER_DEBUGF(3, "rt_raster_from_band: source raster has %d bands", 
     3875                rt_raster_get_num_bands(raster)); 
     3876 
     3877        /* create new raster */ 
     3878        rast = rt_raster_new(raster->width, raster->height); 
     3879        if (!rast) { 
     3880                rterror("rt_raster_from_band: Out of memory allocating new raster\n"); 
     3881                return 0; 
     3882        } 
     3883 
     3884        /* copy bands */ 
     3885        for (i = 0; i < count; i++) { 
     3886                idx = bandNums[i]; 
     3887                flag = rt_raster_copy_band(rast, raster, idx, i); 
     3888 
     3889                if (flag < 0) { 
     3890                        rterror("rt_raster_from_band: Unable to copy band\n"); 
     3891                        rt_raster_destroy(rast); 
     3892                        return 0; 
     3893                } 
     3894 
     3895                RASTER_DEBUGF(3, "rt_raster_from_band: band created at index %d", 
     3896                        flag); 
     3897        } 
     3898 
     3899        RASTER_DEBUGF(3, "rt_raster_from_band: new raster has %d bands", 
     3900                rt_raster_get_num_bands(rast)); 
     3901        return rast; 
     3902} 
     3903 
  • raster/rt_core/rt_api.h

    diff -rupN postgis-old/raster/rt_core/rt_api.h postgis-new/raster/rt_core/rt_api.h
    old new  
    757757int32_t rt_raster_copy_band(rt_raster torast, 
    758758        rt_raster fromrast, int fromindex, int toindex); 
    759759 
     760/** 
     761 * Construct a new rt_raster from an existing rt_raster and an array 
     762 * of band numbers 
     763 * 
     764 * @param raster : the source raster 
     765 * @param bandNums : array of band numbers to extract from source raster 
     766 *                   and add to the new raster (0 based) 
     767 * @param count : number of elements in bandNums 
     768 * 
     769 * @return a new rt_raster or 0 on error 
     770 */ 
     771rt_raster rt_raster_from_band(rt_raster raster, uint32_t *bandNums, 
     772        int count); 
     773 
     774 
    760775/*- utilities -------------------------------------------------------*/ 
    761776 
    762777/* 
  • raster/rt_pg/rt_pg.c

    diff -rupN postgis-old/raster/rt_pg/rt_pg.c postgis-new/raster/rt_pg/rt_pg.c
    old new  
    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, FLOAT4OID, FLOAT8OID and TEXTOID */ 
     55 
    5256#define POSTGIS_RASTER_WARN_ON_TRUNCATION 
    5357 
    5458/* 
     
    180184/* Raster analysis */ 
    181185Datum RASTER_mapAlgebra(PG_FUNCTION_ARGS); 
    182186 
     187/* create new raster from existing raster's bands */ 
     188Datum RASTER_band(PG_FUNCTION_ARGS); 
     189 
    183190 
    184191/* Replace function taken from 
    185192 * http://ubuntuforums.org/showthread.php?s=aa6f015109fd7e4c7e30d2fd8b717497&t=141670&page=3 
     
    26172624    PG_RETURN_POINTER(pgraster); 
    26182625} 
    26192626 
     2627/** 
     2628 * Return new raster from selected bands of existing raster through ST_Band. 
     2629 * second argument is an array of band numbers (1 based) 
     2630 */ 
     2631PG_FUNCTION_INFO_V1(RASTER_band); 
     2632Datum RASTER_band(PG_FUNCTION_ARGS) 
     2633{ 
     2634        rt_pgraster *pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); 
     2635        rt_pgraster *pgrast; 
     2636        rt_raster raster; 
     2637        rt_raster rast; 
     2638 
     2639        bool skip = FALSE; 
     2640        ArrayType *array; 
     2641        Oid etype; 
     2642        Datum *e; 
     2643        bool *nulls; 
     2644        int16 typlen; 
     2645        bool typbyval; 
     2646        char typalign; 
     2647        int ndims = 1; 
     2648        int *dims; 
     2649        int *lbs; 
     2650 
     2651        uint32_t *bandNums; 
     2652        uint32 idx = 0; 
     2653        int n; 
     2654        int i = 0; 
     2655        int j = 0; 
     2656 
     2657        raster = rt_raster_deserialize(pgraster); 
     2658        if (!raster) { 
     2659                elog(ERROR, "RASTER_band: Could not deserialize raster"); 
     2660                PG_RETURN_NULL(); 
     2661        } 
     2662 
     2663        /* process bandNums */ 
     2664        if (PG_ARGISNULL(1)) { 
     2665                elog(NOTICE, "Band number(s) not provided.  Returning original raster"); 
     2666                skip = TRUE; 
     2667        } 
     2668        do { 
     2669                if (skip) break; 
     2670 
     2671                array = PG_GETARG_ARRAYTYPE_P(1); 
     2672                etype = ARR_ELEMTYPE(array); 
     2673                get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign); 
     2674 
     2675                switch (etype) { 
     2676                        case INT2OID: 
     2677                        case INT4OID: 
     2678                                break; 
     2679                        default: 
     2680                                elog(ERROR, "RASTER_band: Invalid data type for band number(s)"); 
     2681                                rt_raster_destroy(raster); 
     2682                                PG_RETURN_NULL(); 
     2683                                break; 
     2684                } 
     2685 
     2686                ndims = ARR_NDIM(array); 
     2687                dims = ARR_DIMS(array); 
     2688                lbs = ARR_LBOUND(array); 
     2689 
     2690                deconstruct_array(array, etype, typlen, typbyval, typalign, &e, 
     2691                        &nulls, &n); 
     2692 
     2693                bandNums = (uint32_t *) palloc(sizeof(uint32_t) * n); 
     2694                for (i = 0, j = 0; i < n; i++) { 
     2695                        if (nulls[i]) continue; 
     2696 
     2697                        switch (etype) { 
     2698                                case INT2OID: 
     2699                                        idx = (uint32_t) DatumGetInt16(e[i]); 
     2700                                        break; 
     2701                                case INT4OID: 
     2702                                        idx = (uint32_t) DatumGetInt32(e[i]); 
     2703                                        break; 
     2704                        } 
     2705 
     2706                        POSTGIS_RT_DEBUGF(3, "band idx (before): %d", idx); 
     2707                        if (idx > pgraster->numBands || idx < 1) { 
     2708        elog(NOTICE, "Invalid band index (must use 1-based). Returning original raster"); 
     2709                                pfree(bandNums); 
     2710                                skip = TRUE; 
     2711                        } 
     2712                        if (skip) break; 
     2713 
     2714                        bandNums[j] = idx - 1; 
     2715                        POSTGIS_RT_DEBUGF(3, "bandNums[%d] = %d", j, bandNums[j]); 
     2716                        j++; 
     2717                } 
     2718 
     2719                if (skip || j < 1) { 
     2720                        pfree(bandNums); 
     2721                        skip = TRUE; 
     2722                } 
     2723        } 
     2724        while (0); 
     2725 
     2726        if (!skip) { 
     2727                rast = rt_raster_from_band(raster, bandNums, j); 
     2728                pfree(bandNums); 
     2729                rt_raster_destroy(raster); 
     2730                if (!rast) { 
     2731                        elog(ERROR, "RASTER_band: Could not create new raster"); 
     2732                        PG_RETURN_NULL(); 
     2733                } 
     2734 
     2735                pgrast = rt_raster_serialize(rast); 
     2736        } 
     2737        else { 
     2738                pgrast = pgraster; 
     2739        } 
     2740 
     2741        if (!pgrast) 
     2742                PG_RETURN_NULL(); 
     2743 
     2744        SET_VARSIZE(pgrast, pgrast->size); 
     2745        PG_RETURN_POINTER(pgrast); 
     2746} 
     2747 
    26202748/* ---------------------------------------------------------------- */ 
    26212749/*  Memory allocation / error reporting hooks                       */ 
    26222750/* ---------------------------------------------------------------- */ 
  • raster/rt_pg/rtpostgis.sql.in.c

    diff -rupN postgis-old/raster/rt_pg/rtpostgis.sql.in.c postgis-new/raster/rt_pg/rtpostgis.sql.in.c
    old new  
    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/test/core/testapi.c

    diff -rupN postgis-old/raster/test/core/testapi.c postgis-new/raster/test/core/testapi.c
    old new  
    972972    CHECK_EQUALS(flag, 1); 
    973973} 
    974974 
     975static void testRasterFromBand(rt_raster raster) { 
     976        uint32_t bandNums[] = {1,3}; 
     977        int lenBandNums = 2; 
     978        rt_raster rast; 
     979 
     980        rast = rt_raster_from_band(raster, bandNums, lenBandNums); 
     981        assert(rast); 
     982 
     983        CHECK(rast); 
     984        CHECK(!rt_raster_is_empty(rast)); 
     985        CHECK(!rt_raster_has_no_band(rast, 1)); 
     986 
     987        rt_raster_destroy(rast); 
     988} 
     989 
    975990int 
    976991main() 
    977992{ 
     
    12781293    printf("Testing band hasnodata flag\n"); 
    12791294    testBandHasNoData(band_64BF); 
    12801295 
     1296                printf("Testing rt_raster_from_band\n"); 
     1297                testRasterFromBand(raster); 
     1298                printf("Successfully tested rt_raster_from_band\n"); 
     1299 
     1300 
    12811301    deepRelease(raster); 
    12821302 
    12831303    return EXIT_SUCCESS; 
  • raster/test/regress/Makefile.in

    diff -rupN postgis-old/raster/test/regress/Makefile.in postgis-new/raster/test/regress/Makefile.in
    old new  
    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.sql

    diff -rupN postgis-old/raster/test/regress/rt_band.sql postgis-new/raster/test/regress/rt_band.sql
    old new  
     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/test/regress/rt_band_expected

    diff -rupN postgis-old/raster/test/regress/rt_band_expected postgis-new/raster/test/regress/rt_band_expected
    old new  
     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