PostGIS 3.0.6dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ rt_raster_colormap()

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 1523 of file rt_mapalgebra.c.

1526 {
1527 _rti_colormap_arg arg = NULL;
1528 rt_raster rtnraster = NULL;
1529 rt_band band = NULL;
1530 int i = 0;
1531 int j = 0;
1532 int k = 0;
1533
1534 assert(colormap != NULL);
1535
1536 /* empty raster */
1537 if (rt_raster_is_empty(raster))
1538 return NULL;
1539
1540 /* no colormap entries */
1541 if (colormap->nentry < 1) {
1542 rterror("rt_raster_colormap: colormap must have at least one entry");
1543 return NULL;
1544 }
1545
1546 /* nband is valid */
1547 if (!rt_raster_has_band(raster, nband)) {
1548 rterror("rt_raster_colormap: raster has no band at index %d", nband);
1549 return NULL;
1550 }
1551
1552 band = rt_raster_get_band(raster, nband);
1553 if (band == NULL) {
1554 rterror("rt_raster_colormap: Could not get band at index %d", nband);
1555 return NULL;
1556 }
1557
1558 /* init internal variables */
1559 arg = _rti_colormap_arg_init(raster);
1560 if (arg == NULL) {
1561 rterror("rt_raster_colormap: Could not initialize internal variables");
1562 return NULL;
1563 }
1564
1565 /* handle NODATA */
1566 if (rt_band_get_hasnodata_flag(band)) {
1567 arg->hasnodata = 1;
1568 rt_band_get_nodata(band, &(arg->nodataval));
1569 }
1570
1571 /* # of colors */
1572 if (colormap->ncolor < 1) {
1573 rterror("rt_raster_colormap: At least one color must be provided");
1575 return NULL;
1576 }
1577 else if (colormap->ncolor > 4) {
1578 rtinfo("More than four colors indicated. Using only the first four colors");
1579 colormap->ncolor = 4;
1580 }
1581
1582 /* find non-NODATA entries */
1583 arg->npos = 0;
1584 arg->pos = rtalloc(sizeof(uint16_t) * colormap->nentry);
1585 if (arg->pos == NULL) {
1586 rterror("rt_raster_colormap: Could not allocate memory for valid entries");
1588 return NULL;
1589 }
1590 for (i = 0, j = 0; i < colormap->nentry; i++) {
1591 /* special handling for NODATA entries */
1592 if (colormap->entry[i].isnodata) {
1593 /* first NODATA entry found, use it */
1594 if (arg->nodataentry == NULL)
1595 arg->nodataentry = &(colormap->entry[i]);
1596 else
1597 rtwarn("More than one colormap entry found for NODATA value. Only using first NOTDATA entry");
1598
1599 continue;
1600 }
1601
1602 (arg->npos)++;
1603 arg->pos[j++] = i;
1604 }
1605
1606 /* INTERPOLATE and only one non-NODATA entry */
1607 if (colormap->method == CM_INTERPOLATE && arg->npos < 2) {
1608 rtwarn("Method INTERPOLATE requires at least two non-NODATA colormap entries. Using NEAREST instead");
1609 colormap->method = CM_NEAREST;
1610 }
1611
1612 /* NODATA entry but band has no NODATA value */
1613 if (!arg->hasnodata && arg->nodataentry != NULL) {
1614 rtinfo("Band at index %d has no NODATA value. Ignoring NODATA entry", nband);
1615 arg->nodataentry = NULL;
1616 }
1617
1618 /* allocate expr */
1619 arg->nexpr = arg->npos;
1620
1621 /* INTERPOLATE needs one less than the number of entries */
1622 if (colormap->method == CM_INTERPOLATE)
1623 arg->nexpr -= 1;
1624 /* EXACT requires a no matching expression */
1625 else if (colormap->method == CM_EXACT)
1626 arg->nexpr += 1;
1627
1628 /* NODATA entry exists, add expression */
1629 if (arg->nodataentry != NULL)
1630 arg->nexpr += 1;
1631 arg->expr = rtalloc(sizeof(rt_reclassexpr) * arg->nexpr);
1632 if (arg->expr == NULL) {
1633 rterror("rt_raster_colormap: Could not allocate memory for reclass expressions");
1635 return NULL;
1636 }
1637 RASTER_DEBUGF(4, "nexpr = %d", arg->nexpr);
1638 RASTER_DEBUGF(4, "expr @ %p", arg->expr);
1639
1640 for (i = 0; i < arg->nexpr; i++) {
1641 arg->expr[i] = rtalloc(sizeof(struct rt_reclassexpr_t));
1642 if (arg->expr[i] == NULL) {
1643 rterror("rt_raster_colormap: Could not allocate memory for reclass expression");
1645 return NULL;
1646 }
1647 }
1648
1649 /* reclassify bands */
1650 /* by # of colors */
1651 for (i = 0; i < colormap->ncolor; i++) {
1652 k = 0;
1653
1654 /* handle NODATA entry first */
1655 if (arg->nodataentry != NULL) {
1656 arg->expr[k]->src.min = arg->nodataentry->value;
1657 arg->expr[k]->src.max = arg->nodataentry->value;
1658 arg->expr[k]->src.inc_min = 1;
1659 arg->expr[k]->src.inc_max = 1;
1660 arg->expr[k]->src.exc_min = 0;
1661 arg->expr[k]->src.exc_max = 0;
1662
1663 arg->expr[k]->dst.min = arg->nodataentry->color[i];
1664 arg->expr[k]->dst.max = arg->nodataentry->color[i];
1665
1666 arg->expr[k]->dst.inc_min = 1;
1667 arg->expr[k]->dst.inc_max = 1;
1668 arg->expr[k]->dst.exc_min = 0;
1669 arg->expr[k]->dst.exc_max = 0;
1670
1671 RASTER_DEBUGF(4, "NODATA expr[%d]->src (min, max, in, ix, en, ex) = (%f, %f, %d, %d, %d, %d)",
1672 k,
1673 arg->expr[k]->src.min,
1674 arg->expr[k]->src.max,
1675 arg->expr[k]->src.inc_min,
1676 arg->expr[k]->src.inc_max,
1677 arg->expr[k]->src.exc_min,
1678 arg->expr[k]->src.exc_max
1679 );
1680 RASTER_DEBUGF(4, "NODATA expr[%d]->dst (min, max, in, ix, en, ex) = (%f, %f, %d, %d, %d, %d)",
1681 k,
1682 arg->expr[k]->dst.min,
1683 arg->expr[k]->dst.max,
1684 arg->expr[k]->dst.inc_min,
1685 arg->expr[k]->dst.inc_max,
1686 arg->expr[k]->dst.exc_min,
1687 arg->expr[k]->dst.exc_max
1688 );
1689
1690 k++;
1691 }
1692
1693 /* by non-NODATA entry */
1694 for (j = 0; j < arg->npos; j++) {
1695 if (colormap->method == CM_INTERPOLATE) {
1696 if (j == arg->npos - 1)
1697 continue;
1698
1699 arg->expr[k]->src.min = colormap->entry[arg->pos[j + 1]].value;
1700 arg->expr[k]->src.inc_min = 1;
1701 arg->expr[k]->src.exc_min = 0;
1702
1703 arg->expr[k]->src.max = colormap->entry[arg->pos[j]].value;
1704 arg->expr[k]->src.inc_max = 1;
1705 arg->expr[k]->src.exc_max = 0;
1706
1707 arg->expr[k]->dst.min = colormap->entry[arg->pos[j + 1]].color[i];
1708 arg->expr[k]->dst.max = colormap->entry[arg->pos[j]].color[i];
1709
1710 arg->expr[k]->dst.inc_min = 1;
1711 arg->expr[k]->dst.exc_min = 0;
1712
1713 arg->expr[k]->dst.inc_max = 1;
1714 arg->expr[k]->dst.exc_max = 0;
1715 }
1716 else if (colormap->method == CM_NEAREST) {
1717
1718 /* NOT last entry */
1719 if (j != arg->npos - 1) {
1720 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;
1721 arg->expr[k]->src.inc_min = 0;
1722 arg->expr[k]->src.exc_min = 0;
1723 }
1724 /* last entry */
1725 else {
1726 arg->expr[k]->src.min = colormap->entry[arg->pos[j]].value;
1727 arg->expr[k]->src.inc_min = 1;
1728 arg->expr[k]->src.exc_min = 1;
1729 }
1730
1731 /* NOT first entry */
1732 if (j > 0) {
1733 arg->expr[k]->src.max = arg->expr[k - 1]->src.min;
1734 arg->expr[k]->src.inc_max = 1;
1735 arg->expr[k]->src.exc_max = 0;
1736 }
1737 /* first entry */
1738 else {
1739 arg->expr[k]->src.max = colormap->entry[arg->pos[j]].value;
1740 arg->expr[k]->src.inc_max = 1;
1741 arg->expr[k]->src.exc_max = 1;
1742 }
1743
1744 arg->expr[k]->dst.min = colormap->entry[arg->pos[j]].color[i];
1745 arg->expr[k]->dst.inc_min = 1;
1746 arg->expr[k]->dst.exc_min = 0;
1747
1748 arg->expr[k]->dst.max = colormap->entry[arg->pos[j]].color[i];
1749 arg->expr[k]->dst.inc_max = 1;
1750 arg->expr[k]->dst.exc_max = 0;
1751 }
1752 else if (colormap->method == CM_EXACT) {
1753 arg->expr[k]->src.min = colormap->entry[arg->pos[j]].value;
1754 arg->expr[k]->src.inc_min = 1;
1755 arg->expr[k]->src.exc_min = 0;
1756
1757 arg->expr[k]->src.max = colormap->entry[arg->pos[j]].value;
1758 arg->expr[k]->src.inc_max = 1;
1759 arg->expr[k]->src.exc_max = 0;
1760
1761 arg->expr[k]->dst.min = colormap->entry[arg->pos[j]].color[i];
1762 arg->expr[k]->dst.inc_min = 1;
1763 arg->expr[k]->dst.exc_min = 0;
1764
1765 arg->expr[k]->dst.max = colormap->entry[arg->pos[j]].color[i];
1766 arg->expr[k]->dst.inc_max = 1;
1767 arg->expr[k]->dst.exc_max = 0;
1768 }
1769
1770 RASTER_DEBUGF(4, "expr[%d]->src (min, max, in, ix, en, ex) = (%f, %f, %d, %d, %d, %d)",
1771 k,
1772 arg->expr[k]->src.min,
1773 arg->expr[k]->src.max,
1774 arg->expr[k]->src.inc_min,
1775 arg->expr[k]->src.inc_max,
1776 arg->expr[k]->src.exc_min,
1777 arg->expr[k]->src.exc_max
1778 );
1779
1780 RASTER_DEBUGF(4, "expr[%d]->dst (min, max, in, ix, en, ex) = (%f, %f, %d, %d, %d, %d)",
1781 k,
1782 arg->expr[k]->dst.min,
1783 arg->expr[k]->dst.max,
1784 arg->expr[k]->dst.inc_min,
1785 arg->expr[k]->dst.inc_max,
1786 arg->expr[k]->dst.exc_min,
1787 arg->expr[k]->dst.exc_max
1788 );
1789
1790 k++;
1791 }
1792
1793 /* EXACT has one last expression for catching all uncaught values */
1794 if (colormap->method == CM_EXACT) {
1795 arg->expr[k]->src.min = 0;
1796 arg->expr[k]->src.inc_min = 1;
1797 arg->expr[k]->src.exc_min = 1;
1798
1799 arg->expr[k]->src.max = 0;
1800 arg->expr[k]->src.inc_max = 1;
1801 arg->expr[k]->src.exc_max = 1;
1802
1803 arg->expr[k]->dst.min = 0;
1804 arg->expr[k]->dst.inc_min = 1;
1805 arg->expr[k]->dst.exc_min = 0;
1806
1807 arg->expr[k]->dst.max = 0;
1808 arg->expr[k]->dst.inc_max = 1;
1809 arg->expr[k]->dst.exc_max = 0;
1810
1811 RASTER_DEBUGF(4, "expr[%d]->src (min, max, in, ix, en, ex) = (%f, %f, %d, %d, %d, %d)",
1812 k,
1813 arg->expr[k]->src.min,
1814 arg->expr[k]->src.max,
1815 arg->expr[k]->src.inc_min,
1816 arg->expr[k]->src.inc_max,
1817 arg->expr[k]->src.exc_min,
1818 arg->expr[k]->src.exc_max
1819 );
1820
1821 RASTER_DEBUGF(4, "expr[%d]->dst (min, max, in, ix, en, ex) = (%f, %f, %d, %d, %d, %d)",
1822 k,
1823 arg->expr[k]->dst.min,
1824 arg->expr[k]->dst.max,
1825 arg->expr[k]->dst.inc_min,
1826 arg->expr[k]->dst.inc_max,
1827 arg->expr[k]->dst.exc_min,
1828 arg->expr[k]->dst.exc_max
1829 );
1830
1831 k++;
1832 }
1833
1834 /* call rt_band_reclass */
1835 arg->band = rt_band_reclass(band, PT_8BUI, 0, 0, arg->expr, arg->nexpr);
1836 if (arg->band == NULL) {
1837 rterror("rt_raster_colormap: Could not reclassify band");
1839 return NULL;
1840 }
1841
1842 /* add reclassified band to raster */
1843 if (rt_raster_add_band(arg->raster, arg->band, rt_raster_get_num_bands(arg->raster)) < 0) {
1844 rterror("rt_raster_colormap: Could not add reclassified band to output raster");
1846 return NULL;
1847 }
1848 }
1849
1850 rtnraster = arg->raster;
1851 arg->raster = NULL;
1853
1854 return rtnraster;
1855}
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_DEBUGF(level, msg,...)
Definition librtcore.h:299
void rtinfo(const char *fmt,...)
Definition rt_context.c:211
int rt_raster_add_band(rt_raster raster, rt_band band, int index)
Add band data to a raster.
Definition rt_raster.c:405
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
Definition rt_band.c:674
@ PT_8BUI
Definition librtcore.h:190
int rt_raster_has_band(rt_raster raster, int nband)
Return TRUE if the raster has a band of this number.
Definition rt_raster.c:1342
void rtwarn(const char *fmt,...)
Definition rt_context.c:224
uint16_t rt_raster_get_num_bands(rt_raster raster)
Definition rt_raster.c:372
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
Definition rt_band.c:1730
int rt_raster_is_empty(rt_raster raster)
Return TRUE if the raster is empty.
Definition rt_raster.c:1329
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
Definition rt_raster.c:381
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.
static void _rti_colormap_arg_destroy(_rti_colormap_arg arg)
static _rti_colormap_arg _rti_colormap_arg_init(rt_raster raster)
rt_colormap_entry nodataentry
rt_reclassexpr * expr
uint8_t color[4]
Definition librtcore.h:2485
double value
Definition librtcore.h:2484
int isnodata
Definition librtcore.h:2483
rt_colormap_entry entry
Definition librtcore.h:2497
enum rt_colormap_t::@9 method
uint16_t nentry
Definition librtcore.h:2496
struct rt_reclassexpr_t::rt_reclassrange src
struct rt_reclassexpr_t::rt_reclassrange dst

References _rti_colormap_arg_destroy(), _rti_colormap_arg_init(), _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().

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