PostGIS  2.1.10dev-r@@SVN_REVISION@@
rt_valuecount rt_band_get_value_count ( rt_band  band,
int  exclude_nodata_value,
double *  search_values,
uint32_t  search_values_count,
double  roundto,
uint32_t *  rtn_total,
uint32_t *  rtn_count 
)

Count the number of times provided value(s) occur in the band.

Parameters
band: the band to query for minimum and maximum pixel values
exclude_nodata_value: if non-zero, ignore nodata values
search_values: array of values to count
search_values_count: the number of search values
roundto: the decimal place to round the values to
rtn_total: the number of pixels examined in the band
rtn_count: the number of value counts being returned
Returns
the number of times the provide value(s) occur or NULL

Definition at line 4750 of file rt_api.c.

References genraster::count, rt_valuecount_t::count, ovdump::data, ES_NONE, FALSE, FLT_EQ, FLT_NEQ, rt_band_t::height, rt_valuecount_t::percent, rt_band_t::pixtype, PT_16BSI, PT_16BUI, PT_1BB, PT_2BUI, PT_32BF, PT_32BSI, PT_32BUI, PT_4BUI, PT_64BF, PT_8BSI, PT_8BUI, PT_END, RASTER_DEBUG, RASTER_DEBUGF, ROUND, rt_band_get_data(), rt_band_get_hasnodata_flag(), rt_band_get_isnodata_flag(), rt_band_get_nodata(), rt_band_get_pixel(), rtalloc(), rterror(), rtrealloc(), rtwarn(), genraster::value, rt_valuecount_t::value, rt_band_t::width, pixval::x, and pixval::y.

Referenced by RASTER_valueCount(), RASTER_valueCountCoverage(), and test_band_value_count().

