31 #define _LARGEFILE64_SOURCE 1
34 #include <utils/builtins.h>
35 #include "utils/lsyscache.h"
36 #include "utils/array.h"
37 #include "catalog/pg_type.h"
39 #include "../../postgis_config.h"
42 #include "access/htup_details.h"
79 if (PG_ARGISNULL(0)) PG_RETURN_NULL();
80 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
83 bandindex = PG_GETARG_INT32(1);
84 if ( bandindex < 1 ) {
85 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
86 PG_FREE_IF_COPY(pgraster, 0);
92 PG_FREE_IF_COPY(pgraster, 0);
93 elog(ERROR,
"RASTER_getBandPixelType: Could not deserialize raster");
100 elog(NOTICE,
"Could not find raster band of index %d when getting pixel type. Returning NULL", bandindex);
102 PG_FREE_IF_COPY(pgraster, 0);
109 PG_FREE_IF_COPY(pgraster, 0);
111 PG_RETURN_INT32(pixtype);
127 const size_t name_size = 8;
133 if (PG_ARGISNULL(0)) PG_RETURN_NULL();
134 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
137 bandindex = PG_GETARG_INT32(1);
138 if ( bandindex < 1 ) {
139 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
140 PG_FREE_IF_COPY(pgraster, 0);
146 PG_FREE_IF_COPY(pgraster, 0);
147 elog(ERROR,
"RASTER_getBandPixelTypeName: Could not deserialize raster");
154 elog(NOTICE,
"Could not find raster band of index %d when getting pixel type name. Returning NULL", bandindex);
156 PG_FREE_IF_COPY(pgraster, 0);
162 result = palloc(VARHDRSZ + name_size);
167 memset(VARDATA(
result), 0, name_size);
168 ptr = (
char *)
result + VARHDRSZ;
171 size = VARHDRSZ + strlen(ptr);
172 SET_VARSIZE(
result, size);
175 PG_FREE_IF_COPY(pgraster, 0);
194 if (PG_ARGISNULL(0)) PG_RETURN_NULL();
195 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
198 bandindex = PG_GETARG_INT32(1);
199 if ( bandindex < 1 ) {
200 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
201 PG_FREE_IF_COPY(pgraster, 0);
207 PG_FREE_IF_COPY(pgraster, 0);
208 elog(ERROR,
"RASTER_getBandNoDataValue: Could not deserialize raster");
215 elog(NOTICE,
"Could not find raster band of index %d when getting band nodata value. Returning NULL", bandindex);
217 PG_FREE_IF_COPY(pgraster, 0);
224 PG_FREE_IF_COPY(pgraster, 0);
231 PG_FREE_IF_COPY(pgraster, 0);
233 PG_RETURN_FLOAT8(nodata);
244 bool forcechecking =
FALSE;
245 bool bandisnodata =
FALSE;
248 bandindex = PG_GETARG_INT32(1);
249 if ( bandindex < 1 ) {
250 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
255 if (PG_ARGISNULL(0)) PG_RETURN_NULL();
256 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
260 PG_FREE_IF_COPY(pgraster, 0);
261 elog(ERROR,
"RASTER_bandIsNoData: Could not deserialize raster");
268 elog(NOTICE,
"Could not find raster band of index %d when determining if band is nodata. Returning NULL", bandindex);
270 PG_FREE_IF_COPY(pgraster, 0);
274 forcechecking = PG_GETARG_BOOL(2);
276 bandisnodata = (forcechecking) ?
280 PG_FREE_IF_COPY(pgraster, 0);
282 PG_RETURN_BOOL(bandisnodata);
295 const char *bandpath;
299 bandindex = PG_GETARG_INT32(1);
300 if ( bandindex < 1 ) {
301 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
306 if (PG_ARGISNULL(0)) PG_RETURN_NULL();
307 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
311 PG_FREE_IF_COPY(pgraster, 0);
312 elog(ERROR,
"RASTER_getBandPath: Could not deserialize raster");
321 "Could not find raster band of index %d when getting band path. Returning NULL",
325 PG_FREE_IF_COPY(pgraster, 0);
333 PG_FREE_IF_COPY(pgraster, 0);
337 result = cstring_to_text(bandpath);
341 PG_FREE_IF_COPY(pgraster, 0);
360 bandindex = PG_GETARG_INT32(1);
361 if ( bandindex < 1 ) {
362 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
366 if (PG_ARGISNULL(0)) PG_RETURN_NULL();
367 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
371 PG_FREE_IF_COPY(pgraster, 0);
372 elog(ERROR,
"RASTER_getFileSize: Could not deserialize raster");
381 "Could not find raster band of index %d when getting band path. Returning NULL",
385 PG_FREE_IF_COPY(pgraster, 0);
390 elog(NOTICE,
"Band of index %d is not out-db.", bandindex);
393 PG_FREE_IF_COPY(pgraster, 0);
401 PG_FREE_IF_COPY(pgraster, 0);
403 PG_RETURN_INT64(fileSize);
419 bandindex = PG_GETARG_INT32(1);
420 if ( bandindex < 1 ) {
421 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
425 if (PG_ARGISNULL(0)) PG_RETURN_NULL();
426 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
430 PG_FREE_IF_COPY(pgraster, 0);
431 elog(ERROR,
"RASTER_getBandFileTimestamp: Could not deserialize raster");
440 "Could not find raster band of index %d when getting band path. Returning NULL",
444 PG_FREE_IF_COPY(pgraster, 0);
449 elog(NOTICE,
"Band of index %d is not out-db.", bandindex);
452 PG_FREE_IF_COPY(pgraster, 0);
460 PG_FREE_IF_COPY(pgraster, 0);
462 PG_RETURN_INT64(fileSize);
465 #define VALUES_LENGTH 8
473 FuncCallContext *funcctx;
478 struct bandmetadata {
490 struct bandmetadata *bmd = NULL;
491 struct bandmetadata *bmd2 = NULL;
496 if (SRF_IS_FIRSTCALL()) {
497 MemoryContext oldcontext;
516 uint32_t *bandNums = NULL;
517 const char *chartmp = NULL;
524 funcctx = SRF_FIRSTCALL_INIT();
527 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
530 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
531 MemoryContextSwitchTo(oldcontext);
533 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
535 "function returning record called in context "
536 "that cannot accept type record"
541 BlessTupleDesc(tupdesc);
542 funcctx->tuple_desc = tupdesc;
545 if (PG_ARGISNULL(0)) {
546 bmd = (
struct bandmetadata *) palloc(
sizeof(
struct bandmetadata));
547 bmd->isnullband =
TRUE;
548 funcctx->user_fctx = bmd;
549 funcctx->max_calls = 1;
550 MemoryContextSwitchTo(oldcontext);
553 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
558 PG_FREE_IF_COPY(pgraster, 0);
559 MemoryContextSwitchTo(oldcontext);
560 elog(ERROR,
"RASTER_bandmetadata: Could not deserialize raster");
561 SRF_RETURN_DONE(funcctx);
567 elog(NOTICE,
"Raster provided has no bands");
569 PG_FREE_IF_COPY(pgraster, 0);
570 bmd = (
struct bandmetadata *) palloc(
sizeof(
struct bandmetadata));
571 bmd->isnullband =
TRUE;
572 funcctx->user_fctx = bmd;
573 funcctx->max_calls = 1;
574 MemoryContextSwitchTo(oldcontext);
579 array = PG_GETARG_ARRAYTYPE_P(1);
580 etype = ARR_ELEMTYPE(array);
581 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
589 PG_FREE_IF_COPY(pgraster, 0);
590 MemoryContextSwitchTo(oldcontext);
591 elog(ERROR,
"RASTER_bandmetadata: Invalid data type for band number(s)");
592 SRF_RETURN_DONE(funcctx);
596 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
599 bandNums = palloc(
sizeof(uint32_t) * n);
600 for (i = 0, j = 0; i < n; i++) {
601 if (nulls[i])
continue;
605 idx = (uint32_t) DatumGetInt16(e[i]);
608 idx = (uint32_t) DatumGetInt32(e[i]);
613 if (idx > numBands || idx < 1) {
614 elog(NOTICE,
"Invalid band index: %d. Indices must be 1-based. Returning NULL", idx);
617 PG_FREE_IF_COPY(pgraster, 0);
618 bmd = (
struct bandmetadata *) palloc(
sizeof(
struct bandmetadata));
619 bmd->isnullband =
TRUE;
620 funcctx->user_fctx = bmd;
621 funcctx->max_calls = 1;
622 MemoryContextSwitchTo(oldcontext);
633 bandNums = repalloc(bandNums,
sizeof(uint32_t) * j);
634 for (i = 0; i < j; i++)
638 bandNums = repalloc(bandNums,
sizeof(uint32_t) * j);
640 bmd = (
struct bandmetadata *) palloc0(
sizeof(
struct bandmetadata) * j);
642 for (i = 0; i < j; i++) {
645 elog(NOTICE,
"Could not get raster band at index %d", bandNums[i]);
647 PG_FREE_IF_COPY(pgraster, 0);
648 bmd[0].isnullband =
TRUE;
649 funcctx->user_fctx = bmd;
650 funcctx->max_calls = 1;
651 MemoryContextSwitchTo(oldcontext);
656 bmd[i].bandnum = bandNums[i];
660 charlen = strlen(chartmp) + 1;
661 bmd[i].pixeltype = palloc(
sizeof(
char) * charlen);
662 strncpy(bmd[i].pixeltype, chartmp, charlen);
666 bmd[i].hasnodata =
TRUE;
668 bmd[i].hasnodata =
FALSE;
671 if (bmd[i].hasnodata)
674 bmd[i].nodataval = 0;
679 charlen = strlen(chartmp) + 1;
680 bmd[i].bandpath = palloc(
sizeof(
char) * charlen);
681 strncpy(bmd[i].bandpath, chartmp, charlen);
684 bmd[i].bandpath = NULL;
687 bmd[i].isoutdb = bmd[i].bandpath ?
TRUE :
FALSE;
691 bmd[i].extbandnum = extbandnum + 1;
693 bmd[i].extbandnum = 0;
696 bmd[i].timestamp = 0;
699 if( VSIStatL(bmd[i].bandpath, &sStat) == 0 ) {
700 bmd[i].filesize = sStat.st_size;
701 bmd[i].timestamp = sStat.st_mtime;
709 PG_FREE_IF_COPY(pgraster, 0);
712 funcctx->user_fctx = bmd;
715 funcctx->max_calls = j;
717 MemoryContextSwitchTo(oldcontext);
723 funcctx = SRF_PERCALL_SETUP();
725 call_cntr = funcctx->call_cntr;
726 max_calls = funcctx->max_calls;
727 tupdesc = funcctx->tuple_desc;
728 bmd2 = funcctx->user_fctx;
731 if (call_cntr < max_calls) {
735 if (bmd2[0].isnullband) {
739 result = HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls));
740 SRF_RETURN_NEXT(funcctx,
result);
745 values[0] = UInt32GetDatum(bmd2[call_cntr].bandnum);
746 values[1] = CStringGetTextDatum(bmd2[call_cntr].pixeltype);
748 if (bmd2[call_cntr].hasnodata)
749 values[2] = Float8GetDatum(bmd2[call_cntr].nodataval);
753 values[3] = BoolGetDatum(bmd2[call_cntr].isoutdb);
754 if (bmd2[call_cntr].bandpath && strlen(bmd2[call_cntr].bandpath)) {
755 values[4] = CStringGetTextDatum(bmd2[call_cntr].bandpath);
756 values[5] = UInt32GetDatum(bmd2[call_cntr].extbandnum);
763 if (bmd2[call_cntr].filesize)
765 values[6] = UInt64GetDatum(bmd2[call_cntr].filesize);
766 values[7] = UInt64GetDatum(bmd2[call_cntr].timestamp);
775 tuple = heap_form_tuple(tupdesc, values, nulls);
778 result = HeapTupleGetDatum(tuple);
781 pfree(bmd2[call_cntr].pixeltype);
782 if (bmd2[call_cntr].bandpath) pfree(bmd2[call_cntr].bandpath);
784 SRF_RETURN_NEXT(funcctx,
result);
789 SRF_RETURN_DONE(funcctx);
805 bool forcechecking =
FALSE;
806 bool skipset =
FALSE;
811 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
817 bandindex = PG_GETARG_INT32(1);
819 elog(NOTICE,
"Invalid band index (must use 1-based). Nodata value not set. Returning original raster");
825 PG_FREE_IF_COPY(pgraster, 0);
826 elog(ERROR,
"RASTER_setBandNoDataValue: Could not deserialize raster");
834 elog(NOTICE,
"Could not find raster band of index %d when setting pixel value. Nodata value not set. Returning original raster", bandindex);
837 if (!PG_ARGISNULL(3))
838 forcechecking = PG_GETARG_BOOL(3);
840 if (PG_ARGISNULL(2)) {
847 nodata = PG_GETARG_FLOAT8(2);
861 PG_FREE_IF_COPY(pgraster, 0);
865 SET_VARSIZE(pgrtn, pgrtn->
size);
866 PG_RETURN_POINTER(pgrtn);
883 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
887 PG_FREE_IF_COPY(pgraster, 0);
888 elog(ERROR,
"RASTER_setBandIsNoData: Could not deserialize raster");
896 bandindex = PG_GETARG_INT32(1);
899 elog(NOTICE,
"Invalid band index (must use 1-based). Isnodata flag not set. Returning original raster");
905 elog(NOTICE,
"Could not find raster band of index %d. Isnodata flag not set. Returning original raster", bandindex);
908 elog(NOTICE,
"Band of index %d has no NODATA so cannot be NODATA. Returning original raster", bandindex);
920 PG_FREE_IF_COPY(pgraster, 0);
921 if (!pgrtn) PG_RETURN_NULL();
923 SET_VARSIZE(pgrtn, pgrtn->
size);
924 PG_RETURN_POINTER(pgrtn);
937 int32_t bandindex = 1;
938 const char *outdbpathchar = NULL;
939 int32_t outdbindex = 1;
940 bool forceset =
FALSE;
944 double nodataval = 0.;
948 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
952 PG_FREE_IF_COPY(pgraster, 0);
953 elog(ERROR,
"RASTER_setBandPath: Cannot deserialize raster");
958 if (!PG_ARGISNULL(1))
959 bandindex = PG_GETARG_INT32(1);
962 elog(NOTICE,
"Invalid band index (must use 1-based). Returning original raster");
968 elog(NOTICE,
"Cannot find raster band of index %d. Returning original raster", bandindex);
970 elog(NOTICE,
"Band of index %d is not out-db. Returning original raster", bandindex);
974 if (!PG_ARGISNULL(2))
975 outdbpathchar = text_to_cstring(PG_GETARG_TEXT_P(2));
980 if (!PG_ARGISNULL(3))
981 outdbindex = PG_GETARG_INT32(3);
984 if (!PG_ARGISNULL(4))
985 forceset = PG_GETARG_BOOL(4);
1002 elog(NOTICE,
"Cannot change path of band. Returning original raster");
1012 PG_FREE_IF_COPY(pgraster, 0);
1013 if (!pgrtn) PG_RETURN_NULL();
1015 SET_VARSIZE(pgrtn, pgrtn->
size);
1016 PG_RETURN_POINTER(pgrtn);
char result[OUT_DOUBLE_BUFFER_SIZE]
void rt_band_set_hasnodata_flag(rt_band band, int flag)
Set hasnodata flag value.
rt_errorstate rt_band_set_isnodata_flag(rt_band band, int flag)
Set isnodata flag 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).
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.
int rt_band_get_isnodata_flag(rt_band band)
Get isnodata flag value.
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
rt_band rt_raster_replace_band(rt_raster raster, rt_band band, int index)
Replace band at provided index with new band.
uint64_t rt_band_get_file_size(rt_band band)
Return file size in bytes.
int rt_band_check_is_nodata(rt_band band)
Returns TRUE if the band is only nodata values.
rt_errorstate rt_band_set_nodata(rt_band band, double val, int *converted)
Set nodata value.
void rt_band_destroy(rt_band band)
Destroy a raster band.
uint16_t rt_raster_get_num_bands(rt_raster raster)
uint16_t rt_raster_get_height(rt_raster raster)
rt_errorstate rt_band_get_ext_band_num(rt_band band, uint8_t *bandnum)
Return bands' external band number (only valid when rt_band_is_offline returns non-zero).
uint64_t rt_band_get_file_timestamp(rt_band band)
Return file timestamp.
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
rt_pixtype rt_band_get_pixtype(rt_band band)
Return pixeltype of this band.
const char * rt_pixtype_name(rt_pixtype pixtype)
rt_band rt_band_new_offline_from_path(uint16_t width, uint16_t height, int hasnodata, double nodataval, uint8_t bandNum, const char *path, int force)
Create an out-db rt_band from path.
uint16_t rt_raster_get_width(rt_raster raster)
int rt_band_is_offline(rt_band band)
Return non-zero if the given band data is on the filesystem.
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
Datum RASTER_bandIsNoData(PG_FUNCTION_ARGS)
Datum RASTER_setBandIndex(PG_FUNCTION_ARGS)
Datum RASTER_bandmetadata(PG_FUNCTION_ARGS)
Datum RASTER_setBandNoDataValue(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(RASTER_getBandPixelType)
Return pixel type of the specified band of raster.
bool enable_outdb_rasters
Datum RASTER_getBandPath(PG_FUNCTION_ARGS)
Datum RASTER_getBandFileTimestamp(PG_FUNCTION_ARGS)
Datum RASTER_getBandFileSize(PG_FUNCTION_ARGS)
Datum RASTER_getBandNoDataValue(PG_FUNCTION_ARGS)
Datum RASTER_setBandPath(PG_FUNCTION_ARGS)
Datum RASTER_getBandPixelType(PG_FUNCTION_ARGS)
Datum RASTER_setBandIsNoData(PG_FUNCTION_ARGS)
Datum RASTER_getBandPixelTypeName(PG_FUNCTION_ARGS)
#define POSTGIS_RT_DEBUG(level, msg)
#define POSTGIS_RT_DEBUGF(level, msg,...)