33 #include <utils/builtins.h> 34 #include "utils/lsyscache.h" 35 #include "utils/array.h" 36 #include "catalog/pg_type.h" 38 #include "../../postgis_config.h" 41 #include "access/htup_details.h" 74 if (PG_ARGISNULL(0)) PG_RETURN_NULL();
75 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
78 bandindex = PG_GETARG_INT32(1);
79 if ( bandindex < 1 ) {
80 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
81 PG_FREE_IF_COPY(pgraster, 0);
87 PG_FREE_IF_COPY(pgraster, 0);
88 elog(ERROR,
"RASTER_getBandPixelType: Could not deserialize raster");
95 elog(NOTICE,
"Could not find raster band of index %d when getting pixel type. Returning NULL", bandindex);
97 PG_FREE_IF_COPY(pgraster, 0);
104 PG_FREE_IF_COPY(pgraster, 0);
106 PG_RETURN_INT32(pixtype);
122 const size_t name_size = 8;
128 if (PG_ARGISNULL(0)) PG_RETURN_NULL();
129 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
132 bandindex = PG_GETARG_INT32(1);
133 if ( bandindex < 1 ) {
134 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
135 PG_FREE_IF_COPY(pgraster, 0);
141 PG_FREE_IF_COPY(pgraster, 0);
142 elog(ERROR,
"RASTER_getBandPixelTypeName: Could not deserialize raster");
149 elog(NOTICE,
"Could not find raster band of index %d when getting pixel type name. Returning NULL", bandindex);
151 PG_FREE_IF_COPY(pgraster, 0);
157 result = palloc(VARHDRSZ + name_size);
162 memset(VARDATA(result), 0, name_size);
163 ptr = (
char *)result + VARHDRSZ;
166 size = VARHDRSZ + strlen(ptr);
167 SET_VARSIZE(result, size);
170 PG_FREE_IF_COPY(pgraster, 0);
172 PG_RETURN_TEXT_P(result);
189 if (PG_ARGISNULL(0)) PG_RETURN_NULL();
190 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
193 bandindex = PG_GETARG_INT32(1);
194 if ( bandindex < 1 ) {
195 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
196 PG_FREE_IF_COPY(pgraster, 0);
202 PG_FREE_IF_COPY(pgraster, 0);
203 elog(ERROR,
"RASTER_getBandNoDataValue: Could not deserialize raster");
210 elog(NOTICE,
"Could not find raster band of index %d when getting band nodata value. Returning NULL", bandindex);
212 PG_FREE_IF_COPY(pgraster, 0);
219 PG_FREE_IF_COPY(pgraster, 0);
226 PG_FREE_IF_COPY(pgraster, 0);
228 PG_RETURN_FLOAT8(nodata);
239 bool forcechecking =
FALSE;
240 bool bandisnodata =
FALSE;
243 bandindex = PG_GETARG_INT32(1);
244 if ( bandindex < 1 ) {
245 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
250 if (PG_ARGISNULL(0)) PG_RETURN_NULL();
251 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
255 PG_FREE_IF_COPY(pgraster, 0);
256 elog(ERROR,
"RASTER_bandIsNoData: Could not deserialize raster");
263 elog(NOTICE,
"Could not find raster band of index %d when determining if band is nodata. Returning NULL", bandindex);
265 PG_FREE_IF_COPY(pgraster, 0);
269 forcechecking = PG_GETARG_BOOL(2);
271 bandisnodata = (forcechecking) ?
275 PG_FREE_IF_COPY(pgraster, 0);
277 PG_RETURN_BOOL(bandisnodata);
290 const char *bandpath;
294 bandindex = PG_GETARG_INT32(1);
295 if ( bandindex < 1 ) {
296 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
301 if (PG_ARGISNULL(0)) PG_RETURN_NULL();
302 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
306 PG_FREE_IF_COPY(pgraster, 0);
307 elog(ERROR,
"RASTER_getBandPath: Could not deserialize raster");
316 "Could not find raster band of index %d when getting band path. Returning NULL",
320 PG_FREE_IF_COPY(pgraster, 0);
328 PG_FREE_IF_COPY(pgraster, 0);
332 result = (text *) palloc(VARHDRSZ + strlen(bandpath) + 1);
333 SET_VARSIZE(result, VARHDRSZ + strlen(bandpath) + 1);
334 strcpy((
char *) VARDATA(result), bandpath);
338 PG_FREE_IF_COPY(pgraster, 0);
340 PG_RETURN_TEXT_P(result);
343 #define VALUES_LENGTH 8 351 FuncCallContext *funcctx;
356 struct bandmetadata {
364 struct bandmetadata *bmd = NULL;
365 struct bandmetadata *bmd2 = NULL;
370 if (SRF_IS_FIRSTCALL()) {
371 MemoryContext oldcontext;
391 const char *tmp = NULL;
396 funcctx = SRF_FIRSTCALL_INIT();
399 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
402 if (PG_ARGISNULL(0)) {
403 MemoryContextSwitchTo(oldcontext);
404 SRF_RETURN_DONE(funcctx);
406 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
411 PG_FREE_IF_COPY(pgraster, 0);
412 MemoryContextSwitchTo(oldcontext);
413 elog(ERROR,
"RASTER_bandmetadata: Could not deserialize raster");
414 SRF_RETURN_DONE(funcctx);
420 elog(NOTICE,
"Raster provided has no bands");
422 PG_FREE_IF_COPY(pgraster, 0);
423 MemoryContextSwitchTo(oldcontext);
424 SRF_RETURN_DONE(funcctx);
428 array = PG_GETARG_ARRAYTYPE_P(1);
429 etype = ARR_ELEMTYPE(array);
430 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
438 PG_FREE_IF_COPY(pgraster, 0);
439 MemoryContextSwitchTo(oldcontext);
440 elog(ERROR,
"RASTER_bandmetadata: Invalid data type for band number(s)");
441 SRF_RETURN_DONE(funcctx);
445 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
448 bandNums = palloc(
sizeof(
uint32_t) * n);
449 for (i = 0, j = 0; i < n; i++) {
450 if (nulls[i])
continue;
454 idx = (
uint32_t) DatumGetInt16(e[i]);
457 idx = (
uint32_t) DatumGetInt32(e[i]);
462 if (idx > numBands || idx < 1) {
463 elog(NOTICE,
"Invalid band index: %d. Indices must be 1-based. Returning NULL", idx);
466 PG_FREE_IF_COPY(pgraster, 0);
467 MemoryContextSwitchTo(oldcontext);
468 SRF_RETURN_DONE(funcctx);
478 bandNums = repalloc(bandNums,
sizeof(
uint32_t) * j);
479 for (i = 0; i < j; i++)
483 bandNums = repalloc(bandNums,
sizeof(
uint32_t) * j);
485 bmd = (
struct bandmetadata *) palloc(
sizeof(
struct bandmetadata) * j);
487 for (i = 0; i < j; i++) {
490 elog(NOTICE,
"Could not get raster band at index %d", bandNums[i]);
492 PG_FREE_IF_COPY(pgraster, 0);
493 MemoryContextSwitchTo(oldcontext);
494 SRF_RETURN_DONE(funcctx);
498 bmd[i].bandnum = bandNums[i];
502 bmd[i].pixeltype = palloc(
sizeof(
char) * (strlen(tmp) + 1));
503 strncpy(bmd[i].pixeltype, tmp, strlen(tmp) + 1);
507 bmd[i].hasnodata =
TRUE;
509 bmd[i].hasnodata =
FALSE;
512 if (bmd[i].hasnodata)
515 bmd[i].nodataval = 0;
520 bmd[i].bandpath = palloc(
sizeof(
char) * (strlen(tmp) + 1));
521 strncpy(bmd[i].bandpath, tmp, strlen(tmp) + 1);
524 bmd[i].bandpath = NULL;
527 bmd[i].isoutdb = bmd[i].bandpath ?
TRUE :
FALSE;
533 PG_FREE_IF_COPY(pgraster, 0);
536 funcctx->user_fctx = bmd;
539 funcctx->max_calls = j;
542 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
543 MemoryContextSwitchTo(oldcontext);
545 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
547 "function returning record called in context " 548 "that cannot accept type record" 553 BlessTupleDesc(tupdesc);
554 funcctx->tuple_desc = tupdesc;
556 MemoryContextSwitchTo(oldcontext);
560 funcctx = SRF_PERCALL_SETUP();
562 call_cntr = funcctx->call_cntr;
563 max_calls = funcctx->max_calls;
564 tupdesc = funcctx->tuple_desc;
565 bmd2 = funcctx->user_fctx;
568 if (call_cntr < max_calls) {
574 values[0] = UInt32GetDatum(bmd2[call_cntr].bandnum);
575 values[1] = CStringGetTextDatum(bmd2[call_cntr].pixeltype);
577 if (bmd2[call_cntr].hasnodata)
578 values[2] = Float8GetDatum(bmd2[call_cntr].nodataval);
582 values[3] = BoolGetDatum(bmd2[call_cntr].isoutdb);
583 if (bmd2[call_cntr].bandpath && strlen(bmd2[call_cntr].bandpath))
584 values[4] = CStringGetTextDatum(bmd2[call_cntr].bandpath);
589 tuple = heap_form_tuple(tupdesc, values, nulls);
592 result = HeapTupleGetDatum(tuple);
595 pfree(bmd2[call_cntr].pixeltype);
596 if (bmd2[call_cntr].bandpath) pfree(bmd2[call_cntr].bandpath);
598 SRF_RETURN_NEXT(funcctx, result);
603 SRF_RETURN_DONE(funcctx);
619 bool forcechecking =
FALSE;
620 bool skipset =
FALSE;
625 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
631 bandindex = PG_GETARG_INT32(1);
633 elog(NOTICE,
"Invalid band index (must use 1-based). Nodata value not set. Returning original raster");
639 PG_FREE_IF_COPY(pgraster, 0);
640 elog(ERROR,
"RASTER_setBandNoDataValue: Could not deserialize raster");
648 elog(NOTICE,
"Could not find raster band of index %d when setting pixel value. Nodata value not set. Returning original raster", bandindex);
651 if (!PG_ARGISNULL(3))
652 forcechecking = PG_GETARG_BOOL(3);
654 if (PG_ARGISNULL(2)) {
661 nodata = PG_GETARG_FLOAT8(2);
675 PG_FREE_IF_COPY(pgraster, 0);
679 SET_VARSIZE(pgrtn, pgrtn->
size);
680 PG_RETURN_POINTER(pgrtn);
694 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
698 PG_FREE_IF_COPY(pgraster, 0);
699 elog(ERROR,
"RASTER_setBandIsNoData: Could not deserialize raster");
707 bandindex = PG_GETARG_INT32(1);
710 elog(NOTICE,
"Invalid band index (must use 1-based). Isnodata flag not set. Returning original raster");
716 elog(NOTICE,
"Could not find raster band of index %d. Isnodata flag not set. Returning original raster", bandindex);
719 elog(NOTICE,
"Band of index %d has no NODATA so cannot be NODATA. Returning original raster", bandindex);
731 PG_FREE_IF_COPY(pgraster, 0);
732 if (!pgrtn) PG_RETURN_NULL();
734 SET_VARSIZE(pgrtn, pgrtn->
size);
735 PG_RETURN_POINTER(pgrtn);
PG_FUNCTION_INFO_V1(RASTER_getBandPixelType)
Return pixel type of the specified band of raster.
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
int rt_raster_get_num_bands(rt_raster raster)
raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
Datum RASTER_bandmetadata(PG_FUNCTION_ARGS)
Datum RASTER_getBandPixelTypeName(PG_FUNCTION_ARGS)
rt_errorstate rt_band_set_nodata(rt_band band, double val, int *converted)
Set nodata value.
Datum RASTER_getBandNoDataValue(PG_FUNCTION_ARGS)
void rt_band_destroy(rt_band band)
Destroy a raster band.
#define POSTGIS_RT_DEBUGF(level, msg,...)
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
const char * rt_band_get_ext_path(rt_band band)
Return band's external path (only valid when rt_band_is_offline returns non-zero).
Datum RASTER_getBandPixelType(PG_FUNCTION_ARGS)
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
int rt_band_check_is_nodata(rt_band band)
Returns TRUE if the band is only nodata values.
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
void rt_band_set_hasnodata_flag(rt_band band, int flag)
Set hasnodata flag value.
Datum RASTER_getBandPath(PG_FUNCTION_ARGS)
Datum RASTER_setBandNoDataValue(PG_FUNCTION_ARGS)
rt_errorstate rt_band_set_isnodata_flag(rt_band band, int flag)
Set isnodata flag value.
const char * rt_pixtype_name(rt_pixtype pixtype)
rt_pixtype rt_band_get_pixtype(rt_band band)
Return pixeltype of this band.
int rt_band_get_isnodata_flag(rt_band band)
Get isnodata flag value.
Datum RASTER_setBandIsNoData(PG_FUNCTION_ARGS)
Datum RASTER_bandIsNoData(PG_FUNCTION_ARGS)
#define POSTGIS_RT_DEBUG(level, msg)
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.