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