Toshihiro Shimizu 890ddd
#include "igs_density.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
double accum_by_trans_(
Shinya Kitaoka 120a6e
    const double src_value /* 元値(R,G,B) */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const double transparent /* src_valueの透明度(0...1) */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int integer_part /* 濃度値の整数部分(0...) */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const double fractional_part /* 濃度値の少数部分(0...1) */
Shinya Kitaoka 120a6e
    ) {
Shinya Kitaoka 120a6e
  double accumulation = src_value;
Shinya Kitaoka 120a6e
  if (1 <= integer_part) {
Shinya Kitaoka 120a6e
    for (int ii = 1; ii < integer_part; ++ii) {
Shinya Kitaoka 120a6e
      accumulation = accumulation * transparent + src_value;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (0.0 < fractional_part) {
Shinya Kitaoka 120a6e
      accumulation +=
Shinya Kitaoka 120a6e
          ((accumulation * transparent + src_value) - accumulation) *
Shinya Kitaoka 120a6e
          fractional_part;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else { /* 整数部分がゼロ以下のとき */
Shinya Kitaoka 120a6e
    if (0.0 < fractional_part) {
Shinya Kitaoka 120a6e
      accumulation *= fractional_part;
Shinya Kitaoka 120a6e
    } else { /* 少数部分もゼロ以下のとき */
Shinya Kitaoka 120a6e
      accumulation = 0.0;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return (1.0 < accumulation) ? 1.0
Shinya Kitaoka 120a6e
                              : ((accumulation < 0.0) ? 0.0 : accumulation);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
#include <limits>           /* std::numeric_limits */</limits>
Toshihiro Shimizu 890ddd
#include "igs_ifx_common.h" /* igs::image::rgba */
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
template <class class="" it,="" rt=""></class>
Toshihiro Shimizu 890ddd
void change_template_(
Shinya Kitaoka 120a6e
    IT *image_array, const int height, const int width, const int channels
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const RT *ref /* 求める画像と同じ高、幅、ch数 */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int ref_mode /* 0=R,1=G,2=B,3=A,4=Luminance,5=Nothing */
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const double density) {
Shinya Kitaoka 120a6e
  const int integer_part       = (int)density;
Shinya Kitaoka 120a6e
  const double fractional_part = density - (int)density;
Shinya Kitaoka 120a6e
  const double maxi            = std::numeric_limits<it>::max();</it>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  using namespace igs::image::rgba;
Shinya Kitaoka 120a6e
  const int pixsize = height * width;
Shinya Kitaoka 120a6e
  const int r_max   = std::numeric_limits<rt>::max();</rt>
Shinya Kitaoka 120a6e
  for (int ii = 0; ii < pixsize; ++ii, image_array += channels) {
Shinya Kitaoka 120a6e
    const double rr1 = (double)(image_array[red]) / maxi;
Shinya Kitaoka 120a6e
    const double gg1 = (double)(image_array[gre]) / maxi;
Shinya Kitaoka 120a6e
    const double bb1 = (double)(image_array[blu]) / maxi;
Shinya Kitaoka 120a6e
    const double aa1 = (double)(image_array[alp]) / maxi;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    double rr2 = accum_by_trans_(rr1, 1.0 - aa1, integer_part, fractional_part);
Shinya Kitaoka 120a6e
    double gg2 = accum_by_trans_(gg1, 1.0 - aa1, integer_part, fractional_part);
Shinya Kitaoka 120a6e
    double bb2 = accum_by_trans_(bb1, 1.0 - aa1, integer_part, fractional_part);
Shinya Kitaoka 120a6e
    double aa2 = accum_by_trans_(aa1, 1.0 - aa1, integer_part, fractional_part);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    /* 参照画像あればピクセル単位の画像変化 */
Shinya Kitaoka 120a6e
    if (ref != 0) {
Shinya Kitaoka 120a6e
      const double refv = igs::color::ref_value(ref, channels, r_max, ref_mode);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      ref += channels; /* continue;の前に行うこと */
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      rr2 = (rr2 - rr1) * refv + rr1;
Shinya Kitaoka 120a6e
      gg2 = (gg2 - gg1) * refv + gg1;
Shinya Kitaoka 120a6e
      bb2 = (bb2 - bb1) * refv + bb1;
Shinya Kitaoka 120a6e
      aa2 = (aa2 - aa1) * refv + aa1;
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    image_array[red] = static_cast<it>(rr2 * (maxi + 0.999999));</it>
Shinya Kitaoka 120a6e
    image_array[gre] = static_cast<it>(gg2 * (maxi + 0.999999));</it>
Shinya Kitaoka 120a6e
    image_array[blu] = static_cast<it>(bb2 * (maxi + 0.999999));</it>
Shinya Kitaoka 120a6e
    image_array[alp] = static_cast<it>(aa2 * (maxi + 0.999999));</it>
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
#include <stdexcept> /* std::domain_error(-) */</stdexcept>
Toshihiro Shimizu 890ddd
void igs::density::change(
Shinya Kitaoka 120a6e
    unsigned char *image_array /* RGBAでなければならない */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int height, const int width,
Shinya Kitaoka 120a6e
    const int channels /* 4(=RGBAでなければならない) */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int bits
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const unsigned char *ref /* 求める画像と同じ高、幅、ch数 */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int ref_bits /* refがゼロのときはここもゼロ */
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const int ref_mode /* 0=R,1=G,2=B,3=A,4=Luminance,5=Nothing */
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    ,
Shinya Kitaoka 120a6e
    const double density) {
Shinya Kitaoka 120a6e
  if (igs::image::rgba::siz != channels) {
Shinya Kitaoka 120a6e
    throw std::domain_error("Bad channels,Not rgba");
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
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
    change_template_(image_array, height, width, channels, ref, ref_mode,
Shinya Kitaoka 120a6e
                     density);
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
    change_template_(reinterpret_cast<unsigned *="" short="">(image_array), height,</unsigned>
Shinya Kitaoka 120a6e
                     width, channels, ref, ref_mode, density);
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
    change_template_(reinterpret_cast<unsigned *="" short="">(image_array), height,</unsigned>
Shinya Kitaoka 120a6e
                     width, channels,
Shinya Kitaoka 120a6e
                     reinterpret_cast<const *="" short="" unsigned="">(ref), ref_mode,</const>
Shinya Kitaoka 120a6e
                     density);
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
    change_template_(image_array, height, width, channels,
Shinya Kitaoka 120a6e
                     reinterpret_cast<const *="" short="" unsigned="">(ref), ref_mode,</const>
Shinya Kitaoka 120a6e
                     density);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    throw std::domain_error("Bad bits,Not uchar/ushort");
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}