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

Definition at line 11153 of file rt_pg.c.

References rtpg_colormap_arg_t::band, rtpg_colormap_arg_t::bandstats, rt_colormap_entry_t::color, rtpg_colormap_arg_t::colormap, rtpg_colormap_arg_t::element, rt_colormap_t::entry, rtpg_colormap_arg_t::entry, FALSE, rt_colormap_entry_t::isnodata, rt_bandstats_t::max, rt_colormap_t::method, rt_bandstats_t::min, pixval::nband, rtpg_colormap_arg_t::nband, rt_colormap_t::ncolor, rtpg_colormap_arg_t::nelement, rt_colormap_t::nentry, rtpg_colormap_arg_t::nentry, rtpg_colormap_arg_t::nodataentry, POSTGIS_RT_DEBUG, POSTGIS_RT_DEBUGF, rtrowdump::raster, rtpg_colormap_arg_t::raster, rt_band_get_summary_stats(), rt_raster_clone(), rt_raster_colormap(), rt_raster_deserialize(), rt_raster_destroy(), rt_raster_get_band(), rt_raster_has_band(), rt_raster_serialize(), rtpg_colormap_arg_destroy(), rtpg_colormap_arg_init(), rtpg_strreplace(), rtpg_strsplit(), rtpg_strtoupper(), rtpg_trim(), genraster::value, and rt_colormap_entry_t::value.

