Shinya Kitaoka 810553
#pragma once
Shinya Kitaoka 810553
Toshihiro Shimizu 890ddd
#ifndef igs_maxmin_getput_h
Toshihiro Shimizu 890ddd
#define igs_maxmin_getput_h
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <vector></vector>
shun-iwasawa 481b59
#include <limits>            /* std::numeric_limits<->::max()</limits>
Toshihiro Shimizu 890ddd
		--> (std::numeric_limits<->::max)() */
Shinya Kitaoka 120a6e
#include "igs_ifx_common.h"  // igs::color::ref_value(-)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
/* 画像配列の高さ位置を、実際の範囲内にclampし、scanlineの先頭を返す */
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
const T *csl_top_clamped_in_h_(const T *top, const int height, const int width,
Shinya Kitaoka 120a6e
                               const int channels, const int yy) {
Shinya Kitaoka 120a6e
  if (height <= yy) {
Shinya Kitaoka 120a6e
    return top + (channels * width * (height - 1));
Shinya Kitaoka 120a6e
  } else if (yy < 0) {
Shinya Kitaoka 120a6e
    return top;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return top + (channels * width * yy);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
T *sl_out_clamped_in_h_(T *out, const int height, const int width,
Shinya Kitaoka 120a6e
                        const int channels, const int yy) {
Shinya Kitaoka 120a6e
  if (height <= yy) {
Shinya Kitaoka 120a6e
    return out + (channels * width * (height - 1));
Shinya Kitaoka 120a6e
  } else if (yy < 0) {
Shinya Kitaoka 120a6e
    return out;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return out + (channels * width * yy);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/* trackの余白を画像の端の色で塗りつぶす(余白部分をtracksの前後にコピー) */
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
void paint_margin_(const int margin, std::vector<t> &track) {</t>
Shinya Kitaoka 120a6e
  int xx;
Shinya Kitaoka 120a6e
  /* 始点側の余白を塗りつぶす */
Shinya Kitaoka 120a6e
  for (xx = 0; xx < margin; ++xx) {
Shinya Kitaoka 120a6e
    track.at(xx) = track.at(margin);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  /* 終端側の余白を塗りつぶす */
Shinya Kitaoka 120a6e
  for (xx = 0; xx < margin; ++xx) {
Shinya Kitaoka 120a6e
    track.at(track.size() - 1 - xx) = track.at(track.size() - 1 - margin);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/* 入力画像を計算用のtrackバッファーの真ん中に正規化して入れる */
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
void inn_to_track_(const T *sl, const int width, const int channels,
Shinya Kitaoka 120a6e
                   const double div_val, const int margin,
Shinya Kitaoka 120a6e
                   std::vector<double> &track) {</double>
Shinya Kitaoka 120a6e
  for (int xx = 0; xx < width; ++xx) {
Shinya Kitaoka 120a6e
    track.at(margin + xx) = sl[xx * channels] / div_val;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/* 入力画像を正規化して、結果を置く場所(result)に初期値として入れる */
Toshihiro Shimizu 890ddd
template <class t=""></class>
Toshihiro Shimizu 890ddd
void inn_to_result_(
Shinya Kitaoka 120a6e
    const T *inn, const int height, const int width, const int channels,
Shinya Kitaoka 120a6e
    const int yy, const int zz, const double div_val,
Shinya Kitaoka 120a6e
    std::vector<double> &result /* 元値をいれといて、結果を入れる */</double>
shun-iwasawa 481b59
) {
Shinya Kitaoka 120a6e
  const T *ss = csl_top_clamped_in_h_(inn, height, width, channels, yy) + zz;
Shinya Kitaoka 120a6e
  for (int xx = 0; xx < width; ++xx) {
Shinya Kitaoka 120a6e
    result.at(xx) = ss[xx * channels] / div_val;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/* Scanlineで、効果を調節するデータ(alpha_ref)に、初期値を与える */
Shinya Kitaoka 120a6e
void alpha_ref_init_one_(const int width, std::vector<double> &alpha_ref) {</double>
Shinya Kitaoka 120a6e
  for (int xx = 0; xx < width; ++xx) {
Shinya Kitaoka 120a6e
    alpha_ref.at(xx) = 1.0; /* 全面的に処理を加える値で埋める */
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/* Scanlineで、効果を調節するデータ(alpha_ref)に、画像の影響を与える */
Toshihiro Shimizu 890ddd
template <class rt=""></class>
Shinya Kitaoka 120a6e
void alpha_ref_mul_ref_(const RT *ref, const int height, const int width,
Shinya Kitaoka 120a6e
                        const int channels, const int yy, const int ref_mode,
Shinya Kitaoka 120a6e
                        std::vector<double> &alpha_ref) {</double>
Shinya Kitaoka 120a6e
  const int r_max = (std::numeric_limits<rt>::max)();</rt>
Shinya Kitaoka 120a6e
  const RT *rr    = csl_top_clamped_in_h_(ref, height, width, channels, yy);
Shinya Kitaoka 120a6e
  for (int xx = 0; xx < width; ++xx) {
shun-iwasawa 481b59
    double refv =
Shinya Kitaoka 120a6e
        igs::color::ref_value(&rr[xx * channels], channels, r_max, ref_mode);
shun-iwasawa 481b59
    // clamp 0 to 1 in case using HDR raster
shun-iwasawa 481b59
    alpha_ref.at(xx) *= std::min(1., std::max(0., refv));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/* Scanlineで、効果を調節するデータ(alpha_ref)に、
Shinya Kitaoka 120a6e
        計算済み画像(out)のalphaチャンネル値の影響を与える */
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
void alpha_ref_mul_alpha_(const T *out, const int height, const int width,
Shinya Kitaoka 120a6e
                          const int channels, const int yy,
Shinya Kitaoka 120a6e
                          const double div_val,
Shinya Kitaoka 120a6e
                          std::vector<double> &alpha_ref) {</double>
Shinya Kitaoka 120a6e
  const T *dd = csl_top_clamped_in_h_(out, height, width, channels, yy) + 3;
Shinya Kitaoka 120a6e
  for (int xx = 0; xx < width; ++xx) {
Shinya Kitaoka 120a6e
    alpha_ref.at(xx) *= dd[xx * channels] / div_val;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
shun-iwasawa 481b59
}  // namespace
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Shinya Kitaoka 120a6e
namespace igs {
Shinya Kitaoka 120a6e
namespace maxmin {
Shinya Kitaoka 120a6e
namespace getput {
Toshihiro Shimizu 890ddd
/* 1番初めのスキャンラインのセット
Shinya Kitaoka 120a6e
        * IT is 'unsigned char' or 'unsigned short'
Shinya Kitaoka 120a6e
        * alphaは先に処理して結果(out)に入れ、
Shinya Kitaoka 120a6e
                その後rgbのために参照する
Toshihiro Shimizu 890ddd
   */
Toshihiro Shimizu 890ddd
template <class class="" it,="" rt=""></class>
Toshihiro Shimizu 890ddd
void get_first(
Shinya Kitaoka 120a6e
    const IT *inn /* outと同じ高さ、幅、チャンネル数 */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const IT *out /* outの処理結果alpha値をinとして使用 */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int hh, const int ww, const int ch,
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 yy, const int zz, const int margin, const bool add_blend_sw,
Shinya Kitaoka 120a6e
    std::vector<std::vector<double>> &tracks /* sl影響範囲のpixel値 */</std::vector<double>
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    std::vector<double> &alpha_ref /* pixel毎の変化の割合 */</double>
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    std::vector<double> &result /* 元値をいれといて、結果を入れる */</double>
shun-iwasawa 481b59
) {
Shinya Kitaoka 120a6e
  const int t_max      = (std::numeric_limits<it>::max)();</it>
Shinya Kitaoka 120a6e
  const double div_val = static_cast<double>(t_max);</double>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  /* 計算範囲の画像値を計算バッファ(tracks)に入れる */
Shinya Kitaoka 120a6e
  int ii = margin * 2;
Shinya Kitaoka 120a6e
  for (int yp = -margin + yy; yp <= margin + yy; ++yp, --ii) {
Shinya Kitaoka 120a6e
    const IT *sl = csl_top_clamped_in_h_(inn, hh, ww, ch, yp) + zz;
Shinya Kitaoka 120a6e
    inn_to_track_(sl, ww, ch, div_val, margin, tracks.at(ii));
Shinya Kitaoka 120a6e
    paint_margin_(margin, tracks.at(ii));
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  inn_to_result_(inn, hh, ww, ch, yy, zz, div_val, result);
Shinya Kitaoka 120a6e
  if (alpha_ref.size() <= 0) {
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  } /* alphaチャンネルを計算する場合 */
Shinya Kitaoka 120a6e
  alpha_ref_init_one_(ww, alpha_ref);
Shinya Kitaoka 120a6e
  if (ref != 0) {
Shinya Kitaoka 120a6e
    alpha_ref_mul_ref_(ref, hh, ww, ch, yy, ref_mode, alpha_ref);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (ch < 4) {
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  } /* alphaチャンネルがない場合はここで終わり */
Shinya Kitaoka 120a6e
  if (add_blend_sw) {
Shinya Kitaoka 120a6e
    alpha_ref_mul_alpha_(out, hh, ww, ch, yy, div_val, alpha_ref);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
shun-iwasawa 481b59
shun-iwasawa 481b59
template <>
shun-iwasawa 481b59
void get_first(
shun-iwasawa 481b59
    const float *inn /* outと同じ高さ、幅、チャンネル数 */
shun-iwasawa 481b59
    ,
shun-iwasawa 481b59
    const float *out /* outの処理結果alpha値をinとして使用 */
shun-iwasawa 481b59
    ,
shun-iwasawa 481b59
    const int hh, const int ww, const int ch,
shun-iwasawa 481b59
    const float *ref /* outと同じ高さ、幅、チャンネル数 */
shun-iwasawa 481b59
    ,
shun-iwasawa 481b59
    const int ref_mode /* 0=R,1=G,2=B,3=A,4=Luminance,5=Nothing */
shun-iwasawa 481b59
    ,
shun-iwasawa 481b59
    const int yy, const int zz, const int margin, const bool add_blend_sw,
shun-iwasawa 481b59
    std::vector<std::vector<double>> &tracks /* sl影響範囲のpixel値 */</std::vector<double>
shun-iwasawa 481b59
    ,
shun-iwasawa 481b59
    std::vector<double> &alpha_ref /* pixel毎の変化の割合 */</double>
shun-iwasawa 481b59
    ,
shun-iwasawa 481b59
    std::vector<double> &result /* 元値をいれといて、結果を入れる */</double>
shun-iwasawa 481b59
) {
shun-iwasawa 481b59
  const double div_val = 1.;
shun-iwasawa 481b59
shun-iwasawa 481b59
  /* 計算範囲の画像値を計算バッファ(tracks)に入れる */
shun-iwasawa 481b59
  int ii = margin * 2;
shun-iwasawa 481b59
  for (int yp = -margin + yy; yp <= margin + yy; ++yp, --ii) {
shun-iwasawa 481b59
    const float *sl = csl_top_clamped_in_h_(inn, hh, ww, ch, yp) + zz;
shun-iwasawa 481b59
    inn_to_track_(sl, ww, ch, div_val, margin, tracks.at(ii));
shun-iwasawa 481b59
    paint_margin_(margin, tracks.at(ii));
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
  inn_to_result_(inn, hh, ww, ch, yy, zz, div_val, result);
shun-iwasawa 481b59
  if (alpha_ref.size() <= 0) {
shun-iwasawa 481b59
    return;
shun-iwasawa 481b59
  } /* alphaチャンネルを計算する場合 */
shun-iwasawa 481b59
  alpha_ref_init_one_(ww, alpha_ref);
shun-iwasawa 481b59
  if (ref != 0) {
shun-iwasawa 481b59
    alpha_ref_mul_ref_(ref, hh, ww, ch, yy, ref_mode, alpha_ref);
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
  if (ch < 4) {
shun-iwasawa 481b59
    return;
shun-iwasawa 481b59
  } /* alphaチャンネルがない場合はここで終わり */
shun-iwasawa 481b59
  if (add_blend_sw) {
shun-iwasawa 481b59
    alpha_ref_mul_alpha_(out, hh, ww, ch, yy, div_val, alpha_ref);
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
}
Toshihiro Shimizu 890ddd
/*--- 2番以後のスキャンラインのセット -------------------------------*/
Toshihiro Shimizu 890ddd
template <class class="" it,="" rt=""></class>
Shinya Kitaoka 120a6e
void get_next(const IT *inn /* outと同じ高さ、幅、チャンネル数 */
Shinya Kitaoka 120a6e
              ,
Shinya Kitaoka 120a6e
              const IT *out /* outの処理結果alpha値をinとして使用 */
Shinya Kitaoka 120a6e
              ,
Shinya Kitaoka 120a6e
              const int hh, const int ww, const int ch,
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 yy, const int zz, const int margin,
Shinya Kitaoka 120a6e
              const bool add_blend_sw,
Shinya Kitaoka 120a6e
              std::vector<std::vector<double>> &tracks /* sl影響範囲のpixel値 */</std::vector<double>
Shinya Kitaoka 120a6e
              ,
Shinya Kitaoka 120a6e
              std::vector<double> &alpha_ref /* pixel毎の変化の割合 */</double>
Shinya Kitaoka 120a6e
              ,
Shinya Kitaoka 120a6e
              std::vector<double> &result /* 元値をいれといて、結果を入れる */</double>
shun-iwasawa 481b59
) {
Shinya Kitaoka 120a6e
  const int t_max      = (std::numeric_limits<it>::max)();</it>
Shinya Kitaoka 120a6e
  const double div_val = static_cast<double>(t_max);</double>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const IT *sl = csl_top_clamped_in_h_(inn, hh, ww, ch, yy + margin) + zz;
Shinya Kitaoka 120a6e
  inn_to_track_(sl, ww, ch, div_val, margin, tracks.at(0));
Shinya Kitaoka 120a6e
  paint_margin_(margin, tracks.at(0));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  inn_to_result_(inn, hh, ww, ch, yy, zz, div_val, result);
Shinya Kitaoka 120a6e
  if (alpha_ref.size() <= 0) {
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  } /* alphaチャンネルを計算する場合 */
Shinya Kitaoka 120a6e
  alpha_ref_init_one_(ww, alpha_ref);
Shinya Kitaoka 120a6e
  if (ref != 0) {
Shinya Kitaoka 120a6e
    alpha_ref_mul_ref_(ref, hh, ww, ch, yy, ref_mode, alpha_ref);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (ch < 4) {
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  } /* alphaチャンネルがない場合はここで終わり */
Shinya Kitaoka 120a6e
  if (add_blend_sw) {
Shinya Kitaoka 120a6e
    alpha_ref_mul_alpha_(out, hh, ww, ch, yy, div_val, alpha_ref);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
shun-iwasawa 481b59
template <>
shun-iwasawa 481b59
void get_next(const float *inn /* outと同じ高さ、幅、チャンネル数 */
shun-iwasawa 481b59
              ,
shun-iwasawa 481b59
              const float *out /* outの処理結果alpha値をinとして使用 */
shun-iwasawa 481b59
              ,
shun-iwasawa 481b59
              const int hh, const int ww, const int ch,
shun-iwasawa 481b59
              const float *ref /* 求める画像(out)と同じ高さ、幅、チャンネル数 */
shun-iwasawa 481b59
              ,
shun-iwasawa 481b59
              const int ref_mode /* 0=R,1=G,2=B,3=A,4=Luminance,5=Nothing */
shun-iwasawa 481b59
              ,
shun-iwasawa 481b59
              const int yy, const int zz, const int margin,
shun-iwasawa 481b59
              const bool add_blend_sw,
shun-iwasawa 481b59
              std::vector<std::vector<double>> &tracks /* sl影響範囲のpixel値 */</std::vector<double>
shun-iwasawa 481b59
              ,
shun-iwasawa 481b59
              std::vector<double> &alpha_ref /* pixel毎の変化の割合 */</double>
shun-iwasawa 481b59
              ,
shun-iwasawa 481b59
              std::vector<double> &result /* 元値をいれといて、結果を入れる */</double>
shun-iwasawa 481b59
) {
shun-iwasawa 481b59
  const double div_val = 1.;
shun-iwasawa 481b59
shun-iwasawa 481b59
  const float *sl = csl_top_clamped_in_h_(inn, hh, ww, ch, yy + margin) + zz;
shun-iwasawa 481b59
  inn_to_track_(sl, ww, ch, div_val, margin, tracks.at(0));
shun-iwasawa 481b59
  paint_margin_(margin, tracks.at(0));
shun-iwasawa 481b59
shun-iwasawa 481b59
  inn_to_result_(inn, hh, ww, ch, yy, zz, div_val, result);
shun-iwasawa 481b59
  if (alpha_ref.size() <= 0) {
shun-iwasawa 481b59
    return;
shun-iwasawa 481b59
  } /* alphaチャンネルを計算する場合 */
shun-iwasawa 481b59
  alpha_ref_init_one_(ww, alpha_ref);
shun-iwasawa 481b59
  if (ref != 0) {
shun-iwasawa 481b59
    alpha_ref_mul_ref_(ref, hh, ww, ch, yy, ref_mode, alpha_ref);
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
  if (ch < 4) {
shun-iwasawa 481b59
    return;
shun-iwasawa 481b59
  } /* alphaチャンネルがない場合はここで終わり */
shun-iwasawa 481b59
  if (add_blend_sw) {
shun-iwasawa 481b59
    alpha_ref_mul_alpha_(out, hh, ww, ch, yy, div_val, alpha_ref);
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
}
shun-iwasawa 481b59
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
void copy(const T *inn, const int hh, const int ww, const int ch, const int yy,
Shinya Kitaoka 120a6e
          const int zz, T *out) {
Shinya Kitaoka 120a6e
  const T *ss = csl_top_clamped_in_h_(inn, hh, ww, ch, yy) + zz;
Shinya Kitaoka 120a6e
  T *dd       = sl_out_clamped_in_h_(out, hh, ww, ch, yy) + zz;
Shinya Kitaoka 120a6e
  for (int xx = 0; xx < ww; ++xx) {
Shinya Kitaoka 120a6e
    dd[ch * xx] = ss[ch * xx];
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
shun-iwasawa 481b59
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
void put(const std::vector<double> &result, const int hh, const int ww,</double>
Shinya Kitaoka 120a6e
         const int ch, const int yy, const int zz, T *out) {
Shinya Kitaoka 120a6e
  const int t_max      = (std::numeric_limits<t>::max)();</t>
Shinya Kitaoka 120a6e
  const double mul_val = static_cast<double>(t_max) + 0.999999;</double>
Shinya Kitaoka 120a6e
  T *dd                = sl_out_clamped_in_h_(out, hh, ww, ch, yy) + zz;
Shinya Kitaoka 120a6e
  for (int xx = 0; xx < ww; ++xx) {
Shinya Kitaoka 120a6e
    dd[ch * xx] = static_cast<t>(result.at(xx) * mul_val);</t>
Shinya Kitaoka 120a6e
    // std::cout << " (" << result.at(xx) << ")(" << (int)dd[ch * xx] << ")";
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  // std::cout << std::endl;
Toshihiro Shimizu 890ddd
}
shun-iwasawa 481b59
shun-iwasawa 481b59
template <>
shun-iwasawa 481b59
void put(const std::vector<double> &result, const int hh, const int ww,</double>
shun-iwasawa 481b59
         const int ch, const int yy, const int zz, float *out) {
shun-iwasawa 481b59
  float *dd = sl_out_clamped_in_h_(out, hh, ww, ch, yy) + zz;
shun-iwasawa 481b59
  for (int xx = 0; xx < ww; ++xx) {
shun-iwasawa 481b59
    dd[ch * xx] = static_cast<float>(result.at(xx));</float>
shun-iwasawa 481b59
  }
Toshihiro Shimizu 890ddd
}
shun-iwasawa 481b59
shun-iwasawa 481b59
}  // namespace getput
shun-iwasawa 481b59
}  // namespace maxmin
shun-iwasawa 481b59
}  // namespace igs
Toshihiro Shimizu 890ddd
#endif /* !igs_maxmin_getput_h */