4754  {
4755  rt_valuecount vcnts = NULL;
4756  rt_pixtype pixtype = PT_END;
4757  uint8_t *data = NULL;
4758  double nodata = 0;
4759 
4760  int scale = 0;
4761  int doround = 0;
4762  double tmpd = 0;
4763  int i = 0;
4764 
4765  uint32_t x = 0;
4766  uint32_t y = 0;
4767  int rtn;
4768  double pxlval;
4769  int isnodata = 0;
4770  double rpxlval;
4771  uint32_t total = 0;
4772  int vcnts_count = 0;
4773  int new_valuecount = 0;
4774 
4775 #if POSTGIS_DEBUG_LEVEL > 0
4776  clock_t start, stop;
4777  double elapsed = 0;
4778 #endif
4779 
4780  RASTER_DEBUG(3, "starting");
4781 #if POSTGIS_DEBUG_LEVEL > 0
4782  start = clock();
4783 #endif
4784 
4785  assert(NULL != band);
4786  assert(NULL != rtn_count);
4787 
4788  data = rt_band_get_data(band);
4789  if (data == NULL) {
4790  rterror("rt_band_get_summary_stats: Cannot get band data");
4791  return NULL;
4792  }
4793 
4794  pixtype = band->pixtype;
4795 
4796  if (rt_band_get_hasnodata_flag(band)) {
4797  rt_band_get_nodata(band, &nodata);
4798  RASTER_DEBUGF(3, "hasnodata, nodataval = 1, %f", nodata);
4799  }
4800  else {
4801  exclude_nodata_value = 0;
4802  RASTER_DEBUG(3, "hasnodata, nodataval = 0, 0");
4803  }
4804 
4805  RASTER_DEBUGF(3, "exclude_nodata_value = %d", exclude_nodata_value);
4806 
4807  /* process roundto */
4808  if (roundto < 0 || FLT_EQ(roundto, 0.0)) {
4809  roundto = 0;
4810  scale = 0;
4811  }
4812  /* tenths, hundredths, thousandths, etc */
4813  else if (roundto < 1) {
4814  switch (pixtype) {
4815  /* integer band types don't have digits after the decimal place */
4816  case PT_1BB:
4817  case PT_2BUI:
4818  case PT_4BUI:
4819  case PT_8BSI:
4820  case PT_8BUI:
4821  case PT_16BSI:
4822  case PT_16BUI:
4823  case PT_32BSI:
4824  case PT_32BUI:
4825  roundto = 0;
4826  break;
4827  /* floating points, check the rounding */
4828  case PT_32BF:
4829  case PT_64BF:
4830  for (scale = 0; scale <= 20; scale++) {
4831  tmpd = roundto * pow(10, scale);
4832  if (FLT_EQ((tmpd - ((int) tmpd)), 0.0)) break;
4833  }
4834  break;
4835  case PT_END:
4836  break;
4837  }
4838  }
4839  /* ones, tens, hundreds, etc */
4840  else {
4841  for (scale = 0; scale >= -20; scale--) {
4842  tmpd = roundto * pow(10, scale);
4843  if (tmpd < 1 || FLT_EQ(tmpd, 1.0)) {
4844  if (scale == 0) doround = 1;
4845  break;
4846  }
4847  }
4848  }
4849 
4850  if (scale != 0 || doround)
4851  doround = 1;
4852  else
4853  doround = 0;
4854  RASTER_DEBUGF(3, "scale = %d", scale);
4855  RASTER_DEBUGF(3, "doround = %d", doround);
4856 
4857  /* process search_values */
4858  if (search_values_count > 0 && NULL != search_values) {
4859  vcnts = (rt_valuecount) rtalloc(sizeof(struct rt_valuecount_t) * search_values_count);
4860  if (NULL == vcnts) {
4861  rterror("rt_band_get_count_of_values: Could not allocate memory for value counts");
4862  *rtn_count = 0;
4863  return NULL;
4864  }
4865 
4866  for (i = 0; i < search_values_count; i++) {
4867  vcnts[i].count = 0;
4868  vcnts[i].percent = 0;
4869  if (!doround)
4870  vcnts[i].value = search_values[i];
4871  else
4872  vcnts[i].value = ROUND(search_values[i], scale);
4873  }
4874  vcnts_count = i;
4875  }
4876  else
4877  search_values_count = 0;
4878  RASTER_DEBUGF(3, "search_values_count = %d", search_values_count);
4879 
4880  /* entire band is nodata */
4881  if (rt_band_get_isnodata_flag(band) != FALSE) {
4882  if (exclude_nodata_value) {
4883  rtwarn("All pixels of band have the NODATA value");
4884  return NULL;
4885  }
4886  else {
4887  if (search_values_count > 0) {
4888  /* check for nodata match */
4889  for (i = 0; i < search_values_count; i++) {
4890  if (!doround)
4891  tmpd = nodata;
4892  else
4893  tmpd = ROUND(nodata, scale);
4894 
4895  if (FLT_NEQ(tmpd, vcnts[i].value))
4896  continue;
4897 
4898  vcnts[i].count = band->width * band->height;
4899  if (NULL != rtn_total) *rtn_total = vcnts[i].count;
4900  vcnts->percent = 1.0;
4901  }
4902 
4903  *rtn_count = vcnts_count;
4904  }
4905  /* no defined search values */
4906  else {
4907  vcnts = (rt_valuecount) rtalloc(sizeof(struct rt_valuecount_t));
4908  if (NULL == vcnts) {
4909  rterror("rt_band_get_count_of_values: Could not allocate memory for value counts");
4910  *rtn_count = 0;
4911  return NULL;
4912  }
4913 
4914  vcnts->value = nodata;
4915  vcnts->count = band->width * band->height;
4916  if (NULL != rtn_total) *rtn_total = vcnts[i].count;
4917  vcnts->percent = 1.0;
4918 
4919  *rtn_count = 1;
4920  }
4921 
4922  return vcnts;
4923  }
4924  }
4925 
4926  for (x = 0; x < band->width; x++) {
4927  for (y = 0; y < band->height; y++) {
4928  rtn = rt_band_get_pixel(band, x, y, &pxlval, &isnodata);
4929 
4930  /* error getting value, continue */
4931  if (rtn != ES_NONE)
4932  continue;
4933 
4934  if (!exclude_nodata_value || (exclude_nodata_value && !isnodata)) {
4935  total++;
4936  if (doround) {
4937  rpxlval = ROUND(pxlval, scale);
4938  }
4939  else
4940  rpxlval = pxlval;
4941  RASTER_DEBUGF(5, "(pxlval, rpxlval) => (%0.6f, %0.6f)", pxlval, rpxlval);
4942 
4943  new_valuecount = 1;
4944  /* search for match in existing valuecounts */
4945  for (i = 0; i < vcnts_count; i++) {
4946  /* match found */
4947  if (FLT_EQ(vcnts[i].value, rpxlval)) {
4948  vcnts[i].count++;
4949  new_valuecount = 0;
4950  RASTER_DEBUGF(5, "(value, count) => (%0.6f, %d)", vcnts[i].value, vcnts[i].count);
4951  break;
4952  }
4953  }
4954 
4955  /*
4956  don't add new valuecount either because
4957  - no need for new one
4958  - user-defined search values
4959  */
4960  if (!new_valuecount || search_values_count > 0) continue;
4961 
4962  /* add new valuecount */
4963  vcnts = rtrealloc(vcnts, sizeof(struct rt_valuecount_t) * (vcnts_count + 1));
4964  if (NULL == vcnts) {
4965  rterror("rt_band_get_count_of_values: Could not allocate memory for value counts");
4966  *rtn_count = 0;
4967  return NULL;
4968  }
4969 
4970  vcnts[vcnts_count].value = rpxlval;
4971  vcnts[vcnts_count].count = 1;
4972  vcnts[vcnts_count].percent = 0;
4973  RASTER_DEBUGF(5, "(value, count) => (%0.6f, %d)", vcnts[vcnts_count].value, vcnts[vcnts_count].count);
4974  vcnts_count++;
4975  }
4976  }
4977  }
4978 
4979 #if POSTGIS_DEBUG_LEVEL > 0
4980  stop = clock();
4981  elapsed = ((double) (stop - start)) / CLOCKS_PER_SEC;
4982  RASTER_DEBUGF(3, "elapsed time = %0.4f", elapsed);
4983 #endif
4984 
4985  for (i = 0; i < vcnts_count; i++) {
4986  vcnts[i].percent = (double) vcnts[i].count / total;
4987  RASTER_DEBUGF(5, "(value, count) => (%0.6f, %d)", vcnts[i].value, vcnts[i].count);
4988  }
4989 
4990  RASTER_DEBUG(3, "done");
4991  if (NULL != rtn_total) *rtn_total = total;
4992  *rtn_count = vcnts_count;
4993  return vcnts;
4994 }
struct rt_valuecount_t * rt_valuecount
Definition: rt_api.h:140
#define FLT_NEQ(x, y)
Definition: rt_api.h:2158
tuple data
Definition: ovdump.py:103
void * rt_band_get_data(rt_band band)
Get pointer to raster band data.
Definition: rt_api.c:1710
uint32_t count
Definition: rt_api.h:2342
rt_pixtype pixtype
Definition: rt_api.h:2239
Definition: rt_api.h:184
uint16_t height
Definition: rt_api.h:2242
Definition: rt_api.h:173
int rt_band_get_isnodata_flag(rt_band band)
Get isnodata flag value.
Definition: rt_api.c:2042
double value
Definition: rt_api.h:2341
#define RASTER_DEBUG(level, msg)
Definition: rt_api.h:281
void rtwarn(const char *fmt,...)
Definition: rt_api.c:920
rt_pixtype
Definition: rt_api.h:172
#define RASTER_DEBUGF(level, msg,...)
Definition: rt_api.h:285
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
Definition: rt_api.c:3058
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
Definition: rt_api.c:2549
int count
Definition: genraster.py:57
#define FLT_EQ(x, y)
Definition: rt_api.h:2159
uint16_t width
Definition: rt_api.h:2241
tuple x
Definition: pixval.py:53
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
double percent
Definition: rt_api.h:2343
#define FALSE
Definition: dbfopen.c:169
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
Definition: rt_api.c:2002
tuple y
Definition: pixval.py:54
#define ROUND(x, y)
Definition: rt_api.h:2166
void * rtrealloc(void *mem, size_t size)
Definition: rt_api.c:875

Here is the call graph for this function:

Here is the caller graph for this function: