Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tfxparam.h"
Toshihiro Shimizu 890ddd
#include "tfx.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tparamset.h"
Toshihiro Shimizu 890ddd
#include "stdfx.h"
Toshihiro Shimizu 890ddd
#include "time.h"
Toshihiro Shimizu 890ddd
#include "trop.h"
Toshihiro Shimizu 890ddd
#include "trasterfx.h"
Toshihiro Shimizu 890ddd
#include "tpixelutils.h"
Toshihiro Shimizu 890ddd
#include "tparamuiconcept.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "timage_io.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/tdistort.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
inline bool myIsEmpty(const TRectD &r)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return r.x0 >= r.x1 || r.y0 >= r.y1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class FreeDistortBaseFx : public TStandardRasterFx
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	enum { PERSPECTIVE,
Toshihiro Shimizu 890ddd
		   BILINEAR };
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	FreeDistortBaseFx(bool isCastShadow);
Toshihiro Shimizu 890ddd
	~FreeDistortBaseFx();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void doCompute(TTile &tile, double frame, const TRenderSettings &ri);
Toshihiro Shimizu 890ddd
	void doDryCompute(TRectD &rect, double frame, const TRenderSettings &ri);
Toshihiro Shimizu 890ddd
	void onPortConnected(TFxPort *port);
Toshihiro Shimizu 890ddd
	bool canHandle(const TRenderSettings &info, double frame);