11154 {
11155  rt_pgraster *pgraster = NULL;
11156  rtpg_colormap_arg arg = NULL;
11157  char *junk = NULL;
11158  rt_raster raster = NULL;
11159 
11160  POSTGIS_RT_DEBUG(3, "RASTER_colorMap: Starting");
11161 
11162  /* pgraster is NULL, return NULL */
11163  if (PG_ARGISNULL(0))
11164  PG_RETURN_NULL();
11165 
11166  /* init arg */
11167  arg = rtpg_colormap_arg_init();
11168  if (arg == NULL) {
11169  elog(ERROR, "RASTER_colorMap: Could not initialize argument structure");
11170  PG_RETURN_NULL();
11171  }
11172 
11173  /* raster (0) */
11174  pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
11175 
11176  /* raster object */
11177  arg->raster = rt_raster_deserialize(pgraster, FALSE);
11178  if (!arg->raster) {
11180  PG_FREE_IF_COPY(pgraster, 0);
11181  elog(ERROR, "RASTER_colorMap: Could not deserialize raster");
11182  PG_RETURN_NULL();
11183  }
11184 
11185  /* nband (1) */
11186  if (!PG_ARGISNULL(1))
11187  arg->nband = PG_GETARG_INT32(1);
11188  POSTGIS_RT_DEBUGF(4, "nband = %d", arg->nband);
11189 
11190  /* check that band works */
11191  if (!rt_raster_has_band(arg->raster, arg->nband - 1)) {
11192  elog(NOTICE, "Raster does not have band at index %d. Returning empty raster", arg->nband);
11193 
11194  raster = rt_raster_clone(arg->raster, 0);
11195  if (raster == NULL) {
11197  PG_FREE_IF_COPY(pgraster, 0);
11198  elog(ERROR, "RASTER_colorMap: Could not create empty raster");
11199  PG_RETURN_NULL();
11200  }
11201 
11203  PG_FREE_IF_COPY(pgraster, 0);
11204 
11205  pgraster = rt_raster_serialize(raster);
11206  rt_raster_destroy(raster);
11207  if (pgraster == NULL)
11208  PG_RETURN_NULL();
11209 
11210  SET_VARSIZE(pgraster, ((rt_pgraster*) pgraster)->size);
11211  PG_RETURN_POINTER(pgraster);
11212  }
11213 
11214  /* get band */
11215  arg->band = rt_raster_get_band(arg->raster, arg->nband - 1);
11216  if (arg->band == NULL) {
11217  int nband = arg->nband;
11219  PG_FREE_IF_COPY(pgraster, 0);
11220  elog(ERROR, "RASTER_colorMap: Could not get band at index %d", nband);
11221  PG_RETURN_NULL();
11222  }
11223 
11224  /* method (3) */
11225  if (!PG_ARGISNULL(3)) {
11226  char *method = NULL;
11227  char *tmp = text_to_cstring(PG_GETARG_TEXT_P(3));
11228  POSTGIS_RT_DEBUGF(4, "raw method = %s", tmp);
11229 
11230  method = rtpg_trim(tmp);
11231  pfree(tmp);
11232  method = rtpg_strtoupper(method);
11233 
11234  if (strcmp(method, "INTERPOLATE") == 0)
11235  arg->colormap->method = CM_INTERPOLATE;
11236  else if (strcmp(method, "EXACT") == 0)
11237  arg->colormap->method = CM_EXACT;
11238  else if (strcmp(method, "NEAREST") == 0)
11239  arg->colormap->method = CM_NEAREST;
11240  else {
11241  elog(NOTICE, "Unknown value provided for method. Defaulting to INTERPOLATE");
11242  arg->colormap->method = CM_INTERPOLATE;
11243  }
11244  }
11245  /* default to INTERPOLATE */
11246  else
11247  arg->colormap->method = CM_INTERPOLATE;
11248  POSTGIS_RT_DEBUGF(4, "method = %d", arg->colormap->method);
11249 
11250  /* colormap (2) */
11251  if (PG_ARGISNULL(2)) {
11253  PG_FREE_IF_COPY(pgraster, 0);
11254  elog(ERROR, "RASTER_colorMap: Value must be provided for colormap");
11255  PG_RETURN_NULL();
11256  }
11257  else {
11258  char *tmp = NULL;
11259  char *colormap = text_to_cstring(PG_GETARG_TEXT_P(2));
11260  char *_entry;
11261  char *_element;
11262  int i = 0;
11263  int j = 0;
11264 
11265  POSTGIS_RT_DEBUGF(4, "colormap = %s", colormap);
11266 
11267  /* empty string */
11268  if (!strlen(colormap)) {
11270  PG_FREE_IF_COPY(pgraster, 0);
11271  elog(ERROR, "RASTER_colorMap: Value must be provided for colormap");
11272  PG_RETURN_NULL();
11273  }
11274 
11275  arg->entry = rtpg_strsplit(colormap, "\n", &(arg->nentry));
11276  pfree(colormap);
11277  if (arg->nentry < 1) {
11279  PG_FREE_IF_COPY(pgraster, 0);
11280  elog(ERROR, "RASTER_colorMap: Could not process the value provided for colormap");
11281  PG_RETURN_NULL();
11282  }
11283 
11284  /* allocate the max # of colormap entries */
11285  arg->colormap->entry = palloc(sizeof(struct rt_colormap_entry_t) * arg->nentry);
11286  if (arg->colormap->entry == NULL) {
11288  PG_FREE_IF_COPY(pgraster, 0);
11289  elog(ERROR, "RASTER_colorMap: Could not allocate memory for colormap entries");
11290  PG_RETURN_NULL();
11291  }
11292  memset(arg->colormap->entry, 0, sizeof(struct rt_colormap_entry_t) * arg->nentry);
11293 
11294  /* each entry */
11295  for (i = 0; i < arg->nentry; i++) {
11296  /* substitute space for other delimiters */
11297  tmp = rtpg_strreplace(arg->entry[i], ":", " ", NULL);
11298  _entry = rtpg_strreplace(tmp, ",", " ", NULL);
11299  pfree(tmp);
11300  tmp = rtpg_strreplace(_entry, "\t", " ", NULL);
11301  pfree(_entry);
11302  _entry = rtpg_trim(tmp);
11303  pfree(tmp);
11304 
11305  POSTGIS_RT_DEBUGF(4, "Processing entry[%d] = %s", i, arg->entry[i]);
11306  POSTGIS_RT_DEBUGF(4, "Cleaned entry[%d] = %s", i, _entry);
11307 
11308  /* empty entry, continue */
11309  if (!strlen(_entry)) {
11310  POSTGIS_RT_DEBUGF(3, "Skipping empty entry[%d]", i);
11311  pfree(_entry);
11312  continue;
11313  }
11314 
11315  arg->element = rtpg_strsplit(_entry, " ", &(arg->nelement));
11316  pfree(_entry);
11317  if (arg->nelement < 2) {
11319  PG_FREE_IF_COPY(pgraster, 0);
11320  elog(ERROR, "RASTER_colorMap: Could not process colormap entry %d", i + 1);
11321  PG_RETURN_NULL();
11322  }
11323  else if (arg->nelement > 5) {
11324  elog(NOTICE, "More than five elements in colormap entry %d. Using at most five elements", i + 1);
11325  arg->nelement = 5;
11326  }
11327 
11328  /* smallest # of colors */
11329  if ((arg->nelement - 1) < arg->colormap->ncolor)
11330  arg->colormap->ncolor = arg->nelement - 1;
11331 
11332  /* each element of entry */
11333  for (j = 0; j < arg->nelement; j++) {
11334 
11335  _element = rtpg_trim(arg->element[j]);
11336  _element = rtpg_strtoupper(_element);
11337  POSTGIS_RT_DEBUGF(4, "Processing entry[%d][%d] = %s", i, j, arg->element[j]);
11338  POSTGIS_RT_DEBUGF(4, "Cleaned entry[%d][%d] = %s", i, j, _element);
11339 
11340  /* first element is ALWAYS a band value, percentage OR "nv" string */
11341  if (j == 0) {
11342  char *percent = NULL;
11343 
11344  /* NODATA */
11345  if (
11346  strcmp(_element, "NV") == 0 ||
11347  strcmp(_element, "NULL") == 0 ||
11348  strcmp(_element, "NODATA") == 0
11349  ) {
11350  POSTGIS_RT_DEBUG(4, "Processing NODATA string");
11351 
11352  if (arg->nodataentry > -1) {
11353  elog(NOTICE, "More than one NODATA entry found. Using only the first one");
11354  }
11355  else {
11356  arg->colormap->entry[arg->colormap->nentry].isnodata = 1;
11357  /* no need to set value as value comes from band's NODATA */
11358  arg->colormap->entry[arg->colormap->nentry].value = 0;
11359  }
11360  }
11361  /* percent value */
11362  else if ((percent = strchr(_element, '%')) != NULL) {
11363  double value;
11364  POSTGIS_RT_DEBUG(4, "Processing percent string");
11365 
11366  /* get the band stats */
11367  if (arg->bandstats == NULL) {
11368  POSTGIS_RT_DEBUG(4, "Getting band stats");
11369 
11370  arg->bandstats = rt_band_get_summary_stats(arg->band, 1, 1, 0, NULL, NULL, NULL);
11371  if (arg->bandstats == NULL) {
11372  pfree(_element);
11374  PG_FREE_IF_COPY(pgraster, 0);
11375  elog(ERROR, "RASTER_colorMap: Could not get band's summary stats to process percentages");
11376  PG_RETURN_NULL();
11377  }
11378  }
11379 
11380  /* get the string before the percent char */
11381  tmp = palloc(sizeof(char) * (percent - _element + 1));
11382  if (tmp == NULL) {
11383  pfree(_element);
11385  PG_FREE_IF_COPY(pgraster, 0);
11386  elog(ERROR, "RASTER_colorMap: Could not allocate memory for value of percentage");
11387  PG_RETURN_NULL();
11388  }
11389 
11390  memcpy(tmp, _element, percent - _element);
11391  tmp[percent - _element] = '\0';
11392  POSTGIS_RT_DEBUGF(4, "Percent value = %s", tmp);
11393 
11394  /* get percentage value */
11395  errno = 0;
11396  value = strtod(tmp, NULL);
11397  pfree(tmp);
11398  if (errno != 0 || _element == junk) {
11399  pfree(_element);
11401  PG_FREE_IF_COPY(pgraster, 0);
11402  elog(ERROR, "RASTER_colorMap: Could not process percent string to value");
11403  PG_RETURN_NULL();
11404  }
11405 
11406  /* check percentage */
11407  if (value < 0.) {
11408  elog(NOTICE, "Percentage values cannot be less than zero. Defaulting to zero");
11409  value = 0.;
11410  }
11411  else if (value > 100.) {
11412  elog(NOTICE, "Percentage values cannot be greater than 100. Defaulting to 100");
11413  value = 100.;
11414  }
11415 
11416  /* get the true pixel value */
11417  /* TODO: should the percentage be quantile based? */
11418  arg->colormap->entry[arg->colormap->nentry].value = ((value / 100.) * (arg->bandstats->max - arg->bandstats->min)) + arg->bandstats->min;
11419  }
11420  /* straight value */
11421  else {
11422  errno = 0;
11423  arg->colormap->entry[arg->colormap->nentry].value = strtod(_element, &junk);
11424  if (errno != 0 || _element == junk) {
11425  pfree(_element);
11427  PG_FREE_IF_COPY(pgraster, 0);
11428  elog(ERROR, "RASTER_colorMap: Could not process string to value");
11429  PG_RETURN_NULL();
11430  }
11431  }
11432 
11433  }
11434  /* RGB values (0 - 255) */
11435  else {
11436  int value = 0;
11437 
11438  errno = 0;
11439  value = (int) strtod(_element, &junk);
11440  if (errno != 0 || _element == junk) {
11441  pfree(_element);
11443  PG_FREE_IF_COPY(pgraster, 0);
11444  elog(ERROR, "RASTER_colorMap: Could not process string to value");
11445  PG_RETURN_NULL();
11446  }
11447 
11448  if (value > 255) {
11449  elog(NOTICE, "RGBA value cannot be greater than 255. Defaulting to 255");
11450  value = 255;
11451  }
11452  else if (value < 0) {
11453  elog(NOTICE, "RGBA value cannot be less than zero. Defaulting to zero");
11454  value = 0;
11455  }
11456  arg->colormap->entry[arg->colormap->nentry].color[j - 1] = value;
11457  }
11458 
11459  pfree(_element);
11460  }
11461 
11462  POSTGIS_RT_DEBUGF(4, "colormap->entry[%d] (isnodata, value, R, G, B, A) = (%d, %f, %d, %d, %d, %d)",
11463  arg->colormap->nentry,
11464  arg->colormap->entry[arg->colormap->nentry].isnodata,
11465  arg->colormap->entry[arg->colormap->nentry].value,
11466  arg->colormap->entry[arg->colormap->nentry].color[0],
11467  arg->colormap->entry[arg->colormap->nentry].color[1],
11468  arg->colormap->entry[arg->colormap->nentry].color[2],
11469  arg->colormap->entry[arg->colormap->nentry].color[3]
11470  );
11471 
11472  arg->colormap->nentry++;
11473  }
11474 
11475  POSTGIS_RT_DEBUGF(4, "colormap->nentry = %d", arg->colormap->nentry);
11476  POSTGIS_RT_DEBUGF(4, "colormap->ncolor = %d", arg->colormap->ncolor);
11477  }
11478 
11479  /* call colormap */
11480  raster = rt_raster_colormap(arg->raster, arg->nband - 1, arg->colormap);
11481  if (raster == NULL) {
11483  PG_FREE_IF_COPY(pgraster, 0);
11484  elog(ERROR, "RASTER_colorMap: Could not create new raster with applied colormap");
11485  PG_RETURN_NULL();
11486  }
11487 
11489  PG_FREE_IF_COPY(pgraster, 0);
11490  pgraster = rt_raster_serialize(raster);
11491  rt_raster_destroy(raster);
11492 
11493  POSTGIS_RT_DEBUG(3, "RASTER_colorMap: Done");
11494 
11495  if (pgraster == NULL)
11496  PG_RETURN_NULL();
11497 
11498  SET_VARSIZE(pgraster, ((rt_pgraster*) pgraster)->size);
11499  PG_RETURN_POINTER(pgraster);
11500 }
static char * rtpg_strtoupper(char *str)
Definition: rt_pg.c:730
static char * rtpg_strreplace(const char *str, const char *oldstr, const char *newstr, int *count)
Definition: rt_pg.c:685
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
Definition: rt_api.c:8158
rt_raster rt_raster_colormap(rt_raster raster, int nband, rt_colormap colormap)
Returns a new raster with up to four 8BUI bands (RGBA) from applying a colormap to the user-specified...
Definition: rt_api.c:14937
uint16_t nentry
Definition: rt_api.h:2410
rt_raster raster
Definition: rt_pg.c:11071
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
Definition: rt_api.c:5387
rt_colormap colormap
Definition: rt_pg.c:11076
static char * rtpg_trim(const char *input)
Definition: rt_pg.c:856
rt_bandstats bandstats
Definition: rt_pg.c:11074
uint8_t color[4]
Definition: rt_api.h:2399
int rt_raster_has_band(rt_raster raster, int nband)
Return TRUE if the raster has a band of this number.
Definition: rt_api.c:8563
tuple raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
Definition: rtrowdump.py:123
double min
Definition: rt_api.h:2279
static void rtpg_colormap_arg_destroy(rtpg_colormap_arg arg)
Definition: rt_pg.c:11120
static char ** rtpg_strsplit(const char *str, const char *delimiter, int *n)
Definition: rt_pg.c:772
enum rt_colormap_t::@15 method
#define POSTGIS_RT_DEBUG(level, msg)
Definition: rt_pg.h:58
tuple nband
Definition: pixval.py:52
rt_colormap_entry entry
Definition: rt_api.h:2411
rt_bandstats rt_band_get_summary_stats(rt_band band, int exclude_nodata_value, double sample, int inc_vals, uint64_t *cK, double *cM, double *cQ)
Compute summary statistics for a band.
Definition: rt_api.c:3269
rt_band rt_raster_get_band(rt_raster raster, int n)
Return Nth band, or NULL if unavailable.
Definition: rt_api.c:5686
Definition: rt_api.h:2396
#define FALSE
Definition: dbfopen.c:169
Struct definitions.
Definition: rt_api.h:2175
#define POSTGIS_RT_DEBUGF(level, msg,...)
Definition: rt_pg.h:62
static rtpg_colormap_arg rtpg_colormap_arg_init()
Definition: rt_pg.c:11086
double max
Definition: rt_api.h:2280
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
Definition: rt_api.c:8350
rt_raster rt_raster_clone(rt_raster raster, uint8_t deep)
Clone an existing raster.
Definition: rt_api.c:8740
int isnodata
Definition: rt_api.h:2397
double value
Definition: rt_api.h:2398

Here is the call graph for this function: