|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "trop.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tpixelutils.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/* NOTE: Scale operations can be performed using Look-Up-Tables.
|
|
Toshihiro Shimizu |
890ddd |
This is convenient for 8-bit channels, but perhaps not for 16-bit ones:
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
In the 32-bit case, we perform max 256 channel operations,
|
|
Toshihiro Shimizu |
890ddd |
equal to performing plain scale on a 16 x 16 image.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
In the 64-bit case, the cost is 65536 channel operations,
|
|
Toshihiro Shimizu |
890ddd |
equal to performing plain scale on a 256 x 256 image.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
The raster size is used to discriminate LUT usage in the latter case
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
namespace {
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename chan=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void buildLUT(Chan *lut, double a, double k, int chanLow, int chanHigh) {
|
|
Shinya Kitaoka |
120a6e |
int i, max = (std::numeric_limits<chan>::max)();</chan>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
a += 0.5; // round rather than trunc
|
|
shun-iwasawa |
481b59 |
for (i = 0; i <= max; ++i)
|
|
Shinya Kitaoka |
120a6e |
lut[i] = tcrop((int)(a + i * k), chanLow, chanHigh);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename t=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void do_greyScale_lut(TRasterPT<t> rout, TRasterPT<t> rin, double a, double k,</t></t>
|
|
Shinya Kitaoka |
120a6e |
int out0, int out1) {
|
|
Shinya Kitaoka |
120a6e |
assert(rout->getSize() == rin->getSize());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
typedef typename T::Channel Channel;
|
|
Shinya Kitaoka |
120a6e |
int chanValuesCount = T::maxChannelValue + 1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
int fac = chanValuesCount / 256;
|
|
Shinya Kitaoka |
120a6e |
out0 = std::max(fac * out0, 0),
|
|
Shinya Kitaoka |
120a6e |
out1 = std::min(fac * out1, T::maxChannelValue);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Build lut
|
|
Shinya Kitaoka |
120a6e |
Channel *lut = new Channel[chanValuesCount];
|
|
Shinya Kitaoka |
120a6e |
buildLUT(lut, a, k, out0, out1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Perform scale
|
|
Shinya Kitaoka |
120a6e |
T *in, *end, *out;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
int y, lx = rin->getLx(), ly = rin->getLy();
|
|
Shinya Kitaoka |
120a6e |
for (y = 0; y < ly; ++y) {
|
|
Shinya Kitaoka |
120a6e |
in = rin->pixels(y), end = in + lx, out = rout->pixels(y);
|
|
Shinya Kitaoka |
120a6e |
for (; in < end; ++in, ++out) out->value = lut[in->value];
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
delete[] lut;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename t=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void do_greyAdjust(TRasterPT<t> rout, TRasterPT<t> rin, const int in0,</t></t>
|
|
Shinya Kitaoka |
120a6e |
const int in1, const int out0, const int out1) {
|
|
Shinya Kitaoka |
120a6e |
typedef typename T::Channel Channel;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
assert(rout->getSize() == rin->getSize());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Build scale parameters
|
|
Shinya Kitaoka |
120a6e |
double k = (out1 - out0) / (double)(in1 - in0);
|
|
Shinya Kitaoka |
120a6e |
double a = out0 - k * in0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
do_greyScale_lut(rout, rin, a, k, out0, out1);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename t=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void do_rgbmScale_lut(TRasterPT<t> rout, TRasterPT<t> rin, const double *a,</t></t>
|
|
Shinya Kitaoka |
120a6e |
const double *k, const int *out0, const int *out1) {
|
|
Shinya Kitaoka |
120a6e |
assert(rout->getSize() == rin->getSize());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
typedef typename T::Channel Channel;
|
|
Shinya Kitaoka |
120a6e |
int m, max = T::maxChannelValue, chanValuesCount = max + 1;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int fac = chanValuesCount / 256;
|
|
Shinya Kitaoka |
120a6e |
int out0R = std::max(fac * out0[0], 0),
|
|
Shinya Kitaoka |
120a6e |
out1R = std::min(fac * out1[0], T::maxChannelValue);
|
|
Shinya Kitaoka |
120a6e |
int out0G = std::max(fac * out0[1], 0),
|
|
Shinya Kitaoka |
120a6e |
out1G = std::min(fac * out1[1], T::maxChannelValue);
|
|
Shinya Kitaoka |
120a6e |
int out0B = std::max(fac * out0[2], 0),
|
|
Shinya Kitaoka |
120a6e |
out1B = std::min(fac * out1[2], T::maxChannelValue);
|
|
Shinya Kitaoka |
120a6e |
int out0M = std::max(fac * out0[3], 0),
|
|
Shinya Kitaoka |
120a6e |
out1M = std::min(fac * out1[3], T::maxChannelValue);
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
481b59 |
double aFac[4];
|
|
shun-iwasawa |
481b59 |
for (int i = 0; i < 4; i++) aFac[i] = a[i] * (double)fac;
|
|
shun-iwasawa |
481b59 |
|
|
Shinya Kitaoka |
120a6e |
// Build luts
|
|
Shinya Kitaoka |
120a6e |
Channel *lut_r = new Channel[chanValuesCount];
|
|
shun-iwasawa |
481b59 |
buildLUT(lut_r, aFac[0], k[0], out0R, out1R);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
Channel *lut_g = new Channel[chanValuesCount];
|
|
shun-iwasawa |
481b59 |
buildLUT(lut_g, aFac[1], k[1], out0G, out1G);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
Channel *lut_b = new Channel[chanValuesCount];
|
|
shun-iwasawa |
481b59 |
buildLUT(lut_b, aFac[2], k[2], out0B, out1B);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
Channel *lut_m = new Channel[chanValuesCount];
|
|
shun-iwasawa |
481b59 |
buildLUT(lut_m, aFac[3], k[3], out0M, out1M);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Retrieve de/premultiplication luts
|
|
Shinya Kitaoka |
120a6e |
const double *lut_prem = premultiplyTable<channel>();</channel>
|
|
Shinya Kitaoka |
120a6e |
const double *lut_deprem = depremultiplyTable<channel>();</channel>
|
|
Shinya Kitaoka |
120a6e |
double premFac, depremFac;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Process raster
|
|
Shinya Kitaoka |
120a6e |
int y, lx = rin->getLx(), ly = rin->getLy();
|
|
Shinya Kitaoka |
120a6e |
T *in, *end, *out;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (y = 0; y < ly; ++y) {
|
|
Shinya Kitaoka |
120a6e |
in = rin->pixels(y), end = in + lx, out = rout->pixels(y);
|
|
Shinya Kitaoka |
120a6e |
for (; in < end; ++in, ++out) {
|
|
Shinya Kitaoka |
120a6e |
m = lut_m[in->m];
|
|
Shinya Kitaoka |
120a6e |
depremFac = lut_deprem[in->m];
|
|
Shinya Kitaoka |
120a6e |
premFac = lut_prem[m];
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
out->r = premFac * lut_r[std::min((int)(in->r * depremFac), max)];
|
|
Shinya Kitaoka |
120a6e |
out->g = premFac * lut_g[std::min((int)(in->g * depremFac), max)];
|
|
Shinya Kitaoka |
120a6e |
out->b = premFac * lut_b[std::min((int)(in->b * depremFac), max)];
|
|
Shinya Kitaoka |
120a6e |
out->m = m;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
delete[] lut_r;
|
|
Shinya Kitaoka |
120a6e |
delete[] lut_g;
|
|
Shinya Kitaoka |
120a6e |
delete[] lut_b;
|
|
Shinya Kitaoka |
120a6e |
delete[] lut_m;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename t=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void do_rgbmScale(TRasterPT<t> rout, TRasterPT<t> rin, const double *a,</t></t>
|
|
Shinya Kitaoka |
120a6e |
const double *k, const int *out0, const int *out1) {
|
|
Shinya Kitaoka |
120a6e |
assert(rout->getSize() == rin->getSize());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
typedef typename T::Channel Channel;
|
|
Shinya Kitaoka |
120a6e |
int m, chanValuesCount = T::maxChannelValue + 1;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int fac = chanValuesCount / 256;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int out0R = std::max(fac * out0[0], 0),
|
|
Shinya Kitaoka |
120a6e |
out1R = std::min(fac * out1[0], T::maxChannelValue);
|
|
Shinya Kitaoka |
120a6e |
int out0G = std::max(fac * out0[1], 0),
|
|
Shinya Kitaoka |
120a6e |
out1G = std::min(fac * out1[1], T::maxChannelValue);
|
|
Shinya Kitaoka |
120a6e |
int out0B = std::max(fac * out0[2], 0),
|
|
Shinya Kitaoka |
120a6e |
out1B = std::min(fac * out1[2], T::maxChannelValue);
|
|
Shinya Kitaoka |
120a6e |
int out0M = std::max(fac * out0[3], 0),
|
|
Shinya Kitaoka |
120a6e |
out1M = std::min(fac * out1[3], T::maxChannelValue);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Retrieve de/premultiplication luts
|
|
Shinya Kitaoka |
120a6e |
const double *lut_prem = premultiplyTable<channel>();</channel>
|
|
Shinya Kitaoka |
120a6e |
const double *lut_deprem = depremultiplyTable<channel>();</channel>
|
|
Shinya Kitaoka |
120a6e |
double premFac, depremFac;
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
481b59 |
double aFac[4];
|
|
shun-iwasawa |
481b59 |
for (int i = 0; i < 4; i++) aFac[i] = a[i] * (double)fac;
|
|
shun-iwasawa |
481b59 |
|
|
Shinya Kitaoka |
120a6e |
// Process raster
|
|
Shinya Kitaoka |
120a6e |
int y, lx = rin->getLx(), ly = rin->getLy();
|
|
Shinya Kitaoka |
120a6e |
T *in, *end, *out;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (y = 0; y < ly; ++y) {
|
|
Shinya Kitaoka |
120a6e |
in = rin->pixels(y), end = in + lx, out = rout->pixels(y);
|
|
Shinya Kitaoka |
120a6e |
for (; in < end; ++in, ++out) {
|
|
shun-iwasawa |
481b59 |
m = tcrop((int)(aFac[3] + k[3] * in->m), out0M, out1M);
|
|
Shinya Kitaoka |
120a6e |
depremFac = lut_deprem[in->m];
|
|
Shinya Kitaoka |
120a6e |
premFac = lut_prem[m];
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
481b59 |
out->r = premFac *
|
|
shun-iwasawa |
481b59 |
tcrop((int)(aFac[0] + k[0] * in->r * depremFac), out0R, out1R);
|
|
shun-iwasawa |
481b59 |
out->g = premFac *
|
|
shun-iwasawa |
481b59 |
tcrop((int)(aFac[1] + k[1] * in->g * depremFac), out0G, out1G);
|
|
shun-iwasawa |
481b59 |
out->b = premFac *
|
|
shun-iwasawa |
481b59 |
tcrop((int)(aFac[2] + k[2] * in->b * depremFac), out0B, out1B);
|
|
Shinya Kitaoka |
120a6e |
out->m = m;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
shun-iwasawa |
481b59 |
template <>
|
|
shun-iwasawa |
481b59 |
void do_rgbmScale<tpixelf>(TRasterFP rout, TRasterFP rin, const double *a,</tpixelf>
|
|
shun-iwasawa |
481b59 |
const double *k, const int *out0, const int *out1) {
|
|
shun-iwasawa |
481b59 |
assert(rout->getSize() == rin->getSize());
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
float fac = 1.f / 255.f;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
float out0R = std::max(fac * (float)out0[0], 0.f);
|
|
shun-iwasawa |
481b59 |
float out1R = std::min(fac * (float)out1[0], 1.f);
|
|
shun-iwasawa |
481b59 |
float out0G = std::max(fac * (float)out0[1], 0.f);
|
|
shun-iwasawa |
481b59 |
float out1G = std::min(fac * (float)out1[1], 1.f);
|
|
shun-iwasawa |
481b59 |
float out0B = std::max(fac * (float)out0[2], 0.f);
|
|
shun-iwasawa |
481b59 |
float out1B = std::min(fac * (float)out1[2], 1.f);
|
|
shun-iwasawa |
481b59 |
float out0M = std::max(fac * (float)out0[3], 0.f);
|
|
shun-iwasawa |
481b59 |
float out1M = std::min(fac * (float)out1[3], 1.f);
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
float aFac[4];
|
|
shun-iwasawa |
481b59 |
for (int i = 0; i < 4; i++) aFac[i] = a[i] * (float)fac;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
// Process raster
|
|
shun-iwasawa |
481b59 |
int y, lx = rin->getLx(), ly = rin->getLy();
|
|
shun-iwasawa |
481b59 |
TPixelF *in, *end, *out;
|
|
shun-iwasawa |
481b59 |
float m;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
for (y = 0; y < ly; ++y) {
|
|
shun-iwasawa |
481b59 |
in = rin->pixels(y), end = in + lx, out = rout->pixels(y);
|
|
shun-iwasawa |
481b59 |
for (; in < end; ++in, ++out) {
|
|
shun-iwasawa |
481b59 |
m = tcrop(aFac[3] + (float)k[3] * in->m, out0M, out1M);
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
if (in->m <= 0.f) {
|
|
shun-iwasawa |
481b59 |
out->r = m * tcrop(aFac[0], out0R, out1R);
|
|
shun-iwasawa |
481b59 |
out->g = m * tcrop(aFac[1], out0G, out1G);
|
|
shun-iwasawa |
481b59 |
out->b = m * tcrop(aFac[2], out0B, out1B);
|
|
shun-iwasawa |
481b59 |
out->m = m;
|
|
shun-iwasawa |
481b59 |
} else {
|
|
shun-iwasawa |
481b59 |
out->r = m * tcrop(aFac[0] + (float)k[0] * in->r / in->m, out0R, out1R);
|
|
shun-iwasawa |
481b59 |
out->g = m * tcrop(aFac[1] + (float)k[1] * in->g / in->m, out0G, out1G);
|
|
shun-iwasawa |
481b59 |
out->b = m * tcrop(aFac[2] + (float)k[2] * in->b / in->m, out0B, out1B);
|
|
shun-iwasawa |
481b59 |
out->m = m;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
//-----------------------------------------------------------------------------
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
void do_rgbmScaleFloat(TRasterFP rout, TRasterFP rin, const double *a,
|
|
shun-iwasawa |
481b59 |
const double *k, const int *out0, const int *out1) {
|
|
shun-iwasawa |
481b59 |
assert(rout->getSize() == rin->getSize());
|
|
shun-iwasawa |
481b59 |
float fac = 1.f / 255.f;
|
|
shun-iwasawa |
481b59 |
float out0R = std::max(fac * (float)out0[0], 0.f);
|
|
shun-iwasawa |
481b59 |
float out1R = fac * (float)out1[0];
|
|
shun-iwasawa |
481b59 |
float out0G = std::max(fac * (float)out0[1], 0.f);
|
|
shun-iwasawa |
481b59 |
float out1G = fac * (float)out1[1];
|
|
shun-iwasawa |
481b59 |
float out0B = std::max(fac * (float)out0[2], 0.f);
|
|
shun-iwasawa |
481b59 |
float out1B = fac * (float)out1[2];
|
|
shun-iwasawa |
481b59 |
float out0M = std::max(fac * (float)out0[3], 0.f);
|
|
shun-iwasawa |
481b59 |
float out1M = fac * (float)out1[3];
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
float aFac[4];
|
|
shun-iwasawa |
481b59 |
for (int i = 0; i < 4; i++) aFac[i] = a[i] * fac;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
// Process raster
|
|
shun-iwasawa |
481b59 |
for (int y = 0; y < rin->getLy(); ++y) {
|
|
shun-iwasawa |
481b59 |
TPixelF *in = rin->pixels(y), *out = rout->pixels(y);
|
|
shun-iwasawa |
481b59 |
TPixelF *end = in + rin->getLx();
|
|
shun-iwasawa |
481b59 |
for (; in < end; ++in, ++out) {
|
|
shun-iwasawa |
481b59 |
out->m = tcrop(aFac[3] + (float)k[3] * in->m, out0M, out1M);
|
|
shun-iwasawa |
481b59 |
if (out->m == 0.f) {
|
|
shun-iwasawa |
481b59 |
out->r = 0.f;
|
|
shun-iwasawa |
481b59 |
out->g = 0.f;
|
|
shun-iwasawa |
481b59 |
out->b = 0.f;
|
|
shun-iwasawa |
481b59 |
} else if (in->m == 0.f) {
|
|
shun-iwasawa |
481b59 |
out->r = out->m * tcrop(aFac[0], out0R, out1R);
|
|
shun-iwasawa |
481b59 |
out->g = out->m * tcrop(aFac[1], out0G, out1G);
|
|
shun-iwasawa |
481b59 |
out->b = out->m * tcrop(aFac[2], out0B, out1B);
|
|
shun-iwasawa |
481b59 |
} else {
|
|
shun-iwasawa |
481b59 |
out->r =
|
|
shun-iwasawa |
481b59 |
out->m * tcrop(aFac[0] + (float)k[0] * in->r / in->m, out0R, out1R);
|
|
shun-iwasawa |
481b59 |
out->g =
|
|
shun-iwasawa |
481b59 |
out->m * tcrop(aFac[1] + (float)k[1] * in->g / in->m, out0G, out1G);
|
|
shun-iwasawa |
481b59 |
out->b =
|
|
shun-iwasawa |
481b59 |
out->m * tcrop(aFac[2] + (float)k[2] * in->b / in->m, out0B, out1B);
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
//-----------------------------------------------------------------------------
|
|
shun-iwasawa |
481b59 |
|
|
Toshihiro Shimizu |
890ddd |
template <typename scalefunc="" t,="" typename=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
void do_rgbmAdjust(TRasterPT<t> rout, TRasterPT<t> rin, ScaleFunc scaleFunc,</t></t>
|
|
Shinya Kitaoka |
120a6e |
const int *in0, const int *in1, const int *out0,
|
|
shun-iwasawa |
481b59 |
const int *out1, bool doClamp = true) {
|
|
Shinya Kitaoka |
120a6e |
assert(rout->getSize() == rin->getSize());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
double a[5], k[5];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Build scale parameters
|
|
Shinya Kitaoka |
120a6e |
int i;
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < 5; ++i) {
|
|
Shinya Kitaoka |
120a6e |
k[i] = (out1[i] - out0[i]) / (double)(in1[i] - in0[i]);
|
|
Shinya Kitaoka |
120a6e |
a[i] = out0[i] - k[i] * in0[i];
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
for (i = 1; i < 4; ++i) {
|
|
Shinya Kitaoka |
120a6e |
a[i] += k[i] * a[0];
|
|
Shinya Kitaoka |
120a6e |
k[i] *= k[0];
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Ensure that the output is cropped according to output params
|
|
Shinya Kitaoka |
120a6e |
int out0i[4], out1i[4];
|
|
shun-iwasawa |
481b59 |
if (doClamp) {
|
|
shun-iwasawa |
481b59 |
out0i[0] = std::max(out0[0], tcrop((int)(a[0] + k[0] * out0[1]), 0, 255));
|
|
shun-iwasawa |
481b59 |
out1i[0] = std::min(out1[0], tcrop((int)(a[0] + k[0] * out1[1]), 0, 255));
|
|
Toshihiro Shimizu |
890ddd |
|
|
shun-iwasawa |
481b59 |
out0i[1] = std::max(out0[0], tcrop((int)(a[0] + k[0] * out0[2]), 0, 255));
|
|
shun-iwasawa |
481b59 |
out1i[1] = std::min(out1[0], tcrop((int)(a[0] + k[0] * out1[2]), 0, 255));
|
|
Toshihiro Shimizu |
890ddd |
|
|
shun-iwasawa |
481b59 |
out0i[2] = std::max(out0[0], tcrop((int)(a[0] + k[0] * out0[3]), 0, 255));
|
|
shun-iwasawa |
481b59 |
out1i[2] = std::min(out1[0], tcrop((int)(a[0] + k[0] * out1[3]), 0, 255));
|
|
shun-iwasawa |
481b59 |
} else {
|
|
shun-iwasawa |
481b59 |
out0i[0] = std::max(out0[0], (int)(a[0] + k[0] * out0[1]));
|
|
shun-iwasawa |
481b59 |
out1i[0] = std::min(out1[0], (int)(a[0] + k[0] * out1[1]));
|
|
Toshihiro Shimizu |
890ddd |
|
|
shun-iwasawa |
481b59 |
out0i[1] = std::max(out0[0], (int)(a[0] + k[0] * out0[2]));
|
|
shun-iwasawa |
481b59 |
out1i[1] = std::min(out1[0], (int)(a[0] + k[0] * out1[2]));
|
|
Toshihiro Shimizu |
890ddd |
|
|
shun-iwasawa |
481b59 |
out0i[2] = std::max(out0[0], (int)(a[0] + k[0] * out0[3]));
|
|
shun-iwasawa |
481b59 |
out1i[2] = std::min(out1[0], (int)(a[0] + k[0] * out1[3]));
|
|
shun-iwasawa |
481b59 |
}
|
|
Shinya Kitaoka |
120a6e |
out0i[3] = out0[4];
|
|
Shinya Kitaoka |
120a6e |
out1i[3] = out1[4];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
scaleFunc(rout, rin, &a[1], &k[1], out0i, out1i);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
} // namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TRop::rgbmScale(TRasterP rout, TRasterP rin, const double *k,
|
|
Shinya Kitaoka |
120a6e |
const double *a, const int *out0, const int *out1) {
|
|
Shinya Kitaoka |
120a6e |
if (rout->getSize() != rin->getSize()) throw TRopException("size mismatch");
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
rout->lock();
|
|
Shinya Kitaoka |
120a6e |
rin->lock();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if ((TRaster32P)rout && (TRaster32P)rin)
|
|
Shinya Kitaoka |
120a6e |
do_rgbmScale_lut<tpixel32>(rout, rin, a, k, out0, out1);</tpixel32>
|
|
Shinya Kitaoka |
120a6e |
else if ((TRaster64P)rout && (TRaster64P)rin) {
|
|
Shinya Kitaoka |
120a6e |
if (rin->getLx() * rin->getLy() < TPixel64::maxChannelValue)
|
|
Shinya Kitaoka |
120a6e |
do_rgbmScale<tpixel64>(rout, rin, a, k, out0, out1);</tpixel64>
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
do_rgbmScale_lut<tpixel64>(rout, rin, a, k, out0, out1);</tpixel64>
|
|
Shinya Kitaoka |
120a6e |
} else if ((TRasterGR8P)rout && (TRasterGR8P)rin)
|
|
Shinya Kitaoka |
120a6e |
do_greyScale_lut<tpixelgr8>(rout, rin, a[0], k[0], out0[0], out1[0]);</tpixelgr8>
|
|
Shinya Kitaoka |
120a6e |
else if ((TRasterGR16P)rout && (TRasterGR16P)rin)
|
|
Shinya Kitaoka |
120a6e |
do_greyScale_lut<tpixelgr16>(rout, rin, a[0], k[0], out0[0], out1[0]);</tpixelgr16>
|
|
shun-iwasawa |
481b59 |
else if ((TRasterFP)rout && (TRasterFP)rin)
|
|
shun-iwasawa |
481b59 |
do_rgbmScale<tpixelf>(rout, rin, a, k, out0, out1);</tpixelf>
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
rout->unlock();
|
|
Shinya Kitaoka |
120a6e |
rin->unlock();
|
|
Shinya Kitaoka |
120a6e |
throw TRopException("pixel type mismatch");
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
rout->unlock();
|
|
Shinya Kitaoka |
120a6e |
rin->unlock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TRop::rgbmScale(TRasterP rout, TRasterP rin, double kr, double kg,
|
|
Shinya Kitaoka |
120a6e |
double kb, double km, double ar, double ag, double ab,
|
|
Shinya Kitaoka |
120a6e |
double am) {
|
|
Shinya Kitaoka |
120a6e |
double k[4], a[4];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
a[0] = ar, a[1] = ag, a[2] = ab, a[3] = am;
|
|
Shinya Kitaoka |
120a6e |
k[0] = kr, k[1] = kg, k[2] = kb, k[3] = km;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
int out0[4], out1[4];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
out0[0] = out0[1] = out0[2] = out0[3] = 0;
|
|
Shinya Kitaoka |
120a6e |
out1[0] = out1[1] = out1[2] = out1[3] = 255;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
rgbmScale(rout, rin, k, a, out0, out1);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TRop::rgbmAdjust(TRasterP rout, TRasterP rin, const int *in0,
|
|
Shinya Kitaoka |
120a6e |
const int *in1, const int *out0, const int *out1) {
|
|
Shinya Kitaoka |
120a6e |
if (rout->getSize() != rin->getSize()) throw TRopException("size mismatch");
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
rout->lock();
|
|
Shinya Kitaoka |
120a6e |
rin->lock();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if ((TRaster32P)rout && (TRaster32P)rin)
|
|
Shinya Kitaoka |
120a6e |
do_rgbmAdjust<tpixel32>(rout, rin, &do_rgbmScale_lut<tpixel32>, in0, in1,</tpixel32></tpixel32>
|
|
Shinya Kitaoka |
120a6e |
out0, out1);
|
|
Shinya Kitaoka |
120a6e |
else if ((TRaster64P)rout && (TRaster64P)rin) {
|
|
Shinya Kitaoka |
120a6e |
if (rin->getLx() * rin->getLy() < TPixel64::maxChannelValue)
|
|
Shinya Kitaoka |
120a6e |
do_rgbmAdjust<tpixel64>(rout, rin, &do_rgbmScale<tpixel64>, in0, in1,</tpixel64></tpixel64>
|
|
Shinya Kitaoka |
120a6e |
out0, out1);
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
do_rgbmAdjust<tpixel64>(rout, rin, &do_rgbmScale_lut<tpixel64>, in0, in1,</tpixel64></tpixel64>
|
|
Shinya Kitaoka |
120a6e |
out0, out1);
|
|
shun-iwasawa |
481b59 |
} else if ((TRasterFP)rout && (TRasterFP)rin)
|
|
shun-iwasawa |
481b59 |
do_rgbmAdjust<tpixelf>(rout, rin, &do_rgbmScaleFloat, in0, in1, out0, out1,</tpixelf>
|
|
shun-iwasawa |
481b59 |
false);
|
|
shun-iwasawa |
481b59 |
else if ((TRasterGR8P)rout && (TRasterGR8P)rin)
|
|
Shinya Kitaoka |
120a6e |
do_greyAdjust<tpixelgr8>(rout, rin, in0[0], in1[0], out0[0], out1[0]);</tpixelgr8>
|
|
Shinya Kitaoka |
120a6e |
else if ((TRasterGR16P)rout && (TRasterGR16P)rin)
|
|
Shinya Kitaoka |
120a6e |
do_greyAdjust<tpixelgr16>(rout, rin, in0[0], in1[0], out0[0], out1[0]);</tpixelgr16>
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
rout->unlock();
|
|
Shinya Kitaoka |
120a6e |
rin->unlock();
|
|
Shinya Kitaoka |
120a6e |
throw TRopException("pixel type mismatch");
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
rout->unlock();
|
|
Shinya Kitaoka |
120a6e |
rin->unlock();
|
|
Toshihiro Shimizu |
890ddd |
}
|