Blob Blame Raw


#include "texception.h"
#include "tfxparam.h"
#include "stdfx.h"

#include "tparamset.h"

static void OLDRGB2HSV(double r, double g, double b,
					   double *h, double *s, double *v)
{
	double max, min;
	double delta;

	max = std::max({r, g, b});
	min = std::min({r, g, b});

	*v = max;

	if (max != 0)
		*s = (max - min) / max;
	else
		*s = 0;

	if (*s == 0)
		*h = 0;
	else {
		delta = max - min;

		if (r == max)
			*h = (g - b) / delta;
		else if (g == max)
			*h = 2 + (b - r) / delta;
		else if (b == max)
			*h = 4 + (r - g) / delta;
		*h = *h * 60;
		if (*h < 0)
			*h += 360;
	}
}

static void OLDHSV2RGB(double hue, double sat, double value,
					   double *red, double *green, double *blue)
{
	int i;
	double p, q, t, f;

	//  if (hue > 360 || hue < 0)
	//    hue=0;
	if (hue > 360)
		hue -= 360;
	if (hue < 0)
		hue += 360;
	if (sat < 0)
		sat = 0;
	if (sat > 1)
		sat = 1;
	if (value < 0)
		value = 0;
	if (value > 1)
		value = 1;
	if (sat == 0) {
		*red = value;
		*green = value;
		*blue = value;
	} else {
		if (hue == 360)
			hue = 0;

		hue = hue / 60;
		i = (int)hue;
		f = hue - i;
		p = value * (1 - sat);
		q = value * (1 - (sat * f));
		t = value * (1 - (sat * (1 - f)));

		switch (i) {
		case 0:
			*red = value;
			*green = t;
			*blue = p;
			break;
		case 1:
			*red = q;
			*green = value;
			*blue = p;
			break;
		case 2:
			*red = p;
			*green = value;
			*blue = t;
			break;
		case 3:
			*red = p;
			*green = q;
			*blue = value;
			break;
		case 4:
			*red = t;
			*green = p;
			*blue = value;
			break;
		case 5:
			*red = value;
			*green = p;
			*blue = q;
			break;
		}
	}
}

class ChangeColorFx : public TStandardRasterFx
{
	FX_PLUGIN_DECLARATION(ChangeColorFx)
	TRasterFxPort m_input;
	TPixelParamP m_from_color;
	TPixelParamP m_to_color;
	TDoubleParamP m_range;
	TDoubleParamP m_falloff;

public:
	ChangeColorFx()
		: m_from_color(TPixel32::Red), m_to_color(TPixel32::Blue), m_range(0.0), m_falloff(0.0)
	{
		addInputPort("Source", m_input);
		bindParam(this, "range", m_range);
		bindParam(this, "falloff", m_falloff);
		bindParam(this, "from_color", m_from_color);
		bindParam(this, "to_color", m_to_color);
		m_range->setValueRange(0, 100);
		m_falloff->setValueRange(0, 100);
	}
	~ChangeColorFx(){};

	bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info)
	{
		if (m_input.isConnected())
			return m_input->doGetBBox(frame, bBox, info);
		{
			bBox = TRectD();
			return false;
		}
	};

	void doCompute(TTile &tile, double frame, const TRenderSettings &ri);
};

double normalize_h(double h)
{
	if (h < 0)
		h += 360;
	if (h > 360)
		h -= 360;
	return h;
}
//------------------------------------------------------------------------------

