404 FuncCallContext *funcctx;
421 if (SRF_IS_FIRSTCALL()) {
422 MemoryContext oldcontext;
428 bool exclude_nodata_value =
TRUE;
441 funcctx = SRF_FIRSTCALL_INIT();
444 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
447 if (PG_ARGISNULL(0)) {
448 MemoryContextSwitchTo(oldcontext);
449 SRF_RETURN_DONE(funcctx);
451 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
455 PG_FREE_IF_COPY(pgraster, 0);
457 errcode(ERRCODE_OUT_OF_MEMORY),
458 errmsg(
"Could not deserialize raster")
460 MemoryContextSwitchTo(oldcontext);
461 SRF_RETURN_DONE(funcctx);
478 elog(NOTICE,
"Raster provided has no bands");
480 PG_FREE_IF_COPY(pgraster, 0);
481 MemoryContextSwitchTo(oldcontext);
482 SRF_RETURN_DONE(funcctx);
489 PG_FREE_IF_COPY(pgraster, 0);
490 MemoryContextSwitchTo(oldcontext);
491 elog(ERROR,
"RASTER_dumpValues: Could not initialize argument structure");
492 SRF_RETURN_DONE(funcctx);
496 if (!PG_ARGISNULL(1)) {
497 array = PG_GETARG_ARRAYTYPE_P(1);
498 etype = ARR_ELEMTYPE(array);
499 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
508 PG_FREE_IF_COPY(pgraster, 0);
509 MemoryContextSwitchTo(oldcontext);
510 elog(ERROR,
"RASTER_dumpValues: Invalid data type for band indexes");
511 SRF_RETURN_DONE(funcctx);
515 deconstruct_array(array, etype, typlen, typbyval, typalign, &e, &nulls, &(arg1->
numbands));
518 if (arg1->
nbands == NULL) {
521 PG_FREE_IF_COPY(pgraster, 0);
522 MemoryContextSwitchTo(oldcontext);
523 elog(ERROR,
"RASTER_dumpValues: Could not allocate memory for band indexes");
524 SRF_RETURN_DONE(funcctx);
527 for (i = 0, j = 0; i < arg1->
numbands; i++) {
528 if (nulls[i])
continue;
532 arg1->
nbands[j] = DatumGetInt16(e[i]) - 1;
535 arg1->
nbands[j] = DatumGetInt32(e[i]) - 1;
542 if (j < arg1->numbands) {
544 if (arg1->
nbands == NULL) {
547 PG_FREE_IF_COPY(pgraster, 0);
548 MemoryContextSwitchTo(oldcontext);
549 elog(ERROR,
"RASTER_dumpValues: Could not reallocate memory for band indexes");
550 SRF_RETURN_DONE(funcctx);
557 for (i = 0; i < arg1->
numbands; i++) {
559 elog(NOTICE,
"Band at index %d not found in raster", arg1->
nbands[i] + 1);
562 PG_FREE_IF_COPY(pgraster, 0);
563 MemoryContextSwitchTo(oldcontext);
564 SRF_RETURN_DONE(funcctx);
574 if (arg1->
nbands == NULL) {
577 PG_FREE_IF_COPY(pgraster, 0);
578 MemoryContextSwitchTo(oldcontext);
579 elog(ERROR,
"RASTER_dumpValues: Could not allocate memory for band indexes");
580 SRF_RETURN_DONE(funcctx);
583 for (i = 0; i < arg1->
numbands; i++) {
593 if (!PG_ARGISNULL(2))
594 exclude_nodata_value = PG_GETARG_BOOL(2);
603 PG_FREE_IF_COPY(pgraster, 0);
604 MemoryContextSwitchTo(oldcontext);
605 elog(ERROR,
"RASTER_dumpValues: Could not allocate memory for pixel values");
606 SRF_RETURN_DONE(funcctx);
612 for (z = 0; z < arg1->
numbands; z++) {
622 PG_FREE_IF_COPY(pgraster, 0);
623 MemoryContextSwitchTo(oldcontext);
624 elog(ERROR,
"RASTER_dumpValues: Could not get band at index %d",
nband);
625 SRF_RETURN_DONE(funcctx);
631 if (arg1->
values[z] == NULL || arg1->
nodata[z] == NULL) {
634 PG_FREE_IF_COPY(pgraster, 0);
635 MemoryContextSwitchTo(oldcontext);
636 elog(ERROR,
"RASTER_dumpValues: Could not allocate memory for pixel values");
637 SRF_RETURN_DONE(funcctx);
646 for (i = (arg1->
rows * arg1->
columns) - 1; i >= 0; i--)
651 for (
y = 0;
y < arg1->
rows;
y++) {
658 PG_FREE_IF_COPY(pgraster, 0);
659 MemoryContextSwitchTo(oldcontext);
660 elog(ERROR,
"RASTER_dumpValues: Could not pixel (%d, %d) of band %d",
x,
y,
nband);
661 SRF_RETURN_DONE(funcctx);
664 arg1->
values[z][i] = Float8GetDatum(val);
668 if (exclude_nodata_value && isnodata) {
682 PG_FREE_IF_COPY(pgraster, 0);
685 funcctx->user_fctx = arg1;
688 funcctx->max_calls = arg1->
numbands;
691 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
692 MemoryContextSwitchTo(oldcontext);
694 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
696 "function returning record called in context "
697 "that cannot accept type record"
702 BlessTupleDesc(tupdesc);
703 funcctx->tuple_desc = tupdesc;
705 MemoryContextSwitchTo(oldcontext);
709 funcctx = SRF_PERCALL_SETUP();
711 call_cntr = funcctx->call_cntr;
712 max_calls = funcctx->max_calls;
713 tupdesc = funcctx->tuple_desc;
714 arg2 = funcctx->user_fctx;
717 if (call_cntr < max_calls) {
722 ArrayType *mdValues = NULL;
725 int lbound[2] = {1, 1};
732 values[0] = Int32GetDatum(arg2->
nbands[call_cntr] + 1);
735 get_typlenbyvalalign(FLOAT8OID, &typlen, &typbyval, &typalign);
738 if (arg2->
values[call_cntr] == NULL)
742 mdValues = construct_md_array(
746 typlen, typbyval, typalign
748 values[1] = PointerGetDatum(mdValues);
751 tuple = heap_form_tuple(tupdesc, values, nulls);
752 result = HeapTupleGetDatum(tuple);
754 SRF_RETURN_NEXT(funcctx,
result);
759 SRF_RETURN_DONE(funcctx);
char result[OUT_DOUBLE_BUFFER_SIZE]
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel 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.
int rt_raster_has_band(rt_raster raster, int nband)
Return TRUE if the raster has a band of this number.
uint16_t rt_raster_get_num_bands(rt_raster raster)
uint16_t rt_raster_get_height(rt_raster raster)
uint16_t rt_raster_get_width(rt_raster raster)
int rt_band_clamped_value_is_nodata(rt_band band, double val)
Compare clamped value to band's clamped NODATA value.
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
int rt_raster_is_empty(rt_raster raster)
Return TRUE if the raster is empty.
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): ...
static void rtpg_dumpvalues_arg_destroy(rtpg_dumpvalues_arg arg)
static rtpg_dumpvalues_arg rtpg_dumpvalues_arg_init()
#define POSTGIS_RT_DEBUG(level, msg)
#define POSTGIS_RT_DEBUGF(level, msg,...)