PostGIS  2.5.7dev-r@@SVN_REVISION@@

◆ rt_band_get_nearest_pixel()

uint32_t rt_band_get_nearest_pixel ( rt_band  band,
int  x,
int  y,
uint16_t  distancex,
uint16_t  distancey,
int  exclude_nodata_value,
rt_pixel npixels 
)

Get nearest pixel(s) with value (not NODATA) to specified pixel.

Parameters
band: the band to get nearest pixel(s) from
x: the column of the pixel (0-based)
y: the line of the pixel (0-based)
distancex: the number of pixels around the specified pixel along the X axis
distancey: the number of pixels around the specified pixel along the Y axis
exclude_nodata_value: if non-zero, ignore nodata values to check for pixels with value
npixels: return set of rt_pixel object or NULL
Returns
-1 on error, otherwise the number of rt_pixel objects in npixels

Definition at line 1374 of file rt_band.c.

1380  {
1381  rt_pixel npixel = NULL;
1382  int extent[4] = {0};
1383  int max_extent[4] = {0};
1384  int d0 = 0;
1385  uint32_t distance[2] = {0};
1386  uint32_t _d[2] = {0};
1387  uint32_t i = 0;
1388  uint32_t j = 0;
1389  uint32_t k = 0;
1390  int _max = 0;
1391  int _x = 0;
1392  int _y = 0;
1393  int *_min = NULL;
1394  double pixval = 0;
1395  double minval = 0;
1396  uint32_t count = 0;
1397  int isnodata = 0;
1398 
1399  int inextent = 0;
1400 
1401  assert(NULL != band);
1402  assert(NULL != npixels);
1403 
1404  RASTER_DEBUG(3, "Starting");
1405 
1406  /* process distance */
1407  distance[0] = distancex;
1408  distance[1] = distancey;
1409 
1410  /* no distance, means get nearest pixels and return */
1411  if (!distance[0] && !distance[1])
1412  d0 = 1;
1413 
1414  RASTER_DEBUGF(4, "Selected pixel: %d x %d", x, y);
1415  RASTER_DEBUGF(4, "Distances: %d x %d", distance[0], distance[1]);
1416 
1417  /* shortcuts if outside band extent */
1418  if (
1419  exclude_nodata_value && (
1420  (x < 0 || x > band->width) ||
1421  (y < 0 || y > band->height)
1422  )
1423  ) {
1424  /* no distances specified, jump to pixel close to extent */
1425  if (d0) {
1426  if (x < 0)
1427  x = -1;
1428  else if (x > band->width)
1429  x = band->width;
1430 
1431  if (y < 0)
1432  y = -1;
1433  else if (y > band->height)
1434  y = band->height;
1435 
1436  RASTER_DEBUGF(4, "Moved selected pixel: %d x %d", x, y);
1437  }
1438  /*
1439  distances specified
1440  if distances won't capture extent of band, return 0
1441  */
1442  else if (
1443  ((x < 0 && (uint32_t) abs(x) > distance[0]) || (x - band->width >= (int)distance[0])) ||
1444  ((y < 0 && (uint32_t) abs(y) > distance[1]) || (y - band->height >= (int)distance[1]))
1445  ) {
1446  RASTER_DEBUG(4, "No nearest pixels possible for provided pixel and distances");
1447  return 0;
1448  }
1449  }
1450 
1451  /* no NODATA, exclude is FALSE */
1452  if (!band->hasnodata)
1453  exclude_nodata_value = FALSE;
1454  /* band is NODATA and excluding NODATA */
1455  else if (exclude_nodata_value && band->isnodata) {
1456  RASTER_DEBUG(4, "No nearest pixels possible as band is NODATA and excluding NODATA values");
1457  return 0;
1458  }
1459 
1460  /* determine the maximum distance to prevent an infinite loop */
1461  if (d0) {
1462  int a, b;
1463 
1464  /* X axis */
1465  a = abs(x);
1466  b = abs(x - band->width);
1467 
1468  if (a > b)
1469  distance[0] = a;
1470  else
1471  distance[0] = b;
1472 
1473  /* Y axis */
1474  a = abs(y);
1475  b = abs(y - band->height);
1476  if (a > b)
1477  distance[1] = a;
1478  else
1479  distance[1] = b;
1480 
1481  RASTER_DEBUGF(4, "Maximum distances: %d x %d", distance[0], distance[1]);
1482  }
1483 
1484  /* minimum possible value for pixel type */
1485  minval = rt_pixtype_get_min_value(band->pixtype);
1486  RASTER_DEBUGF(4, "pixtype: %s", rt_pixtype_name(band->pixtype));
1487  RASTER_DEBUGF(4, "minval: %f", minval);
1488 
1489  /* set variables */
1490  count = 0;
1491  *npixels = NULL;
1492 
1493  /* maximum extent */
1494  max_extent[0] = x - distance[0]; /* min X */
1495  max_extent[1] = y - distance[1]; /* min Y */
1496  max_extent[2] = x + distance[0]; /* max X */
1497  max_extent[3] = y + distance[1]; /* max Y */
1498  RASTER_DEBUGF(4, "Maximum Extent: (%d, %d, %d, %d)",
1499  max_extent[0], max_extent[1], max_extent[2], max_extent[3]);
1500 
1501  _d[0] = 0;
1502  _d[1] = 0;
1503  do {
1504  _d[0]++;
1505  _d[1]++;
1506 
1507  extent[0] = x - _d[0]; /* min x */
1508  extent[1] = y - _d[1]; /* min y */
1509  extent[2] = x + _d[0]; /* max x */
1510  extent[3] = y + _d[1]; /* max y */
1511 
1512  RASTER_DEBUGF(4, "Processing distances: %d x %d", _d[0], _d[1]);
1513  RASTER_DEBUGF(4, "Extent: (%d, %d, %d, %d)",
1514  extent[0], extent[1], extent[2], extent[3]);
1515 
1516  for (i = 0; i < 2; i++) {
1517 
1518  /* by row */
1519  if (i < 1)
1520  _max = extent[2] - extent[0] + 1;
1521  /* by column */
1522  else
1523  _max = extent[3] - extent[1] + 1;
1524  _max = abs(_max);
1525 
1526  for (j = 0; j < 2; j++) {
1527  /* by row */
1528  if (i < 1) {
1529  _x = extent[0];
1530  _min = &_x;
1531 
1532  /* top row */
1533  if (j < 1)
1534  _y = extent[1];
1535  /* bottom row */
1536  else
1537  _y = extent[3];
1538  }
1539  /* by column */
1540  else {
1541  _y = extent[1] + 1;
1542  _min = &_y;
1543 
1544  /* left column */
1545  if (j < 1) {
1546  _x = extent[0];
1547  _max -= 2;
1548  }
1549  /* right column */
1550  else
1551  _x = extent[2];
1552  }
1553 
1554  RASTER_DEBUGF(4, "_min, _max: %d, %d", *_min, _max);
1555  for (k = 0; k < (uint32_t) _max; k++) {
1556  /* check that _x and _y are not outside max extent */
1557  if (
1558  _x < max_extent[0] || _x > max_extent[2] ||
1559  _y < max_extent[1] || _y > max_extent[3]
1560  ) {
1561  (*_min)++;
1562  continue;
1563  }
1564 
1565  /* outside band extent, set to NODATA */
1566  if (
1567  (_x < 0 || _x >= band->width) ||
1568  (_y < 0 || _y >= band->height)
1569  ) {
1570  /* no NODATA, set to minimum possible value */
1571  if (!band->hasnodata)
1572  pixval = minval;
1573  /* has NODATA, use NODATA */
1574  else
1575  pixval = band->nodataval;
1576  RASTER_DEBUGF(4, "NODATA pixel outside band extent: (x, y, val) = (%d, %d, %f)", _x, _y, pixval);
1577  inextent = 0;
1578  isnodata = 1;
1579  }
1580  else {
1581  if (rt_band_get_pixel(
1582  band,
1583  _x, _y,
1584  &pixval,
1585  &isnodata
1586  ) != ES_NONE) {
1587  rterror("rt_band_get_nearest_pixel: Could not get pixel value");
1588  if (count) rtdealloc(*npixels);
1589  return -1;
1590  }
1591  RASTER_DEBUGF(4, "Pixel: (x, y, val) = (%d, %d, %f)", _x, _y, pixval);
1592  inextent = 1;
1593  }
1594 
1595  /* use pixval? */
1596  if (!exclude_nodata_value || (exclude_nodata_value && !isnodata)) {
1597  /* add pixel to result set */
1598  RASTER_DEBUGF(4, "Adding pixel to set of nearest pixels: (x, y, val) = (%d, %d, %f)", _x, _y, pixval);
1599  count++;
1600 
1601  if (*npixels == NULL)
1602  *npixels = (rt_pixel) rtalloc(sizeof(struct rt_pixel_t) * count);
1603  else
1604  *npixels = (rt_pixel) rtrealloc(*npixels, sizeof(struct rt_pixel_t) * count);
1605  if (*npixels == NULL) {
1606  rterror("rt_band_get_nearest_pixel: Could not allocate memory for nearest pixel(s)");
1607  return -1;
1608  }
1609 
1610  npixel = &((*npixels)[count - 1]);
1611  npixel->x = _x;
1612  npixel->y = _y;
1613  npixel->value = pixval;
1614 
1615  /* special case for when outside band extent */
1616  if (!inextent && !band->hasnodata)
1617  npixel->nodata = 1;
1618  else
1619  npixel->nodata = 0;
1620  }
1621 
1622  (*_min)++;
1623  }
1624  }
1625  }
1626 
1627  /* distance threshholds met */
1628  if (_d[0] >= distance[0] && _d[1] >= distance[1])
1629  break;
1630  else if (d0 && count)
1631  break;
1632  }
1633  while (1);
1634 
1635  RASTER_DEBUGF(3, "Nearest pixels in return: %d", count);
1636 
1637  return count;
1638 }
#define FALSE
Definition: dbfopen.c:168
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
#define RASTER_DEBUG(level, msg)
Definition: librtcore.h:295
#define RASTER_DEBUGF(level, msg,...)
Definition: librtcore.h:299
double rt_pixtype_get_min_value(rt_pixtype pixtype)
Return minimum value possible for pixel type.
Definition: rt_pixel.c:148
struct rt_pixel_t * rt_pixel
Definition: librtcore.h:147
@ ES_NONE
Definition: librtcore.h:180
void * rtrealloc(void *mem, size_t size)
Definition: rt_context.c:179
const char * rt_pixtype_name(rt_pixtype pixtype)
Definition: rt_pixel.c:110
void rtdealloc(void *mem)
Definition: rt_context.c:186
Datum distance(PG_FUNCTION_ARGS)
int count
Definition: genraster.py:56
band
Definition: ovdump.py:57
pixval
Definition: pixval.py:93
Definition: pixval.py:1
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
Definition: rt_band.c:1221
double value
Definition: librtcore.h:2338
uint8_t nodata
Definition: librtcore.h:2337
unsigned int uint32_t
Definition: uthash.h:78

References ovdump::band, genraster::count, distance(), ES_NONE, FALSE, rt_pixel_t::nodata, pixval::pixval, RASTER_DEBUG, RASTER_DEBUGF, rt_band_get_pixel(), rt_pixtype_get_min_value(), rt_pixtype_name(), rtalloc(), rtdealloc(), rterror(), rtrealloc(), rt_pixel_t::value, rt_pixel_t::x, pixval::x, rt_pixel_t::y, and pixval::y.

Referenced by RASTER_nearestValue(), RASTER_neighborhood(), rt_raster_iterator(), test_band_get_nearest_pixel(), and test_pixel_set_to_array().

Here is the call graph for this function:
Here is the caller graph for this function: