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) {
otakuto ed7dcd
    std::swap(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);
Rozhuk Ivan 823a31
      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")