Shinya Kitaoka 120a6e
#include <iostream>   // std::cout</iostream>
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_rotate_blur.h"
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
class rotate_ {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  rotate_(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 radian, const double blur_radius,
Shinya Kitaoka 120a6e
          const double spin_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
      , radian_(radian)
Shinya Kitaoka 120a6e
      , blur_radius_(blur_radius)
Shinya Kitaoka 120a6e
      , spin_radius_(spin_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->blur_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
    /* 円周接線方向Sampling1つずらした位置への回転角度 */
Shinya Kitaoka 120a6e
    const double xw = xv - this->sub_size_ * sinval;
Shinya Kitaoka 120a6e
    const double yw = yv + this->sub_size_ * cosval;
Shinya Kitaoka 120a6e
    const double sub_radian =
Shinya Kitaoka 120a6e
        acos((xv * xw + yv * yw) /
Shinya Kitaoka 120a6e
             (sqrt(xv * xv + yv * yv) * sqrt(xw * xw + yw * yw)));
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
    /* 参照画像による強弱付加 */
Shinya Kitaoka 120a6e
    double scale = this->radian_;
Shinya Kitaoka 120a6e
    if (0.0 <= each_pixel_blur_ratio) {
Shinya Kitaoka 120a6e
      scale *= each_pixel_blur_ratio;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* Radial方向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
      /* Radial方向位置 */
Shinya Kitaoka 120a6e
      const double xp2 = xp + ss * cosval;
Shinya Kitaoka 120a6e
      const double yp2 = yp + ss * sinval;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /* ぼかす回転角度範囲range */
Shinya Kitaoka 120a6e
      double radian = scale;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (0.0 < this->spin_radius_) { /* 外への強調 */
Shinya Kitaoka 120a6e
        const double xv2   = xp2 - this->xc_;
Shinya Kitaoka 120a6e
        const double yv2   = yp2 - this->yc_;
Shinya Kitaoka 120a6e
        const double dist2 = sqrt(xv2 * xv2 + yv2 * yv2);
Shinya Kitaoka 120a6e
        radian *=
Shinya Kitaoka 120a6e
            /**(dist2              - this->blur_radius_) /
Shinya Kitaoka 120a6e
(this->spin_radius_ - this->blur_radius_);**/
Shinya Kitaoka 120a6e
            (dist2 - this->blur_radius_) / this->spin_radius_;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /* Sampling回数 */
Shinya Kitaoka 120a6e
      int sub_count = static_cast<int>(radian / sub_radian);</int>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /* Sampling開始角度 */
Shinya Kitaoka 120a6e
      const double sub_start =
Shinya Kitaoka 120a6e
          (radian - sub_count * sub_radian) / 2.0 - radian / 2.0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /* 円周方向Sampling */
Shinya Kitaoka 120a6e
      for (double rr = sub_start; 0 < sub_count--; rr += sub_radian) {
Shinya Kitaoka 120a6e
        /* Radial位置(xp2,yp2)から円周位置(xx,yy)へ */
Shinya Kitaoka 120a6e
        const double cosval2 = cos(rr);
Shinya Kitaoka 120a6e
        const double sinval2 = sin(rr);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        const double xd = xp2 - this->xc_;
Shinya Kitaoka 120a6e
        const double yd = yp2 - this->yc_;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        int xx = static_cast<int>(xd * cosval2 - yd * sinval2 + this->xc_);</int>
Shinya Kitaoka 120a6e
        int yy = static_cast<int>(xd * sinval2 + yd * cosval2 + this->yc_);</int>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        /* clamp */
Shinya Kitaoka 120a6e
        xx = (xx < 0) ? 0 : ((this->ww_ <= xx) ? this->ww_ - 1 : xx);
Shinya Kitaoka 120a6e
        yy = (yy < 0) ? 0 : ((this->hh_ <= yy) ? this->hh_ - 1 : yy);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        /* 画像のPixel位置 */
Shinya Kitaoka 120a6e
        const T *in_current =
Shinya Kitaoka 120a6e
            this->in_top_ + this->cc_ * yy * this->ww_ + this->cc_ * xx;
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
  rotate_() {}
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 radian_;
Shinya Kitaoka 120a6e
  const double blur_radius_;
Shinya Kitaoka 120a6e
  const double spin_radius_;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* copy constructorを無効化 */
Shinya Kitaoka 120a6e
  rotate_(const rotate_ &);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* 代入演算子を無効化 */
Shinya Kitaoka 120a6e
  rotate_ &operator=(const rotate_ &);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
const double pi = 3.14159265358979;
Toshihiro Shimizu 890ddd
template <class class="" it,="" rt=""></class>
Toshihiro Shimizu 890ddd
void rotate_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 degree,
Shinya Kitaoka 120a6e
    const double blur_radius /* ぼかしの始まる半径 */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const double spin_radius /* ゼロ以上でspin指定となり、
Shinya Kitaoka 120a6e
                            かつぼかし強弱の一定になる半径となる */
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 (degree <= 0.0 || sub_div <= 0
Shinya Kitaoka 120a6e
      // || spin_radius<=blur_radius
Shinya Kitaoka 120a6e
      ) {
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  rotate_<it> cl_rota(in, hh + margin * 2, ww + margin * 2, cc, xc + margin,</it>
Shinya Kitaoka 120a6e
                      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
                      degree * pi / 180.0, blur_radius, spin_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_rota.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_rota.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_rota.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_rota.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_rota.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_rota.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_rota.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_rota.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
Toshihiro Shimizu 890ddd
void igs::rotate_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 degree /* ぼかしの回転角度 */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const double blur_radius /* ぼかしの始まる半径 */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const double spin_radius /* ゼロ以上でspin指定となり、
Shinya Kitaoka 120a6e
                            かつぼかし強弱の一定になる半径となる */
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 (degree <= 0.0 || sub_div <= 0
Shinya Kitaoka 120a6e
      // || spin_radius<=blur_radius
Shinya Kitaoka 120a6e
      ) {
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 (std::numeric_limits<unsigned char="">::digits == ref_bits) {</unsigned>
Shinya Kitaoka 120a6e
    if (std::numeric_limits<unsigned char="">::digits == bits) {</unsigned>
Shinya Kitaoka 120a6e
      rotate_convert_template_(in, margin, ref, ref_bits, ref_mode, out, height,
Shinya Kitaoka 120a6e
                               width, channels, xc, yc, degree, blur_radius,
Shinya Kitaoka 120a6e
                               spin_radius, sub_div, alpha_rendering_sw);
Shinya Kitaoka 120a6e
    } else if (std::numeric_limits<unsigned short="">::digits == bits) {</unsigned>
Shinya Kitaoka 120a6e
      rotate_convert_template_(reinterpret_cast<const *="" short="" unsigned="">(in),</const>
Shinya Kitaoka 120a6e
                               margin, ref, ref_bits, ref_mode,
Shinya Kitaoka 120a6e
                               reinterpret_cast<unsigned *="" short="">(out), height,</unsigned>
Shinya Kitaoka 120a6e
                               width, channels, xc, yc, degree, blur_radius,
Shinya Kitaoka 120a6e
                               spin_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
      rotate_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, degree, blur_radius,
Shinya Kitaoka 120a6e
          spin_radius, sub_div, alpha_rendering_sw);
Shinya Kitaoka 120a6e
    } else if (std::numeric_limits<unsigned short="">::digits == bits) {</unsigned>
Shinya Kitaoka 120a6e
      rotate_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, xc,</unsigned>
Shinya Kitaoka 120a6e
          yc, degree, blur_radius, spin_radius, sub_div, alpha_rendering_sw);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------
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, double radian,
Shinya Kitaoka 120a6e
                                const double blur_radius,
Shinya Kitaoka 120a6e
                                const double spin_radius,
Shinya Kitaoka 120a6e
                                const double sub_size) {
Shinya Kitaoka 120a6e
  sub_size;  // for warning
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  const double xv = xp - xc;
Shinya Kitaoka 120a6e
  const double yv = yp - yc;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (0.0 < spin_radius) { /* 外への強調 */
Shinya Kitaoka 120a6e
    const double dist = sqrt(xv * xv + yv * yv);
Shinya Kitaoka 120a6e
    // radian *= (dist-blur_radius)/(spin_radius-blur_radius);
Shinya Kitaoka 120a6e
    radian *= (dist - blur_radius) / spin_radius;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double cosval      = cos(radian / 2.0);
Shinya Kitaoka 120a6e
  double sinval      = sin(radian / 2.0);
Shinya Kitaoka 120a6e
  const double x1    = xv * cosval - yv * sinval + xc;
Shinya Kitaoka 120a6e
  const double y1    = xv * sinval + yv * cosval + yc;
Shinya Kitaoka 120a6e
  const double xv1   = x1 - xp;
Shinya Kitaoka 120a6e
  const double yv1   = y1 - yp;
Shinya Kitaoka 120a6e
  const double dist1 = sqrt(xv1 * xv1 + yv1 * yv1); /* 必ずプラス値 */
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  cosval             = cos(-radian / 2.0);
Shinya Kitaoka 120a6e
  sinval             = sin(-radian / 2.0);
Shinya Kitaoka 120a6e
  const double xp2   = xv * cosval - yv * sinval + xc;
Shinya Kitaoka 120a6e
  const double yp2   = xv * sinval + yv * cosval + yc;
Shinya Kitaoka 120a6e
  const double xv2   = xp2 - xp;
Shinya Kitaoka 120a6e
  const double yv2   = yp2 - yp;
Shinya Kitaoka 120a6e
  const double dist2 = sqrt(xv2 * xv2 + yv2 * yv2); /* 必ずプラス値 */
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return (dist1 < dist2) ? dist2 : dist1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
int igs::rotate_blur::reference_margin(
Shinya Kitaoka 120a6e
    const int height /* 求める画像(out)の高さ */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int width /* 求める画像(out)の幅 */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const double xc, const double yc, const double degree /* ぼかしの回転角度 */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const double blur_radius /* ぼかしの始まる半径 */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const double spin_radius /* ゼロ以上でspin指定となり、
Shinya Kitaoka 120a6e
                            かつぼかし強弱の一定になる半径となる */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int sub_div /* 1ならJaggy、2以上はAntialias */
Shinya Kitaoka 120a6e
    ) {
Shinya Kitaoka 120a6e
  /* 強度のないとき、または、サブ分割がないとき、なにもしない */
Shinya Kitaoka 120a6e
  if (degree <= 0.0 || sub_div <= 0
Shinya Kitaoka 120a6e
      // || spin_radius<=blur_radius
Shinya Kitaoka 120a6e
      ) {
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
  double deg = degree;
Shinya Kitaoka 120a6e
  if (180.0 < deg) {
Shinya Kitaoka 120a6e
    deg = 180.0;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  margin1 = reference_margin_length_(xc, yc, -width / 2.0, -height / 2.0,
Shinya Kitaoka 120a6e
                                     deg * pi / 180.0, blur_radius, spin_radius,
Shinya Kitaoka 120a6e
                                     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
                                     deg * pi / 180.0, blur_radius, spin_radius,
Shinya Kitaoka 120a6e
                                     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
                                     deg * pi / 180.0, blur_radius, spin_radius,
Shinya Kitaoka 120a6e
                                     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
                                     deg * pi / 180.0, blur_radius, spin_radius,
Shinya Kitaoka 120a6e
                                     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
}