|
Toshihiro Shimizu |
890ddd |
#include "tenv.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tsystem.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "ino_common.h"
|
|
shun-iwasawa |
e00258 |
#include "tfxparam.h"
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
#include <sstream> /* std::ostringstream */</sstream>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/* copy and paste from
|
|
Toshihiro Shimizu |
890ddd |
igs_ifx_common.h */
|
|
Shinya Kitaoka |
120a6e |
namespace igs {
|
|
Shinya Kitaoka |
120a6e |
namespace image {
|
|
Shinya Kitaoka |
120a6e |
namespace rgba {
|
|
Shinya Kitaoka |
120a6e |
enum num { blu = 0, gre, red, alp, siz };
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
shun-iwasawa |
e00258 |
} // namespace image
|
|
shun-iwasawa |
e00258 |
} // namespace igs
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------
|
|
Shinya Kitaoka |
120a6e |
namespace {
|
|
Toshihiro Shimizu |
890ddd |
// T is TPixel32 or TPixel64
|
|
Toshihiro Shimizu |
890ddd |
// U is unsigned char or unsigned short
|
|
Toshihiro Shimizu |
890ddd |
template <class class="" t,="" u=""></class>
|
|
shun-iwasawa |
e00258 |
void ras_to_arr_(const TRasterPT<t> ras, U* arr, const int channels) {</t>
|
|
Shinya Kitaoka |
120a6e |
using namespace igs::image::rgba;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
for (int yy = 0; yy < ras->getLy(); ++yy) {
|
|
shun-iwasawa |
e00258 |
const T* ras_sl = ras->pixels(yy);
|
|
Shinya Kitaoka |
120a6e |
for (int xx = 0; xx < ras->getLx(); ++xx, arr += channels) {
|
|
Shinya Kitaoka |
120a6e |
if (red < channels) {
|
|
Shinya Kitaoka |
120a6e |
arr[red] = ras_sl[xx].r;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (gre < channels) {
|
|
Shinya Kitaoka |
120a6e |
arr[gre] = ras_sl[xx].g;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (blu < channels) {
|
|
Shinya Kitaoka |
120a6e |
arr[blu] = ras_sl[xx].b;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (alp < channels) {
|
|
Shinya Kitaoka |
120a6e |
arr[alp] = ras_sl[xx].m;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
shun-iwasawa |
0e1837 |
|
|
shun-iwasawa |
481b59 |
// T is TPixel32, TPixel64 or TPixelF
|
|
shun-iwasawa |
0e1837 |
// normalize to 0.0 - 1.0
|
|
shun-iwasawa |
0e1837 |
template <class t=""></class>
|
|
shun-iwasawa |
0e1837 |
void ras_to_float_arr_(const TRasterPT<t> ras, float* arr, const int channels) {</t>
|
|
shun-iwasawa |
0e1837 |
using namespace igs::image::rgba;
|
|
shun-iwasawa |
0e1837 |
float fac = 1.f / (float)T::maxChannelValue;
|
|
shun-iwasawa |
0e1837 |
for (int yy = 0; yy < ras->getLy(); ++yy) {
|
|
shun-iwasawa |
0e1837 |
const T* ras_sl = ras->pixels(yy);
|
|
shun-iwasawa |
0e1837 |
for (int xx = 0; xx < ras->getLx(); ++xx, arr += channels) {
|
|
shun-iwasawa |
0e1837 |
if (red < channels) {
|
|
shun-iwasawa |
0e1837 |
arr[red] = (float)ras_sl[xx].r * fac;
|
|
shun-iwasawa |
0e1837 |
}
|
|
shun-iwasawa |
0e1837 |
if (gre < channels) {
|
|
shun-iwasawa |
0e1837 |
arr[gre] = (float)ras_sl[xx].g * fac;
|
|
shun-iwasawa |
0e1837 |
}
|
|
shun-iwasawa |
0e1837 |
if (blu < channels) {
|
|
shun-iwasawa |
0e1837 |
arr[blu] = (float)ras_sl[xx].b * fac;
|
|
shun-iwasawa |
0e1837 |
}
|
|
shun-iwasawa |
0e1837 |
if (alp < channels) {
|
|
shun-iwasawa |
0e1837 |
arr[alp] = (float)ras_sl[xx].m * fac;
|
|
shun-iwasawa |
0e1837 |
}
|
|
shun-iwasawa |
0e1837 |
}
|
|
shun-iwasawa |
0e1837 |
}
|
|
shun-iwasawa |
0e1837 |
}
|
|
shun-iwasawa |
0e1837 |
|
|
Toshihiro Shimizu |
890ddd |
template <class class="" t="" u,=""></class>
|
|
shun-iwasawa |
e00258 |
void arr_to_ras_(const U* arr, const int channels, TRasterPT<t> ras,</t>
|
|
Shinya Kitaoka |
120a6e |
const int margin // default is 0
|
|
shun-iwasawa |
e00258 |
) {
|
|
Shinya Kitaoka |
120a6e |
arr +=
|
|
Shinya Kitaoka |
120a6e |
(ras->getLx() + margin + margin) * margin * channels + margin * channels;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
using namespace igs::image::rgba;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
for (int yy = 0; yy < ras->getLy();
|
|
Shinya Kitaoka |
120a6e |
++yy, arr += (ras->getLx() + margin + margin) * channels) {
|
|
shun-iwasawa |
e00258 |
const U* arrx = arr;
|
|
shun-iwasawa |
e00258 |
T* ras_sl = ras->pixels(yy);
|
|
Shinya Kitaoka |
120a6e |
for (int xx = 0; xx < ras->getLx(); ++xx, arrx += channels) {
|
|
Shinya Kitaoka |
120a6e |
if (red < channels) {
|
|
Shinya Kitaoka |
120a6e |
ras_sl[xx].r = arrx[red];
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (gre < channels) {
|
|
Shinya Kitaoka |
120a6e |
ras_sl[xx].g = arrx[gre];
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (blu < channels) {
|
|
Shinya Kitaoka |
120a6e |
ras_sl[xx].b = arrx[blu];
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (alp < channels) {
|
|
Shinya Kitaoka |
120a6e |
ras_sl[xx].m = arrx[alp];
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
shun-iwasawa |
0e1837 |
|
|
shun-iwasawa |
0e1837 |
template <class t=""></class>
|
|
shun-iwasawa |
0e1837 |
void float_arr_to_ras_(const float* arr, const int channels, TRasterPT<t> ras,</t>
|
|
shun-iwasawa |
0e1837 |
const int margin // default is 0
|
|
shun-iwasawa |
0e1837 |
) {
|
|
shun-iwasawa |
0e1837 |
arr +=
|
|
shun-iwasawa |
0e1837 |
(ras->getLx() + margin + margin) * margin * channels + margin * channels;
|
|
shun-iwasawa |
0e1837 |
|
|
shun-iwasawa |
0e1837 |
using namespace igs::image::rgba;
|
|
shun-iwasawa |
0e1837 |
float fac = (float)T::maxChannelValue;
|
|
shun-iwasawa |
0e1837 |
|
|
shun-iwasawa |
0e1837 |
for (int yy = 0; yy < ras->getLy();
|
|
shun-iwasawa |
0e1837 |
++yy, arr += (ras->getLx() + margin + margin) * channels) {
|
|
shun-iwasawa |
0e1837 |
const float* arrx = arr;
|
|
shun-iwasawa |
0e1837 |
T* ras_sl = ras->pixels(yy);
|
|
shun-iwasawa |
0e1837 |
for (int xx = 0; xx < ras->getLx(); ++xx, arrx += channels) {
|
|
shun-iwasawa |
0e1837 |
if (red < channels) {
|
|
shun-iwasawa |
481b59 |
ras_sl[xx].r =
|
|
shun-iwasawa |
481b59 |
(arrx[red] >= 1.f) ? T::maxChannelValue
|
|
shun-iwasawa |
481b59 |
: (arrx[red] <= 0.f)
|
|
shun-iwasawa |
481b59 |
? (typename T::Channel)0
|
|
shun-iwasawa |
481b59 |
: (typename T::Channel)(std::round(arrx[red] * fac + 0.5f));
|
|
shun-iwasawa |
0e1837 |
}
|
|
shun-iwasawa |
0e1837 |
if (gre < channels) {
|
|
shun-iwasawa |
481b59 |
ras_sl[xx].g =
|
|
shun-iwasawa |
481b59 |
(arrx[gre] >= 1.f) ? T::maxChannelValue
|
|
shun-iwasawa |
481b59 |
: (arrx[gre] <= 0.f)
|
|
shun-iwasawa |
481b59 |
? (typename T::Channel)0
|
|
shun-iwasawa |
481b59 |
: (typename T::Channel)(std::round(arrx[gre] * fac + 0.5f));
|
|
shun-iwasawa |
0e1837 |
}
|
|
shun-iwasawa |
0e1837 |
if (blu < channels) {
|
|
shun-iwasawa |
481b59 |
ras_sl[xx].b =
|
|
shun-iwasawa |
481b59 |
(arrx[blu] >= 1.f) ? T::maxChannelValue
|
|
shun-iwasawa |
481b59 |
: (arrx[blu] <= 0.f)
|
|
shun-iwasawa |
481b59 |
? (typename T::Channel)0
|
|
shun-iwasawa |
481b59 |
: (typename T::Channel)(std::round(arrx[blu] * fac + 0.5f));
|
|
shun-iwasawa |
0e1837 |
}
|
|
shun-iwasawa |
0e1837 |
if (alp < channels) {
|
|
shun-iwasawa |
481b59 |
ras_sl[xx].m =
|
|
shun-iwasawa |
481b59 |
(arrx[alp] >= 1.f) ? T::maxChannelValue
|
|
shun-iwasawa |
481b59 |
: (arrx[alp] <= 0.f)
|
|
shun-iwasawa |
481b59 |
? (typename T::Channel)0
|
|
shun-iwasawa |
481b59 |
: (typename T::Channel)(std::round(arrx[alp] * fac + 0.5f));
|
|
shun-iwasawa |
0e1837 |
}
|
|
shun-iwasawa |
0e1837 |
}
|
|
shun-iwasawa |
0e1837 |
}
|
|
shun-iwasawa |
0e1837 |
}
|
|
shun-iwasawa |
0e1837 |
|
|
shun-iwasawa |
481b59 |
template <>
|
|
shun-iwasawa |
481b59 |
void float_arr_to_ras_<tpixelf>(const float* arr, const int channels,</tpixelf>
|
|
shun-iwasawa |
481b59 |
TRasterFP ras,
|
|
shun-iwasawa |
481b59 |
const int margin // default is 0
|
|
shun-iwasawa |
481b59 |
) {
|
|
shun-iwasawa |
481b59 |
arr +=
|
|
shun-iwasawa |
481b59 |
(ras->getLx() + margin + margin) * margin * channels + margin * channels;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
using namespace igs::image::rgba;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
for (int yy = 0; yy < ras->getLy();
|
|
shun-iwasawa |
481b59 |
++yy, arr += (ras->getLx() + margin + margin) * channels) {
|
|
shun-iwasawa |
481b59 |
const float* arrx = arr;
|
|
shun-iwasawa |
481b59 |
TPixelF* ras_sl = ras->pixels(yy);
|
|
shun-iwasawa |
481b59 |
for (int xx = 0; xx < ras->getLx(); ++xx, arrx += channels) {
|
|
shun-iwasawa |
481b59 |
if (red < channels) ras_sl[xx].r = arrx[red];
|
|
shun-iwasawa |
481b59 |
if (gre < channels) ras_sl[xx].g = arrx[gre];
|
|
shun-iwasawa |
481b59 |
if (blu < channels) ras_sl[xx].b = arrx[blu];
|
|
shun-iwasawa |
481b59 |
if (alp < channels) ras_sl[xx].m = arrx[alp];
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
0e1837 |
template <class t=""></class>
|
|
shun-iwasawa |
0e1837 |
float getFactor() {
|
|
shun-iwasawa |
0e1837 |
return 1.f / (float)T::maxChannelValue;
|
|
shun-iwasawa |
0e1837 |
}
|
|
shun-iwasawa |
0e1837 |
|
|
shun-iwasawa |
481b59 |
template <>
|
|
shun-iwasawa |
481b59 |
float getFactor<tpixelf>() {</tpixelf>
|
|
shun-iwasawa |
481b59 |
return 1.f;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
// T is either TPixel32, TPixel64, or TPixelF
|
|
shun-iwasawa |
0e1837 |
template <class t=""></class>
|
|
shun-iwasawa |
0e1837 |
void ras_to_ref_float_arr_(const TRasterPT<t> ras, float* arr,</t>
|
|
shun-iwasawa |
0e1837 |
const int refer_mode) {
|
|
shun-iwasawa |
0e1837 |
float fac = getFactor<t>();</t>
|
|
shun-iwasawa |
0e1837 |
for (int yy = 0; yy < ras->getLy(); ++yy) {
|
|
shun-iwasawa |
0e1837 |
const T* ras_sl = ras->pixels(yy);
|
|
shun-iwasawa |
0e1837 |
for (int xx = 0; xx < ras->getLx(); ++xx, arr++, ras_sl++) {
|
|
shun-iwasawa |
0e1837 |
switch (refer_mode) {
|
|
shun-iwasawa |
0e1837 |
case 0:
|
|
shun-iwasawa |
0e1837 |
*arr = static_cast<float>(ras_sl->r) * fac;</float>
|
|
shun-iwasawa |
0e1837 |
break;
|
|
shun-iwasawa |
0e1837 |
case 1:
|
|
shun-iwasawa |
0e1837 |
*arr = static_cast<float>(ras_sl->g) * fac;</float>
|
|
shun-iwasawa |
0e1837 |
break;
|
|
shun-iwasawa |
0e1837 |
case 2:
|
|
shun-iwasawa |
0e1837 |
*arr = static_cast<float>(ras_sl->b) * fac;</float>
|
|
shun-iwasawa |
0e1837 |
break;
|
|
shun-iwasawa |
0e1837 |
case 3:
|
|
shun-iwasawa |
0e1837 |
*arr = static_cast<float>(ras_sl->m) * fac;</float>
|
|
shun-iwasawa |
0e1837 |
break;
|
|
shun-iwasawa |
0e1837 |
case 4:
|
|
shun-iwasawa |
0e1837 |
*arr = /* 輝度(Luminance)(CCIR Rec.601) */
|
|
shun-iwasawa |
0e1837 |
(0.298912f * static_cast<float>(ras_sl->r) +</float>
|
|
shun-iwasawa |
0e1837 |
0.586611f * static_cast<float>(ras_sl->g) +</float>
|
|
shun-iwasawa |
0e1837 |
0.114478f * static_cast<float>(ras_sl->b)) *</float>
|
|
shun-iwasawa |
0e1837 |
fac;
|
|
shun-iwasawa |
0e1837 |
break;
|
|
shun-iwasawa |
0e1837 |
}
|
|
shun-iwasawa |
481b59 |
// clamp 0.f to 1.f in case computing TPixelF
|
|
shun-iwasawa |
481b59 |
*arr = std::min(1.f, std::max(0.f, *arr));
|
|
shun-iwasawa |
0e1837 |
}
|
|
shun-iwasawa |
0e1837 |
}
|
|
shun-iwasawa |
0e1837 |
}
|
|
shun-iwasawa |
0e1837 |
|
|
shun-iwasawa |
e00258 |
} // namespace
|
|
Toshihiro Shimizu |
890ddd |
//--------------------
|
|
Shinya Kitaoka |
120a6e |
void ino::ras_to_arr(const TRasterP in_ras, const int channels,
|
|
shun-iwasawa |
e00258 |
unsigned char* out_arr) {
|
|
Shinya Kitaoka |
120a6e |
if ((TRaster32P)in_ras) {
|
|
Shinya Kitaoka |
120a6e |
ras_to_arr_<tpixel32, char="" unsigned="">(in_ras, out_arr, channels);</tpixel32,>
|
|
Shinya Kitaoka |
120a6e |
} else if ((TRaster64P)in_ras) {
|
|
Shinya Kitaoka |
120a6e |
ras_to_arr_<tpixel64, short="" unsigned="">(</tpixel64,>
|
|
shun-iwasawa |
e00258 |
in_ras, reinterpret_cast<unsigned short*="">(out_arr), channels);</unsigned>
|
|
shun-iwasawa |
481b59 |
} else if ((TRasterFP)in_ras) {
|
|
shun-iwasawa |
481b59 |
ras_to_float_arr(in_ras, channels, reinterpret_cast<float*>(out_arr));</float*>
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
shun-iwasawa |
0e1837 |
void ino::ras_to_float_arr(const TRasterP in_ras, const int channels,
|
|
shun-iwasawa |
0e1837 |
float* out_arr) {
|
|
shun-iwasawa |
0e1837 |
if ((TRaster32P)in_ras) {
|
|
shun-iwasawa |
0e1837 |
ras_to_float_arr_<tpixel32>(in_ras, out_arr, channels);</tpixel32>
|
|
shun-iwasawa |
0e1837 |
} else if ((TRaster64P)in_ras) {
|
|
shun-iwasawa |
0e1837 |
ras_to_float_arr_<tpixel64>(in_ras, out_arr, channels);</tpixel64>
|
|
shun-iwasawa |
481b59 |
} else if ((TRasterFP)in_ras) {
|
|
shun-iwasawa |
481b59 |
ras_to_float_arr_<tpixelf>(in_ras, out_arr, channels);</tpixelf>
|
|
shun-iwasawa |
0e1837 |
}
|
|
shun-iwasawa |
0e1837 |
}
|
|
shun-iwasawa |
e00258 |
void ino::arr_to_ras(const unsigned char* in_arr, const int channels,
|
|
Shinya Kitaoka |
120a6e |
TRasterP out_ras, const int margin) {
|
|
Shinya Kitaoka |
120a6e |
if ((TRaster32P)out_ras) {
|
|
Shinya Kitaoka |
120a6e |
arr_to_ras_<unsigned char,="" tpixel32="">(in_arr, channels, out_ras, margin);</unsigned>
|
|
Shinya Kitaoka |
120a6e |
} else if ((TRaster64P)out_ras) {
|
|
Shinya Kitaoka |
120a6e |
arr_to_ras_<unsigned short,="" tpixel64="">(</unsigned>
|
|
shun-iwasawa |
e00258 |
reinterpret_cast<const short*="" unsigned="">(in_arr), channels, out_ras,</const>
|
|
Shinya Kitaoka |
120a6e |
margin);
|
|
shun-iwasawa |
481b59 |
} else if ((TRasterFP)out_ras) {
|
|
shun-iwasawa |
481b59 |
arr_to_ras_<float, tpixelf="">(reinterpret_cast<const float*="">(in_arr),</const></float,>
|
|
shun-iwasawa |
481b59 |
channels, out_ras, margin);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
shun-iwasawa |
0e1837 |
void ino::float_arr_to_ras(const unsigned char* in_arr, const int channels,
|
|
shun-iwasawa |
0e1837 |
TRasterP out_ras, const int margin) {
|
|
shun-iwasawa |
0e1837 |
if ((TRaster32P)out_ras) {
|
|
shun-iwasawa |
0e1837 |
float_arr_to_ras_<tpixel32>(reinterpret_cast<const float*="">(in_arr),</const></tpixel32>
|
|
shun-iwasawa |
0e1837 |
channels, out_ras, margin);
|
|
shun-iwasawa |
0e1837 |
} else if ((TRaster64P)out_ras) {
|
|
shun-iwasawa |
0e1837 |
float_arr_to_ras_<tpixel64>(reinterpret_cast<const float*="">(in_arr),</const></tpixel64>
|
|
shun-iwasawa |
0e1837 |
channels, out_ras, margin);
|
|
shun-iwasawa |
481b59 |
} else if ((TRasterFP)out_ras) {
|
|
shun-iwasawa |
481b59 |
float_arr_to_ras_<tpixelf>(reinterpret_cast<const float*="">(in_arr), channels,</const></tpixelf>
|
|
shun-iwasawa |
481b59 |
out_ras, margin);
|
|
shun-iwasawa |
0e1837 |
}
|
|
shun-iwasawa |
0e1837 |
}
|
|
Toshihiro Shimizu |
890ddd |
//--------------------
|
|
Shinya Kitaoka |
120a6e |
void ino::ras_to_vec(const TRasterP in_ras, const int channels,
|
|
shun-iwasawa |
e00258 |
std::vector<unsigned char="">& out_vec) {</unsigned>
|
|
Shinya Kitaoka |
120a6e |
out_vec.resize(
|
|
Shinya Kitaoka |
120a6e |
in_ras->getLy() * in_ras->getLx() * channels *
|
|
Shinya Kitaoka |
120a6e |
(((TRaster64P)in_ras) ? sizeof(unsigned short) : sizeof(unsigned char)));
|
|
Shinya Kitaoka |
120a6e |
ino::ras_to_arr(in_ras, channels, &out_vec.at(0));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
shun-iwasawa |
e00258 |
void ino::vec_to_ras(std::vector<unsigned char="">& in_vec, const int channels,</unsigned>
|
|
Shinya Kitaoka |
120a6e |
TRasterP out_ras, const int margin // default is 0
|
|
shun-iwasawa |
e00258 |
) {
|
|
Shinya Kitaoka |
120a6e |
ino::arr_to_ras(&in_vec.at(0), channels, out_ras, margin);
|
|
Shinya Kitaoka |
120a6e |
in_vec.clear();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
//--------------------
|
|
shun-iwasawa |
0e1837 |
|
|
shun-iwasawa |
0e1837 |
void ino::ras_to_ref_float_arr(const TRasterP in_ras, float* out_arr,
|
|
shun-iwasawa |
0e1837 |
const int refer_mode) {
|
|
shun-iwasawa |
0e1837 |
if ((TRaster32P)in_ras) {
|
|
shun-iwasawa |
0e1837 |
ras_to_ref_float_arr_<tpixel32>(in_ras, out_arr, refer_mode);</tpixel32>
|
|
shun-iwasawa |
0e1837 |
} else if ((TRaster64P)in_ras) {
|
|
shun-iwasawa |
0e1837 |
ras_to_ref_float_arr_<tpixel64>(in_ras, out_arr, refer_mode);</tpixel64>
|
|
shun-iwasawa |
481b59 |
} else if ((TRasterFP)in_ras) {
|
|
shun-iwasawa |
481b59 |
ras_to_ref_float_arr_<tpixelf>(in_ras, out_arr, refer_mode);</tpixelf>
|
|
shun-iwasawa |
0e1837 |
}
|
|
shun-iwasawa |
0e1837 |
}
|
|
shun-iwasawa |
0e1837 |
|
|
shun-iwasawa |
0e1837 |
//--------------------
|
|
Shinya Kitaoka |
120a6e |
#if 0 //---
|
|
Toshihiro Shimizu |
890ddd |
void ino::Lx_to_wrap( TRasterP ras ) {
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Toshihiro Shimizu |
890ddd |
ras->getLx() : 描画の幅
|
|
Toshihiro Shimizu |
890ddd |
ras->getWrap() : データの存在幅
|
|
Toshihiro Shimizu |
890ddd |
描画幅よりデータの存在幅の方が大きい場合、
|
|
Toshihiro Shimizu |
890ddd |
存在幅位置に置き直し、残りをゼロクリア
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
if ( ras->getWrap() <= ras->getLx() ) { return; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const int rowSize = ras->getLx() * ras->getPixelSize();
|
|
Toshihiro Shimizu |
890ddd |
const int wrapSize = ras->getWrap() * ras->getPixelSize();
|
|
Toshihiro Shimizu |
890ddd |
const int restSize = wrapSize - rowSize;
|
|
Toshihiro Shimizu |
890ddd |
const UCHAR *rowImg = ras->getRawData()+rowSize *(ras->getLy()-1);
|
|
Toshihiro Shimizu |
890ddd |
UCHAR *wrapImg = ras->getRawData()+wrapSize*(ras->getLy()-1);
|
|
Toshihiro Shimizu |
890ddd |
for (int yy = 0; yy < ras->getLy(); ++yy) {
|
|
Toshihiro Shimizu |
890ddd |
::memcpy(wrapImg, rowImg, rowSize);
|
|
Toshihiro Shimizu |
890ddd |
::memset(wrapImg+rowSize, 0, restSize); /* 上下にはみ出すとここで落ちる */
|
|
Toshihiro Shimizu |
890ddd |
rowImg -= rowSize;
|
|
Toshihiro Shimizu |
890ddd |
wrapImg -= wrapSize;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Shinya Kitaoka |
120a6e |
#endif //---
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------
|
|
Shinya Kitaoka |
120a6e |
namespace {
|
|
Toshihiro Shimizu |
890ddd |
bool enable_sw_ = true;
|
|
Shinya Kitaoka |
120a6e |
bool check_sw_ = true;
|
|
shun-iwasawa |
e00258 |
} // namespace
|
|
Shinya Kitaoka |
120a6e |
bool ino::log_enable_sw(void) {
|
|
Shinya Kitaoka |
120a6e |
if (check_sw_) {
|
|
Shinya Kitaoka |
120a6e |
TFileStatus file(
|
|
Shinya Kitaoka |
120a6e |
// ToonzFolder::getProfileFolder()
|
|
Shinya Kitaoka |
120a6e |
TEnv::getConfigDir() + "fx_ino_no_log.setup");
|
|
Shinya Kitaoka |
120a6e |
if (file.doesExist()) {
|
|
Shinya Kitaoka |
120a6e |
enable_sw_ = false;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
check_sw_ = false;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return enable_sw_;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
//------------------------------------------------------------
|
|
shun-iwasawa |
e00258 |
namespace {
|
|
shun-iwasawa |
e00258 |
/* より大きな四角エリアにPixel整数値で密着する */
|
|
shun-iwasawa |
e00258 |
void makeRectCoherent(TRectD& rect, const TPointD& pos) {
|
|
shun-iwasawa |
e00258 |
rect -= pos;
|
|
shun-iwasawa |
e00258 |
rect.x0 = tfloor(rect.x0); /* ((x)<(int)(x)? (int)(x)-1: (int)(x))*/
|
|
shun-iwasawa |
e00258 |
rect.y0 = tfloor(rect.y0);
|
|
shun-iwasawa |
e00258 |
rect.x1 = tceil(rect.x1); /* ((int)(x)<(x)? (int)(x)+1: (int)(x))*/
|
|
shun-iwasawa |
e00258 |
rect.y1 = tceil(rect.y1);
|
|
shun-iwasawa |
e00258 |
rect += pos;
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
inline void to_xyz(double* xyz, double const* bgr) {
|
|
shun-iwasawa |
e00258 |
xyz[0] = 0.6069 * bgr[2] + 0.1735 * bgr[1] + 0.2003 * bgr[0]; // X
|
|
shun-iwasawa |
e00258 |
xyz[1] = 0.2989 * bgr[2] + 0.5866 * bgr[1] + 0.1145 * bgr[0]; // Y
|
|
shun-iwasawa |
e00258 |
xyz[2] = 0.0000 * bgr[2] + 0.0661 * bgr[1] + 1.1162 * bgr[0]; // Z
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
inline void to_bgr(double* bgr, double const* xyz) {
|
|
shun-iwasawa |
e00258 |
bgr[0] = +0.0585 * xyz[0] - 0.1187 * xyz[1] + 0.9017 * xyz[2]; // blue
|
|
shun-iwasawa |
e00258 |
bgr[1] = -0.9844 * xyz[0] + 1.9985 * xyz[1] - 0.0279 * xyz[2]; // green
|
|
shun-iwasawa |
e00258 |
bgr[2] = +1.9104 * xyz[0] - 0.5338 * xyz[1] - 0.2891 * xyz[2]; // red
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
// convert sRGB color space to power space
|
|
shun-iwasawa |
e00258 |
template <typename t="double"></typename>
|
|
shun-iwasawa |
e00258 |
inline T to_linear_color_space(T nonlinear_color, T exposure, T gamma) {
|
|
shun-iwasawa |
e00258 |
// return -std::log(T(1) - std::pow(nonlinear_color, gamma)) / exposure;
|
|
shun-iwasawa |
481b59 |
if (nonlinear_color <= T(0)) return T(0);
|
|
shun-iwasawa |
e00258 |
return std::pow(nonlinear_color, gamma) / exposure;
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
// convert power space to sRGB color space
|
|
shun-iwasawa |
e00258 |
template <typename t="double"></typename>
|
|
shun-iwasawa |
e00258 |
inline T to_nonlinear_color_space(T linear_color, T exposure, T gamma) {
|
|
shun-iwasawa |
e00258 |
// return std::pow(T(1) - std::exp(-exposure * linear_color), T(1) / gamma);
|
|
shun-iwasawa |
481b59 |
if (linear_color <= T(0)) return T(0);
|
|
shun-iwasawa |
e00258 |
return std::pow(linear_color * exposure, T(1) / gamma);
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
template <class t="double"></class>
|
|
shun-iwasawa |
e00258 |
const T& clamp(const T& v, const T& lo, const T& hi) {
|
|
shun-iwasawa |
e00258 |
assert(!(hi < lo));
|
|
shun-iwasawa |
e00258 |
return (v < lo) ? lo : (hi < v) ? hi : v;
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
} // namespace
|
|
shun-iwasawa |
e00258 |
//------------------------------------------------------------
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
TBlendForeBackRasterFx::TBlendForeBackRasterFx(bool clipping_mask,
|
|
shun-iwasawa |
e00258 |
bool has_alpha_option)
|
|
shun-iwasawa |
e00258 |
: m_opacity(1.0 * ino::param_range())
|
|
shun-iwasawa |
e00258 |
, m_clipping_mask(clipping_mask)
|
|
shun-iwasawa |
e00258 |
, m_linear(false)
|
|
shun-iwasawa |
e00258 |
, m_gamma(2.2)
|
|
shun-iwasawa |
481b59 |
, m_gammaAdjust(0.)
|
|
shun-iwasawa |
481b59 |
, m_premultiplied(true)
|
|
shun-iwasawa |
481b59 |
, m_colorSpaceMode(new TIntEnumParam(Auto, "Auto")) {
|
|
shun-iwasawa |
e00258 |
addInputPort("Fore", this->m_up);
|
|
shun-iwasawa |
e00258 |
addInputPort("Back", this->m_down);
|
|
shun-iwasawa |
e00258 |
bindParam(this, "opacity", this->m_opacity);
|
|
shun-iwasawa |
e00258 |
bindParam(this, "clipping_mask", this->m_clipping_mask);
|
|
shun-iwasawa |
481b59 |
bindParam(this, "linear", this->m_linear, true, true); // obsolete
|
|
shun-iwasawa |
481b59 |
bindParam(this, "colorSpaceMode", this->m_colorSpaceMode);
|
|
shun-iwasawa |
e00258 |
bindParam(this, "gamma", this->m_gamma);
|
|
shun-iwasawa |
481b59 |
bindParam(this, "gammaAdjust", this->m_gammaAdjust);
|
|
shun-iwasawa |
e00258 |
bindParam(this, "premultiplied", this->m_premultiplied);
|
|
shun-iwasawa |
e00258 |
this->m_opacity->setValueRange(0, 1.0 * ino::param_range());
|
|
shun-iwasawa |
e00258 |
this->m_gamma->setValueRange(0.2, 5.0);
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
481b59 |
this->m_gammaAdjust->setValueRange(-5., 5.);
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
m_colorSpaceMode->addItem(Linear, "Linear");
|
|
shun-iwasawa |
481b59 |
m_colorSpaceMode->addItem(Nonlinear, "Nonlinear");
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
e00258 |
if (has_alpha_option) {
|
|
shun-iwasawa |
e00258 |
m_alpha_rendering = TBoolParamP(true);
|
|
shun-iwasawa |
e00258 |
bindParam(this, "alpha_rendering", this->m_alpha_rendering);
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
481b59 |
enableComputeInFloat(true);
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
// version 1: Gamma had been diretory specified
|
|
shun-iwasawa |
481b59 |
// version 2: Gamma is computed by rs.m_colorSpaceGamma + gammaAdjust
|
|
shun-iwasawa |
481b59 |
setFxVersion(2);
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
//--------------------------------------------
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
void TBlendForeBackRasterFx::onFxVersionSet() {
|
|
shun-iwasawa |
481b59 |
bool useGamma = getFxVersion() == 1;
|
|
shun-iwasawa |
481b59 |
if (useGamma) {
|
|
shun-iwasawa |
481b59 |
// Automatically update version
|
|
shun-iwasawa |
481b59 |
if (m_gamma->getKeyframeCount() == 0 &&
|
|
shun-iwasawa |
481b59 |
areAlmostEqual(m_gamma->getDefaultValue(), 2.2)) {
|
|
shun-iwasawa |
481b59 |
useGamma = false;
|
|
shun-iwasawa |
481b59 |
// call onObsoleteParamLoaded here in case loading the old fx before
|
|
shun-iwasawa |
481b59 |
// introducing the linear option
|
|
shun-iwasawa |
481b59 |
onObsoleteParamLoaded("linear");
|
|
shun-iwasawa |
481b59 |
setFxVersion(2);
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
getParams()->getParamVar("gamma")->setIsHidden(!useGamma);
|
|
shun-iwasawa |
481b59 |
getParams()->getParamVar("gammaAdjust")->setIsHidden(useGamma);
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
//------------------------------------------------
|
|
shun-iwasawa |
481b59 |
// This will be called in TFx::loadData when obsolete "linear" value is
|
|
shun-iwasawa |
481b59 |
// loaded
|
|
shun-iwasawa |
481b59 |
void TBlendForeBackRasterFx::onObsoleteParamLoaded(
|
|
shun-iwasawa |
481b59 |
const std::string& paramName) {
|
|
shun-iwasawa |
481b59 |
if (paramName != "linear") return;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
if (m_linear->getValue())
|
|
shun-iwasawa |
481b59 |
m_colorSpaceMode->setValue(Linear);
|
|
shun-iwasawa |
481b59 |
else
|
|
shun-iwasawa |
481b59 |
m_colorSpaceMode->setValue(Nonlinear);
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
e00258 |
//------------------------------------------------------------
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
bool TBlendForeBackRasterFx::doGetBBox(double frame, TRectD& bBox,
|
|
shun-iwasawa |
e00258 |
const TRenderSettings& rs) {
|
|
shun-iwasawa |
e00258 |
TRectD up_bx;
|
|
shun-iwasawa |
e00258 |
const bool up_sw =
|
|
shun-iwasawa |
e00258 |
(m_up.isConnected() ? m_up->doGetBBox(frame, up_bx, rs) : false);
|
|
shun-iwasawa |
e00258 |
TRectD dn_bx;
|
|
shun-iwasawa |
e00258 |
const bool dn_sw =
|
|
shun-iwasawa |
e00258 |
(m_down.isConnected() ? m_down->doGetBBox(frame, dn_bx, rs) : false);
|
|
shun-iwasawa |
e00258 |
if (up_sw && dn_sw) {
|
|
shun-iwasawa |
e00258 |
bBox = up_bx + dn_bx;
|
|
shun-iwasawa |
e00258 |
return !bBox.isEmpty();
|
|
shun-iwasawa |
e00258 |
} else if (up_sw) {
|
|
shun-iwasawa |
e00258 |
bBox = up_bx;
|
|
shun-iwasawa |
e00258 |
return true;
|
|
shun-iwasawa |
e00258 |
} else if (dn_sw) {
|
|
shun-iwasawa |
e00258 |
bBox = dn_bx;
|
|
shun-iwasawa |
e00258 |
return true;
|
|
shun-iwasawa |
e00258 |
} else {
|
|
shun-iwasawa |
e00258 |
bBox = TRectD();
|
|
shun-iwasawa |
e00258 |
return false;
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
//------------------------------------------------------------
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
void TBlendForeBackRasterFx::dryComputeUpAndDown(TRectD& rect, double frame,
|
|
shun-iwasawa |
e00258 |
const TRenderSettings& rs,
|
|
shun-iwasawa |
e00258 |
bool upComputesWholeTile) {
|
|
shun-iwasawa |
e00258 |
const bool up_is = (this->m_up.isConnected() &&
|
|
shun-iwasawa |
e00258 |
this->m_up.getFx()->getTimeRegion().contains(frame));
|
|
shun-iwasawa |
e00258 |
const bool down_is = (this->m_down.isConnected() &&
|
|
shun-iwasawa |
e00258 |
this->m_down.getFx()->getTimeRegion().contains(frame));
|
|
shun-iwasawa |
e00258 |
/* ------ 両方とも切断の時処理しない ---------------------- */
|
|
shun-iwasawa |
e00258 |
if (!up_is && !down_is) {
|
|
shun-iwasawa |
e00258 |
return;
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
/* ------ up接続かつdown切断の時 -------------------------- */
|
|
shun-iwasawa |
e00258 |
if (up_is && !down_is) {
|
|
shun-iwasawa |
e00258 |
this->m_up->dryCompute(rect, frame, rs);
|
|
shun-iwasawa |
e00258 |
return;
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
/* ------ down接続時 -------------------------------------- */
|
|
shun-iwasawa |
e00258 |
if (down_is) {
|
|
shun-iwasawa |
e00258 |
this->m_down->dryCompute(rect, frame, rs);
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
/* ------ up切断時 ---------------------------------------- */
|
|
shun-iwasawa |
e00258 |
if (!up_is) {
|
|
shun-iwasawa |
e00258 |
return;
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
/* ------ tileのgeometryを計算する ------------------------ */
|
|
shun-iwasawa |
e00258 |
TRectD upBBox;
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
if (upComputesWholeTile) {
|
|
shun-iwasawa |
e00258 |
upBBox = rect;
|
|
shun-iwasawa |
e00258 |
} else {
|
|
shun-iwasawa |
e00258 |
this->m_up->getBBox(frame, upBBox, rs);
|
|
shun-iwasawa |
e00258 |
upBBox *= rect;
|
|
shun-iwasawa |
e00258 |
makeRectCoherent(upBBox, rect.getP00());
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
if ((upBBox.getLx() > 0.5) && (upBBox.getLy() > 0.5)) {
|
|
shun-iwasawa |
e00258 |
this->m_up->dryCompute(upBBox, frame, rs);
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
//------------------------------------------------------------
|
|
shun-iwasawa |
e00258 |
void TBlendForeBackRasterFx::doCompute(TTile& tile, double frame,
|
|
shun-iwasawa |
e00258 |
const TRenderSettings& rs) {
|
|
shun-iwasawa |
e00258 |
/* ------ 画像生成 ---------------------------------------- */
|
|
shun-iwasawa |
e00258 |
TRasterP dn_ras, up_ras;
|
|
shun-iwasawa |
e00258 |
this->computeUpAndDown(tile, frame, rs, dn_ras, up_ras);
|
|
shun-iwasawa |
a834fd |
if (!up_ras) {
|
|
shun-iwasawa |
e00258 |
return;
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
a834fd |
// blend on the empty raster if the back port is not active
|
|
shun-iwasawa |
a834fd |
if (!dn_ras) {
|
|
shun-iwasawa |
a834fd |
dn_ras = tile.getRaster();
|
|
shun-iwasawa |
a834fd |
}
|
|
shun-iwasawa |
e00258 |
/* ------ 動作パラメータを得る ---------------------------- */
|
|
shun-iwasawa |
e00258 |
const double up_opacity =
|
|
shun-iwasawa |
e00258 |
this->m_opacity->getValue(frame) / ino::param_range();
|
|
shun-iwasawa |
481b59 |
double gamma;
|
|
shun-iwasawa |
481b59 |
if (getFxVersion() == 1)
|
|
shun-iwasawa |
481b59 |
gamma = this->m_gamma->getValue(frame);
|
|
shun-iwasawa |
481b59 |
else {
|
|
shun-iwasawa |
481b59 |
gamma = std::max(1., rs.m_colorSpaceGamma + m_gammaAdjust->getValue(frame));
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
bool linear_sw = toBeComputedInLinearColorSpace(rs.m_linearColorSpace,
|
|
shun-iwasawa |
481b59 |
tile.getRaster()->isLinear());
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
e00258 |
/* ------ (app_begin)log記憶 ------------------------------ */
|
|
shun-iwasawa |
e00258 |
const bool log_sw = ino::log_enable_sw();
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
if (log_sw) {
|
|
shun-iwasawa |
e00258 |
std::ostringstream os;
|
|
shun-iwasawa |
e00258 |
os << "params"
|
|
shun-iwasawa |
e00258 |
<< " up_opacity " << up_opacity << " dn_tile w " << dn_ras->getLx()
|
|
shun-iwasawa |
e00258 |
<< " wrap " << dn_ras->getWrap() << " h " << dn_ras->getLy()
|
|
shun-iwasawa |
e00258 |
<< " pixbits " << ino::pixel_bits(dn_ras) << " up_tile w "
|
|
shun-iwasawa |
e00258 |
<< up_ras->getLx() << " wrap " << up_ras->getWrap() << " h "
|
|
shun-iwasawa |
e00258 |
<< up_ras->getLy() << " pixbits " << ino::pixel_bits(up_ras)
|
|
shun-iwasawa |
e00258 |
<< " frame " << frame;
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
/* ------ fx処理 ------------------------------------------ */
|
|
shun-iwasawa |
e00258 |
try {
|
|
shun-iwasawa |
e00258 |
if (dn_ras) {
|
|
shun-iwasawa |
e00258 |
dn_ras->lock();
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
if (up_ras) {
|
|
shun-iwasawa |
e00258 |
up_ras->lock();
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
481b59 |
doComputeFx(dn_ras, up_ras, TPoint(), up_opacity,
|
|
shun-iwasawa |
481b59 |
gamma / rs.m_colorSpaceGamma, rs.m_colorSpaceGamma, linear_sw);
|
|
shun-iwasawa |
e00258 |
// fx_(dn_ras, up_ras, TPoint(), up_opacity,
|
|
shun-iwasawa |
e00258 |
// this->m_clipping_mask->getValue(),
|
|
shun-iwasawa |
e00258 |
// this->m_linear->getValue(), gamma, this->m_premultiplied->getValue());
|
|
shun-iwasawa |
e00258 |
if (up_ras) {
|
|
shun-iwasawa |
e00258 |
up_ras->unlock();
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
if (dn_ras) {
|
|
shun-iwasawa |
e00258 |
dn_ras->unlock();
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
/* ------ error処理 --------------------------------------- */
|
|
shun-iwasawa |
e00258 |
catch (std::exception& e) {
|
|
shun-iwasawa |
e00258 |
if (up_ras) {
|
|
shun-iwasawa |
e00258 |
up_ras->unlock();
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
if (dn_ras) {
|
|
shun-iwasawa |
e00258 |
dn_ras->unlock();
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
if (log_sw) {
|
|
shun-iwasawa |
e00258 |
std::string str("exception <");
|
|
shun-iwasawa |
e00258 |
str += e.what();
|
|
shun-iwasawa |
e00258 |
str += '>';
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
throw;
|
|
shun-iwasawa |
e00258 |
} catch (...) {
|
|
shun-iwasawa |
e00258 |
if (up_ras) {
|
|
shun-iwasawa |
e00258 |
up_ras->unlock();
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
if (dn_ras) {
|
|
shun-iwasawa |
e00258 |
dn_ras->unlock();
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
if (log_sw) {
|
|
shun-iwasawa |
e00258 |
std::string str("other exception");
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
throw;
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
//------------------------------------------------------------
|
|
shun-iwasawa |
481b59 |
void TBlendForeBackRasterFx::doComputeFx(
|
|
shun-iwasawa |
481b59 |
TRasterP& dn_ras_out, const TRasterP& up_ras, const TPoint& pos,
|
|
shun-iwasawa |
481b59 |
const double up_opacity, const double gammaDif,
|
|
shun-iwasawa |
481b59 |
const double colorSpaceGamma, const bool linear_sw) {
|
|
shun-iwasawa |
e00258 |
/* 交差したエリアを処理するようにする、いるのか??? */
|
|
shun-iwasawa |
e00258 |
TRect outRect(dn_ras_out->getBounds());
|
|
shun-iwasawa |
e00258 |
TRect upRect(up_ras->getBounds() + pos);
|
|
shun-iwasawa |
e00258 |
TRect intersection = outRect * upRect;
|
|
shun-iwasawa |
e00258 |
if (intersection.isEmpty()) return;
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
TRasterP cRout = dn_ras_out->extract(intersection);
|
|
shun-iwasawa |
e00258 |
TRect rr = intersection - pos;
|
|
shun-iwasawa |
e00258 |
TRasterP cRup = up_ras->extract(rr);
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
TRaster32P rout32 = cRout, rup32 = cRup;
|
|
shun-iwasawa |
e00258 |
TRaster64P rout64 = cRout, rup64 = cRup;
|
|
shun-iwasawa |
481b59 |
TRasterFP routF = cRout, rupF = cRup;
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
481b59 |
bool premultiplied_sw = this->m_premultiplied->getValue();
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
if (rout32 && rup32) {
|
|
shun-iwasawa |
481b59 |
if (linear_sw) {
|
|
shun-iwasawa |
481b59 |
if (!premultiplied_sw)
|
|
shun-iwasawa |
481b59 |
premultiToUnpremulti<tpixel32, uchar="">(rout32, rup32, colorSpaceGamma);</tpixel32,>
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
linearTmpl<tpixel32, uchar="">(rout32, rup32, up_opacity, gammaDif);</tpixel32,>
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
e00258 |
// linearAdd<tpixel32, uchar="">(rout32, rup32, up_opacity, clipping_mask_sw,</tpixel32,>
|
|
shun-iwasawa |
e00258 |
// gamma, premultiplied_sw);
|
|
shun-iwasawa |
e00258 |
else
|
|
shun-iwasawa |
e00258 |
nonlinearTmpl<tpixel32, uchar="">(rout32, rup32, up_opacity);</tpixel32,>
|
|
shun-iwasawa |
e00258 |
// tmpl_<tpixel32, uchar="">(rout32, rup32, up_opacity, clipping_mask_sw);</tpixel32,>
|
|
shun-iwasawa |
e00258 |
} else if (rout64 && rup64) {
|
|
shun-iwasawa |
481b59 |
if (linear_sw) {
|
|
shun-iwasawa |
481b59 |
if (!premultiplied_sw)
|
|
shun-iwasawa |
481b59 |
premultiToUnpremulti<tpixel64, ushort="">(rout64, rup64, colorSpaceGamma);</tpixel64,>
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
linearTmpl<tpixel64, ushort="">(rout64, rup64, up_opacity, gammaDif);</tpixel64,>
|
|
shun-iwasawa |
481b59 |
} else
|
|
shun-iwasawa |
e00258 |
nonlinearTmpl<tpixel64, ushort="">(rout64, rup64, up_opacity);</tpixel64,>
|
|
shun-iwasawa |
481b59 |
} else if (routF && rupF) {
|
|
shun-iwasawa |
481b59 |
if (linear_sw) {
|
|
shun-iwasawa |
481b59 |
if (!premultiplied_sw)
|
|
shun-iwasawa |
481b59 |
premultiToUnpremulti<tpixelf, float="">(routF, rupF, colorSpaceGamma);</tpixelf,>
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
linearTmpl<tpixelf, float="">(routF, rupF, up_opacity, gammaDif);</tpixelf,>
|
|
shun-iwasawa |
481b59 |
} else
|
|
shun-iwasawa |
481b59 |
nonlinearTmpl<tpixelf, float="">(routF, rupF, up_opacity);</tpixelf,>
|
|
shun-iwasawa |
e00258 |
} else {
|
|
shun-iwasawa |
e00258 |
throw TRopException("unsupported pixel type");
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
//------------------------------------------------------------
|
|
shun-iwasawa |
e00258 |
template <class class="" q="" t,=""></class>
|
|
shun-iwasawa |
e00258 |
void TBlendForeBackRasterFx::nonlinearTmpl(TRasterPT<t> dn_ras_out,</t>
|
|
shun-iwasawa |
e00258 |
const TRasterPT<t>& up_ras,</t>
|
|
shun-iwasawa |
e00258 |
const double up_opacity) {
|
|
shun-iwasawa |
e00258 |
bool clipping_mask_sw = this->m_clipping_mask->getValue();
|
|
shun-iwasawa |
e00258 |
bool alpha_rendering_sw = (m_alpha_rendering.getPointer())
|
|
shun-iwasawa |
e00258 |
? this->m_alpha_rendering->getValue()
|
|
shun-iwasawa |
e00258 |
: true;
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
double maxi = static_cast<double>(T::maxChannelValue); // 255or65535</double>
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
assert(dn_ras_out->getSize() == up_ras->getSize());
|
|
shun-iwasawa |
481b59 |
assert(dn_ras_out->isLinear() == up_ras->isLinear());
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) {
|
|
shun-iwasawa |
e00258 |
T* out_pix = dn_ras_out->pixels(yy);
|
|
shun-iwasawa |
e00258 |
const T* const out_end = out_pix + dn_ras_out->getLx();
|
|
shun-iwasawa |
e00258 |
const T* up_pix = up_ras->pixels(yy);
|
|
shun-iwasawa |
e00258 |
for (; out_pix < out_end; ++out_pix, ++up_pix) {
|
|
shun-iwasawa |
e00258 |
double upr = static_cast<double>(up_pix->r) / maxi;</double>
|
|
shun-iwasawa |
e00258 |
double upg = static_cast<double>(up_pix->g) / maxi;</double>
|
|
shun-iwasawa |
e00258 |
double upb = static_cast<double>(up_pix->b) / maxi;</double>
|
|
shun-iwasawa |
e00258 |
double upa = static_cast<double>(up_pix->m) / maxi;</double>
|
|
shun-iwasawa |
e00258 |
double dnr = static_cast<double>(out_pix->r) / maxi;</double>
|
|
shun-iwasawa |
e00258 |
double dng = static_cast<double>(out_pix->g) / maxi;</double>
|
|
shun-iwasawa |
e00258 |
double dnb = static_cast<double>(out_pix->b) / maxi;</double>
|
|
shun-iwasawa |
e00258 |
double dna = static_cast<double>(out_pix->m) / maxi;</double>
|
|
shun-iwasawa |
e00258 |
brendKernel(dnr, dng, dnb, dna, upr, upg, upb, upa,
|
|
shun-iwasawa |
e00258 |
clipping_mask_sw ? up_opacity * dna : up_opacity,
|
|
shun-iwasawa |
481b59 |
alpha_rendering_sw, true);
|
|
shun-iwasawa |
e00258 |
out_pix->r = static_cast<q>(dnr * (maxi + 0.999999));</q>
|
|
shun-iwasawa |
e00258 |
out_pix->g = static_cast<q>(dng * (maxi + 0.999999));</q>
|
|
shun-iwasawa |
e00258 |
out_pix->b = static_cast<q>(dnb * (maxi + 0.999999));</q>
|
|
shun-iwasawa |
e00258 |
out_pix->m = static_cast<q>(dna * (maxi + 0.999999));</q>
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
//------------------------------------------------------------
|
|
shun-iwasawa |
481b59 |
template <>
|
|
shun-iwasawa |
481b59 |
void TBlendForeBackRasterFx::nonlinearTmpl<tpixelf, float="">(</tpixelf,>
|
|
shun-iwasawa |
481b59 |
TRasterFP dn_ras_out, const TRasterFP& up_ras, const double up_opacity) {
|
|
shun-iwasawa |
481b59 |
bool clipping_mask_sw = this->m_clipping_mask->getValue();
|
|
shun-iwasawa |
481b59 |
bool alpha_rendering_sw = (m_alpha_rendering.getPointer())
|
|
shun-iwasawa |
481b59 |
? this->m_alpha_rendering->getValue()
|
|
shun-iwasawa |
481b59 |
: true;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
assert(dn_ras_out->getSize() == up_ras->getSize());
|
|
shun-iwasawa |
481b59 |
assert(dn_ras_out->isLinear() == up_ras->isLinear());
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) {
|
|
shun-iwasawa |
481b59 |
TPixelF* out_pix = dn_ras_out->pixels(yy);
|
|
shun-iwasawa |
481b59 |
const TPixelF* const out_end = out_pix + dn_ras_out->getLx();
|
|
shun-iwasawa |
481b59 |
const TPixelF* up_pix = up_ras->pixels(yy);
|
|
shun-iwasawa |
481b59 |
for (; out_pix < out_end; ++out_pix, ++up_pix) {
|
|
shun-iwasawa |
481b59 |
double dnr = static_cast<double>(out_pix->r);</double>
|
|
shun-iwasawa |
481b59 |
double dng = static_cast<double>(out_pix->g);</double>
|
|
shun-iwasawa |
481b59 |
double dnb = static_cast<double>(out_pix->b);</double>
|
|
shun-iwasawa |
481b59 |
double dna = static_cast<double>(out_pix->m);</double>
|
|
shun-iwasawa |
481b59 |
brendKernel(dnr, dng, dnb, dna, up_pix->r, up_pix->g, up_pix->b,
|
|
shun-iwasawa |
481b59 |
up_pix->m, clipping_mask_sw ? up_opacity * dna : up_opacity,
|
|
shun-iwasawa |
481b59 |
alpha_rendering_sw, false);
|
|
shun-iwasawa |
481b59 |
out_pix->r = dnr;
|
|
shun-iwasawa |
481b59 |
out_pix->g = dng;
|
|
shun-iwasawa |
481b59 |
out_pix->b = dnb;
|
|
shun-iwasawa |
481b59 |
out_pix->m = dna;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
//------------------------------------------------------------
|
|
shun-iwasawa |
e00258 |
template <class class="" q="" t,=""></class>
|
|
shun-iwasawa |
e00258 |
void TBlendForeBackRasterFx::linearTmpl(TRasterPT<t> dn_ras_out,</t>
|
|
shun-iwasawa |
e00258 |
const TRasterPT<t>& up_ras,</t>
|
|
shun-iwasawa |
e00258 |
const double up_opacity,
|
|
shun-iwasawa |
481b59 |
const double gammaDif) {
|
|
shun-iwasawa |
e00258 |
bool clipping_mask_sw = this->m_clipping_mask->getValue();
|
|
shun-iwasawa |
e00258 |
bool alpha_rendering_sw = (m_alpha_rendering.getPointer())
|
|
shun-iwasawa |
e00258 |
? this->m_alpha_rendering->getValue()
|
|
shun-iwasawa |
e00258 |
: true;
|
|
shun-iwasawa |
481b59 |
bool premultiplied_sw = this->m_premultiplied->getValue();
|
|
shun-iwasawa |
e00258 |
double maxi = static_cast<double>(T::maxChannelValue); // 255or65535</double>
|
|
shun-iwasawa |
e00258 |
double limit = (maxi + 0.5) / (maxi + 1.0);
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
assert(dn_ras_out->getSize() == up_ras->getSize());
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) {
|
|
shun-iwasawa |
e00258 |
T* out_pix = dn_ras_out->pixels(yy);
|
|
shun-iwasawa |
e00258 |
const T* const out_end = out_pix + dn_ras_out->getLx();
|
|
shun-iwasawa |
e00258 |
const T* up_pix = up_ras->pixels(yy);
|
|
shun-iwasawa |
e00258 |
for (; out_pix < out_end; ++out_pix, ++up_pix) {
|
|
shun-iwasawa |
e00258 |
if (up_pix->m <= 0 || up_opacity <= 0) {
|
|
shun-iwasawa |
e00258 |
continue;
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
double dna = static_cast<double>(out_pix->m) / maxi;</double>
|
|
shun-iwasawa |
e00258 |
double tmp_opacity = clipping_mask_sw ? up_opacity * dna : up_opacity;
|
|
shun-iwasawa |
e00258 |
if (tmp_opacity <= 0) continue;
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
double dnBGR[3];
|
|
shun-iwasawa |
e00258 |
dnBGR[0] = static_cast<double>(out_pix->b) / maxi;</double>
|
|
shun-iwasawa |
e00258 |
dnBGR[1] = static_cast<double>(out_pix->g) / maxi;</double>
|
|
shun-iwasawa |
e00258 |
dnBGR[2] = static_cast<double>(out_pix->r) / maxi;</double>
|
|
shun-iwasawa |
e00258 |
double dnXYZ[3] = {0.0, 0.0, 0.0};
|
|
shun-iwasawa |
e00258 |
if (dna > 0.0) {
|
|
shun-iwasawa |
e00258 |
for (int c = 0; c < 3; c++) {
|
|
shun-iwasawa |
e00258 |
if (premultiplied_sw)
|
|
shun-iwasawa |
481b59 |
dnBGR[c] =
|
|
shun-iwasawa |
481b59 |
to_linear_color_space(dnBGR[c] / dna, 1.0, gammaDif) * dna;
|
|
shun-iwasawa |
e00258 |
else
|
|
shun-iwasawa |
481b59 |
dnBGR[c] = to_linear_color_space(dnBGR[c], 1.0, gammaDif);
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
e00258 |
to_xyz(dnXYZ, dnBGR);
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
double upBGR[3];
|
|
shun-iwasawa |
e00258 |
upBGR[0] = static_cast<double>(up_pix->b) / maxi;</double>
|
|
shun-iwasawa |
e00258 |
upBGR[1] = static_cast<double>(up_pix->g) / maxi;</double>
|
|
shun-iwasawa |
e00258 |
upBGR[2] = static_cast<double>(up_pix->r) / maxi;</double>
|
|
shun-iwasawa |
e00258 |
double upa = static_cast<double>(up_pix->m) / maxi;</double>
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
e00258 |
for (int c = 0; c < 3; c++) {
|
|
shun-iwasawa |
e00258 |
if (premultiplied_sw)
|
|
shun-iwasawa |
481b59 |
upBGR[c] = to_linear_color_space(upBGR[c] / upa, 1.0, gammaDif) * upa;
|
|
shun-iwasawa |
e00258 |
else
|
|
shun-iwasawa |
481b59 |
upBGR[c] = to_linear_color_space(upBGR[c], 1.0, gammaDif);
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
double upXYZ[3];
|
|
shun-iwasawa |
e00258 |
to_xyz(upXYZ, upBGR);
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
brendKernel(dnXYZ[0], dnXYZ[1], dnXYZ[2], dna, upXYZ[0], upXYZ[1],
|
|
shun-iwasawa |
481b59 |
upXYZ[2], upa, tmp_opacity, alpha_rendering_sw, false);
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
to_bgr(dnBGR, dnXYZ);
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
// premultiply the result
|
|
shun-iwasawa |
e00258 |
double nonlinear_b =
|
|
shun-iwasawa |
481b59 |
to_nonlinear_color_space(dnBGR[0] / dna, 1.0, gammaDif) * dna;
|
|
shun-iwasawa |
e00258 |
double nonlinear_g =
|
|
shun-iwasawa |
481b59 |
to_nonlinear_color_space(dnBGR[1] / dna, 1.0, gammaDif) * dna;
|
|
shun-iwasawa |
e00258 |
double nonlinear_r =
|
|
shun-iwasawa |
481b59 |
to_nonlinear_color_space(dnBGR[2] / dna, 1.0, gammaDif) * dna;
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
out_pix->r =
|
|
shun-iwasawa |
e00258 |
static_cast<q>(clamp(nonlinear_r, 0.0, 1.0) * (maxi + 0.999999));</q>
|
|
shun-iwasawa |
e00258 |
out_pix->g =
|
|
shun-iwasawa |
e00258 |
static_cast<q>(clamp(nonlinear_g, 0.0, 1.0) * (maxi + 0.999999));</q>
|
|
shun-iwasawa |
e00258 |
out_pix->b =
|
|
shun-iwasawa |
e00258 |
static_cast<q>(clamp(nonlinear_b, 0.0, 1.0) * (maxi + 0.999999));</q>
|
|
shun-iwasawa |
e00258 |
out_pix->m = static_cast<q>(dna * (maxi + 0.999999));</q>
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
//------------------------------------------------------------
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
481b59 |
template <>
|
|
shun-iwasawa |
481b59 |
void TBlendForeBackRasterFx::linearTmpl<tpixelf, float="">(TRasterFP dn_ras_out,</tpixelf,>
|
|
shun-iwasawa |
481b59 |
const TRasterFP& up_ras,
|
|
shun-iwasawa |
481b59 |
const double up_opacity,
|
|
shun-iwasawa |
481b59 |
const double gammaDif) {
|
|
shun-iwasawa |
481b59 |
bool clipping_mask_sw = this->m_clipping_mask->getValue();
|
|
shun-iwasawa |
481b59 |
bool alpha_rendering_sw = (m_alpha_rendering.getPointer())
|
|
shun-iwasawa |
481b59 |
? this->m_alpha_rendering->getValue()
|
|
shun-iwasawa |
481b59 |
: true;
|
|
shun-iwasawa |
481b59 |
bool premultiplied_sw = this->m_premultiplied->getValue();
|
|
shun-iwasawa |
481b59 |
// double maxi = static_cast<double>(T::maxChannelValue); // 255or65535</double>
|
|
shun-iwasawa |
481b59 |
// double limit = (maxi + 0.5) / (maxi + 1.0);
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
assert(dn_ras_out->getSize() == up_ras->getSize());
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) {
|
|
shun-iwasawa |
481b59 |
TPixelF* out_pix = dn_ras_out->pixels(yy);
|
|
shun-iwasawa |
481b59 |
const TPixelF* const out_end = out_pix + dn_ras_out->getLx();
|
|
shun-iwasawa |
481b59 |
const TPixelF* up_pix = up_ras->pixels(yy);
|
|
shun-iwasawa |
481b59 |
for (; out_pix < out_end; ++out_pix, ++up_pix) {
|
|
shun-iwasawa |
481b59 |
if (up_pix->m <= 0.f || up_opacity <= 0.f) {
|
|
shun-iwasawa |
481b59 |
continue;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
double dna = static_cast<double>(out_pix->m);</double>
|
|
shun-iwasawa |
481b59 |
double tmp_opacity = clipping_mask_sw ? up_opacity * dna : up_opacity;
|
|
shun-iwasawa |
481b59 |
if (tmp_opacity <= 0.) continue;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
double dnBGR[3];
|
|
shun-iwasawa |
481b59 |
dnBGR[0] = static_cast<double>(out_pix->b);</double>
|
|
shun-iwasawa |
481b59 |
dnBGR[1] = static_cast<double>(out_pix->g);</double>
|
|
shun-iwasawa |
481b59 |
dnBGR[2] = static_cast<double>(out_pix->r);</double>
|
|
shun-iwasawa |
481b59 |
double dnXYZ[3] = {0.0, 0.0, 0.0};
|
|
shun-iwasawa |
481b59 |
if (dna > 0.0) {
|
|
shun-iwasawa |
481b59 |
for (int c = 0; c < 3; c++) {
|
|
shun-iwasawa |
481b59 |
if (premultiplied_sw)
|
|
shun-iwasawa |
481b59 |
dnBGR[c] =
|
|
shun-iwasawa |
481b59 |
to_linear_color_space(dnBGR[c] / dna, 1.0, gammaDif) * dna;
|
|
shun-iwasawa |
481b59 |
else
|
|
shun-iwasawa |
481b59 |
dnBGR[c] = to_linear_color_space(dnBGR[c], 1.0, gammaDif);
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
to_xyz(dnXYZ, dnBGR);
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
double upBGR[3];
|
|
shun-iwasawa |
481b59 |
upBGR[0] = static_cast<double>(up_pix->b);</double>
|
|
shun-iwasawa |
481b59 |
upBGR[1] = static_cast<double>(up_pix->g);</double>
|
|
shun-iwasawa |
481b59 |
upBGR[2] = static_cast<double>(up_pix->r);</double>
|
|
shun-iwasawa |
481b59 |
double upa = static_cast<double>(up_pix->m);</double>
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
for (int c = 0; c < 3; c++) {
|
|
shun-iwasawa |
481b59 |
if (premultiplied_sw)
|
|
shun-iwasawa |
481b59 |
upBGR[c] = to_linear_color_space(upBGR[c] / upa, 1.0, gammaDif) * upa;
|
|
shun-iwasawa |
481b59 |
else
|
|
shun-iwasawa |
481b59 |
upBGR[c] = to_linear_color_space(upBGR[c], 1.0, gammaDif);
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
double upXYZ[3];
|
|
shun-iwasawa |
481b59 |
to_xyz(upXYZ, upBGR);
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
brendKernel(dnXYZ[0], dnXYZ[1], dnXYZ[2], dna, upXYZ[0], upXYZ[1],
|
|
shun-iwasawa |
481b59 |
upXYZ[2], upa, tmp_opacity, alpha_rendering_sw, false);
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
to_bgr(dnBGR, dnXYZ);
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
// premultiply the result
|
|
shun-iwasawa |
481b59 |
double nonlinear_b =
|
|
shun-iwasawa |
481b59 |
to_nonlinear_color_space(dnBGR[0] / dna, 1.0, gammaDif) * dna;
|
|
shun-iwasawa |
481b59 |
double nonlinear_g =
|
|
shun-iwasawa |
481b59 |
to_nonlinear_color_space(dnBGR[1] / dna, 1.0, gammaDif) * dna;
|
|
shun-iwasawa |
481b59 |
double nonlinear_r =
|
|
shun-iwasawa |
481b59 |
to_nonlinear_color_space(dnBGR[2] / dna, 1.0, gammaDif) * dna;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
out_pix->r = nonlinear_r;
|
|
shun-iwasawa |
481b59 |
out_pix->g = nonlinear_g;
|
|
shun-iwasawa |
481b59 |
out_pix->b = nonlinear_b;
|
|
shun-iwasawa |
481b59 |
out_pix->m = dna;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
//------------------------------------------------------------
|
|
shun-iwasawa |
481b59 |
template <class class="" q="" t,=""></class>
|
|
shun-iwasawa |
481b59 |
void TBlendForeBackRasterFx::premultiToUnpremulti(
|
|
shun-iwasawa |
481b59 |
TRasterPT<t> dn_ras, const TRasterPT<t>& up_ras,</t></t>
|
|
shun-iwasawa |
481b59 |
const double colorSpaceGamma) {
|
|
shun-iwasawa |
481b59 |
double maxi = static_cast<double>(T::maxChannelValue); // 255or65535</double>
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
assert(dn_ras->getSize() == up_ras->getSize());
|
|
shun-iwasawa |
481b59 |
assert(dn_ras->isLinear() == up_ras->isLinear());
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
for (int yy = 0; yy < dn_ras->getLy(); ++yy) {
|
|
shun-iwasawa |
481b59 |
T* dn_pix = dn_ras->pixels(yy);
|
|
shun-iwasawa |
481b59 |
const T* const dn_end = dn_pix + dn_ras->getLx();
|
|
shun-iwasawa |
481b59 |
T* up_pix = up_ras->pixels(yy);
|
|
shun-iwasawa |
481b59 |
for (; dn_pix < dn_end; ++dn_pix, ++up_pix) {
|
|
shun-iwasawa |
481b59 |
double upa = static_cast<double>(up_pix->m) / maxi;</double>
|
|
shun-iwasawa |
481b59 |
if (upa > 0. && upa < 1.) {
|
|
shun-iwasawa |
481b59 |
double upr = static_cast<double>(up_pix->r) / maxi;</double>
|
|
shun-iwasawa |
481b59 |
double upg = static_cast<double>(up_pix->g) / maxi;</double>
|
|
shun-iwasawa |
481b59 |
double upb = static_cast<double>(up_pix->b) / maxi;</double>
|
|
shun-iwasawa |
481b59 |
double up_fac = std::pow(upa, colorSpaceGamma - 1.);
|
|
shun-iwasawa |
481b59 |
up_pix->r = static_cast<q>(upr * up_fac * (maxi + 0.999999));</q>
|
|
shun-iwasawa |
481b59 |
up_pix->g = static_cast<q>(upg * up_fac * (maxi + 0.999999));</q>
|
|
shun-iwasawa |
481b59 |
up_pix->b = static_cast<q>(upb * up_fac * (maxi + 0.999999));</q>
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
double dna = static_cast<double>(dn_pix->m) / maxi;</double>
|
|
shun-iwasawa |
481b59 |
if (dna > 0. && dna < 1.) {
|
|
shun-iwasawa |
481b59 |
double dnr = static_cast<double>(dn_pix->r) / maxi;</double>
|
|
shun-iwasawa |
481b59 |
double dng = static_cast<double>(dn_pix->g) / maxi;</double>
|
|
shun-iwasawa |
481b59 |
double dnb = static_cast<double>(dn_pix->b) / maxi;</double>
|
|
shun-iwasawa |
481b59 |
double dn_fac = std::pow(dna, colorSpaceGamma - 1.);
|
|
shun-iwasawa |
481b59 |
dn_pix->r = static_cast<q>(dnr * dn_fac * (maxi + 0.999999));</q>
|
|
shun-iwasawa |
481b59 |
dn_pix->g = static_cast<q>(dng * dn_fac * (maxi + 0.999999));</q>
|
|
shun-iwasawa |
481b59 |
dn_pix->b = static_cast<q>(dnb * dn_fac * (maxi + 0.999999));</q>
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
//------------------------------------------------------------
|
|
shun-iwasawa |
481b59 |
template <>
|
|
shun-iwasawa |
481b59 |
void TBlendForeBackRasterFx::premultiToUnpremulti<tpixelf, float="">(</tpixelf,>
|
|
shun-iwasawa |
481b59 |
TRasterFP dn_ras, const TRasterFP& up_ras, const double colorSpaceGamma) {
|
|
shun-iwasawa |
481b59 |
assert(dn_ras->getSize() == up_ras->getSize());
|
|
shun-iwasawa |
481b59 |
assert(dn_ras->isLinear() == up_ras->isLinear());
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
for (int yy = 0; yy < dn_ras->getLy(); ++yy) {
|
|
shun-iwasawa |
481b59 |
TPixelF* dn_pix = dn_ras->pixels(yy);
|
|
shun-iwasawa |
481b59 |
const TPixelF* const dn_end = dn_pix + dn_ras->getLx();
|
|
shun-iwasawa |
481b59 |
TPixelF* up_pix = up_ras->pixels(yy);
|
|
shun-iwasawa |
481b59 |
for (; dn_pix < dn_end; ++dn_pix, ++up_pix) {
|
|
shun-iwasawa |
481b59 |
if (up_pix->m > 0.f && up_pix->m < 1.f) {
|
|
shun-iwasawa |
481b59 |
float up_fac =
|
|
shun-iwasawa |
481b59 |
std::pow(up_pix->m, static_cast<float>(colorSpaceGamma - 1.));</float>
|
|
shun-iwasawa |
481b59 |
up_pix->r *= up_fac;
|
|
shun-iwasawa |
481b59 |
up_pix->g *= up_fac;
|
|
shun-iwasawa |
481b59 |
up_pix->b *= up_fac;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
if (dn_pix->m > 0.f && dn_pix->m < 1.f) {
|
|
shun-iwasawa |
481b59 |
float dn_fac =
|
|
shun-iwasawa |
481b59 |
std::pow(dn_pix->m, static_cast<float>(colorSpaceGamma - 1.));</float>
|
|
shun-iwasawa |
481b59 |
dn_pix->r *= dn_fac;
|
|
shun-iwasawa |
481b59 |
dn_pix->g *= dn_fac;
|
|
shun-iwasawa |
481b59 |
dn_pix->b *= dn_fac;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
//------------------------------------------------------------
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
e00258 |
void TBlendForeBackRasterFx::computeUpAndDown(TTile& tile, double frame,
|
|
shun-iwasawa |
e00258 |
const TRenderSettings& rs,
|
|
shun-iwasawa |
e00258 |
TRasterP& dn_ras,
|
|
shun-iwasawa |
e00258 |
TRasterP& up_ras,
|
|
shun-iwasawa |
e00258 |
bool upComputesWholeTile) {
|
|
shun-iwasawa |
e00258 |
/* ------ サポートしていないPixelタイプはエラーを投げる --- */
|
|
shun-iwasawa |
481b59 |
if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster()) &&
|
|
shun-iwasawa |
481b59 |
!((TRasterFP)tile.getRaster())) {
|
|
shun-iwasawa |
e00258 |
throw TRopException("unsupported input pixel type");
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
/*
|
|
shun-iwasawa |
e00258 |
m_down,m_upは繋がっている方があればそれを表示する
|
|
shun-iwasawa |
e00258 |
両方とも接続していれば合成処理する
|
|
shun-iwasawa |
e00258 |
表示スイッチを切ってあるならm_upを表示する
|
|
shun-iwasawa |
e00258 |
fxをreplaceすると、
|
|
shun-iwasawa |
e00258 |
m_source --> m_up (=port0)
|
|
luz paz |
86a900 |
m_reference --> m_down(=port1)
|
|
shun-iwasawa |
e00258 |
となる
|
|
shun-iwasawa |
e00258 |
*/
|
|
shun-iwasawa |
e00258 |
const bool up_is = (this->m_up.isConnected() &&
|
|
shun-iwasawa |
e00258 |
this->m_up.getFx()->getTimeRegion().contains(frame));
|
|
shun-iwasawa |
e00258 |
const bool down_is = (this->m_down.isConnected() &&
|
|
shun-iwasawa |
e00258 |
this->m_down.getFx()->getTimeRegion().contains(frame));
|
|
shun-iwasawa |
e00258 |
/* ------ 両方とも切断の時処理しない ---------------------- */
|
|
shun-iwasawa |
e00258 |
if (!up_is && !down_is) {
|
|
shun-iwasawa |
e00258 |
tile.getRaster()->clear();
|
|
shun-iwasawa |
e00258 |
return;
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
/* ------ up接続かつdown切断の時 -------------------------- */
|
|
shun-iwasawa |
e00258 |
if (up_is && !down_is) {
|
|
shun-iwasawa |
a834fd |
TTile upTile;
|
|
shun-iwasawa |
a834fd |
this->m_up->allocateAndCompute(upTile, tile.m_pos,
|
|
shun-iwasawa |
a834fd |
tile.getRaster()->getSize(),
|
|
shun-iwasawa |
a834fd |
tile.getRaster(), frame, rs);
|
|
shun-iwasawa |
a834fd |
up_ras = upTile.getRaster();
|
|
shun-iwasawa |
e00258 |
return;
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
/* ------ down接続時 downのみ描画して... ------------------ */
|
|
shun-iwasawa |
e00258 |
if (down_is) {
|
|
shun-iwasawa |
e00258 |
this->m_down->compute(tile, frame, rs);
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
/* ------ up切断時 ---------------------------------------- */
|
|
shun-iwasawa |
e00258 |
if (!up_is) {
|
|
shun-iwasawa |
e00258 |
return;
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
/* upと重なる部分を描画する */
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
/* ------ tileの範囲 -------------------------------------- */
|
|
shun-iwasawa |
e00258 |
const TDimension tsz(tile.getRaster()->getSize()); /* 整数 */
|
|
shun-iwasawa |
e00258 |
const TRectD tileRect(tile.m_pos, TDimensionD(tsz.lx, tsz.ly));
|
|
shun-iwasawa |
e00258 |
TRectD upBBox;
|
|
shun-iwasawa |
e00258 |
if (upComputesWholeTile) {
|
|
shun-iwasawa |
e00258 |
upBBox = tileRect;
|
|
shun-iwasawa |
e00258 |
} /* tile全体を得る */
|
|
shun-iwasawa |
e00258 |
else { /* 厳密なエリア... */
|
|
shun-iwasawa |
e00258 |
this->m_up->getBBox(frame, upBBox, rs);
|
|
shun-iwasawa |
e00258 |
upBBox *= tileRect; /* upとtileの交差エリア */
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
/* より大きな四角エリアにPixel整数値で密着する */
|
|
shun-iwasawa |
e00258 |
makeRectCoherent(upBBox, tile.m_pos); // double-->int grid
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
TDimensionI upSize( /* TRectDをTDimensionIに変換 */
|
|
shun-iwasawa |
e00258 |
tround(upBBox.getLx()) // getLx() = "x1>=x0?x1-x0:0"
|
|
shun-iwasawa |
e00258 |
,
|
|
shun-iwasawa |
e00258 |
tround(upBBox.getLy()) // getLy() = "y1>=y0?y1-y0:0"
|
|
shun-iwasawa |
e00258 |
);
|
|
shun-iwasawa |
e00258 |
if ((upSize.lx <= 0) || (upSize.ly <= 0)) {
|
|
shun-iwasawa |
e00258 |
return;
|
|
shun-iwasawa |
e00258 |
}
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
/* ------ upのメモリ確保と描画 ---------------------------- */
|
|
shun-iwasawa |
e00258 |
TTile upTile;
|
|
shun-iwasawa |
e00258 |
this->m_up->allocateAndCompute(upTile, upBBox.getP00(), upSize,
|
|
shun-iwasawa |
e00258 |
tile.getRaster() /* 32/64bitsの判定に使う */
|
|
shun-iwasawa |
e00258 |
,
|
|
shun-iwasawa |
e00258 |
frame, rs);
|
|
shun-iwasawa |
e00258 |
/* ------ upとdownのTRasterを得る ------------------------- */
|
|
shun-iwasawa |
e00258 |
TRectI dnRect(upTile.getRaster()->getSize()); // TDimensionI(-)
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
dnRect += convert(upTile.m_pos - tile.m_pos); /* uptile->tile原点 */
|
|
shun-iwasawa |
e00258 |
/*
|
|
shun-iwasawa |
e00258 |
ここで問題はdoubleの位置を、四捨五入して整数値にしていること
|
|
shun-iwasawa |
e00258 |
移動してから四捨五入ではないの???
|
|
shun-iwasawa |
e00258 |
dnRectの元位置が整数位置なので、問題ないか...
|
|
shun-iwasawa |
e00258 |
*/
|
|
shun-iwasawa |
e00258 |
|
|
shun-iwasawa |
e00258 |
dn_ras = upComputesWholeTile ? tile.getRaster()
|
|
shun-iwasawa |
e00258 |
: tile.getRaster()->extract(dnRect);
|
|
shun-iwasawa |
e00258 |
up_ras = upTile.getRaster();
|
|
shun-iwasawa |
e00258 |
assert(dn_ras->getSize() == up_ras->getSize());
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
//------------------------------------------------------------
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
bool TBlendForeBackRasterFx::toBeComputedInLinearColorSpace(
|
|
shun-iwasawa |
481b59 |
bool settingsIsLinear, bool tileIsLinear) const {
|
|
shun-iwasawa |
481b59 |
ColorSpaceMode mode =
|
|
shun-iwasawa |
481b59 |
static_cast<colorspacemode>(m_colorSpaceMode->getValue());</colorspacemode>
|
|
shun-iwasawa |
481b59 |
return mode == Linear || (mode == Auto && settingsIsLinear);
|
|
shun-iwasawa |
481b59 |
}
|