Shinya Kitaoka 120a6e
#include <vector>     // std::vector</vector>
Shinya Kitaoka 120a6e
#include <cmath>      // cos(),sin(),sqrt()</cmath>
Shinya Kitaoka 120a6e
#include <limits>     // std::numeric_limits<t></t></limits>
Shinya Kitaoka 120a6e
#include <stdexcept>  // std::domain_error()</stdexcept>
Toshihiro Shimizu 890ddd
#include "igs_ifx_common.h"
Toshihiro Shimizu 890ddd
#include "igs_radial_blur.h"
shun-iwasawa a6544b
shun-iwasawa a6544b
#include <qvector2d></qvector2d>
shun-iwasawa a6544b
#include <qtransform></qtransform>
shun-iwasawa a6544b
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
shun-iwasawa a6544b
enum Type { Accelerator = 0, Uniform_Length };
shun-iwasawa a6544b
Shinya Kitaoka 120a6e
class radial_ {
shun-iwasawa a6544b
  const float* in_top_;
shun-iwasawa a6544b
  const int hh_;
shun-iwasawa a6544b
  const int ww_;
shun-iwasawa a6544b
  const int cc_;
shun-iwasawa a6544b
  const TPointD center_;
shun-iwasawa a6544b
  const bool antialias_sw_;
shun-iwasawa a6544b
  const bool alpha_rendering_sw_;
shun-iwasawa a6544b
  const double intensity_;
shun-iwasawa a6544b
  const double blur_radius_;
shun-iwasawa a6544b
  const double twist_radian_;
shun-iwasawa a6544b
  const double pivot_radius_;
shun-iwasawa a6544b
  const int type_;
shun-iwasawa a6544b
  const double ellipse_aspect_ratio_;
shun-iwasawa a6544b
  const double ellipse_angle_;
shun-iwasawa a6544b
  const double intensity_correlation_with_ellipse_;
shun-iwasawa a6544b
  QTransform tr_, tr_inv_;
shun-iwasawa a6544b
Toshihiro Shimizu 890ddd
public:
shun-iwasawa a6544b
  radial_(const float* in_top, const int height, const int width,
shun-iwasawa a6544b
          const int channels, const TPointD center, const bool antialias_sw,
shun-iwasawa a6544b
          const bool alpha_rendering_sw,
shun-iwasawa a6544b
          const double intensity,   /* 平均値ぼかし強度 */
shun-iwasawa a6544b
          const double blur_radius, /* 平均値ぼかしの始まる半径 */
shun-iwasawa a6544b
          const double twist_radian, const double pivot_radius, const int type,
shun-iwasawa a6544b
          const double ellipse_aspect_ratio, const double ellipse_angle,
shun-iwasawa a6544b
          const double intensity_correlation_with_ellipse)
Shinya Kitaoka 120a6e
      : in_top_(in_top)
Shinya Kitaoka 120a6e
      , hh_(height)
Shinya Kitaoka 120a6e
      , ww_(width)
Shinya Kitaoka 120a6e
      , cc_(channels)
shun-iwasawa a6544b
      , center_(center)
shun-iwasawa a6544b
      , antialias_sw_(antialias_sw)
shun-iwasawa a6544b
      , alpha_rendering_sw_(alpha_rendering_sw)
Shinya Kitaoka 120a6e
      , intensity_(intensity)
shun-iwasawa a6544b
      , blur_radius_(blur_radius)
shun-iwasawa a6544b
      , twist_radian_(twist_radian)
shun-iwasawa a6544b
      , pivot_radius_(pivot_radius)
shun-iwasawa a6544b
      , type_(type)
shun-iwasawa a6544b
      , ellipse_aspect_ratio_(ellipse_aspect_ratio)
shun-iwasawa a6544b
      , ellipse_angle_(ellipse_angle)
shun-iwasawa a6544b
      , intensity_correlation_with_ellipse_(
shun-iwasawa a6544b
            intensity_correlation_with_ellipse) {
shun-iwasawa a6544b
    if (ellipse_aspect_ratio_ != 1.0) {
shun-iwasawa a6544b
      double axis_x =
shun-iwasawa a6544b
          2.0 * ellipse_aspect_ratio_ / (ellipse_aspect_ratio_ + 1.0);
shun-iwasawa a6544b
      double axis_y = axis_x / ellipse_aspect_ratio_;
shun-iwasawa a6544b
      tr_           = QTransform()
shun-iwasawa a6544b
                .rotateRadians(this->ellipse_angle_)
shun-iwasawa a6544b
                .scale(axis_x, axis_y);
shun-iwasawa a6544b
      tr_inv_ = QTransform(tr_).inverted();
Shinya Kitaoka 120a6e
    }
shun-iwasawa a6544b
  }
shun-iwasawa a6544b
  void pixel_value(const float* in_current_pixel, const int xx, const int yy,
shun-iwasawa a6544b
                   const bool isRGB, const double refVal, float* result_pixel) {
shun-iwasawa a6544b
    auto in_pixel = [&](int x, int y) {
shun-iwasawa a6544b
      /* clamp */
shun-iwasawa a6544b
      x = (x < 0) ? 0 : ((this->ww_ <= x) ? this->ww_ - 1 : x);
shun-iwasawa a6544b
      y = (y < 0) ? 0 : ((this->hh_ <= y) ? this->hh_ - 1 : y);
shun-iwasawa a6544b
      return this->in_top_ + this->cc_ * y * this->ww_ + this->cc_ * x;
shun-iwasawa a6544b
    };
shun-iwasawa a6544b
    auto interp = [&](float v1, float v2, float r) {
shun-iwasawa a6544b
      return v1 * (1.f - r) + v2 * r;
shun-iwasawa a6544b
    };
shun-iwasawa a6544b
    auto accum_interp_in_values = [&](QPointF pos, std::vector<float>& accumP,</float>
shun-iwasawa a6544b
                                      int z1, int z2, float weight) {
shun-iwasawa a6544b
      int xId          = (int)std::floor(pos.x());
shun-iwasawa a6544b
      float rx         = pos.x() - (float)xId;
shun-iwasawa a6544b
      int yId          = (int)std::floor(pos.y());
shun-iwasawa a6544b
      float ry         = pos.y() - (float)yId;
shun-iwasawa a6544b
      const float* p00 = in_pixel(xId, yId);
shun-iwasawa a6544b
      const float* p01 = in_pixel(xId + 1, yId);
shun-iwasawa a6544b
      const float* p10 = in_pixel(xId, yId + 1);
shun-iwasawa a6544b
      const float* p11 = in_pixel(xId + 1, yId + 1);
shun-iwasawa a6544b
      for (int zz = z1; zz <= z2; zz++) {
shun-iwasawa a6544b
        accumP[zz] += weight * interp(interp(p00[zz], p01[zz], rx),
shun-iwasawa a6544b
                                      interp(p10[zz], p11[zz], rx), ry);
Shinya Kitaoka 120a6e
      }
shun-iwasawa a6544b
    };
shun-iwasawa a6544b
    auto accum_in_values = [&](QPointF pos, std::vector<float>& accumP, int z1,</float>
shun-iwasawa a6544b
                               int z2, float weight) {
shun-iwasawa a6544b
      int xId        = (int)std::round(pos.x());
shun-iwasawa a6544b
      int yId        = (int)std::round(pos.y());
shun-iwasawa a6544b
      const float* p = in_pixel(xId, yId);
shun-iwasawa a6544b
      for (int zz = z1; zz <= z2; zz++) {
shun-iwasawa a6544b
        accumP[zz] += weight * p[zz];
Shinya Kitaoka 120a6e
      }
shun-iwasawa a6544b
    };
Toshihiro Shimizu 890ddd
shun-iwasawa a6544b
    int c1, c2;
shun-iwasawa a6544b
    if (isRGB) {
Toshihiro Shimizu 890ddd
#if defined RGBA_ORDER_OF_TOONZ6
shun-iwasawa a6544b
      c1 = igs::image::rgba::blu;
shun-iwasawa a6544b
      c2 = igs::image::rgba::red;
Toshihiro Shimizu 890ddd
#elif defined RGBA_ORDER_OF_OPENGL
shun-iwasawa a6544b
      c1 = igs::image::rgba::red;
shun-iwasawa a6544b
      c2 = igs::image::rgba::blu;
Toshihiro Shimizu 890ddd
#else
shun-iwasawa a6544b
      Must be define / DRGBA_ORDER_OF_TOONZ6 or / DRGBA_ORDER_OF_OPENGL
Toshihiro Shimizu 890ddd
#endif
shun-iwasawa a6544b
    } else {
shun-iwasawa a6544b
      c1 = igs::image::rgba::alp;
shun-iwasawa a6544b
      c2 = igs::image::rgba::alp;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
shun-iwasawa a6544b
    const QPointF center(this->center_.x, this->center_.y);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* Pixel位置(0.5 1.5 2.5 ...) */
shun-iwasawa a6544b
    const QPointF p(static_cast<float>(xx) + 0.5f,</float>
shun-iwasawa a6544b
                    static_cast<float>(yy) + 0.5f);</float>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* 中心からPixel位置へのベクトルと長さ */
shun-iwasawa a6544b
    const QVector2D v(p - center);
shun-iwasawa a6544b
    const float dist = v.length();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* 指定半径の範囲内なら何もしない */
shun-iwasawa a6544b
    bool is_in_blur_radius = false;
shun-iwasawa a6544b
    if (this->ellipse_aspect_ratio_ == 1.f) {
shun-iwasawa a6544b
      is_in_blur_radius = (dist <= this->blur_radius_);
shun-iwasawa a6544b
    } else {
shun-iwasawa a6544b
      is_in_blur_radius =
shun-iwasawa a6544b
          QVector2D(this->tr_inv_.map(v.toPointF())).lengthSquared() <=
shun-iwasawa a6544b
          (this->blur_radius_ * this->blur_radius_);
shun-iwasawa a6544b
    }
shun-iwasawa a6544b
    if (is_in_blur_radius) {
shun-iwasawa a6544b
      for (int c = c1; c <= c2; ++c) {
shun-iwasawa a6544b
        result_pixel[c] = in_current_pixel[c];
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
shun-iwasawa a6544b
    /* 積算値と積算回数 */
shun-iwasawa a6544b
    std::vector<float> accum_val(this->cc_);</float>
shun-iwasawa a6544b
    float accum_counter = 0.f;
shun-iwasawa a6544b
Shinya Kitaoka 120a6e
    /* Radial方向のSamplingの開始位置と終了位置 */
shun-iwasawa a6544b
    float scale = this->intensity_ * refVal;
shun-iwasawa a6544b
shun-iwasawa a6544b
    float distanceRatio = 1.f;
shun-iwasawa a6544b
    float length;
shun-iwasawa a6544b
    if (this->ellipse_aspect_ratio_ == 1.) {
shun-iwasawa a6544b
      if (this->type_ == Accelerator)
shun-iwasawa a6544b
        length = (dist - this->blur_radius_) * scale;
shun-iwasawa a6544b
      else  // Uniform_Length
shun-iwasawa a6544b
        length = (this->pivot_radius_ - this->blur_radius_) * scale;
shun-iwasawa a6544b
    } else {
shun-iwasawa a6544b
      float dist_mod = QVector2D(this->tr_inv_.map(v.toPointF())).length();
shun-iwasawa a6544b
      distanceRatio  = dist / dist_mod;
shun-iwasawa a6544b
      if (this->type_ == Accelerator)
shun-iwasawa a6544b
        length = (dist - this->blur_radius_ * distanceRatio) * scale *
shun-iwasawa a6544b
                 std::pow(distanceRatio, intensity_correlation_with_ellipse_);
shun-iwasawa a6544b
      else  // Uniform_Length
shun-iwasawa a6544b
        length = (this->pivot_radius_ - this->blur_radius_) * scale *
shun-iwasawa a6544b
                 std::pow(distanceRatio, intensity_correlation_with_ellipse_);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
shun-iwasawa a6544b
    float blur_length_half = length * 0.5f;
shun-iwasawa a6544b
shun-iwasawa a6544b
    // sampling in both directions
shun-iwasawa a6544b
    float sample_length = 0.f;
shun-iwasawa a6544b
    while (sample_length < blur_length_half) {
shun-iwasawa a6544b
      // compute weight
shun-iwasawa a6544b
      float weight = 1.f;
shun-iwasawa a6544b
      if (sample_length > blur_length_half - 1.f) {
shun-iwasawa a6544b
        if (antialias_sw_)
shun-iwasawa a6544b
          weight = blur_length_half - sample_length;
shun-iwasawa a6544b
        else
shun-iwasawa a6544b
          break;
shun-iwasawa a6544b
      }
shun-iwasawa a6544b
      // advance to the next sample
shun-iwasawa a6544b
      sample_length += weight;
shun-iwasawa a6544b
shun-iwasawa a6544b
      float sample_dists[2] = {dist + sample_length, dist - sample_length};
shun-iwasawa a6544b
      for (int i = 0; i < 2; i++) {
shun-iwasawa a6544b
        if (sample_dists[i] < 0.f) continue;  // 中心を突き抜けた場合は無視する
shun-iwasawa a6544b
        QPointF v_smpl;
shun-iwasawa a6544b
        float scaleVal = sample_dists[i] / dist;
shun-iwasawa a6544b
        if (this->twist_radian_ == 0.0) {
shun-iwasawa a6544b
          if (this->ellipse_aspect_ratio_ == 1.f)
shun-iwasawa a6544b
            v_smpl = v.toPointF() * scaleVal;
shun-iwasawa a6544b
          else
shun-iwasawa a6544b
            v_smpl = (this->tr_inv_ *
shun-iwasawa a6544b
                      QTransform(this->tr_).scale(scaleVal, scaleVal))
shun-iwasawa a6544b
                         .map(v.toPointF());
shun-iwasawa a6544b
        } else {  // twisted case
shun-iwasawa a6544b
          if (this->ellipse_aspect_ratio_ == 1.f) {
shun-iwasawa a6544b
            double tmp_twist_angle =
shun-iwasawa a6544b
                twist_radian_ * (sample_dists[i] - dist) / pivot_radius_;
shun-iwasawa a6544b
shun-iwasawa a6544b
            float cos = std::cos(tmp_twist_angle);
shun-iwasawa a6544b
            float sin = std::sin(tmp_twist_angle);
shun-iwasawa a6544b
shun-iwasawa a6544b
            v_smpl =
shun-iwasawa a6544b
                QPointF(cos * v.x() - sin * v.y(), sin * v.x() + cos * v.y()) *
shun-iwasawa a6544b
                scaleVal;
shun-iwasawa a6544b
          } else {
shun-iwasawa a6544b
            double tmp_twist_angle = twist_radian_ * (sample_dists[i] - dist) *
shun-iwasawa a6544b
                                     distanceRatio / pivot_radius_;
shun-iwasawa a6544b
            v_smpl = (this->tr_inv_ * QTransform(this->tr_)
shun-iwasawa a6544b
                                          .rotateRadians(tmp_twist_angle)
shun-iwasawa a6544b
                                          .scale(scaleVal, scaleVal))
shun-iwasawa a6544b
                         .map(v.toPointF());
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
shun-iwasawa a6544b
shun-iwasawa a6544b
        if (antialias_sw_)
shun-iwasawa a6544b
          accum_interp_in_values(v_smpl + center, accum_val, c1, c2, weight);
shun-iwasawa a6544b
        else
shun-iwasawa a6544b
          accum_in_values(v_smpl + center, accum_val, c1, c2, weight);
shun-iwasawa a6544b
        accum_counter += weight;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
shun-iwasawa a6544b
    // sample the original pos
shun-iwasawa a6544b
    if (antialias_sw_)
shun-iwasawa a6544b
      accum_interp_in_values(p, accum_val, c1, c2, 1.f);
shun-iwasawa a6544b
    else
shun-iwasawa a6544b
      accum_in_values(p, accum_val, c1, c2, 1.f);
shun-iwasawa a6544b
    accum_counter += 1.f;
shun-iwasawa a6544b
Shinya Kitaoka 120a6e
    /* 積算しなかったとき(念のためのCheck) */
shun-iwasawa a6544b
    if (accum_counter <= 0.f) {
shun-iwasawa a6544b
      for (int c = c1; c <= c2; ++c) {
shun-iwasawa a6544b
        result_pixel[c] = in_current_pixel[c];
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    /* ここで画像Pixelに保存 */
shun-iwasawa a6544b
    for (int c = c1; c <= c2; ++c) {
shun-iwasawa a6544b
      accum_val[c] /= accum_counter;
shun-iwasawa a6544b
shun-iwasawa a6544b
      if (isRGB && !this->alpha_rendering_sw_ &&
shun-iwasawa a6544b
          (in_current_pixel[c] < accum_val[c]) &&
shun-iwasawa a6544b
          result_pixel[igs::image::rgba::alp] < 1.f) {
shun-iwasawa a6544b
        result_pixel[c] =
shun-iwasawa a6544b
            in_current_pixel[c] + (accum_val[c] - in_current_pixel[c]) *
shun-iwasawa a6544b
                                      result_pixel[igs::image::rgba::alp];
Shinya Kitaoka 120a6e
      } else {
shun-iwasawa a6544b
        result_pixel[c] = accum_val[c];
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
shun-iwasawa a6544b
  radial_();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* copy constructorを無効化 */
shun-iwasawa a6544b
  radial_(const radial_&);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* 代入演算子を無効化 */
shun-iwasawa a6544b
  radial_& operator=(const radial_&);
Toshihiro Shimizu 890ddd
};
Shinya Kitaoka 120a6e
shun-iwasawa a6544b
void radial_convert(
shun-iwasawa a6544b
    const float* in, float* out, const int margin, /* 参照画像(in)がもつ余白 */
shun-iwasawa a6544b
    const TDimension out_dim,             /* 求める画像(out)のサイズ */
shun-iwasawa a6544b
    const int channels, const float* ref, /* 求める画像(out)と同じ高さ、幅 */
shun-iwasawa a6544b
    const TPointD center,
shun-iwasawa a6544b
    const double intensity, /* 強度。ゼロより大きく2以下 */
shun-iwasawa a6544b
    /* radius円境界での平均値ぼかしゼロとするためintensityは2より小さい */
shun-iwasawa a6544b
    const double radius, /* 平均値ぼかしの始まる半径 */
shun-iwasawa a6544b
    const double twist_radian, const double pivot_radius,
shun-iwasawa a6544b
    const int type,          // 0: Accelerator, 1: Uniform Length
shun-iwasawa a6544b
    const bool antialias_sw, /*  when true, sampled pixel will be
shun-iwasawa a6544b
                                bilinear-interpolated */
shun-iwasawa a6544b
    const bool alpha_rendering_sw, const double ellipse_aspect_ratio,
shun-iwasawa a6544b
    const double ellipse_angle,
shun-iwasawa a6544b
    const double intensity_correlation_with_ellipse) {
shun-iwasawa a6544b
  assert(intensity > 0.0);
shun-iwasawa a6544b
shun-iwasawa a6544b
  radial_ radial(in, out_dim.ly + margin * 2, out_dim.lx + margin * 2, channels,
shun-iwasawa a6544b
                 center, antialias_sw, alpha_rendering_sw, intensity, radius,
shun-iwasawa a6544b
                 twist_radian, pivot_radius, type, ellipse_aspect_ratio,
shun-iwasawa a6544b
                 ellipse_angle * M_PI_180, intensity_correlation_with_ellipse);
shun-iwasawa a6544b
shun-iwasawa a6544b
  const float* p_in =
shun-iwasawa a6544b
      in + margin * (out_dim.lx + margin * 2) * channels + margin * channels;
shun-iwasawa a6544b
shun-iwasawa a6544b
  float* p_out       = out;
shun-iwasawa a6544b
  const float* p_ref = ref;
shun-iwasawa a6544b
shun-iwasawa a6544b
  for (int yy = margin; yy < out_dim.ly + margin;
shun-iwasawa a6544b
       ++yy, p_in += 2 * margin * channels) {
shun-iwasawa a6544b
    for (int xx = margin; xx < out_dim.lx + margin;
shun-iwasawa a6544b
         ++xx, p_in += channels, p_out += channels) {
Shinya Kitaoka 120a6e
      using namespace igs::image::rgba;
shun-iwasawa a6544b
      float refVal = (ref) ? *p_ref : 1.f;
shun-iwasawa a6544b
shun-iwasawa a6544b
      // if the reference value is zero
shun-iwasawa a6544b
      if (refVal == 0.f) {
shun-iwasawa a6544b
        for (int c = 0; c < channels; ++c) p_out[c] = p_in[c];
shun-iwasawa a6544b
        p_ref++;
shun-iwasawa a6544b
        continue;
Shinya Kitaoka 120a6e
      }
shun-iwasawa a6544b
shun-iwasawa a6544b
      if (alpha_rendering_sw) {  // blur alpha
shun-iwasawa a6544b
        radial.pixel_value(p_in, xx, yy, false, refVal, p_out);
shun-iwasawa a6544b
      } else {  // use the src alpha as-is
shun-iwasawa a6544b
        p_out[alp] = p_in[alp];
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
shun-iwasawa a6544b
      if (p_out[alp] == 0.f) {
shun-iwasawa a6544b
        p_out[red] = p_in[red];
shun-iwasawa a6544b
        p_out[gre] = p_in[gre];
shun-iwasawa a6544b
        p_out[blu] = p_in[blu];
shun-iwasawa a6544b
        if (ref) p_ref++;
shun-iwasawa a6544b
        continue;
Shinya Kitaoka 120a6e
      }
shun-iwasawa a6544b
shun-iwasawa a6544b
      // blur RGB channels
shun-iwasawa a6544b
      radial.pixel_value(p_in, xx, yy, true, refVal, p_out);
shun-iwasawa a6544b
shun-iwasawa a6544b
      if (ref) p_ref++;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
shun-iwasawa a6544b
}  // namespace
shun-iwasawa a6544b
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------
Toshihiro Shimizu 890ddd
void igs::radial_blur::convert(
shun-iwasawa a6544b
    const float* in, float* out, const int margin, /* 参照画像(in)がもつ余白 */
shun-iwasawa a6544b
    const TDimension out_dim,             /* 求める画像(out)の大きさ*/
shun-iwasawa a6544b
    const int channels, const float* ref, /* outと同じ高さ、幅 */
shun-iwasawa a6544b
    const TPointD center, const double twist_radian, const double twist_radius,
shun-iwasawa a6544b
    const double intensity, /* 強度。ゼロより大きく2以下 */
Shinya Kitaoka 120a6e
    /* radius円境界での平均値ぼかしゼロとするためintensityは2より小さい */
shun-iwasawa a6544b
    const double radius, /* 平均値ぼかしの始まる半径 */
shun-iwasawa a6544b
    const int type, const bool antialias_sw, const bool alpha_rendering_sw,
shun-iwasawa a6544b
    const double ellipse_aspect_ratio, const double ellipse_angle,
shun-iwasawa a6544b
    const double intensity_correlation_with_ellipse) {
shun-iwasawa a6544b
  /* 強度のないとき */
shun-iwasawa a6544b
  if (intensity <= 0.0) {
shun-iwasawa a6544b
    igs::image::copy_except_margin(in, margin, out, out_dim.ly, out_dim.lx,
shun-iwasawa a6544b
                                   channels);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
shun-iwasawa a6544b
  radial_convert(in, out, margin, out_dim, channels, ref, center, intensity,
shun-iwasawa a6544b
                 radius, twist_radian, twist_radius, type, antialias_sw,
shun-iwasawa a6544b
                 alpha_rendering_sw, ellipse_aspect_ratio, ellipse_angle,
shun-iwasawa a6544b
                 intensity_correlation_with_ellipse);
Toshihiro Shimizu 890ddd
}
shun-iwasawa a6544b
//-------------------- comment out end -------------------------
Toshihiro Shimizu 890ddd
namespace {
shun-iwasawa a6544b
shun-iwasawa a6544b
double reference_margin_length_(const TPointD center, const double xp,
shun-iwasawa a6544b
                                const double yp, const double intensity,
shun-iwasawa a6544b
                                const double radius, const double pivot_radius,
shun-iwasawa a6544b
                                const int type,
shun-iwasawa a6544b
                                const double ellipse_aspect_ratio,
shun-iwasawa a6544b
                                const double intensity_correlation_with_ellipse,
shun-iwasawa a6544b
                                const QTransform& tr_inv) {
shun-iwasawa a6544b
  const QPointF c(center.x, center.y);
shun-iwasawa a6544b
  const QPointF p(xp, yp);
shun-iwasawa a6544b
  const QVector2D v(p - c);
shun-iwasawa a6544b
  const float dist = v.length();
Shinya Kitaoka 120a6e
  if (dist <= radius) {
Shinya Kitaoka 120a6e
    return 0;
Shinya Kitaoka 120a6e
  }
shun-iwasawa a6544b
  double length;
shun-iwasawa a6544b
  if (ellipse_aspect_ratio == 1.) {
shun-iwasawa a6544b
    if (type == Accelerator)
shun-iwasawa a6544b
      length = (dist - radius) * intensity;
shun-iwasawa a6544b
    else
shun-iwasawa a6544b
      length = (pivot_radius - radius) * intensity;
shun-iwasawa a6544b
  } else {
shun-iwasawa a6544b
    float dist_mod       = QVector2D(tr_inv.map(v.toPointF())).length();
shun-iwasawa a6544b
    double distanceRatio = dist / dist_mod;
shun-iwasawa a6544b
    if (type == Accelerator)
shun-iwasawa a6544b
      length = (dist - radius * distanceRatio) * intensity *
shun-iwasawa a6544b
               std::pow(distanceRatio, intensity_correlation_with_ellipse);
shun-iwasawa a6544b
    else  // Uniform_Length
shun-iwasawa a6544b
      length = (pivot_radius - radius) * intensity *
shun-iwasawa a6544b
               std::pow(distanceRatio, intensity_correlation_with_ellipse);
shun-iwasawa a6544b
  }
shun-iwasawa a6544b
  return length;
Toshihiro Shimizu 890ddd
}
shun-iwasawa a6544b
shun-iwasawa a6544b
}  // namespace
Shinya Kitaoka 120a6e
int igs::radial_blur::
Shinya Kitaoka 120a6e
    reference_margin(/* Twist時は正確ではない... */
shun-iwasawa a6544b
                     const int height, const int width, const TPointD center,
shun-iwasawa a6544b
                     const double twist_radian, const double twist_radius,
shun-iwasawa a6544b
                     const double intensity, /* 強度。ゼロより大きく2以下 */
Shinya Kitaoka 120a6e
                     /* radius円境界での平均値ぼかしゼロとするためintensityは2より小さい
shun-iwasawa a6544b
                      */
shun-iwasawa a6544b
                     const double radius, /* 平均値ぼかしの始まる半径 */
shun-iwasawa a6544b
                     const int type, const double ellipse_aspect_ratio,
shun-iwasawa a6544b
                     const double ellipse_angle,
shun-iwasawa a6544b
                     const double intensity_correlation_with_ellipse) {
shun-iwasawa a6544b
  /* 強度のないとき、2以上のとき、なにもしない */
shun-iwasawa a6544b
  if (intensity <= 0.0 || 2.0 <= intensity) {
Shinya Kitaoka 120a6e
    return 0;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double margin1 = 0;
Shinya Kitaoka 120a6e
  double margin2 = 0;
Shinya Kitaoka 120a6e
shun-iwasawa a6544b
  QTransform tr_inv;
shun-iwasawa a6544b
  if (ellipse_aspect_ratio != 1.0) {
shun-iwasawa a6544b
    double axis_x = 2.0 * ellipse_aspect_ratio / (ellipse_aspect_ratio + 1.0);
shun-iwasawa a6544b
    double axis_y = axis_x / ellipse_aspect_ratio;
shun-iwasawa a6544b
    tr_inv        = QTransform()
shun-iwasawa a6544b
                 .rotateRadians(ellipse_angle)
shun-iwasawa a6544b
                 .scale(axis_x, axis_y)
shun-iwasawa a6544b
                 .inverted();
shun-iwasawa a6544b
  }
shun-iwasawa a6544b
Shinya Kitaoka 120a6e
  /*
Shinya Kitaoka 120a6e
  四隅から参照する外部への最大マージンを計算する
Shinya Kitaoka 120a6e
  */
shun-iwasawa a6544b
  margin1 = reference_margin_length_(
shun-iwasawa a6544b
      center, -width / 2.0, -height / 2.0, intensity, radius, twist_radius,
shun-iwasawa a6544b
      type, ellipse_aspect_ratio, intensity_correlation_with_ellipse, tr_inv);
Shinya Kitaoka 120a6e
shun-iwasawa a6544b
  margin2 = reference_margin_length_(
shun-iwasawa a6544b
      center, -width / 2.0, height / 2.0, intensity, radius, twist_radius, type,
shun-iwasawa a6544b
      ellipse_aspect_ratio, intensity_correlation_with_ellipse, tr_inv);
Shinya Kitaoka 120a6e
  if (margin1 < margin2) {
Shinya Kitaoka 120a6e
    margin1 = margin2;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
shun-iwasawa a6544b
  margin2 = reference_margin_length_(
shun-iwasawa a6544b
      center, width / 2.0, -height / 2.0, intensity, radius, twist_radius, type,
shun-iwasawa a6544b
      ellipse_aspect_ratio, intensity_correlation_with_ellipse, tr_inv);
Shinya Kitaoka 120a6e
  if (margin1 < margin2) {
Shinya Kitaoka 120a6e
    margin1 = margin2;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
shun-iwasawa a6544b
  margin2 = reference_margin_length_(
shun-iwasawa a6544b
      center, width / 2.0, height / 2.0, intensity, radius, twist_radius, type,
shun-iwasawa a6544b
      ellipse_aspect_ratio, intensity_correlation_with_ellipse, tr_inv);
Shinya Kitaoka 120a6e
  if (margin1 < margin2) {
Shinya Kitaoka 120a6e
    margin1 = margin2;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return static_cast<int>(ceil(margin1));</int>
Toshihiro Shimizu 890ddd
}