| #include "texception.h" |
| #include "tfxparam.h" |
| #include "trop.h" |
| #include "stdfx.h" |
| #include "trasterfx.h" |
| |
| |
| |
| class BlurFx final : public TStandardRasterFx { |
| FX_PLUGIN_DECLARATION(BlurFx) |
| |
| TRasterFxPort m_input; |
| TDoubleParamP m_value; |
| TBoolParamP m_useSSE; |
| |
| public: |
| BlurFx() : m_value(20), m_useSSE(true) { |
| m_value->setMeasureName("fxLength"); |
| bindParam(this, "value", m_value); |
| bindParam(this, "useSSE", m_useSSE, true); |
| |
| addInputPort("Source", m_input); |
| m_value->setValueRange(0, std::numeric_limits<double>::max()); |
| } |
| |
| ~BlurFx(){}; |
| |
| bool doGetBBox(double frame, TRectD &bBox, |
| const TRenderSettings &info) override { |
| if (m_input.isConnected()) { |
| bool ret = m_input->doGetBBox(frame, bBox, info); |
| |
| double blur = fabs(m_value->getValue(frame)); |
| int brad = tceil(blur); |
| bBox = bBox.enlarge(brad); |
| |
| return ret; |
| } else { |
| bBox = TRectD(); |
| return false; |
| } |
| } |
| |
| void enlarge(const TRectD &bbox, TRectD &requestedRect, int blur); |
| |
| void transform(double frame, int port, const TRectD &rectOnOutput, |
| const TRenderSettings &infoOnOutput, TRectD &rectOnInput, |
| TRenderSettings &infoOnInput) override; |
| |
| void doCompute(TTile &tile, double frame, const TRenderSettings &) override; |
| |
| int getMemoryRequirement(const TRectD &rect, double frame, |
| const TRenderSettings &info) override; |
| |
| bool canHandle(const TRenderSettings &info, double frame) override { |
| if (m_value->getValue(frame) == 0) return true; |
| return (isAlmostIsotropic(info.m_affine)); |
| } |
| }; |
| |
| FX_PLUGIN_IDENTIFIER(BlurFx, "blurFx") |
| |
| |
| |
| |
| |
| |
| void BlurFx::enlarge(const TRectD &bbox, TRectD &requestedRect, int blur) { |
| if (bbox.isEmpty() || requestedRect.isEmpty()) { |
| requestedRect.empty(); |
| return; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| TRectD enlargedBBox(bbox.enlarge(blur)); |
| TRectD enlargedOut(requestedRect.enlarge(blur)); |
| |
| TPointD originalP00(requestedRect.getP00()); |
| requestedRect = (enlargedOut * bbox) + (enlargedBBox * requestedRect); |
| |
| |
| requestedRect -= originalP00; |
| requestedRect.x0 = tfloor(requestedRect.x0); |
| requestedRect.y0 = tfloor(requestedRect.y0); |
| requestedRect.x1 = tceil(requestedRect.x1); |
| requestedRect.y1 = tceil(requestedRect.y1); |
| requestedRect += originalP00; |
| } |
| |
| |
| |
| void BlurFx::transform(double frame, int port, const TRectD &rectOnOutput, |
| const TRenderSettings &infoOnOutput, TRectD &rectOnInput, |
| TRenderSettings &infoOnInput) { |
| infoOnInput = infoOnOutput; |
| rectOnInput = rectOnOutput; |
| |
| double blur = |
| fabs(m_value->getValue(frame) * sqrt(fabs(infoOnOutput.m_affine.det()))); |
| |
| if (blur == 0) { |
| rectOnInput = rectOnOutput; |
| return; |
| } |
| |
| int brad = tceil(blur); |
| TRectD bbox; |
| m_input->getBBox(frame, bbox, infoOnInput); |
| enlarge(bbox, rectOnInput, brad); |
| } |
| |
| |
| |
| int BlurFx::getMemoryRequirement(const TRectD &rect, double frame, |
| const TRenderSettings &info) { |
| double blurValue = |
| fabs(m_value->getValue(frame) * sqrt(fabs(info.m_affine.det()))); |
| |
| if (blurValue == 0.0) return 0; |
| |
| int brad = tceil(blurValue); |
| |
| |
| |
| return TRasterFx::memorySize(rect.enlarge(brad), sizeof(float) << 5); |
| } |
| |
| |
| |
| void BlurFx::doCompute(TTile &tile, double frame, |
| const TRenderSettings &renderSettings) { |
| if (!m_input.isConnected()) return; |
| |
| double shrink = 0.5 * (renderSettings.m_shrinkX + renderSettings.m_shrinkY); |
| |
| |
| double blurValue = fabs(m_value->getValue(frame) * |
| sqrt(fabs(renderSettings.m_affine.det())) / shrink); |
| |
| if (blurValue == 0) { |
| |
| m_input->compute(tile, frame, renderSettings); |
| return; |
| } |
| |
| int brad = tceil(blurValue); |
| |
| |
| TRectD rectIn, rectOut; |
| rectOut = TRectD(tile.m_pos, TDimensionD(tile.getRaster()->getLx(), |
| tile.getRaster()->getLy())); |
| |
| |
| |
| |
| if (!m_input->getBBox(frame, rectIn, renderSettings) || rectOut.isEmpty()) |
| return; |
| |
| enlarge(rectIn, rectOut, brad); |
| |
| if (rectOut.isEmpty()) return; |
| |
| |
| TTile tileIn; |
| m_input->allocateAndCompute(tileIn, rectOut.getP00(), |
| TDimension(rectOut.getLx(), rectOut.getLy()), |
| tile.getRaster(), frame, renderSettings); |
| |
| TPointD displacement(rectOut.getP00() - tile.m_pos); |
| TRop::blur(tile.getRaster(), tileIn.getRaster(), blurValue, displacement.x, |
| displacement.y, false); |
| } |