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