Skip to content

Commit a25c1c7

Browse files
larochjdoug-walker
authored andcommitted
RGB to HSY fixed functions using CPU (#17)
1 parent d658e70 commit a25c1c7

File tree

5 files changed

+617
-18
lines changed

5 files changed

+617
-18
lines changed

src/OpenColorIO/ops/fixedfunction/FixedFunctionOpCPU.cpp

Lines changed: 290 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,66 @@ class Renderer_HSV_TO_RGB : public OpCPU
238238
void apply(const void * inImg, void * outImg, long numPixels) const override;
239239
};
240240

241+
class Renderer_RGB_TO_HSY_LOG : public OpCPU
242+
{
243+
const float MIN_0 = -0.1f;
244+
public:
245+
Renderer_RGB_TO_HSY_LOG() = delete;
246+
explicit Renderer_RGB_TO_HSY_LOG(ConstFixedFunctionOpDataRcPtr & data);
247+
248+
void apply(const void * inImg, void * outImg, long numPixels) const override;
249+
};
250+
251+
class Renderer_HSY_LOG_TO_RGB : public OpCPU
252+
{
253+
const float MIN_0 = -0.1f;;
254+
public:
255+
Renderer_HSY_LOG_TO_RGB() = delete;
256+
explicit Renderer_HSY_LOG_TO_RGB(ConstFixedFunctionOpDataRcPtr & data);
257+
258+
void apply(const void * inImg, void * outImg, long numPixels) const override;
259+
};
260+
261+
class Renderer_RGB_TO_HSY_VID : public OpCPU
262+
{
263+
const float MIN_0 = 0.0f;
264+
public:
265+
Renderer_RGB_TO_HSY_VID() = delete;
266+
explicit Renderer_RGB_TO_HSY_VID(ConstFixedFunctionOpDataRcPtr & data);
267+
268+
void apply(const void * inImg, void * outImg, long numPixels) const override;
269+
};
270+
271+
class Renderer_HSY_VID_TO_RGB : public OpCPU
272+
{
273+
const float MIN_0 = 0.0f;
274+
public:
275+
Renderer_HSY_VID_TO_RGB() = delete;
276+
explicit Renderer_HSY_VID_TO_RGB(ConstFixedFunctionOpDataRcPtr & data);
277+
278+
void apply(const void * inImg, void * outImg, long numPixels) const override;
279+
};
280+
281+
class Renderer_RGB_TO_HSY_LIN : public OpCPU
282+
{
283+
const float MIN_0 = 0.2f;
284+
public:
285+
Renderer_RGB_TO_HSY_LIN() = delete;
286+
explicit Renderer_RGB_TO_HSY_LIN(ConstFixedFunctionOpDataRcPtr & data);
287+
288+
void apply(const void * inImg, void * outImg, long numPixels) const override;
289+
};
290+
291+
class Renderer_HSY_LIN_TO_RGB : public OpCPU
292+
{
293+
const float MIN_0 = 0.2f;
294+
public:
295+
Renderer_HSY_LIN_TO_RGB() = delete;
296+
explicit Renderer_HSY_LIN_TO_RGB(ConstFixedFunctionOpDataRcPtr & data);
297+
298+
void apply(const void * inImg, void * outImg, long numPixels) const override;
299+
};
300+
241301
class Renderer_XYZ_TO_xyY : public OpCPU
242302
{
243303
public:
@@ -1534,6 +1594,230 @@ void Renderer_HSV_TO_RGB::apply(const void * inImg, void * outImg, long numPixel
15341594
}
15351595
}
15361596

