Toshihiro Shimizu 890ddd
#include <string></string>
Toshihiro Shimizu 890ddd
#include <vector></vector>
Toshihiro Shimizu 890ddd
#include <stdexcept></stdexcept>
Toshihiro Shimizu 890ddd
#include <fstream></fstream>
Toshihiro Shimizu 890ddd
#include <limits></limits>
Toshihiro Shimizu 890ddd
#include <cmath></cmath>
Toshihiro Shimizu 890ddd
#include "igs_ifx_common.h" /* igs::image::rgba */
Toshihiro Shimizu 890ddd
#include "igs_gaussian_blur.h"
Toshihiro Shimizu 890ddd
#include "igs_gauss_distribution.cpp"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Shinya Kitaoka 120a6e
const int diameter_from_radius_(const int radius) {
Shinya Kitaoka 120a6e
  /* テーブルの半径サイズ(=中心位置)からテーブルの大きさを決める */
Shinya Kitaoka 120a6e
  return radius * 2 + 1;
Toshihiro Shimizu 890ddd
}
shun-iwasawa 481b59
#if 0
Toshihiro Shimizu 890ddd
template <class rt=""></class>
Toshihiro Shimizu 890ddd
void blur_1st_hori_(
Shinya Kitaoka 120a6e
    const double **in_plane_with_margin  // &(std::vector<double *="">).at(0)</double>
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int height_with_margin, const int width_with_margin,
Shinya Kitaoka 120a6e
    double *brush_sequence  // &(std::vector<double *="">).at(0)</double>
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int int_radius,
Shinya Kitaoka 120a6e
    double **out_plane_with_margin  // &(std::vector<double *="">).at(0)</double>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* 参照画像用情報(no margin) */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const RT *ref /* 求める画像(out)と同じ高さ、幅、チャンネル数 */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int ref_mode /* 0=R,1=G,2=B,3=A,4=Luminance,5=Nothing */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int ref_channels, const double real_radius, const double sigma) {
Shinya Kitaoka 120a6e
  const int brush_diameter  = diameter_from_radius_(int_radius);
Shinya Kitaoka 120a6e
  const int width_no_margin = width_with_margin - int_radius * 2;
Shinya Kitaoka 120a6e
  const int r_max           = std::numeric_limits<rt>::max();</rt>
Shinya Kitaoka 120a6e
  const RT *ref_vert        = ref;
Shinya Kitaoka 120a6e
  const RT *ref_hori        = ref;
Shinya Kitaoka 120a6e
  double before_real_radius = -1.0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* 縦方向 */
Shinya Kitaoka 120a6e
  for (int yo = 0; yo < height_with_margin; ++yo) {
Shinya Kitaoka 120a6e
    if (ref != 0) {
Shinya Kitaoka 120a6e
      if (int_radius < yo && yo < (height_with_margin - int_radius)) {
Shinya Kitaoka 120a6e
        ref_vert += width_no_margin * ref_channels;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      ref_hori = ref_vert;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* 横方向 */
Shinya Kitaoka 120a6e
    for (int xx = 0, xo = int_radius; xx < width_no_margin; ++xx, ++xo) {
Shinya Kitaoka 120a6e
      if (ref != 0) {
Shinya Kitaoka 120a6e
        const double read_r =
Shinya Kitaoka 120a6e
            real_radius *
Shinya Kitaoka 120a6e
            igs::color::ref_value(ref_hori, ref_channels, r_max, ref_mode);
Shinya Kitaoka 120a6e
        ref_hori += ref_channels;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (read_r != before_real_radius) {
Shinya Kitaoka 120a6e
          gauss_distribution_1d_(brush_sequence, brush_diameter,
Shinya Kitaoka 120a6e
                                 igs::gaussian_blur_hv::int_radius(read_r),
Shinya Kitaoka 120a6e
                                 read_r, sigma);
Shinya Kitaoka 120a6e
          before_real_radius = read_r;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      /* ガウス分布で横blur */
Shinya Kitaoka 120a6e
      double accum = 0;
Shinya Kitaoka 120a6e
      /*
Shinya Kitaoka 120a6e
for (int xb=0, xi=xx; xb
Shinya Kitaoka 120a6e
accum += in_plane_with_margin[yo][xi] * brush_sequence[xb];
Shinya Kitaoka 120a6e
}
Toshihiro Shimizu 890ddd
*/
Shinya Kitaoka 120a6e
      const double *bru_seq = brush_sequence;
Shinya Kitaoka 120a6e
      int bru_dia           = brush_diameter;
Shinya Kitaoka 120a6e
      const double *inn_pla = &in_plane_with_margin[yo][xx];
Shinya Kitaoka 120a6e
      while (0 < bru_dia--) {
Shinya Kitaoka 120a6e
        accum += (*inn_pla++) * (*bru_seq++);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      out_plane_with_margin[yo][xo] = accum;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
shun-iwasawa 481b59
#endif
shun-iwasawa 481b59
shun-iwasawa 481b59
void blur_1st_hori_(
shun-iwasawa 481b59
    const double** in_plane_with_margin  // &(std::vector<double *="">).at(0)</double>
shun-iwasawa 481b59
    ,
shun-iwasawa 481b59
    const int height_with_margin, const int width_with_margin,
shun-iwasawa 481b59
    double* brush_sequence  // &(std::vector<double *="">).at(0)</double>
shun-iwasawa 481b59
    ,
shun-iwasawa 481b59
    const int int_radius,
shun-iwasawa 481b59
    double** out_plane_with_margin  // &(std::vector<double *="">).at(0)</double>
shun-iwasawa 481b59
shun-iwasawa 481b59
    /* 参照画像用情報(no margin) */
shun-iwasawa 481b59
    ,
shun-iwasawa 481b59
    const float* ref /* 求める画像(out)と同じ高さ、幅、チャンネル数 */
shun-iwasawa 481b59
    ,
shun-iwasawa 481b59
    const double real_radius, const double sigma) {
shun-iwasawa 481b59
  const int brush_diameter  = diameter_from_radius_(int_radius);
shun-iwasawa 481b59
  const int width_no_margin = width_with_margin - int_radius * 2;
shun-iwasawa 481b59
  // const int r_max = std::numeric_limits<rt>::max();</rt>
shun-iwasawa 481b59
  const float* ref_vert     = ref;
shun-iwasawa 481b59
  const float* ref_hori     = ref;
shun-iwasawa 481b59
  double before_real_radius = -1.0;
shun-iwasawa 481b59
shun-iwasawa 481b59
  /* 縦方向 */
shun-iwasawa 481b59
  for (int yo = 0; yo < height_with_margin; ++yo) {
shun-iwasawa 481b59
    if (ref != nullptr) {
shun-iwasawa 481b59
      if (int_radius < yo && yo < (height_with_margin - int_radius)) {
shun-iwasawa 481b59
        ref_vert += width_no_margin;
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
      ref_hori = ref_vert;
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
shun-iwasawa 481b59
    /* 横方向 */
shun-iwasawa 481b59
    for (int xx = 0, xo = int_radius; xx < width_no_margin; ++xx, ++xo) {
shun-iwasawa 481b59
      if (ref != 0) {
shun-iwasawa 481b59
        const double read_r = real_radius * (*ref_hori);
shun-iwasawa 481b59
        ref_hori++;
shun-iwasawa 481b59
shun-iwasawa 481b59
        if (read_r != before_real_radius) {
shun-iwasawa 481b59
          gauss_distribution_1d_(brush_sequence, brush_diameter,
shun-iwasawa 481b59
                                 igs::gaussian_blur_hv::int_radius(read_r),
shun-iwasawa 481b59
                                 read_r, sigma);
shun-iwasawa 481b59
          before_real_radius = read_r;
shun-iwasawa 481b59
        }
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
      /* ガウス分布で横blur */
shun-iwasawa 481b59
      double accum = 0;
shun-iwasawa 481b59
shun-iwasawa 481b59
      const double* bru_seq = brush_sequence;
shun-iwasawa 481b59
      int bru_dia           = brush_diameter;
shun-iwasawa 481b59
      const double* inn_pla = &in_plane_with_margin[yo][xx];
shun-iwasawa 481b59
      while (0 < bru_dia--) {
shun-iwasawa 481b59
        accum += (*inn_pla++) * (*bru_seq++);
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
      out_plane_with_margin[yo][xo] = accum;
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
}
shun-iwasawa 481b59
shun-iwasawa 481b59
#if 0
Toshihiro Shimizu 890ddd
template <class rt=""></class>
Toshihiro Shimizu 890ddd
void blur_2nd_vert_(
Shinya Kitaoka 120a6e
    const double **in_plane_with_margin  // &(std::vector<double *="">).at(0)</double>
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int height_with_margin, const int width_with_margin,
Shinya Kitaoka 120a6e
    double *brush_sequence  // &(std::vector<double *="">).at(0)</double>
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int int_radius,
Shinya Kitaoka 120a6e
    double **out_plane_with_margin  // &(std::vector<double *="">).at(0)</double>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* 参照画像用情報(no margin) */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const RT *ref /* 求める画像(out)と同じ高さ、幅、チャンネル数 */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int ref_mode /* 0=R,1=G,2=B,3=A,4=Luminance,5=Nothing */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int ref_channels, const double real_radius, const double sigma) {
Shinya Kitaoka 120a6e
  const int brush_diameter   = diameter_from_radius_(int_radius);
Shinya Kitaoka 120a6e
  const int height_no_margin = height_with_margin - int_radius * 2;
Shinya Kitaoka 120a6e
  const int width_no_margin  = width_with_margin - int_radius * 2;
Shinya Kitaoka 120a6e
  const int r_max            = std::numeric_limits<rt>::max();</rt>
Shinya Kitaoka 120a6e
  const RT *ref_vert         = ref;
Shinya Kitaoka 120a6e
  const RT *ref_hori         = ref;
Shinya Kitaoka 120a6e
  double before_real_radius  = -1.0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* 左右マージン部分はもう処理しなくていい */
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* 横方向 */
Shinya Kitaoka 120a6e
  for (int xx = 0, xo = int_radius; xx < width_no_margin; ++xx, ++xo) {
Shinya Kitaoka 120a6e
    if (ref != 0) {
Shinya Kitaoka 120a6e
      ref_hori += ref_channels;
Shinya Kitaoka 120a6e
      ref_vert = ref_hori;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /* 縦方向 */
Shinya Kitaoka 120a6e
    for (int yy = 0, yo = int_radius; yy < height_no_margin; ++yy, ++yo) {
Shinya Kitaoka 120a6e
      if (ref != 0) {
Shinya Kitaoka 120a6e
        const double read_r =
Shinya Kitaoka 120a6e
            real_radius *
Shinya Kitaoka 120a6e
            igs::color::ref_value(ref_vert, ref_channels, r_max, ref_mode);
Shinya Kitaoka 120a6e
        ref_vert += width_no_margin * ref_channels;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (read_r != before_real_radius) {
Shinya Kitaoka 120a6e
          gauss_distribution_1d_(brush_sequence, brush_diameter,
Shinya Kitaoka 120a6e
                                 igs::gaussian_blur_hv::int_radius(read_r),
Shinya Kitaoka 120a6e
                                 read_r, sigma);
Shinya Kitaoka 120a6e
          before_real_radius = read_r;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      /* ガウス分布で横blur */
Shinya Kitaoka 120a6e
      double accum = 0;
Shinya Kitaoka 120a6e
      /*
Shinya Kitaoka 120a6e
for (int yb=0,yi=yy; yb
Shinya Kitaoka 120a6e
accum += in_plane_with_margin[yi][xo] * brush_sequence[yb];
Shinya Kitaoka 120a6e
}
Toshihiro Shimizu 890ddd
*/
Shinya Kitaoka 120a6e
      const double *bru_seq = brush_sequence;
Shinya Kitaoka 120a6e
      int bru_dia           = brush_diameter;
Shinya Kitaoka 120a6e
      const double *inn_pla = &in_plane_with_margin[yy][xo];
Shinya Kitaoka 120a6e
      while (0 < bru_dia--) {
Shinya Kitaoka 120a6e
        accum += (*inn_pla) * (*bru_seq++);
Shinya Kitaoka 120a6e
        inn_pla += width_with_margin;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      out_plane_with_margin[yo][xo] = accum;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
shun-iwasawa 481b59
#endif
shun-iwasawa 481b59
shun-iwasawa 481b59
void blur_2nd_vert_(
shun-iwasawa 481b59
    const double** in_plane_with_margin  // &(std::vector<double *="">).at(0)</double>
shun-iwasawa 481b59
    ,
shun-iwasawa 481b59
    const int height_with_margin, const int width_with_margin,
shun-iwasawa 481b59
    double* brush_sequence  // &(std::vector<double *="">).at(0)</double>
shun-iwasawa 481b59
    ,
shun-iwasawa 481b59
    const int int_radius,
shun-iwasawa 481b59
    double** out_plane_with_margin  // &(std::vector<double *="">).at(0)</double>
shun-iwasawa 481b59
shun-iwasawa 481b59
    /* 参照画像用情報(no margin) */
shun-iwasawa 481b59
    ,
shun-iwasawa 481b59
    const float* ref /* 求める画像(out)と同じ高さ、幅、チャンネル数 */
shun-iwasawa 481b59
    ,
shun-iwasawa 481b59
    const double real_radius, const double sigma) {
shun-iwasawa 481b59
  const int brush_diameter   = diameter_from_radius_(int_radius);
shun-iwasawa 481b59
  const int height_no_margin = height_with_margin - int_radius * 2;
shun-iwasawa 481b59
  const int width_no_margin  = width_with_margin - int_radius * 2;
shun-iwasawa 481b59
  // const int r_max = std::numeric_limits<rt>::max();</rt>
shun-iwasawa 481b59
  const float* ref_vert     = ref;
shun-iwasawa 481b59
  const float* ref_hori     = ref;
shun-iwasawa 481b59
  double before_real_radius = -1.0;
shun-iwasawa 481b59
shun-iwasawa 481b59
  /* 左右マージン部分はもう処理しなくていい */
shun-iwasawa 481b59
shun-iwasawa 481b59
  /* 横方向 */
shun-iwasawa 481b59
  for (int xx = 0, xo = int_radius; xx < width_no_margin; ++xx, ++xo) {
shun-iwasawa 481b59
    if (ref != nullptr) {
shun-iwasawa 481b59
      ref_hori++;
shun-iwasawa 481b59
      ref_vert = ref_hori;
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
shun-iwasawa 481b59
    /* 縦方向 */
shun-iwasawa 481b59
    for (int yy = 0, yo = int_radius; yy < height_no_margin; ++yy, ++yo) {
shun-iwasawa 481b59
      if (ref != 0) {
shun-iwasawa 481b59
        const double read_r = real_radius * (*ref_vert);
shun-iwasawa 481b59
        ref_vert += width_no_margin;
shun-iwasawa 481b59
shun-iwasawa 481b59
        if (read_r != before_real_radius) {
shun-iwasawa 481b59
          gauss_distribution_1d_(brush_sequence, brush_diameter,
shun-iwasawa 481b59
                                 igs::gaussian_blur_hv::int_radius(read_r),
shun-iwasawa 481b59
                                 read_r, sigma);
shun-iwasawa 481b59
          before_real_radius = read_r;
shun-iwasawa 481b59
        }
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
      /* ガウス分布で横blur */
shun-iwasawa 481b59
      double accum          = 0;
shun-iwasawa 481b59
      const double* bru_seq = brush_sequence;
shun-iwasawa 481b59
      int bru_dia           = brush_diameter;
shun-iwasawa 481b59
      const double* inn_pla = &in_plane_with_margin[yy][xo];
shun-iwasawa 481b59
      while (0 < bru_dia--) {
shun-iwasawa 481b59
        accum += (*inn_pla) * (*bru_seq++);
shun-iwasawa 481b59
        inn_pla += width_with_margin;
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
      out_plane_with_margin[yo][xo] = accum;
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
}
shun-iwasawa 481b59
shun-iwasawa 481b59
#if 0
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
void get_(const T *in, const int height, const int width, const int channels,
Shinya Kitaoka 120a6e
          const int current_ch, double **out  // &(std::vector<double *="">).at(0)</double>
Shinya Kitaoka 120a6e
          ) {
Shinya Kitaoka 120a6e
  in += current_ch;
Shinya Kitaoka 120a6e
  const double maxi = static_cast<double>(std::numeric_limits<t>::max());</t></double>
Shinya Kitaoka 120a6e
  for (int yy = 0; yy < height; ++yy) {
Shinya Kitaoka 120a6e
    for (int xx = 0; xx < width; ++xx) {
Shinya Kitaoka 120a6e
      out[yy][xx] = static_cast<double>(*in) / maxi;</double>
Shinya Kitaoka 120a6e
      in += channels;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
shun-iwasawa 481b59
#endif
shun-iwasawa 481b59
shun-iwasawa 481b59
void get_(const float* in, const int height, const int width,
shun-iwasawa 481b59
          const int channels, const int current_ch,
shun-iwasawa 481b59
          double** out  // &(std::vector<double *="">).at(0)</double>
shun-iwasawa 481b59
) {
shun-iwasawa 481b59
  in += current_ch;
shun-iwasawa 481b59
  for (int yy = 0; yy < height; ++yy) {
shun-iwasawa 481b59
    for (int xx = 0; xx < width; ++xx) {
shun-iwasawa 481b59
      out[yy][xx] = static_cast<double>(*in);</double>
shun-iwasawa 481b59
      in += channels;
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
}
shun-iwasawa 481b59
shun-iwasawa 481b59
#if 0
Toshihiro Shimizu 890ddd
template <class t=""></class>
Toshihiro Shimizu 890ddd
void put_margin_(
Shinya Kitaoka 120a6e
    const double **in_with_margin  // &(std::vector<double *="">).at(0)</double>
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int height_with_margin, const int width_with_margin,
Shinya Kitaoka 120a6e
    const int channels, const int current_ch, const int margin,
Shinya Kitaoka 120a6e
    T *out_no_margin) {
Shinya Kitaoka 120a6e
  out_no_margin += current_ch;
Shinya Kitaoka 120a6e
  const double maxi =
Shinya Kitaoka 120a6e
      static_cast<double>(std::numeric_limits<t>::max()) + 0.999999;</t></double>
Shinya Kitaoka 120a6e
  for (int yy = margin; yy < (height_with_margin - margin); ++yy) {
Shinya Kitaoka 120a6e
    for (int xx = margin; xx < (width_with_margin - margin); ++xx) {
Shinya Kitaoka 120a6e
      *out_no_margin = static_cast<t>(in_with_margin[yy][xx] * maxi);</t>
Shinya Kitaoka 120a6e
      out_no_margin += channels;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
shun-iwasawa 481b59
#endif
shun-iwasawa 481b59
shun-iwasawa 481b59
void put_margin_(
shun-iwasawa 481b59
    const double** in_with_margin,  // &(std::vector<double *="">).at(0)</double>
shun-iwasawa 481b59
    const int height_with_margin, const int width_with_margin,
shun-iwasawa 481b59
    const int channels, const int current_ch, const int margin,
shun-iwasawa 481b59
    float* out_no_margin) {
shun-iwasawa 481b59
  out_no_margin += current_ch;
shun-iwasawa 481b59
  for (int yy = margin; yy < (height_with_margin - margin); ++yy) {
shun-iwasawa 481b59
    for (int xx = margin; xx < (width_with_margin - margin); ++xx) {
shun-iwasawa 481b59
      *out_no_margin = in_with_margin[yy][xx];
shun-iwasawa 481b59
      out_no_margin += channels;
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
}
shun-iwasawa 481b59
shun-iwasawa 481b59
#if 0
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
bool diff_between_channel_(const T *in, const int height, const int width,
Shinya Kitaoka 120a6e
                           const int channels, const int ch1, const int ch2) {
Shinya Kitaoka 120a6e
  // if (ch1 == ch2) { return false; }
Shinya Kitaoka 120a6e
  // if (channels <= ch1) { return false; }
Shinya Kitaoka 120a6e
  // if (channels <= ch2) { return false; }
Shinya Kitaoka 120a6e
  for (int yy = 0; yy < height; ++yy) {
Shinya Kitaoka 120a6e
    for (int xx = 0; xx < width; ++xx) {
Shinya Kitaoka 120a6e
      if (in[ch1] != in[ch2]) {
Shinya Kitaoka 120a6e
        return true;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      in += channels;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return false;
Toshihiro Shimizu 890ddd
}
shun-iwasawa 481b59
#endif
shun-iwasawa 481b59
bool diff_between_channel_(const float* in, const int height, const int width,
shun-iwasawa 481b59
                           const int channels, const int ch1, const int ch2) {
shun-iwasawa 481b59
  for (int yy = 0; yy < height; ++yy) {
shun-iwasawa 481b59
    for (int xx = 0; xx < width; ++xx) {
shun-iwasawa 481b59
      if (in[ch1] != in[ch2]) {
shun-iwasawa 481b59
        return true;
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
      in += channels;
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
  return false;
shun-iwasawa 481b59
}
shun-iwasawa 481b59
shun-iwasawa 481b59
#if 0
Toshihiro Shimizu 890ddd
template <class class="" it,="" rt=""></class>
Shinya Kitaoka 120a6e
void convert_hv_(const IT *in_with_margin, IT *out_no_margin,
Shinya Kitaoka 120a6e
                 const int height_with_margin, const int width_with_margin,
Shinya Kitaoka 120a6e
                 const int channels
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
                 ,
Shinya Kitaoka 120a6e
                 double *filter  // (double *)(&filter_buf.at(0))
Shinya Kitaoka 120a6e
                 ,
Shinya Kitaoka 120a6e
                 const int int_radius,
Shinya Kitaoka 120a6e
                 double **buffer_inn  // &(std::vector<double *="">).at(0)</double>
Shinya Kitaoka 120a6e
                 ,
Shinya Kitaoka 120a6e
                 double **buffer_out  // &(std::vector<double *="">).at(0)</double>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
                 /* 参照画像用情報(no margin) */
Shinya Kitaoka 120a6e
                 ,
Shinya Kitaoka 120a6e
                 const RT *ref /* 求める画像(out)と同じ高さ、幅、チャンネル数 */
Shinya Kitaoka 120a6e
                 ,
Shinya Kitaoka 120a6e
                 const int ref_mode /* 0=R,1=G,2=B,3=A,4=Luminance,5=Nothing */
Shinya Kitaoka 120a6e
                 ,
Shinya Kitaoka 120a6e
                 const double real_radius, const double sigma) {
Shinya Kitaoka 120a6e
  bool diff_sw = true; /* 1番目の画像は処理する */
Shinya Kitaoka 120a6e
  for (int cc = 0; cc < channels; ++cc) {
Shinya Kitaoka 120a6e
    if (0 < cc) { /* 2番目のチャンネル以後 */
Shinya Kitaoka 120a6e
      /* 1つ前のチャンネルと違いを調べる */
Shinya Kitaoka 120a6e
      diff_sw = diff_between_channel_(in_with_margin, height_with_margin,
Shinya Kitaoka 120a6e
                                      width_with_margin, channels, cc - 1, cc);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    /* 一つ前と同じ画像なら処理せず使い回して高速化する */
Shinya Kitaoka 120a6e
    if (diff_sw) {
Shinya Kitaoka 120a6e
      get_(in_with_margin, height_with_margin, width_with_margin, channels, cc,
Shinya Kitaoka 120a6e
           buffer_inn);
Shinya Kitaoka 120a6e
      blur_1st_hori_((const double **)(buffer_inn), height_with_margin,
Shinya Kitaoka 120a6e
                     width_with_margin, filter, int_radius, buffer_out
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
                     ,
Shinya Kitaoka 120a6e
                     ref, ref_mode, channels, real_radius, sigma);
Shinya Kitaoka 120a6e
      blur_2nd_vert_((const double **)(buffer_out), height_with_margin,
Shinya Kitaoka 120a6e
                     width_with_margin, filter, int_radius, buffer_inn
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
                     ,
Shinya Kitaoka 120a6e
                     ref, ref_mode, channels, real_radius, sigma);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    put_margin_((const double **)(buffer_inn), height_with_margin,
Shinya Kitaoka 120a6e
                width_with_margin, channels, cc, int_radius, out_no_margin);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
shun-iwasawa 481b59
#endif
shun-iwasawa 481b59
shun-iwasawa 481b59
void convert_hv_(
shun-iwasawa 481b59
    const float* in_with_margin, float* out_no_margin,
shun-iwasawa 481b59
    const int height_with_margin, const int width_with_margin,
shun-iwasawa 481b59
    const int channels,
shun-iwasawa 481b59
    double* filter,  // (double *)(&filter_buf.at(0))
shun-iwasawa 481b59
    const int int_radius,
shun-iwasawa 481b59
    double** buffer_inn,  // &(std::vector<double *="">).at(0)</double>
shun-iwasawa 481b59
    double** buffer_out,  // &(std::vector<double *="">).at(0)</double>
shun-iwasawa 481b59
    /* 参照画像用情報(no margin) */
shun-iwasawa 481b59
    const float* ref, /* 求める画像(out)と同じ高さ、幅、チャンネル数 */
shun-iwasawa 481b59
    const double real_radius, const double sigma) {
shun-iwasawa 481b59
  bool diff_sw = true; /* 1番目の画像は処理する */
shun-iwasawa 481b59
  for (int cc = 0; cc < channels; ++cc) {
shun-iwasawa 481b59
    if (0 < cc) { /* 2番目のチャンネル以後 */
shun-iwasawa 481b59
      /* 1つ前のチャンネルと違いを調べる */
shun-iwasawa 481b59
      diff_sw = diff_between_channel_(in_with_margin, height_with_margin,
shun-iwasawa 481b59
                                      width_with_margin, channels, cc - 1, cc);
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
    /* 一つ前と同じ画像なら処理せず使い回して高速化する */
shun-iwasawa 481b59
    if (diff_sw) {
shun-iwasawa 481b59
      get_(in_with_margin, height_with_margin, width_with_margin, channels, cc,
shun-iwasawa 481b59
           buffer_inn);
shun-iwasawa 481b59
      blur_1st_hori_((const double**)(buffer_inn), height_with_margin,
shun-iwasawa 481b59
                     width_with_margin, filter, int_radius, buffer_out, ref,
shun-iwasawa 481b59
                     real_radius, sigma);
shun-iwasawa 481b59
      blur_2nd_vert_((const double**)(buffer_out), height_with_margin,
shun-iwasawa 481b59
                     width_with_margin, filter, int_radius, buffer_inn, ref,
shun-iwasawa 481b59
                     real_radius, sigma);
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
shun-iwasawa 481b59
    put_margin_((const double**)(buffer_inn), height_with_margin,
shun-iwasawa 481b59
                width_with_margin, channels, cc, int_radius, out_no_margin);
shun-iwasawa 481b59
  }
Toshihiro Shimizu 890ddd
}
shun-iwasawa 481b59
shun-iwasawa 481b59
}  // namespace
Shinya Kitaoka 120a6e
const int igs::gaussian_blur_hv::int_radius(const double real_radius) {
Shinya Kitaoka 120a6e
  /* ぼかしの半径から、pixelサイズ半径(=中心位置=margin)を決める */
Shinya Kitaoka 120a6e
  return static_cast<int>(ceil(real_radius));</int>
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
const int igs::gaussian_blur_hv::buffer_bytes(const int height_with_margin,
Shinya Kitaoka 120a6e
                                              const int width_with_margin,
Shinya Kitaoka 120a6e
                                              const int int_radius) {
Shinya Kitaoka 120a6e
  const int int_diameter = diameter_from_radius_(int_radius);
Shinya Kitaoka 120a6e
  return int_diameter * int_diameter * sizeof(double) +
Shinya Kitaoka 120a6e
         height_with_margin * width_with_margin * sizeof(double) +
Shinya Kitaoka 120a6e
         height_with_margin * width_with_margin * sizeof(double);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
void igs::gaussian_blur_hv::convert(
Shinya Kitaoka 120a6e
    /* 入出力画像 */
shun-iwasawa 481b59
    const float* in_with_margin, float* out_no_margin,
Shinya Kitaoka 120a6e
    const int height_with_margin, const int width_with_margin,
shun-iwasawa 481b59
    const int channels,
Shinya Kitaoka 120a6e
    /* Pixel毎に効果の強弱 */
shun-iwasawa 481b59
    const float* ref, /* 求める画像(out)と同じ高、幅、ch数 */
Shinya Kitaoka 120a6e
    /* 計算バッファ */
shun-iwasawa 481b59
    void* buffer,
shun-iwasawa 481b59
    int buffer_bytes,  // Must be igs::gaussian_blur_hv::buffer_bytes(-)
Shinya Kitaoka 120a6e
    /* Action Geometry */
shun-iwasawa 481b59
    const int int_radius,                         // =margin
Shinya Kitaoka 120a6e
    const double real_radius, const double sigma  //= 0.25
shun-iwasawa 481b59
) {
Shinya Kitaoka 120a6e
  /* 引数チェック */
Shinya Kitaoka 120a6e
  if (real_radius <= 0.0) {
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if ((igs::image::rgba::siz != channels) &&
Shinya Kitaoka 120a6e
      (igs::image::rgb::siz != channels) && (1 != channels) /* grayscale */
shun-iwasawa 481b59
  ) {
Shinya Kitaoka 120a6e
    throw std::domain_error("Bad channels,Not rgba/rgb/grayscale");
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* 変数の設定 */
Shinya Kitaoka 120a6e
  const int int_diameter = diameter_from_radius_(int_radius);
shun-iwasawa 481b59
  double* double_buffer  = static_cast<double*>(buffer);</double*>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* メモリバッファの設定 */
Shinya Kitaoka 120a6e
  std::vector<double> filter_buf(int_diameter);</double>
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  std::vector<double*> in_plane_with_margin_dp(height_with_margin);</double*>
Shinya Kitaoka 120a6e
  for (int yy = 0; yy < height_with_margin; ++yy) {
Shinya Kitaoka 120a6e
    in_plane_with_margin_dp.at(yy) = double_buffer;
Shinya Kitaoka 120a6e
    double_buffer += width_with_margin;
Shinya Kitaoka 120a6e
    buffer_bytes -= width_with_margin * sizeof(double);
Shinya Kitaoka 120a6e
    if (buffer_bytes <= 0) {
Shinya Kitaoka 120a6e
      std::string msg("buffer_inn is empty");
Shinya Kitaoka 120a6e
      throw std::domain_error(msg);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  std::vector<double*> out_plane_with_margin_dp(height_with_margin);</double*>
Shinya Kitaoka 120a6e
  for (int yy = 0; yy < height_with_margin; ++yy) {
Shinya Kitaoka 120a6e
    out_plane_with_margin_dp.at(yy) = double_buffer;
Shinya Kitaoka 120a6e
    double_buffer += width_with_margin;
Shinya Kitaoka 120a6e
    buffer_bytes -= width_with_margin * sizeof(double);
Shinya Kitaoka 120a6e
    if (buffer_bytes <= 0) {
Shinya Kitaoka 120a6e
      std::string msg("buffer_out is empty");
Shinya Kitaoka 120a6e
      throw std::domain_error(msg);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* filter生成 */
Shinya Kitaoka 120a6e
  gauss_distribution_1d_(&filter_buf.at(0), int_diameter, int_radius,
Shinya Kitaoka 120a6e
                         real_radius, sigma);
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  convert_hv_(in_with_margin, out_no_margin, height_with_margin,
shun-iwasawa 481b59
              width_with_margin, channels, &filter_buf.at(0), int_radius,
shun-iwasawa 481b59
              &in_plane_with_margin_dp.at(0), &out_plane_with_margin_dp.at(0),
shun-iwasawa 481b59
              ref, real_radius, sigma);
shun-iwasawa 481b59
  /*
Shinya Kitaoka 120a6e
  if ((std::numeric_limits<unsigned char="">::digits == bits) &&</unsigned>
Shinya Kitaoka 120a6e
      ((std::numeric_limits<unsigned char="">::digits == ref_bits) ||</unsigned>
Shinya Kitaoka 120a6e
       (0 == ref_bits))) {
Shinya Kitaoka 120a6e
    convert_hv_(static_cast<const *="" char="" unsigned="">(in_with_margin),</const>
Shinya Kitaoka 120a6e
                static_cast<unsigned *="" char="">(out_no_margin), height_with_margin,</unsigned>
Shinya Kitaoka 120a6e
                width_with_margin, channels, &filter_buf.at(0), int_radius,
Shinya Kitaoka 120a6e
                &in_plane_with_margin_dp.at(0), &out_plane_with_margin_dp.at(0)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
                                                    ,
Shinya Kitaoka 120a6e
                ref, ref_mode, real_radius, sigma);
Shinya Kitaoka 120a6e
  } else if ((std::numeric_limits<unsigned short="">::digits == bits) &&</unsigned>
Shinya Kitaoka 120a6e
             ((std::numeric_limits<unsigned char="">::digits == ref_bits) ||</unsigned>
Shinya Kitaoka 120a6e
              (0 == ref_bits))) {
Shinya Kitaoka 120a6e
    convert_hv_(static_cast<const *="" short="" unsigned="">(in_with_margin),</const>
Shinya Kitaoka 120a6e
                static_cast<unsigned *="" short="">(out_no_margin),</unsigned>
Shinya Kitaoka 120a6e
                height_with_margin, width_with_margin, channels,
Shinya Kitaoka 120a6e
                &filter_buf.at(0), int_radius, &in_plane_with_margin_dp.at(0),
Shinya Kitaoka 120a6e
                &out_plane_with_margin_dp.at(0)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
                    ,
Shinya Kitaoka 120a6e
                ref, ref_mode, real_radius, sigma);
Shinya Kitaoka 120a6e
  } else if ((std::numeric_limits<unsigned short="">::digits == bits) &&</unsigned>
Shinya Kitaoka 120a6e
             (std::numeric_limits<unsigned short="">::digits == ref_bits)) {</unsigned>
Shinya Kitaoka 120a6e
    convert_hv_(static_cast<const *="" short="" unsigned="">(in_with_margin),</const>
Shinya Kitaoka 120a6e
                static_cast<unsigned *="" short="">(out_no_margin),</unsigned>
Shinya Kitaoka 120a6e
                height_with_margin, width_with_margin, channels,
Shinya Kitaoka 120a6e
                &filter_buf.at(0), int_radius, &in_plane_with_margin_dp.at(0),
Shinya Kitaoka 120a6e
                &out_plane_with_margin_dp.at(0)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
                    ,
Shinya Kitaoka 120a6e
                reinterpret_cast<const *="" short="" unsigned="">(ref), ref_mode,</const>
Shinya Kitaoka 120a6e
                real_radius, sigma);
Shinya Kitaoka 120a6e
  } else if ((std::numeric_limits<unsigned char="">::digits == bits) &&</unsigned>
Shinya Kitaoka 120a6e
             (std::numeric_limits<unsigned short="">::digits == ref_bits)) {</unsigned>
Shinya Kitaoka 120a6e
    convert_hv_(static_cast<const *="" short="" unsigned="">(in_with_margin),</const>
Shinya Kitaoka 120a6e
                static_cast<unsigned *="" short="">(out_no_margin),</unsigned>
Shinya Kitaoka 120a6e
                height_with_margin, width_with_margin, channels,
Shinya Kitaoka 120a6e
                &filter_buf.at(0), int_radius, &in_plane_with_margin_dp.at(0),
Shinya Kitaoka 120a6e
                &out_plane_with_margin_dp.at(0)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
                    ,
Shinya Kitaoka 120a6e
                reinterpret_cast<const *="" char="" unsigned="">(ref), ref_mode,</const>
Shinya Kitaoka 120a6e
                real_radius, sigma);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    throw std::domain_error("Bad bits,Not uchar/ushort");
Shinya Kitaoka 120a6e
  }
shun-iwasawa 481b59
  */
Toshihiro Shimizu 890ddd
}