PostGIS  2.4.9dev-r@@SVN_REVISION@@
rtpg_band_properties.c
Go to the documentation of this file.
1 /*
2  *
3  * WKTRaster - Raster Types for PostGIS
4  * http://trac.osgeo.org/postgis/wiki/WKTRaster
5  *
6  * Copyright (C) 2011-2013 Regents of the University of California
7  * <bkpark@ucdavis.edu>
8  * Copyright (C) 2010-2011 Jorge Arevalo <jorge.arevalo@deimos-space.com>
9  * Copyright (C) 2010-2011 David Zwarg <dzwarg@azavea.com>
10  * Copyright (C) 2009-2011 Pierre Racine <pierre.racine@sbf.ulaval.ca>
11  * Copyright (C) 2009-2011 Mateusz Loskot <mateusz@loskot.net>
12  * Copyright (C) 2008-2009 Sandro Santilli <strk@kbt.io>
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software Foundation,
26  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27  *
28  */
29 
30 #include <postgres.h>
31 #include <fmgr.h>
32 #include <funcapi.h>
33 #include <utils/builtins.h>
34 #include "utils/lsyscache.h" /* for get_typlenbyvalalign */
35 #include "utils/array.h" /* for ArrayType */
36 #include "catalog/pg_type.h" /* for INT2OID, INT4OID, FLOAT4OID, FLOAT8OID and TEXTOID */
37 
38 #include "../../postgis_config.h"
39 
40 
41 #include "access/htup_details.h" /* for heap_form_tuple() */
42 
43 
44 #include "rtpostgis.h"
45 
46 /* Get all the properties of a raster band */
47 Datum RASTER_getBandPixelType(PG_FUNCTION_ARGS);
48 Datum RASTER_getBandPixelTypeName(PG_FUNCTION_ARGS);
49 Datum RASTER_getBandNoDataValue(PG_FUNCTION_ARGS);
50 Datum RASTER_getBandPath(PG_FUNCTION_ARGS);
51 Datum RASTER_bandIsNoData(PG_FUNCTION_ARGS);
52 
53 /* get raster band's meta data */
54 Datum RASTER_bandmetadata(PG_FUNCTION_ARGS);
55 
56 /* Set all the properties of a raster band */
57 Datum RASTER_setBandIsNoData(PG_FUNCTION_ARGS);
58 Datum RASTER_setBandNoDataValue(PG_FUNCTION_ARGS);
59 
65 Datum RASTER_getBandPixelType(PG_FUNCTION_ARGS)
66 {
67  rt_pgraster *pgraster = NULL;
68  rt_raster raster = NULL;
69  rt_band band = NULL;
70  rt_pixtype pixtype;
71  int32_t bandindex;
72 
73  /* Deserialize raster */
74  if (PG_ARGISNULL(0)) PG_RETURN_NULL();
75  pgraster = (rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
76 
77  /* Index is 1-based */
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);
82  PG_RETURN_NULL();
83  }
84 
85  raster = rt_raster_deserialize(pgraster, FALSE);
86  if ( ! raster ) {
87  PG_FREE_IF_COPY(pgraster, 0);
88  elog(ERROR, "RASTER_getBandPixelType: Could not deserialize raster");
89  PG_RETURN_NULL();
90  }
91 
92  /* Fetch requested band and its pixel type */
93  band = rt_raster_get_band(raster, bandindex - 1);
94  if ( ! band ) {
95  elog(NOTICE, "Could not find raster band of index %d when getting pixel type. Returning NULL", bandindex);
96  rt_raster_destroy(raster);
97  PG_FREE_IF_COPY(pgraster, 0);
98  PG_RETURN_NULL();
99  }
100 
101  pixtype = rt_band_get_pixtype(band);
102 
103  rt_raster_destroy(raster);
104  PG_FREE_IF_COPY(pgraster, 0);
105 
106  PG_RETURN_INT32(pixtype);
107 }
108 
115 Datum RASTER_getBandPixelTypeName(PG_FUNCTION_ARGS)
116 {
117  rt_pgraster *pgraster = NULL;
118  rt_raster raster = NULL;
119  rt_band band = NULL;
120  rt_pixtype pixtype;
121  int32_t bandindex;
122  const size_t name_size = 8; /* size of type name */
123  size_t size = 0;
124  char *ptr = NULL;
125  text *result = NULL;
126 
127  /* Deserialize raster */
128  if (PG_ARGISNULL(0)) PG_RETURN_NULL();
129  pgraster = (rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
130 
131  /* Index is 1-based */
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);
136  PG_RETURN_NULL();
137  }
138 
139  raster = rt_raster_deserialize(pgraster, FALSE);
140  if ( ! raster ) {
141  PG_FREE_IF_COPY(pgraster, 0);
142  elog(ERROR, "RASTER_getBandPixelTypeName: Could not deserialize raster");
143  PG_RETURN_NULL();
144  }
145 
146  /* Fetch requested band and its pixel type */
147  band = rt_raster_get_band(raster, bandindex - 1);
148  if ( ! band ) {
149  elog(NOTICE, "Could not find raster band of index %d when getting pixel type name. Returning NULL", bandindex);
150  rt_raster_destroy(raster);
151  PG_FREE_IF_COPY(pgraster, 0);
152  PG_RETURN_NULL();
153  }
154 
155  pixtype = rt_band_get_pixtype(band);
156 
157  result = palloc(VARHDRSZ + name_size);
158  /* We don't need to check for NULL pointer, because if out of memory, palloc
159  * exit via elog(ERROR). It never returns NULL.
160  */
161 
162  memset(VARDATA(result), 0, name_size);
163  ptr = (char *)result + VARHDRSZ;
164  strcpy(ptr, rt_pixtype_name(pixtype));
165 
166  size = VARHDRSZ + strlen(ptr);
167  SET_VARSIZE(result, size);
168 
169  rt_raster_destroy(raster);
170  PG_FREE_IF_COPY(pgraster, 0);
171 
172  PG_RETURN_TEXT_P(result);
173 }
174 
180 Datum RASTER_getBandNoDataValue(PG_FUNCTION_ARGS)
181 {
182  rt_pgraster *pgraster = NULL;
183  rt_raster raster = NULL;
184  rt_band band = NULL;
185  int32_t bandindex;
186  double nodata;
187 
188  /* Deserialize raster */
189  if (PG_ARGISNULL(0)) PG_RETURN_NULL();
190  pgraster = (rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
191 
192  /* Index is 1-based */
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);
197  PG_RETURN_NULL();
198  }
199 
200  raster = rt_raster_deserialize(pgraster, FALSE);
201  if ( ! raster ) {
202  PG_FREE_IF_COPY(pgraster, 0);
203  elog(ERROR, "RASTER_getBandNoDataValue: Could not deserialize raster");
204  PG_RETURN_NULL();
205  }
206 
207  /* Fetch requested band and its nodata value */
208  band = rt_raster_get_band(raster, bandindex - 1);
209  if ( ! band ) {
210  elog(NOTICE, "Could not find raster band of index %d when getting band nodata value. Returning NULL", bandindex);
211  rt_raster_destroy(raster);
212  PG_FREE_IF_COPY(pgraster, 0);
213  PG_RETURN_NULL();
214  }
215 
216  if ( ! rt_band_get_hasnodata_flag(band) ) {
217  /* Raster does not have a nodata value set so we return NULL */
218  rt_raster_destroy(raster);
219  PG_FREE_IF_COPY(pgraster, 0);
220  PG_RETURN_NULL();
221  }
222 
223  rt_band_get_nodata(band, &nodata);
224 
225  rt_raster_destroy(raster);
226  PG_FREE_IF_COPY(pgraster, 0);
227 
228  PG_RETURN_FLOAT8(nodata);
229 }
230 
231 
233 Datum RASTER_bandIsNoData(PG_FUNCTION_ARGS)
234 {
235  rt_pgraster *pgraster = NULL;
236  rt_raster raster = NULL;
237  rt_band band = NULL;
238  int32_t bandindex;
239  bool forcechecking = FALSE;
240  bool bandisnodata = FALSE;
241 
242  /* Index is 1-based */
243  bandindex = PG_GETARG_INT32(1);
244  if ( bandindex < 1 ) {
245  elog(NOTICE, "Invalid band index (must use 1-based). Returning NULL");
246  PG_RETURN_NULL();
247  }
248 
249  /* Deserialize raster */
250  if (PG_ARGISNULL(0)) PG_RETURN_NULL();
251  pgraster = (rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
252 
253  raster = rt_raster_deserialize(pgraster, FALSE);
254  if ( ! raster ) {
255  PG_FREE_IF_COPY(pgraster, 0);
256  elog(ERROR, "RASTER_bandIsNoData: Could not deserialize raster");
257  PG_RETURN_NULL();
258  }
259 
260  /* Fetch requested band and its nodata value */
261  band = rt_raster_get_band(raster, bandindex - 1);
262  if ( ! band ) {
263  elog(NOTICE, "Could not find raster band of index %d when determining if band is nodata. Returning NULL", bandindex);
264  rt_raster_destroy(raster);
265  PG_FREE_IF_COPY(pgraster, 0);
266  PG_RETURN_NULL();
267  }
268 
269  forcechecking = PG_GETARG_BOOL(2);
270 
271  bandisnodata = (forcechecking) ?
273 
274  rt_raster_destroy(raster);
275  PG_FREE_IF_COPY(pgraster, 0);
276 
277  PG_RETURN_BOOL(bandisnodata);
278 }
279 
284 Datum RASTER_getBandPath(PG_FUNCTION_ARGS)
285 {
286  rt_pgraster *pgraster = NULL;
287  rt_raster raster = NULL;
288  rt_band band = NULL;
289  int32_t bandindex;
290  const char *bandpath;
291  text *result;
292 
293  /* Index is 1-based */
294  bandindex = PG_GETARG_INT32(1);
295  if ( bandindex < 1 ) {
296  elog(NOTICE, "Invalid band index (must use 1-based). Returning NULL");
297  PG_RETURN_NULL();
298  }
299 
300  /* Deserialize raster */
301  if (PG_ARGISNULL(0)) PG_RETURN_NULL();
302  pgraster = (rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
303 
304  raster = rt_raster_deserialize(pgraster, FALSE);
305  if (!raster) {
306  PG_FREE_IF_COPY(pgraster, 0);
307  elog(ERROR, "RASTER_getBandPath: Could not deserialize raster");
308  PG_RETURN_NULL();
309  }
310 
311  /* Fetch requested band */
312  band = rt_raster_get_band(raster, bandindex - 1);
313  if (!band) {
314  elog(
315  NOTICE,
316  "Could not find raster band of index %d when getting band path. Returning NULL",
317  bandindex
318  );
319  rt_raster_destroy(raster);
320  PG_FREE_IF_COPY(pgraster, 0);
321  PG_RETURN_NULL();
322  }
323 
324  bandpath = rt_band_get_ext_path(band);
325  if (!bandpath) {
326  rt_band_destroy(band);
327  rt_raster_destroy(raster);
328  PG_FREE_IF_COPY(pgraster, 0);
329  PG_RETURN_NULL();
330  }
331 
332  result = (text *) palloc(VARHDRSZ + strlen(bandpath) + 1);
333  SET_VARSIZE(result, VARHDRSZ + strlen(bandpath) + 1);
334  strcpy((char *) VARDATA(result), bandpath);
335 
336  rt_band_destroy(band);
337  rt_raster_destroy(raster);
338  PG_FREE_IF_COPY(pgraster, 0);
339 
340  PG_RETURN_TEXT_P(result);
341 }
342 
343 #define VALUES_LENGTH 8
344 
349 Datum RASTER_bandmetadata(PG_FUNCTION_ARGS)
350 {
351  FuncCallContext *funcctx;
352  TupleDesc tupdesc;
353  int call_cntr;
354  int max_calls;
355 
356  struct bandmetadata {
357  uint32_t bandnum;
358  char *pixeltype;
359  bool hasnodata;
360  double nodataval;
361  bool isoutdb;
362  char *bandpath;
363  };
364  struct bandmetadata *bmd = NULL;
365  struct bandmetadata *bmd2 = NULL;
366 
367  HeapTuple tuple;
368  Datum result;
369 
370  if (SRF_IS_FIRSTCALL()) {
371  MemoryContext oldcontext;
372 
373  rt_pgraster *pgraster = NULL;
374  rt_raster raster = NULL;
375  rt_band band = NULL;
376 
377  ArrayType *array;
378  Oid etype;
379  Datum *e;
380  bool *nulls;
381  int16 typlen;
382  bool typbyval;
383  char typalign;
384  int i = 0;
385  int j = 0;
386  int n = 0;
387 
388  uint32_t numBands;
389  uint32_t idx = 1;
390  uint32_t *bandNums = NULL;
391  const char *tmp = NULL;
392 
393  POSTGIS_RT_DEBUG(3, "RASTER_bandmetadata: Starting");
394 
395  /* create a function context for cross-call persistence */
396  funcctx = SRF_FIRSTCALL_INIT();
397 
398  /* switch to memory context appropriate for multiple function calls */
399  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
400 
401  /* pgraster is null, return null */
402  if (PG_ARGISNULL(0)) {
403  MemoryContextSwitchTo(oldcontext);
404  SRF_RETURN_DONE(funcctx);
405  }
406  pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
407 
408  /* raster */
409  raster = rt_raster_deserialize(pgraster, FALSE);
410  if (!raster) {
411  PG_FREE_IF_COPY(pgraster, 0);
412  MemoryContextSwitchTo(oldcontext);
413  elog(ERROR, "RASTER_bandmetadata: Could not deserialize raster");
414  SRF_RETURN_DONE(funcctx);
415  }
416 
417  /* numbands */
418  numBands = rt_raster_get_num_bands(raster);
419  if (numBands < 1) {
420  elog(NOTICE, "Raster provided has no bands");
421  rt_raster_destroy(raster);
422  PG_FREE_IF_COPY(pgraster, 0);
423  MemoryContextSwitchTo(oldcontext);
424  SRF_RETURN_DONE(funcctx);
425  }
426 
427  /* band index */
428  array = PG_GETARG_ARRAYTYPE_P(1);
429  etype = ARR_ELEMTYPE(array);
430  get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
431 
432  switch (etype) {
433  case INT2OID:
434  case INT4OID:
435  break;
436  default:
437  rt_raster_destroy(raster);
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);
442  break;
443  }
444 
445  deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
446  &nulls, &n);
447 
448  bandNums = palloc(sizeof(uint32_t) * n);
449  for (i = 0, j = 0; i < n; i++) {
450  if (nulls[i]) continue;
451 
452  switch (etype) {
453  case INT2OID:
454  idx = (uint32_t) DatumGetInt16(e[i]);
455  break;
456  case INT4OID:
457  idx = (uint32_t) DatumGetInt32(e[i]);
458  break;
459  }
460 
461  POSTGIS_RT_DEBUGF(3, "band idx (before): %d", idx);
462  if (idx > numBands || idx < 1) {
463  elog(NOTICE, "Invalid band index: %d. Indices must be 1-based. Returning NULL", idx);
464  pfree(bandNums);
465  rt_raster_destroy(raster);
466  PG_FREE_IF_COPY(pgraster, 0);
467  MemoryContextSwitchTo(oldcontext);
468  SRF_RETURN_DONE(funcctx);
469  }
470 
471  bandNums[j] = idx;
472  POSTGIS_RT_DEBUGF(3, "bandNums[%d] = %d", j, bandNums[j]);
473  j++;
474  }
475 
476  if (j < 1) {
477  j = numBands;
478  bandNums = repalloc(bandNums, sizeof(uint32_t) * j);
479  for (i = 0; i < j; i++)
480  bandNums[i] = i + 1;
481  }
482  else if (j < n)
483  bandNums = repalloc(bandNums, sizeof(uint32_t) * j);
484 
485  bmd = (struct bandmetadata *) palloc(sizeof(struct bandmetadata) * j);
486 
487  for (i = 0; i < j; i++) {
488  band = rt_raster_get_band(raster, bandNums[i] - 1);
489  if (NULL == band) {
490  elog(NOTICE, "Could not get raster band at index %d", bandNums[i]);
491  rt_raster_destroy(raster);
492  PG_FREE_IF_COPY(pgraster, 0);
493  MemoryContextSwitchTo(oldcontext);
494  SRF_RETURN_DONE(funcctx);
495  }
496 
497  /* bandnum */
498  bmd[i].bandnum = bandNums[i];
499 
500  /* pixeltype */
502  bmd[i].pixeltype = palloc(sizeof(char) * (strlen(tmp) + 1));
503  strncpy(bmd[i].pixeltype, tmp, strlen(tmp) + 1);
504 
505  /* hasnodatavalue */
506  if (rt_band_get_hasnodata_flag(band))
507  bmd[i].hasnodata = TRUE;
508  else
509  bmd[i].hasnodata = FALSE;
510 
511  /* nodatavalue */
512  if (bmd[i].hasnodata)
513  rt_band_get_nodata(band, &(bmd[i].nodataval));
514  else
515  bmd[i].nodataval = 0;
516 
517  /* path */
518  tmp = rt_band_get_ext_path(band);
519  if (tmp) {
520  bmd[i].bandpath = palloc(sizeof(char) * (strlen(tmp) + 1));
521  strncpy(bmd[i].bandpath, tmp, strlen(tmp) + 1);
522  }
523  else
524  bmd[i].bandpath = NULL;
525 
526  /* isoutdb */
527  bmd[i].isoutdb = bmd[i].bandpath ? TRUE : FALSE;
528 
529  rt_band_destroy(band);
530  }
531 
532  rt_raster_destroy(raster);
533  PG_FREE_IF_COPY(pgraster, 0);
534 
535  /* Store needed information */
536  funcctx->user_fctx = bmd;
537 
538  /* total number of tuples to be returned */
539  funcctx->max_calls = j;
540 
541  /* Build a tuple descriptor for our result type */
542  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
543  MemoryContextSwitchTo(oldcontext);
544  ereport(ERROR, (
545  errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
546  errmsg(
547  "function returning record called in context "
548  "that cannot accept type record"
549  )
550  ));
551  }
552 
553  BlessTupleDesc(tupdesc);
554  funcctx->tuple_desc = tupdesc;
555 
556  MemoryContextSwitchTo(oldcontext);
557  }
558 
559  /* stuff done on every call of the function */
560  funcctx = SRF_PERCALL_SETUP();
561 
562  call_cntr = funcctx->call_cntr;
563  max_calls = funcctx->max_calls;
564  tupdesc = funcctx->tuple_desc;
565  bmd2 = funcctx->user_fctx;
566 
567  /* do when there is more left to send */
568  if (call_cntr < max_calls) {
569  Datum values[VALUES_LENGTH];
570  bool nulls[VALUES_LENGTH];
571 
572  memset(nulls, FALSE, sizeof(bool) * VALUES_LENGTH);
573 
574  values[0] = UInt32GetDatum(bmd2[call_cntr].bandnum);
575  values[1] = CStringGetTextDatum(bmd2[call_cntr].pixeltype);
576 
577  if (bmd2[call_cntr].hasnodata)
578  values[2] = Float8GetDatum(bmd2[call_cntr].nodataval);
579  else
580  nulls[2] = TRUE;
581 
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);
585  else
586  nulls[4] = TRUE;
587 
588  /* build a tuple */
589  tuple = heap_form_tuple(tupdesc, values, nulls);
590 
591  /* make the tuple into a datum */
592  result = HeapTupleGetDatum(tuple);
593 
594  /* clean up */
595  pfree(bmd2[call_cntr].pixeltype);
596  if (bmd2[call_cntr].bandpath) pfree(bmd2[call_cntr].bandpath);
597 
598  SRF_RETURN_NEXT(funcctx, result);
599  }
600  /* do when there is no more left */
601  else {
602  pfree(bmd2);
603  SRF_RETURN_DONE(funcctx);
604  }
605 }
606 
611 Datum RASTER_setBandNoDataValue(PG_FUNCTION_ARGS)
612 {
613  rt_pgraster *pgraster = NULL;
614  rt_pgraster *pgrtn = NULL;
615  rt_raster raster = NULL;
616  rt_band band = NULL;
617  double nodata;
618  int32_t bandindex;
619  bool forcechecking = FALSE;
620  bool skipset = FALSE;
621 
622  /* Deserialize raster */
623  if (PG_ARGISNULL(0))
624  PG_RETURN_NULL();
625  pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
626 
627  /* Check index is not NULL or smaller than 1 */
628  if (PG_ARGISNULL(1))
629  bandindex = -1;
630  else
631  bandindex = PG_GETARG_INT32(1);
632  if (bandindex < 1) {
633  elog(NOTICE, "Invalid band index (must use 1-based). Nodata value not set. Returning original raster");
634  skipset = TRUE;
635  }
636 
637  raster = rt_raster_deserialize(pgraster, FALSE);
638  if (!raster) {
639  PG_FREE_IF_COPY(pgraster, 0);
640  elog(ERROR, "RASTER_setBandNoDataValue: Could not deserialize raster");
641  PG_RETURN_NULL();
642  }
643 
644  if (!skipset) {
645  /* Fetch requested band */
646  band = rt_raster_get_band(raster, bandindex - 1);
647  if (!band) {
648  elog(NOTICE, "Could not find raster band of index %d when setting pixel value. Nodata value not set. Returning original raster", bandindex);
649  }
650  else {
651  if (!PG_ARGISNULL(3))
652  forcechecking = PG_GETARG_BOOL(3);
653 
654  if (PG_ARGISNULL(2)) {
655  /* Set the hasnodata flag to FALSE */
657  POSTGIS_RT_DEBUGF(3, "Raster band %d does not have a nodata value", bandindex);
658  }
659  else {
660  /* Get the nodata value */
661  nodata = PG_GETARG_FLOAT8(2);
662 
663  /* Set the band's nodata value */
664  rt_band_set_nodata(band, nodata, NULL);
665 
666  /* Recheck all pixels if requested */
667  if (forcechecking)
669  }
670  }
671  }
672 
673  pgrtn = rt_raster_serialize(raster);
674  rt_raster_destroy(raster);
675  PG_FREE_IF_COPY(pgraster, 0);
676  if (!pgrtn)
677  PG_RETURN_NULL();
678 
679  SET_VARSIZE(pgrtn, pgrtn->size);
680  PG_RETURN_POINTER(pgrtn);
681 }
682 
684 Datum RASTER_setBandIsNoData(PG_FUNCTION_ARGS)
685 {
686  rt_pgraster *pgraster = NULL;
687  rt_pgraster *pgrtn = NULL;
688  rt_raster raster = NULL;
689  rt_band band = NULL;
690  int32_t bandindex;
691 
692  if (PG_ARGISNULL(0))
693  PG_RETURN_NULL();
694  pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
695 
696  raster = rt_raster_deserialize(pgraster, FALSE);
697  if (!raster) {
698  PG_FREE_IF_COPY(pgraster, 0);
699  elog(ERROR, "RASTER_setBandIsNoData: Could not deserialize raster");
700  PG_RETURN_NULL();
701  }
702 
703  /* Check index is not NULL or smaller than 1 */
704  if (PG_ARGISNULL(1))
705  bandindex = -1;
706  else
707  bandindex = PG_GETARG_INT32(1);
708 
709  if (bandindex < 1)
710  elog(NOTICE, "Invalid band index (must use 1-based). Isnodata flag not set. Returning original raster");
711  else {
712  /* Fetch requested band */
713  band = rt_raster_get_band(raster, bandindex - 1);
714 
715  if (!band)
716  elog(NOTICE, "Could not find raster band of index %d. Isnodata flag not set. Returning original raster", bandindex);
717  else {
718  if (!rt_band_get_hasnodata_flag(band)) {
719  elog(NOTICE, "Band of index %d has no NODATA so cannot be NODATA. Returning original raster", bandindex);
720  }
721  /* Set the band's nodata value */
722  else {
723  rt_band_set_isnodata_flag(band, 1);
724  }
725  }
726  }
727 
728  /* Serialize raster again */
729  pgrtn = rt_raster_serialize(raster);
730  rt_raster_destroy(raster);
731  PG_FREE_IF_COPY(pgraster, 0);
732  if (!pgrtn) PG_RETURN_NULL();
733 
734  SET_VARSIZE(pgrtn, pgrtn->size);
735  PG_RETURN_POINTER(pgrtn);
736 }
737 
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.
Definition: rt_serialize.c:521
int rt_raster_get_num_bands(rt_raster raster)
Definition: rt_raster.c:372
raster
Be careful!! Zeros function&#39;s input parameter can be a (height x width) array, not (width x height): ...
Definition: rtrowdump.py:121
band
Definition: ovdump.py:57
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.
Definition: rt_band.c:600
Datum RASTER_getBandNoDataValue(PG_FUNCTION_ARGS)
rt_pixtype
Definition: librtcore.h:185
void rt_band_destroy(rt_band band)
Destroy a raster band.
Definition: rt_band.c:242
#define POSTGIS_RT_DEBUGF(level, msg,...)
Definition: rtpostgis.h:65
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
Definition: rt_band.c:1597
const char * rt_band_get_ext_path(rt_band band)
Return band&#39;s external path (only valid when rt_band_is_offline returns non-zero).
Definition: rt_band.c:265
unsigned int uint32_t
Definition: uthash.h:78
Datum RASTER_getBandPixelType(PG_FUNCTION_ARGS)
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
Definition: rt_raster.c:381
int rt_band_check_is_nodata(rt_band band)
Returns TRUE if the band is only nodata values.
Definition: rt_band.c:1619
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
Definition: rt_band.c:541
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
Definition: rt_raster.c:82
void rt_band_set_hasnodata_flag(rt_band band, int flag)
Set hasnodata flag value.
Definition: rt_band.c:548
#define VALUES_LENGTH
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.
Definition: rt_band.c:562
#define FALSE
Definition: dbfopen.c:168
Struct definitions.
Definition: librtcore.h:2201
const char * rt_pixtype_name(rt_pixtype pixtype)
Definition: rt_pixel.c:110
rt_pixtype rt_band_get_pixtype(rt_band band)
Return pixeltype of this band.
Definition: rt_band.c:498
int rt_band_get_isnodata_flag(rt_band band)
Get isnodata flag value.
Definition: rt_band.c:581
Datum RASTER_setBandIsNoData(PG_FUNCTION_ARGS)
Datum RASTER_bandIsNoData(PG_FUNCTION_ARGS)
#define POSTGIS_RT_DEBUG(level, msg)
Definition: rtpostgis.h:61
#define TRUE
Definition: dbfopen.c:169
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
Definition: rt_serialize.c:717