| |
| #include "igs_motion_wind_table.h" |
| #include "igs_motion_wind_pixel.h" |
| |
| igs::motion_wind::pixel::pixel( |
| const bool blow_dark_sw, const bool blow_alpha_sw |
| |
| , |
| const unsigned long length_random_seed, const double length_min, const double length_max, const double length_bias, const bool length_ref_sw |
| |
| , |
| const unsigned long force_random_seed, const double force_min, const double force_max, const double force_bias, const bool force_ref_sw |
| |
| , |
| const unsigned long density_random_seed, const double density_min, const double density_max, const double density_bias, const bool density_ref_sw) |
| : blow_dark_sw_(blow_dark_sw), blow_alpha_sw_(blow_alpha_sw) |
| |
| , |
| length_min_(length_min), length_max_(length_max), length_bias_(length_bias), length_ref_sw_(length_ref_sw) |
| |
| , |
| force_min_(force_min), force_max_(force_max), force_bias_(force_bias), force_ref_sw_(force_ref_sw) |
| |
| , |
| density_min_(density_min), density_max_(density_max), density_bias_(density_bias), density_ref_sw_(density_ref_sw) |
| |
| , |
| key_lightness_(0), table_len_(0), table_pos_(0), table_array_(0) |
| { |
| this->table_.resize( |
| igs::motion_wind::table_size(length_min, length_max)); |
| this->length_random_.seed(length_random_seed); |
| this->force_random_.seed(force_random_seed); |
| this->density_random_.seed(density_random_seed); |
| } |
| void igs::motion_wind::pixel::clear(void) |
| { |
| this->table_.clear(); |
| } |
| |
| namespace |
| { |
| void wind_rgba_( |
| const double key, const double alp, const double ratio, bool &sw, double &tgt) |
| { |
| if (tgt < key) { |
| tgt += ratio * (key - tgt) * alp; |
| tgt = (tgt < 0.0) ? 0.0 : ((1.0 < tgt) ? 1.0 : tgt); |
| sw = true; |
| } |
| } |
| void wind_rgb_( |
| const double key, const double ratio, bool &sw, double &tgt) |
| { |
| if (tgt < key) { |
| |
| tgt += ratio * (key - tgt); |
| |
| tgt = (tgt < 0.0) ? 0.0 : ((1.0 < tgt) ? 1.0 : tgt); |
| sw = true; |
| } |
| } |
| void wind_a_( |
| const double key |
| , |
| const double ratio, const bool sw, double &tgt |
| ) |
| { |
| if ((tgt < key) || sw) { |
| double val = tgt + (ratio * (key - tgt)); |
| if (tgt < val) { |
| tgt = val; |
| tgt = (tgt < 0.0) ? 0.0 : ((1.0 < tgt) ? 1.0 : tgt); |
| } |
| } |
| } |
| |
| void blow_wind_( |
| const int channels, const double *key, const double *tbl_a, const int tbl_p, const bool blow_alpha_sw, double *tgt) |
| { |
| bool sw = false; |
| |
| if (igs::image::rgba::siz == channels) { |
| using namespace igs::image::rgba; |
| if (blow_alpha_sw) { |
| |
| wind_rgb_(key[red], tbl_a[tbl_p], sw, tgt[red]); |
| wind_rgb_(key[gre], tbl_a[tbl_p], sw, tgt[gre]); |
| wind_rgb_(key[blu], tbl_a[tbl_p], sw, tgt[blu]); |
| |
| |
| wind_a_(key[alp], tbl_a[tbl_p], sw, tgt[alp]); |
| } else { |
| wind_rgba_(key[red], tgt[alp], tbl_a[tbl_p], sw, tgt[red]); |
| wind_rgba_(key[gre], tgt[alp], tbl_a[tbl_p], sw, tgt[gre]); |
| wind_rgba_(key[blu], tgt[alp], tbl_a[tbl_p], sw, tgt[blu]); |
| } |
| } else { |
| for (int zz = 0; zz < channels; ++zz) { |
| wind_rgb_(key[zz], tbl_a[tbl_p], sw, tgt[zz]); |
| } |
| } |
| } |
| void invert_pixel_( |
| const int channels, double *pixel) |
| { |
| if (igs::image::rgba::siz == channels) { |
| using namespace igs::image::rgba; |
| pixel[red] = (1.0 - pixel[red]) * pixel[alp]; |
| pixel[gre] = (1.0 - pixel[gre]) * pixel[alp]; |
| pixel[blu] = (1.0 - pixel[blu]) * pixel[alp]; |
| } else |
| if (igs::image::rgb::siz == channels) { |
| using namespace igs::image::rgb; |
| pixel[red] = 1.0 - pixel[red]; |
| pixel[gre] = 1.0 - pixel[gre]; |
| pixel[blu] = 1.0 - pixel[blu]; |
| } else { |
| for (int zz = 0; zz < channels; ++zz) { |
| pixel[zz] = 1.0 - pixel[zz]; |
| } |
| } |
| } |
| void rgb_to_lightness_( |
| const double re, const double gr, const double bl, double &li) |
| { |
| li = ((re < gr) ? ((gr < bl) ? bl : gr) : ((re < bl) ? bl : re) + |
| (gr < re) |
| ? ((bl < gr) ? bl : gr) |
| : ((bl < re) ? bl : re)) / |
| 2.0; |
| } |
| double get_lightness_( |
| const int channels, const double *pixel |
| |
| ) |
| { |
| double lightness; |
| |
| if (igs::image::rgba::siz == channels) { |
| using namespace igs::image::rgba; |
| rgb_to_lightness_( |
| pixel[red], pixel[gre], pixel[blu], lightness); |
| } else if (igs::image::rgb::siz == channels) { |
| using namespace igs::image::rgb; |
| rgb_to_lightness_( |
| pixel[red], pixel[gre], pixel[blu], lightness); |
| } else { |
| lightness = pixel[0]; |
| } |
| |
| |
| return lightness; |
| } |
| } |
| |
| int igs::motion_wind::pixel::change( |
| const bool key_reset_sw |
| |
| |
| |
| |
| , |
| const double ref_val |
| , |
| const int channels, double *pixel_tgt) |
| { |
| |
| |
| if (this->blow_dark_sw_) { |
| invert_pixel_(channels, pixel_tgt); |
| } |
| |
| |
| const double crnt_lightness = get_lightness_( |
| channels, pixel_tgt |
| ); |
| |
| |
| if (key_reset_sw) { |
| this->key_lightness_ = crnt_lightness; |
| for (int ii = 0; ii < channels; ++ii) { |
| this->pixel_key_[ii] = pixel_tgt[ii]; |
| } |
| } |
| |
| |
| if (crnt_lightness < this->key_lightness_) { |
| |
| |
| if (0 == this->table_array_) { |
| double length_min = this->length_min_; |
| double length_max = this->length_max_; |
| double length_bias = this->length_bias_; |
| double force_min = this->force_min_; |
| double force_max = this->force_max_; |
| double force_bias = this->force_bias_; |
| double density_min = this->density_min_; |
| double density_max = this->density_max_; |
| double density_bias = this->density_bias_; |
| #if 0 |
| double ref_value; |
| |
| if (0 != ref_pixel) { |
| ref_value = ref_pixel[ref_channel]; |
| } else { |
| ref_value = get_lightness_( |
| channels, pixel_tgt); |
| } |
| #endif |
| double ref_value = ref_val; |
| |
| if (ref_value < 0.0) { |
| ref_value = get_lightness_( |
| channels, pixel_tgt); |
| } |
| |
| if (this->length_ref_sw_) { |
| length_min *= ref_value; |
| length_max *= ref_value; |
| } |
| if (this->force_ref_sw_) { |
| force_min *= ref_value; |
| force_max *= ref_value; |
| } |
| if (this->density_ref_sw_) { |
| density_min *= ref_value; |
| density_max *= ref_value; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| this->table_len_ = igs::motion_wind::make_table( |
| this->table_, this->length_random_, this->force_random_, this->density_random_, length_min, length_max, length_bias, force_min, force_max, force_bias, density_min, density_max, density_bias); |
| this->table_array_ = &this->table_.at(0); |
| this->table_pos_ = 1; |
| |
| |
| |
| |
| |
| |
| } |
| |
| |
| if (this->table_pos_ < this->table_len_) { |
| |
| blow_wind_( |
| channels, this->pixel_key_, this->table_array_, this->table_pos_, this->blow_alpha_sw_, pixel_tgt); |
| ++this->table_pos_; |
| |
| |
| if (this->blow_dark_sw_) { |
| invert_pixel_(channels, pixel_tgt); |
| } |
| |
| return true; |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| this->key_lightness_ = crnt_lightness; |
| for (int ii = 0L; ii < channels; ++ii) { |
| this->pixel_key_[ii] = pixel_tgt[ii]; |
| } |
| |
| |
| this->table_array_ = 0; |
| |
| return false; |
| } |