Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "stdfx.h"
Toshihiro Shimizu 890ddd
#include "tfxparam.h"
Toshihiro Shimizu 890ddd
#include "trop.h"
Toshihiro Shimizu 890ddd
#include "tdoubleparam.h"
Toshihiro Shimizu 890ddd
#include "trasterfx.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/* (Daniele)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  NOTE: Current LocalBlurFx is effectively flawed. Following implementation relies on the idea that
Toshihiro Shimizu 890ddd
        the blurring filter is separable and therefore appliable on rows and columns, in sequence.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
        It actually is not. It can be easily verified applying the fx on a chessboard with a strong
Toshihiro Shimizu 890ddd
        blur intensity. The squares will be cast vertically towards blurred regions.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
        Originally, this was a sub-optimal O(lx * ly * blur) algorithm. The following (still separated)
Toshihiro Shimizu 890ddd
        is O(lx * ly) using precomputed sums in an additional line.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
        The 'correct' algorithm could be implemented again as O(lx * ly * blur), with additional O(lx * blur)
Toshihiro Shimizu 890ddd
        memory usage with precomputed sums along (blur) rows.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
        Pixels would have to be filtered one by one, but the horizontal filtering per pixel convolution row
Toshihiro Shimizu 890ddd
        would take O(1). Thus it would be O(blur) (column filtering) per pixel.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
