|
Shinya Kitaoka |
120a6e |
#include <cmath> // pow(-)</cmath>
|
|
Toshihiro Shimizu |
890ddd |
#include <stdexcept> /* std::domain_error(-) */</stdexcept>
|
|
Shinya Kitaoka |
120a6e |
#include <limits> // std::numeric_limits</limits>
|
|
Toshihiro Shimizu |
890ddd |
#include <vector></vector>
|
|
Toshihiro Shimizu |
890ddd |
#include "igs_level_auto.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "igs_ifx_common.h" /* igs::image::rgba */
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------
|
|
Shinya Kitaoka |
120a6e |
namespace {
|
|
Shinya Kitaoka |
120a6e |
double level_value_(double value, double mul_max, bool act_sw, double in_min,
|
|
Shinya Kitaoka |
120a6e |
double in_max, double out_min, double out_max,
|
|
Shinya Kitaoka |
120a6e |
double gamma) {
|
|
Shinya Kitaoka |
120a6e |
if (act_sw) {
|
|
Shinya Kitaoka |
120a6e |
if (in_max == in_min) {
|
|
Shinya Kitaoka |
120a6e |
value = in_max;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
/* 制限(in_min〜in_max) */
|
|
Shinya Kitaoka |
120a6e |
if (in_min < in_max) {
|
|
Shinya Kitaoka |
120a6e |
if (value < in_min) {
|
|
Shinya Kitaoka |
120a6e |
value = in_min;
|
|
Shinya Kitaoka |
120a6e |
} else if (in_max < value) {
|
|
Shinya Kitaoka |
120a6e |
value = in_max;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if (value < in_max) {
|
|
Shinya Kitaoka |
120a6e |
value = in_max;
|
|
Shinya Kitaoka |
120a6e |
} else if (in_min < value) {
|
|
Shinya Kitaoka |
120a6e |
value = in_min;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
/* 正規化(0〜1) */
|
|
Shinya Kitaoka |
120a6e |
value = (value - in_min) / (in_max - in_min);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
/* Gamma変換 */
|
|
Shinya Kitaoka |
120a6e |
if ((1.0 != gamma) && (0.0 != gamma)) {
|
|
Shinya Kitaoka |
120a6e |
value = pow(value, 1.0 / gamma);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
/* Outputの範囲にスケール変換 */
|
|
Shinya Kitaoka |
120a6e |
value = out_min + value * (out_max - out_min);
|
|
Shinya Kitaoka |
120a6e |
/* 0...1の間で制限かける */
|
|
Shinya Kitaoka |
120a6e |
if (value < 0.0) {
|
|
Shinya Kitaoka |
120a6e |
value = 0.0;
|
|
Shinya Kitaoka |
120a6e |
} else if (1.0 < value) {
|
|
Shinya Kitaoka |
120a6e |
value = 1.0;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
/* 0〜1.0 --> 0〜mul_maxスケール変換し、整数値化 */
|
|
Shinya Kitaoka |
120a6e |
return floor(value * mul_max);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------
|
|
Shinya Kitaoka |
120a6e |
void level_ctable_template_(const unsigned int channels,
|
|
Shinya Kitaoka |
120a6e |
const bool *act_sw, // user setting
|
|
Shinya Kitaoka |
120a6e |
const int *in_min, // image pixel value
|
|
Shinya Kitaoka |
120a6e |
const int *in_max, // image pixel value
|
|
Shinya Kitaoka |
120a6e |
const double *in_min_shift, // user settting
|
|
Shinya Kitaoka |
120a6e |
const double *in_max_shift, // user settting
|
|
Shinya Kitaoka |
120a6e |
const double *out_min, // user settting
|
|
Shinya Kitaoka |
120a6e |
const double *out_max, // user settting
|
|
Shinya Kitaoka |
120a6e |
const double *gamma, // user settting
|
|
Shinya Kitaoka |
120a6e |
const unsigned int div_num,
|
|
Shinya Kitaoka |
120a6e |
std::vector<std::vector<unsigned int="">> &table_array</std::vector<unsigned>
|
|
Shinya Kitaoka |
120a6e |
/*
|
|
Shinya Kitaoka |
120a6e |
std::vector< std::vector<t> > &table_array</t>
|
|
Shinya Kitaoka |
120a6e |
とするとvc2005mdで他プログラムとのリンク時、
|
|
Shinya Kitaoka |
120a6e |
allocatorの2重定義でエラーとなる。
|
|
Shinya Kitaoka |
120a6e |
std::vector< std::vector<unsigned int=""> >&table_array</unsigned>
|
|
Shinya Kitaoka |
120a6e |
ならOK
|
|
Shinya Kitaoka |
120a6e |
2009-01-27
|
|
Shinya Kitaoka |
120a6e |
*/
|
|
Shinya Kitaoka |
120a6e |
) {
|
|
Shinya Kitaoka |
120a6e |
const double div_val = static_cast<double>(div_num);</double>
|
|
Shinya Kitaoka |
120a6e |
const double mul_val = div_val + 0.999999;
|
|
Shinya Kitaoka |
120a6e |
#if defined _WIN32 // vc compile_type
|
|
Shinya Kitaoka |
120a6e |
double in_min_[4], in_max_[4];
|
|
Toshihiro Shimizu |
890ddd |
#else
|
|
Shinya Kitaoka |
120a6e |
double in_min_[channels], in_max_[channels];
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Shinya Kitaoka |
120a6e |
for (unsigned int cc = 0; cc < channels; ++cc) {
|
|
Shinya Kitaoka |
120a6e |
in_min_[cc] = in_min_shift[cc] + in_min[cc] / div_val;
|
|
Shinya Kitaoka |
120a6e |
in_max_[cc] = in_max_shift[cc] + in_max[cc] / div_val;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
table_array.resize(channels);
|
|
Shinya Kitaoka |
120a6e |
for (unsigned int cc = 0; cc < channels; ++cc) {
|
|
Shinya Kitaoka |
120a6e |
table_array[cc].resize(div_num + 1);
|
|
Shinya Kitaoka |
120a6e |
for (unsigned int yy = 0; yy <= div_num; ++yy) {
|
|
Shinya Kitaoka |
120a6e |
table_array[cc][yy] = static_cast<unsigned int="">(</unsigned>
|
|
Shinya Kitaoka |
120a6e |
level_value_(yy / div_val, mul_val, act_sw[cc], in_min_[cc],
|
|
Shinya Kitaoka |
120a6e |
in_max_[cc], out_min[cc], out_max[cc], gamma[cc]));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
template <class t=""></class>
|
|
Shinya Kitaoka |
120a6e |
void change_template_(T *image_array, const int height, const int width,
|
|
Shinya Kitaoka |
120a6e |
const int channels,
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
const bool *act_sw, const double *in_min_shift,
|
|
Shinya Kitaoka |
120a6e |
const double *in_max_shift, const double *out_min,
|
|
Shinya Kitaoka |
120a6e |
const double *out_max, const double *gamma) {
|
|
Toshihiro Shimizu |
890ddd |
/* 1.まず最大値、最小値を求める */
|
|
Toshihiro Shimizu |
890ddd |
#if defined _WIN32
|
|
Shinya Kitaoka |
120a6e |
int in_min[4], in_max[4];
|
|
Toshihiro Shimizu |
890ddd |
#else
|
|
Shinya Kitaoka |
120a6e |
int in_min[channels], in_max[channels];
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Shinya Kitaoka |
120a6e |
for (int zz = 0; zz < channels; ++zz) {
|
|
Shinya Kitaoka |
120a6e |
in_min[zz] = in_max[zz] = image_array[zz];
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
T *image_crnt = image_array;
|
|
Shinya Kitaoka |
120a6e |
for (int yy = 0; yy < height; ++yy) {
|
|
Shinya Kitaoka |
120a6e |
for (int xx = 0; xx < width; ++xx) {
|
|
Shinya Kitaoka |
120a6e |
for (int zz = 0; zz < channels; ++zz) {
|
|
Shinya Kitaoka |
120a6e |
if (image_crnt[zz] < in_min[zz]) {
|
|
Shinya Kitaoka |
120a6e |
in_min[zz] = image_crnt[zz];
|
|
Shinya Kitaoka |
120a6e |
} else if (in_max[zz] < image_crnt[zz]) {
|
|
Shinya Kitaoka |
120a6e |
in_max[zz] = image_crnt[zz];
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
image_crnt += channels;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
/* 2.最大値、最小値から変換テーブルを求める */
|
|
Shinya Kitaoka |
120a6e |
std::vector<std::vector<unsigned int="">> table_array;</std::vector<unsigned>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
level_ctable_template_(channels, act_sw, in_min, in_max, in_min_shift,
|
|
Shinya Kitaoka |
120a6e |
in_max_shift, out_min, out_max, gamma,
|
|
Shinya Kitaoka |
120a6e |
std::numeric_limits<t>::max(), table_array);</t>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
/* 3.変換テーブルを使ってlevel変換する */
|
|
Shinya Kitaoka |
120a6e |
image_crnt = image_array;
|
|
Shinya Kitaoka |
120a6e |
const int pixsize = height * width;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (igs::image::rgba::siz == channels) {
|
|
Shinya Kitaoka |
120a6e |
using namespace igs::image::rgba;
|
|
Shinya Kitaoka |
120a6e |
for (int ii = 0; ii < pixsize; ++ii, image_crnt += channels) {
|
|
Shinya Kitaoka |
120a6e |
image_crnt[red] = static_cast<t>(table_array[0][image_crnt[red]]);</t>
|
|
Shinya Kitaoka |
120a6e |
image_crnt[gre] = static_cast<t>(table_array[1][image_crnt[gre]]);</t>
|
|
Shinya Kitaoka |
120a6e |
image_crnt[blu] = static_cast<t>(table_array[2][image_crnt[blu]]);</t>
|
|
Shinya Kitaoka |
120a6e |
image_crnt[alp] = static_cast<t>(table_array[3][image_crnt[alp]]);</t>
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else if (igs::image::rgb::siz == channels) {
|
|
Shinya Kitaoka |
120a6e |
using namespace igs::image::rgb;
|
|
Shinya Kitaoka |
120a6e |
for (int ii = 0; ii < pixsize; ++ii, image_crnt += channels) {
|
|
Shinya Kitaoka |
120a6e |
image_crnt[red] = static_cast<t>(table_array[0][image_crnt[red]]);</t>
|
|
Shinya Kitaoka |
120a6e |
image_crnt[gre] = static_cast<t>(table_array[1][image_crnt[gre]]);</t>
|
|
Shinya Kitaoka |
120a6e |
image_crnt[blu] = static_cast<t>(table_array[2][image_crnt[blu]]);</t>
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else if (1 == channels) { /* grayscale */
|
|
Shinya Kitaoka |
120a6e |
for (int ii = 0; ii < pixsize; ++ii, ++image_crnt) {
|
|
Shinya Kitaoka |
120a6e |
image_crnt[0] = static_cast<t>(table_array[0][image_crnt[0]]);</t>
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
table_array.clear();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void igs::level_auto::change(unsigned char *image_array,
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
const int height, const int width,
|
|
Shinya Kitaoka |
120a6e |
const int channels, const int bits,
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
const bool *act_sw, // channels array
|
|
Shinya Kitaoka |
120a6e |
const double *in_min_shift, // channels array
|
|
Shinya Kitaoka |
120a6e |
const double *in_max_shift, // channels array
|
|
Shinya Kitaoka |
120a6e |
const double *out_min, // channels array
|
|
Shinya Kitaoka |
120a6e |
const double *out_max, // channels array
|
|
Shinya Kitaoka |
120a6e |
const double *gamma // channels array
|
|
Shinya Kitaoka |
120a6e |
) {
|
|
Shinya Kitaoka |
120a6e |
if ((igs::image::rgba::siz != channels) &&
|
|
Shinya Kitaoka |
120a6e |
(igs::image::rgb::siz != channels) && (1 != channels) /* grayscale */
|
|
Shinya Kitaoka |
120a6e |
) {
|
|
Shinya Kitaoka |
120a6e |
throw std::domain_error("Bad channels,Not rgba/rgb/grayscale");
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (std::numeric_limits<unsigned char="">::digits == bits) {</unsigned>
|
|
Shinya Kitaoka |
120a6e |
change_template_(image_array, height, width, channels, act_sw, in_min_shift,
|
|
Shinya Kitaoka |
120a6e |
in_max_shift, out_min, out_max, gamma);
|
|
Shinya Kitaoka |
120a6e |
} else if (std::numeric_limits<unsigned short="">::digits == bits) {</unsigned>
|
|
Shinya Kitaoka |
120a6e |
change_template_(reinterpret_cast<unsigned *="" short="">(image_array), height,</unsigned>
|
|
Shinya Kitaoka |
120a6e |
width, channels, act_sw, in_min_shift, in_max_shift,
|
|
Shinya Kitaoka |
120a6e |
out_min, out_max, gamma);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
throw std::domain_error("Bad bits,Not uchar/ushort");
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|