PostGIS  2.4.9dev-r@@SVN_REVISION@@

◆ rt_band_get_value_count()

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 1608 of file rt_statistics.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().

1612  {
1613  rt_valuecount vcnts = NULL;
1614  rt_pixtype pixtype = PT_END;
1615  uint8_t *data = NULL;
1616  double nodata = 0;
1617 
1618  int scale = 0;
1619  int doround = 0;
1620  double tmpd = 0;
1621  int i = 0;
1622 
1623  uint32_t x = 0;
1624  uint32_t y = 0;
1625  int rtn;
1626  double pxlval;
1627  int isnodata = 0;
1628  double rpxlval;
1629  uint32_t total = 0;
1630  int vcnts_count = 0;
1631  int new_valuecount = 0;
1632 
1633 #if POSTGIS_DEBUG_LEVEL > 0
1634  clock_t start, stop;
1635  double elapsed = 0;
1636 #endif
1637 
1638  RASTER_DEBUG(3, "starting");
1639 #if POSTGIS_DEBUG_LEVEL > 0
1640  start = clock();
1641 #endif
1642 
1643  assert(NULL != band);
1644  assert(NULL != rtn_count);
1645 
1646  data = rt_band_get_data(band);
1647  if (data == NULL) {
1648  rterror("rt_band_get_summary_stats: Cannot get band data");
1649  return NULL;
1650  }
1651 
1652  pixtype = band->pixtype;
1653 
1654  if (rt_band_get_hasnodata_flag(band)) {
1655  rt_band_get_nodata(band, &nodata);
1656  RASTER_DEBUGF(3, "hasnodata, nodataval = 1, %f", nodata);
1657  }
1658  else {
1659  exclude_nodata_value = 0;
1660  RASTER_DEBUG(3, "hasnodata, nodataval = 0, 0");
1661  }
1662 
1663  RASTER_DEBUGF(3, "exclude_nodata_value = %d", exclude_nodata_value);
1664 
1665  /* process roundto */
1666  if (roundto < 0 || FLT_EQ(roundto, 0.0)) {
1667  roundto = 0;
1668  scale = 0;
1669  }
1670  /* tenths, hundredths, thousandths, etc */
1671  else if (roundto < 1) {
1672  switch (pixtype) {
1673  /* integer band types don't have digits after the decimal place */
1674  case PT_1BB:
1675  case PT_2BUI:
1676  case PT_4BUI:
1677  case PT_8BSI:
1678  case PT_8BUI:
1679  case PT_16BSI:
1680  case PT_16BUI:
1681  case PT_32BSI:
1682  case PT_32BUI:
1683  roundto = 0;
1684  break;
1685  /* floating points, check the rounding */
1686  case PT_32BF:
1687  case PT_64BF:
1688  for (scale = 0; scale <= 20; scale++) {
1689  tmpd = roundto * pow(10, scale);
1690  if (FLT_EQ((tmpd - ((int) tmpd)), 0.0)) break;
1691  }
1692  break;
1693  case PT_END:
1694  break;
1695  }
1696  }
1697  /* ones, tens, hundreds, etc */
1698  else {
1699  for (scale = 0; scale >= -20; scale--) {
1700  tmpd = roundto * pow(10, scale);
1701  if (tmpd < 1 || FLT_EQ(tmpd, 1.0)) {
1702  if (scale == 0) doround = 1;
1703  break;
1704  }
1705  }
1706  }
1707 
1708  if (scale != 0 || doround)
1709  doround = 1;
1710  else
1711  doround = 0;
1712  RASTER_DEBUGF(3, "scale = %d", scale);
1713  RASTER_DEBUGF(3, "doround = %d", doround);
1714 
1715  /* process search_values */
1716  if (search_values_count > 0 && NULL != search_values) {
1717  vcnts = (rt_valuecount) rtalloc(sizeof(struct rt_valuecount_t) * search_values_count);
1718  if (NULL == vcnts) {
1719  rterror("rt_band_get_count_of_values: Could not allocate memory for value counts");
1720  *rtn_count = 0;
1721  return NULL;
1722  }
1723 
1724  for (i = 0; i < search_values_count; i++) {
1725  vcnts[i].count = 0;
1726  vcnts[i].percent = 0;
1727  if (!doround)
1728  vcnts[i].value = search_values[i];
1729  else
1730  vcnts[i].value = ROUND(search_values[i], scale);
1731  }
1732  vcnts_count = i;
1733  }
1734  else
1735  search_values_count = 0;
1736  RASTER_DEBUGF(3, "search_values_count = %d", search_values_count);
1737 
1738  /* entire band is nodata */
1739  if (rt_band_get_isnodata_flag(band) != FALSE) {
1740  if (exclude_nodata_value) {
1741  rtwarn("All pixels of band have the NODATA value");
1742  return NULL;
1743  }
1744  else {
1745  if (search_values_count > 0) {
1746  /* check for nodata match */
1747  for (i = 0; i < search_values_count; i++) {
1748  if (!doround)
1749  tmpd = nodata;
1750  else
1751  tmpd = ROUND(nodata, scale);
1752 
1753  if (FLT_NEQ(tmpd, vcnts[i].value))
1754  continue;
1755 
1756  vcnts[i].count = band->width * band->height;
1757  if (NULL != rtn_total) *rtn_total = vcnts[i].count;
1758  vcnts->percent = 1.0;
1759  }
1760 
1761  *rtn_count = vcnts_count;
1762  }
1763  /* no defined search values */
1764  else {
1765  vcnts = (rt_valuecount) rtalloc(sizeof(struct rt_valuecount_t));
1766  if (NULL == vcnts) {
1767  rterror("rt_band_get_count_of_values: Could not allocate memory for value counts");
1768  *rtn_count = 0;
1769  return NULL;
1770  }
1771 
1772  vcnts->value = nodata;
1773  vcnts->count = band->width * band->height;
1774  if (NULL != rtn_total) *rtn_total = vcnts[i].count;
1775  vcnts->percent = 1.0;
1776 
1777  *rtn_count = 1;
1778  }
1779 
1780  return vcnts;
1781  }
1782  }
1783 
1784  for (x = 0; x < band->width; x++) {
1785  for (y = 0; y < band->height; y++) {
1786  rtn = rt_band_get_pixel(band, x, y, &pxlval, &isnodata);
1787 
1788  /* error getting value, continue */
1789  if (rtn != ES_NONE)
1790  continue;
1791 
1792  if (!exclude_nodata_value || (exclude_nodata_value && !isnodata)) {
1793  total++;
1794  if (doround) {
1795  rpxlval = ROUND(pxlval, scale);
1796  }
1797  else
1798  rpxlval = pxlval;
1799  RASTER_DEBUGF(5, "(pxlval, rpxlval) => (%0.6f, %0.6f)", pxlval, rpxlval);
1800 
1801  new_valuecount = 1;
1802  /* search for match in existing valuecounts */
1803  for (i = 0; i < vcnts_count; i++) {
1804  /* match found */
1805  if (FLT_EQ(vcnts[i].value, rpxlval)) {
1806  vcnts[i].count++;
1807  new_valuecount = 0;
1808  RASTER_DEBUGF(5, "(value, count) => (%0.6f, %d)", vcnts[i].value, vcnts[i].count);
1809  break;
1810  }
1811  }
1812 
1813  /*
1814  don't add new valuecount either because
1815  - no need for new one
1816  - user-defined search values
1817  */
1818  if (!new_valuecount || search_values_count > 0) continue;
1819 
1820  /* add new valuecount */
1821  vcnts = rtrealloc(vcnts, sizeof(struct rt_valuecount_t) * (vcnts_count + 1));
1822  if (NULL == vcnts) {
1823  rterror("rt_band_get_count_of_values: Could not allocate memory for value counts");
1824  *rtn_count = 0;
1825  return NULL;
1826  }
1827 
1828  vcnts[vcnts_count].value = rpxlval;
1829  vcnts[vcnts_count].count = 1;
1830  vcnts[vcnts_count].percent = 0;
1831  RASTER_DEBUGF(5, "(value, count) => (%0.6f, %d)", vcnts[vcnts_count].value, vcnts[vcnts_count].count);
1832  vcnts_count++;
1833  }
1834  }
1835  }
1836 
1837 #if POSTGIS_DEBUG_LEVEL > 0
1838  stop = clock();
1839  elapsed = ((double) (stop - start)) / CLOCKS_PER_SEC;
1840  RASTER_DEBUGF(3, "elapsed time = %0.4f", elapsed);
1841 #endif
1842 
1843  for (i = 0; i < vcnts_count; i++) {
1844  vcnts[i].percent = (double) vcnts[i].count / total;
1845  RASTER_DEBUGF(5, "(value, count) => (%0.6f, %d)", vcnts[i].value, vcnts[i].count);
1846  }
1847 
1848  RASTER_DEBUG(3, "done");
1849  if (NULL != rtn_total) *rtn_total = total;
1850  *rtn_count = vcnts_count;
1851  return vcnts;
1852 }
uint32_t count
Definition: librtcore.h:2376
rt_pixtype pixtype
Definition: librtcore.h:2265
#define FLT_EQ(x, y)
Definition: librtcore.h:2185
void rterror(const char *fmt,...)
Wrappers used for reporting errors and info.
Definition: rt_context.c:199
void * rtalloc(size_t size)
Wrappers used for managing memory.
Definition: rt_context.c:171
data
Definition: ovdump.py:103
void * rtrealloc(void *mem, size_t size)
Definition: rt_context.c:179
uint16_t height
Definition: librtcore.h:2268
rt_pixtype
Definition: librtcore.h:185
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
Definition: rt_band.c:1597
unsigned int uint32_t
Definition: uthash.h:78
void rtwarn(const char *fmt,...)
Definition: rt_context.c:224
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
Definition: rt_band.c:1088
#define FLT_NEQ(x, y)
Definition: librtcore.h:2184
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
Definition: rt_band.c:541
int count
Definition: genraster.py:56
void * rt_band_get_data(rt_band band)
Get pointer to raster band data.
Definition: rt_band.c:302
#define RASTER_DEBUGF(level, msg,...)
Definition: librtcore.h:299
uint16_t width
Definition: librtcore.h:2267
struct rt_valuecount_t * rt_valuecount
Definition: librtcore.h:153
#define ROUND(x, y)
Definition: librtcore.h:2192
#define FALSE
Definition: dbfopen.c:168
#define RASTER_DEBUG(level, msg)
Definition: librtcore.h:295
int rt_band_get_isnodata_flag(rt_band band)
Get isnodata flag value.
Definition: rt_band.c:581
int value
Definition: genraster.py:61
unsigned char uint8_t
Definition: uthash.h:79
Here is the call graph for this function:
Here is the caller graph for this function: