PostGIS  2.1.10dev-r@@SVN_REVISION@@
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 band of the input raster.

Parameters
rasterinput raster
nband0-based index of the band to process with colormap
colormaprt_colormap object of colormap to apply to band
Returns
new raster or NULL on error

Definition at line 14937 of file rt_api.c.

References _rti_colormap_arg_destroy(), _rti_colormap_arg_init(), ovdump::band, _rti_colormap_arg_t::band, rt_colormap_entry_t::color, rt_reclassexpr_t::dst, rt_colormap_t::entry, rt_reclassexpr_t::rt_reclassrange::exc_max, rt_reclassexpr_t::rt_reclassrange::exc_min, _rti_colormap_arg_t::expr, _rti_colormap_arg_t::hasnodata, rt_reclassexpr_t::rt_reclassrange::inc_max, rt_reclassexpr_t::rt_reclassrange::inc_min, rt_colormap_entry_t::isnodata, rt_reclassexpr_t::rt_reclassrange::max, rt_colormap_t::method, rt_reclassexpr_t::rt_reclassrange::min, rt_colormap_t::ncolor, rt_colormap_t::nentry, _rti_colormap_arg_t::nexpr, _rti_colormap_arg_t::nodataentry, _rti_colormap_arg_t::nodataval, _rti_colormap_arg_t::npos, _rti_colormap_arg_t::pos, PT_8BUI, _rti_colormap_arg_t::raster, RASTER_DEBUGF, rt_band_get_hasnodata_flag(), rt_band_get_nodata(), rt_band_reclass(), rt_raster_add_band(), rt_raster_get_band(), rt_raster_get_num_bands(), rt_raster_has_band(), rt_raster_is_empty(), rtalloc(), rterror(), rtinfo(), rtwarn(), rt_reclassexpr_t::src, and rt_colormap_entry_t::value.

Referenced by RASTER_colorMap(), and test_raster_colormap().