Toshihiro Shimizu 890ddd
	int getMemoryRequirement(const TRectD &rect, double frame, const TRenderSettings &info);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void transform(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 safeTransform(
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
		TRectD &inBBox);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void getParamUIs(TParamUIConcept *&concepts, int &length);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	bool m_isCastShadow;
Toshihiro Shimizu 890ddd
	TRasterFxPort m_input;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TIntEnumParamP m_distortType;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointParamP m_p00_a;
Toshihiro Shimizu 890ddd
	TPointParamP m_p00_b;
Toshihiro Shimizu 890ddd
	TPointParamP m_p01_a;
Toshihiro Shimizu 890ddd
	TPointParamP m_p01_b;
Toshihiro Shimizu 890ddd
	TPointParamP m_p11_a;
Toshihiro Shimizu 890ddd
	TPointParamP m_p11_b;
Toshihiro Shimizu 890ddd
	TPointParamP m_p10_a;
Toshihiro Shimizu 890ddd
	TPointParamP m_p10_b;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TBoolParamP m_deactivate;
Toshihiro Shimizu 890ddd
	TPixelParamP m_color;
Toshihiro Shimizu 890ddd
	TDoubleParamP m_fade;
Toshihiro Shimizu 890ddd
	TDoubleParamP m_upTransp;
Toshihiro Shimizu 890ddd
	TDoubleParamP m_downTransp;
Toshihiro Shimizu 890ddd
	TDoubleParamP m_upBlur;
Toshihiro Shimizu 890ddd
	TDoubleParamP m_downBlur;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class FreeDistortFx : public FreeDistortBaseFx
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	FX_PLUGIN_DECLARATION(FreeDistortFx)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	FreeDistortFx() : FreeDistortBaseFx(false) {}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class CastShadowFx : public FreeDistortBaseFx
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	FX_PLUGIN_DECLARATION(CastShadowFx)
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	CastShadowFx() : FreeDistortBaseFx(true)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
FreeDistortBaseFx::FreeDistortBaseFx(bool isCastShadow)
Toshihiro Shimizu 890ddd
	: m_deactivate(false), m_color(TPixel32::Black), m_fade(0.0), m_upTransp(0.0), m_downTransp(0.0), m_upBlur(0.0), m_downBlur(0.0), m_isCastShadow(isCastShadow), m_distortType(new TIntEnumParam(PERSPECTIVE, "Perspective"))
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_upBlur->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	m_downBlur->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	double ext = 400.;
Toshihiro Shimizu 890ddd
	double inn = 400.;
Toshihiro Shimizu 890ddd
	m_p00_a = TPointD(-ext, -ext);
Toshihiro Shimizu 890ddd
	m_p00_b = TPointD(-inn, -inn);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_p01_a = TPointD(-ext, ext);
Toshihiro Shimizu 890ddd
	m_p01_b = TPointD(-inn, inn);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_p11_a = TPointD(ext, ext);
Toshihiro Shimizu 890ddd
	m_p11_b = TPointD(inn, inn);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_p10_a = TPointD(ext, -ext);
Toshihiro Shimizu 890ddd
	m_p10_b = TPointD(inn, -inn);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_p00_b->getX()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	m_p00_b->getY()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	m_p10_b->getX()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	m_p10_b->getY()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	m_p01_b->getX()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	m_p01_b->getY()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	m_p11_b->getX()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	m_p11_b->getY()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_p00_a->getX()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	m_p00_a->getY()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	m_p10_a->getX()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	m_p10_a->getY()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	m_p01_a->getX()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	m_p01_a->getY()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	m_p11_a->getX()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	m_p11_a->getY()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bindParam(this, "distort_type", m_distortType);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bindParam(this, "bottom_left_b", m_p00_b);
Toshihiro Shimizu 890ddd
	bindParam(this, "bottom_right_b", m_p10_b);
Toshihiro Shimizu 890ddd
	bindParam(this, "top_left_b", m_p01_b);
Toshihiro Shimizu 890ddd
	bindParam(this, "top_right_b", m_p11_b);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bindParam(this, "bottom_left_a", m_p00_a);
Toshihiro Shimizu 890ddd
	bindParam(this, "bottom_right_a", m_p10_a);
Toshihiro Shimizu 890ddd
	bindParam(this, "top_left_a", m_p01_a);
Toshihiro Shimizu 890ddd
	bindParam(this, "top_right_a", m_p11_a);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (isCastShadow) {
Toshihiro Shimizu 890ddd
		bindParam(this, "color", m_color);
Toshihiro Shimizu 890ddd
		bindParam(this, "fade", m_fade);
Toshihiro Shimizu 890ddd
		bindParam(this, "up_transp", m_upTransp);
Toshihiro Shimizu 890ddd
		bindParam(this, "down_transp", m_downTransp);
Toshihiro Shimizu 890ddd
		bindParam(this, "up_blur", m_upBlur);
Toshihiro Shimizu 890ddd
		bindParam(this, "down_blur", m_downBlur);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_color->enableMatte(false);
Toshihiro Shimizu 890ddd
		m_fade->setValueRange(0.0, 100.0);
Toshihiro Shimizu 890ddd
		m_upTransp->setValueRange(0.0, 100.0);
Toshihiro Shimizu 890ddd
		m_downTransp->setValueRange(0.0, 100.0);
Toshihiro Shimizu 890ddd
		m_upBlur->setValueRange(0.0, (std::numeric_limits<double>::max)());</double>
Toshihiro Shimizu 890ddd
		m_downBlur->setValueRange(0.0, (std::numeric_limits<double>::max)());</double>
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bindParam(this, "deactivate", m_deactivate);
Toshihiro Shimizu 890ddd
	addInputPort("source", m_input);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_p00_a->getX()->setValueRange(-1000, 1000);
Toshihiro Shimizu 890ddd
	m_p00_b->getX()->setValueRange(-1000, 1000);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_p00_a->getY()->setValueRange(-1000, 1000);
Toshihiro Shimizu 890ddd
	m_p00_b->getY()->setValueRange(-1000, 1000);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_p01_a->getX()->setValueRange(-1000, 1000);
Toshihiro Shimizu 890ddd
	m_p01_b->getX()->setValueRange(-1000, 1000);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_p01_a->getY()->setValueRange(-1000, 1000);
Toshihiro Shimizu 890ddd
	m_p01_b->getY()->setValueRange(-1000, 1000);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_p11_a->getX()->setValueRange(-1000, 1000);
Toshihiro Shimizu 890ddd
	m_p11_b->getX()->setValueRange(-1000, 1000);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_p11_a->getY()->setValueRange(-1000, 1000);
Toshihiro Shimizu 890ddd
	m_p11_b->getY()->setValueRange(-1000, 1000);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_p10_a->getX()->setValueRange(-1000, 1000);
Toshihiro Shimizu 890ddd
	m_p10_b->getX()->setValueRange(-1000, 1000);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_p10_a->getY()->setValueRange(-1000, 1000);
Toshihiro Shimizu 890ddd
	m_p10_b->getY()->setValueRange(-1000, 1000);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_distortType->addItem(BILINEAR, "Bilinear");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
FreeDistortBaseFx::~FreeDistortBaseFx()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool FreeDistortBaseFx::canHandle(const TRenderSettings &info, double frame)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Blurs cant deal with anisotropic affines, so these are retained above
Toshihiro Shimizu 890ddd
	return m_upBlur->getValue(frame) == 0 && m_downBlur->getValue(frame) == 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool FreeDistortBaseFx::doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_input.isConnected()) {
Toshihiro Shimizu 890ddd
		//We'll treat this fx like a zerary one. The idea is, since
Toshihiro Shimizu 890ddd
		//the task of taking images and pre-images of rects through
Toshihiro Shimizu 890ddd
		//these kind of distortions is definitely non-trivial, we'll
Toshihiro Shimizu 890ddd
		//simply avoid doing so...
Toshihiro Shimizu 890ddd
		bBox = TConsts::infiniteRectD;
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		/*
Toshihiro Shimizu 890ddd
    bool ret = m_input->doGetBBox(frame, bBox);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
    if(m_deactivate->getValue())
Toshihiro Shimizu 890ddd
      return ret;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
    TPointD p00_a = m_p00_a->getValue(frame);
Toshihiro Shimizu 890ddd
    TPointD p00_b = m_p00_b->getValue(frame);
Toshihiro Shimizu 890ddd
    TPointD p10_a = m_p10_a->getValue(frame);
Toshihiro Shimizu 890ddd
    TPointD p10_b = m_p10_b->getValue(frame);
Toshihiro Shimizu 890ddd
    TPointD p01_a = m_p01_a->getValue(frame);
Toshihiro Shimizu 890ddd
    TPointD p01_b = m_p01_b->getValue(frame);
Toshihiro Shimizu 890ddd
    TPointD p11_a = m_p11_a->getValue(frame);
Toshihiro Shimizu 890ddd
    TPointD p11_b = m_p11_b->getValue(frame);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m_isCastShadow)
Toshihiro Shimizu 890ddd
    {
Toshihiro Shimizu 890ddd
			tswap(p00_a, p01_a);
Toshihiro Shimizu 890ddd
      tswap(p10_a, p11_a);
Toshihiro Shimizu 890ddd
		}*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		/*TRectD source;
Shinya Kitaoka 12c444
    source.x0 = std::min(p00_b.x, p10_b.x, p01_b.x, p11_b.x);
Shinya Kitaoka 12c444
    source.y0 = std::min(p00_b.y, p10_b.y, p01_b.y, p11_b.y);
Shinya Kitaoka 12c444
    source.x1 = std::max(p00_b.x, p10_b.x, p01_b.x, p11_b.x);
Shinya Kitaoka 12c444
    source.y1 = std::max(p00_b.y, p10_b.y, p01_b.y, p11_b.y);
Toshihiro Shimizu 890ddd
    bBox *= source;
Toshihiro Shimizu 890ddd
    
Toshihiro Shimizu 890ddd
    int distortType = m_distortType->getValue();
Toshihiro Shimizu 890ddd
    if(distortType == PERSPECTIVE)
Toshihiro Shimizu 890ddd
    {
Toshihiro Shimizu 890ddd
      PerspectiveDistorter distorter(
Toshihiro Shimizu 890ddd
          p00_b, p10_b, p01_b, p11_b,
Toshihiro Shimizu 890ddd
          p00_a, p10_a, p01_a, p11_a
Toshihiro Shimizu 890ddd
      );
Toshihiro Shimizu 890ddd
      bBox = distorter.map(bBox);
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
    else if(distortType == BILINEAR)
Toshihiro Shimizu 890ddd
    {
Toshihiro Shimizu 890ddd
      BilinearDistorter distorter(
Toshihiro Shimizu 890ddd
        p00_b, p10_b, p01_b, p11_b,
Toshihiro Shimizu 890ddd
        p00_a, p10_a, p01_a, p11_a
Toshihiro Shimizu 890ddd
      );
Toshihiro Shimizu 890ddd
      bBox = distorter.map(bBox);
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
    else assert(0);*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Further, we will also avoid the assumption that the bbox
Toshihiro Shimizu 890ddd
		//is defined by that of destination points...
Toshihiro Shimizu 890ddd
		/*TRectD result;
Shinya Kitaoka 12c444
    result.x0 = std::min(p00_a.x, p10_a.x, p01_a.x, p11_a.x);
Shinya Kitaoka 12c444
    result.y0 = std::min(p00_a.y, p10_a.y, p01_a.y, p11_a.y);
Shinya Kitaoka 12c444
    result.x1 = std::max(p00_a.x, p10_a.x, p01_a.x, p11_a.x);
Shinya Kitaoka 12c444
    result.y1 = std::max(p00_a.y, p10_a.y, p01_a.y, p11_a.y);
Toshihiro Shimizu 890ddd
    bBox = result;    //bBox *= result;*/
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		bBox = TRectD();
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_upBlur->getValue(frame) > 0 || m_downBlur->getValue(frame) > 0) {
Shinya Kitaoka 12c444
		int brad = std::max((int)m_upBlur->getValue(frame), (int)m_downBlur->getValue(frame));
Toshihiro Shimizu 890ddd
		bBox.x0 -= brad;
Toshihiro Shimizu 890ddd
		bBox.x1 += brad;
Toshihiro Shimizu 890ddd
		bBox.y0 -= brad;
Toshihiro Shimizu 890ddd
		bBox.y1 += brad;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// ------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FreeDistortBaseFx::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
	TPointD p00_b = m_p00_b->getValue(frame);
Toshihiro Shimizu 890ddd
	TPointD p10_b = m_p10_b->getValue(frame);
Toshihiro Shimizu 890ddd
	TPointD p01_b = m_p01_b->getValue(frame);
Toshihiro Shimizu 890ddd
	TPointD p11_b = m_p11_b->getValue(frame);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD p00_a = m_p00_a->getValue(frame);
Toshihiro Shimizu 890ddd
	TPointD p10_a = m_p10_a->getValue(frame);
Toshihiro Shimizu 890ddd
	TPointD p01_a = m_p01_a->getValue(frame);
Toshihiro Shimizu 890ddd
	TPointD p11_a = m_p11_a->getValue(frame);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_isCastShadow) {
Toshihiro Shimizu 890ddd
		//Shadows are mirrored
Toshihiro Shimizu 890ddd
		tswap(p00_a, p01_a);
Toshihiro Shimizu 890ddd
		tswap(p10_a, p11_a);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Build the input affine
Toshihiro Shimizu 890ddd
	infoOnInput = infoOnOutput;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double scale = 0;
Shinya Kitaoka 12c444
	scale = std::max(scale, norm(p10_a - p00_a) / norm(p10_b - p00_b));
Shinya Kitaoka 12c444
	scale = std::max(scale, norm(p01_a - p00_a) / norm(p01_b - p00_b));
Shinya Kitaoka 12c444
	scale = std::max(scale, norm(p11_a - p10_a) / norm(p11_b - p10_b));
Shinya Kitaoka 12c444
	scale = std::max(scale, norm(p11_a - p01_a) / norm(p11_b - p01_b));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	scale *= sqrt(fabs(infoOnInput.m_affine.det()));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (infoOnOutput.m_isSwatch) {
Toshihiro Shimizu 890ddd
		//Swatch viewers work out a lite version of the distort: only contractions
Toshihiro Shimizu 890ddd
		//are passed below in the schematic - so that input memory load is always at minimum.
Toshihiro Shimizu 890ddd
		//This is allowed in order to make fx adjusts the less frustrating as possible.
Toshihiro Shimizu 890ddd
		if (scale > 1)
Toshihiro Shimizu 890ddd
			scale = 1;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	infoOnInput.m_affine = TScale(scale);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Build rectOnInput
Toshihiro Shimizu 890ddd
	p00_a = infoOnOutput.m_affine * p00_a;
Toshihiro Shimizu 890ddd
	p10_a = infoOnOutput.m_affine * p10_a;
Toshihiro Shimizu 890ddd
	p01_a = infoOnOutput.m_affine * p01_a;
Toshihiro Shimizu 890ddd
	p11_a = infoOnOutput.m_affine * p11_a;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	p00_b = infoOnInput.m_affine * p00_b;
Toshihiro Shimizu 890ddd
	p10_b = infoOnInput.m_affine * p10_b;
Toshihiro Shimizu 890ddd
	p01_b = infoOnInput.m_affine * p01_b;
Toshihiro Shimizu 890ddd
	p11_b = infoOnInput.m_affine * p11_b;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_distortType->getValue() == PERSPECTIVE) {
Toshihiro Shimizu 890ddd
		PerspectiveDistorter pd(
Toshihiro Shimizu 890ddd
			p00_b, p10_b, p01_b, p11_b,
Toshihiro Shimizu 890ddd
			p00_a, p10_a, p01_a, p11_a);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		rectOnInput = ((TQuadDistorter *)&pd)->invMap(rectOnOutput);
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		BilinearDistorter bd(
Toshihiro Shimizu 890ddd
			p00_b, p10_b, p01_b, p11_b,
Toshihiro Shimizu 890ddd
			p00_a, p10_a, p01_a, p11_a);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		rectOnInput = ((TQuadDistorter *)&bd)->invMap(rectOnOutput);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (rectOnInput.x0 != TConsts::infiniteRectD.x0)
Toshihiro Shimizu 890ddd
		rectOnInput.x0 = tfloor(rectOnInput.x0);
Toshihiro Shimizu 890ddd
	if (rectOnInput.y0 != TConsts::infiniteRectD.y0)
Toshihiro Shimizu 890ddd
		rectOnInput.y0 = tfloor(rectOnInput.y0);
Toshihiro Shimizu 890ddd
	if (rectOnInput.x1 != TConsts::infiniteRectD.x1)
Toshihiro Shimizu 890ddd
		rectOnInput.x1 = tceil(rectOnInput.x1);
Toshihiro Shimizu 890ddd
	if (rectOnInput.y1 != TConsts::infiniteRectD.y1)
Toshihiro Shimizu 890ddd
		rectOnInput.y1 = tceil(rectOnInput.y1);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// ------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FreeDistortBaseFx::safeTransform(
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
	TRectD &inBBox)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(port == 0 && m_input.isConnected());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_deactivate->getValue()) {
Toshihiro Shimizu 890ddd
		infoOnInput = infoOnOutput;
Toshihiro Shimizu 890ddd
		rectOnInput = rectOnOutput;
Toshihiro Shimizu 890ddd
		m_input->getBBox(frame, inBBox, infoOnInput);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Avoid the singular matrix cases
Toshihiro Shimizu 890ddd
	if (fabs(infoOnOutput.m_affine.det()) < 1.e-3) {
Toshihiro Shimizu 890ddd
		infoOnInput = infoOnOutput;
Toshihiro Shimizu 890ddd
		rectOnInput.empty();
Toshihiro Shimizu 890ddd
		m_input->getBBox(frame, inBBox, infoOnInput);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	transform(frame, port, rectOnOutput, infoOnOutput, rectOnInput, infoOnInput);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_input->getBBox(frame, inBBox, infoOnInput);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//In case inBBox is infinite, such as with gradients, also intersect with the input quadrilateral's bbox
Toshihiro Shimizu 890ddd
	if (inBBox == TConsts::infiniteRectD) {
Toshihiro Shimizu 890ddd
		TPointD affP00_b(infoOnInput.m_affine * m_p00_b->getValue(frame));
Toshihiro Shimizu 890ddd
		TPointD affP10_b(infoOnInput.m_affine * m_p10_b->getValue(frame));
Toshihiro Shimizu 890ddd
		TPointD affP01_b(infoOnInput.m_affine * m_p01_b->getValue(frame));
Toshihiro Shimizu 890ddd
		TPointD affP11_b(infoOnInput.m_affine * m_p11_b->getValue(frame));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TRectD source;
Shinya Kitaoka 12c444
		source.x0 = std::min({affP00_b.x, affP10_b.x, affP01_b.x, affP11_b.x});
Shinya Kitaoka 12c444
		source.y0 = std::min({affP00_b.y, affP10_b.y, affP01_b.y, affP11_b.y});
Shinya Kitaoka 12c444
		source.x1 = std::max({affP00_b.x, affP10_b.x, affP01_b.x, affP11_b.x});
Shinya Kitaoka 12c444
		source.y1 = std::max({affP00_b.y, affP10_b.y, affP01_b.y, affP11_b.y});
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		rectOnInput *= source;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// ------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FreeDistortBaseFx::getParamUIs(TParamUIConcept *&concepts, int &length)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	concepts = new TParamUIConcept[length = 14];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	concepts[0].m_type = TParamUIConcept::QUAD;
Toshihiro Shimizu 890ddd
	concepts[0].m_params.push_back(m_p00_b);
Toshihiro Shimizu 890ddd
	concepts[0].m_params.push_back(m_p10_b);
Toshihiro Shimizu 890ddd
	concepts[0].m_params.push_back(m_p11_b);
Toshihiro Shimizu 890ddd
	concepts[0].m_params.push_back(m_p01_b);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	concepts[1].m_type = TParamUIConcept::QUAD;
Toshihiro Shimizu 890ddd
	concepts[1].m_params.push_back(m_p00_a);
Toshihiro Shimizu 890ddd
	concepts[1].m_params.push_back(m_p10_a);
Toshihiro Shimizu 890ddd
	concepts[1].m_params.push_back(m_p11_a);
Toshihiro Shimizu 890ddd
	concepts[1].m_params.push_back(m_p01_a);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	concepts[2].m_type = TParamUIConcept::VECTOR;
Toshihiro Shimizu 890ddd
	concepts[2].m_params.push_back(m_p00_b);
Toshihiro Shimizu 890ddd
	concepts[2].m_params.push_back(m_p00_a);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	concepts[3].m_type = TParamUIConcept::VECTOR;
Toshihiro Shimizu 890ddd
	concepts[3].m_params.push_back(m_p10_b);
Toshihiro Shimizu 890ddd
	concepts[3].m_params.push_back(m_p10_a);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	concepts[4].m_type = TParamUIConcept::VECTOR;
Toshihiro Shimizu 890ddd
	concepts[4].m_params.push_back(m_p01_b);
Toshihiro Shimizu 890ddd
	concepts[4].m_params.push_back(m_p01_a);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	concepts[5].m_type = TParamUIConcept::VECTOR;
Toshihiro Shimizu 890ddd
	concepts[5].m_params.push_back(m_p11_b);
Toshihiro Shimizu 890ddd
	concepts[5].m_params.push_back(m_p11_a);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	concepts[6].m_type = TParamUIConcept::POINT;
Toshihiro Shimizu 890ddd
	concepts[6].m_label = "Bottom Left Src";
Toshihiro Shimizu 890ddd
	concepts[6].m_params.push_back(m_p00_b);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	concepts[7].m_type = TParamUIConcept::POINT;
Toshihiro Shimizu 890ddd
	concepts[7].m_label = "Bottom Right Src";
Toshihiro Shimizu 890ddd
	concepts[7].m_params.push_back(m_p10_b);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	concepts[8].m_type = TParamUIConcept::POINT;
Toshihiro Shimizu 890ddd
	concepts[8].m_label = "Top Left Src";
Toshihiro Shimizu 890ddd
	concepts[8].m_params.push_back(m_p01_b);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	concepts[9].m_type = TParamUIConcept::POINT;
Toshihiro Shimizu 890ddd
	concepts[9].m_label = "Top Right Src";
Toshihiro Shimizu 890ddd
	concepts[9].m_params.push_back(m_p11_b);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	concepts[10].m_type = TParamUIConcept::POINT;
Toshihiro Shimizu 890ddd
	concepts[10].m_label = "Bottom Left Dst";
Toshihiro Shimizu 890ddd
	concepts[10].m_params.push_back(m_p00_a);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	concepts[11].m_type = TParamUIConcept::POINT;
Toshihiro Shimizu 890ddd
	concepts[11].m_label = "Bottom Right Dst";
Toshihiro Shimizu 890ddd
	concepts[11].m_params.push_back(m_p10_a);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	concepts[12].m_type = TParamUIConcept::POINT;
Toshihiro Shimizu 890ddd
	concepts[12].m_label = "Top Left Dst";
Toshihiro Shimizu 890ddd
	concepts[12].m_params.push_back(m_p01_a);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	concepts[13].m_type = TParamUIConcept::POINT;
Toshihiro Shimizu 890ddd
	concepts[13].m_label = "Top Right Dst";
Toshihiro Shimizu 890ddd
	concepts[13].m_params.push_back(m_p11_a);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// ------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pix=""></typename>
Toshihiro Shimizu 890ddd
void doFade(TRasterPT<pix> &ras, PIX col, double intensity)</pix>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double maxChannelValueD = PIX::maxChannelValue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int j;
Toshihiro Shimizu 890ddd
	ras->lock();
Toshihiro Shimizu 890ddd
	for (j = 0; j < ras->getLy(); j++) {
Toshihiro Shimizu 890ddd
		PIX *pix = ras->pixels(j);
Toshihiro Shimizu 890ddd
		PIX *endPix = pix + ras->getLx();
Toshihiro Shimizu 890ddd
		while (pix < endPix) {
Toshihiro Shimizu 890ddd
			if (pix->m > 0) {
Toshihiro Shimizu 890ddd
				double factor = pix->m / maxChannelValueD;
Toshihiro Shimizu 890ddd
				int val;
Toshihiro Shimizu 890ddd
				val = troundp(pix->r + intensity * (col.r * factor - pix->r));
Toshihiro Shimizu 890ddd
				pix->r = (val > PIX::maxChannelValue) ? PIX::maxChannelValue : val;
Toshihiro Shimizu 890ddd
				val = troundp(pix->g + intensity * (col.g * factor - pix->g));
Toshihiro Shimizu 890ddd
				pix->g = (val > PIX::maxChannelValue) ? PIX::maxChannelValue : val;
Toshihiro Shimizu 890ddd
				val = troundp(pix->b + intensity * (col.b * factor - pix->b));
Toshihiro Shimizu 890ddd
				pix->b = (val > PIX::maxChannelValue) ? PIX::maxChannelValue : val;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			++pix;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	ras->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pix=""></typename>
Toshihiro Shimizu 890ddd
void doTransparency(TRasterPT<pix> &ras, double downTransp, double upTransp, double y0, double y1)</pix>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(y0 <= 0.0 && y1 >= ras->getLy() - 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double den = y1 - y0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int j;
Toshihiro Shimizu 890ddd
	ras->lock();
Toshihiro Shimizu 890ddd
	for (j = 0; j < ras->getLy(); j++) {
Toshihiro Shimizu 890ddd
		double transp = (1 - downTransp) + (downTransp - upTransp) * (j - y0) / den;
Toshihiro Shimizu 890ddd
		PIX *pix = ras->pixels(j);
Toshihiro Shimizu 890ddd
		PIX *endPix = pix + ras->getLx();
Toshihiro Shimizu 890ddd
		while (pix < endPix) {
Toshihiro Shimizu 890ddd
			if (pix->m > 0) {
Toshihiro Shimizu 890ddd
				pix->r = troundp(pix->r * transp);
Toshihiro Shimizu 890ddd
				pix->g = troundp(pix->g * transp);
Toshihiro Shimizu 890ddd
				pix->b = troundp(pix->b * transp);
Toshihiro Shimizu 890ddd
				pix->m = troundp(pix->m * transp);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			++pix;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	ras->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// ------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pix=""></typename>
Toshihiro Shimizu 890ddd
inline void filterPixel(PIX *bufin, int wrap, PIX *bufout, double blur, int coord, int maxVal)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int rad, k, index;
Toshihiro Shimizu 890ddd
	double coeff, weight;
Toshihiro Shimizu 890ddd
	double valr = 0.0, valg = 0.0, valb = 0.0, valm = 0.0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	rad = tceil(blur);
Toshihiro Shimizu 890ddd
	coeff = 1.0 / rad;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	valr = bufin[0].r;
Toshihiro Shimizu 890ddd
	valg = bufin[0].g;
Toshihiro Shimizu 890ddd
	valb = bufin[0].b;
Toshihiro Shimizu 890ddd
	valm = bufin[0].m;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (k = 1, index = wrap, weight = (1 - coeff); k < rad; k++, index += wrap, weight -= coeff) {
Toshihiro Shimizu 890ddd
		if (k + coord < maxVal) {
Toshihiro Shimizu 890ddd
			if (-k + coord >= 0) {
Toshihiro Shimizu 890ddd
				valr += (bufin[index].r + bufin[-index].r) * weight;
Toshihiro Shimizu 890ddd
				valg += (bufin[index].g + bufin[-index].g) * weight;
Toshihiro Shimizu 890ddd
				valb += (bufin[index].b + bufin[-index].b) * weight;
Toshihiro Shimizu 890ddd
				valm += (bufin[index].m + bufin[-index].m) * weight;
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				valr += bufin[index].r * weight;
Toshihiro Shimizu 890ddd
				valg += bufin[index].g * weight;
Toshihiro Shimizu 890ddd
				valb += bufin[index].b * weight;
Toshihiro Shimizu 890ddd
				valm += bufin[index].m * weight;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} else if (-k + coord >= 0) {
Toshihiro Shimizu 890ddd
			if (k + coord < maxVal) {
Toshihiro Shimizu 890ddd
				valr += (bufin[index].r + bufin[-index].r) * weight;
Toshihiro Shimizu 890ddd
				valg += (bufin[index].g + bufin[-index].g) * weight;
Toshihiro Shimizu 890ddd
				valb += (bufin[index].b + bufin[-index].b) * weight;
Toshihiro Shimizu 890ddd
				valm += (bufin[index].m + bufin[-index].m) * weight;
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				valr += bufin[-index].r * weight;
Toshihiro Shimizu 890ddd
				valg += bufin[-index].g * weight;
Toshihiro Shimizu 890ddd
				valb += bufin[-index].b * weight;
Toshihiro Shimizu 890ddd
				valm += bufin[-index].m * weight;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	valr *= coeff;
Toshihiro Shimizu 890ddd
	valg *= coeff;
Toshihiro Shimizu 890ddd
	valb *= coeff;
Toshihiro Shimizu 890ddd
	valm *= coeff;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bufout->r = troundp(valr);
Toshihiro Shimizu 890ddd
	bufout->g = troundp(valg);
Toshihiro Shimizu 890ddd
	bufout->b = troundp(valb);
Toshihiro Shimizu 890ddd
	bufout->m = troundp(valm);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*----------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pix=""></typename>
Toshihiro Shimizu 890ddd
void doBlur(TRasterPT<pix> &r,</pix>
Toshihiro Shimizu 890ddd
			double blur0, double blur1,
Toshihiro Shimizu 890ddd
			double transp0, double transp1,
Toshihiro Shimizu 890ddd
			double y0, double y1)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int lx, ly, wrap;
Toshihiro Shimizu 890ddd
	int i, j, brad, blur_max;
Toshihiro Shimizu 890ddd
	PIX *bufin, *bufout, *pixin, *pixout, *row;
Toshihiro Shimizu 890ddd
	double cur_blur, actual_blur, blur_incr, cur_transp, actual_transp, transp_incr;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	lx = r->getLx();
Toshihiro Shimizu 890ddd
	ly = r->getLy();
Toshihiro Shimizu 890ddd
	wrap = r->getWrap();
Shinya Kitaoka 12c444
	blur_max = (int)std::max(blur0, blur1);
Toshihiro Shimizu 890ddd
	brad = tceil(blur_max);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//assert(y0 <= brad && y1 >= r->getLy()-1 - 2 * brad + y0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double den = y1 - y0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	blur_incr = (blur1 - blur0) / den;
Toshihiro Shimizu 890ddd
	transp_incr = (transp0 - transp1) / den;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 12c444
	row = new PIX[std::max(lx, ly)];
Toshihiro Shimizu 890ddd
	r->lock();
Toshihiro Shimizu 890ddd
	bufin = r->pixels(0);
Shinya Kitaoka 12c444
	for (i = 0, cur_blur = blur0 + (blur1 - blur0) * (i - y0) / den, 0.0, actual_blur = std::max(cur_blur, 0.0);
Toshihiro Shimizu 890ddd
		 i < ly;
Shinya Kitaoka 12c444
		 i++, bufin += wrap, cur_blur += blur_incr, actual_blur = std::max(cur_blur, 0.0)) {
Toshihiro Shimizu 890ddd
		pixin = bufin;
Toshihiro Shimizu 890ddd
		for (j = 0; j < lx; j++, pixin++) {
Toshihiro Shimizu 890ddd
			if (cur_blur > 1.0)
Toshihiro Shimizu 890ddd
				filterPixel(pixin, 1, row + j, actual_blur, j, lx);
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				row[j] = *pixin;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		for (j = 0; j < lx; j++)
Toshihiro Shimizu 890ddd
			bufin[j] = row[j];
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bufin = r->pixels(0);
Toshihiro Shimizu 890ddd
	bufout = r->pixels(0);
Toshihiro Shimizu 890ddd
	for (i = 0; i < lx; i++, bufin++, bufout++) {
Toshihiro Shimizu 890ddd
		pixin = bufin;
Toshihiro Shimizu 890ddd
		pixout = bufout;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 12c444
		for (j = 0, cur_blur = blur0 + (blur1 - blur0) * (j - y0) / den, actual_blur = std::max(cur_blur, 0.0);
Toshihiro Shimizu 890ddd
			 j < ly;
Shinya Kitaoka 12c444
			 j++, pixin += wrap, cur_blur += blur_incr, actual_blur = std::max(cur_blur, 0.0)) {
Toshihiro Shimizu 890ddd
			if (cur_blur > 1.0)
Toshihiro Shimizu 890ddd
				filterPixel(pixin, wrap, row + j, actual_blur, j, ly);
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				row[j] = *pixin;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (transp0 > 0 || transp1 > 0)
Shinya Kitaoka 12c444
			for (j = 0, cur_transp = 1 - transp0 + (transp0 - transp1) * (j - y0) / den, actual_transp = std::max(cur_transp, 0.0);
Toshihiro Shimizu 890ddd
				 j < ly;
Shinya Kitaoka 12c444
				 j++, pixout += wrap, cur_transp += transp_incr, actual_transp = std::max(cur_transp, 0.0)) {
Toshihiro Shimizu 890ddd
				pixout->r = troundp(row[j].r * actual_transp);
Toshihiro Shimizu 890ddd
				pixout->g = troundp(row[j].g * actual_transp);
Toshihiro Shimizu 890ddd
				pixout->b = troundp(row[j].b * actual_transp);
Toshihiro Shimizu 890ddd
				pixout->m = troundp(row[j].m * actual_transp);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			for (j = 0; j < ly; j++, pixout += wrap) {
Toshihiro Shimizu 890ddd
				pixout->r = row[j].r;
Toshihiro Shimizu 890ddd
				pixout->g = row[j].g;
Toshihiro Shimizu 890ddd
				pixout->b = row[j].b;
Toshihiro Shimizu 890ddd
				pixout->m = row[j].m;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	r->unlock();
Toshihiro Shimizu 890ddd
	delete[] row;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// ------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FreeDistortBaseFx::doDryCompute(TRectD &rect, double frame, const TRenderSettings &info)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_input.isConnected())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_deactivate->getValue()) {
Toshihiro Shimizu 890ddd
		m_input->dryCompute(rect, frame, info);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRectD rectOnInput;
Toshihiro Shimizu 890ddd
	TRenderSettings infoOnInput;
Toshihiro Shimizu 890ddd
	TRectD inBBox;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	safeTransform(frame, 0, rect, info, rectOnInput, infoOnInput, inBBox);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	rectOnInput *= inBBox;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!myIsEmpty(rectOnInput))
Toshihiro Shimizu 890ddd
		m_input->dryCompute(rectOnInput, frame, infoOnInput);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// ------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FreeDistortBaseFx::doCompute(TTile &tile, double frame, const TRenderSettings &ri)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_input.isConnected())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Upon deactivation, this fx does nothing.
Toshihiro Shimizu 890ddd
	if (m_deactivate->getValue()) {
Toshihiro Shimizu 890ddd
		m_input->compute(tile, frame, ri);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Get the source quad
Toshihiro Shimizu 890ddd
	TPointD p00_b = m_p00_b->getValue(frame);
Toshihiro Shimizu 890ddd
	TPointD p10_b = m_p10_b->getValue(frame);
Toshihiro Shimizu 890ddd
	TPointD p01_b = m_p01_b->getValue(frame);
Toshihiro Shimizu 890ddd
	TPointD p11_b = m_p11_b->getValue(frame);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Get destination quad
Toshihiro Shimizu 890ddd
	TPointD p00_a = m_p00_a->getValue(frame);
Toshihiro Shimizu 890ddd
	TPointD p10_a = m_p10_a->getValue(frame);
Toshihiro Shimizu 890ddd
	TPointD p01_a = m_p01_a->getValue(frame);
Toshihiro Shimizu 890ddd
	TPointD p11_a = m_p11_a->getValue(frame);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_isCastShadow) {
Toshihiro Shimizu 890ddd
		//Shadows are mirrored
Toshihiro Shimizu 890ddd
		tswap(p00_a, p01_a);
Toshihiro Shimizu 890ddd
		tswap(p10_a, p11_a);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Get requested tile's geometry
Toshihiro Shimizu 890ddd
	TRasterP tileRas(tile.getRaster());
Toshihiro Shimizu 890ddd
	TRectD tileRect(convert(tileRas->getBounds()) + tile.m_pos);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Call transform to get the minimal rectOnInput
Toshihiro Shimizu 890ddd
	TRectD inRect;
Toshihiro Shimizu 890ddd
	TRenderSettings riNew;
Toshihiro Shimizu 890ddd
	TRectD inBBox;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	safeTransform(frame, 0, tileRect, ri, inRect, riNew, inBBox);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Intersect with the bbox
Toshihiro Shimizu 890ddd
	inRect *= inBBox;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (myIsEmpty(inRect))
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double scale = ri.m_affine.a11;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double downBlur = m_downBlur->getValue(frame) * scale;
Toshihiro Shimizu 890ddd
	double upBlur = m_upBlur->getValue(frame) * scale;
Shinya Kitaoka 12c444
	int brad = tceil(std::max(downBlur, upBlur));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	inRect = inRect.enlarge(brad);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TDimension inRectSize(tceil(inRect.getLx()), tceil(inRect.getLy()));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TTile inTile;
Toshihiro Shimizu 890ddd
	m_input->allocateAndCompute(inTile, inRect.getP00(), inRectSize, tileRas, frame, riNew);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD inTilePosRi = inTile.m_pos;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Update quads by the scale factors
Toshihiro Shimizu 890ddd
	p00_b = riNew.m_affine * p00_b;
Toshihiro Shimizu 890ddd
	p10_b = riNew.m_affine * p10_b;
Toshihiro Shimizu 890ddd
	p01_b = riNew.m_affine * p01_b;
Toshihiro Shimizu 890ddd
	p11_b = riNew.m_affine * p11_b;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	p00_a = ri.m_affine * p00_a;
Toshihiro Shimizu 890ddd
	p10_a = ri.m_affine * p10_a;
Toshihiro Shimizu 890ddd
	p01_a = ri.m_affine * p01_a;
Toshihiro Shimizu 890ddd
	p11_a = ri.m_affine * p11_a;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	PerspectiveDistorter perpDistorter(
Toshihiro Shimizu 890ddd
		p00_b - inTile.m_pos, p10_b - inTile.m_pos, p01_b - inTile.m_pos, p11_b - inTile.m_pos,
Toshihiro Shimizu 890ddd
		p00_a, p10_a, p01_a, p11_a);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	BilinearDistorter bilDistorter(
Toshihiro Shimizu 890ddd
		p00_b - inTile.m_pos, p10_b - inTile.m_pos, p01_b - inTile.m_pos, p11_b - inTile.m_pos,
Toshihiro Shimizu 890ddd
		p00_a, p10_a, p01_a, p11_a);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TQuadDistorter *distorter;
Toshihiro Shimizu 890ddd
	if (m_distortType->getValue() == PERSPECTIVE)
Toshihiro Shimizu 890ddd
		distorter = &perpDistorter;
Toshihiro Shimizu 890ddd
	else if (m_distortType->getValue() == BILINEAR)
Toshihiro Shimizu 890ddd
		distorter = &bilDistorter;
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		assert(0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_isCastShadow) {
Toshihiro Shimizu 890ddd
		TRaster32P ras32 = inTile.getRaster();
Toshihiro Shimizu 890ddd
		TRaster64P ras64 = inTile.getRaster();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (ras32) {
Toshihiro Shimizu 890ddd
			if (m_fade->getValue(frame) > 0)
Toshihiro Shimizu 890ddd
				doFade(ras32, m_color->getValue(frame), m_fade->getValue(frame) / 100.0);
Toshihiro Shimizu 890ddd
			if (brad > 0)
Toshihiro Shimizu 890ddd
				doBlur(ras32, upBlur, downBlur,
Toshihiro Shimizu 890ddd
					   m_upTransp->getValue(frame) / 100.0, m_downTransp->getValue(frame) / 100.0,
Toshihiro Shimizu 890ddd
					   inBBox.y0 - inTile.m_pos.y, inBBox.y1 - inTile.m_pos.y);
Toshihiro Shimizu 890ddd
			else if (m_upTransp->getValue(frame) > 0 || m_downTransp->getValue(frame) > 0)
Toshihiro Shimizu 890ddd
				doTransparency(ras32, m_upTransp->getValue(frame) / 100.0, m_downTransp->getValue(frame) / 100.0,
Toshihiro Shimizu 890ddd
							   inBBox.y0 - inTile.m_pos.y, inBBox.y1 - inTile.m_pos.y);
Toshihiro Shimizu 890ddd
		} else if (ras64) {
Toshihiro Shimizu 890ddd
			if (m_fade->getValue(frame) > 0)
Toshihiro Shimizu 890ddd
				doFade(ras64, toPixel64(m_color->getValue(frame)), m_fade->getValue(frame) / 100.0);
Toshihiro Shimizu 890ddd
			if (brad > 0)
Toshihiro Shimizu 890ddd
				doBlur(ras64, upBlur, downBlur,
Toshihiro Shimizu 890ddd
					   m_upTransp->getValue(frame) / 100.0, m_downTransp->getValue(frame) / 100.0,
Toshihiro Shimizu 890ddd
					   inBBox.y0 - inTile.m_pos.y, inBBox.y1 - inTile.m_pos.y);
Toshihiro Shimizu 890ddd
			else if (m_upTransp->getValue(frame) > 0 || m_downTransp->getValue(frame) > 0)
Toshihiro Shimizu 890ddd
				doTransparency(ras64, m_upTransp->getValue(frame) / 100.0, m_downTransp->getValue(frame) / 100.0,
Toshihiro Shimizu 890ddd
							   inBBox.y0 - inTile.m_pos.y, inBBox.y1 - inTile.m_pos.y);
Toshihiro Shimizu 890ddd
		} else
Toshihiro Shimizu 890ddd
			assert(false);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	distort(tileRas, inTile.getRaster(), *distorter, convert(tile.m_pos), TRop::Bilinear);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int FreeDistortBaseFx::getMemoryRequirement(const TRectD &rect, double frame, const TRenderSettings &info)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_input.isConnected())
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRectD inRect;
Toshihiro Shimizu 890ddd
	TRenderSettings riNew;
Toshihiro Shimizu 890ddd
	TRectD inBBox;
Toshihiro Shimizu 890ddd
	safeTransform(frame, 0, rect, info, inRect, riNew, inBBox);
Toshihiro Shimizu 890ddd
	inRect *= inBBox;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return TRasterFx::memorySize(inRect, riNew.m_bpp);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
FX_PLUGIN_IDENTIFIER(FreeDistortFx, "freeDistortFx");
Toshihiro Shimizu 890ddd
FX_PLUGIN_IDENTIFIER(CastShadowFx, "castShadowFx");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*----------------------------------------------------------------------------*/