tahoma2d/toonz/sources/stdfx/igs_level_auto_in_camera.cpp
luz paz 35e409e926 fix various typos
Found via `codespell -q 3 -S *.ts,thirdparty, -L appy,ba,inbetween,inout,pevent,possibile,upto`
2021-08-31 11:10:50 -04:00

207 lines
7.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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