| |
| |
|
|
| #include "tfxparam.h" |
| #include <math.h> |
| #include "stdfx.h" |
| #include "hsvutil.h" |
| |
| class HSVScaleFx final : public TStandardRasterFx { |
| FX_PLUGIN_DECLARATION(HSVScaleFx) |
| |
| TRasterFxPort m_input; |
| TDoubleParamP m_hue; |
| TDoubleParamP m_sat; |
| TDoubleParamP m_value; |
| TDoubleParamP m_hueScale; |
| TDoubleParamP m_satScale; |
| TDoubleParamP m_valueScale; |
| |
| public: |
| HSVScaleFx() |
| : m_hue(0.0) |
| , m_sat(0.0) |
| , m_value(0.0) |
| , m_hueScale(100.0) |
| , m_satScale(100.0) |
| , m_valueScale(100.0) |
| |
| { |
| bindParam(this, "hue", m_hue); |
| bindParam(this, "saturation", m_sat); |
| bindParam(this, "value", m_value); |
| bindParam(this, "hue_scale", m_hueScale); |
| bindParam(this, "saturation_scale", m_satScale); |
| bindParam(this, "value_scale", m_valueScale); |
| m_hue->setValueRange(-180, 180); |
| m_sat->setValueRange(-1, 1); |
| m_value->setValueRange(-1, 1); |
| m_hueScale->setValueRange(0, (std::numeric_limits<double>::max)()); |
| m_satScale->setValueRange(0, (std::numeric_limits<double>::max)()); |
| m_valueScale->setValueRange(0, (std::numeric_limits<double>::max)()); |
| addInputPort("Source", m_input); |
| } |
| |
| ~HSVScaleFx(){}; |
| |
| bool doGetBBox(double frame, TRectD &bBox, |
| const TRenderSettings &info) override { |
| if (m_input.isConnected()) { |
| m_input->doGetBBox(frame, bBox, info); |
| return true; |
| } |
| |
| return false; |
| }; |
| |
| void doCompute(TTile &tile, double frame, const TRenderSettings &) override; |
| |
| bool canHandle(const TRenderSettings &info, double frame) override { |
| return true; |
| } |
| }; |
| |
| template <typename PIXEL, typename CHANNEL_TYPE> |
| void doHSVScale(const TRasterPT<PIXEL> &ras, double hue, double sat, |
| double value, double hueScale, double satScale, |
| double valueScale) { |
| int j; |
| ras->lock(); |
| for (j = 0; j < ras->getLy(); j++) { |
| PIXEL *pix = ras->pixels(j); |
| PIXEL *endPix = pix + ras->getLx(); |
| |
| for (; pix < endPix; ++pix) { |
| if (pix->m == 0) continue; |
| |
| double m = pix->m; |
| |
| double r, g, b, h, s, v; |
| |
| r = pix->r / m; |
| g = pix->g / m; |
| b = pix->b / m; |
| OLDRGB2HSV(r, g, b, &h, &s, &v); |
| |
| |
| |
| |
| |
| h += hue; |
| s += sat; |
| v += value; |
| h *= hueScale; |
| s *= satScale; |
| v *= valueScale; |
| |
| |
| |
| |
| |
| OLDHSV2RGB(h, s, v, &r, &g, &b); |
| pix->r = (CHANNEL_TYPE)(r * m); |
| pix->g = (CHANNEL_TYPE)(g * m); |
| pix->b = (CHANNEL_TYPE)(b * m); |
| |
| } |
| } |
| ras->unlock(); |
| } |
| |
| |
| void HSVScaleFx::doCompute(TTile &tile, double frame, |
| const TRenderSettings &ri) { |
| if (!m_input.isConnected()) return; |
| |
| m_input->compute(tile, frame, ri); |
| |
| double hue = m_hue->getValue(frame); |
| double sat = m_sat->getValue(frame); |
| double value = m_value->getValue(frame); |
| double hueScale = m_hueScale->getValue(frame) / 100.0; |
| double satScale = m_satScale->getValue(frame) / 100.0; |
| double valueScale = m_valueScale->getValue(frame) / 100.0; |
| |
| TRaster32P raster32 = tile.getRaster(); |
| |
| if (raster32) |
| doHSVScale<TPixel32, UCHAR>(raster32, hue, sat, value, hueScale, satScale, |
| valueScale); |
| else { |
| TRaster64P raster64 = tile.getRaster(); |
| if (raster64) |
| doHSVScale<TPixel64, USHORT>(raster64, hue, sat, value, hueScale, |
| satScale, valueScale); |
| else |
| throw TException("HSVScale: unsupported Pixel Type"); |
| } |
| } |
| |
| |
| |
| FX_PLUGIN_IDENTIFIER(HSVScaleFx, "hsvScaleFx") |
| |