//    Local namespace stuff
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct Sums {
Shinya Kitaoka 6a4e01
	std::unique_ptr<tuint64[]> m_sumsIX_r; //!< m_sumsIX1[i+1] = m_sumsIX1[i] + i * pix.r</tuint64[]>
Shinya Kitaoka 6a4e01
	std::unique_ptr<tuint64[]> m_sumsIX_g;</tuint64[]>
Shinya Kitaoka 6a4e01
	std::unique_ptr<tuint64[]> m_sumsIX_b;</tuint64[]>
Shinya Kitaoka 6a4e01
	std::unique_ptr<tuint64[]> m_sumsIX_m;</tuint64[]>
Shinya Kitaoka 6a4e01
	std::unique_ptr<tuint64[]> m_sumsX_r; //!< m_sumsX[i+1] = m_sumsX[i] + pix.r</tuint64[]>
Shinya Kitaoka 6a4e01
	std::unique_ptr<tuint64[]> m_sumsX_g;</tuint64[]>
Shinya Kitaoka 6a4e01
	std::unique_ptr<tuint64[]> m_sumsX_b;</tuint64[]>
Shinya Kitaoka 6a4e01
	std::unique_ptr<tuint64[]> m_sumsX_m;</tuint64[]>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	Sums(int length)
Shinya Kitaoka 6a4e01
		: m_sumsIX_r(new TUINT64[length + 1])
Shinya Kitaoka 6a4e01
		, m_sumsIX_g(new TUINT64[length + 1])
Shinya Kitaoka 6a4e01
		, m_sumsIX_b(new TUINT64[length + 1])
Shinya Kitaoka 6a4e01
		, m_sumsIX_m(new TUINT64[length + 1])
Shinya Kitaoka 6a4e01
		, m_sumsX_r(new TUINT64[length + 1])
Shinya Kitaoka 6a4e01
		, m_sumsX_g(new TUINT64[length + 1])
Shinya Kitaoka 6a4e01
		, m_sumsX_b(new TUINT64[length + 1])
Shinya Kitaoka 6a4e01
		, m_sumsX_m(new TUINT64[length + 1])
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	template <typename pix=""></typename>
Toshihiro Shimizu 890ddd
	void build(Pix *line, int wrap, int n)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		++n;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_sumsIX_r[0] = m_sumsX_r[0] = 0;
Toshihiro Shimizu 890ddd
		m_sumsIX_g[0] = m_sumsX_g[0] = 0;
Toshihiro Shimizu 890ddd
		m_sumsIX_b[0] = m_sumsX_b[0] = 0;
Toshihiro Shimizu 890ddd
		m_sumsIX_m[0] = m_sumsX_m[0] = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		Pix *pix;
Toshihiro Shimizu 890ddd
		int i, i_1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (pix = line, i_1 = 0, i = 1; i < n; pix += wrap, i_1 = i++) {
Toshihiro Shimizu 890ddd
			m_sumsIX_r[i] = m_sumsIX_r[i_1] + i * pix->r;
Toshihiro Shimizu 890ddd
			m_sumsIX_g[i] = m_sumsIX_g[i_1] + i * pix->g;
Toshihiro Shimizu 890ddd
			m_sumsIX_b[i] = m_sumsIX_b[i_1] + i * pix->b;
Toshihiro Shimizu 890ddd
			m_sumsIX_m[i] = m_sumsIX_m[i_1] + i * pix->m;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			m_sumsX_r[i] = m_sumsX_r[i_1] + pix->r;
Toshihiro Shimizu 890ddd
			m_sumsX_g[i] = m_sumsX_g[i_1] + pix->g;
Toshihiro Shimizu 890ddd
			m_sumsX_b[i] = m_sumsX_b[i_1] + pix->b;
Toshihiro Shimizu 890ddd
			m_sumsX_m[i] = m_sumsX_m[i_1] + pix->m;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename grey="" pix,="" typename=""></typename>
Toshihiro Shimizu 890ddd
void filterLine(Pix *lineIn, int wrapIn, Grey *lineGr, int wrapGr, Pix *lineOut, int wrapOut, int length,
Toshihiro Shimizu 890ddd
				double blurFactor, Sums &sums)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// Build temporary sums
Toshihiro Shimizu 890ddd
	sums.build(lineIn, wrapIn, length);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Declare vars
Toshihiro Shimizu 890ddd
	double blur, kLeft, kRight, cLeft, cRight;
Toshihiro Shimizu 890ddd
	double blurI;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Perform line filtering
Toshihiro Shimizu 890ddd
	Pix *pixIn, *pixOut;
Toshihiro Shimizu 890ddd
	Grey *pixGr;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int i, iLeft, iRight;
Toshihiro Shimizu 890ddd
	++length;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = 1, pixIn = lineIn, pixGr = lineGr, pixOut = lineOut; i < length;
Toshihiro Shimizu 890ddd
		 ++i, pixIn += wrapIn, pixGr += wrapGr, pixOut += wrapOut) {
Toshihiro Shimizu 890ddd
		blur = pixGr->value * blurFactor; // A table of factors should be made - since we have a finite
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (blur > 0.0) {
Toshihiro Shimizu 890ddd
			blur += 0.5; /*-- 0.5足すのは、注目ピクセルの半径分。例えばBlur0.5は、
Toshihiro Shimizu 890ddd
								注目ピクセルの外側0.5ピクセルボケるということなので。
Toshihiro Shimizu 890ddd
							--*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			blurI = (double)tfloor(blur);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			double amount = blur + (2 * blur - blurI - 1) * blurI;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			double dR = 1.0 / amount;
Toshihiro Shimizu 890ddd
			double ini = (blur - blurI) / amount;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			kLeft = dR;
Toshihiro Shimizu 890ddd
			cLeft = ini - dR * (i - blurI);
Toshihiro Shimizu 890ddd
			kRight = -dR;
Toshihiro Shimizu 890ddd
			cRight = blur / amount + dR * i;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// NOTE: The normalization factor with blur (not integer) would be:
Toshihiro Shimizu 890ddd
			//        1.0 / (1 + 2 * blurI - (blurI / blur) * (blurI + 1))                    -- could be done using a factors table
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			iLeft = tmax(i - tfloor(blur) - 1, 0);
Toshihiro Shimizu 890ddd
			iRight = tmin(i + tfloor(blur), length - 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			pixOut->r = troundp(
Toshihiro Shimizu 890ddd
				kLeft * (sums.m_sumsIX_r[i] - sums.m_sumsIX_r[iLeft]) + kRight * (sums.m_sumsIX_r[iRight] - sums.m_sumsIX_r[i]) +
Toshihiro Shimizu 890ddd
				cLeft * (sums.m_sumsX_r[i] - sums.m_sumsX_r[iLeft]) + cRight * (sums.m_sumsX_r[iRight] - sums.m_sumsX_r[i]));
Toshihiro Shimizu 890ddd
			pixOut->g = troundp(
Toshihiro Shimizu 890ddd
				kLeft * (sums.m_sumsIX_g[i] - sums.m_sumsIX_g[iLeft]) + kRight * (sums.m_sumsIX_g[iRight] - sums.m_sumsIX_g[i]) +
Toshihiro Shimizu 890ddd
				cLeft * (sums.m_sumsX_g[i] - sums.m_sumsX_g[iLeft]) + cRight * (sums.m_sumsX_g[iRight] - sums.m_sumsX_g[i]));
Toshihiro Shimizu 890ddd
			pixOut->b = troundp(
Toshihiro Shimizu 890ddd
				kLeft * (sums.m_sumsIX_b[i] - sums.m_sumsIX_b[iLeft]) + kRight * (sums.m_sumsIX_b[iRight] - sums.m_sumsIX_b[i]) +
Toshihiro Shimizu 890ddd
				cLeft * (sums.m_sumsX_b[i] - sums.m_sumsX_b[iLeft]) + cRight * (sums.m_sumsX_b[iRight] - sums.m_sumsX_b[i]));
Toshihiro Shimizu 890ddd
			pixOut->m = troundp(
Toshihiro Shimizu 890ddd
				kLeft * (sums.m_sumsIX_m[i] - sums.m_sumsIX_m[iLeft]) + kRight * (sums.m_sumsIX_m[iRight] - sums.m_sumsIX_m[i]) +
Toshihiro Shimizu 890ddd
				cLeft * (sums.m_sumsX_m[i] - sums.m_sumsX_m[iLeft]) + cRight * (sums.m_sumsX_m[iRight] - sums.m_sumsX_m[i]));
Toshihiro Shimizu 890ddd
		} else
Toshihiro Shimizu 890ddd
			*pixOut = *pixIn;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename grey="" pix,="" typename=""></typename>
Toshihiro Shimizu 890ddd
void doLocalBlur(TRasterPT<pix> rin, TRasterPT<pix> rcontrol, TRasterPT<pix> rout,</pix></pix></pix>
Toshihiro Shimizu 890ddd
				 double blur, const TPoint &displacement)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(rin->getLx() == rcontrol->getLx() && rin->getLy() == rcontrol->getLy());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double blurFactor = blur / Grey::maxChannelValue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int x, y, inLx, inLy, outLx, outLy, wrapIn, wrapOut, wrapC;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	inLx = rin->getLx();
Toshihiro Shimizu 890ddd
	inLy = rin->getLy();
Toshihiro Shimizu 890ddd
	wrapIn = rin->getWrap();
Toshihiro Shimizu 890ddd
	outLx = rout->getLx();
Toshihiro Shimizu 890ddd
	outLy = rout->getLy();
Toshihiro Shimizu 890ddd
	wrapOut = rout->getWrap();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Convert the control raster to grey values (this avoids the overhead of performing the pixel-to-value
Toshihiro Shimizu 890ddd
	// conversion twice, once per line filtering)
Toshihiro Shimizu 890ddd
	TRasterPT<grey> rcontrolGrey(rcontrol->getLx(), rcontrol->getLy());</grey>
Toshihiro Shimizu 890ddd
	TRop::convert(rcontrolGrey, rcontrol);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	wrapC = rcontrolGrey->getWrap();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	Pix *lineIn, *bufIn;
Toshihiro Shimizu 890ddd
	Grey *lineC, *bufC;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Filter rin. The output filtering is still stored in rin.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	rin->lock();
Toshihiro Shimizu 890ddd
	rcontrolGrey->lock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bufIn = rin->pixels(0);
Toshihiro Shimizu 890ddd
	bufC = rcontrolGrey->pixels(0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		Sums sums(inLx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (y = 0, lineIn = bufIn, lineC = bufC; y < inLy;
Toshihiro Shimizu 890ddd
			 ++y, lineIn += wrapIn, lineC += wrapC) {
Toshihiro Shimizu 890ddd
			// Filter row
Toshihiro Shimizu 890ddd
			filterLine(lineIn, 1, lineC, 1, lineIn, 1, inLx, blurFactor, sums);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		Sums sums(inLy);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (x = 0, lineIn = bufIn, lineC = bufC; x < inLx;
Toshihiro Shimizu 890ddd
			 ++x, ++lineIn, ++lineC) {
Toshihiro Shimizu 890ddd
			// Filter column
Toshihiro Shimizu 890ddd
			filterLine(lineIn, wrapIn, lineC, wrapC, lineIn, wrapIn, inLy, blurFactor, sums);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	rin->unlock();
Toshihiro Shimizu 890ddd
	rcontrolGrey->unlock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Copy the interesting part of rin to rout
Toshihiro Shimizu 890ddd
	TRect rectOut(rout->getBounds() - displacement);
Toshihiro Shimizu 890ddd
	TRect rectIn(rin->getBounds() + displacement);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRop::copy(rout->extract(rectIn), rin->extract(rectOut));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} //namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
//    LocalBlurFx implementation
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class LocalBlurFx : public TStandardRasterFx
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	FX_PLUGIN_DECLARATION(LocalBlurFx)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
protected:
Toshihiro Shimizu 890ddd
	TRasterFxPort m_up, m_ref;
Toshihiro Shimizu 890ddd
	TDoubleParamP m_value;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	LocalBlurFx()
Toshihiro Shimizu 890ddd
		: m_value(20)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_value->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
		addInputPort("Source", m_up);
Toshihiro Shimizu 890ddd
		addInputPort("Reference", m_ref);
Toshihiro Shimizu 890ddd
		bindParam(this, "value", m_value);
Toshihiro Shimizu 890ddd
		m_value->setValueRange(0, (std::numeric_limits<double>::max)());</double>
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	~LocalBlurFx() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool canHandle(const TRenderSettings &info, double frame)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return (isAlmostIsotropic(info.m_affine) || m_value->getValue(frame) == 0);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (m_up.isConnected()) {
Toshihiro Shimizu 890ddd
			bool ret = m_up->doGetBBox(frame, bBox, info);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			double blur = fabs(m_value->getValue(frame));
Toshihiro Shimizu 890ddd
			int blurI = tceil(blur);
Toshihiro Shimizu 890ddd
			bBox = bBox.enlarge(blurI);
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 doDryCompute(TRectD &rect, double frame, const TRenderSettings &info);
Toshihiro Shimizu 890ddd
	void doCompute(TTile &tile, double frame, const TRenderSettings &info);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getMemoryRequirement(const TRectD &rect, double frame, const TRenderSettings &info);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void LocalBlurFx::enlarge(const TRectD &bbox, TRectD &requestedRect, int blur)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// See BlurFx: this is a faithful replica
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
	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
	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 LocalBlurFx::doDryCompute(TRectD &rectOut, double frame, const TRenderSettings &info)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// Mimics the doCompute() without actual computation.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TTile refTile;
Toshihiro Shimizu 890ddd
	bool isUp = m_up.isConnected();
Toshihiro Shimizu 890ddd
	bool isDown = m_ref.isConnected();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!isUp)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!isDown) {
Toshihiro Shimizu 890ddd
		m_up->dryCompute(rectOut, frame, info);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double blur = fabs(m_value->getValue(frame) * sqrt(fabs(info.m_affine.det())));
Toshihiro Shimizu 890ddd
	int blurI = tceil(blur);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRectD bboxIn;
Toshihiro Shimizu 890ddd
	if (!m_up->getBBox(frame, bboxIn, info) || rectOut.isEmpty())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRectD rectIn(rectOut);
Toshihiro Shimizu 890ddd
	enlarge(bboxIn, rectIn, blurI);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (rectIn.isEmpty())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_up->dryCompute(rectOut, frame, info);
Toshihiro Shimizu 890ddd
	m_ref->dryCompute(rectOut, frame, info);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void LocalBlurFx::doCompute(TTile &tile, double frame, const TRenderSettings &info)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TTile refTile;
Toshihiro Shimizu 890ddd
	bool isUp = m_up.isConnected();
Toshihiro Shimizu 890ddd
	bool isDown = m_ref.isConnected();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!isUp)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!isDown) {
Toshihiro Shimizu 890ddd
		m_up->compute(tile, frame, info);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Generic case
Toshihiro Shimizu 890ddd
	assert(isAlmostIsotropic(info.m_affine));
Toshihiro Shimizu 890ddd
	double blur = fabs(m_value->getValue(frame) * sqrt(fabs(info.m_affine.det())));
Toshihiro Shimizu 890ddd
	int blurI = tceil(blur);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Get the requested tile's geometry
Toshihiro Shimizu 890ddd
	TRectD rectOut(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
	TRectD bboxIn;
Toshihiro Shimizu 890ddd
	if (!m_up->getBBox(frame, bboxIn, info) || rectOut.isEmpty())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRectD rectIn(rectOut);
Toshihiro Shimizu 890ddd
	enlarge(bboxIn, rectIn, blurI);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (rectIn.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_up->allocateAndCompute(
Toshihiro Shimizu 890ddd
		tileIn, rectIn.getP00(), TDimension(rectIn.getLx(), rectIn.getLy()),
Toshihiro Shimizu 890ddd
		tile.getRaster(), frame, info);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TTile tileRef;
Toshihiro Shimizu 890ddd
	m_ref->allocateAndCompute(
Toshihiro Shimizu 890ddd
		tileRef, rectIn.getP00(), TDimension(rectIn.getLx(), rectIn.getLy()),
Toshihiro Shimizu 890ddd
		tile.getRaster(), frame, info);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Perform Local Blur
Toshihiro Shimizu 890ddd
	TRasterP inRas(tileIn.getRaster());
Toshihiro Shimizu 890ddd
	TRasterP refRas(tileRef.getRaster());
Toshihiro Shimizu 890ddd
	TRasterP outRas(tile.getRaster());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRaster32P in32(inRas);
Toshihiro Shimizu 890ddd
	TRaster32P ref32(refRas);
Toshihiro Shimizu 890ddd
	TRaster32P out32(outRas);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPoint displacement(convert(rectIn.getP00() - tile.m_pos)); // inTile position relative to (out)tile
Toshihiro Shimizu 890ddd
																// The difference already has integer coordinates due to enlarge()
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (in32 && ref32 && out32)
Toshihiro Shimizu 890ddd
		doLocalBlur<tpixelrgbm32, tpixelgr8="">(in32, ref32, out32, blur, displacement);</tpixelrgbm32,>
Toshihiro Shimizu 890ddd
	else {
Toshihiro Shimizu 890ddd
		TRaster64P in64(inRas);
Toshihiro Shimizu 890ddd
		TRaster64P ref64(refRas);
Toshihiro Shimizu 890ddd
		TRaster64P out64(outRas);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (in64 && ref64 && out64)
Toshihiro Shimizu 890ddd
			doLocalBlur<tpixelrgbm64, tpixelgr16="">(in64, ref64, out64, blur, displacement);</tpixelrgbm64,>
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			throw TException("LocalBlurFx: unsupported raster type");
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int LocalBlurFx::getMemoryRequirement(const TRectD &rect, double frame, const TRenderSettings &info)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double blur = fabs(m_value->getValue(frame) * sqrt(fabs(info.m_affine.det())));
Toshihiro Shimizu 890ddd
	int blurI = tceil(blur);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return 2 * TRasterFx::memorySize(rect.enlarge(blurI), info.m_bpp);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
FX_PLUGIN_IDENTIFIER(LocalBlurFx, "localBlurFx")