#include #include /* std::domain_error(-) */ #include "igs_motion_wind_pixel.h" namespace { template const T *ref_pixel_(const T *ref, const int hh, const int ww, const int cc, int xx, int yy) { while (xx < 0) { xx += ww; } while (ww <= xx) { xx -= ww; } while (yy < 0) { yy += hh; } while (hh <= yy) { yy -= hh; } return ref + cc * ww * yy + cc * xx; } template void pixel_pop_(const T *in, const double div_val, const int cc, double *out) { /* 正規化し取り出し */ for (int zz = 0; zz < cc; ++zz) { out[zz] = static_cast(in[zz]) / div_val; } } template void pixel_push_(const double *in, const double mul_val, const int cc, T *out) { /* 値が変化したら格納する */ for (int zz = 0; zz < cc; ++zz) { out[zz] = static_cast(in[zz] * mul_val); } } //----------------------------------------------------------- template void change_template_vert_( T *in, const int ww, const int hh, const int cc, const R *ref, const int rw, const int rh, const int rc //, const int rz , const int ref_mode /* 0=R,1=G,2=B,3=A,4=Luminance,5=Nothing */ , igs::motion_wind::pixel &pix_rend, const bool reverse_sw) { const unsigned int max_val = std::numeric_limits::max(); const double div_val = static_cast(max_val); const double mul_val = div_val + 0.999999; const unsigned int ref_max_val = std::numeric_limits::max(); const double ref_div_val = static_cast(ref_max_val); const int refprev = (reverse_sw) ? 1 : -1; for (int xx = 0; xx < ww; ++xx) { for (int yy = 0; yy < hh; ++yy) { T *next = in; if (reverse_sw) { /* 上から */ next += (hh - 1 - yy) * ww * cc + xx * cc; } else { /* 下から */ next += yy * ww * cc + xx * cc; } double pixel_in[igs::image::rgba::siz]; pixel_pop_(next, div_val, cc, pixel_in); /****double pixel_ref[igs::image::rgba::siz]; double *rp_p = 0; if (0 != ref) { pixel_pop_( ref_pixel_(ref,rh,rw,rc,xx,yy+refprev) , ref_div_val, rc, pixel_ref); rp_p = pixel_ref; } if (pix_rend.change(xx <= 0, rz, rp_p, cc, pixel_in)) { pixel_push_(pixel_in,mul_val,cc,next); } ***/ double ref_val = -1.0; if (0 != ref && 0 <= ref_mode && ref_mode <= 4) { ref_val = igs::color::ref_value(ref_pixel_(ref, rh, rw, rc, xx, yy + refprev), rc, ref_max_val, ref_mode); } if (pix_rend.change(xx <= 0, ref_val, cc, pixel_in)) { pixel_push_(pixel_in, mul_val, cc, next); } } } } template void change_template_hori_( T *in, const int ww, const int hh, const int cc, const R *ref, const int rw, const int rh, const int rc //, const int rz , const int ref_mode /* 0=R,1=G,2=B,3=A,4=Luminance,5=Nothing */ , igs::motion_wind::pixel &pix_rend, const bool reverse_sw) { const unsigned int max_val = std::numeric_limits::max(); const double div_val = static_cast(max_val); const double mul_val = div_val + 0.999999; const unsigned int ref_max_val = std::numeric_limits::max(); const double ref_div_val = static_cast(ref_max_val); const int refprev = (reverse_sw) ? 1 : -1; for (int yy = 0; yy < hh; ++yy) { T *next = in; /* 左から */ if (reverse_sw) { next += (ww - 1) * cc; } /* 右から */ for (int xx = 0; xx < ww; ++xx) { double pixel_in[igs::image::rgba::siz]; pixel_pop_(next, div_val, cc, pixel_in); /***double pixel_ref[igs::image::rgba::siz]; double *rp_p = 0; if (0 != ref) { pixel_pop_( ref_pixel_(ref,rh,rw,rc,xx+refprev,yy) , ref_div_val, rc, pixel_ref); rp_p = pixel_ref; } if (pix_rend.change(xx <= 0, rz, rp_p, cc, pixel_in)) { pixel_push_(pixel_in,mul_val,cc,next); }***/ double ref_val = -1.0; if (0 != ref && 0 <= ref_mode && ref_mode <= 4) { ref_val = igs::color::ref_value(ref_pixel_(ref, rh, rw, rc, xx, yy + refprev), rc, ref_max_val, ref_mode); } if (pix_rend.change(xx <= 0, ref_val, cc, pixel_in)) { pixel_push_(pixel_in, mul_val, cc, next); } if (reverse_sw) { next -= cc; } /* 右から左 */ else { next += cc; } /* 左から右 */ } in += ww * cc; /* 下から上 */ } } } /*------------------------------------------------------- Parameter 方向 left-bottom is origin. 0 : 0 : left to right 1 : 90 : bottom to top 2 : 180 : right to left 3 : 270 : top to bottom 暗い風へ変更するスイッチ true : blow dark false : blow light アルファにも風吹くスイッチ true : blow alpha false : not blow alpha 風長さ(ランダム初期種) 1(0...) 風長さ(最小値) 0(0...) 風長さ(最大値) 18(0...) 風長さ(最大最小のかたより値) 0.0(-1.0...0.0...1.0) 風長さ(参照スイッチ) false(true/false) 風曲線(ランダム初期種) 1(0...) 風曲線(最小値) 0(0...) 風曲線(最大値) 1(0...) 風曲線(最大最小のかたより値) 0.0(-1.0...0.0...1.0) 風曲線(参照スイッチ) false(true/false) 風高さ(ランダム初期種) 1(0...) 風高さ(最小値) 0(0...) 風高さ(最大値) 1(0...) 風高さ(最大最小のかたより値) 0.0(-1.0...0.0...1.0) 風高さ(参照スイッチ) false(true/false) -------------------------------------------------------*/ #include "igs_motion_wind.h" void igs::motion_wind::change( unsigned char *in , const int hh, const int ww, const int cc, const int bb , const unsigned char *ref , const int rh, const int rw, const int rc, const int rb //, const int rz , const int ref_mode /* 0=R,1=G,2=B,3=A,4=Luminance,5=Nothing */ , const int direction // 0(0(LtoR),1(BtoT),2(RtoL),3(TtoB)) , const bool blow_dark_sw // false(false,true) , const bool blow_alpha_sw // true(false,true) , const unsigned long length_random_seed // 0(0...) , const double length_min // 0.0... , const double length_max // 18.0... , const double length_bias // 1.0(0.0<...1.0...) , const bool length_ref_sw // false(false,true) , const unsigned long force_random_seed // 0(0...) , const double force_min // 0.0... , const double force_max // 1.0... , const double force_bias // 1.0(0.0<...1.0...) , const bool force_ref_sw // false(false,true) , const unsigned long density_random_seed // 0(0...) , const double density_min // 0.0... , const double density_max // 1.0... , const double density_bias // 1.0(0.0<...1.0...) , const bool density_ref_sw // false(false,true) ) { /* ユーザーによるノーアクションの指定、つまりゼロ長 の時は処理せず終る */ if ((length_max <= 0.0) && (length_min <= 0.0)) { return; } //------------ igs::motion_wind::pixel pix_rend( blow_dark_sw, blow_alpha_sw, length_random_seed, length_min, length_max, length_bias, length_ref_sw, force_random_seed, force_min, force_max, force_bias, force_ref_sw, density_random_seed, density_min, density_max, density_bias, density_ref_sw); //------------ const int bi = static_cast(bb); const int refbi = static_cast(rb); if (std::numeric_limits::digits == bi) { if (std::numeric_limits::digits == refbi) { if ((0 == direction) || (2 == direction)) { change_template_hori_( in, ww, hh, cc, reinterpret_cast(ref), rw, rh, rc //,rz , ref_mode, pix_rend, (0 == direction) ? false : true); } else if ((1 == direction) || (3 == direction)) { change_template_vert_( in, ww, hh, cc, reinterpret_cast(ref), rw, rh, rc //,rz , ref_mode, pix_rend, (1 == direction) ? false : true); } } else { /* refbi is 8(uchar) or other(0...) */ if ((0 == direction) || (2 == direction)) { change_template_hori_(in, ww, hh, cc, ref, rw, rh, rc //,rz , ref_mode, pix_rend, (0 == direction) ? false : true); } else if ((1 == direction) || (3 == direction)) { change_template_vert_(in, ww, hh, cc, ref, rw, rh, rc //,rz , ref_mode, pix_rend, (1 == direction) ? false : true); } } } else if (std::numeric_limits::digits == bi) { if (std::numeric_limits::digits == refbi) { if ((0 == direction) || (2 == direction)) { change_template_hori_( reinterpret_cast(in), ww, hh, cc, reinterpret_cast(ref), rw, rh, rc //,rz , ref_mode, pix_rend, (0 == direction) ? false : true); } else if ((1 == direction) || (3 == direction)) { change_template_vert_( reinterpret_cast(in), ww, hh, cc, reinterpret_cast(ref), rw, rh, rc //,rz , ref_mode, pix_rend, (1 == direction) ? false : true); } } else { /* refbi is 8(uchar) or other(0...) */ if ((0 == direction) || (2 == direction)) { change_template_hori_( reinterpret_cast(in), ww, hh, cc, ref, rw, rh, rc //,rz , ref_mode, pix_rend, (0 == direction) ? false : true); } else if ((1 == direction) || (3 == direction)) { change_template_vert_( reinterpret_cast(in), ww, hh, cc, ref, rw, rh, rc //,rz , ref_mode, pix_rend, (1 == direction) ? false : true); } } } else { throw std::domain_error("Bad bits,Not uchar/ushort"); } pix_rend.clear(); }