Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tstream.h"
Toshihiro Shimizu 890ddd
#include "trop.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzBase includes
Toshihiro Shimizu 890ddd
#include "tdoubleparam.h"
Toshihiro Shimizu 890ddd
#include "tnotanimatableparam.h"
Toshihiro Shimizu 890ddd
#include "tfxparam.h"
Toshihiro Shimizu 890ddd
#include "trasterfx.h"
Toshihiro Shimizu 890ddd
#include "tbasefx.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//******************************************************************************************
Toshihiro Shimizu 890ddd
//    Local namespace
Toshihiro Shimizu 890ddd
//******************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Shinya Kitaoka 120a6e
void makeRectCoherent(TRectD &rect, const TPointD &pos) {
Shinya Kitaoka 120a6e
  rect -= pos;
Shinya Kitaoka 120a6e
  rect.x0 = tfloor(rect.x0);
Shinya Kitaoka 120a6e
  rect.y0 = tfloor(rect.y0);
Shinya Kitaoka 120a6e
  rect.x1 = tceil(rect.x1);
Shinya Kitaoka 120a6e
  rect.y1 = tceil(rect.y1);
Shinya Kitaoka 120a6e
  rect += pos;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//******************************************************************************************
Toshihiro Shimizu 890ddd
//    TImageCombinationFx  declaration
Toshihiro Shimizu 890ddd
//******************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class TImageCombinationFx : public TBaseRasterFx {
Shinya Kitaoka 120a6e
  TFxPortDG m_group;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  TImageCombinationFx();
Shinya Kitaoka 120a6e
  virtual ~TImageCombinationFx() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  // Virtual interface for heirs
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //! The raster processing function that must be reimplemented to perform the
Shinya Kitaoka 120a6e
  //! fx
Shinya Kitaoka 120a6e
  virtual void process(const TRasterP &up, const TRasterP &down,
Shinya Kitaoka 120a6e
                       double frame) = 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //! Whether the 'up' rasters of process() invocations must be allocated to
Shinya Kitaoka 120a6e
  //! entirely cover the 'down' counterpart. Should be enabled if the process()
Shinya Kitaoka 120a6e
  //! function affects 'down' pixels when the 'up's are fully transparent.
Shinya Kitaoka 120a6e
  virtual bool requiresFullRect() { return false; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  // Low-level TRasterFx-related functions
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  int dynamicPortGroupsCount() const override { return 1; }
Shinya Kitaoka 473e70
  const TFxPortDG *dynamicPortGroup(int g) const override {
Shinya Kitaoka 120a6e
    return (g == 0) ? &m_group : 0;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 38fd86
  bool canHandle(const TRenderSettings &info, double frame) override {
Shinya Kitaoka 38fd86
    return true;
Shinya Kitaoka 38fd86
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int getMemoryRequirement(const TRectD &rect, double frame,
Shinya Kitaoka 473e70
                           const TRenderSettings &info) override {
Shinya Kitaoka 120a6e
    // At max the memory of another tile with the same infos may be allocated
Shinya Kitaoka 120a6e
    // apart from
Shinya Kitaoka 120a6e
    // the externally supplied one.
Shinya Kitaoka 120a6e
    return TRasterFx::memorySize(rect, info.m_bpp);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 38fd86
  bool doGetBBox(double frame, TRectD &bBox,
Shinya Kitaoka 38fd86
                 const TRenderSettings &info) override;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 38fd86
  void doDryCompute(TRectD &rect, double frame,
Shinya Kitaoka 38fd86
                    const TRenderSettings &info) override;
Shinya Kitaoka 38fd86
  void doCompute(TTile &tile, double frame,
Shinya Kitaoka 38fd86
                 const TRenderSettings &info) override;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void compatibilityTranslatePort(int majorVersion, int minorVersion,
Shinya Kitaoka 473e70
                                  std::string &portName) override;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  int getPreferredInputPort() override { return 1; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//******************************************************************************************
Toshihiro Shimizu 890ddd
//    TImageCombinationFx  implementation
Toshihiro Shimizu 890ddd
//******************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TImageCombinationFx::TImageCombinationFx() : m_group("Source", 2) {
Shinya Kitaoka 120a6e
  addInputPort("Source1", new TRasterFxPort, 0);
Shinya Kitaoka 120a6e
  addInputPort("Source2", new TRasterFxPort, 0);
Shinya Kitaoka 120a6e
  setName(L"ImageCombinationFx");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TImageCombinationFx::doGetBBox(double frame, TRectD &bBox,
Shinya Kitaoka 120a6e
                                    const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  bBox = TRectD();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int p, pCount = getInputPortCount();
Shinya Kitaoka 120a6e
  for (p = 0; p != pCount; ++p) {
Shinya Kitaoka 120a6e
    TRasterFxPort *port = static_cast<trasterfxport *="">(getInputPort(p));</trasterfxport>
Shinya Kitaoka 120a6e
    TRectD inputBBox;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    bool hasInput = (port && port->isConnected())
Shinya Kitaoka 120a6e
                        ? (*port)->doGetBBox(frame, inputBBox, info)
Shinya Kitaoka 120a6e
                        : false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (hasInput) bBox += inputBBox;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return (bBox.getLx() >= 0) && (bBox.getLy() >= 0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TImageCombinationFx::doCompute(TTile &tile, double frame,
Shinya Kitaoka 120a6e
                                    const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  int p, pCount = getInputPortCount();
Shinya Kitaoka 120a6e
  TRasterFxPort *port = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Skip empty ports
Shinya Kitaoka 120a6e
  for (p = pCount - 1; p >= 0;
Shinya Kitaoka 120a6e
       --p)  // Reverse iteration - bottom ports have high indices
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    port = static_cast<trasterfxport *="">(getInputPort(p));</trasterfxport>
Shinya Kitaoka 120a6e
    if (port && port->getFx()) break;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // If there is no input, clear and return
Shinya Kitaoka 120a6e
  if (p < 0) {
Shinya Kitaoka 120a6e
    tile.getRaster()
Shinya Kitaoka 120a6e
        ->clear();  // Probably not necessary unless externally invocation
Shinya Kitaoka 120a6e
    return;  // deliberately soiled tile - however, should be rare anyway.
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Calculate the tiles' geometries
Shinya Kitaoka 120a6e
  const TRect &tileRect(tile.getRaster()->getBounds());
Shinya Kitaoka 120a6e
  const TDimension &tileSize(tileRect.getSize());
Shinya Kitaoka 120a6e
  TRectD tileRectD(tile.m_pos, TDimensionD(tileSize.lx, tileSize.ly));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Render the first viable port directly on tile
Shinya Kitaoka 120a6e
  (*port)->compute(tile, frame,
Shinya Kitaoka 120a6e
                   info);  // Should we do it only if the bbox is not empty?
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Then, render each subsequent port and process() it on top of tile
Shinya Kitaoka 120a6e
  bool canRestrict = !requiresFullRect();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (--p; p >= 0; --p) {
Shinya Kitaoka 120a6e
    port = static_cast<trasterfxport *="">(getInputPort(p));</trasterfxport>
Shinya Kitaoka 120a6e
    if (!(port && port->getFx()))  // Skip empty ports
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Will allocate a new tile to calculate the input contribution - so, if
Shinya Kitaoka 120a6e
    // possible
Shinya Kitaoka 120a6e
    // we'll restrict allocation to the input port's bbox
Shinya Kitaoka 120a6e
    TRectD computeRect(tileRectD);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (canRestrict) {
Shinya Kitaoka 120a6e
      TRectD inBBox;
Shinya Kitaoka 120a6e
      (*port)->getBBox(frame, inBBox, info);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      computeRect *= inBBox;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      makeRectCoherent(
Shinya Kitaoka 120a6e
          computeRect,
Shinya Kitaoka 120a6e
          tile.m_pos);  // Make it coherent with tile's pixel geometry
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Calculate the input port and perform processing
Shinya Kitaoka 120a6e
    TDimension computeSize(tround(computeRect.getLx()),
Shinya Kitaoka 120a6e
                           tround(computeRect.getLy()));
Shinya Kitaoka 120a6e
    if ((computeSize.lx > 0) && (computeSize.ly > 0)) {
Shinya Kitaoka 120a6e
      TTile inTile;  // Observe its locality - not incidental
Shinya Kitaoka 120a6e
      (*port)->allocateAndCompute(inTile, computeRect.getP00(), computeSize,
Shinya Kitaoka 120a6e
                                  tile.getRaster(), frame, info);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Invoke process() to deal with the actual fx processing
Shinya Kitaoka 120a6e
      TRasterP up(inTile.getRaster()), down(tile.getRaster());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (canRestrict) {
Shinya Kitaoka 120a6e
        // Extract from tile the part corresponding to inTile
Shinya Kitaoka 120a6e
        TRect downRect(convert(computeRect.getP00() - tile.m_pos), computeSize);
Shinya Kitaoka 120a6e
        down = down->extract(downRect);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      assert(up->getSize() == down->getSize());
Shinya Kitaoka 120a6e
      process(up, down, frame);  // This is the point with the max concentration
Shinya Kitaoka 120a6e
                                 // of allocated resources
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TImageCombinationFx::doDryCompute(TRectD &rect, double frame,
Shinya Kitaoka 120a6e
                                       const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  // Mere copy of doCompute(), stripped of the actual computations
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int p, pCount = getInputPortCount();
Shinya Kitaoka 120a6e
  TRasterFxPort *port = 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (p = pCount - 1; p >= 0; --p) {
Shinya Kitaoka 120a6e
    port = static_cast<trasterfxport *="">(getInputPort(p));</trasterfxport>
Shinya Kitaoka 120a6e
    if (port && port->getFx()) break;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (p < 0) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  (*port)->dryCompute(rect, frame, info);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool canRestrict = !requiresFullRect();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (--p; p >= 0; --p) {
Shinya Kitaoka 120a6e
    port = static_cast<trasterfxport *="">(getInputPort(p));</trasterfxport>
Shinya Kitaoka 120a6e
    if (!(port && port->getFx())) continue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TRectD computeRect(rect);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (canRestrict) {
Shinya Kitaoka 120a6e
      TRectD inBBox;
Shinya Kitaoka 120a6e
      (*port)->getBBox(frame, inBBox, info);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      computeRect *= inBBox;
Shinya Kitaoka 120a6e
      makeRectCoherent(computeRect, rect.getP00());
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TDimension computeSize(tround(computeRect.getLx()),
Shinya Kitaoka 120a6e
                           tround(computeRect.getLy()));
Shinya Kitaoka 120a6e
    if ((computeSize.lx > 0) && (computeSize.ly > 0))
Shinya Kitaoka 120a6e
      (*port)->dryCompute(computeRect, frame, info);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TImageCombinationFx::compatibilityTranslatePort(int major, int minor,
Shinya Kitaoka 120a6e
                                                     std::string &portName) {
Shinya Kitaoka 120a6e
  if (VersionNumber(major, minor) < VersionNumber(1, 20)) {
Shinya Kitaoka 120a6e
    if (portName == "Up")
Shinya Kitaoka 120a6e
      portName = "Source1";
Shinya Kitaoka 120a6e
    else if (portName == "Down")
Shinya Kitaoka 120a6e
      portName = "Source2";
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//******************************************************************************************
Toshihiro Shimizu 890ddd
//    TImageCombinationFx  heir classes
Toshihiro Shimizu 890ddd
//******************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class OverFx final : public TImageCombinationFx {
Shinya Kitaoka 120a6e
  FX_DECLARATION(OverFx)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  OverFx() { setName(L"OverFx"); }
Shinya Kitaoka 120a6e
Shinya Kitaoka 38fd86
  void process(const TRasterP &up, const TRasterP &down,
Shinya Kitaoka 38fd86
               double frame) override {
Shinya Kitaoka 120a6e
    TRop::over(down, up);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class AddFx final : public TImageCombinationFx {
Shinya Kitaoka 120a6e
  FX_DECLARATION(AddFx)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TDoubleParamP m_value;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  AddFx() : m_value(100.0) { bindParam(this, "value", m_value); }
Shinya Kitaoka 120a6e
Shinya Kitaoka 38fd86
  void process(const TRasterP &up, const TRasterP &down,
Shinya Kitaoka 38fd86
               double frame) override {
Shinya Kitaoka 120a6e
    double value = m_value->getValue(frame) / 100.0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (value != 1.0)
Shinya Kitaoka 120a6e
      TRop::add(up, down, down, value);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      TRop::add(up, down, down);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  TFxPort *getXsheetPort() const override { return getInputPort(1); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class ColorDodgeFx final : public TImageCombinationFx {
Shinya Kitaoka 120a6e
  FX_DECLARATION(AddFx)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 38fd86
  void process(const TRasterP &up, const TRasterP &down,
Shinya Kitaoka 38fd86
               double frame) override {
Shinya Kitaoka 120a6e
    TRop::colordodge(up, down, down);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  TFxPort *getXsheetPort() const override { return getInputPort(1); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class ColorBurnFx final : public TImageCombinationFx {
Shinya Kitaoka 120a6e
  FX_DECLARATION(AddFx)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 38fd86
  void process(const TRasterP &up, const TRasterP &down,
Shinya Kitaoka 38fd86
               double frame) override {
Shinya Kitaoka 120a6e
    TRop::colorburn(up, down, down);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  TFxPort *getXsheetPort() const override { return getInputPort(1); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class ScreenFx final : public TImageCombinationFx {
Shinya Kitaoka 120a6e
  FX_DECLARATION(AddFx)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 473e70
  bool requiresFullRect() override { return true; }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 38fd86
  void process(const TRasterP &up, const TRasterP &down,
Shinya Kitaoka 38fd86
               double frame) override {
Shinya Kitaoka 120a6e
    TRop::screen(up, down, down);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  TFxPort *getXsheetPort() const override { return getInputPort(1); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class SubFx final : public TImageCombinationFx {
Shinya Kitaoka 120a6e
  FX_DECLARATION(SubFx)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TBoolParamP m_matte;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  SubFx() : m_matte(false) { bindParam(this, "matte", m_matte); }
Shinya Kitaoka 120a6e
Shinya Kitaoka 38fd86
  void process(const TRasterP &up, const TRasterP &down,
Shinya Kitaoka 38fd86
               double frame) override {
Shinya Kitaoka 120a6e
    TRop::sub(up, down, down, m_matte->getValue());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  TFxPort *getXsheetPort() const override { return getInputPort(1); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class MultFx final : public TImageCombinationFx {
Shinya Kitaoka 120a6e
  FX_DECLARATION(MultFx)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TDoubleParamP m_value;
Shinya Kitaoka 120a6e
  TBoolParamP m_matte;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  MultFx() : m_value(0.0), m_matte(false) {
Shinya Kitaoka 120a6e
    bindParam(this, "value", m_value);
Shinya Kitaoka 120a6e
    bindParam(this, "matte", m_matte);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  bool requiresFullRect() override { return m_matte->getValue(); }
Shinya Kitaoka 120a6e
Shinya Kitaoka 38fd86
  void process(const TRasterP &up, const TRasterP &down,
Shinya Kitaoka 38fd86
               double frame) override {
Shinya Kitaoka 120a6e
    TRop::mult(up, down, down, m_value->getValue(frame), m_matte->getValue());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  TFxPort *getXsheetPort() const override { return getInputPort(1); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class MinFx final : public TImageCombinationFx {
Shinya Kitaoka 120a6e
  FX_DECLARATION(MinFx)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TBoolParamP m_matte;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  MinFx() : m_matte(true) { bindParam(this, "matte", m_matte); }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  bool requiresFullRect() override { return true; }
Shinya Kitaoka 120a6e
Shinya Kitaoka 38fd86
  void process(const TRasterP &up, const TRasterP &down,
Shinya Kitaoka 38fd86
               double frame) override {
Shinya Kitaoka 120a6e
    TRop::ropmin(up, down, down, m_matte->getValue());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  TFxPort *getXsheetPort() const override { return getInputPort(1); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class MaxFx final : public TImageCombinationFx {
Shinya Kitaoka 120a6e
  FX_DECLARATION(MaxFx)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 38fd86
  void process(const TRasterP &up, const TRasterP &down,
Shinya Kitaoka 38fd86
               double frame) override {
Shinya Kitaoka 120a6e
    TRop::ropmax(up, down, down);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  TFxPort *getXsheetPort() const override { return getInputPort(1); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class LinearBurnFx final : public TImageCombinationFx {
Shinya Kitaoka 120a6e
  FX_DECLARATION(LinearBurnFx)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 38fd86
  void process(const TRasterP &up, const TRasterP &down,
Shinya Kitaoka 38fd86
               double frame) override {
Shinya Kitaoka 120a6e
    TRop::linearburn(up, down, down);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  TFxPort *getXsheetPort() const override { return getInputPort(1); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// This Fx is probably unused...!
Shinya Kitaoka d1f6c4
class OverlayFx final : public TImageCombinationFx {
Shinya Kitaoka 120a6e
  FX_DECLARATION(OverlayFx)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  OverlayFx() {}
Shinya Kitaoka 120a6e
  ~OverlayFx() {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 38fd86
  void process(const TRasterP &up, const TRasterP &down,
Shinya Kitaoka 38fd86
               double frame) override {
Shinya Kitaoka 120a6e
    TRop::overlay(up, down, down);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class BlendFx final : public TImageCombinationFx {
Shinya Kitaoka 120a6e
  FX_DECLARATION(BlendFx)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TDoubleParamP m_value;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  BlendFx() : m_value(0.0) {
Shinya Kitaoka 120a6e
    bindParam(this, "value", m_value);
Shinya Kitaoka 120a6e
    m_value->setValueRange(0.0, 100.0);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  bool requiresFullRect() override { return true; }
Shinya Kitaoka 120a6e
Shinya Kitaoka 38fd86
  void process(const TRasterP &up, const TRasterP &down,
Shinya Kitaoka 38fd86
               double frame) override {
Shinya Kitaoka 120a6e
    double value     = 0.01 * m_value->getValue(frame);
Shinya Kitaoka 120a6e
    UCHAR matteValue = (UCHAR)(value * 255.0 + 0.5);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TRop::crossDissolve(up, down, down, matteValue);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  TFxPort *getXsheetPort() const override { return getInputPort(1); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//******************************************************************************************
Toshihiro Shimizu 890ddd
//    Matte Fxs  definition
Toshihiro Shimizu 890ddd
//******************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class InFx final : public TBaseRasterFx {
Shinya Kitaoka 120a6e
  FX_DECLARATION(InFx)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRasterFxPort m_source, m_matte;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  InFx() {
Shinya Kitaoka 120a6e
    addInputPort("Source", m_source);
Shinya Kitaoka 120a6e
    addInputPort("Matte", m_matte);
Shinya Kitaoka 120a6e
    setName(L"InFx");
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ~InFx() {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 38fd86
  bool doGetBBox(double frame, TRectD &bbox,
Shinya Kitaoka 38fd86
                 const TRenderSettings &info) override {
Shinya Kitaoka 120a6e
    if (m_matte.isConnected() && m_source.isConnected()) {
Shinya Kitaoka 120a6e
      bool ret = m_matte->doGetBBox(frame, bbox, info);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (bbox == TConsts::infiniteRectD)
Shinya Kitaoka 120a6e
        return m_source->doGetBBox(frame, bbox, info);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        return ret;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    bbox = TRectD();
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 38fd86
  bool canHandle(const TRenderSettings &info, double frame) override {
Shinya Kitaoka 38fd86
    return true;
Shinya Kitaoka 38fd86
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 38fd86
  void doCompute(TTile &tile, double frame,
Shinya Kitaoka 38fd86
                 const TRenderSettings &ri) override {
Shinya Kitaoka 120a6e
    // This fx is not visible if either the source or the matte tiles are empty.
Shinya Kitaoka 120a6e
    // It's because only source is visible, and only where matte is opaque.
Shinya Kitaoka 120a6e
    if (!(m_source.isConnected() && m_matte.isConnected())) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TTile srcTile;
Shinya Kitaoka 120a6e
    m_source->allocateAndCompute(srcTile, tile.m_pos,
Shinya Kitaoka 120a6e
                                 tile.getRaster()->getSize(), tile.getRaster(),
Shinya Kitaoka 120a6e
                                 frame, ri);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_matte->compute(tile, frame, ri);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TRop::ropin(srcTile.getRaster(), tile.getRaster(), tile.getRaster());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 38fd86
  void doDryCompute(TRectD &rect, double frame,
Shinya Kitaoka 38fd86
                    const TRenderSettings &info) override {
Shinya Kitaoka 120a6e
    if (!(m_source.isConnected() && m_matte.isConnected())) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_source->dryCompute(rect, frame, info);
Shinya Kitaoka 120a6e
    m_matte->dryCompute(rect, frame, info);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int getMemoryRequirement(const TRectD &rect, double frame,
Shinya Kitaoka 473e70
                           const TRenderSettings &info) override {
Shinya Kitaoka 120a6e
    return TRasterFx::memorySize(rect, info.m_bpp);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class OutFx final : public TBaseRasterFx {
Shinya Kitaoka 120a6e
  FX_DECLARATION(OutFx)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRasterFxPort m_source, m_matte;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  OutFx() {
Shinya Kitaoka 120a6e
    addInputPort("Source", m_source);
Shinya Kitaoka 120a6e
    addInputPort("Matte", m_matte);
Shinya Kitaoka 120a6e
    setName(L"OutFx");
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ~OutFx() {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 38fd86
  bool doGetBBox(double frame, TRectD &bbox,
Shinya Kitaoka 38fd86
                 const TRenderSettings &info) override {
Shinya Kitaoka 120a6e
    if (m_source.isConnected()) return m_source->doGetBBox(frame, bbox, info);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 38fd86
  bool canHandle(const TRenderSettings &info, double frame) override {
Shinya Kitaoka 38fd86
    return true;
Shinya Kitaoka 38fd86
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 38fd86
  void doCompute(TTile &tile, double frame,
Shinya Kitaoka 38fd86
                 const TRenderSettings &ri) override {
Shinya Kitaoka 120a6e
    // If there is no source, do nothing
Shinya Kitaoka 120a6e
    if (!m_source.isConnected()) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Here, source is visible where matte is transparent. So if there is
Shinya Kitaoka 120a6e
    // no matte, just build source.
Shinya Kitaoka 120a6e
    if (!m_matte.isConnected()) {
Shinya Kitaoka 120a6e
      m_source->compute(tile, frame, ri);
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TTile srcTile;
Shinya Kitaoka 120a6e
    m_source->allocateAndCompute(srcTile, tile.m_pos,
Shinya Kitaoka 120a6e
                                 tile.getRaster()->getSize(), tile.getRaster(),
Shinya Kitaoka 120a6e
                                 frame, ri);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_matte->compute(tile, frame, ri);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TRop::ropout(srcTile.getRaster(), tile.getRaster(), tile.getRaster());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 38fd86
  void doDryCompute(TRectD &rect, double frame,
Shinya Kitaoka 38fd86
                    const TRenderSettings &info) override {
Shinya Kitaoka 120a6e
    if (!m_source.isConnected()) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (!m_matte.isConnected()) {
Shinya Kitaoka 120a6e
      m_source->dryCompute(rect, frame, info);
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_source->dryCompute(rect, frame, info);
Shinya Kitaoka 120a6e
    m_matte->dryCompute(rect, frame, info);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int getMemoryRequirement(const TRectD &rect, double frame,
Shinya Kitaoka 473e70
                           const TRenderSettings &info) override {
Shinya Kitaoka 120a6e
    return TRasterFx::memorySize(rect, info.m_bpp);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class AtopFx final : public TBaseRasterFx {
Shinya Kitaoka 120a6e
  FX_DECLARATION(AtopFx)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRasterFxPort m_up, m_dn;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  AtopFx() {
Shinya Kitaoka 120a6e
    addInputPort("Up", m_up);
Shinya Kitaoka 120a6e
    addInputPort("Down", m_dn);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 38fd86
  bool canHandle(const TRenderSettings &info, double frame) override {
Shinya Kitaoka 38fd86
    return true;
Shinya Kitaoka 38fd86
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 38fd86
  bool doGetBBox(double frame, TRectD &bBox,
Shinya Kitaoka 38fd86
                 const TRenderSettings &info) override {
Shinya Kitaoka 120a6e
    bBox = TRectD();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      TRectD inputBBox;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      bool hasInput =
Shinya Kitaoka 120a6e
          m_up.isConnected() ? m_up->doGetBBox(frame, inputBBox, info) : false;
Shinya Kitaoka 120a6e
      if (hasInput) bBox += inputBBox;
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      TRectD inputBBox;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      bool hasInput =
Shinya Kitaoka 120a6e
          m_dn.isConnected() ? m_dn->doGetBBox(frame, inputBBox, info) : false;
Shinya Kitaoka 120a6e
      if (hasInput) bBox += inputBBox;
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    return (bBox.getLx() >= 0) && (bBox.getLy() >= 0);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 38fd86
  void doCompute(TTile &tile, double frame,
Shinya Kitaoka 38fd86
                 const TRenderSettings &ri) override {
Shinya Kitaoka 120a6e
    // Here it's just like matte in, but the matte is visible under up.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (!m_dn.isConnected()) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (!m_up.isConnected()) {
Shinya Kitaoka 120a6e
      m_dn->compute(tile, frame, ri);
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TTile upTile;
Shinya Kitaoka 120a6e
    m_up->allocateAndCompute(upTile, tile.m_pos, tile.getRaster()->getSize(),
Shinya Kitaoka 120a6e
                             tile.getRaster(), frame, ri);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_dn->compute(tile, frame, ri);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TRop::atop(upTile.getRaster(), tile.getRaster(), tile.getRaster());
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 38fd86
  void doDryCompute(TRectD &rect, double frame,
Shinya Kitaoka 38fd86
                    const TRenderSettings &info) override {
Shinya Kitaoka 120a6e
    if (!m_dn.isConnected()) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (!m_up.isConnected()) {
Shinya Kitaoka 120a6e
      m_dn->dryCompute(rect, frame, info);
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_up->dryCompute(rect, frame, info);
Shinya Kitaoka 120a6e
    m_dn->dryCompute(rect, frame, info);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int getMemoryRequirement(const TRectD &rect, double frame,
Shinya Kitaoka 473e70
                           const TRenderSettings &info) override {
Shinya Kitaoka 120a6e
    return TRasterFx::memorySize(rect, info.m_bpp);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=======================
Toshihiro Shimizu 890ddd
//    Fx identifiers
Toshihiro Shimizu 890ddd
//-----------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
FX_IDENTIFIER(OverFx, "overFx")
Toshihiro Shimizu 890ddd
FX_IDENTIFIER(AddFx, "addFx")
Toshihiro Shimizu 890ddd
FX_IDENTIFIER(SubFx, "subFx")
Toshihiro Shimizu 890ddd
FX_IDENTIFIER(MultFx, "multFx")
Toshihiro Shimizu 890ddd
FX_IDENTIFIER(InFx, "inFx")
Toshihiro Shimizu 890ddd
FX_IDENTIFIER(OutFx, "outFx")
Toshihiro Shimizu 890ddd
FX_IDENTIFIER(AtopFx, "atopFx")
Shinya Kitaoka 120a6e
// FX_IDENTIFIER(XorFx,       "xorFx")
Toshihiro Shimizu 890ddd
FX_IDENTIFIER(MinFx, "minFx")
Toshihiro Shimizu 890ddd
FX_IDENTIFIER(MaxFx, "maxFx")
Toshihiro Shimizu 890ddd
FX_IDENTIFIER(LinearBurnFx, "linearBurnFx")
Toshihiro Shimizu 890ddd
FX_IDENTIFIER(OverlayFx, "overlayFx")
Toshihiro Shimizu 890ddd
FX_IDENTIFIER(BlendFx, "blendFx")
Toshihiro Shimizu 890ddd
FX_IDENTIFIER(ColorDodgeFx, "colorDodgeFx")
Toshihiro Shimizu 890ddd
FX_IDENTIFIER(ColorBurnFx, "colorBurnFx")
Toshihiro Shimizu 890ddd
FX_IDENTIFIER(ScreenFx, "screenFx")