Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "stdfx.h"
Toshihiro Shimizu 890ddd
#include "tfxparam.h"
Toshihiro Shimizu 890ddd
#include "tpixelgr.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class ColorEmbossFx final : public TStandardRasterFx {
Shinya Kitaoka 120a6e
  FX_PLUGIN_DECLARATION(ColorEmbossFx)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRasterFxPort m_input;
Shinya Kitaoka 120a6e
  TRasterFxPort m_controller;
Shinya Kitaoka 120a6e
  TDoubleParamP m_intensity;
Shinya Kitaoka 120a6e
  TDoubleParamP m_elevation;
Shinya Kitaoka 120a6e
  TDoubleParamP m_direction;
Shinya Kitaoka 120a6e
  TDoubleParamP m_radius;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  ColorEmbossFx()
Shinya Kitaoka 120a6e
      : m_intensity(0.5), m_elevation(45.0), m_direction(90.0), m_radius(1.0) {
Shinya Kitaoka 120a6e
    m_radius->setMeasureName("fxLength");
Shinya Kitaoka 120a6e
    bindParam(this, "intensity", m_intensity);
Shinya Kitaoka 120a6e
    bindParam(this, "elevation", m_elevation);
Shinya Kitaoka 120a6e
    bindParam(this, "direction", m_direction);
Shinya Kitaoka 120a6e
    bindParam(this, "radius", m_radius);
Shinya Kitaoka 120a6e
    addInputPort("Source", m_input);
Shinya Kitaoka 120a6e
    addInputPort("Controller", m_controller);
Shinya Kitaoka 120a6e
    m_intensity->setValueRange(0.0, 1.0, 0.1);
Shinya Kitaoka 120a6e
    m_elevation->setValueRange(0.0, 360.0);
Shinya Kitaoka 120a6e
    m_direction->setValueRange(0.0, 360.0);
Shinya Kitaoka 120a6e
    m_radius->setValueRange(0.0, 10.0);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ~ColorEmbossFx(){};
Shinya Kitaoka 120a6e
Shinya Kitaoka d1f6c4
  bool doGetBBox(double frame, TRectD &bBox,
Shinya Kitaoka d1f6c4
                 const TRenderSettings &info) override {
Shinya Kitaoka 120a6e
    if (m_input.isConnected()) {
Shinya Kitaoka 120a6e
      bool ret = m_input->doGetBBox(frame, bBox, info);
Shinya Kitaoka 120a6e
      return ret;
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      bBox = TRectD();
Shinya Kitaoka 120a6e
      return false;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void transform(double frame, int port, const TRectD &rectOnOutput,
Shinya Kitaoka 120a6e
                 const TRenderSettings &infoOnOutput, TRectD &rectOnInput,
Michał Janiszewski d37dbb
                 TRenderSettings &infoOnInput) override;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int getMemoryRequirement(const TRectD &rect, double frame,
Michał Janiszewski d37dbb
                           const TRenderSettings &info) override;
Michał Janiszewski d37dbb
  void doCompute(TTile &tile, double frame, const TRenderSettings &ri) override;
Michał Janiszewski d37dbb
  bool canHandle(const TRenderSettings &info, double frame) override {
Shinya Kitaoka 120a6e
    return (isAlmostIsotropic(info.m_affine));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
template <typename channel_type="" pixel,="" pixelgray,="" typename=""></typename>
Shinya Kitaoka 120a6e
void doColorEmboss(TRasterPT<pixel> ras, TRasterPT<pixel> srcraster,</pixel></pixel>
Shinya Kitaoka 120a6e
                   TRasterPT<pixel> ctrraster, double azimuth, double elevation,</pixel>
Shinya Kitaoka 120a6e
                   double intensity, double radius) {
Shinya Kitaoka 120a6e
  double Lx         = cos(azimuth) * cos(elevation) * PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
  double Ly         = sin(azimuth) * cos(elevation) * PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
  double Lz         = sin(elevation) * PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
  double Nz         = (6 * PIXEL::maxChannelValue) * (1 - intensity);
Shinya Kitaoka 120a6e
  double Nz2        = Nz * Nz;
Shinya Kitaoka 120a6e
  double background = Lz;
Shinya Kitaoka 120a6e
  double NdotL;
Shinya Kitaoka 120a6e
  int j, m, n;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int border            = radius + 1;
Shinya Kitaoka 120a6e
  double borderFracMult = radius - (int)radius;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int wrap = srcraster->getWrap();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double nsbuffer, ewbuffer;
Shinya Kitaoka 120a6e
  double nsFracbuffer, ewFracbuffer;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ras->lock();
Shinya Kitaoka 120a6e
  srcraster->lock();
Shinya Kitaoka 120a6e
  ctrraster->lock();
Shinya Kitaoka 120a6e
  for (j = border; j < srcraster->getLy() - border; j++) {
Shinya Kitaoka 120a6e
    PIXEL *pixout    = ras->pixels(j - border);
Shinya Kitaoka 120a6e
    PIXEL *pix       = srcraster->pixels(j) + border;
Shinya Kitaoka 120a6e
    PIXEL *ctrpix    = ctrraster->pixels(j) + border;
Shinya Kitaoka 120a6e
    PIXEL *endPixout = pixout + ras->getLx();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    while (pixout < endPixout) {
Shinya Kitaoka 120a6e
      double val, emboss;
Shinya Kitaoka 120a6e
      {
Shinya Kitaoka 120a6e
        nsbuffer = 0;
Shinya Kitaoka 120a6e
        ewbuffer = 0;
Shinya Kitaoka 120a6e
        for (m = 1; m < border; m++)
Shinya Kitaoka 120a6e
          for (n = -m; n <= m; n++) {
Shinya Kitaoka 120a6e
            nsbuffer += PIXELGRAY::from(*(ctrpix + m * wrap + n)).value;
Shinya Kitaoka 120a6e
            nsbuffer -= PIXELGRAY::from(*(ctrpix - m * wrap + n)).value;
Shinya Kitaoka 120a6e
            ewbuffer += PIXELGRAY::from(*(ctrpix + n * wrap + m)).value;
Shinya Kitaoka 120a6e
            ewbuffer -= PIXELGRAY::from(*(ctrpix + n * wrap - m)).value;
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        nsFracbuffer = 0;
Shinya Kitaoka 120a6e
        ewFracbuffer = 0;
Shinya Kitaoka 120a6e
        for (n = -m; n <= m; n++) {
Shinya Kitaoka 120a6e
          nsFracbuffer += PIXELGRAY::from(*(ctrpix + m * wrap + n)).value;
Shinya Kitaoka 120a6e
          nsFracbuffer -= PIXELGRAY::from(*(ctrpix - m * wrap + n)).value;
Shinya Kitaoka 120a6e
          ewFracbuffer += PIXELGRAY::from(*(ctrpix + n * wrap + m)).value;
Shinya Kitaoka 120a6e
          ewFracbuffer -= PIXELGRAY::from(*(ctrpix + n * wrap - m)).value;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        nsbuffer += nsFracbuffer * borderFracMult;
Shinya Kitaoka 120a6e
        ewbuffer += ewFracbuffer * borderFracMult;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      double Nx = ewbuffer;
Shinya Kitaoka 120a6e
      double Ny = nsbuffer;
Shinya Kitaoka 120a6e
      Nx        = Nx / radius;
Shinya Kitaoka 120a6e
      Ny        = Ny / radius;
Shinya Kitaoka 120a6e
      // val= 127+sinsin*nordsud(pix, wrap)+coscos*eastwest(pix, wrap);
Shinya Kitaoka 120a6e
      if (Nx == 0 && Ny == 0)
Shinya Kitaoka 120a6e
        emboss = background;
Shinya Kitaoka 120a6e
      else if ((NdotL = Nx * Lx + Ny * Ly + Nz * Lz) < 0)
Shinya Kitaoka 120a6e
        emboss = 0;
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        emboss    = NdotL / sqrt(Nx * Nx + Ny * Ny + Nz2);
Shinya Kitaoka 120a6e
      val         = emboss * pix->r / PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      (pixout)->r = (val < PIXEL::maxChannelValue)
Shinya Kitaoka 120a6e
                        ? (val > 0 ? (CHANNEL_TYPE)val : 0)
Shinya Kitaoka 120a6e
                        : PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      val         = emboss * pix->g / PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      (pixout)->g = (val < PIXEL::maxChannelValue)
Shinya Kitaoka 120a6e
                        ? (val > 0 ? (CHANNEL_TYPE)val : 0)
Shinya Kitaoka 120a6e
                        : PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      val         = emboss * pix->b / PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      (pixout)->b = (val < PIXEL::maxChannelValue)
Shinya Kitaoka 120a6e
                        ? (val > 0 ? (CHANNEL_TYPE)val : 0)
Shinya Kitaoka 120a6e
                        : PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      (pixout)->m = (pix)->m;
Rozhuk Ivan 823a31
      pix++;
Rozhuk Ivan 823a31
      pixout++;
Rozhuk Ivan 823a31
      ctrpix++;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  ras->unlock();
Shinya Kitaoka 120a6e
  srcraster->unlock();
Shinya Kitaoka 120a6e
  ctrraster->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ColorEmbossFx::transform(double frame, int port,
Shinya Kitaoka 120a6e
                              const TRectD &rectOnOutput,
Shinya Kitaoka 120a6e
                              const TRenderSettings &infoOnOutput,
Shinya Kitaoka 120a6e
                              TRectD &rectOnInput,
Shinya Kitaoka 120a6e
                              TRenderSettings &infoOnInput) {
Shinya Kitaoka 120a6e
  infoOnInput = infoOnOutput;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double scale  = sqrt(fabs(infoOnOutput.m_affine.det()));
Shinya Kitaoka 120a6e
  double radius = m_radius->getValue(frame) * scale;
Shinya Kitaoka 120a6e
  int border    = radius + 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  rectOnInput = rectOnOutput.enlarge(border);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ColorEmbossFx::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
  double scale     = sqrt(fabs(ri.m_affine.det()));
Shinya Kitaoka 120a6e
  double radius    = m_radius->getValue(frame) * scale;
Shinya Kitaoka 120a6e
  double direction = m_direction->getValue(frame);
Shinya Kitaoka 120a6e
  double elevation = (m_elevation->getValue(frame)) * M_PI_180;
Shinya Kitaoka 120a6e
  double intensity = m_intensity->getValue(frame);
Shinya Kitaoka 120a6e
  double azimuth   = direction * M_PI_180;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int border = radius + 1;
Shinya Kitaoka 120a6e
  TRasterP srcRas =
Shinya Kitaoka 120a6e
      tile.getRaster()->create(tile.getRaster()->getLx() + border * 2,
Shinya Kitaoka 120a6e
                               tile.getRaster()->getLy() + border * 2);
Shinya Kitaoka 120a6e
  // TRaster32P srcRas(tile.getRaster()->getLx() + border*2,
Shinya Kitaoka 120a6e
  // tile.getRaster()->getLy() + border*2);
Shinya Kitaoka 120a6e
  TTile srcTile(srcRas, tile.m_pos - TPointD(border, border));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TTile ctrTile;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_input->compute(srcTile, frame, ri);
Shinya Kitaoka 120a6e
  if (!m_controller.isConnected()) {
Shinya Kitaoka 120a6e
    ctrTile.m_pos = srcTile.m_pos;
Shinya Kitaoka 120a6e
    ctrTile.setRaster(srcTile.getRaster());
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    ctrTile.m_pos = tile.m_pos - TPointD(border, border);
Shinya Kitaoka 120a6e
    ctrTile.setRaster(
Shinya Kitaoka 120a6e
        tile.getRaster()->create(tile.getRaster()->getLx() + border * 2,
Shinya Kitaoka 120a6e
                                 tile.getRaster()->getLy() + border * 2));
Shinya Kitaoka 120a6e
    m_controller->allocateAndCompute(ctrTile, ctrTile.m_pos,
Shinya Kitaoka 120a6e
                                     ctrTile.getRaster()->getSize(),
Shinya Kitaoka 120a6e
                                     ctrTile.getRaster(), frame, ri);
Shinya Kitaoka 120a6e
    // m_controller->compute(ctrTile,frame,ri);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  TRaster32P raster32    = tile.getRaster();
Shinya Kitaoka 120a6e
  TRaster32P srcraster32 = srcTile.getRaster();
Shinya Kitaoka 120a6e
  TRaster32P ctrraster32 = ctrTile.getRaster();
Shinya Kitaoka 120a6e
  if (raster32)
Shinya Kitaoka 120a6e
    doColorEmboss<tpixel32, tpixelgr8,="" uchar="">(raster32, srcraster32,</tpixel32,>
Shinya Kitaoka 120a6e
                                              ctrraster32, azimuth, elevation,
Shinya Kitaoka 120a6e
                                              intensity, radius);
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    TRaster64P raster64    = tile.getRaster();
Shinya Kitaoka 120a6e
    TRaster64P srcraster64 = srcTile.getRaster();
Shinya Kitaoka 120a6e
    TRaster64P ctrraster64 = ctrTile.getRaster();
Shinya Kitaoka 120a6e
    if (raster64)
Shinya Kitaoka 120a6e
      doColorEmboss<tpixel64, tpixelgr16,="" ushort="">(raster64, srcraster64,</tpixel64,>
Shinya Kitaoka 120a6e
                                                  ctrraster64, azimuth,
Shinya Kitaoka 120a6e
                                                  elevation, intensity, radius);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      throw TException("Brightness&Contrast: unsupported Pixel Type");
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int ColorEmbossFx::getMemoryRequirement(const TRectD &rect, double frame,
Shinya Kitaoka 120a6e
                                        const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  double scale  = sqrt(fabs(info.m_affine.det()));
Shinya Kitaoka 120a6e
  double radius = m_radius->getValue(frame) * scale;
Shinya Kitaoka 120a6e
  int border    = radius + 1;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return TRasterFx::memorySize(rect.enlarge(border), info.m_bpp);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
FX_PLUGIN_IDENTIFIER(ColorEmbossFx, "colorEmbossFx");