#include "stdfx.h" #include "tfxparam.h" #include "warp.h" #include "trop.h" #include "trasterfx.h" #include "tspectrumparam.h" #include "gradients.h" #include "timage_io.h" #include "tparamuiconcept.h" //------------------------------------------------------------------- class RippleFx : public TStandardRasterFx { FX_PLUGIN_DECLARATION(RippleFx) protected: TRasterFxPort m_warped; TDoubleParamP m_intensity; TDoubleParamP m_gridStep; TPointParamP m_center; TDoubleParamP m_period; TDoubleParamP m_count; TDoubleParamP m_cycle; TDoubleParamP m_scaleX; TDoubleParamP m_scaleY; TDoubleParamP m_angle; TBoolParamP m_sharpen; public: RippleFx() : m_intensity(20), m_gridStep(2), m_center(TPointD(0.0, 0.0)), m_period(100) //args, "Period") , m_count(2) //args, "Count") , m_cycle(0.0), m_scaleX(100.0), m_scaleY(100.0), m_angle(0.0), m_sharpen(false) { m_center->getX()->setMeasureName("fxLength"); m_center->getY()->setMeasureName("fxLength"); m_period->setMeasureName("fxLength"); addInputPort("Source", m_warped); bindParam(this, "period", m_period); bindParam(this, "count", m_count); bindParam(this, "cycle", m_cycle); bindParam(this, "center", m_center); bindParam(this, "scalex", m_scaleX); bindParam(this, "scaley", m_scaleY); bindParam(this, "angle", m_angle); bindParam(this, "intensity", m_intensity); bindParam(this, "sensitivity", m_gridStep); bindParam(this, "sharpen", m_sharpen); m_intensity->setValueRange(-1000, 1000); m_gridStep->setValueRange(2, 20); m_period->setValueRange(0, (std::numeric_limits::max)()); m_cycle->setValueRange(0, (std::numeric_limits::max)()); m_count->setValueRange(0, (std::numeric_limits::max)()); m_angle->setMeasureName("angle"); } virtual ~RippleFx() {} //------------------------------------------------------------------- bool canHandle(const TRenderSettings &info, double frame) { return isAlmostIsotropic(info.m_affine); } //------------------------------------------------------------------- bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) { if (m_warped.isConnected()) { int ret = m_warped->doGetBBox(frame, bBox, info); if (ret && !bBox.isEmpty()) { if (bBox != TConsts::infiniteRectD) { WarpParams params; params.m_intensity = m_intensity->getValue(frame); bBox = bBox.enlarge(getWarpRadius(params)); } return true; } } bBox = TRectD(); return false; } //------------------------------------------------------------------- void doDryCompute(TRectD &rect, double frame, const TRenderSettings &info) { bool isWarped = m_warped.isConnected(); if (!isWarped) return; if (fabs(m_intensity->getValue(frame)) < 0.01) { m_warped->dryCompute(rect, frame, info); return; } double scale = sqrt(fabs(info.m_affine.det())); double gridStep = 1.5 * m_gridStep->getValue(frame); WarpParams params; params.m_intensity = m_intensity->getValue(frame) / gridStep; params.m_warperScale = scale * gridStep; params.m_sharpen = m_sharpen->getValue(); TRectD warpedBox, warpedComputeRect, tileComputeRect; m_warped->getBBox(frame, warpedBox, info); getWarpComputeRects(tileComputeRect, warpedComputeRect, warpedBox, rect, params); if (tileComputeRect.getLx() <= 0 || tileComputeRect.getLy() <= 0) return; if (warpedComputeRect.getLx() <= 0 || warpedComputeRect.getLy() <= 0) return; m_warped->dryCompute(warpedComputeRect, frame, info); } //------------------------------------------------------------------- void doCompute(TTile &tile, double frame, const TRenderSettings &info) { bool isWarped = m_warped.isConnected(); if (!isWarped) return; if (fabs(m_intensity->getValue(frame)) < 0.01) { m_warped->compute(tile, frame, info); return; } int shrink = (info.m_shrinkX + info.m_shrinkY) / 2; double scale = sqrt(fabs(info.m_affine.det())); double gridStep = 1.5 * m_gridStep->getValue(frame); WarpParams params; params.m_intensity = m_intensity->getValue(frame) / gridStep; params.m_warperScale = scale * gridStep; params.m_sharpen = m_sharpen->getValue(); params.m_shrink = shrink; double period = m_period->getValue(frame) / info.m_shrinkX; double count = m_count->getValue(frame); double cycle = m_cycle->getValue(frame) / info.m_shrinkX; double scaleX = m_scaleX->getValue(frame) / 100.0; double scaleY = m_scaleY->getValue(frame) / 100.0; double angle = -m_angle->getValue(frame); TPointD center = m_center->getValue(frame) * (1.0 / info.m_shrinkX); //The warper is calculated on a standard reference, with fixed dpi. This makes sure //that the lattice created for the warp does not depend on camera transforms and resolution. TRenderSettings warperInfo(info); double warperScaleFactor = 1.0 / params.m_warperScale; warperInfo.m_affine = TScale(warperScaleFactor) * info.m_affine; //Retrieve tile's geometry TRectD tileRect; { TRasterP tileRas = tile.getRaster(); tileRect = TRectD(tile.m_pos, TDimensionD(tileRas->getLx(), tileRas->getLy())); } //Build the compute rect TRectD warpedBox, warpedComputeRect, tileComputeRect; m_warped->getBBox(frame, warpedBox, info); getWarpComputeRects(tileComputeRect, warpedComputeRect, warpedBox, tileRect, params); if (tileComputeRect.getLx() <= 0 || tileComputeRect.getLy() <= 0) return; if (warpedComputeRect.getLx() <= 0 || warpedComputeRect.getLy() <= 0) return; TRectD warperComputeRect(TScale(warperScaleFactor) * tileComputeRect); double warperEnlargement = getWarperEnlargement(params); warperComputeRect = warperComputeRect.enlarge(warperEnlargement); warperComputeRect.x0 = tfloor(warperComputeRect.x0); warperComputeRect.y0 = tfloor(warperComputeRect.y0); warperComputeRect.x1 = tceil(warperComputeRect.x1); warperComputeRect.y1 = tceil(warperComputeRect.y1); //Compute the warped tile TTile tileIn; m_warped->allocateAndCompute(tileIn, warpedComputeRect.getP00(), TDimension(warpedComputeRect.getLx(), warpedComputeRect.getLy()), tile.getRaster(), frame, info); TRasterP rasIn = tileIn.getRaster(); //Compute the warper tile TSpectrum::ColorKey colors[] = { TSpectrum::ColorKey(0, TPixel32::White), TSpectrum::ColorKey(0.5, TPixel32::Black), TSpectrum::ColorKey(1, TPixel32::White)}; TSpectrumParamP ripplecolors = TSpectrumParamP(tArrayCount(colors), colors); //Build the multiradial warperInfo.m_affine = warperInfo.m_affine * TTranslation(center) * TRotation(angle) * TScale(scaleX, scaleY); TAffine aff = warperInfo.m_affine.inv(); TPointD posTrasf = aff * (warperComputeRect.getP00()); TRasterP rasWarper = rasIn->create(warperComputeRect.getLx(), warperComputeRect.getLy()); multiRadial(rasWarper, posTrasf, ripplecolors, period, count, cycle, aff, frame); //TImageWriter::save(TFilePath("C:\\ripple.tif"), rasWarper); //Warp TPointD db; TRect rasComputeRectI(convert(tileComputeRect - tileRect.getP00(), db)); TRasterP tileRas = tile.getRaster()->extract(rasComputeRectI); TPointD rasInPos(warpedComputeRect.getP00() - tileComputeRect.getP00()); TPointD warperPos((TScale(params.m_warperScale) * warperComputeRect.getP00()) - tileComputeRect.getP00()); warp(tileRas, rasIn, rasWarper, rasInPos, warperPos, params); } //------------------------------------------------------------------- void getParamUIs(TParamUIConcept *&concepts, int &length) { concepts = new TParamUIConcept[length = 2]; concepts[0].m_type = TParamUIConcept::POINT; concepts[0].m_label = "Center"; concepts[0].m_params.push_back(m_center); concepts[1].m_type = TParamUIConcept::RADIUS; concepts[1].m_label = "Period"; concepts[1].m_params.push_back(m_period); concepts[1].m_params.push_back(m_center); } //------------------------------------------------------------------- int getMemoryRequirement(const TRectD &rect, double frame, const TRenderSettings &info) { //return -1; //Deactivated. This fx is currently very inefficient if subdivided! int shrink = (info.m_shrinkX + info.m_shrinkY) / 2; double scale = sqrt(fabs(info.m_affine.det())); double gridStep = 1.5 * m_gridStep->getValue(frame); WarpParams params; params.m_intensity = m_intensity->getValue(frame) / gridStep; params.m_warperScale = scale * gridStep; params.m_sharpen = m_sharpen->getValue(); params.m_shrink = shrink; double warperScaleFactor = 1.0 / params.m_warperScale; TRectD warpedBox, warpedComputeRect, tileComputeRect; m_warped->getBBox(frame, warpedBox, info); getWarpComputeRects(tileComputeRect, warpedComputeRect, warpedBox, rect, params); TRectD warperComputeRect(TScale(warperScaleFactor) * tileComputeRect); double warperEnlargement = getWarperEnlargement(params); warperComputeRect = warperComputeRect.enlarge(warperEnlargement); return tmax( TRasterFx::memorySize(warpedComputeRect, info.m_bpp), TRasterFx::memorySize(warperComputeRect, info.m_bpp)); } }; //------------------------------------------------------------------- FX_PLUGIN_IDENTIFIER(RippleFx, "rippleFx")