14940  {
14941  _rti_colormap_arg arg = NULL;
14942  rt_raster rtnraster = NULL;
14943  rt_band band = NULL;
14944  int i = 0;
14945  int j = 0;
14946  int k = 0;
14947 
14948  assert(colormap != NULL);
14949 
14950  /* empty raster */
14951  if (rt_raster_is_empty(raster))
14952  return NULL;
14953 
14954  /* no colormap entries */
14955  if (colormap->nentry < 1) {
14956  rterror("rt_raster_colormap: colormap must have at least one entry");
14957  return NULL;
14958  }
14959 
14960  /* nband is valid */
14961  if (!rt_raster_has_band(raster, nband)) {
14962  rterror("rt_raster_colormap: raster has no band at index %d", nband);
14963  return NULL;
14964  }
14965 
14966  band = rt_raster_get_band(raster, nband);
14967  if (band == NULL) {
14968  rterror("rt_raster_colormap: Could not get band at index %d", nband);
14969  return NULL;
14970  }
14971 
14972  /* init internal variables */
14973  arg = _rti_colormap_arg_init(raster);
14974  if (arg == NULL) {
14975  rterror("rt_raster_colormap: Could not initialize internal variables");
14976  return NULL;
14977  }
14978 
14979  /* handle NODATA */
14980  if (rt_band_get_hasnodata_flag(band)) {
14981  arg->hasnodata = 1;
14982  rt_band_get_nodata(band, &(arg->nodataval));
14983  }
14984 
14985  /* # of colors */
14986  if (colormap->ncolor < 1) {
14987  rterror("rt_raster_colormap: At least one color must be provided");
14989  return NULL;
14990  }
14991  else if (colormap->ncolor > 4) {
14992  rtinfo("More than four colors indicated. Using only the first four colors");
14993  colormap->ncolor = 4;
14994  }
14995 
14996  /* find non-NODATA entries */
14997  arg->npos = 0;
14998  arg->pos = rtalloc(sizeof(uint16_t) * colormap->nentry);
14999  if (arg->pos == NULL) {
15000  rterror("rt_raster_colormap: Could not allocate memory for valid entries");
15002  return NULL;
15003  }
15004  for (i = 0, j = 0; i < colormap->nentry; i++) {
15005  /* special handling for NODATA entries */
15006  if (colormap->entry[i].isnodata) {
15007  /* first NODATA entry found, use it */
15008  if (arg->nodataentry == NULL)
15009  arg->nodataentry = &(colormap->entry[i]);
15010  else
15011  rtwarn("More than one colormap entry found for NODATA value. Only using first NOTDATA entry");
15012 
15013  continue;
15014  }
15015 
15016  (arg->npos)++;
15017  arg->pos[j++] = i;
15018  }
15019 
15020  /* INTERPOLATE and only one non-NODATA entry */
15021  if (colormap->method == CM_INTERPOLATE && arg->npos < 2) {
15022  rtinfo("Method INTERPOLATE requires at least two non-NODATA colormap entries. Using NEAREST instead");
15023  colormap->method = CM_NEAREST;
15024  }
15025 
15026  /* NODATA entry but band has no NODATA value */
15027  if (!arg->hasnodata && arg->nodataentry != NULL) {
15028  rtinfo("Band at index %d has no NODATA value. Ignoring NODATA entry", nband);
15029  arg->nodataentry = NULL;
15030  }
15031 
15032  /* allocate expr */
15033  arg->nexpr = arg->npos;
15034 
15035  /* INTERPOLATE needs one less than the number of entries */
15036  if (colormap->method == CM_INTERPOLATE)
15037  arg->nexpr -= 1;
15038  /* EXACT requires a no matching expression */
15039  else if (colormap->method == CM_EXACT)
15040  arg->nexpr += 1;
15041 
15042  /* NODATA entry exists, add expression */
15043  if (arg->nodataentry != NULL)
15044  arg->nexpr += 1;
15045  arg->expr = rtalloc(sizeof(rt_reclassexpr) * arg->nexpr);
15046  if (arg->expr == NULL) {
15047  rterror("rt_raster_colormap: Could not allocate memory for reclass expressions");
15049  return NULL;
15050  }
15051  RASTER_DEBUGF(4, "nexpr = %d", arg->nexpr);
15052  RASTER_DEBUGF(4, "expr @ %p", arg->expr);
15053 
15054  for (i = 0; i < arg->nexpr; i++) {
15055  arg->expr[i] = rtalloc(sizeof(struct rt_reclassexpr_t));
15056  if (arg->expr[i] == NULL) {
15057  rterror("rt_raster_colormap: Could not allocate memory for reclass expression");
15059  return NULL;
15060  }
15061  }
15062 
15063  /* reclassify bands */
15064  /* by # of colors */
15065  for (i = 0; i < colormap->ncolor; i++) {
15066  k = 0;
15067 
15068  /* handle NODATA entry first */
15069  if (arg->nodataentry != NULL) {
15070  arg->expr[k]->src.min = arg->nodataentry->value;
15071  arg->expr[k]->src.max = arg->nodataentry->value;
15072  arg->expr[k]->src.inc_min = 1;
15073  arg->expr[k]->src.inc_max = 1;
15074  arg->expr[k]->src.exc_min = 0;
15075  arg->expr[k]->src.exc_max = 0;
15076 
15077  arg->expr[k]->dst.min = arg->nodataentry->color[i];
15078  arg->expr[k]->dst.max = arg->nodataentry->color[i];
15079 
15080  arg->expr[k]->dst.inc_min = 1;
15081  arg->expr[k]->dst.inc_max = 1;
15082  arg->expr[k]->dst.exc_min = 0;
15083  arg->expr[k]->dst.exc_max = 0;
15084 
15085  RASTER_DEBUGF(4, "NODATA expr[%d]->src (min, max, in, ix, en, ex) = (%f, %f, %d, %d, %d, %d)",
15086  k,
15087  arg->expr[k]->src.min,
15088  arg->expr[k]->src.max,
15089  arg->expr[k]->src.inc_min,
15090  arg->expr[k]->src.inc_max,
15091  arg->expr[k]->src.exc_min,
15092  arg->expr[k]->src.exc_max
15093  );
15094  RASTER_DEBUGF(4, "NODATA expr[%d]->dst (min, max, in, ix, en, ex) = (%f, %f, %d, %d, %d, %d)",
15095  k,
15096  arg->expr[k]->dst.min,
15097  arg->expr[k]->dst.max,
15098  arg->expr[k]->dst.inc_min,
15099  arg->expr[k]->dst.inc_max,
15100  arg->expr[k]->dst.exc_min,
15101  arg->expr[k]->dst.exc_max
15102  );
15103 
15104  k++;
15105  }
15106 
15107  /* by non-NODATA entry */
15108  for (j = 0; j < arg->npos; j++) {
15109  if (colormap->method == CM_INTERPOLATE) {
15110  if (j == arg->npos - 1)
15111  continue;
15112 
15113  arg->expr[k]->src.min = colormap->entry[arg->pos[j + 1]].value;
15114  arg->expr[k]->src.inc_min = 1;
15115  arg->expr[k]->src.exc_min = 0;
15116 
15117  arg->expr[k]->src.max = colormap->entry[arg->pos[j]].value;
15118  arg->expr[k]->src.inc_max = 1;
15119  arg->expr[k]->src.exc_max = 0;
15120 
15121  arg->expr[k]->dst.min = colormap->entry[arg->pos[j + 1]].color[i];
15122  arg->expr[k]->dst.max = colormap->entry[arg->pos[j]].color[i];
15123 
15124  arg->expr[k]->dst.inc_min = 1;
15125  arg->expr[k]->dst.exc_min = 0;
15126 
15127  arg->expr[k]->dst.inc_max = 1;
15128  arg->expr[k]->dst.exc_max = 0;
15129  }
15130  else if (colormap->method == CM_NEAREST) {
15131 
15132  /* NOT last entry */
15133  if (j != arg->npos - 1) {
15134  arg->expr[k]->src.min = ((colormap->entry[arg->pos[j]].value - colormap->entry[arg->pos[j + 1]].value) / 2.) + colormap->entry[arg->pos[j + 1]].value;
15135  arg->expr[k]->src.inc_min = 0;
15136  arg->expr[k]->src.exc_min = 0;
15137  }
15138  /* last entry */
15139  else {
15140  arg->expr[k]->src.min = colormap->entry[arg->pos[j]].value;
15141  arg->expr[k]->src.inc_min = 1;
15142  arg->expr[k]->src.exc_min = 1;
15143  }
15144 
15145  /* NOT first entry */
15146  if (j > 0) {
15147  arg->expr[k]->src.max = arg->expr[k - 1]->src.min;
15148  arg->expr[k]->src.inc_max = 1;
15149  arg->expr[k]->src.exc_max = 0;
15150  }
15151  /* first entry */
15152  else {
15153  arg->expr[k]->src.max = colormap->entry[arg->pos[j]].value;
15154  arg->expr[k]->src.inc_max = 1;
15155  arg->expr[k]->src.exc_max = 1;
15156  }
15157 
15158  arg->expr[k]->dst.min = colormap->entry[arg->pos[j]].color[i];
15159  arg->expr[k]->dst.inc_min = 1;
15160  arg->expr[k]->dst.exc_min = 0;
15161 
15162  arg->expr[k]->dst.max = colormap->entry[arg->pos[j]].color[i];
15163  arg->expr[k]->dst.inc_max = 1;
15164  arg->expr[k]->dst.exc_max = 0;
15165  }
15166  else if (colormap->method == CM_EXACT) {
15167  arg->expr[k]->src.min = colormap->entry[arg->pos[j]].value;
15168  arg->expr[k]->src.inc_min = 1;
15169  arg->expr[k]->src.exc_min = 0;
15170 
15171  arg->expr[k]->src.max = colormap->entry[arg->pos[j]].value;
15172  arg->expr[k]->src.inc_max = 1;
15173  arg->expr[k]->src.exc_max = 0;
15174 
15175  arg->expr[k]->dst.min = colormap->entry[arg->pos[j]].color[i];
15176  arg->expr[k]->dst.inc_min = 1;
15177  arg->expr[k]->dst.exc_min = 0;
15178 
15179  arg->expr[k]->dst.max = colormap->entry[arg->pos[j]].color[i];
15180  arg->expr[k]->dst.inc_max = 1;
15181  arg->expr[k]->dst.exc_max = 0;
15182  }
15183 
15184  RASTER_DEBUGF(4, "expr[%d]->src (min, max, in, ix, en, ex) = (%f, %f, %d, %d, %d, %d)",
15185  k,
15186  arg->expr[k]->src.min,
15187  arg->expr[k]->src.max,
15188  arg->expr[k]->src.inc_min,
15189  arg->expr[k]->src.inc_max,
15190  arg->expr[k]->src.exc_min,
15191  arg->expr[k]->src.exc_max
15192  );
15193 
15194  RASTER_DEBUGF(4, "expr[%d]->dst (min, max, in, ix, en, ex) = (%f, %f, %d, %d, %d, %d)",
15195  k,
15196  arg->expr[k]->dst.min,
15197  arg->expr[k]->dst.max,
15198  arg->expr[k]->dst.inc_min,
15199  arg->expr[k]->dst.inc_max,
15200  arg->expr[k]->dst.exc_min,
15201  arg->expr[k]->dst.exc_max
15202  );
15203 
15204  k++;
15205  }
15206 
15207  /* EXACT has one last expression for catching all uncaught values */
15208  if (colormap->method == CM_EXACT) {
15209  arg->expr[k]->src.min = 0;
15210  arg->expr[k]->src.inc_min = 1;
15211  arg->expr[k]->src.exc_min = 1;
15212 
15213  arg->expr[k]->src.max = 0;
15214  arg->expr[k]->src.inc_max = 1;
15215  arg->expr[k]->src.exc_max = 1;
15216 
15217  arg->expr[k]->dst.min = 0;
15218  arg->expr[k]->dst.inc_min = 1;
15219  arg->expr[k]->dst.exc_min = 0;
15220 
15221  arg->expr[k]->dst.max = 0;
15222  arg->expr[k]->dst.inc_max = 1;
15223  arg->expr[k]->dst.exc_max = 0;
15224 
15225  RASTER_DEBUGF(4, "expr[%d]->src (min, max, in, ix, en, ex) = (%f, %f, %d, %d, %d, %d)",
15226  k,
15227  arg->expr[k]->src.min,
15228  arg->expr[k]->src.max,
15229  arg->expr[k]->src.inc_min,
15230  arg->expr[k]->src.inc_max,
15231  arg->expr[k]->src.exc_min,
15232  arg->expr[k]->src.exc_max
15233  );
15234 
15235  RASTER_DEBUGF(4, "expr[%d]->dst (min, max, in, ix, en, ex) = (%f, %f, %d, %d, %d, %d)",
15236  k,
15237  arg->expr[k]->dst.min,
15238  arg->expr[k]->dst.max,
15239  arg->expr[k]->dst.inc_min,
15240  arg->expr[k]->dst.inc_max,
15241  arg->expr[k]->dst.exc_min,
15242  arg->expr[k]->dst.exc_max
15243  );
15244 
15245  k++;
15246  }
15247 
15248  /* call rt_band_reclass */
15249  arg->band = rt_band_reclass(band, PT_8BUI, 0, 0, arg->expr, arg->nexpr);
15250  if (arg->band == NULL) {
15251  rterror("rt_raster_colormap: Could not reclassify band");
15253  return NULL;
15254  }
15255 
15256  /* add reclassified band to raster */
15257  if (rt_raster_add_band(arg->raster, arg->band, rt_raster_get_num_bands(arg->raster)) < 0) {
15258  rterror("rt_raster_colormap: Could not add reclassified band to output raster");
15260  return NULL;
15261  }
15262  }
15263 
15264  rtnraster = arg->raster;
15265  arg->raster = NULL;
15267 
15268  return rtnraster;
15269 }
static _rti_colormap_arg _rti_colormap_arg_init(rt_raster raster)
Definition: rt_api.c:14861
int rt_raster_get_num_bands(rt_raster raster)
Definition: rt_api.c:5677
rt_reclassexpr * expr
Definition: rt_api.c:14853
uint16_t * pos
Definition: rt_api.c:14856
uint16_t nentry
Definition: rt_api.h:2410
static void _rti_colormap_arg_destroy(_rti_colormap_arg arg)
Definition: rt_api.c:14896
struct rt_reclassexpr_t::rt_reclassrange dst
uint8_t color[4]
Definition: rt_api.h:2399
tuple band
Definition: ovdump.py:57
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
rt_raster raster
Definition: rt_api.c:14845
void rtinfo(const char *fmt,...)
Definition: rt_api.c:907
int rt_raster_add_band(rt_raster raster, rt_band band, int index)
Add band data to a raster.
Definition: rt_api.c:5706
struct rt_reclassexpr_t::rt_reclassrange src
void rtwarn(const char *fmt,...)
Definition: rt_api.c:920
#define RASTER_DEBUGF(level, msg,...)
Definition: rt_api.h:285
enum rt_colormap_t::@15 method
tuple nband
Definition: pixval.py:52
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
Definition: rt_api.c:3058
rt_colormap_entry entry
Definition: rt_api.h:2411
rt_band rt_band_reclass(rt_band srcband, rt_pixtype pixtype, uint32_t hasnodata, double nodataval, rt_reclassexpr *exprset, int exprcount)
Returns new band with values reclassified.
Definition: rt_api.c:5009
void * rtalloc(size_t size)
Raster core memory management functions.
Definition: rt_api.c:867
void rterror(const char *fmt,...)
Raster core error and info handlers.
Definition: rt_api.c:895
rt_band rt_raster_get_band(rt_raster raster, int n)
Return Nth band, or NULL if unavailable.
Definition: rt_api.c:5686
int rt_raster_is_empty(rt_raster raster)
Return TRUE if the raster is empty.
Definition: rt_api.c:8550
int isnodata
Definition: rt_api.h:2397
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
Definition: rt_api.c:2002
double value
Definition: rt_api.h:2398
rt_colormap_entry nodataentry
Definition: rt_api.c:14848

Here is the call graph for this function:

Here is the caller graph for this function: