Toshihiro Shimizu 890ddd
#include <vector></vector>
Shinya Kitaoka 120a6e
#include <stdexcept>        /* std::domain_error(-) */</stdexcept>
Shinya Kitaoka 120a6e
#include <limits>           /* std::numeric_limits */</limits>
Shinya Kitaoka 120a6e
#include <cmath>            /* pow(-),abs(-) */</cmath>
Shinya Kitaoka 120a6e
#include <cstring>          /* memmove */</cstring>
Toshihiro Shimizu 890ddd
#include "igs_ifx_common.h" /* igs::image::rgba */
Toshihiro Shimizu 890ddd
#include "igs_motion_blur.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// #include <numeric> /* std::accumulate(-) */</numeric>
Shinya Kitaoka 120a6e
#if 0   //------comment out-----------------------------------------------
Toshihiro Shimizu 890ddd
namespace {
Toshihiro Shimizu 890ddd
 void dda_array_(
Toshihiro Shimizu 890ddd
	const int dx,	/* = abs(x_vector = x2 - x1) */
Toshihiro Shimizu 890ddd
	const int dy, /* = abs(y_vector = y2 - y1) = array_size - 1 */
Toshihiro Shimizu 890ddd
	std::vector<int>&y_array	/* array_size(0...dy)個ある */</int>
Toshihiro Shimizu 890ddd
 ) {
Toshihiro Shimizu 890ddd
	/* ここではy方向に傾いている場合(dx <= dy)のみ扱う
Toshihiro Shimizu 890ddd
	    y +      *
Toshihiro Shimizu 890ddd
	  (dy)|     *
Toshihiro Shimizu 890ddd
	      |    *
Toshihiro Shimizu 890ddd
	      |   *
Toshihiro Shimizu 890ddd
	  OUT +   *
Toshihiro Shimizu 890ddd
	      |  *
Toshihiro Shimizu 890ddd
	      | *
Toshihiro Shimizu 890ddd
	      |*
Toshihiro Shimizu 890ddd
	    0 +---+---+---+
Toshihiro Shimizu 890ddd
	      0           x(dx)
Toshihiro Shimizu 890ddd
		   IN
Toshihiro Shimizu 890ddd
	*/
Toshihiro Shimizu 890ddd
	if (dy < dx) { return; } /* x方向に傾いていると処理できない */
Toshihiro Shimizu 890ddd
	if (dy <= 0) { return; } /* y長さがないと処理しない */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	y_array.at(0) = 0; /* 始めは原点なのでインクリメントはゼロ */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/* 線分ループ */
Toshihiro Shimizu 890ddd
	const int incr1 = 2 * dx;
Toshihiro Shimizu 890ddd
	const int incr2 = 2 * (dx - dy);
Toshihiro Shimizu 890ddd
	int dd = (2 * dx) - dy;
Toshihiro Shimizu 890ddd
	for (int ii = 1; ii <= dy; ++ii) {
Toshihiro Shimizu 890ddd
		if (dd < 0) { dd += incr1; y_array.at(ii) = 0; }
Toshihiro Shimizu 890ddd
		else        { dd += incr2; y_array.at(ii) = 1; }
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
 }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
namespace {
Toshihiro Shimizu 890ddd
 void set_position_(
Toshihiro Shimizu 890ddd
	const int x_vector,
Toshihiro Shimizu 890ddd
	const int y_vector,/* 絶対値の大きいほうが"size-1" */
Toshihiro Shimizu 890ddd
	std::vector<int>&x_array,</int>
Toshihiro Shimizu 890ddd
	std::vector<int>&y_array /* 位置格納配列size個ある */</int>
Toshihiro Shimizu 890ddd
 ) {
Toshihiro Shimizu 890ddd
	int dx = abs(x_vector);/* 線分の幅、ゼロ以上の大きさの数 */
Toshihiro Shimizu 890ddd
	int dy = abs(y_vector);/* 線分の高さ、ゼロ以上の大きさの数 */
Toshihiro Shimizu 890ddd
	int count = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/* x方向に傾いている場合(dy < dx)
Toshihiro Shimizu 890ddd
	     y +        *
Toshihiro Shimizu 890ddd
	   (dy)|       *
Toshihiro Shimizu 890ddd
	       |      *
Toshihiro Shimizu 890ddd
	       |     *
Toshihiro Shimizu 890ddd
	   OUT +   *
Toshihiro Shimizu 890ddd
	       |  *
Toshihiro Shimizu 890ddd
	       | *
Toshihiro Shimizu 890ddd
	       |*
Toshihiro Shimizu 890ddd
	     0 +---+---+---+
Toshihiro Shimizu 890ddd
	       0           x(dx)
Toshihiro Shimizu 890ddd
                    IN
Toshihiro Shimizu 890ddd
	*/
Toshihiro Shimizu 890ddd
	if (dy < dx) {
Toshihiro Shimizu 890ddd
	 for (int ii=0;ii<=dx;++ii) {x_array.at(ii) = ii;}
Toshihiro Shimizu 890ddd
	 dda_array_( dy, dx, y_array );
Toshihiro Shimizu 890ddd
	 for (int ii=1;ii<=dx;++ii) {y_array.at(ii)+=y_array.at(ii-1);}
Toshihiro Shimizu 890ddd
	 count = dx;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/* y方向に傾いている場合(dx <= dy)
Toshihiro Shimizu 890ddd
	    y +      *
Toshihiro Shimizu 890ddd
	  (dy)|     *
Toshihiro Shimizu 890ddd
	      |    *
Toshihiro Shimizu 890ddd
	      |   *
Toshihiro Shimizu 890ddd
	  OUT +   *
Toshihiro Shimizu 890ddd
	      |  *
Toshihiro Shimizu 890ddd
	      | *
Toshihiro Shimizu 890ddd
	      |*
Toshihiro Shimizu 890ddd
	    0 +---+---+---+
Toshihiro Shimizu 890ddd
	      0           x(dx)
Toshihiro Shimizu 890ddd
                   IN
Toshihiro Shimizu 890ddd
	*/
Toshihiro Shimizu 890ddd
	else {
Toshihiro Shimizu 890ddd
	 for (int ii=0;ii<=dy;++ii) {y_array.at(ii) = ii;}
Toshihiro Shimizu 890ddd
	 dda_array_( dx, dy, x_array );
Toshihiro Shimizu 890ddd
	 for (int ii=1;ii<=dy;++ii) {x_array.at(ii)+=x_array.at(ii-1);}
Toshihiro Shimizu 890ddd
	 count = dy;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/* マイナス方向の場合は反転 */
Toshihiro Shimizu 890ddd
	if (x_vector < 0) {
Toshihiro Shimizu 890ddd
	 for (int ii=1;ii<=count;++ii){x_array.at(ii)=-x_array.at(ii);}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (y_vector < 0) {
Toshihiro Shimizu 890ddd
	 for (int ii=1;ii<=count;++ii){y_array.at(ii)=-y_array.at(ii);}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
 }
Toshihiro Shimizu 890ddd
 void set_ratio_(
Toshihiro Shimizu 890ddd
	const double curve,
Toshihiro Shimizu 890ddd
	std::vector<double>&ratio_array</double>
Toshihiro Shimizu 890ddd
 ) {
Toshihiro Shimizu 890ddd
	const int size = ratio_array.size();
Toshihiro Shimizu 890ddd
	/* リニア配置をする */
Toshihiro Shimizu 890ddd
	for (int ii = 0; ii < size; ++ii) {
Toshihiro Shimizu 890ddd
		ratio_array.at(ii) = ((double)(size-ii))/(double)(size);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	/* カーブを設定(ガンマ計算) */
Toshihiro Shimizu 890ddd
	if (curve <= 0.0) {
Toshihiro Shimizu 890ddd
	 for (int ii = 1; ii < size; ++ii) { ratio_array.at(ii) = 0.0; }
Toshihiro Shimizu 890ddd
	} else
Toshihiro Shimizu 890ddd
	if (1.0 != curve) {
Toshihiro Shimizu 890ddd
	 for (int ii = 1; ii < size; ++ii) {
Toshihiro Shimizu 890ddd
		ratio_array.at(ii)=pow(ratio_array.at(ii),1.0/curve);
Toshihiro Shimizu 890ddd
	 }
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	/* 正規化 */
Toshihiro Shimizu 890ddd
	double accum = 0;
Toshihiro Shimizu 890ddd
	for (int ii = 0; ii < size; ++ii) { accum+=ratio_array.at(ii);}
Toshihiro Shimizu 890ddd
	for (int ii = 0; ii < size; ++ii) { ratio_array.at(ii)/=accum;}
Toshihiro Shimizu 890ddd
 }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
namespace {
Toshihiro Shimizu 890ddd
 void set_jaggy_(
Toshihiro Shimizu 890ddd
	const double x_vector,
Toshihiro Shimizu 890ddd
	const double y_vector,
Toshihiro Shimizu 890ddd
	const double vector_scale,
Toshihiro Shimizu 890ddd
	const double curve,
Toshihiro Shimizu 890ddd
	std::vector<double>&ratio_array,</double>
Toshihiro Shimizu 890ddd
	std::vector<int>&x_array,</int>
Toshihiro Shimizu 890ddd
	std::vector<int>&y_array</int>
Toshihiro Shimizu 890ddd
 ) {
Toshihiro Shimizu 890ddd
	if (curve <= 0.0) { return; } /* blur効果なしならなにもしない */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int xv = static_cast<int>(x_vector * vector_scale + 0.5);</int>
Toshihiro Shimizu 890ddd
	int yv = static_cast<int>(y_vector * vector_scale + 0.5);</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int size;
Toshihiro Shimizu 890ddd
	if (abs(xv) <= abs(yv))	{ size = abs(yv) + 1; }
Toshihiro Shimizu 890ddd
	else			{ size = abs(xv) + 1; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ratio_array.resize(size);
Toshihiro Shimizu 890ddd
	x_array.resize(size);
Toshihiro Shimizu 890ddd
	y_array.resize(size);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	set_ratio_( curve, ratio_array );
Toshihiro Shimizu 890ddd
	set_position_( xv, yv, x_array,y_array );
Toshihiro Shimizu 890ddd
 }
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
#endif  //------comment out----------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
#ifndef M_PI
Toshihiro Shimizu 890ddd
#define M_PI 3.14159265358979323846
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
void vec_poi_to_len_pos_(
Shinya Kitaoka 120a6e
    const double xv, const double yv, /* vector */
Shinya Kitaoka 120a6e
    const double xp, const double yp, /* point */
Shinya Kitaoka 120a6e
    double &len,                      /* vectorからpointまでの距離 */
Shinya Kitaoka 120a6e
    double &pos /* vector方向でvector原点からpointまでの距離 */
Shinya Kitaoka 120a6e
    ) {
Shinya Kitaoka 120a6e
  /*
Shinya Kitaoka 120a6e
   * ベクトルの角度を求める
Shinya Kitaoka 120a6e
   */
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double radian = 0.0;
Shinya Kitaoka 120a6e
  /* ゼロエラー */
Shinya Kitaoka 120a6e
  if ((0.0 == xv) && (0.0 == yv)) {
Shinya Kitaoka 120a6e
    len = 0.0;
Shinya Kitaoka 120a6e
    pos = 0.0;
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  /* 第1象限(0 <= degree < 90)*/
Shinya Kitaoka 120a6e
  else if ((0.0 < xv) && (0.0 <= yv)) {
Shinya Kitaoka 120a6e
    radian = atan(yv / xv);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  /* 第2象限(90 <= degree < 180) */
Shinya Kitaoka 120a6e
  else if ((xv <= 0.0) && (0.0 < yv)) {
Shinya Kitaoka 120a6e
    radian = atan(-xv / yv) + M_PI / 2.0;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  /* 第3象限(180 <= degree < 270) */
Shinya Kitaoka 120a6e
  else if ((xv < 0.0) && (yv <= 0.0)) {
Shinya Kitaoka 120a6e
    radian = atan(yv / xv) + M_PI;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  /* 第4象限(270 <= degree < 360(=0)) */
Shinya Kitaoka 120a6e
  else if ((0.0 <= xv) && (yv < 0.0)) {
Shinya Kitaoka 120a6e
    radian = atan(xv / -yv) + M_PI + M_PI / 2.0;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*
Shinya Kitaoka 120a6e
   * 逆回転し、ベクトルを+X軸上に置く
Shinya Kitaoka 120a6e
   */
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* ベクトルを逆回転し、x軸プラス上に置く */
Shinya Kitaoka 120a6e
  double xv_rot = xv * cos(-radian) - yv * sin(-radian);
Shinya Kitaoka 120a6e
  // double yv_rot = xv * sin(-radian) + yv * cos(-radian);
Shinya Kitaoka 120a6e
  /* ターゲット点も同様に逆回転する */
Shinya Kitaoka 120a6e
  double xp_rot = xp * cos(-radian) - yp * sin(-radian);
Shinya Kitaoka 120a6e
  double yp_rot = xp * sin(-radian) + yp * cos(-radian);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*
Shinya Kitaoka 120a6e
   * vectorからpointまでの距離
Shinya Kitaoka 120a6e
   */
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* マイナス(原点より小さい)の場合、ベクトル始点からの距離 */
Shinya Kitaoka 120a6e
  if (xp_rot < 0.0) {
Shinya Kitaoka 120a6e
    len = sqrt((xp * xp) + (yp * yp));
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  /* ベクトルより大きい場合、ベクトル終点からの距離 */
Shinya Kitaoka 120a6e
  else if (xv_rot < xp_rot) {
Shinya Kitaoka 120a6e
    len = sqrt((xp - xv) * (xp - xv) + (yp - yv) * (yp - yv));
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  /* ベクトルの横範囲内なら、上下位置が距離となる */
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    len = fabs(yp_rot);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*
Shinya Kitaoka 120a6e
   * vector方向でvector原点からpointまでの距離
Shinya Kitaoka 120a6e
   */
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  pos = xp_rot;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
/* ベクトルからの指定範囲でサブピクセルがどのくらい含むかカウントする
Shinya Kitaoka 120a6e
        ピクセルの位置は以下の図参照
Shinya Kitaoka 120a6e
          y
Shinya Kitaoka 120a6e
          ^
Shinya Kitaoka 120a6e
          |
Shinya Kitaoka 120a6e
          |
Shinya Kitaoka 120a6e
          |
Shinya Kitaoka 120a6e
          |
Shinya Kitaoka 120a6e
        +---+
Shinya Kitaoka 120a6e
        | | |
Shinya Kitaoka 120a6e
        | +-|-------------------> x
Shinya Kitaoka 120a6e
        |   |
Shinya Kitaoka 120a6e
        +---+
Toshihiro Shimizu 890ddd
 */
Toshihiro Shimizu 890ddd
int count_nearly_vector_(
Shinya Kitaoka 120a6e
    const double xv, const double yv, /* vector */
Shinya Kitaoka 120a6e
    const double x_tgt,
Shinya Kitaoka 120a6e
    const double y_tgt, /* 調査(vectorの原点からの)pixel位置 */
Shinya Kitaoka 120a6e
    const long x_div, const long y_div, /* 調査pixelを分割する(サブpixel)数 */
Shinya Kitaoka 120a6e
    const double valid_len              /* vectorからの有効距離 */
Shinya Kitaoka 120a6e
    ) {
Shinya Kitaoka 120a6e
  int count = 0;
Shinya Kitaoka 120a6e
  for (int yy = 0; yy < y_div; ++yy) {
Shinya Kitaoka 120a6e
    for (int xx = 0; xx < x_div; ++xx) {
Shinya Kitaoka 120a6e
      double xp  = x_tgt + (double)xx / x_div - (0.5 - 0.5 / x_div);
Shinya Kitaoka 120a6e
      double yp  = y_tgt + (double)yy / y_div - (0.5 - 0.5 / y_div);
Shinya Kitaoka 120a6e
      double len = 0.0;
Shinya Kitaoka 120a6e
      double pos = 0.0;
Shinya Kitaoka 120a6e
      vec_poi_to_len_pos_(xv, yv, xp, yp, len, pos);
Shinya Kitaoka 120a6e
      if (len < valid_len) {
Shinya Kitaoka 120a6e
        ++count;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return count;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/* リニア減衰計算 */
Toshihiro Shimizu 890ddd
double liner_decrement_(
Shinya Kitaoka 120a6e
    const double xv, const double yv, /* vector */
Shinya Kitaoka 120a6e
    const double x_tgt,
Shinya Kitaoka 120a6e
    const double y_tgt, /* 調査(vectorの原点からの)pixel位置 */
Shinya Kitaoka 120a6e
    const long x_div, const long y_div, /* 調査pixelを分割する(サブpixel)数 */
Shinya Kitaoka 120a6e
    const double valid_len              /* vectorからの有効距離 */
Shinya Kitaoka 120a6e
    ) {
Shinya Kitaoka 120a6e
  int count             = 0;
Shinya Kitaoka 120a6e
  double accum          = 0.0;
Shinya Kitaoka 120a6e
  const double line_len = sqrt(xv * xv + yv * yv) + valid_len;
Shinya Kitaoka 120a6e
  for (int yy = 0; yy < y_div; ++yy) {
Shinya Kitaoka 120a6e
    for (int xx = 0; xx < x_div; ++xx) {
Shinya Kitaoka 120a6e
      double xp  = x_tgt + (double)xx / x_div - (0.5 - 0.5 / x_div);
Shinya Kitaoka 120a6e
      double yp  = y_tgt + (double)yy / y_div - (0.5 - 0.5 / y_div);
Shinya Kitaoka 120a6e
      double len = 0.0;
Shinya Kitaoka 120a6e
      double pos = 0.0;
Shinya Kitaoka 120a6e
      vec_poi_to_len_pos_(xv, yv, xp, yp, len, pos);
Shinya Kitaoka 120a6e
      if (len < valid_len) {
Shinya Kitaoka 120a6e
        ++count;
Shinya Kitaoka 120a6e
        /* 下の式ではマイナスにはならない */
Shinya Kitaoka 120a6e
        accum += 1.0 - fabs(pos) / line_len;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (count <= 0) {
Shinya Kitaoka 120a6e
    return 0.0;
Shinya Kitaoka 120a6e
  } /* 念のためチェック */
Shinya Kitaoka 120a6e
  return accum / (double)count;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/* ぶれ画像計算 */
Toshihiro Shimizu 890ddd
double bure_decrement_(
Shinya Kitaoka 120a6e
    const double xv, const double yv, /* vector */
Shinya Kitaoka 120a6e
    const double x_tgt,
Shinya Kitaoka 120a6e
    const double y_tgt, /* 調査(vectorの原点からの)pixel位置 */
Shinya Kitaoka 120a6e
    const long x_div, const long y_div, /* 調査pixelを分割する(サブpixel)数 */
Shinya Kitaoka 120a6e
    const double valid_len,             /* vectorからの有効距離 */
Shinya Kitaoka 120a6e
    const int zanzo_length) {
Shinya Kitaoka 120a6e
  long count_in  = 0;
Shinya Kitaoka 120a6e
  long count_out = 0;
Shinya Kitaoka 120a6e
  double pos     = 0.0;
Shinya Kitaoka 120a6e
  for (int yy = 0; yy < y_div; ++yy) {
Shinya Kitaoka 120a6e
    for (int xx = 0; xx < x_div; ++xx) {
Shinya Kitaoka 120a6e
      double xp  = x_tgt + (double)xx / x_div - (0.5 - 0.5 / x_div);
Shinya Kitaoka 120a6e
      double yp  = y_tgt + (double)yy / y_div - (0.5 - 0.5 / y_div);
Shinya Kitaoka 120a6e
      double len = 0.0;
Shinya Kitaoka 120a6e
      pos        = 0.0;
Shinya Kitaoka 120a6e
      vec_poi_to_len_pos_(xv, yv, xp, yp, len, pos);
Shinya Kitaoka 120a6e
      if (len < valid_len) {
Shinya Kitaoka 120a6e
        if (0 == ((int)pos % zanzo_length)) {
Shinya Kitaoka 120a6e
          ++count_in;
Shinya Kitaoka 120a6e
        } else {
Shinya Kitaoka 120a6e
          ++count_out;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* 有効距離内にない場合ゼロを返す。念のためチェック */
Shinya Kitaoka 120a6e
  if ((count_in + count_out) <= 0) {
Shinya Kitaoka 120a6e
    return 0.0;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* 距離で計算するのでマイナス位置では意味がない */
Shinya Kitaoka 120a6e
  if (pos < 0.0) {
Shinya Kitaoka 120a6e
    pos = -pos;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*
Shinya Kitaoka 120a6e
          pos が line_len より大きい場合がある。
Shinya Kitaoka 120a6e
          そのため、pos / line_lenが、1より大きくなり、
Shinya Kitaoka 120a6e
          それゆえ、1.0 - pos / line_lenが、マイナスとなる。
Shinya Kitaoka 120a6e
          マイナスを返してはいけないのでそのための処理
Shinya Kitaoka 120a6e
  */
Shinya Kitaoka 120a6e
  const double line_len = sqrt(xv * xv + yv * yv) + valid_len;
Shinya Kitaoka 120a6e
  if (line_len < pos) {
Shinya Kitaoka 120a6e
    pos = line_len;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* ????????????????? */
Shinya Kitaoka 120a6e
  return (double)count_in / (count_in + count_out) * (1.0 - pos / line_len);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Shinya Kitaoka 120a6e
void set_smooth_(const double x_vector, const double y_vector,
Shinya Kitaoka 120a6e
                 const double vector_scale, const double curve,
Shinya Kitaoka 120a6e
                 const int zanzo_length, const double zanzo_power,
Shinya Kitaoka 120a6e
                 std::vector<double> &ratio_array, std::vector<int> &x_array,</int></double>
Shinya Kitaoka 120a6e
                 std::vector<int> &y_array) {</int>
Shinya Kitaoka 120a6e
  /* blur効果なしならなにもしない */
Shinya Kitaoka 120a6e
  if (curve <= 0.0) {
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* ベクトルの実の長さ */
Shinya Kitaoka 120a6e
  double xv = x_vector * vector_scale;
Shinya Kitaoka 120a6e
  double yv = y_vector * vector_scale;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* vectorの長さがゼロならなにもしない */
Shinya Kitaoka 120a6e
  if ((0.0 == xv) && (0.0 == yv)) {
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* vectorの始点と終点のpixel位置 */
Shinya Kitaoka 120a6e
  int x1, y1, x2, y2;
Shinya Kitaoka 120a6e
  if (0.0 <= xv) {
Shinya Kitaoka 120a6e
    x1 = 0;
Shinya Kitaoka 120a6e
    x2 = (int)xv + 2;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    x1 = (int)xv - 2;
Shinya Kitaoka 120a6e
    x2 = 0;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (0.0 <= yv) {
Shinya Kitaoka 120a6e
    y1 = 0;
Shinya Kitaoka 120a6e
    y2 = (int)yv + 2;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    y1 = (int)yv - 2;
Shinya Kitaoka 120a6e
    y2 = 0;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* smooth線にかかるsubpixel数をカウント */
Shinya Kitaoka 120a6e
  int size = 0;
Shinya Kitaoka 120a6e
  for (int yy = y1; yy <= y2; ++yy) {
Shinya Kitaoka 120a6e
    for (int xx = x1; xx <= x2; ++xx) {
Shinya Kitaoka 120a6e
      if (0 <
Shinya Kitaoka 120a6e
          count_nearly_vector_(xv, yv, (double)xx, (double)yy, 16, 16, 0.5)) {
Shinya Kitaoka 120a6e
        ++size;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* カウント0以下では、blur効果がない */
Shinya Kitaoka 120a6e
  if (size <= 0) {
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* バッファメモリ確保 */
Shinya Kitaoka 120a6e
  ratio_array.resize(size);
Shinya Kitaoka 120a6e
  x_array.resize(size);
Shinya Kitaoka 120a6e
  y_array.resize(size);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* 位置とピクセル値(0
Shinya Kitaoka 120a6e
  int ii = 0;
Shinya Kitaoka 120a6e
  for (int yy = y1; yy <= y2; ++yy) {
Shinya Kitaoka 120a6e
    for (int xx = x1; xx <= x2; ++xx) {
Shinya Kitaoka 120a6e
      const int count =
Shinya Kitaoka 120a6e
          count_nearly_vector_(xv, yv, (double)xx, (double)yy, 16, 16, 0.5);
Shinya Kitaoka 120a6e
      if (0 < count) {
Shinya Kitaoka 120a6e
        ratio_array.at(ii) = (double)count / (16 * 16);
Shinya Kitaoka 120a6e
        x_array.at(ii)     = xx;
Shinya Kitaoka 120a6e
        y_array.at(ii)     = yy;
Shinya Kitaoka 120a6e
        ++ii;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* リニア減衰効果 */
Shinya Kitaoka 120a6e
  for (unsigned int ii = 0; ii < ratio_array.size(); ++ii) {
Shinya Kitaoka 120a6e
    ratio_array.at(ii) *=
Shinya Kitaoka 120a6e
        liner_decrement_(xv, yv, (double)(x_array.at(ii)),
Shinya Kitaoka 120a6e
                         (double)(y_array.at(ii)), 16, 16, 0.5);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* 段々の分割指定があれば設定する */
Shinya Kitaoka 120a6e
  if (0 < zanzo_length) {
Shinya Kitaoka 120a6e
    /* ぶれ残像減衰効果 */
Shinya Kitaoka 120a6e
    for (unsigned int ii = 0; ii < ratio_array.size(); ++ii) {
Shinya Kitaoka 120a6e
      ratio_array.at(ii) =
Shinya Kitaoka 120a6e
          (1.0 - zanzo_power) * ratio_array.at(ii) +
Shinya Kitaoka 120a6e
          zanzo_power * bure_decrement_(xv, yv, (double)(x_array.at(ii)),
Shinya Kitaoka 120a6e
                                        (double)(y_array.at(ii)), 16, 16, 0.5,
Shinya Kitaoka 120a6e
                                        zanzo_length);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* vector始点は1とする */
Shinya Kitaoka 120a6e
  for (unsigned int ii = 0; ii < ratio_array.size(); ++ii) {
Shinya Kitaoka 120a6e
    if ((0 == x_array.at(ii)) && (0 == y_array.at(ii))) {
Shinya Kitaoka 120a6e
      ratio_array.at(ii) = 1.0;
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* ガンマ強弱計算 */
Shinya Kitaoka 120a6e
  if (1.0 != curve) { /* 0.0以下の値のとき既にreturnしてる */
Shinya Kitaoka 120a6e
    for (unsigned int ii = 0; ii < ratio_array.size(); ++ii) {
Shinya Kitaoka 120a6e
      ratio_array.at(ii) = pow(ratio_array.at(ii), 1.0 / curve);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  /* 正規化 */
Shinya Kitaoka 120a6e
  double d_accum = 0.0;
Shinya Kitaoka 120a6e
  for (unsigned int ii = 0; ii < ratio_array.size(); ++ii) {
Shinya Kitaoka 120a6e
    d_accum += ratio_array.at(ii);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  for (unsigned int ii = 0; ii < ratio_array.size(); ++ii) {
Shinya Kitaoka 120a6e
    ratio_array.at(ii) /= d_accum;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
T pixel_value(const T *image_array, const int height, const int width,
Shinya Kitaoka 120a6e
              const int channels, const int xx, const int yy, const int zz,
Shinya Kitaoka 120a6e
              const std::vector<double> &ratio_array,</double>
Shinya Kitaoka 120a6e
              const std::vector<int> &x_array,</int>
Shinya Kitaoka 120a6e
              const std::vector<int> &y_array) {</int>
Shinya Kitaoka 120a6e
  double ratio_accum = 0.0;
Shinya Kitaoka 120a6e
  double accum       = 0.0;
Shinya Kitaoka 120a6e
  for (unsigned int ii = 0; ii < ratio_array.size(); ++ii) {
Shinya Kitaoka 120a6e
    const int xp = xx + x_array.at(ii);
Shinya Kitaoka 120a6e
    const int yp = yy + y_array.at(ii);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (xp < 0) {
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (yp < 0) {
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (width <= xp) {
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (height <= yp) {
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    ratio_accum += ratio_array.at(ii);
Shinya Kitaoka 120a6e
    accum += ratio_array.at(ii) *
Shinya Kitaoka 120a6e
             static_cast<double>(</double>
Shinya Kitaoka 120a6e
                 *(image_array + channels * width * yp + channels * xp + zz));
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* can not calculate */
Shinya Kitaoka 120a6e
  if (0.0 == ratio_accum) {
Shinya Kitaoka 120a6e
    return 0;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* overflowはありえない(ratio_arrayを正規化してあるため) */
Shinya Kitaoka 120a6e
  /*if ((accum/ratio_accum) <= 0.0) { return 0; }
Shinya Kitaoka 120a6e
  if ((USHORT)0xffff <= (USHORT)(accum/ratio_accum)) {
Shinya Kitaoka 120a6e
          return (unsigned short)0xffff;
Shinya Kitaoka 120a6e
  }*/
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return static_cast<t>(accum / ratio_accum + 0.5);</t>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
void convert_template_(const T *in, T *image_out, const int hh, const int ww,
Shinya Kitaoka 120a6e
                       const int cc, const std::vector<double> &ra,</double>
Shinya Kitaoka 120a6e
                       const std::vector<int> &xa, const std::vector<int> &ya,</int></int>
Shinya Kitaoka 120a6e
                       const bool alpha_rend_sw) {
Shinya Kitaoka 120a6e
  /* 効果なしならimageをcopyして終る */
Shinya Kitaoka 120a6e
  if (ra.size() <= 0) {
Shinya Kitaoka 120a6e
    memmove(image_out, in, hh * ww * cc * sizeof(T));
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (igs::image::rgba::siz == cc) { /* Alphaがある */
Shinya Kitaoka 120a6e
    using namespace igs::image::rgba;
Shinya Kitaoka 120a6e
    if (alpha_rend_sw) { /* Alphaも処理する */
Shinya Kitaoka 120a6e
      const T *p_in = in;
Shinya Kitaoka 120a6e
      T *pout       = image_out;
Shinya Kitaoka 120a6e
      for (int yy = 0; yy < hh; ++yy) {
Shinya Kitaoka 120a6e
        for (int xx = 0; xx < ww; ++xx, p_in += cc, pout += cc) {
Shinya Kitaoka 120a6e
          /*Alpha処理-->*/ pout[alp] =
Shinya Kitaoka 120a6e
              pixel_value(in, hh, ww, cc, xx, yy, alp, ra, xa, ya);
Shinya Kitaoka 120a6e
          if (0 == pout[alp]) { /* AlphaがゼロならRGB処理しない */
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
          } else { /* AlphaがゼロでないときRGB処理する */
Shinya Kitaoka 120a6e
            pout[red] = pixel_value(in, hh, ww, cc, xx, yy, red, ra, xa, ya);
Shinya Kitaoka 120a6e
            pout[gre] = pixel_value(in, hh, ww, cc, xx, yy, gre, ra, xa, ya);
Shinya Kitaoka 120a6e
            pout[blu] = pixel_value(in, hh, ww, cc, xx, yy, blu, ra, xa, ya);
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else { /* Alpha処理せず保存のみ */
Shinya Kitaoka 120a6e
      const T *p_in              = in;
Shinya Kitaoka 120a6e
      T *pout                    = image_out;
Shinya Kitaoka 120a6e
      const unsigned int val_max = std::numeric_limits<t>::max();</t>
Shinya Kitaoka 120a6e
      for (int yy = 0; yy < hh; ++yy) {
Shinya Kitaoka 120a6e
        for (int xx = 0; xx < ww; ++xx, p_in += cc, pout += cc) {
Shinya Kitaoka 120a6e
          /*Alpha保存-->*/ pout[alp] = p_in[alp];
Shinya Kitaoka 120a6e
          if (0 == pout[alp]) { /* AlphaがゼロならRGB処理しない */
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
          } else { /* AlphaがゼロでないときRGB処理する */
Shinya Kitaoka 120a6e
            pout[red] = pixel_value(in, hh, ww, cc, xx, yy, red, ra, xa, ya);
Shinya Kitaoka 120a6e
            pout[gre] = pixel_value(in, hh, ww, cc, xx, yy, gre, ra, xa, ya);
Shinya Kitaoka 120a6e
            pout[blu] = pixel_value(in, hh, ww, cc, xx, yy, blu, ra, xa, ya);
Shinya Kitaoka 120a6e
            /* Alphaが0より大きくMaxより小さいとき増分をMaskする */
Shinya Kitaoka 120a6e
            if (p_in[alp] < val_max) {
Shinya Kitaoka 120a6e
              const unsigned int aa = static_cast<unsigned int="">(p_in[alp]);</unsigned>
Shinya Kitaoka 120a6e
              if (p_in[red] < pout[red]) { /* 増分のみMask! */
Shinya Kitaoka 120a6e
                const unsigned int dif =
Shinya Kitaoka 120a6e
                    static_cast<unsigned int="">(pout[red] - p_in[red]);</unsigned>
Shinya Kitaoka 120a6e
                pout[red] = static_cast<t>(p_in[red] + dif * aa / val_max);</t>
Shinya Kitaoka 120a6e
              }
Shinya Kitaoka 120a6e
              if (p_in[gre] < pout[gre]) { /* 増分のみMask! */
Shinya Kitaoka 120a6e
                const unsigned int dif =
Shinya Kitaoka 120a6e
                    static_cast<unsigned int="">(pout[gre] - p_in[gre]);</unsigned>
Shinya Kitaoka 120a6e
                pout[gre] = static_cast<t>(p_in[gre] + dif * aa / val_max);</t>
Shinya Kitaoka 120a6e
              }
Shinya Kitaoka 120a6e
              if (p_in[blu] < pout[blu]) { /* 増分のみMask! */
Shinya Kitaoka 120a6e
                const unsigned int dif =
Shinya Kitaoka 120a6e
                    static_cast<unsigned int="">(pout[blu] - p_in[blu]);</unsigned>
Shinya Kitaoka 120a6e
                pout[blu] = static_cast<t>(p_in[blu] + dif * aa / val_max);</t>
Shinya Kitaoka 120a6e
              }
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else { /* Alphaがない, RGB/Grayscale... */
Shinya Kitaoka 120a6e
    T *pout = image_out;
Shinya Kitaoka 120a6e
    for (int yy = 0; yy < hh; ++yy) {
Shinya Kitaoka 120a6e
      for (int xx = 0; xx < ww; ++xx, pout += cc) {
Shinya Kitaoka 120a6e
        for (int zz = 0; zz < cc; ++zz) {
Shinya Kitaoka 120a6e
          pout[zz] = pixel_value(in, hh, ww, cc, xx, yy, zz, ra, xa, ya);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
void igs::motion_blur::convert(const unsigned char *image_in,
Shinya Kitaoka 120a6e
                               unsigned char *image_out,
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
                               const int height, const int width,
Shinya Kitaoka 120a6e
                               const int channels, const int bits,
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
                               const double x_vector, const double y_vector,
Shinya Kitaoka 120a6e
                               const double vector_scale, const double curve,
Shinya Kitaoka 120a6e
                               const int zanzo_length, const double zanzo_power,
Shinya Kitaoka 120a6e
                               const bool alpha_rend_sw) {
Shinya Kitaoka 120a6e
  std::vector<double> ratio_array;</double>
Shinya Kitaoka 120a6e
  std::vector<int> x_array;</int>
Shinya Kitaoka 120a6e
  std::vector<int> y_array;</int>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  set_smooth_(x_vector, y_vector, vector_scale, curve, zanzo_length,
Shinya Kitaoka 120a6e
              zanzo_power, ratio_array, x_array, y_array);
Shinya Kitaoka 120a6e
  /***set_jaggy_(
Shinya Kitaoka 120a6e
          x_vector, y_vector, vector_scale, curve,
Shinya Kitaoka 120a6e
          ratio_array, x_array, y_array
Shinya Kitaoka 120a6e
  );***/
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (std::numeric_limits<unsigned char="">::digits == bits) {</unsigned>
Shinya Kitaoka 120a6e
    convert_template_(image_in, image_out, height, width, channels, ratio_array,
Shinya Kitaoka 120a6e
                      x_array, y_array, alpha_rend_sw);
Shinya Kitaoka 120a6e
    y_array.clear();
Shinya Kitaoka 120a6e
    x_array.clear();
Shinya Kitaoka 120a6e
    ratio_array.clear();
Shinya Kitaoka 120a6e
  } else if (std::numeric_limits<unsigned short="">::digits == bits) {</unsigned>
Shinya Kitaoka 120a6e
    convert_template_(reinterpret_cast<const *="" short="" unsigned="">(image_in),</const>
Shinya Kitaoka 120a6e
                      reinterpret_cast<unsigned *="" short="">(image_out), height,</unsigned>
Shinya Kitaoka 120a6e
                      width, channels, ratio_array, x_array, y_array,
Shinya Kitaoka 120a6e
                      alpha_rend_sw);
Shinya Kitaoka 120a6e
    y_array.clear();
Shinya Kitaoka 120a6e
    x_array.clear();
Shinya Kitaoka 120a6e
    ratio_array.clear();
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    throw std::domain_error("Bad bits,Not uchar/ushort");
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}