36 #include <executor/spi.h> 37 #include <utils/lsyscache.h> 38 #include <utils/array.h> 39 #include <utils/builtins.h> 40 #include <catalog/pg_type.h> 41 #include <executor/executor.h> 43 #include "../../postgis_config.h" 44 #include "lwgeom_pg.h" 84 #if POSTGIS_PGSQL_VERSION < 120 89 FunctionCallInfoBaseData fcinfo;
90 char fcinfo_data[SizeForFunctionCallInfo(FUNC_MAX_ARGS)];
92 FunctionCallInfo ufc_info;
121 rtpg_nmapalgebra_arg arg = NULL;
125 elog(ERROR,
"rtpg_nmapalgebra_arg_init: Could not allocate memory for arguments");
149 #if POSTGIS_PGSQL_VERSION >= 120 161 if (arg->
raster != NULL) {
178 if( arg->
mask != NULL )
201 if (arg == NULL || array == NULL) {
202 elog(ERROR,
"rtpg_nmapalgebra_rastbandarg_process: NULL values not permitted for parameters");
206 etype = ARR_ELEMTYPE(array);
207 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
212 typlen, typbyval, typalign,
217 elog(ERROR,
"rtpg_nmapalgebra_rastbandarg_process: Invalid argument for rastbandarg");
235 arg->
nband == NULL ||
239 elog(ERROR,
"rtpg_nmapalgebra_rastbandarg_process: Could not allocate memory for processing rastbandarg");
248 for (i = 0; i < n; i++) {
263 tup = (HeapTupleHeader) DatumGetPointer(e[i]);
265 elog(ERROR,
"rtpg_nmapalgebra_rastbandarg_process: Invalid argument for rastbandarg at index %d", i);
271 tupv = GetAttributeByName(tup,
"rast", &isnull);
273 elog(NOTICE,
"First argument (nband) of rastbandarg at index %d is NULL. Assuming NULL raster", i);
287 for (j = 0; j < i; j++) {
299 if (arg->
raster[i] == NULL) {
300 elog(ERROR,
"rtpg_nmapalgebra_rastbandarg_process: Could not deserialize raster at index %d", i);
316 tupv = GetAttributeByName(tup,
"nband", &isnull);
319 elog(NOTICE,
"First argument (nband) of rastbandarg at index %d is NULL. Assuming nband = %d", i, nband);
322 nband = DatumGetInt32(tupv);
325 elog(ERROR,
"rtpg_nmapalgebra_rastbandarg_process: Band number provided for rastbandarg at index %d must be greater than zero (1-based)", i);
329 arg->
nband[i] = nband - 1;
349 arg->
nband == NULL ||
352 elog(ERROR,
"rtpg_nmapalgebra_rastbandarg_process: Could not reallocate memory for processed rastbandarg");
367 double *
value,
int *nodata
375 ArrayType *mdValues = NULL;
376 Datum *_values = NULL;
377 bool *_nodata = NULL;
379 ArrayType *mdPos = NULL;
388 int lbound[3] = {1, 1, 1};
389 Datum datum = (Datum) NULL;
403 if (_values == NULL || _nodata == NULL) {
404 elog(ERROR,
"rtpg_nmapalgebra_callback: Could not allocate memory for values array");
411 for (z = 0; z < arg->
rasters; z++) {
413 for (y = 0; y < arg->
rows; y++) {
415 for (x = 0; x < arg->
columns; x++) {
419 _nodata[i] = (bool) arg->
nodata[z][y][x];
421 _values[i] = Float8GetDatum(arg->
values[z][y][x]);
423 _values[i] = (Datum) NULL;
431 get_typlenbyvalalign(FLOAT8OID, &typlen, &typbyval, &typalign);
434 mdValues = construct_md_array(
438 typlen, typbyval, typalign
443 _pos = palloc(
sizeof(Datum) * (arg->
rasters + 1) * 2);
444 _null = palloc(
sizeof(
bool) * (arg->
rasters + 1) * 2);
445 if (_pos == NULL || _null == NULL) {
447 elog(ERROR,
"rtpg_nmapalgebra_callback: Could not allocate memory for position array");
450 memset(_null, 0,
sizeof(
bool) * (arg->
rasters + 1) * 2);
459 for (z = 0; z < arg->
rasters; z++) {
468 get_typlenbyvalalign(INT4OID, &typlen, &typbyval, &typalign);
476 mdPos = construct_md_array(
480 typlen, typbyval, typalign
485 #if POSTGIS_PGSQL_VERSION < 120 486 callback->
ufc_info.arg[0] = PointerGetDatum(mdValues);
487 callback->
ufc_info.arg[1] = PointerGetDatum(mdPos);
489 callback->
ufc_info->args[0].value = PointerGetDatum(mdValues);
490 callback->
ufc_info->args[1].value = PointerGetDatum(mdPos);
494 #if POSTGIS_PGSQL_VERSION < 120 495 datum = FunctionCallInvoke(&(callback->
ufc_info));
497 datum = FunctionCallInvoke(callback->
ufc_info);
503 #if POSTGIS_PGSQL_VERSION < 120 511 *value = DatumGetFloat8(datum);
514 *value = (double) DatumGetFloat4(datum);
517 *value = (double) DatumGetInt32(datum);
520 *value = (double) DatumGetInt16(datum);
536 rtpg_nmapalgebra_arg arg = NULL;
538 ArrayType *maskArray;
569 elog(ERROR,
"RASTER_nMapAlgebra: Could not initialize argument structure");
576 elog(ERROR,
"RASTER_nMapAlgebra: Could not process rastbandarg");
580 POSTGIS_RT_DEBUGF(4,
"allnull, allempty, noband = %d, %d, %d", allnull, allempty, noband);
584 elog(NOTICE,
"All input rasters are NULL. Returning NULL");
590 if (!PG_ARGISNULL(2)) {
591 char *pixtypename = text_to_cstring(PG_GETARG_TEXT_P(2));
597 elog(ERROR,
"RASTER_nMapAlgebra: Invalid pixel type: %s", pixtypename);
603 if (!PG_ARGISNULL(3)){
604 arg->
distance[0] = PG_GETARG_INT32(3);
609 if (!PG_ARGISNULL(4)){
610 arg->
distance[1] = PG_GETARG_INT32(4);
616 elog(ERROR,
"RASTER_nMapAlgebra: Distance for X and Y axis must be greater than or equal to zero");
621 if (!PG_ARGISNULL(5)) {
629 if (PG_ARGISNULL(6)) {
630 elog(NOTICE,
"Custom extent is NULL. Returning NULL");
641 elog(ERROR,
"RASTER_nMapAlgebra: Could not deserialize custom extent");
645 elog(NOTICE,
"Custom extent is an empty raster. Returning empty raster");
649 if (raster == NULL) {
650 elog(ERROR,
"RASTER_nMapAlgebra: Could not create empty raster");
656 if (!pgraster) PG_RETURN_NULL();
658 SET_VARSIZE(pgraster, pgraster->
size);
659 PG_RETURN_POINTER(pgraster);
665 if( PG_ARGISNULL(7) ){
670 maskArray = PG_GETARG_ARRAYTYPE_P(7);
671 etype = ARR_ELEMTYPE(maskArray);
672 get_typlenbyvalalign(etype,&typlen,&typbyval,&typalign);
680 elog(ERROR,
"RASTER_nMapAlgebra: Mask data type must be FLOAT8 or FLOAT4");
684 ndims = ARR_NDIM(maskArray);
687 elog(ERROR,
"RASTER_nMapAlgebra: Mask Must be a 2D array");
692 maskDims = ARR_DIMS(maskArray);
694 if (maskDims[0] % 2 == 0 || maskDims[1] % 2 == 0) {
695 elog(ERROR,
"RASTER_nMapAlgebra: Mask dimensions must be odd");
703 typlen, typbyval,typalign,
704 &maskElements,&maskNulls,&num
707 if (num < 1 || num != (maskDims[0] * maskDims[1])) {
712 elog(ERROR,
"RASTER_nMapAlgebra: Could not deconstruct new values array");
718 arg->
mask->
values = palloc(
sizeof(
double*)* maskDims[0]);
719 arg->
mask->
nodata = palloc(
sizeof(
int*)*maskDims[0]);
720 for (i = 0; i < maskDims[0]; i++) {
721 arg->
mask->
values[i] = (
double*) palloc(
sizeof(
double) * maskDims[1]);
722 arg->
mask->
nodata[i] = (
int*) palloc(
sizeof(
int) * maskDims[1]);
727 for (y = 0; y < maskDims[0]; y++) {
728 for (x = 0; x < maskDims[1]; x++) {
736 arg->
mask->
values[
y][
x] = (double) DatumGetFloat4(maskElements[i]);
740 arg->
mask->
values[
y][
x] = (double) DatumGetFloat8(maskElements[i]);
751 if (maskDims[0] == 1 && maskDims[1] == 1) {
762 if (PG_ARGISNULL(8) || !PG_GETARG_BOOL(8)) {
763 if (arg->
mask != NULL)
774 elog(NOTICE,
"All input rasters are empty. Returning empty raster");
779 elog(NOTICE,
"All input rasters do not have bands at indicated indexes. Returning empty raster");
786 if (raster == NULL) {
787 elog(ERROR,
"RASTER_nMapAlgebra: Could not create empty raster");
793 if (!pgraster) PG_RETURN_NULL();
795 SET_VARSIZE(pgraster, pgraster->
size);
796 PG_RETURN_POINTER(pgraster);
800 if (!PG_ARGISNULL(1) || get_fn_expr_argtype(fcinfo->flinfo, 1) == REGPROCEDUREOID) {
819 get_func_result_type(
846 elog(ERROR,
"RASTER_nMapAlgebra: Function provided must return a double precision, float, int or smallint");
849 elog(ERROR,
"RASTER_nMapAlgebra: Function provided must return scalar (double precision, float, int, smallint)");
852 elog(ERROR,
"RASTER_nMapAlgebra: Function provided must have three input parameters");
855 elog(ERROR,
"RASTER_nMapAlgebra: Function provided must return double precision, not resultset");
862 elog(NOTICE,
"Function provided is VOLATILE. Unless required and for best performance, function should be IMMUTABLE or STABLE");
865 #if POSTGIS_PGSQL_VERSION < 120 883 if (!PG_ARGISNULL(9))
884 #if POSTGIS_PGSQL_VERSION < 120 893 #if POSTGIS_PGSQL_VERSION < 120 895 construct_empty_array(TEXTOID)
899 arg->
callback.
ufc_info->args[2].value = PointerGetDatum(construct_empty_array(TEXTOID));
904 #if POSTGIS_PGSQL_VERSION < 120 916 elog(ERROR,
"RASTER_nMapAlgebra: callbackfunc must be provided");
961 if (itrset == NULL) {
963 elog(ERROR,
"RASTER_nMapAlgebra: Could not allocate memory for iterator arguments");
992 elog(ERROR,
"RASTER_nMapAlgebra: Could not run raster iterator function");
995 else if (raster == NULL)
1006 SET_VARSIZE(pgraster, pgraster->
size);
1007 PG_RETURN_POINTER(pgraster);
1046 rtpg_nmapalgebraexpr_arg arg = NULL;
1051 elog(ERROR,
"rtpg_nmapalgebraexpr_arg_init: Could not allocate memory for arguments");
1057 elog(ERROR,
"rtpg_nmapalgebraexpr_arg_init: Could not allocate memory for arg->bandarg");
1070 elog(ERROR,
"rtpg_nmapalgebraexpr_arg_init: Could not allocate memory for spi_argpos");
1101 double *value,
int *nodata
1104 SPIPlanPtr plan = NULL;
1124 else if (arg->
nodata[0][0][0] && !arg->
nodata[1][0][0]) {
1127 *value = callback->
expr[id].
val;
1134 else if (!arg->
nodata[0][0][0] && arg->
nodata[1][0][0]) {
1137 *value = callback->
expr[id].
val;
1147 *value = callback->
expr[id].
val;
1161 if (arg->
nodata[0][0][0]) {
1164 *value = callback->
expr[id].
val;
1174 *value = callback->
expr[id].
val;
1181 *value = callback->
expr[id].
val;
1197 SPITupleTable *tuptable = NULL;
1200 bool isnull =
false;
1205 memset(values, (Datum) NULL,
sizeof(Datum) * callback->
kw.
count);
1206 memset(nulls,
FALSE,
sizeof(
bool) * callback->
kw.
count);
1211 for (i = 0; i < callback->
kw.
count; i++) {
1213 if (idx < 1)
continue;
1219 values[idx] = Int32GetDatum(arg->
src_pixel[0][0] + 1);
1223 values[idx] = Int32GetDatum(arg->
src_pixel[0][1] + 1);
1229 if (!arg->
nodata[0][0][0])
1230 values[idx] = Float8GetDatum(arg->
values[0][0][0]);
1237 values[idx] = Int32GetDatum(arg->
src_pixel[0][0] + 1);
1241 values[idx] = Int32GetDatum(arg->
src_pixel[0][1] + 1);
1247 if (!arg->
nodata[0][0][0])
1248 values[idx] = Float8GetDatum(arg->
values[0][0][0]);
1255 values[idx] = Int32GetDatum(arg->
src_pixel[1][0] + 1);
1259 values[idx] = Int32GetDatum(arg->
src_pixel[1][1] + 1);
1265 if (!arg->
nodata[1][0][0])
1266 values[idx] = Float8GetDatum(arg->
values[1][0][0]);
1276 err = SPI_execute_plan(plan, values, nulls,
TRUE, 1);
1277 if (err != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
1278 elog(ERROR,
"rtpg_nmapalgebraexpr_callback: Unexpected error when running prepared statement %d",
id);
1283 tupdesc = SPI_tuptable->tupdesc;
1284 tuptable = SPI_tuptable;
1285 tuple = tuptable->vals[0];
1287 datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
1288 if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
1289 if (SPI_tuptable) SPI_freetuptable(tuptable);
1290 elog(ERROR,
"rtpg_nmapalgebraexpr_callback: Could not get result of prepared statement %d",
id);
1295 *value = DatumGetFloat8(datum);
1309 *value = callback->
expr[1].
val;
1315 if (SPI_tuptable) SPI_freetuptable(tuptable);
1325 MemoryContext mainMemCtx = CurrentMemoryContext;
1326 rtpg_nmapalgebraexpr_arg arg = NULL;
1328 uint16_t exprpos[3] = {1, 4, 5};
1342 SPITupleTable *tuptable = NULL;
1345 bool isnull =
FALSE;
1351 const int argkwcount = 12;
1367 if (PG_ARGISNULL(0))
1373 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not initialize argument structure");
1380 elog(ERROR,
"RASTER_nMapAlgebra: Could not process rastbandarg");
1384 POSTGIS_RT_DEBUGF(4,
"allnull, allempty, noband = %d, %d, %d", allnull, allempty, noband);
1388 elog(NOTICE,
"All input rasters are NULL. Returning NULL");
1400 if (!PG_ARGISNULL(2)) {
1401 char *pixtypename = text_to_cstring(PG_GETARG_TEXT_P(2));
1407 elog(ERROR,
"RASTER_nMapAlgebraExpr: Invalid pixel type: %s", pixtypename);
1414 if (!PG_ARGISNULL(3)) {
1420 if (numraster < 2) {
1421 elog(NOTICE,
"CUSTOM extent type not supported. Defaulting to FIRST");
1425 elog(NOTICE,
"CUSTOM extent type not supported. Defaulting to INTERSECTION");
1429 else if (numraster < 2)
1435 if (!PG_ARGISNULL(6)) {
1443 elog(NOTICE,
"All input rasters are empty. Returning empty raster");
1448 elog(NOTICE,
"All input rasters do not have bands at indicated indexes. Returning empty raster");
1455 if (raster == NULL) {
1456 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not create empty raster");
1462 if (!pgraster) PG_RETURN_NULL();
1464 SET_VARSIZE(pgraster, pgraster->
size);
1465 PG_RETURN_POINTER(pgraster);
1469 if (SPI_connect() != SPI_OK_CONNECT) {
1471 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not connect to the SPI manager");
1487 char place[5] =
"$1";
1489 if (PG_ARGISNULL(exprpos[i]))
1492 expr = text_to_cstring(PG_GETARG_TEXT_P(exprpos[i]));
1495 for (j = 0, k = 1; j < argkwcount; j++) {
1507 sprintf(place,
"$%d", k);
1513 len = strlen(
"SELECT (") + strlen(expr) + strlen(
")::double precision");
1514 sql = (
char *) palloc(len + 1);
1518 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not allocate memory for expression parameter %d", exprpos[i]);
1522 memcpy(sql,
"SELECT (", strlen(
"SELECT ("));
1523 memcpy(sql + strlen(
"SELECT ("), expr, strlen(expr));
1524 memcpy(sql + strlen(
"SELECT (") + strlen(expr),
")::double precision", strlen(
")::double precision"));
1533 if (argtype == NULL) {
1537 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not allocate memory for prepared plan argtypes of expression parameter %d", exprpos[i]);
1542 for (j = 0, k = 0; j < argkwcount; j++) {
1547 (strstr(argkw[j],
"[rast.x]") != NULL) ||
1548 (strstr(argkw[j],
"[rast.y]") != NULL) ||
1549 (strstr(argkw[j],
"[rast1.x]") != NULL) ||
1550 (strstr(argkw[j],
"[rast1.y]") != NULL) ||
1551 (strstr(argkw[j],
"[rast2.x]") != NULL) ||
1552 (strstr(argkw[j],
"[rast2.y]") != NULL)
1554 argtype[k] = INT4OID;
1557 argtype[k] = FLOAT8OID;
1569 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not create prepared plan of expression parameter %d", exprpos[i]);
1575 POSTGIS_RT_DEBUGF(3,
"expression parameter %d has no args, simply executing", exprpos[i]);
1576 err = SPI_execute(sql,
TRUE, 0);
1579 if (err != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
1582 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not evaluate expression parameter %d", exprpos[i]);
1587 tupdesc = SPI_tuptable->tupdesc;
1588 tuptable = SPI_tuptable;
1589 tuple = tuptable->vals[0];
1591 datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
1592 if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
1593 if (SPI_tuptable) SPI_freetuptable(tuptable);
1596 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not get result of expression parameter %d", exprpos[i]);
1605 if (SPI_tuptable) SPI_freetuptable(tuptable);
1625 for (i = 0; i < numraster; i++) {
1649 if (itrset == NULL) {
1652 elog(ERROR,
"RASTER_nMapAlgebra: Could not allocate memory for iterator arguments");
1657 for (i = 0; i < numraster; i++) {
1681 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not run raster iterator function");
1684 else if (raster == NULL) {
1690 MemoryContextSwitchTo(mainMemCtx);
1701 SET_VARSIZE(pgraster, pgraster->
size);
1702 PG_RETURN_POINTER(pgraster);
1722 assert(cutype && strlen(cutype) > 0);
1724 if (strcmp(cutype,
"LAST") == 0)
1726 else if (strcmp(cutype,
"FIRST") == 0)
1728 else if (strcmp(cutype,
"MIN") == 0)
1730 else if (strcmp(cutype,
"MAX") == 0)
1732 else if (strcmp(cutype,
"COUNT") == 0)
1734 else if (strcmp(cutype,
"SUM") == 0)
1736 else if (strcmp(cutype,
"MEAN") == 0)
1738 else if (strcmp(cutype,
"RANGE") == 0)
1765 for (i = 0; i < arg->
numband; i++) {
1789 double *value,
int *nodata
1791 rtpg_union_type *utype = (rtpg_union_type *) userarg;
1801 elog(ERROR,
"rtpg_union_callback: Invalid arguments passed to callback");
1817 else if (!arg->
nodata[0][0][0] && arg->
nodata[1][0][0]) {
1818 *value = arg->
values[0][0][0];
1823 else if (arg->
nodata[0][0][0] && !arg->
nodata[1][0][0]) {
1824 *value = arg->
values[1][0][0];
1832 *value = arg->
values[0][0][0];
1836 *value = arg->
values[0][0][0];
1838 *value = arg->
values[1][0][0];
1842 *value = arg->
values[0][0][0];
1844 *value = arg->
values[1][0][0];
1851 else if (!arg->
nodata[0][0][0] && arg->
nodata[1][0][0])
1852 *value = arg->
values[0][0][0];
1854 else if (arg->
nodata[0][0][0] && !arg->
nodata[1][0][0])
1858 *value = arg->
values[0][0][0] + 1;
1868 *value = arg->
values[1][0][0];
1880 double *value,
int *nodata
1890 elog(ERROR,
"rtpg_union_mean_callback: Invalid arguments passed to callback");
1916 double *value,
int *nodata
1926 elog(ERROR,
"rtpg_union_range_callback: Invalid arguments passed to callback");
1959 HeapTupleHeader tup;
1965 char *utypename = NULL;
1966 rtpg_union_type utype =
UT_LAST;
1968 etype = ARR_ELEMTYPE(array);
1969 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1974 typlen, typbyval, typalign,
1979 elog(ERROR,
"rtpg_union_unionarg_process: Invalid argument for unionarg");
1987 elog(ERROR,
"rtpg_union_unionarg_process: Could not allocate memory for band information");
1992 for (i = 0; i < n; i++) {
2001 tup = (HeapTupleHeader) DatumGetPointer(e[i]);
2003 elog(ERROR,
"rtpg_union_unionarg_process: Invalid argument for unionarg");
2008 tupv = GetAttributeByName(tup,
"nband", &isnull);
2011 elog(NOTICE,
"First argument (nband) of unionarg is NULL. Assuming nband = %d", nband);
2014 nband = DatumGetInt32(tupv);
2017 elog(ERROR,
"rtpg_union_unionarg_process: Band number must be greater than zero (1-based)");
2022 tupv = GetAttributeByName(tup,
"uniontype", &isnull);
2024 elog(NOTICE,
"Second argument (uniontype) of unionarg is NULL. Assuming uniontype = LAST");
2028 utypename = text_to_cstring((text *) DatumGetPointer(tupv));
2049 elog(ERROR,
"rtpg_union_unionarg_process: Could not reallocate memory for band information");
2066 if (numbands <= arg->numband)
2076 elog(ERROR,
"rtpg_union_noarg: Could not reallocate memory for band information");
2082 for (; i < arg->
numband; i++) {
2090 elog(ERROR,
"rtpg_union_noarg: Could not allocate memory for working rasters");
2099 elog(ERROR,
"rtpg_union_noarg: Could not create working raster");
2112 MemoryContext aggcontext;
2113 MemoryContext oldcontext;
2114 rtpg_union_arg iwr = NULL;
2123 int isempty[2] = {0};
2124 int hasband[2] = {0};
2126 double _offset[4] = {0.};
2134 char *utypename = NULL;
2135 rtpg_union_type utype =
UT_LAST;
2138 double nodataval = 0;
2144 uint16_t _dim[2] = {0};
2151 if (!AggCheckCallContext(fcinfo, &aggcontext)) {
2152 elog(ERROR,
"RASTER_union_transfn: Cannot be called in a non-aggregate context");
2157 oldcontext = MemoryContextSwitchTo(aggcontext);
2159 if (PG_ARGISNULL(0)) {
2164 MemoryContextSwitchTo(oldcontext);
2165 elog(ERROR,
"RASTER_union_transfn: Could not allocate memory for state variable");
2181 if (!PG_ARGISNULL(1)) {
2183 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
2187 if (raster == NULL) {
2190 PG_FREE_IF_COPY(pgraster, 1);
2192 MemoryContextSwitchTo(oldcontext);
2193 elog(ERROR,
"RASTER_union_transfn: Could not deserialize raster");
2206 if (!PG_ARGISNULL(2)) {
2207 Oid calltype = get_fn_expr_argtype(fcinfo->flinfo, 2);
2218 utypename = text_to_cstring(PG_GETARG_TEXT_P(2));
2242 if (numband > idx) {
2258 if (raster != NULL) {
2260 PG_FREE_IF_COPY(pgraster, 1);
2263 MemoryContextSwitchTo(oldcontext);
2264 elog(ERROR,
"RASTER_union_transfn: Could not allocate memory for band information");
2269 for (i = idx; i < iwr->
numband; i++) {
2293 nband = PG_GETARG_INT32(2);
2297 if (raster != NULL) {
2299 PG_FREE_IF_COPY(pgraster, 1);
2302 MemoryContextSwitchTo(oldcontext);
2303 elog(ERROR,
"RASTER_union_transfn: Band number must be greater than zero (1-based)");
2312 if (raster != NULL) {
2314 PG_FREE_IF_COPY(pgraster, 1);
2317 MemoryContextSwitchTo(oldcontext);
2318 elog(ERROR,
"RASTER_union_transfn: Could not allocate memory for band information");
2337 if (raster != NULL) {
2339 PG_FREE_IF_COPY(pgraster, 1);
2342 MemoryContextSwitchTo(oldcontext);
2343 elog(ERROR,
"RASTER_union_transfn: Could not process unionarg");
2352 if (nargs > 3 && !PG_ARGISNULL(3)) {
2353 utypename = text_to_cstring(PG_GETARG_TEXT_P(3));
2367 for (i = 0; i < iwr->
numband; i++) {
2380 if (raster != NULL) {
2382 PG_FREE_IF_COPY(pgraster, 1);
2385 MemoryContextSwitchTo(oldcontext);
2386 elog(ERROR,
"RASTER_union_transfn: Could not allocate memory for working raster(s)");
2399 if (raster != NULL) {
2401 PG_FREE_IF_COPY(pgraster, 1);
2404 MemoryContextSwitchTo(oldcontext);
2405 elog(ERROR,
"RASTER_union_transfn: Could not create working raster");
2420 if (raster != NULL) {
2422 PG_FREE_IF_COPY(pgraster, 1);
2425 MemoryContextSwitchTo(oldcontext);
2426 elog(ERROR,
"RASTER_union_transfn: Could not check and balance number of bands");
2433 if (itrset == NULL) {
2436 if (raster != NULL) {
2438 PG_FREE_IF_COPY(pgraster, 1);
2441 MemoryContextSwitchTo(oldcontext);
2442 elog(ERROR,
"RASTER_union_transfn: Could not allocate memory for iterator arguments");
2447 for (i = 0; i < iwr->
numband; i++) {
2467 if (!isempty[0] && hasband[0])
2469 else if (!isempty[1] && hasband[1])
2476 if (_band != NULL) {
2514 itrset[0].
nband = 0;
2530 if (!isempty[0] && !isempty[1] && hasband[0] && hasband[1]) {
2542 if (raster != NULL) {
2544 PG_FREE_IF_COPY(pgraster, 1);
2547 MemoryContextSwitchTo(oldcontext);
2548 elog(ERROR,
"RASTER_union_transfn: Could not create internal raster");
2552 _offset[0], _offset[1], _offset[2], _offset[3]);
2559 double igt[6] = {0};
2575 hasnodata, nodataval,
2582 if (raster != NULL) {
2584 PG_FREE_IF_COPY(pgraster, 1);
2587 MemoryContextSwitchTo(oldcontext);
2588 elog(ERROR,
"RASTER_union_transfn: Could not add new band to internal raster");
2596 for (y = 0; y < _dim[1]; y++) {
2597 POSTGIS_RT_DEBUGF(4,
"Getting pixel line of working raster at (x, y, length) = (0, %d, %d)", y, _dim[0]);
2609 if (raster != NULL) {
2611 PG_FREE_IF_COPY(pgraster, 1);
2614 MemoryContextSwitchTo(oldcontext);
2615 elog(ERROR,
"RASTER_union_transfn: Could not get pixel line from band of working raster");
2619 POSTGIS_RT_DEBUGF(4,
"Setting pixel line at (x, y, length) = (%d, %d, %d)", (
int) _offset[0], (
int) _offset[1] + y, nvals);
2622 (
int) _offset[0], (
int) _offset[1] + y,
2630 if (raster != NULL) {
2632 PG_FREE_IF_COPY(pgraster, 1);
2635 MemoryContextSwitchTo(oldcontext);
2636 elog(ERROR,
"RASTER_union_transfn: Could not set pixel line to band of internal raster");
2652 hasnodata, nodataval,
2667 if (raster != NULL) {
2669 PG_FREE_IF_COPY(pgraster, 1);
2672 MemoryContextSwitchTo(oldcontext);
2673 elog(ERROR,
"RASTER_union_transfn: Could not run raster iterator function");
2681 for (y = 0; y < _dim[1]; y++) {
2682 POSTGIS_RT_DEBUGF(4,
"Getting pixel line of iterator raster at (x, y, length) = (0, %d, %d)", y, _dim[0]);
2696 if (raster != NULL) {
2698 PG_FREE_IF_COPY(pgraster, 1);
2701 MemoryContextSwitchTo(oldcontext);
2702 elog(ERROR,
"RASTER_union_transfn: Could not get pixel line from band of working raster");
2706 POSTGIS_RT_DEBUGF(4,
"Setting pixel line at (x, y, length) = (%d, %d, %d)", (
int) _offset[2], (
int) _offset[3] + y, nvals);
2709 (
int) _offset[2], (
int) _offset[3] + y,
2719 if (raster != NULL) {
2721 PG_FREE_IF_COPY(pgraster, 1);
2724 MemoryContextSwitchTo(oldcontext);
2725 elog(ERROR,
"RASTER_union_transfn: Could not set pixel line to band of internal raster");
2745 hasnodata, nodataval,
2757 if (raster != NULL) {
2759 PG_FREE_IF_COPY(pgraster, 1);
2762 MemoryContextSwitchTo(oldcontext);
2763 elog(ERROR,
"RASTER_union_transfn: Could not run raster iterator function");
2780 if (raster != NULL) {
2782 PG_FREE_IF_COPY(pgraster, 1);
2786 MemoryContextSwitchTo(oldcontext);
2790 PG_RETURN_POINTER(iwr);
2810 double nodataval = 0;
2815 if (!AggCheckCallContext(fcinfo, NULL)) {
2816 elog(ERROR,
"RASTER_union_finalfn: Cannot be called in a non-aggregate context");
2821 if (PG_ARGISNULL(0))
2828 if (itrset == NULL) {
2830 elog(ERROR,
"RASTER_union_finalfn: Could not allocate memory for iterator arguments");
2834 for (i = 0; i < iwr->
numband; i++) {
2849 itrset[0].
nband = 0;
2851 itrset[1].
nband = 0;
2859 hasnodata, nodataval,
2872 hasnodata, nodataval,
2886 elog(ERROR,
"RASTER_union_finalfn: Could not run raster iterator function");
2897 status = (_rtn == NULL) ? -1 : 0;
2922 elog(ERROR,
"RASTER_union_finalfn: Could not add band to final raster");
2931 if (!_rtn) PG_RETURN_NULL();
2941 SET_VARSIZE(pgraster, pgraster->
size);
2942 PG_RETURN_POINTER(pgraster);
2967 rtpg_clip_arg arg = NULL;
2971 elog(ERROR,
"rtpg_clip_arg_init: Could not allocate memory for function arguments");
2985 if (arg->
band != NULL)
2990 if (arg->
mask != NULL)
2998 double *value,
int *nodata
3008 *value = arg->
values[0][0][0];
3026 unsigned char *wkb = NULL;
3041 rtpg_clip_arg arg = NULL;
3055 if (PG_ARGISNULL(0) || PG_ARGISNULL(2))
3061 elog(ERROR,
"RASTER_clip: Could not initialize argument structure");
3066 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
3070 if (arg->
raster == NULL) {
3072 PG_FREE_IF_COPY(pgraster, 0);
3073 elog(ERROR,
"RASTER_clip: Could not deserialize raster");
3079 elog(NOTICE,
"Input raster is empty or has no bands. Returning empty raster");
3082 PG_FREE_IF_COPY(pgraster, 0);
3086 elog(ERROR,
"RASTER_clip: Could not create empty raster");
3095 SET_VARSIZE(pgrtn, pgrtn->
size);
3096 PG_RETURN_POINTER(pgrtn);
3104 gser = PG_GETARG_GSERIALIZED_P(2);
3116 elog(NOTICE,
"Geometry provided does not have the same SRID as the raster. Returning NULL");
3119 PG_FREE_IF_COPY(pgraster, 0);
3121 PG_FREE_IF_COPY(gser, 2);
3127 if (!PG_ARGISNULL(4) && !PG_GETARG_BOOL(4))
3134 PG_FREE_IF_COPY(pgraster, 0);
3136 PG_FREE_IF_COPY(gser, 2);
3138 elog(ERROR,
"RASTER_clip: Could not get convex hull of raster");
3145 PG_FREE_IF_COPY(gser, 2);
3150 elog(NOTICE,
"The input raster and input geometry do not intersect. Returning empty raster");
3153 PG_FREE_IF_COPY(pgraster, 0);
3158 elog(ERROR,
"RASTER_clip: Could not create empty raster");
3167 SET_VARSIZE(pgrtn, pgrtn->
size);
3168 PG_RETURN_POINTER(pgrtn);
3172 if (!PG_ARGISNULL(1)) {
3173 array = PG_GETARG_ARRAYTYPE_P(1);
3174 etype = ARR_ELEMTYPE(array);
3175 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
3183 PG_FREE_IF_COPY(pgraster, 0);
3185 elog(ERROR,
"RASTER_clip: Invalid data type for band indexes");
3192 typlen, typbyval, typalign,
3197 if (arg->
band == NULL) {
3199 PG_FREE_IF_COPY(pgraster, 0);
3201 elog(ERROR,
"RASTER_clip: Could not allocate memory for band arguments");
3205 for (i = 0, j = 0; i < arg->
numbands; i++) {
3206 if (nulls[i])
continue;
3210 arg->
band[j].
nband = DatumGetInt16(e[i]) - 1;
3213 arg->
band[j].
nband = DatumGetInt32(e[i]) - 1;
3220 if (j < arg->numbands) {
3222 if (arg->
band == NULL) {
3224 PG_FREE_IF_COPY(pgraster, 0);
3226 elog(ERROR,
"RASTER_clip: Could not reallocate memory for band arguments");
3234 for (i = 0; i < arg->
numbands; i++) {
3236 elog(NOTICE,
"Band at index %d not found in raster", arg->
band[i].
nband + 1);
3238 PG_FREE_IF_COPY(pgraster, 0);
3253 if (arg->
band == NULL) {
3256 PG_FREE_IF_COPY(pgraster, 0);
3259 elog(ERROR,
"RASTER_clip: Could not allocate memory for band arguments");
3263 for (i = 0; i < arg->
numbands; i++) {
3272 if (!PG_ARGISNULL(3)) {
3273 array = PG_GETARG_ARRAYTYPE_P(3);
3274 etype = ARR_ELEMTYPE(array);
3275 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
3283 PG_FREE_IF_COPY(pgraster, 0);
3285 elog(ERROR,
"RASTER_clip: Invalid data type for NODATA values");
3292 typlen, typbyval, typalign,
3297 for (i = 0, j = 0; i < arg->
numbands; i++, j++) {
3338 if (arg->
mask == NULL) {
3340 PG_FREE_IF_COPY(pgraster, 0);
3341 elog(ERROR,
"RASTER_clip: Could not rasterize intersection geometry");
3352 if (itrset == NULL) {
3354 PG_FREE_IF_COPY(pgraster, 0);
3355 elog(ERROR,
"RASTER_clip: Could not allocate memory for iterator arguments");
3360 for (i = 0; i < arg->
numbands; i++) {
3361 POSTGIS_RT_DEBUGF(4,
"band arg %d (nband, hasnodata, nodataval) = (%d, %d, %f)",
3389 PG_FREE_IF_COPY(pgraster, 0);
3390 elog(ERROR,
"RASTER_clip: Could not create output raster");
3399 PG_FREE_IF_COPY(pgraster, 0);
3400 elog(ERROR,
"RASTER_clip: Could not add NODATA band to output raster");
3414 itrset[1].
nband = 0;
3422 hasnodata, nodataval,
3434 PG_FREE_IF_COPY(pgraster, 0);
3435 elog(ERROR,
"RASTER_clip: Could not run raster iterator function");
3450 PG_FREE_IF_COPY(pgraster, 0);
3451 elog(NOTICE,
"RASTER_clip: Could not get band from working raster");
3460 PG_FREE_IF_COPY(pgraster, 0);
3461 elog(ERROR,
"RASTER_clip: Could not add new band to output raster");
3471 PG_FREE_IF_COPY(pgraster, 0);
3481 SET_VARSIZE(pgrtn, pgrtn->
size);
3482 PG_RETURN_POINTER(pgrtn);
3515 HeapTupleHeader tup;
3520 text *exprtext = NULL;
3525 char *pixeltype = NULL;
3526 text *pixeltypetext = NULL;
3528 double nodataval = 0;
3529 bool hasnodata =
FALSE;
3531 char **comma_set = NULL;
3533 char **colon_set = NULL;
3535 char **dash_set = NULL;
3541 if (PG_ARGISNULL(0))
3543 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
3548 PG_FREE_IF_COPY(pgraster, 0);
3549 elog(ERROR,
"RASTER_reclass: Could not deserialize raster");
3553 POSTGIS_RT_DEBUGF(3,
"RASTER_reclass: %d possible bands to be reclassified", numBands);
3557 array = PG_GETARG_ARRAYTYPE_P(1);
3558 etype = ARR_ELEMTYPE(array);
3559 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
3561 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
3565 elog(NOTICE,
"Invalid argument for reclassargset. Returning original raster");
3569 PG_FREE_IF_COPY(pgraster, 0);
3573 SET_VARSIZE(pgrtn, pgrtn->
size);
3574 PG_RETURN_POINTER(pgrtn);
3582 for (i = 0; i < n; i++) {
3583 if (nulls[i])
continue;
3586 tup = (HeapTupleHeader) DatumGetPointer(e[i]);
3588 elog(NOTICE,
"Invalid argument for reclassargset. Returning original raster");
3592 PG_FREE_IF_COPY(pgraster, 0);
3596 SET_VARSIZE(pgrtn, pgrtn->
size);
3597 PG_RETURN_POINTER(pgrtn);
3601 tupv = GetAttributeByName(tup,
"nband", &isnull);
3603 elog(NOTICE,
"Invalid argument for reclassargset. Missing value of nband for reclassarg of index %d . Returning original raster", i);
3607 PG_FREE_IF_COPY(pgraster, 0);
3611 SET_VARSIZE(pgrtn, pgrtn->
size);
3612 PG_RETURN_POINTER(pgrtn);
3614 nband = DatumGetInt32(tupv);
3618 if (nband < 1 || nband > numBands) {
3619 elog(NOTICE,
"Invalid argument for reclassargset. Invalid band index (must use 1-based) for reclassarg of index %d . Returning original raster", i);
3623 PG_FREE_IF_COPY(pgraster, 0);
3627 SET_VARSIZE(pgrtn, pgrtn->
size);
3628 PG_RETURN_POINTER(pgrtn);
3632 tupv = GetAttributeByName(tup,
"reclassexpr", &isnull);
3634 elog(NOTICE,
"Invalid argument for reclassargset. Missing value of reclassexpr for reclassarg of index %d . Returning original raster", i);
3638 PG_FREE_IF_COPY(pgraster, 0);
3642 SET_VARSIZE(pgrtn, pgrtn->
size);
3643 PG_RETURN_POINTER(pgrtn);
3645 exprtext = (text *) DatumGetPointer(tupv);
3646 if (NULL == exprtext) {
3647 elog(NOTICE,
"Invalid argument for reclassargset. Missing value of reclassexpr for reclassarg of index %d . Returning original raster", i);
3651 PG_FREE_IF_COPY(pgraster, 0);
3655 SET_VARSIZE(pgrtn, pgrtn->
size);
3656 PG_RETURN_POINTER(pgrtn);
3658 expr = text_to_cstring(exprtext);
3667 elog(NOTICE,
"Invalid argument for reclassargset. Invalid expression of reclassexpr for reclassarg of index %d . Returning original raster", i);
3671 PG_FREE_IF_COPY(pgraster, 0);
3675 SET_VARSIZE(pgrtn, pgrtn->
size);
3676 PG_RETURN_POINTER(pgrtn);
3683 for (a = 0, j = 0; a < comma_n; a++) {
3689 elog(NOTICE,
"Invalid argument for reclassargset. Invalid expression of reclassexpr for reclassarg of index %d . Returning original raster", i);
3690 for (k = 0; k < j; k++) pfree(exprset[k]);
3695 PG_FREE_IF_COPY(pgraster, 0);
3699 SET_VARSIZE(pgrtn, pgrtn->
size);
3700 PG_RETURN_POINTER(pgrtn);
3706 for (b = 0; b < colon_n; b++) {
3711 if (dash_n < 1 || dash_n > 3) {
3712 elog(NOTICE,
"Invalid argument for reclassargset. Invalid expression of reclassexpr for reclassarg of index %d . Returning original raster", i);
3713 for (k = 0; k < j; k++) pfree(exprset[k]);
3718 PG_FREE_IF_COPY(pgraster, 0);
3722 SET_VARSIZE(pgrtn, pgrtn->
size);
3723 PG_RETURN_POINTER(pgrtn);
3726 for (c = 0; c < dash_n; c++) {
3730 strlen(dash_set[c]) == 1 && (
3731 strchr(dash_set[c],
'(') != NULL ||
3732 strchr(dash_set[c],
'[') != NULL ||
3733 strchr(dash_set[c],
')') != NULL ||
3734 strchr(dash_set[c],
']') != NULL
3737 junk = palloc(
sizeof(
char) * (strlen(dash_set[c + 1]) + 2));
3739 for (k = 0; k <= j; k++) pfree(exprset[k]);
3742 PG_FREE_IF_COPY(pgraster, 0);
3744 elog(ERROR,
"RASTER_reclass: Could not allocate memory");
3748 sprintf(junk,
"%s%s", dash_set[c], dash_set[c + 1]);
3750 dash_set[c] = repalloc(dash_set[c],
sizeof(
char) * (strlen(junk) + 1));
3751 strcpy(dash_set[c], junk);
3755 for (k = 1; k < dash_n; k++) {
3756 dash_set[k - 1] = repalloc(dash_set[k - 1], (strlen(dash_set[k]) + 1) *
sizeof(
char));
3757 strcpy(dash_set[k - 1], dash_set[k]);
3761 pfree(dash_set[dash_n]);
3762 dash_set = repalloc(dash_set,
sizeof(
char *) * dash_n);
3766 if (c < 1 && dash_n > 2) {
3767 elog(NOTICE,
"Invalid argument for reclassargset. Invalid expression of reclassexpr for reclassarg of index %d . Returning original raster", i);
3768 for (k = 0; k < j; k++) pfree(exprset[k]);
3773 PG_FREE_IF_COPY(pgraster, 0);
3777 SET_VARSIZE(pgrtn, pgrtn->
size);
3778 PG_RETURN_POINTER(pgrtn);
3789 strchr(dash_set[c],
')') != NULL ||
3790 strchr(dash_set[c],
']') != NULL
3795 else if (strchr(dash_set[c],
'(') != NULL){
3805 strrchr(dash_set[c],
'(') != NULL ||
3806 strrchr(dash_set[c],
'[') != NULL
3811 else if (strrchr(dash_set[c],
']') != NULL) {
3819 POSTGIS_RT_DEBUGF(4,
"RASTER_reclass: exc_val %d inc_val %d", exc_val, inc_val);
3827 val = strtod(dash_set[c], &junk);
3828 if (errno != 0 || dash_set[c] == junk) {
3829 elog(NOTICE,
"Invalid argument for reclassargset. Invalid expression of reclassexpr for reclassarg of index %d . Returning original raster", i);
3830 for (k = 0; k < j; k++) pfree(exprset[k]);
3835 PG_FREE_IF_COPY(pgraster, 0);
3839 SET_VARSIZE(pgrtn, pgrtn->
size);
3840 PG_RETURN_POINTER(pgrtn);
3846 junk = strstr(colon_set[b], dash_set[c]);
3851 "(colon_set[%d], dash_set[%d], junk) = (%s, %s, %s)",
3852 b, c, colon_set[b], dash_set[c], junk
3855 if (junk != colon_set[b]) {
3857 if (*(junk - 1) ==
'-') {
3860 ((junk - 1) == colon_set[b]) ||
3861 (*(junk - 2) ==
'-') ||
3862 (*(junk - 2) ==
'[') ||
3863 (*(junk - 2) ==
'(')
3883 exprset[j]->
src.
min = val;
3889 exprset[j]->
src.
max = val;
3899 exprset[j]->
dst.
min = val;
3902 exprset[j]->
dst.
max = val;
3910 , exprset[j]->src.min
3920 tupv = GetAttributeByName(tup,
"pixeltype", &isnull);
3922 elog(NOTICE,
"Invalid argument for reclassargset. Missing value of pixeltype for reclassarg of index %d . Returning original raster", i);
3926 PG_FREE_IF_COPY(pgraster, 0);
3930 SET_VARSIZE(pgrtn, pgrtn->
size);
3931 PG_RETURN_POINTER(pgrtn);
3933 pixeltypetext = (text *) DatumGetPointer(tupv);
3934 if (NULL == pixeltypetext) {
3935 elog(NOTICE,
"Invalid argument for reclassargset. Missing value of pixeltype for reclassarg of index %d . Returning original raster", i);
3939 PG_FREE_IF_COPY(pgraster, 0);
3943 SET_VARSIZE(pgrtn, pgrtn->
size);
3944 PG_RETURN_POINTER(pgrtn);
3946 pixeltype = text_to_cstring(pixeltypetext);
3951 tupv = GetAttributeByName(tup,
"nodataval", &isnull);
3957 nodataval = DatumGetFloat8(tupv);
3966 elog(NOTICE,
"Could not find raster band of index %d. Returning original raster", nband);
3967 for (k = 0; k < j; k++) pfree(exprset[k]);
3972 PG_FREE_IF_COPY(pgraster, 0);
3976 SET_VARSIZE(pgrtn, pgrtn->
size);
3977 PG_RETURN_POINTER(pgrtn);
3979 newband =
rt_band_reclass(band, pixtype, hasnodata, nodataval, exprset, j);
3981 for (k = 0; k < j; k++) pfree(exprset[k]);
3985 PG_FREE_IF_COPY(pgraster, 0);
3987 elog(ERROR,
"RASTER_reclass: Could not reclassify raster band of index %d", nband);
3993 for (k = 0; k < j; k++) pfree(exprset[k]);
3998 PG_FREE_IF_COPY(pgraster, 0);
4000 elog(ERROR,
"RASTER_reclass: Could not replace raster band of index %d with reclassified band", nband);
4008 for (k = 0; k < j; k++) pfree(exprset[k]);
4014 PG_FREE_IF_COPY(pgraster, 0);
4020 SET_VARSIZE(pgrtn, pgrtn->
size);
4021 PG_RETURN_POINTER(pgrtn);
4044 static rtpg_colormap_arg
4046 rtpg_colormap_arg arg = NULL;
4050 elog(ERROR,
"rtpg_colormap_arg: Could not allocate memory for function arguments");
4061 elog(ERROR,
"rtpg_colormap_arg: Could not allocate memory for function arguments");
4094 for (i = 0; i < arg->
nentry; i++) {
4095 if (arg->
entry[i] != NULL)
4096 pfree(arg->
entry[i]);
4102 for (i = 0; i < arg->
nelement; i++)
4115 rtpg_colormap_arg arg = NULL;
4122 if (PG_ARGISNULL(0))
4128 elog(ERROR,
"RASTER_colorMap: Could not initialize argument structure");
4133 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
4139 PG_FREE_IF_COPY(pgraster, 0);
4140 elog(ERROR,
"RASTER_colorMap: Could not deserialize raster");
4145 if (!PG_ARGISNULL(1))
4146 arg->
nband = PG_GETARG_INT32(1);
4151 elog(NOTICE,
"Raster does not have band at index %d. Returning empty raster", arg->
nband);
4154 if (raster == NULL) {
4156 PG_FREE_IF_COPY(pgraster, 0);
4157 elog(ERROR,
"RASTER_colorMap: Could not create empty raster");
4162 PG_FREE_IF_COPY(pgraster, 0);
4166 if (pgraster == NULL)
4170 PG_RETURN_POINTER(pgraster);
4175 if (arg->
band == NULL) {
4178 PG_FREE_IF_COPY(pgraster, 0);
4179 elog(ERROR,
"RASTER_colorMap: Could not get band at index %d", nband);
4184 if (!PG_ARGISNULL(3)) {
4185 char *method = NULL;
4186 char *tmp = text_to_cstring(PG_GETARG_TEXT_P(3));
4193 if (strcmp(method,
"INTERPOLATE") == 0)
4195 else if (strcmp(method,
"EXACT") == 0)
4197 else if (strcmp(method,
"NEAREST") == 0)
4200 elog(NOTICE,
"Unknown value provided for method. Defaulting to INTERPOLATE");
4210 if (PG_ARGISNULL(2)) {
4212 PG_FREE_IF_COPY(pgraster, 0);
4213 elog(ERROR,
"RASTER_colorMap: Value must be provided for colormap");
4218 char *colormap = text_to_cstring(PG_GETARG_TEXT_P(2));
4227 if (!strlen(colormap)) {
4229 PG_FREE_IF_COPY(pgraster, 0);
4230 elog(ERROR,
"RASTER_colorMap: Value must be provided for colormap");
4238 PG_FREE_IF_COPY(pgraster, 0);
4239 elog(ERROR,
"RASTER_colorMap: Could not process the value provided for colormap");
4247 PG_FREE_IF_COPY(pgraster, 0);
4248 elog(ERROR,
"RASTER_colorMap: Could not allocate memory for colormap entries");
4254 for (i = 0; i < arg->
nentry; i++) {
4268 if (!strlen(_entry)) {
4278 PG_FREE_IF_COPY(pgraster, 0);
4279 elog(ERROR,
"RASTER_colorMap: Could not process colormap entry %d", i + 1);
4283 elog(NOTICE,
"More than five elements in colormap entry %d. Using at most five elements", i + 1);
4292 for (j = 0; j < arg->
nelement; j++) {
4301 char *percent = NULL;
4305 strcmp(_element,
"NV") == 0 ||
4306 strcmp(_element,
"NULL") == 0 ||
4307 strcmp(_element,
"NODATA") == 0
4312 elog(NOTICE,
"More than one NODATA entry found. Using only the first one");
4321 else if ((percent = strchr(_element,
'%')) != NULL) {
4333 PG_FREE_IF_COPY(pgraster, 0);
4334 elog(ERROR,
"RASTER_colorMap: Could not get band's summary stats to process percentages");
4340 tmp = palloc(
sizeof(
char) * (percent - _element + 1));
4344 PG_FREE_IF_COPY(pgraster, 0);
4345 elog(ERROR,
"RASTER_colorMap: Could not allocate memory for value of percentage");
4349 memcpy(tmp, _element, percent - _element);
4350 tmp[percent - _element] =
'\0';
4355 value = strtod(tmp, NULL);
4357 if (errno != 0 || _element == junk) {
4360 PG_FREE_IF_COPY(pgraster, 0);
4361 elog(ERROR,
"RASTER_colorMap: Could not process percent string to value");
4367 elog(NOTICE,
"Percentage values cannot be less than zero. Defaulting to zero");
4370 else if (value > 100.) {
4371 elog(NOTICE,
"Percentage values cannot be greater than 100. Defaulting to 100");
4383 if (errno != 0 || _element == junk) {
4386 PG_FREE_IF_COPY(pgraster, 0);
4387 elog(ERROR,
"RASTER_colorMap: Could not process string to value");
4398 value = (int) strtod(_element, &junk);
4399 if (errno != 0 || _element == junk) {
4402 PG_FREE_IF_COPY(pgraster, 0);
4403 elog(ERROR,
"RASTER_colorMap: Could not process string to value");
4408 elog(NOTICE,
"RGBA value cannot be greater than 255. Defaulting to 255");
4411 else if (value < 0) {
4412 elog(NOTICE,
"RGBA value cannot be less than zero. Defaulting to zero");
4421 POSTGIS_RT_DEBUGF(4,
"colormap->entry[%d] (isnodata, value, R, G, B, A) = (%d, %f, %d, %d, %d, %d)",
4440 if (raster == NULL) {
4442 PG_FREE_IF_COPY(pgraster, 0);
4443 elog(ERROR,
"RASTER_colorMap: Could not create new raster with applied colormap");
4448 PG_FREE_IF_COPY(pgraster, 0);
4454 if (pgraster == NULL)
4458 PG_RETURN_POINTER(pgraster);
4472 double newnodatavalue = 0.0;
4473 double newinitialvalue = 0.0;
4474 double newval = 0.0;
4475 char *newexpr = NULL;
4476 char *initexpr = NULL;
4477 char *expression = NULL;
4478 int hasnodataval = 0;
4479 double nodataval = 0.;
4481 int skipcomputation = 0;
4483 const int argkwcount = 3;
4484 enum KEYWORDS { kVAL=0, kX=1, kY=2 };
4485 char *argkw[] = {
"[rast]",
"[rast.x]",
"[rast.y]"};
4486 Oid argkwtypes[] = { FLOAT8OID, INT4OID, INT4OID };
4488 Oid argtype[] = { FLOAT8OID, INT4OID, INT4OID };
4494 SPIPlanPtr spi_plan = NULL;
4495 SPITupleTable * tuptable = NULL;
4497 char * strFromText = NULL;
4498 Datum *values = NULL;
4499 Datum datum = (Datum)NULL;
4501 bool isnull =
FALSE;
4508 if (PG_ARGISNULL(0)) {
4509 elog(NOTICE,
"Raster is NULL. Returning NULL");
4515 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
4517 if (NULL == raster) {
4518 PG_FREE_IF_COPY(pgraster, 0);
4519 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not deserialize raster");
4525 if (PG_ARGISNULL(1))
4528 nband = PG_GETARG_INT32(1);
4534 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraExpr: Creating new empty raster...");
4545 if ( NULL == newrast ) {
4546 PG_FREE_IF_COPY(pgraster, 0);
4547 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not create a new raster");
4572 elog(NOTICE,
"Raster is empty. Returning an empty raster");
4574 PG_FREE_IF_COPY(pgraster, 0);
4578 if (NULL == pgrtn) {
4580 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not serialize raster");
4584 SET_VARSIZE(pgrtn, pgrtn->
size);
4585 PG_RETURN_POINTER(pgrtn);
4589 POSTGIS_RT_DEBUGF(3,
"RASTER_mapAlgebraExpr: Getting raster band %d...", nband);
4596 elog(NOTICE,
"Raster does not have the required band. Returning a raster " 4599 PG_FREE_IF_COPY(pgraster, 0);
4603 if (NULL == pgrtn) {
4604 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not serialize raster");
4608 SET_VARSIZE(pgrtn, pgrtn->
size);
4609 PG_RETURN_POINTER(pgrtn);
4614 if ( NULL == band ) {
4615 elog(NOTICE,
"Could not get the required band. Returning a raster " 4618 PG_FREE_IF_COPY(pgraster, 0);
4622 if (NULL == pgrtn) {
4623 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not serialize raster");
4627 SET_VARSIZE(pgrtn, pgrtn->
size);
4628 PG_RETURN_POINTER(pgrtn);
4634 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraExpr: Getting NODATA value for band...");
4652 newinitialvalue = newnodatavalue;
4659 if (PG_ARGISNULL(2)) {
4664 strFromText = text_to_cstring(PG_GETARG_TEXT_P(2));
4667 if (newpixeltype ==
PT_END)
4671 if (newpixeltype ==
PT_END) {
4672 PG_FREE_IF_COPY(pgraster, 0);
4673 elog(ERROR,
"RASTER_mapAlgebraExpr: Invalid pixeltype");
4682 if (!PG_ARGISNULL(3)) {
4683 expression = text_to_cstring(PG_GETARG_TEXT_P(3));
4684 len = strlen(
"SELECT (") + strlen(expression) + strlen(
")::double precision");
4685 initexpr = (
char *)palloc(len + 1);
4687 strncpy(initexpr,
"SELECT (", strlen(
"SELECT ("));
4688 strncpy(initexpr + strlen(
"SELECT ("), expression, strlen(expression));
4689 strncpy(initexpr + strlen(
"SELECT (") + strlen(expression),
")::double precision", strlen(
")::double precision"));
4690 initexpr[len] =
'\0';
4708 if (!PG_ARGISNULL(4)) {
4710 nodataval = PG_GETARG_FLOAT8(4);
4711 newinitialvalue = nodataval;
4728 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraExpr: Band is a nodata band, returning " 4729 "a raster filled with nodata");
4732 newinitialvalue,
TRUE, newnodatavalue, 0);
4738 PG_FREE_IF_COPY(pgraster, 0);
4743 if (NULL == pgrtn) {
4744 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not serialize raster");
4748 SET_VARSIZE(pgrtn, pgrtn->
size);
4749 PG_RETURN_POINTER(pgrtn);
4757 if (initexpr != NULL && ( !strcmp(initexpr,
"SELECT [rast]") || !strcmp(initexpr,
"SELECT [rast.val]") ) && !hasnodataval) {
4760 "Returning raster with band %d from original raster", nband);
4773 PG_FREE_IF_COPY(pgraster, 0);
4778 if (NULL == pgrtn) {
4779 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not serialize raster");
4783 SET_VARSIZE(pgrtn, pgrtn->
size);
4784 PG_RETURN_POINTER(pgrtn);
4791 if (initexpr != NULL && strstr(initexpr,
"[rast") == NULL) {
4792 ret = SPI_connect();
4793 if (ret != SPI_OK_CONNECT) {
4794 PG_FREE_IF_COPY(pgraster, 0);
4795 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not connect to the SPI manager");
4800 ret = SPI_execute(initexpr,
FALSE, 0);
4802 if (ret != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
4806 SPI_freetuptable(tuptable);
4807 PG_FREE_IF_COPY(pgraster, 0);
4810 elog(ERROR,
"RASTER_mapAlgebraExpr: Invalid construction for expression");
4814 tupdesc = SPI_tuptable->tupdesc;
4815 tuptable = SPI_tuptable;
4817 tuple = tuptable->vals[0];
4818 newexpr = SPI_getvalue(tuple, tupdesc, 1);
4820 POSTGIS_RT_DEBUG(3,
"Constant expression evaluated to NULL, keeping initvalue");
4821 newval = newinitialvalue;
4823 newval = atof(newexpr);
4826 SPI_freetuptable(tuptable);
4833 skipcomputation = 1;
4839 if (!hasnodataval) {
4840 newinitialvalue = newval;
4841 skipcomputation = 2;
4845 else if (
FLT_NEQ(newval, newinitialvalue)) {
4846 skipcomputation = 2;
4855 newinitialvalue,
TRUE, newnodatavalue, 0);
4862 if (expression == NULL || skipcomputation == 2) {
4868 PG_FREE_IF_COPY(pgraster, 0);
4873 if (NULL == pgrtn) {
4874 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not serialize raster");
4878 SET_VARSIZE(pgrtn, pgrtn->
size);
4879 PG_RETURN_POINTER(pgrtn);
4882 RASTER_DEBUG(3,
"RASTER_mapAlgebraExpr: Creating new raster band...");
4886 if ( NULL == newband ) {
4887 elog(NOTICE,
"Could not modify band for new raster. Returning new " 4888 "raster with the original band");
4893 PG_FREE_IF_COPY(pgraster, 0);
4898 if (NULL == pgrtn) {
4899 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not serialize raster");
4903 SET_VARSIZE(pgrtn, pgrtn->
size);
4904 PG_RETURN_POINTER(pgrtn);
4910 if (initexpr != NULL) {
4913 pfree(initexpr); initexpr=newexpr;
4915 sprintf(place,
"$1");
4916 for (i = 0, j = 1; i < argkwcount; i++) {
4919 pfree(initexpr); initexpr=newexpr;
4921 argtype[argcount] = argkwtypes[i];
4925 sprintf(place,
"$%d", j);
4935 values = (Datum *) palloc(
sizeof(Datum) * argcount);
4936 if (values == NULL) {
4941 PG_FREE_IF_COPY(pgraster, 0);
4944 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not allocate memory for value parameters of prepared statement");
4949 nulls = (
char *)palloc(argcount);
4950 if (nulls == NULL) {
4955 PG_FREE_IF_COPY(pgraster, 0);
4958 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not allocate memory for null parameters of prepared statement");
4963 ret = SPI_connect();
4964 if (ret != SPI_OK_CONNECT) {
4969 PG_FREE_IF_COPY(pgraster, 0);
4972 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not connect to the SPI manager");
4977 spi_plan = SPI_prepare(initexpr, argcount, argtype);
4979 if (spi_plan == NULL) {
4982 PG_FREE_IF_COPY(pgraster, 0);
4989 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not prepare expression");
4994 for (x = 0; x <
width; x++) {
4995 for(y = 0; y <
height; y++) {
5003 if (skipcomputation == 0) {
5004 if (initexpr != NULL) {
5006 memset(nulls,
'n', argcount);
5008 for (i = 0; i < argkwcount; i++) {
5010 if (idx < 1)
continue;
5015 values[idx] = Int32GetDatum(x+1);
5020 values[idx] = Int32GetDatum(y+1);
5023 else if (i == kVAL ) {
5024 values[idx] = Float8GetDatum(r);
5030 ret = SPI_execute_plan(spi_plan, values, nulls,
FALSE, 0);
5031 if (ret != SPI_OK_SELECT || SPI_tuptable == NULL ||
5032 SPI_processed != 1) {
5034 SPI_freetuptable(tuptable);
5036 SPI_freeplan(spi_plan);
5044 PG_FREE_IF_COPY(pgraster, 0);
5047 elog(ERROR,
"RASTER_mapAlgebraExpr: Error executing prepared plan");
5052 tupdesc = SPI_tuptable->tupdesc;
5053 tuptable = SPI_tuptable;
5055 tuple = tuptable->vals[0];
5056 datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
5057 if ( SPI_result == SPI_ERROR_NOATTRIBUTE ) {
5058 POSTGIS_RT_DEBUGF(3,
"Expression for pixel %d,%d (value %g) errored, skip setting", x+1,y+1,r);
5059 newval = newinitialvalue;
5061 else if ( isnull ) {
5062 POSTGIS_RT_DEBUGF(3,
"Expression for pixel %d,%d (value %g) evaluated to NULL, skip setting", x+1,y+1,r);
5063 newval = newinitialvalue;
5065 newval = DatumGetFloat8(datum);
5068 SPI_freetuptable(tuptable);
5072 newval = newinitialvalue;
5085 if (initexpr != NULL) {
5086 SPI_freeplan(spi_plan);
5100 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraExpr: raster modified, serializing it.");
5104 PG_FREE_IF_COPY(pgraster, 0);
5111 SET_VARSIZE(pgrtn, pgrtn->
size);
5119 PG_RETURN_POINTER(pgrtn);
5136 double newnodatavalue = 0.0;
5137 double newinitialvalue = 0.0;
5138 double newval = 0.0;
5143 #if POSTGIS_PGSQL_VERSION < 120 5144 FunctionCallInfoData cbdata;
5146 LOCAL_FCINFO(cbdata, FUNC_MAX_ARGS);
5149 char * strFromText = NULL;
5155 if (PG_ARGISNULL(0)) {
5156 elog(WARNING,
"Raster is NULL. Returning NULL");
5162 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
5164 if (NULL == raster) {
5165 PG_FREE_IF_COPY(pgraster, 0);
5166 elog(ERROR,
"RASTER_mapAlgebraFct: Could not deserialize raster");
5174 if (PG_ARGISNULL(1))
5177 nband = PG_GETARG_INT32(1);
5193 if ( NULL == newrast ) {
5196 PG_FREE_IF_COPY(pgraster, 0);
5198 elog(ERROR,
"RASTER_mapAlgebraFct: Could not create a new raster");
5223 elog(NOTICE,
"Raster is empty. Returning an empty raster");
5225 PG_FREE_IF_COPY(pgraster, 0);
5229 if (NULL == pgrtn) {
5230 elog(ERROR,
"RASTER_mapAlgebraFct: Could not serialize raster");
5234 SET_VARSIZE(pgrtn, pgrtn->
size);
5235 PG_RETURN_POINTER(pgrtn);
5245 elog(NOTICE,
"Raster does not have the required band. Returning a raster " 5248 PG_FREE_IF_COPY(pgraster, 0);
5252 if (NULL == pgrtn) {
5253 elog(ERROR,
"RASTER_mapAlgebraFct: Could not serialize raster");
5257 SET_VARSIZE(pgrtn, pgrtn->
size);
5258 PG_RETURN_POINTER(pgrtn);
5263 if ( NULL == band ) {
5264 elog(NOTICE,
"Could not get the required band. Returning a raster "