| |
| |
| #include "texception.h" |
| #include "tfxparam.h" |
| |
| #include "stdfx.h" |
| |
| namespace { |
| template <typename T, typename PIXEL> |
| void prepare_lut(double max, int edge, std::vector<T> &lut) { |
| double aux = (double)PIXEL::maxChannelValue; |
| int i = 0; |
| for (i = 0; i <= edge; i++) { |
| lut[i] = (int)((max / edge) * i); |
| } |
| for (i = edge + 1; i < PIXEL::maxChannelValue + 1; i++) { |
| lut[i] = (int)((max / (edge - aux)) * (i - aux)); |
| } |
| } |
| } |
| |
| |
| |
| class SolarizeFx final : public TStandardRasterFx { |
| FX_PLUGIN_DECLARATION(SolarizeFx) |
| |
| TRasterFxPort m_input; |
| TDoubleParamP m_maximum; |
| TDoubleParamP m_edge; |
| |
| public: |
| SolarizeFx() : m_maximum(1.0), m_edge(128.0) { |
| bindParam(this, "maximum", m_maximum); |
| bindParam(this, "peak_edge", m_edge); |
| addInputPort("Source", m_input); |
| |
| m_maximum->setValueRange(0.0, 10.0); |
| m_edge->setValueRange(0.0, 255.0); |
| } |
| |
| ~SolarizeFx(){}; |
| |
| bool doGetBBox(double frame, TRectD &bBox, |
| const TRenderSettings &info) override { |
| if (m_input.isConnected()) { |
| bool ret = m_input->doGetBBox(frame, bBox, info); |
| return ret; |
| } else { |
| bBox = TRectD(); |
| return false; |
| } |
| } |
| |
| void doCompute(TTile &tile, double frame, const TRenderSettings &ri) override; |
| |
| bool canHandle(const TRenderSettings &info, double frame) override { |
| return true; |
| } |
| }; |
| namespace { |
| template <typename T> |
| void update_param(T ¶m, TRaster32P ras) { |
| return; |
| } |
| |
| template <typename T> |
| void update_param(T ¶m, TRaster64P ras) { |
| param = param * 257; |
| return; |
| } |
| } |
| |
| |
| |
| template <typename PIXEL, typename CHANNEL_TYPE> |
| void doSolarize(TRasterPT<PIXEL> ras, double max, int edge) { |
| std::vector<CHANNEL_TYPE> solarize_lut(PIXEL::maxChannelValue + 1); |
| |
| update_param(max, ras); |
| update_param(edge, ras); |
| |
| prepare_lut<CHANNEL_TYPE, PIXEL>(max, edge, solarize_lut); |
| int j; |
| ras->lock(); |
| for (j = 0; j < ras->getLy(); j++) { |
| PIXEL *pix = ras->pixels(j); |
| PIXEL *endPix = pix + ras->getLx(); |
| while (pix < endPix) { |
| pix->r = (CHANNEL_TYPE)(solarize_lut[(int)(pix->r)]); |
| pix->g = (CHANNEL_TYPE)(solarize_lut[(int)(pix->g)]); |
| pix->b = (CHANNEL_TYPE)(solarize_lut[(int)(pix->b)]); |
| *pix++; |
| } |
| } |
| ras->unlock(); |
| } |
| |
| |
| |
| void SolarizeFx::doCompute(TTile &tile, double frame, |
| const TRenderSettings &ri) { |
| if (!m_input.isConnected()) return; |
| |
| m_input->compute(tile, frame, ri); |
| |
| double min, max, step; |
| m_maximum->getValueRange(min, max, step); |
| double maxValue = 128 * tcrop(m_maximum->getValue(frame), min, max); |
| m_edge->getValueRange(min, max, step); |
| int edge = (int)tcrop(m_edge->getValue(frame), min, max); |
| |
| TRaster32P raster32 = tile.getRaster(); |
| if (raster32) |
| doSolarize<TPixel32, UCHAR>(raster32, maxValue, edge); |
| else { |
| TRaster64P raster64 = tile.getRaster(); |
| if (raster64) |
| doSolarize<TPixel64, USHORT>(raster64, maxValue, edge); |
| else |
| throw TException("SolarizeFx: unsupported Pixel Type"); |
| } |
| } |
| |
| FX_PLUGIN_IDENTIFIER(SolarizeFx, "solarizeFx"); |
| |