| |
| |
| #include "stdfx.h" |
| #include "tfxparam.h" |
| #include "tspectrumparam.h" |
| |
| class MultiToneFx final : public TStandardRasterFx { |
| FX_PLUGIN_DECLARATION(MultiToneFx) |
| |
| TRasterFxPort m_input; |
| TSpectrumParamP m_colors; |
| |
| public: |
| MultiToneFx() { |
| TSpectrum::ColorKey colors[] = {TSpectrum::ColorKey(0, TPixel32::White), |
| TSpectrum::ColorKey(0.5, TPixel32::Yellow), |
| TSpectrum::ColorKey(1, TPixel32::Red)}; |
| m_colors = TSpectrumParamP(tArrayCount(colors), colors); |
| bool ret = m_colors->isKeyframe(0); |
| bindParam(this, "colors", m_colors); |
| |
| ret = getParams()->getParam(0)->isKeyframe(0); |
| addInputPort("Source", m_input); |
| } |
| |
| ~MultiToneFx(){}; |
| |
| bool doGetBBox(double frame, TRectD &bBox, |
| const TRenderSettings &info) override { |
| if (m_input.isConnected()) |
| return m_input->doGetBBox(frame, bBox, info); |
| else { |
| bBox = TRectD(); |
| 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 PIXELGRAY, typename CHANNEL_TYPE> |
| void doMultiTone(const TRasterPT<PIXEL> &ras, |
| const TSpectrumT<PIXEL> &spectrum) { |
| double aux = (double)PIXEL::maxChannelValue; |
| int j; |
| ras->lock(); |
| for (j = 0; j < ras->getLy(); j++) { |
| PIXEL *pix = ras->pixels(j); |
| PIXEL *endPix = pix + ras->getLx(); |
| while (pix < endPix) { |
| if (pix->m) { |
| CHANNEL_TYPE reference; |
| double s; |
| reference = PIXELGRAY::from(*pix).value; |
| s = reference / aux; |
| if (pix->m == aux) { |
| *pix = spectrum.getPremultipliedValue(s); |
| } else { |
| PIXEL tmp = spectrum.getPremultipliedValue(s); |
| s = pix->m / aux; |
| tmp.r = (CHANNEL_TYPE)(tmp.r * s); |
| tmp.g = (CHANNEL_TYPE)(tmp.g * s); |
| tmp.b = (CHANNEL_TYPE)(tmp.b * s); |
| tmp.m = (CHANNEL_TYPE)(tmp.m * s); |
| *pix = tmp; |
| } |
| } |
| pix++; |
| } |
| } |
| ras->unlock(); |
| } |
| |
| |
| |
| void MultiToneFx::doCompute(TTile &tile, double frame, |
| const TRenderSettings &ri) { |
| if (!m_input.isConnected()) return; |
| |
| m_input->compute(tile, frame, ri); |
| |
| if (TRaster32P raster32 = tile.getRaster()) |
| doMultiTone<TPixel32, TPixelGR8, UCHAR>(raster32, |
| m_colors->getValue(frame)); |
| else if (TRaster64P raster64 = tile.getRaster()) |
| doMultiTone<TPixel64, TPixelGR16, USHORT>(raster64, |
| m_colors->getValue64(frame)); |
| else |
| throw TException("MultiToneFx: unsupported Pixel Type"); |
| } |
| |
| |
| |
| FX_PLUGIN_IDENTIFIER(MultiToneFx, "multiToneFx") |
| |