PostGIS  2.1.10dev-r@@SVN_REVISION@@
Datum RASTER_addBand ( PG_FUNCTION_ARGS  )

Definition at line 5328 of file rt_pg.c.

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, and TRUE.

5329 {
5330  rt_pgraster *pgraster = NULL;
5331  rt_pgraster *pgrtn = NULL;
5332  rt_raster raster = NULL;
5333  int bandindex = 0;
5334  int maxbandindex = 0;
5335  int numbands = 0;
5336  int lastnumbands = 0;
5337 
5338  text *text_pixtype = NULL;
5339  char *char_pixtype = NULL;
5340 
5341  struct addbandarg {
5342  int index;
5343  bool append;
5344  rt_pixtype pixtype;
5345  double initialvalue;
5346  bool hasnodata;
5347  double nodatavalue;
5348  };
5349  struct addbandarg *arg = NULL;
5350 
5351  ArrayType *array;
5352  Oid etype;
5353  Datum *e;
5354  bool *nulls;
5355  int16 typlen;
5356  bool typbyval;
5357  char typalign;
5358  int n = 0;
5359 
5360  HeapTupleHeader tup;
5361  bool isnull;
5362  Datum tupv;
5363 
5364  int i = 0;
5365 
5366  /* pgraster is null, return null */
5367  if (PG_ARGISNULL(0))
5368  PG_RETURN_NULL();
5369  pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
5370 
5371  /* raster */
5372  raster = rt_raster_deserialize(pgraster, FALSE);
5373  if (!raster) {
5374  PG_FREE_IF_COPY(pgraster, 0);
5375  elog(ERROR, "RASTER_addBand: Could not deserialize raster");
5376  PG_RETURN_NULL();
5377  }
5378 
5379  /* process set of addbandarg */
5380  POSTGIS_RT_DEBUG(3, "Processing Arg 1 (addbandargset)");
5381  array = PG_GETARG_ARRAYTYPE_P(1);
5382  etype = ARR_ELEMTYPE(array);
5383  get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
5384 
5385  deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
5386  &nulls, &n);
5387 
5388  if (!n) {
5389  PG_FREE_IF_COPY(pgraster, 0);
5390  elog(ERROR, "RASTER_addBand: Invalid argument for addbandargset");
5391  PG_RETURN_NULL();
5392  }
5393 
5394  /* allocate addbandarg */
5395  arg = (struct addbandarg *) palloc(sizeof(struct addbandarg) * n);
5396  if (arg == NULL) {
5397  rt_raster_destroy(raster);
5398  PG_FREE_IF_COPY(pgraster, 0);
5399  elog(ERROR, "RASTER_addBand: Could not allocate memory for addbandarg");
5400  PG_RETURN_NULL();
5401  }
5402 
5403  /*
5404  process each element of addbandargset
5405  each element is the index of where to add the new band,
5406  new band's pixeltype, the new band's initial value and
5407  the new band's NODATA value if NOT NULL
5408  */
5409  for (i = 0; i < n; i++) {
5410  if (nulls[i]) continue;
5411 
5412  POSTGIS_RT_DEBUGF(4, "Processing addbandarg at index %d", i);
5413 
5414  /* each element is a tuple */
5415  tup = (HeapTupleHeader) DatumGetPointer(e[i]);
5416  if (NULL == tup) {
5417  pfree(arg);
5418  rt_raster_destroy(raster);
5419  PG_FREE_IF_COPY(pgraster, 0);
5420  elog(ERROR, "RASTER_addBand: Invalid argument for addbandargset");
5421  PG_RETURN_NULL();
5422  }
5423 
5424  /* new band index, 1-based */
5425  arg[i].index = 0;
5426  arg[i].append = TRUE;
5427  tupv = GetAttributeByName(tup, "index", &isnull);
5428  if (!isnull) {
5429  arg[i].index = DatumGetInt32(tupv);
5430  arg[i].append = FALSE;
5431  }
5432 
5433  /* for now, only check that band index is 1-based */
5434  if (!arg[i].append && arg[i].index < 1) {
5435  pfree(arg);
5436  rt_raster_destroy(raster);
5437  PG_FREE_IF_COPY(pgraster, 0);
5438  elog(ERROR, "RASTER_addBand: Invalid argument for addbandargset. Invalid band index (must be 1-based) for addbandarg of index %d", i);
5439  PG_RETURN_NULL();
5440  }
5441 
5442  /* new band pixeltype */
5443  arg[i].pixtype = PT_END;
5444  tupv = GetAttributeByName(tup, "pixeltype", &isnull);
5445  if (isnull) {
5446  pfree(arg);
5447  rt_raster_destroy(raster);
5448  PG_FREE_IF_COPY(pgraster, 0);
5449  elog(ERROR, "RASTER_addBand: Invalid argument for addbandargset. Pixel type cannot be NULL for addbandarg of index %d", i);
5450  PG_RETURN_NULL();
5451  }
5452  text_pixtype = (text *) DatumGetPointer(tupv);
5453  if (text_pixtype == NULL) {
5454  pfree(arg);
5455  rt_raster_destroy(raster);
5456  PG_FREE_IF_COPY(pgraster, 0);
5457  elog(ERROR, "RASTER_addBand: Invalid argument for addbandargset. Pixel type cannot be NULL for addbandarg of index %d", i);
5458  PG_RETURN_NULL();
5459  }
5460  char_pixtype = text_to_cstring(text_pixtype);
5461 
5462  arg[i].pixtype = rt_pixtype_index_from_name(char_pixtype);
5463  pfree(char_pixtype);
5464  if (arg[i].pixtype == PT_END) {
5465  pfree(arg);
5466  rt_raster_destroy(raster);
5467  PG_FREE_IF_COPY(pgraster, 0);
5468  elog(ERROR, "RASTER_addBand: Invalid argument for addbandargset. Invalid pixel type for addbandarg of index %d", i);
5469  PG_RETURN_NULL();
5470  }
5471 
5472  /* new band initialvalue */
5473  arg[i].initialvalue = 0;
5474  tupv = GetAttributeByName(tup, "initialvalue", &isnull);
5475  if (!isnull)
5476  arg[i].initialvalue = DatumGetFloat8(tupv);
5477 
5478  /* new band NODATA value */
5479  arg[i].hasnodata = FALSE;
5480  arg[i].nodatavalue = 0;
5481  tupv = GetAttributeByName(tup, "nodataval", &isnull);
5482  if (!isnull) {
5483  arg[i].hasnodata = TRUE;
5484  arg[i].nodatavalue = DatumGetFloat8(tupv);
5485  }
5486  }
5487 
5488  /* add new bands to raster */
5489  lastnumbands = rt_raster_get_num_bands(raster);
5490  for (i = 0; i < n; i++) {
5491  if (nulls[i]) continue;
5492 
5493  POSTGIS_RT_DEBUGF(3, "%d bands in old raster", lastnumbands);
5494  maxbandindex = lastnumbands + 1;
5495 
5496  /* check that new band's index doesn't exceed maxbandindex */
5497  if (!arg[i].append) {
5498  if (arg[i].index > maxbandindex) {
5499  elog(NOTICE, "Band index for addbandarg of index %d exceeds possible value. Adding band at index %d", i, maxbandindex);
5500  arg[i].index = maxbandindex;
5501  }
5502  }
5503  /* append, so use maxbandindex */
5504  else
5505  arg[i].index = maxbandindex;
5506 
5507  POSTGIS_RT_DEBUGF(4, "new band (index, pixtype, initialvalue, hasnodata, nodatavalue) = (%d, %s, %f, %s, %f)",
5508  arg[i].index,
5509  rt_pixtype_name(arg[i].pixtype),
5510  arg[i].initialvalue,
5511  arg[i].hasnodata ? "TRUE" : "FALSE",
5512  arg[i].nodatavalue
5513  );
5514 
5515  bandindex = rt_raster_generate_new_band(
5516  raster,
5517  arg[i].pixtype, arg[i].initialvalue,
5518  arg[i].hasnodata, arg[i].nodatavalue,
5519  arg[i].index - 1
5520  );
5521 
5522  numbands = rt_raster_get_num_bands(raster);
5523  if (numbands == lastnumbands || bandindex == -1) {
5524  pfree(arg);
5525  rt_raster_destroy(raster);
5526  PG_FREE_IF_COPY(pgraster, 0);
5527  elog(ERROR, "RASTER_addBand: Could not add band defined by addbandarg of index %d to raster", i);
5528  PG_RETURN_NULL();
5529  }
5530 
5531  lastnumbands = numbands;
5532  POSTGIS_RT_DEBUGF(3, "%d bands in new raster", lastnumbands);
5533  }
5534 
5535  pfree(arg);
5536 
5537  pgrtn = rt_raster_serialize(raster);
5538  rt_raster_destroy(raster);
5539  PG_FREE_IF_COPY(pgraster, 0);
5540  if (!pgrtn)
5541  PG_RETURN_NULL();
5542 
5543  SET_VARSIZE(pgrtn, pgrtn->size);
5544  PG_RETURN_POINTER(pgrtn);
5545 }
int rt_raster_get_num_bands(rt_raster raster)
Definition: rt_api.c:5677
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
Definition: rt_api.c:8158
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
Definition: rt_api.c:5387
const char * rt_pixtype_name(rt_pixtype pixtype)
Definition: rt_api.c:1168
Definition: rt_api.h:184
tuple raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
Definition: rtrowdump.py:123
rt_pixtype
Definition: rt_api.h:172
#define POSTGIS_RT_DEBUG(level, msg)
Definition: rt_pg.h:58
#define FALSE
Definition: dbfopen.c:169
Struct definitions.
Definition: rt_api.h:2175
#define POSTGIS_RT_DEBUGF(level, msg,...)
Definition: rt_pg.h:62
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
Definition: rt_api.c:8350
rt_pixtype rt_pixtype_index_from_name(const char *pixname)
Definition: rt_api.c:1138
#define TRUE
Definition: dbfopen.c:170
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_api.c:5784

Here is the call graph for this function: