Toshihiro Shimizu 890ddd
/*------------------------------------
Toshihiro Shimizu 890ddd
 Iwa_DirectionalBlurFx
Toshihiro Shimizu 890ddd
 ボケ足の伸ばし方を選択でき、参照画像を追加した DirectionalBlur
Toshihiro Shimizu 890ddd
//------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "iwa_directionalblurfx.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tparamuiconcept.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
enum FILTER_TYPE { Linear = 0, Gaussian, Flat };
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*------------------------------------------------------------
Toshihiro Shimizu 890ddd
 参照画像の輝度を0〜1に正規化してホストメモリに読み込む
Toshihiro Shimizu 890ddd
------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixel="" raster,="" typename=""></typename>
Toshihiro Shimizu 890ddd
void Iwa_DirectionalBlurFx::setReferenceRaster(const RASTER srcRas,
Shinya Kitaoka 120a6e
                                               float *dstMem, TDimensionI dim) {
Shinya Kitaoka 120a6e
  float *dst_p = dstMem;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (int j = 0; j < dim.ly; j++) {
Shinya Kitaoka 120a6e
    PIXEL *pix = srcRas->pixels(j);
Shinya Kitaoka 120a6e
    for (int i = 0; i < dim.lx; i++, pix++, dst_p++) {
Shinya Kitaoka 120a6e
      (*dst_p) = ((float)pix->r * 0.3f + (float)pix->g * 0.59f +
Shinya Kitaoka 120a6e
                  (float)pix->b * 0.11f) /
Shinya Kitaoka 120a6e
                 (float)PIXEL::maxChannelValue;
shun-iwasawa 481b59
      // clamp
shun-iwasawa 481b59
      (*dst_p) = std::min(1.f, std::max(0.f, (*dst_p)));
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*------------------------------------------------------------
Toshihiro Shimizu 890ddd
 ソース画像を0〜1に正規化してホストメモリに読み込む
Toshihiro Shimizu 890ddd
------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixel="" raster,="" typename=""></typename>
Shinya Kitaoka 120a6e
void Iwa_DirectionalBlurFx::setSourceRaster(const RASTER srcRas, float4 *dstMem,
Shinya Kitaoka 120a6e
                                            TDimensionI dim) {
Shinya Kitaoka 120a6e
  float4 *chann_p = dstMem;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (int j = 0; j < dim.ly; j++) {
Shinya Kitaoka 120a6e
    PIXEL *pix = srcRas->pixels(j);
Shinya Kitaoka 120a6e
    for (int i = 0; i < dim.lx; i++, pix++, chann_p++) {
Shinya Kitaoka 120a6e
      (*chann_p).x = (float)pix->r / (float)PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      (*chann_p).y = (float)pix->g / (float)PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      (*chann_p).z = (float)pix->b / (float)PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      (*chann_p).w = (float)pix->m / (float)PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*------------------------------------------------------------
Toshihiro Shimizu 890ddd
 出力結果をChannel値に変換してタイルに格納
Toshihiro Shimizu 890ddd
------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
template <typename pixel="" raster,="" typename=""></typename>
Shinya Kitaoka 120a6e
void Iwa_DirectionalBlurFx::setOutputRaster(float4 *srcMem, const RASTER dstRas,
Shinya Kitaoka 120a6e
                                            TDimensionI dim, int2 margin) {
Shinya Kitaoka 120a6e
  int out_j = 0;
Shinya Kitaoka 120a6e
  for (int j = margin.y; j < dstRas->getLy() + margin.y; j++, out_j++) {
Shinya Kitaoka 120a6e
    PIXEL *pix     = dstRas->pixels(out_j);
Shinya Kitaoka 120a6e
    float4 *chan_p = srcMem;
Shinya Kitaoka 120a6e
    chan_p += j * dim.lx + margin.x;
Shinya Kitaoka 120a6e
    for (int i = 0; i < dstRas->getLx(); i++, pix++, chan_p++) {
Shinya Kitaoka 120a6e
      float val;
Shinya Kitaoka 120a6e
      val    = (*chan_p).x * (float)PIXEL::maxChannelValue + 0.5f;
Shinya Kitaoka 120a6e
      pix->r = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue)
Shinya Kitaoka 120a6e
                                             ? (float)PIXEL::maxChannelValue
Shinya Kitaoka 120a6e
                                             : val);
Shinya Kitaoka 120a6e
      val    = (*chan_p).y * (float)PIXEL::maxChannelValue + 0.5f;
Shinya Kitaoka 120a6e
      pix->g = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue)
Shinya Kitaoka 120a6e
                                             ? (float)PIXEL::maxChannelValue
Shinya Kitaoka 120a6e
                                             : val);
Shinya Kitaoka 120a6e
      val    = (*chan_p).z * (float)PIXEL::maxChannelValue + 0.5f;
Shinya Kitaoka 120a6e
      pix->b = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue)
Shinya Kitaoka 120a6e
                                             ? (float)PIXEL::maxChannelValue
Shinya Kitaoka 120a6e
                                             : val);
Shinya Kitaoka 120a6e
      val    = (*chan_p).w * (float)PIXEL::maxChannelValue + 0.5f;
Shinya Kitaoka 120a6e
      pix->m = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue)
Shinya Kitaoka 120a6e
                                             ? (float)PIXEL::maxChannelValue
Shinya Kitaoka 120a6e
                                             : val);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
shun-iwasawa 481b59
template <>
shun-iwasawa 481b59
void Iwa_DirectionalBlurFx::setOutputRaster<trasterfp, tpixelf="">(</trasterfp,>
shun-iwasawa 481b59
    float4 *srcMem, const TRasterFP dstRas, TDimensionI dim, int2 margin) {
shun-iwasawa 481b59
  int out_j = 0;
shun-iwasawa 481b59
  for (int j = margin.y; j < dstRas->getLy() + margin.y; j++, out_j++) {
shun-iwasawa 481b59
    TPixelF *pix   = dstRas->pixels(out_j);
shun-iwasawa 481b59
    float4 *chan_p = srcMem;
shun-iwasawa 481b59
    chan_p += j * dim.lx + margin.x;
shun-iwasawa 481b59
    for (int i = 0; i < dstRas->getLx(); i++, pix++, chan_p++) {
shun-iwasawa 481b59
      pix->r = (*chan_p).x;
shun-iwasawa 481b59
      pix->g = (*chan_p).y;
shun-iwasawa 481b59
      pix->b = (*chan_p).z;
shun-iwasawa 481b59
      pix->m = std::min((*chan_p).w, 1.f);
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
}
shun-iwasawa 481b59
Toshihiro Shimizu 890ddd
//------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Iwa_DirectionalBlurFx::Iwa_DirectionalBlurFx()
Shinya Kitaoka 120a6e
    : m_angle(0.0)
Shinya Kitaoka 120a6e
    , m_intensity(10.0)
Shinya Kitaoka 120a6e
    , m_bidirectional(false)
Shinya Kitaoka 120a6e
    , m_filterType(new TIntEnumParam(Linear, "Linear")) {
Shinya Kitaoka 120a6e
  m_intensity->setMeasureName("fxLength");
Shinya Kitaoka 120a6e
  m_angle->setMeasureName("angle");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bindParam(this, "angle", m_angle);
Shinya Kitaoka 120a6e
  bindParam(this, "intensity", m_intensity);
Shinya Kitaoka 120a6e
  bindParam(this, "bidirectional", m_bidirectional);
Shinya Kitaoka 120a6e
  bindParam(this, "filterType", m_filterType);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  addInputPort("Source", m_input);
Shinya Kitaoka 120a6e
  addInputPort("Reference", m_reference);
Shinya Kitaoka 120a6e
  m_intensity->setValueRange(0, (std::numeric_limits<double>::max)());</double>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_filterType->addItem(Gaussian, "Gaussian");
Shinya Kitaoka 120a6e
  m_filterType->addItem(Flat, "Flat");
shun-iwasawa 481b59
shun-iwasawa 481b59
  enableComputeInFloat(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void Iwa_DirectionalBlurFx::doCompute(TTile &tile, double frame,
Shinya Kitaoka 120a6e
                                      const TRenderSettings &settings) {
Shinya Kitaoka 120a6e
  /*- 接続していない場合は処理しない -*/
Shinya Kitaoka 120a6e
  if (!m_input.isConnected()) {
Shinya Kitaoka 120a6e
    tile.getRaster()->clear();
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPointD blurVector;
Shinya Kitaoka 120a6e
  double angle       = m_angle->getValue(frame) * M_PI_180;
Shinya Kitaoka 120a6e
  double intensity   = m_intensity->getValue(frame);
Shinya Kitaoka 120a6e
  bool bidirectional = m_bidirectional->getValue();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  blurVector.x = intensity * cos(angle);
Shinya Kitaoka 120a6e
  blurVector.y = intensity * sin(angle);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double shrink = (settings.m_shrinkX + settings.m_shrinkY) / 2.0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*- 平行移動成分を消したアフィン変換をかけ、ボケベクトルを変形 -*/
Shinya Kitaoka 120a6e
  TAffine aff = settings.m_affine;
Shinya Kitaoka 120a6e
  aff.a13 = aff.a23 = 0;
Shinya Kitaoka 120a6e
  TPointD blur      = (1.0 / shrink) * (aff * blurVector);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*- ボケの実際の長さを求める -*/
Shinya Kitaoka 120a6e
  double blurValue = norm(blur);
Shinya Kitaoka 120a6e
  /*- ボケの実際の長さがほぼ0なら入力画像をそのまま return -*/
Shinya Kitaoka 120a6e
  if (areAlmostEqual(blurValue, 0, 1e-3)) {
Shinya Kitaoka 120a6e
    m_input->compute(tile, frame, settings);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*-  表示の範囲を得る -*/
Shinya Kitaoka 120a6e
  TRectD bBox =
Shinya Kitaoka 120a6e
      TRectD(tile.m_pos /*- Render画像上(Pixel単位)の位置  -*/
Shinya Kitaoka 120a6e
             ,
Shinya Kitaoka 120a6e
             TDimensionD(/*- Render画像上(Pixel単位)のサイズ  -*/
Shinya Kitaoka 120a6e
                         tile.getRaster()->getLx(), tile.getRaster()->getLy()));
Shinya Kitaoka 120a6e
shun-iwasawa e69abe
  int marginH = (int)ceil(std::abs(blur.x));
shun-iwasawa e69abe
  int marginV = (int)ceil(std::abs(blur.y));
Shinya Kitaoka 120a6e
shun-iwasawa e69abe
  TRectD enlargedBBox(bBox.x0 - (double)marginH, bBox.y0 - (double)marginV,
shun-iwasawa e69abe
                      bBox.x1 + (double)marginH, bBox.y1 + (double)marginV);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TDimensionI enlargedDimIn(/*- Pixel単位に四捨五入 -*/
Shinya Kitaoka 120a6e
                            (int)(enlargedBBox.getLx() + 0.5),
Shinya Kitaoka 120a6e
                            (int)(enlargedBBox.getLy() + 0.5));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TTile enlarge_tile;
Shinya Kitaoka 120a6e
  m_input->allocateAndCompute(enlarge_tile, enlargedBBox.getP00(),
Shinya Kitaoka 120a6e
                              enlargedDimIn, tile.getRaster(), frame, settings);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*- 参照画像が有ったら、メモリに取り込む -*/
Shinya Kitaoka 120a6e
  float *reference_host = 0;
Shinya Kitaoka 120a6e
  TRasterGR8P reference_host_ras;
Shinya Kitaoka 120a6e
  if (m_reference.isConnected()) {
Shinya Kitaoka 120a6e
    TTile reference_tile;
Shinya Kitaoka 120a6e
    m_reference->allocateAndCompute(reference_tile, enlargedBBox.getP00(),
Shinya Kitaoka 120a6e
                                    enlargedDimIn, tile.getRaster(), frame,
Shinya Kitaoka 120a6e
                                    settings);
Shinya Kitaoka 120a6e
    /*- ホストのメモリ確保 -*/
Shinya Kitaoka 120a6e
    reference_host_ras =
Shinya Kitaoka 120a6e
        TRasterGR8P(sizeof(float) * enlargedDimIn.lx, enlargedDimIn.ly);
Shinya Kitaoka 120a6e
    reference_host_ras->lock();
Shinya Kitaoka 120a6e
    reference_host = (float *)reference_host_ras->getRawData();
Shinya Kitaoka 120a6e
    /*- 参照画像の輝度を0〜1に正規化してホストメモリに読み込む -*/
Shinya Kitaoka 120a6e
    TRaster32P ras32 = (TRaster32P)reference_tile.getRaster();
Shinya Kitaoka 120a6e
    TRaster64P ras64 = (TRaster64P)reference_tile.getRaster();
shun-iwasawa 481b59
    TRasterFP rasF   = (TRasterFP)reference_tile.getRaster();
Shinya Kitaoka 120a6e
    if (ras32)
Shinya Kitaoka 120a6e
      setReferenceRaster<traster32p, tpixel32="">(ras32, reference_host,</traster32p,>
Shinya Kitaoka 120a6e
                                               enlargedDimIn);
Shinya Kitaoka 120a6e
    else if (ras64)
Shinya Kitaoka 120a6e
      setReferenceRaster<traster64p, tpixel64="">(ras64, reference_host,</traster64p,>
Shinya Kitaoka 120a6e
                                               enlargedDimIn);
shun-iwasawa 481b59
    else if (rasF)
shun-iwasawa 481b59
      setReferenceRaster<trasterfp, tpixelf="">(rasF, reference_host,</trasterfp,>
shun-iwasawa 481b59
                                             enlargedDimIn);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //-------------------------------------------------------
Shinya Kitaoka 120a6e
  /*- 計算範囲 -*/
Shinya Kitaoka 120a6e
  TDimensionI dimOut(tile.getRaster()->getLx(), tile.getRaster()->getLy());
shun-iwasawa e69abe
  TDimensionI filterDim(2 * marginH + 1, 2 * marginV + 1);
Shinya Kitaoka 120a6e
shun-iwasawa e69abe
  doCompute_CPU(tile, frame, settings, blur, bidirectional, marginH, marginH,
shun-iwasawa e69abe
                marginV, marginV, enlargedDimIn, enlarge_tile, dimOut,
shun-iwasawa e69abe
                filterDim, reference_host);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*-  参照画像が刺さっている場合、メモリを解放する -*/
Shinya Kitaoka 120a6e
  if (reference_host) {
Shinya Kitaoka 120a6e
    reference_host_ras->unlock();
Shinya Kitaoka 120a6e
    reference_host = 0;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void Iwa_DirectionalBlurFx::doCompute_CPU(
Shinya Kitaoka 120a6e
    TTile &tile, double frame, const TRenderSettings &settings, TPointD &blur,
Shinya Kitaoka 120a6e
    bool bidirectional, int marginLeft, int marginRight, int marginTop,
Shinya Kitaoka 120a6e
    int marginBottom, TDimensionI &enlargedDimIn, TTile &enlarge_tile,
Shinya Kitaoka 120a6e
    TDimensionI &dimOut, TDimensionI &filterDim, float *reference_host) {
Shinya Kitaoka 120a6e
  /*- メモリ確保 -*/
Shinya Kitaoka 120a6e
  TRasterGR8P in_ras(sizeof(float4) * enlargedDimIn.lx, enlargedDimIn.ly);
Shinya Kitaoka 120a6e
  in_ras->lock();
Shinya Kitaoka 120a6e
  float4 *in = (float4 *)in_ras->getRawData();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRasterGR8P out_ras(sizeof(float4) * enlargedDimIn.lx, enlargedDimIn.ly);
Shinya Kitaoka 120a6e
  out_ras->lock();
Shinya Kitaoka 120a6e
  float4 *out = (float4 *)out_ras->getRawData();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRasterGR8P filter_ras(sizeof(float) * filterDim.lx, filterDim.ly);
Shinya Kitaoka 120a6e
  filter_ras->lock();
Shinya Kitaoka 120a6e
  float *filter = (float *)filter_ras->getRawData();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*- ソース画像を0〜1に正規化してホストメモリに読み込む -*/
Shinya Kitaoka 120a6e
  TRaster32P ras32 = (TRaster32P)enlarge_tile.getRaster();
Shinya Kitaoka 120a6e
  TRaster64P ras64 = (TRaster64P)enlarge_tile.getRaster();
shun-iwasawa 481b59
  TRasterFP rasF   = (TRasterFP)enlarge_tile.getRaster();
Shinya Kitaoka 120a6e
  if (ras32)
Shinya Kitaoka 120a6e
    setSourceRaster<traster32p, tpixel32="">(ras32, in, enlargedDimIn);</traster32p,>
Shinya Kitaoka 120a6e
  else if (ras64)
Shinya Kitaoka 120a6e
    setSourceRaster<traster64p, tpixel64="">(ras64, in, enlargedDimIn);</traster64p,>
shun-iwasawa 481b59
  else if (rasF)
shun-iwasawa 481b59
    setSourceRaster<trasterfp, tpixelf="">(rasF, in, enlargedDimIn);</trasterfp,>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*- フィルタ作る -*/
Shinya Kitaoka 120a6e
  makeDirectionalBlurFilter_CPU(filter, blur, bidirectional, marginLeft,
Shinya Kitaoka 120a6e
                                marginRight, marginTop, marginBottom,
Shinya Kitaoka 120a6e
                                filterDim);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (reference_host) /*- 参照画像がある場合 -*/
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    float4 *out_p = out + marginTop * enlargedDimIn.lx;
Shinya Kitaoka 120a6e
    float *ref_p  = reference_host + marginTop * enlargedDimIn.lx;
Shinya Kitaoka 120a6e
    /*- フィルタリング -*/
Shinya Kitaoka 120a6e
    for (int y = marginTop; y < dimOut.ly + marginTop; y++) {
Shinya Kitaoka 120a6e
      out_p += marginRight;
Shinya Kitaoka 120a6e
      ref_p += marginRight;
Shinya Kitaoka 120a6e
      for (int x = marginRight; x < dimOut.lx + marginRight;
Shinya Kitaoka 120a6e
           x++, out_p++, ref_p++) {
Shinya Kitaoka 120a6e
        /*- 参照画像が黒ならソースをそのまま返す -*/
Shinya Kitaoka 120a6e
        if ((*ref_p) == 0.0f) {
Shinya Kitaoka 120a6e
          (*out_p) = in[y * enlargedDimIn.lx + x];
Shinya Kitaoka 120a6e
          continue;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        /*- 値を積算する入れ物を用意 -*/
Shinya Kitaoka 120a6e
        float4 value = {0.0f, 0.0f, 0.0f, 0.0f};
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        float *filter_p = filter;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if ((*ref_p) == 1.0f) {
Shinya Kitaoka 120a6e
          /*- フィルタのサイズでループ
Shinya Kitaoka 120a6e
             ただし、フィルタはサンプル点の画像を収集するように
Shinya Kitaoka 120a6e
                  用いるため、上下左右反転してサンプルする -*/
Shinya Kitaoka 120a6e
          for (int fily = -marginBottom; fily < filterDim.ly - marginBottom;
Shinya Kitaoka 120a6e
               fily++) {
Shinya Kitaoka 120a6e
            /*- サンプル座標 と インデックス の このスキャンラインのうしろ -*/
Shinya Kitaoka 120a6e
            int2 samplePos  = {x + marginLeft, y - fily};
Shinya Kitaoka 120a6e
            int sampleIndex = samplePos.y * enlargedDimIn.lx + samplePos.x;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
            for (int filx = -marginLeft; filx < filterDim.lx - marginLeft;
Shinya Kitaoka 120a6e
                 filx++, filter_p++, sampleIndex--) {
Shinya Kitaoka 120a6e
              /*- フィルター値が0またはサンプルピクセルが透明ならcontinue -*/
Shinya Kitaoka 120a6e
              if ((*filter_p) == 0.0f || in[sampleIndex].w == 0.0f) continue;
Shinya Kitaoka 120a6e
              /*- サンプル点の値にフィルタ値を掛けて積算する -*/
Shinya Kitaoka 120a6e
              value.x += in[sampleIndex].x * (*filter_p);
Shinya Kitaoka 120a6e
              value.y += in[sampleIndex].y * (*filter_p);
Shinya Kitaoka 120a6e
              value.z += in[sampleIndex].z * (*filter_p);
Shinya Kitaoka 120a6e
              value.w += in[sampleIndex].w * (*filter_p);
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        } else {
Shinya Kitaoka 120a6e
          for (int fily = -marginBottom; fily < filterDim.ly - marginBottom;
Shinya Kitaoka 120a6e
               fily++) {
Shinya Kitaoka 120a6e
            for (int filx = -marginLeft; filx < filterDim.lx - marginLeft;
Shinya Kitaoka 120a6e
                 filx++, filter_p++) {
Shinya Kitaoka 120a6e
              /*- フィルター値が0ならcontinue -*/
Shinya Kitaoka 120a6e
              if ((*filter_p) == 0.0f) continue;
Shinya Kitaoka 120a6e
              /*- サンプル座標 -*/
shun-iwasawa e69abe
              int2 samplePos  = {tround((float)x - (float)filx * (*ref_p)),
shun-iwasawa 481b59
                                 tround((float)y - (float)fily * (*ref_p))};
Shinya Kitaoka 120a6e
              int sampleIndex = samplePos.y * enlargedDimIn.lx + samplePos.x;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
              /*- サンプルピクセルが透明ならcontinue -*/
Shinya Kitaoka 120a6e
              if (in[sampleIndex].w == 0.0f) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
              /*- サンプル点の値にフィルタ値を掛けて積算する -*/
Shinya Kitaoka 120a6e
              value.x += in[sampleIndex].x * (*filter_p);
Shinya Kitaoka 120a6e
              value.y += in[sampleIndex].y * (*filter_p);
Shinya Kitaoka 120a6e
              value.z += in[sampleIndex].z * (*filter_p);
Shinya Kitaoka 120a6e
              value.w += in[sampleIndex].w * (*filter_p);
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        /*- 値を格納 -*/
Shinya Kitaoka 120a6e
        (*out_p) = value;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      out_p += marginLeft;
Shinya Kitaoka 120a6e
      ref_p += marginLeft;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  } else /*- 参照画像が無い場合 -*/
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    float4 *out_p = out + marginTop * enlargedDimIn.lx;
Shinya Kitaoka 120a6e
    /*- フィルタリング -*/
Shinya Kitaoka 120a6e
    for (int y = marginTop; y < dimOut.ly + marginTop; y++) {
Shinya Kitaoka 120a6e
      out_p += marginRight;
Shinya Kitaoka 120a6e
      for (int x = marginRight; x < dimOut.lx + marginRight; x++, out_p++) {
Shinya Kitaoka 120a6e
        /*- 値を積算する入れ物を用意 -*/
Shinya Kitaoka 120a6e
        float4 value = {0.0f, 0.0f, 0.0f, 0.0f};
Shinya Kitaoka 120a6e
        /*- フィルタのサイズでループ
Shinya Kitaoka 120a6e
           ただし、フィルタはサンプル点の画像を収集するように
Shinya Kitaoka 120a6e
                用いるため、上下左右反転してサンプルする -*/
Shinya Kitaoka 120a6e
        int filterIndex = 0;
Shinya Kitaoka 120a6e
        for (int fily = -marginBottom; fily < filterDim.ly - marginBottom;
Shinya Kitaoka 120a6e
             fily++) {
Shinya Kitaoka 120a6e
          /*- サンプル座標 と インデックス の このスキャンラインのうしろ -*/
Shinya Kitaoka 120a6e
          int2 samplePos  = {x + marginLeft, y - fily};
Shinya Kitaoka 120a6e
          int sampleIndex = samplePos.y * enlargedDimIn.lx + samplePos.x;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          for (int filx = -marginLeft; filx < filterDim.lx - marginLeft;
Shinya Kitaoka 120a6e
               filx++, filterIndex++, sampleIndex--) {
Shinya Kitaoka 120a6e
            /*- フィルター値が0またはサンプルピクセルが透明ならcontinue -*/
Shinya Kitaoka 120a6e
            if (filter[filterIndex] == 0.0f || in[sampleIndex].w == 0.0f)
Shinya Kitaoka 120a6e
              continue;
Shinya Kitaoka 120a6e
            /*- サンプル点の値にフィルタ値を掛けて積算する -*/
Shinya Kitaoka 120a6e
            value.x += in[sampleIndex].x * filter[filterIndex];
Shinya Kitaoka 120a6e
            value.y += in[sampleIndex].y * filter[filterIndex];
Shinya Kitaoka 120a6e
            value.z += in[sampleIndex].z * filter[filterIndex];
Shinya Kitaoka 120a6e
            value.w += in[sampleIndex].w * filter[filterIndex];
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        /*- 値を格納 -*/
Shinya Kitaoka 120a6e
        (*out_p) = value;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      out_p += marginLeft;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  in_ras->unlock();
Shinya Kitaoka 120a6e
  filter_ras->unlock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*- ラスタのクリア -*/
Shinya Kitaoka 120a6e
  tile.getRaster()->clear();
Shinya Kitaoka 120a6e
  TRaster32P outRas32 = (TRaster32P)tile.getRaster();
Shinya Kitaoka 120a6e
  TRaster64P outRas64 = (TRaster64P)tile.getRaster();
shun-iwasawa 481b59
  TRasterFP outRasF   = (TRasterFP)tile.getRaster();
Shinya Kitaoka 120a6e
  int2 margin         = {marginRight, marginTop};
Shinya Kitaoka 120a6e
  if (outRas32)
Shinya Kitaoka 120a6e
    setOutputRaster<traster32p, tpixel32="">(out, outRas32, enlargedDimIn, margin);</traster32p,>
Shinya Kitaoka 120a6e
  else if (outRas64)
Shinya Kitaoka 120a6e
    setOutputRaster<traster64p, tpixel64="">(out, outRas64, enlargedDimIn, margin);</traster64p,>
shun-iwasawa 481b59
  else if (outRasF)
shun-iwasawa 481b59
    setOutputRaster<trasterfp, tpixelf="">(out, outRasF, enlargedDimIn, margin);</trasterfp,>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  out_ras->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void Iwa_DirectionalBlurFx::makeDirectionalBlurFilter_CPU(
Shinya Kitaoka 120a6e
    float *filter, TPointD &blur, bool bidirectional, int marginLeft,
Shinya Kitaoka 120a6e
    int marginRight, int marginTop, int marginBottom, TDimensionI &filterDim) {
Shinya Kitaoka 120a6e
  /*- 必要なら、ガウスフィルタを前計算 -*/
Shinya Kitaoka 120a6e
  FILTER_TYPE filterType = (FILTER_TYPE)m_filterType->getValue();
Shinya Kitaoka 120a6e
  std::vector<float> gaussian;</float>
Shinya Kitaoka 120a6e
  if (filterType == Gaussian) {
Shinya Kitaoka 120a6e
    gaussian.reserve(101);
Shinya Kitaoka 120a6e
    for (int g = 0; g < 101; g++) {
Shinya Kitaoka 120a6e
      float x = (float)g / 100.0f;
Shinya Kitaoka 120a6e
      // sigma == 0.25
Shinya Kitaoka 120a6e
      gaussian.push_back(exp(-x * x / 0.125f));
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*- フィルタを作る -*/
Shinya Kitaoka 120a6e
  TPointD p0 =
Shinya Kitaoka 120a6e
      (bidirectional) ? TPointD(-blur.x, -blur.y) : TPointD(0.0f, 0.0f);
Shinya Kitaoka 120a6e
  TPointD p1       = blur;
Shinya Kitaoka 120a6e
  float2 vec_p0_p1 = {static_cast<float>(p1.x - p0.x),</float>
Shinya Kitaoka 120a6e
                      static_cast<float>(p1.y - p0.y)};</float>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  float *fil_p        = filter;
Shinya Kitaoka 120a6e
  float intensity_sum = 0.0f;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (int fy = -marginBottom; fy <= marginTop; fy++) {
Shinya Kitaoka 120a6e
    for (int fx = -marginLeft; fx <= marginRight; fx++, fil_p++) {
Shinya Kitaoka 120a6e
      /*- 現在の座標とブラー直線の距離を求める -*/
Shinya Kitaoka 120a6e
      /*- P0->サンプル点とP0->P1の内積を求める -*/
Shinya Kitaoka 120a6e
      float2 vec_p0_sample = {static_cast<float>(fx - p0.x),</float>
Shinya Kitaoka 120a6e
                              static_cast<float>(fy - p0.y)};</float>
Shinya Kitaoka 120a6e
      float dot = vec_p0_sample.x * vec_p0_p1.x + vec_p0_sample.y * vec_p0_p1.y;
Shinya Kitaoka 120a6e
      /*- 軌跡ベクトルの長さの2乗を計算する -*/
Shinya Kitaoka 120a6e
      float length2 = vec_p0_p1.x * vec_p0_p1.x + vec_p0_p1.y * vec_p0_p1.y;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /*- 距離の2乗を求める -*/
Shinya Kitaoka 120a6e
      float dist2;
Shinya Kitaoka 120a6e
      float framePosRatio;
Shinya Kitaoka 120a6e
      /*- P0より手前にある場合 -*/
Shinya Kitaoka 120a6e
      if (dot <= 0.0f) {
Shinya Kitaoka 120a6e
        dist2 = vec_p0_sample.x * vec_p0_sample.x +
Shinya Kitaoka 120a6e
                vec_p0_sample.y * vec_p0_sample.y;
Shinya Kitaoka 120a6e
        framePosRatio = 0.0f;
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        /*- P0〜P1間にある場合 -*/
Shinya Kitaoka 120a6e
        if (dot < length2) {
Shinya Kitaoka 120a6e
          float p0_sample_dist2 = vec_p0_sample.x * vec_p0_sample.x +
Shinya Kitaoka 120a6e
                                  vec_p0_sample.y * vec_p0_sample.y;
Shinya Kitaoka 120a6e
          dist2         = p0_sample_dist2 - dot * dot / length2;
Shinya Kitaoka 120a6e
          framePosRatio = dot / length2;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        /*- P1より先にある場合 -*/
Shinya Kitaoka 120a6e
        else {
Shinya Kitaoka 120a6e
          float2 vec_p1_sample = {static_cast<float>(fx - p1.x),</float>
Shinya Kitaoka 120a6e
                                  static_cast<float>(fy - p1.y)};</float>
shun-iwasawa e69abe
          dist2                = vec_p1_sample.x * vec_p1_sample.x +
Shinya Kitaoka 120a6e
                  vec_p1_sample.y * vec_p1_sample.y;
Shinya Kitaoka 120a6e
          framePosRatio = 1.0f;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      /*- 距離が(√2 + 1)/2より遠かったらreturn dist2との比較だから2乗している
Shinya Kitaoka 120a6e
       * -*/
Shinya Kitaoka 120a6e
      if (dist2 > 1.4571f) {
Shinya Kitaoka 120a6e
        (*fil_p) = 0.0f;
Shinya Kitaoka 120a6e
        continue;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /*-
Shinya Kitaoka 120a6e
         現在のピクセルのサブピクセル(16*16)が、近傍ベクトルからの距離0.5の範囲にどれだけ
Shinya Kitaoka 120a6e
               含まれているかをカウントする -*/
Shinya Kitaoka 120a6e
      int count = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      for (int yy = 0; yy < 16; yy++) {
Shinya Kitaoka 120a6e
        /*- サブピクセルのY座標 -*/
Shinya Kitaoka 120a6e
        float subPosY = (float)fy + ((float)yy - 7.5f) / 16.0f;
Shinya Kitaoka 120a6e
        for (int xx = 0; xx < 16; xx++) {
Shinya Kitaoka 120a6e
          /*- サブピクセルのX座標 -*/
Shinya Kitaoka 120a6e
          float subPosX = (float)fx + ((float)xx - 7.5f) / 16.0f;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          float2 vec_p0_sub = {static_cast<float>(subPosX - p0.x),</float>
Shinya Kitaoka 120a6e
                               static_cast<float>(subPosY - p0.y)};</float>
Shinya Kitaoka 120a6e
          float sub_dot =
Shinya Kitaoka 120a6e
              vec_p0_sub.x * vec_p0_p1.x + vec_p0_sub.y * vec_p0_p1.y;
Shinya Kitaoka 120a6e
          /*- 距離の2乗を求める -*/
Shinya Kitaoka 120a6e
          float dist2;
Shinya Kitaoka 120a6e
          /*- P0より手前にある場合 -*/
Shinya Kitaoka 120a6e
          if (sub_dot <= 0.0f)
Shinya Kitaoka 120a6e
            dist2 = vec_p0_sub.x * vec_p0_sub.x + vec_p0_sub.y * vec_p0_sub.y;
Shinya Kitaoka 120a6e
          else {
Shinya Kitaoka 120a6e
            /*- P0〜P1間にある場合 -*/
Shinya Kitaoka 120a6e
            if (sub_dot < length2) {
Shinya Kitaoka 120a6e
              float p0_sub_dist2 =
Shinya Kitaoka 120a6e
                  vec_p0_sub.x * vec_p0_sub.x + vec_p0_sub.y * vec_p0_sub.y;
Shinya Kitaoka 120a6e
              dist2 = p0_sub_dist2 - sub_dot * sub_dot / length2;
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
            /*-  P1より先にある場合 -*/
Shinya Kitaoka 120a6e
            else {
Shinya Kitaoka 120a6e
              float2 vec_p1_sub = {static_cast<float>(subPosX - p1.x),</float>
Shinya Kitaoka 120a6e
                                   static_cast<float>(subPosY - p1.y)};</float>
Shinya Kitaoka 120a6e
              dist2 = vec_p1_sub.x * vec_p1_sub.x + vec_p1_sub.y * vec_p1_sub.y;
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
          /*- 距離の2乗が0.25より近ければカウントをインクリメント -*/
Shinya Kitaoka 120a6e
          if (dist2 <= 0.25f) count++;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      /*- 保険 カウントが0の場合はフィールド値0でreturn -*/
Shinya Kitaoka 120a6e
      if (count == 0) {
Shinya Kitaoka 120a6e
        (*fil_p) = 0.0f;
Shinya Kitaoka 120a6e
        continue;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      /*- countは Max256 -*/
Shinya Kitaoka 120a6e
      float countRatio = (float)count / 256.0f;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /*- オフセット値を求める -*/
Shinya Kitaoka 120a6e
      float offset =
Rozhuk Ivan 823a31
          (bidirectional) ? std::abs(framePosRatio * 2.0 - 1.0) : framePosRatio;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /*- フィルタごとに分ける -*/
Shinya Kitaoka 120a6e
      float bokeAsiVal;
Shinya Kitaoka 120a6e
      switch (filterType) {
Shinya Kitaoka 120a6e
      case Linear:
Shinya Kitaoka 120a6e
        bokeAsiVal = 1.0f - offset;
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      case Gaussian: {
Shinya Kitaoka 120a6e
        int index   = (int)floor(offset * 100.0f);
Shinya Kitaoka 120a6e
        float ratio = offset * 100.0f - (float)index;
shun-iwasawa 481b59
        bokeAsiVal  = (ratio == 0.f) ? gaussian[index]
shun-iwasawa 481b59
                                     : gaussian[index] * (1.0f - ratio) +
shun-iwasawa 481b59
                                          gaussian[index + 1] * ratio;
Shinya Kitaoka 120a6e
      } break;
Shinya Kitaoka 120a6e
      case Flat:
Shinya Kitaoka 120a6e
        bokeAsiVal = 1.0f;
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      default:
Shinya Kitaoka 120a6e
        bokeAsiVal = 1.0f - offset;
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /*- フィールド値の格納 -*/
Shinya Kitaoka 120a6e
      (*fil_p) = bokeAsiVal * countRatio;
Shinya Kitaoka 120a6e
      intensity_sum += (*fil_p);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*- 正規化 -*/
Shinya Kitaoka 120a6e
  fil_p = filter;
Shinya Kitaoka 120a6e
  for (int f = 0; f < filterDim.lx * filterDim.ly; f++, fil_p++) {
Shinya Kitaoka 120a6e
    if ((*fil_p) == 0.0f) continue;
Shinya Kitaoka 120a6e
    (*fil_p) /= intensity_sum;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool Iwa_DirectionalBlurFx::doGetBBox(double frame, TRectD &bBox,
Shinya Kitaoka 120a6e
                                      const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  if (false == this->m_input.isConnected()) {
Shinya Kitaoka 120a6e
    bBox = TRectD();
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool ret = m_input->doGetBBox(frame, bBox, info);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (bBox == TConsts::infiniteRectD) return ret;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPointD blur;
Shinya Kitaoka 120a6e
  double angle       = m_angle->getValue(frame) * M_PI_180;
Shinya Kitaoka 120a6e
  double intensity   = m_intensity->getValue(frame);
Shinya Kitaoka 120a6e
  bool bidirectional = m_bidirectional->getValue();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  blur.x = intensity * cos(angle);
Shinya Kitaoka 120a6e
  blur.y = intensity * sin(angle);
Shinya Kitaoka 120a6e
shun-iwasawa e69abe
  int marginH = (int)ceil(std::abs(blur.x));
shun-iwasawa e69abe
  int marginV = (int)ceil(std::abs(blur.y));
shun-iwasawa e69abe
shun-iwasawa e69abe
  TRectD enlargedBBox(bBox.x0 - (double)marginH, bBox.y0 - (double)marginV,
shun-iwasawa e69abe
                      bBox.x1 + (double)marginH, bBox.y1 + (double)marginV);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bBox = enlargedBBox;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return ret;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool Iwa_DirectionalBlurFx::canHandle(const TRenderSettings &info,
Shinya Kitaoka 120a6e
                                      double frame) {
Shinya Kitaoka 120a6e
  return isAlmostIsotropic(info.m_affine) || m_intensity->getValue(frame) == 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void Iwa_DirectionalBlurFx::getParamUIs(TParamUIConcept *&concepts,
Shinya Kitaoka 120a6e
                                        int &length) {
Shinya Kitaoka 120a6e
  concepts = new TParamUIConcept[length = 1];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  concepts[0].m_type  = TParamUIConcept::POLAR;
Shinya Kitaoka 120a6e
  concepts[0].m_label = "Angle and Intensity";
Shinya Kitaoka 120a6e
  concepts[0].m_params.push_back(m_angle);
Shinya Kitaoka 120a6e
  concepts[0].m_params.push_back(m_intensity);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
FX_PLUGIN_IDENTIFIER(Iwa_DirectionalBlurFx, "iwa_DirectionalBlurFx")