Toshihiro Shimizu 890ddd
#include "texception.h"
Toshihiro Shimizu 890ddd
#include "tfxparam.h"
Toshihiro Shimizu 890ddd
#include "trop.h"
Toshihiro Shimizu 890ddd
#include "stdfx.h"
Toshihiro Shimizu 890ddd
#include "trasterfx.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class BlurFx : public TStandardRasterFx
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	FX_PLUGIN_DECLARATION(BlurFx)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRasterFxPort m_input;
Toshihiro Shimizu 890ddd
	TDoubleParamP m_value;
Toshihiro Shimizu 890ddd
	TBoolParamP m_useSSE;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	BlurFx() : m_value(20), m_useSSE(true)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_value->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
		bindParam(this, "value", m_value);
Toshihiro Shimizu 890ddd
		bindParam(this, "useSSE", m_useSSE, true);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		addInputPort("Source", m_input);
Toshihiro Shimizu 890ddd
		m_value->setValueRange(0, std::numeric_limits<double>::max());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	~BlurFx(){};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (m_input.isConnected()) {
Toshihiro Shimizu 890ddd
			bool ret = m_input->doGetBBox(frame, bBox, info);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			double blur = fabs(m_value->getValue(frame));
Toshihiro Shimizu 890ddd
			int brad = tceil(blur);
Toshihiro Shimizu 890ddd
			bBox = bBox.enlarge(brad);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			return ret;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			bBox = TRectD();
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void enlarge(const TRectD &bbox, TRectD &requestedRect, int blur);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void transform(
Toshihiro Shimizu 890ddd
		double frame,
Toshihiro Shimizu 890ddd
		int port,
Toshihiro Shimizu 890ddd
		const TRectD &rectOnOutput,
Toshihiro Shimizu 890ddd
		const TRenderSettings &infoOnOutput,
Toshihiro Shimizu 890ddd
		TRectD &rectOnInput,
Toshihiro Shimizu 890ddd
		TRenderSettings &infoOnInput);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void doCompute(TTile &tile, double frame, const TRenderSettings &);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getMemoryRequirement(const TRectD &rect, double frame, const TRenderSettings &info);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool canHandle(const TRenderSettings &info, double frame)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (m_value->getValue(frame) == 0)
Toshihiro Shimizu 890ddd
			return true;
Toshihiro Shimizu 890ddd
		return (isAlmostIsotropic(info.m_affine));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
FX_PLUGIN_IDENTIFIER(BlurFx, "blurFx")
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//!Calculates the geometry we need for this node computation, given
Toshihiro Shimizu 890ddd
//!the known input data (bbox), the requested output (requestedRect) and the blur factor.
Toshihiro Shimizu 890ddd
void BlurFx::enlarge(const TRectD &bbox, TRectD &requestedRect, int blur)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (bbox.isEmpty() || requestedRect.isEmpty()) {
Toshihiro Shimizu 890ddd
		requestedRect.empty();
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//We are to find out the geometry that is useful for the fx computation.
Toshihiro Shimizu 890ddd
	//There are some rules to follow:
Toshihiro Shimizu 890ddd
	//  a) First, the interesting output we can generate is bounded by both
Toshihiro Shimizu 890ddd
	//     the requestedRect and the blurred bbox (i.e. enlarged by the blur radius).
Toshihiro Shimizu 890ddd
	//  b) Pixels contributing to any output are necessarily part of bbox - and only
Toshihiro Shimizu 890ddd
	//     those which are blurrable into the requestedRect are useful to us
Toshihiro Shimizu 890ddd
	//     (i.e. pixels contained in its enlargement by the blur radius).
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRectD enlargedBBox(bbox.enlarge(blur));
Toshihiro Shimizu 890ddd
	TRectD enlargedOut(requestedRect.enlarge(blur));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD originalP00(requestedRect.getP00());
Toshihiro Shimizu 890ddd
	requestedRect = (enlargedOut * bbox) + (enlargedBBox * requestedRect);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Finally, make sure that the result is coherent with the original P00
Toshihiro Shimizu 890ddd
	requestedRect -= originalP00;
Toshihiro Shimizu 890ddd
	requestedRect.x0 = tfloor(requestedRect.x0);
Toshihiro Shimizu 890ddd
	requestedRect.y0 = tfloor(requestedRect.y0);
Toshihiro Shimizu 890ddd
	requestedRect.x1 = tceil(requestedRect.x1);
Toshihiro Shimizu 890ddd
	requestedRect.y1 = tceil(requestedRect.y1);
Toshihiro Shimizu 890ddd
	requestedRect += originalP00;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void BlurFx::transform(
Toshihiro Shimizu 890ddd
	double frame,
Toshihiro Shimizu 890ddd
	int port,
Toshihiro Shimizu 890ddd
	const TRectD &rectOnOutput,
Toshihiro Shimizu 890ddd
	const TRenderSettings &infoOnOutput,
Toshihiro Shimizu 890ddd
	TRectD &rectOnInput,
Toshihiro Shimizu 890ddd
	TRenderSettings &infoOnInput)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	infoOnInput = infoOnOutput;
Toshihiro Shimizu 890ddd
	rectOnInput = rectOnOutput;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double blur = fabs(m_value->getValue(frame) * sqrt(fabs(infoOnOutput.m_affine.det())));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (blur == 0) {
Toshihiro Shimizu 890ddd
		rectOnInput = rectOnOutput;
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int brad = tceil(blur);
Toshihiro Shimizu 890ddd
	TRectD bbox;
Toshihiro Shimizu 890ddd
	m_input->getBBox(frame, bbox, infoOnInput);
Toshihiro Shimizu 890ddd
	enlarge(bbox, rectOnInput, brad);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int BlurFx::getMemoryRequirement(const TRectD &rect, double frame, const TRenderSettings &info)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double blurValue = fabs(m_value->getValue(frame) * sqrt(fabs(info.m_affine.det())));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (blurValue == 0.0)
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int brad = tceil(blurValue);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Trop::blur is quite inefficient at the moment - it has to allocate a whole
Toshihiro Shimizu 890ddd
	//raster of the same size of the input/output made of FLOAT QUADRUPLES...!
Toshihiro Shimizu 890ddd
	return TRasterFx::memorySize(rect.enlarge(brad), sizeof(float) << 5);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void BlurFx::doCompute(
Toshihiro Shimizu 890ddd
	TTile &tile,
Toshihiro Shimizu 890ddd
	double frame,
Toshihiro Shimizu 890ddd
	const TRenderSettings &renderSettings)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_input.isConnected())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double shrink = 0.5 * (renderSettings.m_shrinkX + renderSettings.m_shrinkY);
Toshihiro Shimizu 890ddd
	// Note: shrink is obsolete. It should be always = 1
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double blurValue = fabs(m_value->getValue(frame) * sqrt(fabs(renderSettings.m_affine.det())) / shrink);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (blurValue == 0) {
Toshihiro Shimizu 890ddd
		//No blur will be done. The underlying fx may pass by.
Toshihiro Shimizu 890ddd
		m_input->compute(tile, frame, renderSettings);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int brad = tceil(blurValue);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Get the requested tile's geometry
Toshihiro Shimizu 890ddd
	TRectD rectIn, rectOut;
Toshihiro Shimizu 890ddd
	rectOut = TRectD(
Toshihiro Shimizu 890ddd
		tile.m_pos, TDimensionD(tile.getRaster()->getLx(), tile.getRaster()->getLy()));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Retrieve the input interesting geometry - and ensure that something actually has
Toshihiro Shimizu 890ddd
	//to be computed
Toshihiro Shimizu 890ddd
	if (!m_input->getBBox(frame, rectIn, renderSettings) || rectOut.isEmpty())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	enlarge(rectIn, rectOut, brad);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (rectOut.isEmpty())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Finally, allocate and compute the blur argument
Toshihiro Shimizu 890ddd
	TTile tileIn;
Toshihiro Shimizu 890ddd
	m_input->allocateAndCompute(
Toshihiro Shimizu 890ddd
		tileIn, rectOut.getP00(), TDimension(rectOut.getLx(), rectOut.getLy()),
Toshihiro Shimizu 890ddd
		tile.getRaster(), frame, renderSettings);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD displacement(rectOut.getP00() - tile.m_pos);
Toshihiro Shimizu 890ddd
	TRop::blur(tile.getRaster(), tileIn.getRaster(), blurValue, displacement.x, displacement.y, false);
Toshihiro Shimizu 890ddd
}