void ChangeColorFx::doCompute(TTile &tile, double frame, const TRenderSettings &ri)
{
	if (!m_input.isConnected())
		return;

	m_input->compute(tile, frame, ri);

	double from_h, from_s, from_v, to_h, to_s, to_v;
	bool swaprange = false, swapfallmin = false, swapfallmax;
	TPixel32 from_color = m_from_color->getPremultipliedValue(frame);
	TPixel32 to_color = m_to_color->getPremultipliedValue(frame);
	double range = m_range->getValue(frame) / 100;
	double falloff = m_falloff->getValue(frame) / 100;

	OLDRGB2HSV(from_color.r / 255.0, from_color.g / 255.0, from_color.b / 255.0, &from_h, &from_s, &from_v);
	OLDRGB2HSV(to_color.r / 255.0, to_color.g / 255.0, to_color.b / 255.0, &to_h, &to_s, &to_v);
	/*  
  int from_hsv[3];
  int to_hsv[3];
  rgb2hsv(from_hsv, from_color);
  rgb2hsv(to_hsv, to_color);
 
///////////////  verificare   /////// 
  from_h =((double)from_hsv[0]/255.)*360.;
  from_s =from_hsv[1]/255.;
  from_v =from_hsv[2]/255.;
  to_h =((double)to_hsv[0]/255.)*360.;
  to_s =to_hsv[1]/255.;
  to_v =to_hsv[2]/255.;
  */
	////////////////////////
	TRaster32P raster32 = tile.getRaster();
	assert(raster32); // per ora gestisco solo i Raster32

	double hmin = from_h - range * 180;
	hmin = normalize_h(hmin);
	double hmax = from_h + range * 180;
	hmax = normalize_h(hmax);
	if (hmax <= hmin) {
		tswap(hmin, hmax);
		swaprange = true;
	}
	double smin = from_s - range;
	double smax = from_s + range;
	double vmin = from_v - range;
	double vmax = from_v + range;
	double hfallmin = hmin - falloff * 180;
	double hfallmax = hmax + falloff * 180;
	hfallmin = normalize_h(hfallmin);
	hfallmax = normalize_h(hfallmax);
	if (hfallmin > hmin) {
		swapfallmin = true;
	}
	if (hfallmax < hmax) {
		swapfallmax = true;
	}
	double sfallmin = smin - falloff;
	double sfallmax = smax + falloff;
	double vfallmin = vmin - falloff;
	double vfallmax = vmax + falloff;

	int j;
	raster32->lock();
	for (j = 0; j < raster32->getLy(); j++) {
		TPixel32 *pix = raster32->pixels(j);
		TPixel32 *endPix = pix + raster32->getLx();
		while (pix < endPix) {
			double r, g, b, h, s, v;
			r = pix->r / 255.0;
			g = pix->g / 255.0;
			b = pix->b / 255.0;
			//int hsv[3];
			OLDRGB2HSV(r, g, b, &h, &s, &v);
			int hflag = (h <= hmax && h >= hmin);
			if (swaprange)
				hflag = !hflag;
			if (hflag && s <= smax && s >= smin && v <= vmax && v >= vmin)
				*pix = to_color;
			else {
				double hcorr = 0;
				double scorr = 0;
				double vcorr = 0;
				int hfallminflag = (h <= hmin && h >= hfallmin);
				if (hfallminflag)
					hcorr = h - hmin;
				int hfallmaxflag = (h >= hmax && h <= hfallmax);
				if (hfallmaxflag)
					hcorr = h - hmax;
				if (hcorr) {
					if (s <= smin && s >= sfallmin)
						scorr = s - smin;
					if (s >= smax && s <= sfallmax)
						scorr = s - smax;
					if (v <= vmin && v >= vfallmin)
						vcorr = v - vmin;
					if (v >= vmax && v <= vfallmax)
						vcorr = v - vmax;
					if (s < smin && s > sfallmin)
						scorr = s - smin;
					if (s > smax && s < sfallmax)
						scorr = s - smax;
					h = to_h + hcorr;
					if (h < 0)
						h += 360;
					if (h > 360)
						h -= 360;
					OLDHSV2RGB(h, s, v, &r, &g, &b);

					pix->r = (UCHAR)(r * 255);
					pix->g = (UCHAR)(g * 255);
					pix->b = (UCHAR)(b * 255);
				}
			}
			//premultiply(*pix);
			*pix++;
		}
	}
	raster32->unlock();
}

//FX_PLUGIN_IDENTIFIER(ChangeColorFx    , "changeColorFx")