|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "texception.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tfxparam.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "stdfx.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "tparamset.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
static void OLDRGB2HSV(double r, double g, double b, double *h, double *s,
|
|
Shinya Kitaoka |
120a6e |
double *v) {
|
|
Shinya Kitaoka |
120a6e |
double max, min;
|
|
Shinya Kitaoka |
120a6e |
double delta;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
max = std::max({r, g, b});
|
|
Shinya Kitaoka |
120a6e |
min = std::min({r, g, b});
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
*v = max;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (max != 0)
|
|
Shinya Kitaoka |
120a6e |
*s = (max - min) / max;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
*s = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (*s == 0)
|
|
Shinya Kitaoka |
120a6e |
*h = 0;
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
delta = max - min;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (r == max)
|
|
Shinya Kitaoka |
120a6e |
*h = (g - b) / delta;
|
|
Shinya Kitaoka |
120a6e |
else if (g == max)
|
|
Shinya Kitaoka |
120a6e |
*h = 2 + (b - r) / delta;
|
|
Shinya Kitaoka |
120a6e |
else if (b == max)
|
|
Shinya Kitaoka |
120a6e |
*h = 4 + (r - g) / delta;
|
|
Shinya Kitaoka |
120a6e |
*h = *h * 60;
|
|
Shinya Kitaoka |
120a6e |
if (*h < 0) *h += 360;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
static void OLDHSV2RGB(double hue, double sat, double value, double *red,
|
|
Shinya Kitaoka |
120a6e |
double *green, double *blue) {
|
|
Shinya Kitaoka |
120a6e |
int i;
|
|
Shinya Kitaoka |
120a6e |
double p, q, t, f;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// if (hue > 360 || hue < 0)
|
|
Shinya Kitaoka |
120a6e |
// hue=0;
|
|
Shinya Kitaoka |
120a6e |
if (hue > 360) hue -= 360;
|
|
Shinya Kitaoka |
120a6e |
if (hue < 0) hue += 360;
|
|
Shinya Kitaoka |
120a6e |
if (sat < 0) sat = 0;
|
|
Shinya Kitaoka |
120a6e |
if (sat > 1) sat = 1;
|
|
Shinya Kitaoka |
120a6e |
if (value < 0) value = 0;
|
|
Shinya Kitaoka |
120a6e |
if (value > 1) value = 1;
|
|
Shinya Kitaoka |
120a6e |
if (sat == 0) {
|
|
Shinya Kitaoka |
120a6e |
*red = value;
|
|
Shinya Kitaoka |
120a6e |
*green = value;
|
|
Shinya Kitaoka |
120a6e |
*blue = value;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if (hue == 360) hue = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
hue = hue / 60;
|
|
Shinya Kitaoka |
120a6e |
i = (int)hue;
|
|
Shinya Kitaoka |
120a6e |
f = hue - i;
|
|
Shinya Kitaoka |
120a6e |
p = value * (1 - sat);
|
|
Shinya Kitaoka |
120a6e |
q = value * (1 - (sat * f));
|
|
Shinya Kitaoka |
120a6e |
t = value * (1 - (sat * (1 - f)));
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
switch (i) {
|
|
Shinya Kitaoka |
120a6e |
case 0:
|
|
Shinya Kitaoka |
120a6e |
*red = value;
|
|
Shinya Kitaoka |
120a6e |
*green = t;
|
|
Shinya Kitaoka |
120a6e |
*blue = p;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case 1:
|
|
Shinya Kitaoka |
120a6e |
*red = q;
|
|
Shinya Kitaoka |
120a6e |
*green = value;
|
|
Shinya Kitaoka |
120a6e |
*blue = p;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case 2:
|
|
Shinya Kitaoka |
120a6e |
*red = p;
|
|
Shinya Kitaoka |
120a6e |
*green = value;
|
|
Shinya Kitaoka |
120a6e |
*blue = t;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case 3:
|
|
Shinya Kitaoka |
120a6e |
*red = p;
|
|
Shinya Kitaoka |
120a6e |
*green = q;
|
|
Shinya Kitaoka |
120a6e |
*blue = value;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case 4:
|
|
Shinya Kitaoka |
120a6e |
*red = t;
|
|
Shinya Kitaoka |
120a6e |
*green = p;
|
|
Shinya Kitaoka |
120a6e |
*blue = value;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case 5:
|
|
Shinya Kitaoka |
120a6e |
*red = value;
|
|
Shinya Kitaoka |
120a6e |
*green = p;
|
|
Shinya Kitaoka |
120a6e |
*blue = q;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
d1f6c4 |
class ChangeColorFx final : public TStandardRasterFx {
|
|
Shinya Kitaoka |
120a6e |
FX_PLUGIN_DECLARATION(ChangeColorFx)
|
|
Shinya Kitaoka |
120a6e |
TRasterFxPort m_input;
|
|
Shinya Kitaoka |
120a6e |
TPixelParamP m_from_color;
|
|
Shinya Kitaoka |
120a6e |
TPixelParamP m_to_color;
|
|
Shinya Kitaoka |
120a6e |
TDoubleParamP m_range;
|
|
Shinya Kitaoka |
120a6e |
TDoubleParamP m_falloff;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
ChangeColorFx()
|
|
Shinya Kitaoka |
120a6e |
: m_from_color(TPixel32::Red)
|
|
Shinya Kitaoka |
120a6e |
, m_to_color(TPixel32::Blue)
|
|
Shinya Kitaoka |
120a6e |
, m_range(0.0)
|
|
Shinya Kitaoka |
120a6e |
, m_falloff(0.0) {
|
|
Shinya Kitaoka |
120a6e |
addInputPort("Source", m_input);
|
|
Shinya Kitaoka |
120a6e |
bindParam(this, "range", m_range);
|
|
Shinya Kitaoka |
120a6e |
bindParam(this, "falloff", m_falloff);
|
|
Shinya Kitaoka |
120a6e |
bindParam(this, "from_color", m_from_color);
|
|
Shinya Kitaoka |
120a6e |
bindParam(this, "to_color", m_to_color);
|
|
Shinya Kitaoka |
120a6e |
m_range->setValueRange(0, 100);
|
|
Shinya Kitaoka |
120a6e |
m_falloff->setValueRange(0, 100);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
~ChangeColorFx(){};
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
38fd86 |
bool doGetBBox(double frame, TRectD &bBox,
|
|
Shinya Kitaoka |
38fd86 |
const TRenderSettings &info) override {
|
|
Shinya Kitaoka |
120a6e |
if (m_input.isConnected()) return m_input->doGetBBox(frame, bBox, info);
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
bBox = TRectD();
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
};
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
void doCompute(TTile &tile, double frame, const TRenderSettings &ri) override;
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Campbell Barton |
8c6c57 |
static double normalize_h(double h) {
|
|
Shinya Kitaoka |
120a6e |
if (h < 0) h += 360;
|
|
Shinya Kitaoka |
120a6e |
if (h > 360) h -= 360;
|
|
Shinya Kitaoka |
120a6e |
return h;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void ChangeColorFx::doCompute(TTile &tile, double frame,
|
|
Shinya Kitaoka |
120a6e |
const TRenderSettings &ri) {
|
|
Shinya Kitaoka |
120a6e |
if (!m_input.isConnected()) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_input->compute(tile, frame, ri);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double from_h, from_s, from_v, to_h, to_s, to_v;
|
|
Shinya Kitaoka |
120a6e |
bool swaprange = false, swapfallmin = false, swapfallmax;
|
|
Shinya Kitaoka |
120a6e |
TPixel32 from_color = m_from_color->getPremultipliedValue(frame);
|
|
Shinya Kitaoka |
120a6e |
TPixel32 to_color = m_to_color->getPremultipliedValue(frame);
|
|
Shinya Kitaoka |
120a6e |
double range = m_range->getValue(frame) / 100;
|
|
Shinya Kitaoka |
120a6e |
double falloff = m_falloff->getValue(frame) / 100;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
OLDRGB2HSV(from_color.r / 255.0, from_color.g / 255.0, from_color.b / 255.0,
|
|
Shinya Kitaoka |
120a6e |
&from_h, &from_s, &from_v);
|
|
Shinya Kitaoka |
120a6e |
OLDRGB2HSV(to_color.r / 255.0, to_color.g / 255.0, to_color.b / 255.0, &to_h,
|
|
Shinya Kitaoka |
120a6e |
&to_s, &to_v);
|
|
Shinya Kitaoka |
120a6e |
/*
|
|
Shinya Kitaoka |
120a6e |
int from_hsv[3];
|
|
Shinya Kitaoka |
120a6e |
int to_hsv[3];
|
|
Shinya Kitaoka |
120a6e |
rgb2hsv(from_hsv, from_color);
|
|
Shinya Kitaoka |
120a6e |
rgb2hsv(to_hsv, to_color);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/////////////// verificare ///////
|
|
Shinya Kitaoka |
120a6e |
from_h =((double)from_hsv[0]/255.)*360.;
|
|
Shinya Kitaoka |
120a6e |
from_s =from_hsv[1]/255.;
|
|
Shinya Kitaoka |
120a6e |
from_v =from_hsv[2]/255.;
|
|
Shinya Kitaoka |
120a6e |
to_h =((double)to_hsv[0]/255.)*360.;
|
|
Shinya Kitaoka |
120a6e |
to_s =to_hsv[1]/255.;
|
|
Shinya Kitaoka |
120a6e |
to_v =to_hsv[2]/255.;
|
|
Shinya Kitaoka |
120a6e |
*/
|
|
Shinya Kitaoka |
120a6e |
////////////////////////
|
|
Shinya Kitaoka |
120a6e |
TRaster32P raster32 = tile.getRaster();
|
|
Shinya Kitaoka |
120a6e |
assert(raster32); // per ora gestisco solo i Raster32
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double hmin = from_h - range * 180;
|
|
Shinya Kitaoka |
120a6e |
hmin = normalize_h(hmin);
|
|
Shinya Kitaoka |
120a6e |
double hmax = from_h + range * 180;
|
|
Shinya Kitaoka |
120a6e |
hmax = normalize_h(hmax);
|
|
Shinya Kitaoka |
120a6e |
if (hmax <= hmin) {
|
|
Shinya Kitaoka |
120a6e |
tswap(hmin, hmax);
|
|
Shinya Kitaoka |
120a6e |
swaprange = true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
double smin = from_s - range;
|
|
Shinya Kitaoka |
120a6e |
double smax = from_s + range;
|
|
Shinya Kitaoka |
120a6e |
double vmin = from_v - range;
|
|
Shinya Kitaoka |
120a6e |
double vmax = from_v + range;
|
|
Shinya Kitaoka |
120a6e |
double hfallmin = hmin - falloff * 180;
|
|
Shinya Kitaoka |
120a6e |
double hfallmax = hmax + falloff * 180;
|
|
Shinya Kitaoka |
120a6e |
hfallmin = normalize_h(hfallmin);
|
|
Shinya Kitaoka |
120a6e |
hfallmax = normalize_h(hfallmax);
|
|
Shinya Kitaoka |
120a6e |
if (hfallmin > hmin) {
|
|
Shinya Kitaoka |
120a6e |
swapfallmin = true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (hfallmax < hmax) {
|
|
Shinya Kitaoka |
120a6e |
swapfallmax = true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
double sfallmin = smin - falloff;
|
|
Shinya Kitaoka |
120a6e |
double sfallmax = smax + falloff;
|
|
Shinya Kitaoka |
120a6e |
double vfallmin = vmin - falloff;
|
|
Shinya Kitaoka |
120a6e |
double vfallmax = vmax + falloff;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int j;
|
|
Shinya Kitaoka |
120a6e |
raster32->lock();
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < raster32->getLy(); j++) {
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *pix = raster32->pixels(j);
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *endPix = pix + raster32->getLx();
|
|
Shinya Kitaoka |
120a6e |
while (pix < endPix) {
|
|
Shinya Kitaoka |
120a6e |
double r, g, b, h, s, v;
|
|
Shinya Kitaoka |
120a6e |
r = pix->r / 255.0;
|
|
Shinya Kitaoka |
120a6e |
g = pix->g / 255.0;
|
|
Shinya Kitaoka |
120a6e |
b = pix->b / 255.0;
|
|
Shinya Kitaoka |
120a6e |
// int hsv[3];
|
|
Shinya Kitaoka |
120a6e |
OLDRGB2HSV(r, g, b, &h, &s, &v);
|
|
Shinya Kitaoka |
120a6e |
int hflag = (h <= hmax && h >= hmin);
|
|
Shinya Kitaoka |
120a6e |
if (swaprange) hflag = !hflag;
|
|
Shinya Kitaoka |
120a6e |
if (hflag && s <= smax && s >= smin && v <= vmax && v >= vmin)
|
|
Shinya Kitaoka |
120a6e |
*pix = to_color;
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
double hcorr = 0;
|
|
Shinya Kitaoka |
120a6e |
double scorr = 0;
|
|
Shinya Kitaoka |
120a6e |
double vcorr = 0;
|
|
Shinya Kitaoka |
120a6e |
int hfallminflag = (h <= hmin && h >= hfallmin);
|
|
Shinya Kitaoka |
120a6e |
if (hfallminflag) hcorr = h - hmin;
|
|
Shinya Kitaoka |
120a6e |
int hfallmaxflag = (h >= hmax && h <= hfallmax);
|
|
Shinya Kitaoka |
120a6e |
if (hfallmaxflag) hcorr = h - hmax;
|
|
Shinya Kitaoka |
120a6e |
if (hcorr) {
|
|
Shinya Kitaoka |
120a6e |
if (s <= smin && s >= sfallmin) scorr = s - smin;
|
|
Shinya Kitaoka |
120a6e |
if (s >= smax && s <= sfallmax) scorr = s - smax;
|
|
Shinya Kitaoka |
120a6e |
if (v <= vmin && v >= vfallmin) vcorr = v - vmin;
|
|
Shinya Kitaoka |
120a6e |
if (v >= vmax && v <= vfallmax) vcorr = v - vmax;
|
|
Shinya Kitaoka |
120a6e |
if (s < smin && s > sfallmin) scorr = s - smin;
|
|
Shinya Kitaoka |
120a6e |
if (s > smax && s < sfallmax) scorr = s - smax;
|
|
Shinya Kitaoka |
120a6e |
h = to_h + hcorr;
|
|
Shinya Kitaoka |
120a6e |
if (h < 0) h += 360;
|
|
Shinya Kitaoka |
120a6e |
if (h > 360) h -= 360;
|
|
Shinya Kitaoka |
120a6e |
OLDHSV2RGB(h, s, v, &r, &g, &b);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
pix->r = (UCHAR)(r * 255);
|
|
Shinya Kitaoka |
120a6e |
pix->g = (UCHAR)(g * 255);
|
|
Shinya Kitaoka |
120a6e |
pix->b = (UCHAR)(b * 255);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
// premultiply(*pix);
|
|
Shinya Kitaoka |
120a6e |
*pix++;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
raster32->unlock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// FX_PLUGIN_IDENTIFIER(ChangeColorFx , "changeColorFx")
|