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