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