1597+
void applyHSYToRGB(const void * inImg, void * outImg, long numPixels, float min0)
1598+
{
1599+
const float * in = (const float *)inImg;
1600+
float * out = (float *)outImg;
1601+
1602+
for(unsigned idx=0; idx<numPixels; ++idx)
1603+
{
1604+
float hue = in[0] - 1.f/6.f;
1605+
float sat = in[1];
1606+
const float luma = in[2];
1607+
1608+
hue = luma < 0.f ? hue + 0.5f : hue;
1609+
hue = ( hue - std::floor( hue ) ) * 6.f;
1610+
1611+
float red = CLAMP( std::fabs(hue - 3.f) - 1.f, 0.f, 1.f );
1612+
float grn = CLAMP( 2.f - std::fabs(hue - 2.f), 0.f, 1.f );
1613+
float blu = CLAMP( 2.f - std::fabs(hue - 4.f), 0.f, 1.f );
1614+
1615+
const float currY = 0.2126f * red + 0.7152f * grn + 0.0722f * blu;
1616+
red *= luma / currY;
1617+
grn *= luma / currY;
1618+
blu *= luma / currY;
1619+
1620+
float gainS = sat;
1621+
1622+
const float distRgb = std::fabs(red - luma) + std::fabs(grn - luma) + std::fabs(blu - luma);
1623+
1624+
if (min0 > 0.f) // linear
1625+
{
1626+
const float sumRgb = red + grn + blu;
1627+
1628+
const float k = 0.15f;
1629+
const float loGain = 5.f;
1630+
1631+
sat /= 1.4f;
1632+
const float tmp = -sat * sumRgb + sat * 3.f * luma + distRgb;
1633+
const float s1 = (tmp == 0.f) ? 0.f : sat * (k + 3.f * luma) / tmp;
1634+
const float s0 = sat / std::max(1e-10f, distRgb * loGain);
1635+
1636+
const float maxLum = 0.01f;
1637+
const float minLum = maxLum * 0.1f;
1638+
const float alpha = CLAMP( (luma - minLum) / (maxLum - minLum), 0.f, 1.f );
1639+
1640+
if (alpha == 1.f)
1641+
gainS = s1;
1642+
else if (alpha == 0.f)
1643+
gainS = s0;
1644+
else
1645+
{
1646+
const float a = distRgb * loGain * (1.f - alpha) * (sumRgb - 3.f * luma);
1647+
const float b = distRgb * loGain * (1.f - alpha) * (k + 3.f * luma) + distRgb * alpha -
1648+
sat * (sumRgb - 3.f * luma);
1649+
const float c = -sat * (k + 3.f * luma);
1650+
const float discrim = sqrt( b * b - 4.f * a * c );
1651+
const float denom = -discrim - b;
1652+
gainS = (2.f * c) / denom;
1653+
1654+
gainS = gainS >= 0.f ? gainS : (2.f * c) / (denom + discrim * 2.f);
1655+
}
1656+
}
1657+
else if (min0 < 0.f) // log
1658+
{
1659+
const float satGain = 4.f;
1660+
const float currSat = distRgb * satGain;
1661+
gainS = sat / std::max(1e-10f, currSat);
1662+
}
1663+
else // video
1664+
{
1665+
const float satGain = 1.25f;
1666+
const float currSat = distRgb * satGain;
1667+
gainS = sat / std::max(1e-10f, currSat);
1668+
}
1669+
1670+
out[0] = luma + gainS * (red - luma); // red
1671+
out[1] = luma + gainS * (grn - luma); // grn
1672+
out[2] = luma + gainS * (blu - luma); // blu
1673+
out[3] = in[3]; // alpha
1674+
1675+
in += 4;
1676+
out += 4;
1677+
}
1678+
1679+
}
1680+
1681+
void applyRGBToHSY(const void * inImg, void * outImg, long numPixels, float min0)
1682+
{
1683+
const float * in = (const float *)inImg;
1684+
float * out = (float *)outImg;
1685+
1686+
for (long idx=0; idx<numPixels; ++idx)
1687+
{
1688+
const float red = in[0];
1689+
const float grn = in[1];
1690+
const float blu = in[2];
1691+
1692+
const float rgbMin = std::min( std::min( red, grn ), blu );
1693+
const float rgbMax = std::max( std::max( red, grn ), blu );
1694+
1695+
const float luma = 0.2126f * red + 0.7152f * grn + 0.0722f * blu;
1696+
1697+
const float rm = red - luma;
1698+
const float gm = grn - luma;
1699+
const float bm = blu - luma;
1700+
1701+
const float distRgb = std::fabs(rm) + std::fabs(gm) + std::fabs(bm);
1702+
1703+
float sat = 0.f;
1704+
1705+
if (min0 > 0.f) // linear
1706+
{
1707+
const float sumRgb = red + grn + blu;
1708+
const float k = 0.15f;
1709+
const float satHi = distRgb / (k + sumRgb);
1710+
const float loGain = 5.f;
1711+
const float satLo = distRgb * loGain;
1712+
const float maxLum = 0.01f;
1713+
const float minLum = maxLum * 0.1;
1714+
const float alpha = CLAMP( (luma - minLum) / (maxLum - minLum), 0.f, 1.f );
1715+
sat = satLo + alpha * (satHi - satLo);
1716+
sat *= 1.4f;
1717+
}
1718+
else if (min0 < 0.f) // log
1719+
{
1720+
const float sat_gain = 4.f;
1721+
sat = distRgb * sat_gain;
1722+
}
1723+
else // video
1724+
{
1725+
const float sat_gain = 1.25f;
1726+
sat = distRgb * sat_gain;
1727+
}
1728+
1729+
float hue = 0.f;
1730+
if (rgbMin != rgbMax)
1731+
{
1732+
float delta = rgbMax - rgbMin;
1733+
if (red == rgbMax)
1734+
{
1735+
hue = 1.0f + (grn - blu) / delta;
1736+
}
1737+
else
1738+
{
1739+
if (grn == rgbMax)
1740+
{
1741+
hue = 3.0f + (blu - red) / delta;
1742+
}
1743+
else
1744+
{
1745+
hue = 5.0f + (red - grn) / delta;
1746+
}
1747+
}
1748+
hue *= 0.16666666666666666f;
1749+
}
1750+
1751+
out[0] = hue;
1752+
out[1] = sat;
1753+
out[2] = luma;
1754+
out[3] = in[3];
1755+
1756+
in += 4;
1757+
out += 4;
1758+
}
1759+
}
1760+
1761+
Renderer_RGB_TO_HSY_LOG::Renderer_RGB_TO_HSY_LOG(ConstFixedFunctionOpDataRcPtr & /*data*/)
1762+
: OpCPU()
1763+
{
1764+
}
1765+
1766+
void Renderer_RGB_TO_HSY_LOG::apply(const void * inImg, void * outImg, long numPixels) const
1767+
{
1768+
applyRGBToHSY(inImg, outImg, numPixels, MIN_0);
1769+
}
1770+
1771+
Renderer_HSY_LOG_TO_RGB::Renderer_HSY_LOG_TO_RGB(ConstFixedFunctionOpDataRcPtr & /*data*/)
1772+
: OpCPU()
1773+
{
1774+
}
1775+
1776+
void Renderer_HSY_LOG_TO_RGB::apply(const void * inImg, void * outImg, long numPixels) const
1777+
{
1778+
applyHSYToRGB(inImg, outImg, numPixels, MIN_0);
1779+
}
1780+
1781+
Renderer_RGB_TO_HSY_LIN::Renderer_RGB_TO_HSY_LIN(ConstFixedFunctionOpDataRcPtr & /*data*/)
1782+
: OpCPU()
1783+
{
1784+
}
1785+
1786+
void Renderer_RGB_TO_HSY_LIN::apply(const void * inImg, void * outImg, long numPixels) const
1787+
{
1788+
applyRGBToHSY(inImg, outImg, numPixels, MIN_0);
1789+
}
1790+
1791+
Renderer_HSY_LIN_TO_RGB::Renderer_HSY_LIN_TO_RGB(ConstFixedFunctionOpDataRcPtr & /*data*/)
1792+
: OpCPU()
1793+
{
1794+
}
1795+
1796+
void Renderer_HSY_LIN_TO_RGB::apply(const void * inImg, void * outImg, long numPixels) const
1797+
{
1798+
applyHSYToRGB(inImg, outImg, numPixels, MIN_0);
1799+
}
1800+
1801+
Renderer_RGB_TO_HSY_VID::Renderer_RGB_TO_HSY_VID(ConstFixedFunctionOpDataRcPtr & /*data*/)
1802+
: OpCPU()
1803+
{
1804+
}
1805+
1806+
void Renderer_RGB_TO_HSY_VID::apply(const void * inImg, void * outImg, long numPixels) const
1807+
{
1808+
applyRGBToHSY(inImg, outImg, numPixels, MIN_0);
1809+
}
1810+
1811+
Renderer_HSY_VID_TO_RGB::Renderer_HSY_VID_TO_RGB(ConstFixedFunctionOpDataRcPtr & /*data*/)
1812+
: OpCPU()
1813+
{
1814+
}
1815+
1816+
void Renderer_HSY_VID_TO_RGB::apply(const void * inImg, void * outImg, long numPixels) const
1817+
{
1818+
applyHSYToRGB(inImg, outImg, numPixels, MIN_0);
1819+
}
1820+
15371821
Renderer_XYZ_TO_xyY::Renderer_XYZ_TO_xyY(ConstFixedFunctionOpDataRcPtr & /*data*/)
15381822
: OpCPU()
15391823
{
@@ -2325,41 +2609,29 @@ ConstOpCPURcPtr GetFixedFunctionCPURenderer(ConstFixedFunctionOpDataRcPtr & func
23252609

23262610
case FixedFunctionOpData::RGB_TO_HSY_LOG:
23272611
{
2328-
// TODO: Handle CPU rendering for this FixedFunction
2329-
return nullptr;
2330-
//return std::make_shared<Renderer_RGB_TO_HSY_LOG>(func);
2612+
return std::make_shared<Renderer_RGB_TO_HSY_LOG>(func);
23312613
}
23322614
case FixedFunctionOpData::HSY_LOG_TO_RGB:
23332615
{
2334-
// TODO: Handle CPU rendering for this FixedFunction
2335-
return nullptr;
2336-
//return std::make_shared<Renderer_HSY_LOG_TO_RGB>(func);
2616+
return std::make_shared<Renderer_HSY_LOG_TO_RGB>(func);
23372617
}
23382618

23392619
case FixedFunctionOpData::RGB_TO_HSY_LIN:
23402620
{
2341-
// TODO: Handle CPU rendering for this FixedFunction
2342-
return nullptr;
2343-
//return std::make_shared<Renderer_RGB_TO_HSY_LIN>(func);
2621+
return std::make_shared<Renderer_RGB_TO_HSY_LIN>(func);
23442622
}
23452623
case FixedFunctionOpData::HSY_LIN_TO_RGB:
23462624
{
2347-
// TODO: Handle CPU rendering for this FixedFunction
2348-
return nullptr;
2349-
//return std::make_shared<Renderer_HSY_LIN_TO_RGB>(func);
2625+
return std::make_shared<Renderer_HSY_LIN_TO_RGB>(func);
23502626
}
23512627

23522628
case FixedFunctionOpData::RGB_TO_HSY_VID:
23532629
{
2354-
// TODO: Handle CPU rendering for this FixedFunction
2355-
return nullptr;
2356-
//return std::make_shared<Renderer_RGB_TO_HSY_VID>(func);
2630+
return std::make_shared<Renderer_RGB_TO_HSY_VID>(func);
23572631
}
23582632
case FixedFunctionOpData::HSY_VID_TO_RGB:
23592633
{
2360-
// TODO: Handle CPU rendering for this FixedFunction
2361-
return nullptr;
2362-
//return std::make_shared<Renderer_HSY_VID_TO_RGB>(func);
2634+
return std::make_shared<Renderer_HSY_VID_TO_RGB>(func);
23632635
}
23642636
}
23652637

0 commit comments

Comments
 (0)