PostGIS  2.5.7dev-r@@SVN_REVISION@@

◆ RASTER_addBand()

Datum RASTER_addBand ( PG_FUNCTION_ARGS  )

Definition at line 121 of file rtpg_create.c.

122 {
123  rt_pgraster *pgraster = NULL;
124  rt_pgraster *pgrtn = NULL;
125  rt_raster raster = NULL;
126  int bandindex = 0;
127  int maxbandindex = 0;
128  int numbands = 0;
129  int lastnumbands = 0;
130 
131  text *text_pixtype = NULL;
132  char *char_pixtype = NULL;
133 
134  struct addbandarg {
135  int index;
136  bool append;
137  rt_pixtype pixtype;
138  double initialvalue;
139  bool hasnodata;
140  double nodatavalue;
141  };
142  struct addbandarg *arg = NULL;
143 
144  ArrayType *array;
145  Oid etype;
146  Datum *e;
147  bool *nulls;
148  int16 typlen;
149  bool typbyval;
150  char typalign;
151  int n = 0;
152 
153  HeapTupleHeader tup;
154  bool isnull;
155  Datum tupv;
156 
157  int i = 0;
158 
159  /* pgraster is null, return null */
160  if (PG_ARGISNULL(0))
161  PG_RETURN_NULL();
162  pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
163 
164  /* raster */
165  raster = rt_raster_deserialize(pgraster, FALSE);
166  if (!raster) {
167  PG_FREE_IF_COPY(pgraster, 0);
168  elog(ERROR, "RASTER_addBand: Could not deserialize raster");
169  PG_RETURN_NULL();
170  }
171 
172  /* process set of addbandarg */
173  POSTGIS_RT_DEBUG(3, "Processing Arg 1 (addbandargset)");
174  array = PG_GETARG_ARRAYTYPE_P(1);
175  etype = ARR_ELEMTYPE(array);
176  get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
177 
178  deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
179  &nulls, &n);
180 
181  if (!n) {
182  PG_FREE_IF_COPY(pgraster, 0);
183  elog(ERROR, "RASTER_addBand: Invalid argument for addbandargset");
184  PG_RETURN_NULL();
185  }
186 
187  /* allocate addbandarg */
188  arg = (struct addbandarg *) palloc(sizeof(struct addbandarg) * n);
189  if (arg == NULL) {
191  PG_FREE_IF_COPY(pgraster, 0);
192  elog(ERROR, "RASTER_addBand: Could not allocate memory for addbandarg");
193  PG_RETURN_NULL();
194  }
195 
196  /*
197  process each element of addbandargset
198  each element is the index of where to add the new band,
199  new band's pixeltype, the new band's initial value and
200  the new band's NODATA value if NOT NULL
201  */
202  for (i = 0; i < n; i++) {
203  if (nulls[i]) continue;
204 
205  POSTGIS_RT_DEBUGF(4, "Processing addbandarg at index %d", i);
206 
207  /* each element is a tuple */
208  tup = (HeapTupleHeader) DatumGetPointer(e[i]);
209  if (NULL == tup) {
210  pfree(arg);
212  PG_FREE_IF_COPY(pgraster, 0);
213  elog(ERROR, "RASTER_addBand: Invalid argument for addbandargset");
214  PG_RETURN_NULL();
215  }
216 
217  /* new band index, 1-based */
218  arg[i].index = 0;
219  arg[i].append = TRUE;
220  tupv = GetAttributeByName(tup, "index", &isnull);
221  if (!isnull) {
222  arg[i].index = DatumGetInt32(tupv);
223  arg[i].append = FALSE;
224  }
225 
226  /* for now, only check that band index is 1-based */
227  if (!arg[i].append && arg[i].index < 1) {
228  pfree(arg);
230  PG_FREE_IF_COPY(pgraster, 0);
231  elog(ERROR, "RASTER_addBand: Invalid argument for addbandargset. Invalid band index (must be 1-based) for addbandarg of index %d", i);
232  PG_RETURN_NULL();
233  }
234 
235  /* new band pixeltype */
236  arg[i].pixtype = PT_END;
237  tupv = GetAttributeByName(tup, "pixeltype", &isnull);
238  if (isnull) {
239  pfree(arg);
241  PG_FREE_IF_COPY(pgraster, 0);
242  elog(ERROR, "RASTER_addBand: Invalid argument for addbandargset. Pixel type cannot be NULL for addbandarg of index %d", i);
243  PG_RETURN_NULL();
244  }
245  text_pixtype = (text *) DatumGetPointer(tupv);
246  if (text_pixtype == NULL) {
247  pfree(arg);
249  PG_FREE_IF_COPY(pgraster, 0);
250  elog(ERROR, "RASTER_addBand: Invalid argument for addbandargset. Pixel type cannot be NULL for addbandarg of index %d", i);
251  PG_RETURN_NULL();
252  }
253  char_pixtype = text_to_cstring(text_pixtype);
254 
255  arg[i].pixtype = rt_pixtype_index_from_name(char_pixtype);
256  pfree(char_pixtype);
257  if (arg[i].pixtype == PT_END) {
258  pfree(arg);
260  PG_FREE_IF_COPY(pgraster, 0);
261  elog(ERROR, "RASTER_addBand: Invalid argument for addbandargset. Invalid pixel type for addbandarg of index %d", i);
262  PG_RETURN_NULL();
263  }
264 
265  /* new band initialvalue */
266  arg[i].initialvalue = 0;
267  tupv = GetAttributeByName(tup, "initialvalue", &isnull);
268  if (!isnull)
269  arg[i].initialvalue = DatumGetFloat8(tupv);
270 
271  /* new band NODATA value */
272  arg[i].hasnodata = FALSE;
273  arg[i].nodatavalue = 0;
274  tupv = GetAttributeByName(tup, "nodataval", &isnull);
275  if (!isnull) {
276  arg[i].hasnodata = TRUE;
277  arg[i].nodatavalue = DatumGetFloat8(tupv);
278  }
279  }
280 
281  /* add new bands to raster */
282  lastnumbands = rt_raster_get_num_bands(raster);
283  for (i = 0; i < n; i++) {
284  if (nulls[i]) continue;
285 
286  POSTGIS_RT_DEBUGF(3, "%d bands in old raster", lastnumbands);
287  maxbandindex = lastnumbands + 1;
288 
289  /* check that new band's index doesn't exceed maxbandindex */
290  if (!arg[i].append) {
291  if (arg[i].index > maxbandindex) {
292  elog(NOTICE, "Band index for addbandarg of index %d exceeds possible value. Adding band at index %d", i, maxbandindex);
293  arg[i].index = maxbandindex;
294  }
295  }
296  /* append, so use maxbandindex */
297  else
298  arg[i].index = maxbandindex;
299 
300  POSTGIS_RT_DEBUGF(4, "new band (index, pixtype, initialvalue, hasnodata, nodatavalue) = (%d, %s, %f, %s, %f)",
301  arg[i].index,
302  rt_pixtype_name(arg[i].pixtype),
303  arg[i].initialvalue,
304  arg[i].hasnodata ? "TRUE" : "FALSE",
305  arg[i].nodatavalue
306  );
307 
308  bandindex = rt_raster_generate_new_band(
309  raster,
310  arg[i].pixtype, arg[i].initialvalue,
311  arg[i].hasnodata, arg[i].nodatavalue,
312  arg[i].index - 1
313  );
314 
315  numbands = rt_raster_get_num_bands(raster);
316  if (numbands == lastnumbands || bandindex == -1) {
317  pfree(arg);
319  PG_FREE_IF_COPY(pgraster, 0);
320  elog(ERROR, "RASTER_addBand: Could not add band defined by addbandarg of index %d to raster", i);
321  PG_RETURN_NULL();
322  }
323 
324  lastnumbands = numbands;
325  POSTGIS_RT_DEBUGF(3, "%d bands in new raster", lastnumbands);
326  }
327 
328  pfree(arg);
329 
330  pgrtn = rt_raster_serialize(raster);
332  PG_FREE_IF_COPY(pgraster, 0);
333  if (!pgrtn)
334  PG_RETURN_NULL();
335 
336  SET_VARSIZE(pgrtn, pgrtn->size);
337  PG_RETURN_POINTER(pgrtn);
338 }
#define TRUE
Definition: dbfopen.c:169
#define FALSE
Definition: dbfopen.c:168
int rt_raster_generate_new_band(rt_raster raster, rt_pixtype pixtype, double initialvalue, uint32_t hasnodata, double nodatavalue, int index)
Generate a new inline band and add it to a raster.
Definition: rt_raster.c:485
rt_pixtype rt_pixtype_index_from_name(const char *pixname)
Definition: rt_pixel.c:80
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
Definition: rt_raster.c:82
rt_pixtype
Definition: librtcore.h:185
@ PT_END
Definition: librtcore.h:197
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
Definition: rt_serialize.c:521
uint16_t rt_raster_get_num_bands(rt_raster raster)
Definition: rt_raster.c:372
const char * rt_pixtype_name(rt_pixtype pixtype)
Definition: rt_pixel.c:110
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
Definition: rt_serialize.c:725
raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
Definition: rtrowdump.py:121
char * text_to_cstring(const text *textptr)
#define POSTGIS_RT_DEBUG(level, msg)
Definition: rtpostgis.h:61
#define POSTGIS_RT_DEBUGF(level, msg,...)
Definition: rtpostgis.h:65
Struct definitions.
Definition: librtcore.h:2250

References FALSE, POSTGIS_RT_DEBUG, POSTGIS_RT_DEBUGF, PT_END, rtrowdump::raster, rt_pixtype_index_from_name(), rt_pixtype_name(), rt_raster_deserialize(), rt_raster_destroy(), rt_raster_generate_new_band(), rt_raster_get_num_bands(), rt_raster_serialize(), rt_raster_serialized_t::size, text_to_cstring(), and TRUE.

Here is the call graph for this function: