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"
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
class radial_ {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  radial_(const T *in_top, const int height, const int width,
Shinya Kitaoka 120a6e
          const int channels, const double xc, const double yc,
Shinya Kitaoka 120a6e
          const double sub_size, const int imax, const double dmax,
Shinya Kitaoka 120a6e
          const double intensity /* 平均値ぼかし強度 */
Shinya Kitaoka 120a6e
          ,
Shinya Kitaoka 120a6e
          const double radius /* 平均値ぼかしの始まる半径 */
Shinya Kitaoka 120a6e
          )
Shinya Kitaoka 120a6e
      : in_top_(in_top)
Shinya Kitaoka 120a6e
      , hh_(height)
Shinya Kitaoka 120a6e
      , ww_(width)
Shinya Kitaoka 120a6e
      , cc_(channels)
Shinya Kitaoka 120a6e
      , xc_(xc)
Shinya Kitaoka 120a6e
      , yc_(yc)
Shinya Kitaoka 120a6e
      , sub_size_(sub_size)
Shinya Kitaoka 120a6e
      , imax_(imax)
Shinya Kitaoka 120a6e
      , dmax_(dmax)
Shinya Kitaoka 120a6e
      , intensity_(intensity)
Shinya Kitaoka 120a6e
      , radius_(radius) {}
Shinya Kitaoka 120a6e
  void pixel_value(const T *in_current_pixel, const int xx, const int yy,
Shinya Kitaoka 120a6e
                   const int z1, const int z2, const double ref_increase_val,
Shinya Kitaoka 120a6e
                   const double ref_decrease_val,
Shinya Kitaoka 120a6e
                   const double each_pixel_blur_ratio, T *result_pixel) {
Shinya Kitaoka 120a6e
    /* Pixel位置(0.5 1.5 2.5 ...) */
Shinya Kitaoka 120a6e
    const double xp = static_cast<double>(xx) + 0.5;</double>
Shinya Kitaoka 120a6e
    const double yp = static_cast<double>(yy) + 0.5;</double>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* 中心からPixel位置へのベクトルと長さ */
Shinya Kitaoka 120a6e
    const double xv   = xp - this->xc_;
Shinya Kitaoka 120a6e
    const double yv   = yp - this->yc_;
Shinya Kitaoka 120a6e
    const double dist = sqrt(xv * xv + yv * yv);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* 指定半径の範囲内なら何もしない */
Shinya Kitaoka 120a6e
    if (dist <= this->radius_) {
Shinya Kitaoka 120a6e
      for (int zz = z1; zz <= z2; ++zz) {
Shinya Kitaoka 120a6e
        result_pixel[zz] = in_current_pixel[zz];
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* 中心からPixel位置への単位ベクトル */
Shinya Kitaoka 120a6e
    const double cosval = xv / dist;
Shinya Kitaoka 120a6e
    const double sinval = yv / dist;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* Radial方向のSamplingの開始位置と終了位置 */
Shinya Kitaoka 120a6e
    double scale = this->intensity_;
Shinya Kitaoka 120a6e
    if (0.0 <= each_pixel_blur_ratio) {
Shinya Kitaoka 120a6e
      scale *= each_pixel_blur_ratio;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    const double length     = (dist - this->radius_) * scale;
Shinya Kitaoka 120a6e
    const double count_half = floor(length / 2.0 / this->sub_size_);
Shinya Kitaoka 120a6e
    const double sub_sta    = -this->sub_size_ * count_half;
Shinya Kitaoka 120a6e
    const double sub_end    = this->sub_size_ * count_half;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* 積算値と積算回数 */
Shinya Kitaoka 120a6e
    std::vector<double> accum_val(this->cc_);</double>
Shinya Kitaoka 120a6e
    int accum_counter = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* 円周接線方向Samplingの相対位置 */
Shinya Kitaoka 120a6e
    for (double ss = this->sub_size_ / 2.0 - 0.5; ss < 0.5;
Shinya Kitaoka 120a6e
         ss += this->sub_size_) {
Shinya Kitaoka 120a6e
      /* 円周接線方向Sampling位置 */
Shinya Kitaoka 120a6e
      const double xps = xp + ss * sinval;
Shinya Kitaoka 120a6e
      const double yps = yp + ss * cosval;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /* 中心からSampling位置へのベクトルと長さ */
Shinya Kitaoka 120a6e
      const double xvs   = xps - this->xc_;
Shinya Kitaoka 120a6e
      const double yvs   = yps - this->yc_;
Shinya Kitaoka 120a6e
      const double dists = sqrt(xvs * xvs + yvs * yvs);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /* 中心からSampling位置への単位ベクトル */
Shinya Kitaoka 120a6e
      const double cosvals = xvs / dists;
Shinya Kitaoka 120a6e
      const double sinvals = yvs / dists;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /* Radial方向のSampling */
Shinya Kitaoka 120a6e
      for (double tt = sub_sta; tt <= sub_end; tt += this->sub_size_) {
Shinya Kitaoka 120a6e
        /* Sampling位置からPixel位置を得る */
Shinya Kitaoka 120a6e
        int xi = static_cast<int>(xps + tt * cosvals);</int>
Shinya Kitaoka 120a6e
        int yi = static_cast<int>(yps + tt * sinvals);</int>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        /* clamp */
Shinya Kitaoka 120a6e
        xi = (xi < 0) ? 0 : ((this->ww_ <= xi) ? this->ww_ - 1 : xi);
Shinya Kitaoka 120a6e
        yi = (yi < 0) ? 0 : ((this->hh_ <= yi) ? this->hh_ - 1 : yi);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        /* 画像のPixel位置 */
Shinya Kitaoka 120a6e
        const T *in_current =
Shinya Kitaoka 120a6e
            this->in_top_ + this->cc_ * this->ww_ * yi + this->cc_ * xi;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        /* 積算 */
Shinya Kitaoka 120a6e
        for (int zz = z1; zz <= z2; ++zz) {
Shinya Kitaoka 120a6e
          accum_val[zz] += static_cast<double>(in_current[zz]);</double>
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        ++accum_counter;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    /* 積算しなかったとき(念のためのCheck) */
Shinya Kitaoka 120a6e
    if (accum_counter <= 0) {
Shinya Kitaoka 120a6e
      for (int zz = z1; zz <= z2; ++zz) {
Shinya Kitaoka 120a6e
        result_pixel[zz] = in_current_pixel[zz];
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    /* ここで画像Pixelに保存 */
Shinya Kitaoka 120a6e
    for (int zz = z1; zz <= z2; ++zz) {
Shinya Kitaoka 120a6e
      accum_val[zz] /= static_cast<double>(accum_counter);</double>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if ((0 <= ref_increase_val) && (in_current_pixel[zz] < accum_val[zz])) {
Shinya Kitaoka 120a6e
        /* 増分のみMask! */
Shinya Kitaoka 120a6e
        accum_val[zz] =
Shinya Kitaoka 120a6e
            static_cast<double>(in_current_pixel[zz]) +</double>
Shinya Kitaoka 120a6e
            (accum_val[zz] - in_current_pixel[zz]) * ref_increase_val;
Shinya Kitaoka 120a6e
      } else if ((0 <= ref_decrease_val) &&
Shinya Kitaoka 120a6e
                 (accum_val[zz] < in_current_pixel[zz])) {
Shinya Kitaoka 120a6e
        /* 減分のみMask! */
Shinya Kitaoka 120a6e
        accum_val[zz] =
Shinya Kitaoka 120a6e
            static_cast<double>(in_current_pixel[zz]) +</double>
Shinya Kitaoka 120a6e
            (accum_val[zz] - in_current_pixel[zz]) * ref_decrease_val;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      accum_val[zz] += 0.5; /* 誤差対策 */
Shinya Kitaoka 120a6e
      if (this->dmax_ < accum_val[zz]) {
Shinya Kitaoka 120a6e
        result_pixel[zz] = static_cast<t>(this->imax_);</t>
Shinya Kitaoka 120a6e
      } else if (accum_val[zz] < 0) {
Shinya Kitaoka 120a6e
        result_pixel[zz] = 0;
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        result_pixel[zz] = static_cast<t>(accum_val[zz]);</t>
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  radial_() {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  const T *in_top_;
Shinya Kitaoka 120a6e
  const int hh_;
Shinya Kitaoka 120a6e
  const int ww_;
Shinya Kitaoka 120a6e
  const int cc_;
Shinya Kitaoka 120a6e
  const double xc_;
Shinya Kitaoka 120a6e
  const double yc_;
Shinya Kitaoka 120a6e
  const double sub_size_;
Shinya Kitaoka 120a6e
  const int imax_;
Shinya Kitaoka 120a6e
  const double dmax_;
Shinya Kitaoka 120a6e
  const double intensity_;
Shinya Kitaoka 120a6e
  const double radius_;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* copy constructorを無効化 */
Shinya Kitaoka 120a6e
  radial_(const radial_ &);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* 代入演算子を無効化 */
Shinya Kitaoka 120a6e
  radial_ &operator=(const radial_ &);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
template <class class="" it,="" rt=""></class>
Toshihiro Shimizu 890ddd
void radial_convert_template_(
Shinya Kitaoka 120a6e
    const IT *in, const int margin /* 参照画像(in)がもつ余白 */
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const RT *ref /* 求める画像(out)と同じ高さ、幅、チャンネル数 */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int ref_bits, const int ref_mode  // R,G,B,A,luminance
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    IT *out, const int hh /* 求める画像(out)の高さ */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int ww /* 求める画像(out)の幅 */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int cc, const double xc, const double yc,
Shinya Kitaoka 120a6e
    const double intensity /* 強度。ゼロより大きく2以下 */
Shinya Kitaoka 120a6e
    /* radius円境界での平均値ぼかしゼロとするためintensityは2より小さい */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const double radius /* 平均値ぼかしの始まる半径 */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int sub_div /* 1ならJaggy、2以上はAntialias */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const bool alpha_rendering_sw) {
Shinya Kitaoka 120a6e
  ref_bits;  // for warning
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* 強度のないとき、または、サブ分割がないとき、なにもしない */
Shinya Kitaoka 120a6e
  if (intensity <= 0.0 || sub_div <= 0) {
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  radial_<it> cl_ra(</it>
Shinya Kitaoka 120a6e
      in, hh + margin * 2, ww + margin * 2, cc, xc + margin, yc + margin,
Shinya Kitaoka 120a6e
      1.0 / sub_div, std::numeric_limits<it>::max() /* サンプリング値 */</it>
Shinya Kitaoka 120a6e
      ,
Shinya Kitaoka 120a6e
      static_cast<double>(std::numeric_limits<it>::max()), intensity, radius);</it></double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if defined RGBA_ORDER_OF_TOONZ6
Shinya Kitaoka 120a6e
  const int z1 = igs::image::rgba::blu;
Shinya Kitaoka 120a6e
  const int z2 = igs::image::rgba::red;
Toshihiro Shimizu 890ddd
#elif defined RGBA_ORDER_OF_OPENGL
Shinya Kitaoka 120a6e
  const int z1 = igs::image::rgba::red;
Shinya Kitaoka 120a6e
  const int z2 = igs::image::rgba::blu;
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
  Must be define / DRGBA_ORDER_OF_TOONZ6 or
Shinya Kitaoka 120a6e
      / DRGBA_ORDER_OF_OPENGL
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  const IT *p_in = in + margin * (ww + margin * 2) * cc + margin * cc;
Shinya Kitaoka 120a6e
  IT *pout       = out;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (0 == ref) { /* 参照なし */
Shinya Kitaoka 120a6e
    if (igs::image::rgba::siz == cc) {
Shinya Kitaoka 120a6e
      using namespace igs::image::rgba;
Shinya Kitaoka 120a6e
      if (alpha_rendering_sw) { /* Alphaも処理する */
Shinya Kitaoka 120a6e
        for (int yy = margin; yy < hh + margin; ++yy, p_in += 2 * margin * cc) {
Shinya Kitaoka 120a6e
          for (int xx = margin; xx < ww + margin;
Shinya Kitaoka 120a6e
               ++xx, p_in += cc, pout += cc) {
Shinya Kitaoka 120a6e
            cl_ra.pixel_value(p_in, xx, yy, alp, alp, -1.0, -1.0, -1.0, pout);
Shinya Kitaoka 120a6e
            if (0 == pout[alp]) {
Shinya Kitaoka 120a6e
              pout[red] = p_in[red];
Shinya Kitaoka 120a6e
              pout[gre] = p_in[gre];
Shinya Kitaoka 120a6e
              pout[blu] = p_in[blu];
Shinya Kitaoka 120a6e
              continue;
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
            cl_ra.pixel_value(p_in, xx, yy, z1, z2, -1.0, -1.0, -1.0, pout);
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      } else { /* Alpha処理しない、RGB増分をAlphaでMaskする */
Shinya Kitaoka 120a6e
        const unsigned int val_max = std::numeric_limits<it>::max();</it>
Shinya Kitaoka 120a6e
        for (int yy = margin; yy < hh + margin; ++yy, p_in += 2 * margin * cc) {
Shinya Kitaoka 120a6e
          for (int xx = margin; xx < ww + margin;
Shinya Kitaoka 120a6e
               ++xx, p_in += cc, pout += cc) {
Shinya Kitaoka 120a6e
            pout[alp] = p_in[alp];
Shinya Kitaoka 120a6e
            if (0 == pout[alp]) {
Shinya Kitaoka 120a6e
              pout[red] = p_in[red];
Shinya Kitaoka 120a6e
              pout[gre] = p_in[gre];
Shinya Kitaoka 120a6e
              pout[blu] = p_in[blu];
Shinya Kitaoka 120a6e
              continue;
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
            /* Alpha値あるならRGB増分のみAlphaでMaskする */
Shinya Kitaoka 120a6e
            cl_ra.pixel_value(p_in, xx, yy, z1, z2,
Shinya Kitaoka 120a6e
                              static_cast<double>(p_in[alp]) / val_max, -1.0,</double>
Shinya Kitaoka 120a6e
                              -1.0, pout);
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else { /* Alphaがない, RGB/Grayscale... */
Shinya Kitaoka 120a6e
      for (int yy = margin; yy < hh + margin; ++yy, p_in += 2 * margin * cc) {
Shinya Kitaoka 120a6e
        for (int xx = margin; xx < ww + margin; ++xx, p_in += cc, pout += cc) {
Shinya Kitaoka 120a6e
          cl_ra.pixel_value(p_in, xx, yy, 0, cc - 1, -1.0, -1.0, -1.0, pout);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else { /* 参照あり */
Shinya Kitaoka 120a6e
    const RT *refe  = ref;
Shinya Kitaoka 120a6e
    const int r_max = std::numeric_limits<rt>::max();</rt>
Shinya Kitaoka 120a6e
    if (igs::image::rgba::siz == cc) {
Shinya Kitaoka 120a6e
      using namespace igs::image::rgba;
Shinya Kitaoka 120a6e
      if (alpha_rendering_sw) { /* Alpha処理する */
Shinya Kitaoka 120a6e
        for (int yy = margin; yy < hh + margin; ++yy, p_in += 2 * margin * cc) {
Shinya Kitaoka 120a6e
          for (int xx = margin; xx < ww + margin;
Shinya Kitaoka 120a6e
               ++xx, p_in += cc, pout += cc, refe += cc) {
Shinya Kitaoka 120a6e
            const double refv =
Shinya Kitaoka 120a6e
                igs::color::ref_value(refe, cc, r_max, ref_mode);
Shinya Kitaoka 120a6e
            if (0 == refv) {
Shinya Kitaoka 120a6e
              for (int zz = 0; zz < cc; ++zz) {
Shinya Kitaoka 120a6e
                pout[zz] = p_in[zz];
Shinya Kitaoka 120a6e
              }
Shinya Kitaoka 120a6e
              continue;
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
            cl_ra.pixel_value(p_in, xx, yy, alp, alp, -1.0, -1.0, refv, pout);
Shinya Kitaoka 120a6e
            if (0 == pout[alp]) {
Shinya Kitaoka 120a6e
              pout[red] = p_in[red];
Shinya Kitaoka 120a6e
              pout[gre] = p_in[gre];
Shinya Kitaoka 120a6e
              pout[blu] = p_in[blu];
Shinya Kitaoka 120a6e
              continue;
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
            cl_ra.pixel_value(p_in, xx, yy, z1, z2, -1.0, -1.0, refv, pout);
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      } else { /* Alpha処理しない、RGB増分をAlphaでMaskする */
Shinya Kitaoka 120a6e
        const unsigned int val_max = std::numeric_limits<it>::max();</it>
Shinya Kitaoka 120a6e
        for (int yy = margin; yy < hh + margin; ++yy, p_in += 2 * margin * cc) {
Shinya Kitaoka 120a6e
          for (int xx = margin; xx < ww + margin;
Shinya Kitaoka 120a6e
               ++xx, p_in += cc, pout += cc, refe += cc) {
Shinya Kitaoka 120a6e
            const double refv =
Shinya Kitaoka 120a6e
                igs::color::ref_value(refe, cc, r_max, ref_mode);
Shinya Kitaoka 120a6e
            if (0 == refv) {
Shinya Kitaoka 120a6e
              for (int zz = 0; zz < cc; ++zz) {
Shinya Kitaoka 120a6e
                pout[zz] = p_in[zz];
Shinya Kitaoka 120a6e
              }
Shinya Kitaoka 120a6e
              continue;
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
            pout[alp] = p_in[alp];
Shinya Kitaoka 120a6e
            if (0 == pout[alp]) {
Shinya Kitaoka 120a6e
              pout[red] = p_in[red];
Shinya Kitaoka 120a6e
              pout[gre] = p_in[gre];
Shinya Kitaoka 120a6e
              pout[blu] = p_in[blu];
Shinya Kitaoka 120a6e
              continue;
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
            cl_ra.pixel_value(p_in, xx, yy, z1, z2,
Shinya Kitaoka 120a6e
                              static_cast<double>(p_in[alp]) / val_max, -1.0,</double>
Shinya Kitaoka 120a6e
                              refv, pout);
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else { /* Alphaがない, RGB/Grayscale... */
Shinya Kitaoka 120a6e
      for (int yy = margin; yy < hh + margin; ++yy, p_in += 2 * margin * cc) {
Shinya Kitaoka 120a6e
        for (int xx = margin; xx < ww + margin;
Shinya Kitaoka 120a6e
             ++xx, p_in += cc, pout += cc, refe += cc) {
Shinya Kitaoka 120a6e
          const double refv = igs::color::ref_value(refe, cc, r_max, ref_mode);
Shinya Kitaoka 120a6e
          if (0 == refv) {
Shinya Kitaoka 120a6e
            for (int zz = 0; zz < cc; ++zz) {
Shinya Kitaoka 120a6e
              pout[zz] = p_in[zz];
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
            continue;
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          cl_ra.pixel_value(p_in, xx, yy, 0, cc - 1, -1.0, -1.0, refv, pout);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------
Shinya Kitaoka 120a6e
namespace {
Shinya Kitaoka 120a6e
class twist_ {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  twist_(const int height, const double xc, const double yc,
Shinya Kitaoka 120a6e
         const double twist_radian, const double twist_radius)
Shinya Kitaoka 120a6e
      : xc_(xc)
Shinya Kitaoka 120a6e
      , yc_(yc)
Shinya Kitaoka 120a6e
      , twist_xp_(0)
Shinya Kitaoka 120a6e
      , twist_yp_(0)
Shinya Kitaoka 120a6e
      , twist_radian_(twist_radian)
Shinya Kitaoka 120a6e
      , twist_radius_(twist_radius)
Shinya Kitaoka 120a6e
      , current_xp_(0)
Shinya Kitaoka 120a6e
      , current_yp_(0)
Shinya Kitaoka 120a6e
      , current_radian_(0)
Shinya Kitaoka 120a6e
      , current_cos_(0)
Shinya Kitaoka 120a6e
      , current_sin_(0)
Shinya Kitaoka 120a6e
      , current_radius_(0) {
Shinya Kitaoka 120a6e
    /* twist_radiusは、Twist曲線上半径1のPixel画像上半径 */
Shinya Kitaoka 120a6e
    /* twist_radiusはゼロのとき、高さの半分を設定する */
Shinya Kitaoka 120a6e
    if (this->twist_radius_ <= 0.0) {
Shinya Kitaoka 120a6e
      this->twist_radius_ = height / 2.0;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    /* ゼロだと計算不能になる */
Shinya Kitaoka 120a6e
    if (this->twist_radius_ <= 0.0) {
Shinya Kitaoka 120a6e
      throw std::domain_error("twist_radius is equal less than zero");
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  void current_pos(const double xp, const double yp) {
Shinya Kitaoka 120a6e
    /* 現在位置 */
Shinya Kitaoka 120a6e
    this->current_xp_ = xp;
Shinya Kitaoka 120a6e
    this->current_yp_ = yp;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* 中心からの距離 */
Shinya Kitaoka 120a6e
    const double xv       = xp - this->xc_;
Shinya Kitaoka 120a6e
    const double yv       = yp - this->yc_;
Shinya Kitaoka 120a6e
    this->current_radius_ = sqrt(xv * xv + yv * yv);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* 基準からの距離比 */
Shinya Kitaoka 120a6e
    const double tt = this->current_radius_ / this->twist_radius_;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* Twist曲線上の位置 */
Shinya Kitaoka 120a6e
    const double xx = tt * cos(tt * this->twist_radian_);
Shinya Kitaoka 120a6e
    const double yy = tt * sin(tt * this->twist_radian_);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* Twist曲線の回転角度 */
Shinya Kitaoka 120a6e
    this->current_radian_ = atan2(yv, xv) - atan2(yy, xx);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* Twist曲線上の位置を回転角度に傾けた位置 */
Shinya Kitaoka 120a6e
    this->current_cos_ = cos(this->current_radian_);
Shinya Kitaoka 120a6e
    this->current_sin_ = sin(this->current_radian_);
Shinya Kitaoka 120a6e
    this->twist_xp_    = xx * this->current_cos_ - yy * this->current_sin_;
Shinya Kitaoka 120a6e
    this->twist_yp_    = xx * this->current_sin_ + yy * this->current_cos_;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  void twist_pos(const double pixel_pos, int &xi, int &yi) {
Shinya Kitaoka 120a6e
    /* 基準半径からの比 */
Shinya Kitaoka 120a6e
    const double tt = (this->current_radius_ + pixel_pos) / this->twist_radius_;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* Twist曲線上の比による位置 */
Shinya Kitaoka 120a6e
    const double xx = tt * cos(tt * this->twist_radian_);
Shinya Kitaoka 120a6e
    const double yy = tt * sin(tt * this->twist_radian_);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* その位置の角度に傾ける */
Shinya Kitaoka 120a6e
    double x2 = xx * this->current_cos_ - yy * this->current_sin_;
Shinya Kitaoka 120a6e
    double y2 = xx * this->current_sin_ + yy * this->current_cos_;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* Twist曲線上の位置の差 */
Shinya Kitaoka 120a6e
    x2 = (x2 - this->twist_xp_);
Shinya Kitaoka 120a6e
    y2 = (y2 - this->twist_yp_);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* Pixel画像上の位置の差 */
Shinya Kitaoka 120a6e
    x2 *= this->twist_radius_;
Shinya Kitaoka 120a6e
    y2 *= this->twist_radius_;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* Pixel画像上の位置 */
Shinya Kitaoka 120a6e
    x2 += this->current_xp_;
Shinya Kitaoka 120a6e
    y2 += this->current_yp_;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    xi = static_cast<int>(x2);</int>
Shinya Kitaoka 120a6e
    yi = static_cast<int>(y2);</int>
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  twist_();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const double xc_;
Shinya Kitaoka 120a6e
  const double yc_;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double twist_xp_;
Shinya Kitaoka 120a6e
  double twist_yp_;
Shinya Kitaoka 120a6e
  double twist_radian_;
Shinya Kitaoka 120a6e
  double twist_radius_;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double current_xp_;
Shinya Kitaoka 120a6e
  double current_yp_;
Shinya Kitaoka 120a6e
  double current_radian_;
Shinya Kitaoka 120a6e
  double current_cos_;
Shinya Kitaoka 120a6e
  double current_sin_;
Shinya Kitaoka 120a6e
  double current_radius_;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  /* copy constructorを無効化 */
Shinya Kitaoka 120a6e
  twist_(const twist_ &);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  /* 代入演算子を無効化 */
Shinya Kitaoka 120a6e
  twist_ &operator=(const twist_ &);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
//--------------------------------
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
class radial_twist_ {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  radial_twist_(const T *in_top, const int height /* 求める画像(out)の高さ */
Shinya Kitaoka 120a6e
                ,
Shinya Kitaoka 120a6e
                const int width /* 求める画像(out)の幅 */
Shinya Kitaoka 120a6e
                ,
Shinya Kitaoka 120a6e
                const int channels, const double xc, const double yc,
Shinya Kitaoka 120a6e
                const double sub_size, const int imax, const double dmax,
Shinya Kitaoka 120a6e
                const double intensity /* 平均値ぼかし強度 */
Shinya Kitaoka 120a6e
                ,
Shinya Kitaoka 120a6e
                const double radius /* 平均値ぼかしの始まる半径 */
Shinya Kitaoka 120a6e
                ,
Shinya Kitaoka 120a6e
                const double twist_radian, const double twist_radius)
Shinya Kitaoka 120a6e
      : in_top_(in_top)
Shinya Kitaoka 120a6e
      , hh_(height)
Shinya Kitaoka 120a6e
      , ww_(width)
Shinya Kitaoka 120a6e
      , cc_(channels)
Shinya Kitaoka 120a6e
      , xc_(xc)
Shinya Kitaoka 120a6e
      , yc_(yc)
Shinya Kitaoka 120a6e
      , sub_size_(sub_size)
Shinya Kitaoka 120a6e
      , imax_(imax)
Shinya Kitaoka 120a6e
      , dmax_(dmax)
Shinya Kitaoka 120a6e
      , intensity_(intensity)
Shinya Kitaoka 120a6e
      , radius_(radius)
Shinya Kitaoka 120a6e
      , cl_tw_(height, xc, yc, twist_radian, twist_radius) {}
Shinya Kitaoka 120a6e
  void pixel_value(const T *in_current_pixel, const int xx, const int yy,
Shinya Kitaoka 120a6e
                   const int z1, const int z2, const double ref_increase_val,
Shinya Kitaoka 120a6e
                   const double ref_decrease_val,
Shinya Kitaoka 120a6e
                   const double each_pixel_blur_ratio, T *result_pixel) {
Shinya Kitaoka 120a6e
    /* Pixel位置(0.5 1.5 2.5 ...) */
Shinya Kitaoka 120a6e
    const double xp = static_cast<double>(xx) + 0.5;</double>
Shinya Kitaoka 120a6e
    const double yp = static_cast<double>(yy) + 0.5;</double>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* 中心からPixel位置へのベクトルと長さ */
Shinya Kitaoka 120a6e
    const double xv   = xp - this->xc_;
Shinya Kitaoka 120a6e
    const double yv   = yp - this->yc_;
Shinya Kitaoka 120a6e
    const double dist = sqrt(xv * xv + yv * yv);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* 指定半径の範囲内なら何もしない */
Shinya Kitaoka 120a6e
    if (dist <= this->radius_) {
Shinya Kitaoka 120a6e
      for (int zz = z1; zz <= z2; ++zz) {
Shinya Kitaoka 120a6e
        result_pixel[zz] = in_current_pixel[zz];
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* Radial方向のSamplingの開始位置と終了位置 */
Shinya Kitaoka 120a6e
    double scale = this->intensity_;
Shinya Kitaoka 120a6e
    if (0.0 <= each_pixel_blur_ratio) {
Shinya Kitaoka 120a6e
      scale *= each_pixel_blur_ratio;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    const double length     = (dist - this->radius_) * scale;
Shinya Kitaoka 120a6e
    const double count_half = floor(length / 2.0 / this->sub_size_);
Shinya Kitaoka 120a6e
    const double sub_sta    = -this->sub_size_ * count_half;
Shinya Kitaoka 120a6e
    const double sub_end    = this->sub_size_ * count_half;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* 積算値と積算回数 */
Shinya Kitaoka 120a6e
    std::vector<double> accum_val(this->cc_);</double>
Shinya Kitaoka 120a6e
    int accum_counter = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* SubPixelによるSamplingの相対位置 */
Shinya Kitaoka 120a6e
    for (double xsub = this->sub_size_ / 2.0 - 0.5; xsub < 0.5;
Shinya Kitaoka 120a6e
         xsub += this->sub_size_) {
Shinya Kitaoka 120a6e
      for (double ysub = this->sub_size_ / 2.0 - 0.5; ysub < 0.5;
Shinya Kitaoka 120a6e
           ysub += this->sub_size_) {
Shinya Kitaoka 120a6e
        /* Sampling位置をセット */
Shinya Kitaoka 120a6e
        this->cl_tw_.current_pos(xp + xsub, yp + ysub);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        /* Radial&Twist方向のSampling */
Shinya Kitaoka 120a6e
        for (double tt = sub_sta; tt <= sub_end; tt += this->sub_size_) {
Shinya Kitaoka 120a6e
          /* Sampling位置からPixel位置を得る */
Shinya Kitaoka 120a6e
          int xi = 0;
Shinya Kitaoka 120a6e
          int yi = 0;
Shinya Kitaoka 120a6e
          this->cl_tw_.twist_pos(tt, xi, yi);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          /* clamp */
Shinya Kitaoka 120a6e
          xi = (xi < 0) ? 0 : ((this->ww_ <= xi) ? this->ww_ - 1 : xi);
Shinya Kitaoka 120a6e
          yi = (yi < 0) ? 0 : ((this->hh_ <= yi) ? this->hh_ - 1 : yi);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          /* 画像のPixel位置 */
Shinya Kitaoka 120a6e
          const T *in_current =
Shinya Kitaoka 120a6e
              this->in_top_ + this->cc_ * this->ww_ * yi + this->cc_ * xi;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          /* 積算 */
Shinya Kitaoka 120a6e
          for (int zz = z1; zz <= z2; ++zz) {
Shinya Kitaoka 120a6e
            accum_val[zz] += static_cast<double>(in_current[zz]);</double>
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
          ++accum_counter;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    /* 積算しなかったとき(念のためのCheck) */
Shinya Kitaoka 120a6e
    if (accum_counter <= 0) {
Shinya Kitaoka 120a6e
      for (int zz = z1; zz <= z2; ++zz) {
Shinya Kitaoka 120a6e
        result_pixel[zz] = in_current_pixel[zz];
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    /* ここで画像Pixelに保存 */
Shinya Kitaoka 120a6e
    for (int zz = z1; zz <= z2; ++zz) {
Shinya Kitaoka 120a6e
      accum_val[zz] /= static_cast<double>(accum_counter);</double>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if ((0 <= ref_increase_val) && (in_current_pixel[zz] < accum_val[zz])) {
Shinya Kitaoka 120a6e
        /* 増分のみMask! */
Shinya Kitaoka 120a6e
        accum_val[zz] =
Shinya Kitaoka 120a6e
            static_cast<double>(in_current_pixel[zz]) +</double>
Shinya Kitaoka 120a6e
            (accum_val[zz] - in_current_pixel[zz]) * ref_increase_val;
Shinya Kitaoka 120a6e
      } else if ((0 <= ref_decrease_val) &&
Shinya Kitaoka 120a6e
                 (accum_val[zz] < in_current_pixel[zz])) {
Shinya Kitaoka 120a6e
        /* 減分のみMask! */
Shinya Kitaoka 120a6e
        accum_val[zz] =
Shinya Kitaoka 120a6e
            static_cast<double>(in_current_pixel[zz]) +</double>
Shinya Kitaoka 120a6e
            (accum_val[zz] - in_current_pixel[zz]) * ref_decrease_val;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      accum_val[zz] += 0.5; /* 誤差対策 */
Shinya Kitaoka 120a6e
      if (this->dmax_ < accum_val[zz]) {
Shinya Kitaoka 120a6e
        result_pixel[zz] = static_cast<t>(this->imax_);</t>
Shinya Kitaoka 120a6e
      } else if (accum_val[zz] < 0) {
Shinya Kitaoka 120a6e
        result_pixel[zz] = 0;
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        result_pixel[zz] = static_cast<t>(accum_val[zz]);</t>
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  radial_twist_() {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  const T *in_top_;
Shinya Kitaoka 120a6e
  const int hh_;
Shinya Kitaoka 120a6e
  const int ww_;
Shinya Kitaoka 120a6e
  const int cc_;
Shinya Kitaoka 120a6e
  const double xc_;
Shinya Kitaoka 120a6e
  const double yc_;
Shinya Kitaoka 120a6e
  const double sub_size_;
Shinya Kitaoka 120a6e
  const int imax_;
Shinya Kitaoka 120a6e
  const double dmax_;
Shinya Kitaoka 120a6e
  const double intensity_;
Shinya Kitaoka 120a6e
  const double radius_;
Shinya Kitaoka 120a6e
  twist_ cl_tw_;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* copy constructorを無効化 */
Shinya Kitaoka 120a6e
  radial_twist_(const radial_twist_ &);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* 代入演算子を無効化 */
Shinya Kitaoka 120a6e
  radial_twist_ &operator=(const radial_twist_ &);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
//--------------------------------
Toshihiro Shimizu 890ddd
template <class class="" it,="" rt=""></class>
Toshihiro Shimizu 890ddd
void twist_convert_template_(
Shinya Kitaoka 120a6e
    const IT *in, const int margin /* 参照画像(in)がもつ余白 */
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const RT *ref /* 求める画像(out)と同じ高さ、幅、チャンネル数 */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int ref_bits, const int ref_mode  // R,G,B,A,luminance
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    IT *out, const int hh /* 求める画像(out)の高さ */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int ww /* 求める画像(out)の幅 */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int cc, const double xc, const double yc, const double twist_radian,
Shinya Kitaoka 120a6e
    const double twist_radius,
Shinya Kitaoka 120a6e
    const double intensity /* 強度。ゼロより大きく2以下 */
Shinya Kitaoka 120a6e
    /* radius円境界での平均値ぼかしゼロとするためintensityは2より小さい */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const double radius /* 平均値ぼかしの始まる半径 */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int sub_div /* 1ならJaggy、2以上はAntialias */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const bool alpha_rendering_sw) {
Shinya Kitaoka 120a6e
  ref_bits;  // for warning
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* 強度のないとき、または、サブ分割がないとき、なにもしない */
Shinya Kitaoka 120a6e
  if (intensity <= 0.0 || sub_div <= 0) {
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  radial_twist_<it> cl_ratw(in, hh + margin * 2, ww + margin * 2, cc,</it>
Shinya Kitaoka 120a6e
                            xc + margin, yc + margin, 1.0 / sub_div,
Shinya Kitaoka 120a6e
                            std::numeric_limits<it>::max(),</it>
Shinya Kitaoka 120a6e
                            static_cast<double>(std::numeric_limits<it>::max()),</it></double>
Shinya Kitaoka 120a6e
                            intensity, radius, twist_radian, twist_radius);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if defined RGBA_ORDER_OF_TOONZ6
Shinya Kitaoka 120a6e
  const int z1 = igs::image::rgba::blu;
Shinya Kitaoka 120a6e
  const int z2 = igs::image::rgba::red;
Toshihiro Shimizu 890ddd
#elif defined RGBA_ORDER_OF_OPENGL
Shinya Kitaoka 120a6e
  const int z1 = igs::image::rgba::red;
Shinya Kitaoka 120a6e
  const int z2 = igs::image::rgba::blu;
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
  Must be define / DRGBA_ORDER_OF_TOONZ6 or
Shinya Kitaoka 120a6e
      / DRGBA_ORDER_OF_OPENGL
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const IT *p_in = in + margin * (ww + margin * 2) * cc + margin * cc;
Shinya Kitaoka 120a6e
  IT *pout       = out;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (0 == ref) { /* 参照なし */
Shinya Kitaoka 120a6e
    if (igs::image::rgba::siz == cc) {
Shinya Kitaoka 120a6e
      using namespace igs::image::rgba;
Shinya Kitaoka 120a6e
      if (alpha_rendering_sw) { /* Alphaも処理する */
Shinya Kitaoka 120a6e
        for (int yy = margin; yy < hh + margin; ++yy, p_in += 2 * margin * cc) {
Shinya Kitaoka 120a6e
          for (int xx = margin; xx < ww + margin;
Shinya Kitaoka 120a6e
               ++xx, p_in += cc, pout += cc) {
Shinya Kitaoka 120a6e
            cl_ratw.pixel_value(p_in, xx, yy, alp, alp, -1.0, -1.0, -1.0, pout);
Shinya Kitaoka 120a6e
            if (0 == pout[alp]) {
Shinya Kitaoka 120a6e
              pout[red] = p_in[red];
Shinya Kitaoka 120a6e
              pout[gre] = p_in[gre];
Shinya Kitaoka 120a6e
              pout[blu] = p_in[blu];
Shinya Kitaoka 120a6e
              continue;
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
            cl_ratw.pixel_value(p_in, xx, yy, z1, z2, -1.0, -1.0, -1.0, pout);
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      } else { /* Alpha処理しない、RGB増分をAlphaでMaskする */
Shinya Kitaoka 120a6e
        const unsigned int val_max = std::numeric_limits<it>::max();</it>
Shinya Kitaoka 120a6e
        for (int yy = margin; yy < hh + margin; ++yy, p_in += 2 * margin * cc) {
Shinya Kitaoka 120a6e
          for (int xx = margin; xx < ww + margin;
Shinya Kitaoka 120a6e
               ++xx, p_in += cc, pout += cc) {
Shinya Kitaoka 120a6e
            pout[alp] = p_in[alp];
Shinya Kitaoka 120a6e
            if (0 == pout[alp]) {
Shinya Kitaoka 120a6e
              pout[red] = p_in[red];
Shinya Kitaoka 120a6e
              pout[gre] = p_in[gre];
Shinya Kitaoka 120a6e
              pout[blu] = p_in[blu];
Shinya Kitaoka 120a6e
              continue;
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
            cl_ratw.pixel_value(p_in, xx, yy, z1, z2,
Shinya Kitaoka 120a6e
                                static_cast<double>(p_in[alp]) / val_max, -1.0,</double>
Shinya Kitaoka 120a6e
                                -1.0, pout);
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else { /* Alphaがない, RGB/Grayscale... */
Shinya Kitaoka 120a6e
      for (int yy = margin; yy < hh + margin; ++yy, p_in += 2 * margin * cc) {
Shinya Kitaoka 120a6e
        for (int xx = margin; xx < ww + margin; ++xx, p_in += cc, pout += cc) {
Shinya Kitaoka 120a6e
          cl_ratw.pixel_value(p_in, xx, yy, 0, cc - 1, -1.0, -1.0, -1.0, pout);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else { /* 参照あり */
Shinya Kitaoka 120a6e
    const RT *refe  = ref;
Shinya Kitaoka 120a6e
    const int r_max = std::numeric_limits<rt>::max();</rt>
Shinya Kitaoka 120a6e
    if (igs::image::rgba::siz == cc) {
Shinya Kitaoka 120a6e
      using namespace igs::image::rgba;
Shinya Kitaoka 120a6e
      if (alpha_rendering_sw) { /* Alphaも処理する */
Shinya Kitaoka 120a6e
        for (int yy = margin; yy < hh + margin; ++yy, p_in += 2 * margin * cc) {
Shinya Kitaoka 120a6e
          for (int xx = margin; xx < ww + margin;
Shinya Kitaoka 120a6e
               ++xx, p_in += cc, pout += cc, refe += cc) {
Shinya Kitaoka 120a6e
            const double refv =
Shinya Kitaoka 120a6e
                igs::color::ref_value(refe, cc, r_max, ref_mode);
Shinya Kitaoka 120a6e
            if (0 == refv) {
Shinya Kitaoka 120a6e
              for (int zz = 0; zz < cc; ++zz) {
Shinya Kitaoka 120a6e
                pout[zz] = p_in[zz];
Shinya Kitaoka 120a6e
              }
Shinya Kitaoka 120a6e
              continue;
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
            cl_ratw.pixel_value(p_in, xx, yy, alp, alp, -1.0, -1.0, refv, pout);
Shinya Kitaoka 120a6e
            if (0 == pout[alp]) {
Shinya Kitaoka 120a6e
              pout[red] = p_in[red];
Shinya Kitaoka 120a6e
              pout[gre] = p_in[gre];
Shinya Kitaoka 120a6e
              pout[blu] = p_in[blu];
Shinya Kitaoka 120a6e
              continue;
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
            cl_ratw.pixel_value(p_in, xx, yy, z1, z2, -1.0, -1.0, refv, pout);
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      } else { /* Alpha処理しない、RGB増分をAlphaでMaskする */
Shinya Kitaoka 120a6e
        const unsigned int val_max = std::numeric_limits<it>::max();</it>
Shinya Kitaoka 120a6e
        for (int yy = margin; yy < hh + margin; ++yy, p_in += 2 * margin * cc) {
Shinya Kitaoka 120a6e
          for (int xx = margin; xx < ww + margin;
Shinya Kitaoka 120a6e
               ++xx, p_in += cc, pout += cc, refe += cc) {
Shinya Kitaoka 120a6e
            const double refv =
Shinya Kitaoka 120a6e
                igs::color::ref_value(refe, cc, r_max, ref_mode);
Shinya Kitaoka 120a6e
            if (0 == refv) {
Shinya Kitaoka 120a6e
              for (int zz = 0; zz < cc; ++zz) {
Shinya Kitaoka 120a6e
                pout[zz] = p_in[zz];
Shinya Kitaoka 120a6e
              }
Shinya Kitaoka 120a6e
              continue;
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
            pout[alp] = p_in[alp];
Shinya Kitaoka 120a6e
            if (0 == pout[alp]) {
Shinya Kitaoka 120a6e
              pout[red] = p_in[red];
Shinya Kitaoka 120a6e
              pout[gre] = p_in[gre];
Shinya Kitaoka 120a6e
              pout[blu] = p_in[blu];
Shinya Kitaoka 120a6e
              continue;
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
            cl_ratw.pixel_value(p_in, xx, yy, z1, z2,
Shinya Kitaoka 120a6e
                                static_cast<double>(p_in[alp]) / val_max, -1.0,</double>
Shinya Kitaoka 120a6e
                                refv, pout);
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else { /* Alphaがない, RGB/Grayscale... */
Shinya Kitaoka 120a6e
      for (int yy = margin; yy < hh + margin; ++yy, p_in += 2 * margin * cc) {
Shinya Kitaoka 120a6e
        for (int xx = margin; xx < ww + margin;
Shinya Kitaoka 120a6e
             ++xx, p_in += cc, pout += cc, refe += cc) {
Shinya Kitaoka 120a6e
          const double refv = igs::color::ref_value(refe, cc, r_max, ref_mode);
Shinya Kitaoka 120a6e
          if (0 == refv) {
Shinya Kitaoka 120a6e
            for (int zz = 0; zz < cc; ++zz) {
Shinya Kitaoka 120a6e
              pout[zz] = p_in[zz];
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
            continue;
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          cl_ratw.pixel_value(p_in, xx, yy, 0, cc - 1, -1.0, -1.0, refv, pout);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------
Toshihiro Shimizu 890ddd
void igs::radial_blur::convert(
Shinya Kitaoka 120a6e
    const unsigned char *in, const int margin /* 参照画像(in)がもつ余白 */
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const unsigned char *ref /* outと同じ高さ、幅、チャンネル数 */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int ref_bits, const int ref_mode  // R,G,B,A,luminance
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    unsigned char *out
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int height /* 求める画像(out)の高さ */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int width /* 求める画像(out)の幅 */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int channels, const int bits
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const double xc, const double yc, const double twist_radian,
Shinya Kitaoka 120a6e
    const double twist_radius
Shinya Kitaoka 120a6e
    /*
Toshihiro Shimizu 890ddd
Twist Radius
Shinya Kitaoka 120a6e
    ひねりの基準半径を指定します。
Shinya Kitaoka 120a6e
    単位はミリメートルです。
Shinya Kitaoka 120a6e
    最小は0。最大1000mm(1m)です。
Shinya Kitaoka 120a6e
    初期値は0でひねりはありません。
Toshihiro Shimizu 890ddd
*/
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const double intensity /* 強度。ゼロより大きく2以下 */
Shinya Kitaoka 120a6e
    /* radius円境界での平均値ぼかしゼロとするためintensityは2より小さい */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const double radius /* 平均値ぼかしの始まる半径 */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int sub_div /* 1ならJaggy、2以上はAntialias */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const bool alpha_rendering_sw) {
Shinya Kitaoka 120a6e
  if ((igs::image::rgba::siz != channels) &&
Shinya Kitaoka 120a6e
      (igs::image::rgb::siz != channels) && (1 != channels) /* bit(monoBW) */
Shinya Kitaoka 120a6e
      ) {
Shinya Kitaoka 120a6e
    throw std::domain_error("Bad channels,Not rgba/rgb/grayscale");
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if ((std::numeric_limits<unsigned char="">::digits != bits) &&</unsigned>
Shinya Kitaoka 120a6e
      (std::numeric_limits<unsigned short="">::digits != bits)) {</unsigned>
Shinya Kitaoka 120a6e
    throw std::domain_error("Bad in bits,Not uchar/ushort");
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if ((0 != ref) && (std::numeric_limits<unsigned char="">::digits != ref_bits) &&</unsigned>
Shinya Kitaoka 120a6e
      (std::numeric_limits<unsigned short="">::digits != ref_bits)) {</unsigned>
Shinya Kitaoka 120a6e
    throw std::domain_error("Bad ref bits,Not uchar/ushort");
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* 強度のないとき、または、サブ分割がないとき */
Shinya Kitaoka 120a6e
  if (intensity <= 0.0 || sub_div <= 0) {
Shinya Kitaoka 120a6e
    if (std::numeric_limits<unsigned char="">::digits == bits) {</unsigned>
Shinya Kitaoka 120a6e
      igs::image::copy_except_margin(in, margin, out, height, width, channels);
Shinya Kitaoka 120a6e
    } else if (std::numeric_limits<unsigned short="">::digits == bits) {</unsigned>
Shinya Kitaoka 120a6e
      igs::image::copy_except_margin(
Shinya Kitaoka 120a6e
          reinterpret_cast<const *="" short="" unsigned="">(in), margin,</const>
Shinya Kitaoka 120a6e
          reinterpret_cast<unsigned *="" short="">(out), height, width, channels);</unsigned>
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (0.0 == twist_radian) {
Shinya Kitaoka 120a6e
    if (std::numeric_limits<unsigned char="">::digits == ref_bits) {</unsigned>
Shinya Kitaoka 120a6e
      if (std::numeric_limits<unsigned char="">::digits == bits) {</unsigned>
Shinya Kitaoka 120a6e
        radial_convert_template_(in, margin, ref, ref_bits, ref_mode, out,
Shinya Kitaoka 120a6e
                                 height, width, channels, xc, yc, intensity,
Shinya Kitaoka 120a6e
                                 radius, sub_div, alpha_rendering_sw);
Shinya Kitaoka 120a6e
      } else if (std::numeric_limits<unsigned short="">::digits == bits) {</unsigned>
Shinya Kitaoka 120a6e
        radial_convert_template_(
Shinya Kitaoka 120a6e
            reinterpret_cast<const *="" short="" unsigned="">(in), margin, ref, ref_bits,</const>
Shinya Kitaoka 120a6e
            ref_mode, reinterpret_cast<unsigned *="" short="">(out), height, width,</unsigned>
Shinya Kitaoka 120a6e
            channels, xc, yc, intensity, radius, sub_div, alpha_rendering_sw);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else { /* ref_bitsがゼロでも(refがなくても)ここにくる */
Shinya Kitaoka 120a6e
      if (std::numeric_limits<unsigned char="">::digits == bits) {</unsigned>
Shinya Kitaoka 120a6e
        radial_convert_template_(
Shinya Kitaoka 120a6e
            in, margin, reinterpret_cast<const *="" short="" unsigned="">(ref), ref_bits,</const>
Shinya Kitaoka 120a6e
            ref_mode, out, height, width, channels, xc, yc, intensity, radius,
Shinya Kitaoka 120a6e
            sub_div, alpha_rendering_sw);
Shinya Kitaoka 120a6e
      } else if (std::numeric_limits<unsigned short="">::digits == bits) {</unsigned>
Shinya Kitaoka 120a6e
        radial_convert_template_(
Shinya Kitaoka 120a6e
            reinterpret_cast<const *="" short="" unsigned="">(in), margin,</const>
Shinya Kitaoka 120a6e
            reinterpret_cast<const *="" short="" unsigned="">(ref), ref_bits, ref_mode,</const>
Shinya Kitaoka 120a6e
            reinterpret_cast<unsigned *="" short="">(out), height, width, channels,</unsigned>
Shinya Kitaoka 120a6e
            xc, yc, intensity, radius, sub_div, alpha_rendering_sw);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    if (std::numeric_limits<unsigned char="">::digits == ref_bits) {</unsigned>
Shinya Kitaoka 120a6e
      if (std::numeric_limits<unsigned char="">::digits == bits) {</unsigned>
Shinya Kitaoka 120a6e
        twist_convert_template_(in, margin, ref, ref_bits, ref_mode, out,
Shinya Kitaoka 120a6e
                                height, width, channels, xc, yc, twist_radian,
Shinya Kitaoka 120a6e
                                twist_radius, intensity, radius, sub_div,
Shinya Kitaoka 120a6e
                                alpha_rendering_sw);
Shinya Kitaoka 120a6e
      } else if (std::numeric_limits<unsigned short="">::digits == bits) {</unsigned>
Shinya Kitaoka 120a6e
        twist_convert_template_(
Shinya Kitaoka 120a6e
            reinterpret_cast<const *="" short="" unsigned="">(in), margin, ref, ref_bits,</const>
Shinya Kitaoka 120a6e
            ref_mode, reinterpret_cast<unsigned *="" short="">(out), height, width,</unsigned>
Shinya Kitaoka 120a6e
            channels, xc, yc, twist_radian, twist_radius, intensity, radius,
Shinya Kitaoka 120a6e
            sub_div, alpha_rendering_sw);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else { /* ref_bitsがゼロでも(refがなくても)ここにくる */
Shinya Kitaoka 120a6e
      if (std::numeric_limits<unsigned char="">::digits == bits) {</unsigned>
Shinya Kitaoka 120a6e
        twist_convert_template_(
Shinya Kitaoka 120a6e
            in, margin, reinterpret_cast<const *="" short="" unsigned="">(ref), ref_bits,</const>
Shinya Kitaoka 120a6e
            ref_mode, out, height, width, channels, xc, yc, twist_radian,
Shinya Kitaoka 120a6e
            twist_radius, intensity, radius, sub_div, alpha_rendering_sw);
Shinya Kitaoka 120a6e
      } else if (std::numeric_limits<unsigned short="">::digits == bits) {</unsigned>
Shinya Kitaoka 120a6e
        twist_convert_template_(
Shinya Kitaoka 120a6e
            reinterpret_cast<const *="" short="" unsigned="">(in), margin,</const>
Shinya Kitaoka 120a6e
            reinterpret_cast<const *="" short="" unsigned="">(ref), ref_bits, ref_mode,</const>
Shinya Kitaoka 120a6e
            reinterpret_cast<unsigned *="" short="">(out), height, width, channels,</unsigned>
Shinya Kitaoka 120a6e
            xc, yc, twist_radian, twist_radius, intensity, radius, sub_div,
Shinya Kitaoka 120a6e
            alpha_rendering_sw);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
#if 0   //-------------------- comment out start ------------------------
Toshihiro Shimizu 890ddd
namespace {
Toshihiro Shimizu 890ddd
 double enlarge_margin_length_(
Toshihiro Shimizu 890ddd
	const double xc
Toshihiro Shimizu 890ddd
	,const double yc
Toshihiro Shimizu 890ddd
	,const double xp
Toshihiro Shimizu 890ddd
	,const double yp
Toshihiro Shimizu 890ddd
	,const double intensity
Toshihiro Shimizu 890ddd
	,const double radius
Toshihiro Shimizu 890ddd
	,const double sub_size
Toshihiro Shimizu 890ddd
 ) {
Toshihiro Shimizu 890ddd
	const double xv = xp - xc;
Toshihiro Shimizu 890ddd
	const double yv = yp - yc;
Toshihiro Shimizu 890ddd
	const double dist = sqrt(xv*xv + yv*yv);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/* "dist = len - (len - radius) * intensity / 2.0;"より */
Toshihiro Shimizu 890ddd
	const double len = (2.0 * dist - radius * intensity) /
Toshihiro Shimizu 890ddd
				(2.0-intensity);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/***const double length = (len - radius) * intensity;
Toshihiro Shimizu 890ddd
	const double count_half = floor(length / sub_size);
Toshihiro Shimizu 890ddd
	return sub_size * count_half;***/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (len <= radius) { return 0; }
Toshihiro Shimizu 890ddd
	return (len - radius) * intensity / 2.0;
Toshihiro Shimizu 890ddd
 }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
int igs::radial_blur::enlarge_margin( /* Twist時は正確ではない... */
Toshihiro Shimizu 890ddd
	const int height
Toshihiro Shimizu 890ddd
	,const int width
Toshihiro Shimizu 890ddd
	,const double xc
Toshihiro Shimizu 890ddd
	,const double yc
Toshihiro Shimizu 890ddd
	,const double twist_radian
Toshihiro Shimizu 890ddd
	,const double twist_radius
Toshihiro Shimizu 890ddd
	,const double intensity/* 強度。ゼロより大きく2以下 */
Toshihiro Shimizu 890ddd
 /* radius円境界での平均値ぼかしゼロとするためintensityは2より小さい */
Toshihiro Shimizu 890ddd
	,const double radius	/* 平均値ぼかしの始まる半径 */
Toshihiro Shimizu 890ddd
	,const int sub_div	/* 1ならJaggy、2以上はAntialias */
Toshihiro Shimizu 890ddd
) {
Toshihiro Shimizu 890ddd
	/* 強度のないとき、2以上のとき、または、サブ分割がないとき、
Toshihiro Shimizu 890ddd
	なにもしない */
Toshihiro Shimizu 890ddd
	if (intensity <= 0.0 || 2.0 <= intensity || sub_div <= 0) {
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double margin1 = 0;
Toshihiro Shimizu 890ddd
	double margin2 = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	margin1 = enlarge_margin_length_(
Toshihiro Shimizu 890ddd
	  xc,yc,-width/2.0,-height/2.0,intensity,radius,1.0/sub_div);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	margin2 = enlarge_margin_length_(
Toshihiro Shimizu 890ddd
	  xc,yc,-width/2.0, height/2.0,intensity,radius,1.0/sub_div);
Toshihiro Shimizu 890ddd
	if (margin1 < margin2) { margin1 = margin2; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	margin2 = enlarge_margin_length_(
Toshihiro Shimizu 890ddd
	  xc,yc, width/2.0,-height/2.0,intensity,radius,1.0/sub_div);
Toshihiro Shimizu 890ddd
	if (margin1 < margin2) { margin1 = margin2; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	margin2 = enlarge_margin_length_(
Toshihiro Shimizu 890ddd
	  xc,yc, width/2.0, height/2.0,intensity,radius,1.0/sub_div);
Toshihiro Shimizu 890ddd
	if (margin1 < margin2) { margin1 = margin2; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return static_cast<int>(ceil(margin1));</int>
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
#endif  //-------------------- comment out end -------------------------
Shinya Kitaoka 120a6e
namespace {
Shinya Kitaoka 120a6e
double reference_margin_length_(const double xc, const double yc,
Shinya Kitaoka 120a6e
                                const double xp, const double yp,
Shinya Kitaoka 120a6e
                                const double intensity, const double radius,
Shinya Kitaoka 120a6e
                                const double sub_size) {
Shinya Kitaoka 120a6e
  const double xv   = xp - xc;
Shinya Kitaoka 120a6e
  const double yv   = yp - yc;
Shinya Kitaoka 120a6e
  const double dist = sqrt(xv * xv + yv * yv);
Shinya Kitaoka 120a6e
  if (dist <= radius) {
Shinya Kitaoka 120a6e
    return 0;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  const double half_length = (dist - radius) * intensity / 2.0;
Shinya Kitaoka 120a6e
  const double count_half  = floor(half_length / sub_size);
Shinya Kitaoka 120a6e
  return sub_size * count_half;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
int igs::radial_blur::
Shinya Kitaoka 120a6e
    reference_margin(/* Twist時は正確ではない... */
Shinya Kitaoka 120a6e
                     const int height, const int width, const double xc,
Shinya Kitaoka 120a6e
                     const double yc, const double twist_radian,
Shinya Kitaoka 120a6e
                     const double twist_radius,
Shinya Kitaoka 120a6e
                     const double intensity /* 強度。ゼロより大きく2以下 */
Shinya Kitaoka 120a6e
                     /* radius円境界での平均値ぼかしゼロとするためintensityは2より小さい
Shinya Kitaoka 120a6e
                        */
Shinya Kitaoka 120a6e
                     ,
Shinya Kitaoka 120a6e
                     const double radius /* 平均値ぼかしの始まる半径 */
Shinya Kitaoka 120a6e
                     ,
Shinya Kitaoka 120a6e
                     const int sub_div /* 1ならJaggy、2以上はAntialias */
Shinya Kitaoka 120a6e
                     ) {
Shinya Kitaoka 120a6e
  twist_radius;  // for warning
Shinya Kitaoka 120a6e
  twist_radian;  // for warning
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* 強度のないとき、2以上のとき、または、サブ分割がないとき、
Shinya Kitaoka 120a6e
  なにもしない */
Shinya Kitaoka 120a6e
  if (intensity <= 0.0 || 2.0 <= intensity || sub_div <= 0) {
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
Shinya Kitaoka 120a6e
  /*
Shinya Kitaoka 120a6e
  四隅から参照する外部への最大マージンを計算する
Shinya Kitaoka 120a6e
  */
Shinya Kitaoka 120a6e
  margin1 = reference_margin_length_(xc, yc, -width / 2.0, -height / 2.0,
Shinya Kitaoka 120a6e
                                     intensity, radius, 1.0 / sub_div);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  margin2 = reference_margin_length_(xc, yc, -width / 2.0, height / 2.0,
Shinya Kitaoka 120a6e
                                     intensity, radius, 1.0 / sub_div);
Shinya Kitaoka 120a6e
  if (margin1 < margin2) {
Shinya Kitaoka 120a6e
    margin1 = margin2;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  margin2 = reference_margin_length_(xc, yc, width / 2.0, -height / 2.0,
Shinya Kitaoka 120a6e
                                     intensity, radius, 1.0 / sub_div);
Shinya Kitaoka 120a6e
  if (margin1 < margin2) {
Shinya Kitaoka 120a6e
    margin1 = margin2;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  margin2 = reference_margin_length_(xc, yc, width / 2.0, height / 2.0,
Shinya Kitaoka 120a6e
                                     intensity, radius, 1.0 / sub_div);
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
}