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