203 FuncCallContext *funcctx;
220 if (SRF_IS_FIRSTCALL()) {
221 MemoryContext oldcontext;
227 bool exclude_nodata_value =
TRUE;
240 funcctx = SRF_FIRSTCALL_INIT();
243 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
246 if (PG_ARGISNULL(0)) {
247 MemoryContextSwitchTo(oldcontext);
248 SRF_RETURN_DONE(funcctx);
250 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
254 PG_FREE_IF_COPY(pgraster, 0);
256 errcode(ERRCODE_OUT_OF_MEMORY),
257 errmsg(
"Could not deserialize raster")
259 MemoryContextSwitchTo(oldcontext);
260 SRF_RETURN_DONE(funcctx);
277 elog(NOTICE,
"Raster provided has no bands");
279 PG_FREE_IF_COPY(pgraster, 0);
280 MemoryContextSwitchTo(oldcontext);
281 SRF_RETURN_DONE(funcctx);
288 PG_FREE_IF_COPY(pgraster, 0);
289 MemoryContextSwitchTo(oldcontext);
290 elog(ERROR,
"RASTER_dumpValues: Could not initialize argument structure");
291 SRF_RETURN_DONE(funcctx);
295 if (!PG_ARGISNULL(1)) {
296 array = PG_GETARG_ARRAYTYPE_P(1);
297 etype = ARR_ELEMTYPE(array);
298 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
307 PG_FREE_IF_COPY(pgraster, 0);
308 MemoryContextSwitchTo(oldcontext);
309 elog(ERROR,
"RASTER_dumpValues: Invalid data type for band indexes");
310 SRF_RETURN_DONE(funcctx);
314 deconstruct_array(array, etype, typlen, typbyval, typalign, &e, &nulls, &(arg1->
numbands));
317 if (arg1->
nbands == NULL) {
320 PG_FREE_IF_COPY(pgraster, 0);
321 MemoryContextSwitchTo(oldcontext);
322 elog(ERROR,
"RASTER_dumpValues: Could not allocate memory for band indexes");
323 SRF_RETURN_DONE(funcctx);
326 for (i = 0, j = 0; i < arg1->
numbands; i++) {
327 if (nulls[i])
continue;
331 arg1->
nbands[j] = DatumGetInt16(e[i]) - 1;
334 arg1->
nbands[j] = DatumGetInt32(e[i]) - 1;
341 if (j < arg1->numbands) {
343 if (arg1->
nbands == NULL) {
346 PG_FREE_IF_COPY(pgraster, 0);
347 MemoryContextSwitchTo(oldcontext);
348 elog(ERROR,
"RASTER_dumpValues: Could not reallocate memory for band indexes");
349 SRF_RETURN_DONE(funcctx);
356 for (i = 0; i < arg1->
numbands; i++) {
358 elog(NOTICE,
"Band at index %d not found in raster", arg1->
nbands[i] + 1);
361 PG_FREE_IF_COPY(pgraster, 0);
362 MemoryContextSwitchTo(oldcontext);
363 SRF_RETURN_DONE(funcctx);
373 if (arg1->
nbands == NULL) {
376 PG_FREE_IF_COPY(pgraster, 0);
377 MemoryContextSwitchTo(oldcontext);
378 elog(ERROR,
"RASTER_dumpValues: Could not allocate memory for band indexes");
379 SRF_RETURN_DONE(funcctx);
382 for (i = 0; i < arg1->
numbands; i++) {
392 if (!PG_ARGISNULL(2))
393 exclude_nodata_value = PG_GETARG_BOOL(2);
402 PG_FREE_IF_COPY(pgraster, 0);
403 MemoryContextSwitchTo(oldcontext);
404 elog(ERROR,
"RASTER_dumpValues: Could not allocate memory for pixel values");
405 SRF_RETURN_DONE(funcctx);
411 for (z = 0; z < arg1->
numbands; z++) {
421 PG_FREE_IF_COPY(pgraster, 0);
422 MemoryContextSwitchTo(oldcontext);
423 elog(ERROR,
"RASTER_dumpValues: Could not get band at index %d", nband);
424 SRF_RETURN_DONE(funcctx);
430 if (arg1->
values[z] == NULL || arg1->
nodata[z] == NULL) {
433 PG_FREE_IF_COPY(pgraster, 0);
434 MemoryContextSwitchTo(oldcontext);
435 elog(ERROR,
"RASTER_dumpValues: Could not allocate memory for pixel values");
436 SRF_RETURN_DONE(funcctx);
445 for (i = (arg1->
rows * arg1->
columns) - 1; i >= 0; i--)
450 for (y = 0; y < arg1->
rows; y++) {
451 for (x = 0; x < arg1->
columns; x++) {
457 PG_FREE_IF_COPY(pgraster, 0);
458 MemoryContextSwitchTo(oldcontext);
459 elog(ERROR,
"RASTER_dumpValues: Could not pixel (%d, %d) of band %d", x, y, nband);
460 SRF_RETURN_DONE(funcctx);
463 arg1->
values[z][i] = Float8GetDatum(val);
467 if (exclude_nodata_value && isnodata) {
481 PG_FREE_IF_COPY(pgraster, 0);
484 funcctx->user_fctx = arg1;
487 funcctx->max_calls = arg1->
numbands;
490 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
491 MemoryContextSwitchTo(oldcontext);
493 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
495 "function returning record called in context " 496 "that cannot accept type record" 501 BlessTupleDesc(tupdesc);
502 funcctx->tuple_desc = tupdesc;
504 MemoryContextSwitchTo(oldcontext);
508 funcctx = SRF_PERCALL_SETUP();
510 call_cntr = funcctx->call_cntr;
511 max_calls = funcctx->max_calls;
512 tupdesc = funcctx->tuple_desc;
513 arg2 = funcctx->user_fctx;
516 if (call_cntr < max_calls) {
517 int values_length = 2;
518 Datum values[values_length];
519 bool nulls[values_length];
522 ArrayType *mdValues = NULL;
525 int lbound[2] = {1, 1};
530 memset(nulls,
FALSE,
sizeof(
bool) * values_length);
532 values[0] = Int32GetDatum(arg2->
nbands[call_cntr] + 1);
535 get_typlenbyvalalign(FLOAT8OID, &typlen, &typbyval, &typalign);
538 if (arg2->
values[call_cntr] == NULL)
542 mdValues = construct_md_array(
546 typlen, typbyval, typalign
548 values[1] = PointerGetDatum(mdValues);
551 tuple = heap_form_tuple(tupdesc, values, nulls);
552 result = HeapTupleGetDatum(tuple);
554 SRF_RETURN_NEXT(funcctx, result);
559 SRF_RETURN_DONE(funcctx);
uint16_t 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): ...
int rt_raster_is_empty(rt_raster raster)
Return TRUE if the raster is empty.
#define POSTGIS_RT_DEBUGF(level, msg,...)
static void rtpg_dumpvalues_arg_destroy(rtpg_dumpvalues_arg arg)
static rtpg_dumpvalues_arg rtpg_dumpvalues_arg_init()
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
int rt_band_clamped_value_is_nodata(rt_band band, double val)
Compare clamped value to band's clamped NODATA value.
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
int rt_raster_has_band(rt_raster raster, int nband)
Return TRUE if the raster has a band of this number.
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
uint16_t rt_raster_get_width(rt_raster raster)
int rt_band_get_isnodata_flag(rt_band band)
Get isnodata flag value.
uint16_t rt_raster_get_height(rt_raster raster)
#define POSTGIS_RT_DEBUG(level, msg)
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.