PostGIS 3.7.0dev-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 1534 of file rt_mapalgebra.c.

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