Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "stdfx.h"
Toshihiro Shimizu 890ddd
#include "tfxparam.h"
Toshihiro Shimizu 890ddd
#include "tpixelutils.h"
Toshihiro Shimizu 890ddd
#include "tparamset.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//************************************************************************
Toshihiro Shimizu 890ddd
//    Local namespace
Toshihiro Shimizu 890ddd
//************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
enum PixelOp { OVER = 0, ADD, SUBTRACT, MULTIPLY, LIGHTEN, DARKEN };
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixel=""></typename>
Shinya Kitaoka 120a6e
int doBlurValue(PIXEL *SRC, int SRC_WRAP, int BLUR) {
Shinya Kitaoka 120a6e
  unsigned int count = 0;
Shinya Kitaoka 120a6e
  int h, k;
Shinya Kitaoka 120a6e
  int blur_val;
Shinya Kitaoka 120a6e
  PIXEL *pix, *line;
Shinya Kitaoka 120a6e
  pix = line = (SRC) + (-(BLUR) + 1) * (SRC_WRAP);
Shinya Kitaoka 120a6e
  for (h = -(BLUR) + 1; h < (BLUR); h++) {
Shinya Kitaoka 120a6e
    for (k = -(BLUR) + 1; k < (BLUR); k++) count += pix[k].m;
Shinya Kitaoka 120a6e
    line += SRC_WRAP;
Shinya Kitaoka 120a6e
    pix = line;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  blur_val = (int)(count / (4 * (float)(BLUR) * (float)((BLUR)-1) + 1));
Shinya Kitaoka 120a6e
  return blur_val;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename channel_type="" pixel,="" typename=""></typename>
Shinya Kitaoka 120a6e
void doBlur(CHANNEL_TYPE *greymap, const TRasterPT<pixel> &rin, int blur) {</pixel>
Shinya Kitaoka 120a6e
  // Perform a flat mean-convolution filter
Shinya Kitaoka 120a6e
  // NOTE: This is improved due to separability of convolution kernel, plus
Shinya Kitaoka 120a6e
  // - since its elements are all the same, only pixels entering and quitting
Shinya Kitaoka 120a6e
  // the convolution area are added/subtracted from the sums.
Shinya Kitaoka 120a6e
  // As a result, this yields an O(row*columns) complexity, independently
Shinya Kitaoka 120a6e
  // from the blur factor.
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int i, j;
Shinya Kitaoka 120a6e
  int blurDiameter = 2 * blur + 1;
Shinya Kitaoka 120a6e
  unsigned long sum;
Shinya Kitaoka 120a6e
  int wrapSrc = rin->getWrap();
Shinya Kitaoka 120a6e
  int wrapOut = rin->getLx();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // First, blur each column independently
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // We'll need a temporary col for storing sums
Shinya Kitaoka 120a6e
  std::unique_ptr<unsigned long[]=""> tempCol(new unsigned long[rin->getLy()]);</unsigned>
Shinya Kitaoka 120a6e
  int edge = std::min(blur + 1, rin->getLy());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (i = 0; i < rin->getLx(); ++i) {
Shinya Kitaoka 120a6e
    PIXEL *lineSrcPix        = rin->pixels(0) + i;
Shinya Kitaoka 120a6e
    CHANNEL_TYPE *lineOutPix = greymap + i;
Shinya Kitaoka 120a6e
    PIXEL *pixin             = lineSrcPix;
Shinya Kitaoka 120a6e
    unsigned long *pixsum    = tempCol.get();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    memset(tempCol.get(), 0, rin->getLy() * sizeof(unsigned long));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Build up to blur with retro-sums
Shinya Kitaoka 120a6e
    sum = 0;
Shinya Kitaoka 120a6e
    for (j = 0; j < edge; ++j, pixin += wrapSrc, ++pixsum) {
Shinya Kitaoka 120a6e
      sum += pixin->m;
Shinya Kitaoka 120a6e
      *pixsum = sum;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Fill in after blur
Shinya Kitaoka 120a6e
    PIXEL *queuepix = lineSrcPix;
Shinya Kitaoka 120a6e
    for (j = edge; j < rin->getLy();
Shinya Kitaoka 120a6e
         ++j, pixin += wrapSrc, queuepix += wrapSrc, ++pixsum) {
Shinya Kitaoka 120a6e
      sum += (pixin->m - queuepix->m);
Shinya Kitaoka 120a6e
      *pixsum = sum;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Now, the same in reverse
Shinya Kitaoka 120a6e
    lineSrcPix = lineSrcPix + (rin->getLy() - 1) * wrapSrc;
Shinya Kitaoka 120a6e
    pixin      = lineSrcPix;
Shinya Kitaoka 120a6e
    pixsum     = tempCol.get() + rin->getLy() - 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    sum = 0;
Shinya Kitaoka 120a6e
    for (j = 0; j < edge; ++j, pixin -= wrapSrc, --pixsum) {
Shinya Kitaoka 120a6e
      *pixsum += sum;
Shinya Kitaoka 120a6e
      sum += pixin->m;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    queuepix = lineSrcPix;
Shinya Kitaoka 120a6e
    for (j = edge; j < rin->getLy();
Shinya Kitaoka 120a6e
         ++j, pixin -= wrapSrc, queuepix -= wrapSrc, --pixsum) {
Shinya Kitaoka 120a6e
      sum -= queuepix->m;
Shinya Kitaoka 120a6e
      *pixsum += sum;
Shinya Kitaoka 120a6e
      sum += pixin->m;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Finally, transfer sums to the output greymap, divided by the blur.
Shinya Kitaoka 120a6e
    pixsum               = tempCol.get();
Shinya Kitaoka 120a6e
    CHANNEL_TYPE *pixout = lineOutPix;
Shinya Kitaoka 120a6e
    for (j = 0; j < rin->getLy(); ++j, pixout += wrapOut, ++pixsum)
Shinya Kitaoka 120a6e
      *pixout = (*pixsum) / blurDiameter;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Then, the same for all greymap rows
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // We'll need a temporary row for sums
Shinya Kitaoka 120a6e
  std::unique_ptr<unsigned long[]=""> tempRow(new unsigned long[rin->getLx()]);</unsigned>
Shinya Kitaoka 120a6e
  edge = std::min(blur + 1, rin->getLx());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (j = 0; j < rin->getLy(); ++j) {
Shinya Kitaoka 120a6e
    CHANNEL_TYPE *lineSrcPix = greymap + j * wrapOut;
Shinya Kitaoka 120a6e
    CHANNEL_TYPE *lineOutPix = lineSrcPix;
Shinya Kitaoka 120a6e
    unsigned long *pixsum    = tempRow.get();
Shinya Kitaoka 120a6e
    CHANNEL_TYPE *pixin      = lineSrcPix;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    memset(tempRow.get(), 0, rin->getLx() * sizeof(unsigned long));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Build up to blur with retro-sums
Shinya Kitaoka 120a6e
    sum = 0;
Shinya Kitaoka 120a6e
    for (i = 0; i < edge; ++i, ++pixin, ++pixsum) {
Shinya Kitaoka 120a6e
      sum += *pixin;
Shinya Kitaoka 120a6e
      *pixsum = sum;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Fill in after blur
Shinya Kitaoka 120a6e
    CHANNEL_TYPE *queuepix = lineSrcPix;
Shinya Kitaoka 120a6e
    for (i = edge; i < rin->getLx(); ++i, ++pixin, ++pixsum, ++queuepix) {
Shinya Kitaoka 120a6e
      sum += *pixin;
Shinya Kitaoka 120a6e
      sum -= *queuepix;
Shinya Kitaoka 120a6e
      *pixsum = sum;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Now, the same in reverse
Shinya Kitaoka 120a6e
    lineSrcPix = lineSrcPix + rin->getLx() - 1;
Shinya Kitaoka 120a6e
    pixin      = lineSrcPix;
Shinya Kitaoka 120a6e
    pixsum     = tempRow.get() + rin->getLx() - 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    sum = 0;
Shinya Kitaoka 120a6e
    for (i = 0; i < edge; ++i, --pixin, --pixsum) {
Shinya Kitaoka 120a6e
      *pixsum += sum;
Shinya Kitaoka 120a6e
      sum += *pixin;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    queuepix = lineSrcPix;
Shinya Kitaoka 120a6e
    for (i = edge; i < rin->getLx(); ++i, --pixin, --pixsum, --queuepix) {
Shinya Kitaoka 120a6e
      sum -= *queuepix;
Shinya Kitaoka 120a6e
      *pixsum += sum;
Shinya Kitaoka 120a6e
      sum += *pixin;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Finally, transfer sums to the output greymap, divided by the blur.
Shinya Kitaoka 120a6e
    CHANNEL_TYPE *pixout = lineOutPix;
Shinya Kitaoka 120a6e
    pixsum               = tempRow.get();
Shinya Kitaoka 120a6e
    for (i = 0; i < rin->getLx(); ++i, ++pixout, ++pixsum)
Shinya Kitaoka 120a6e
      *pixout = (*pixsum) / blurDiameter;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixel=""></typename>
Shinya Kitaoka 120a6e
void myOver(PIXEL &pixout, const PIXEL &pixin, const PIXEL &color) {
Shinya Kitaoka 120a6e
  pixout = color;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixel=""></typename>
Shinya Kitaoka 120a6e
void myAdd(PIXEL &pixout, const PIXEL &pixin, const PIXEL &color) {
Shinya Kitaoka 120a6e
  pixout.r = std::min(pixin.r + color.r, PIXEL::maxChannelValue);
Shinya Kitaoka 120a6e
  pixout.g = std::min(pixin.g + color.g, PIXEL::maxChannelValue);
Shinya Kitaoka 120a6e
  pixout.b = std::min(pixin.b + color.b, PIXEL::maxChannelValue);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixel=""></typename>
Shinya Kitaoka 120a6e
void mySub(PIXEL &pixout, const PIXEL &pixin, const PIXEL &color) {
Shinya Kitaoka 120a6e
  pixout.r = std::max(pixin.r - color.r, 0);
Shinya Kitaoka 120a6e
  pixout.g = std::max(pixin.g - color.g, 0);
Shinya Kitaoka 120a6e
  pixout.b = std::max(pixin.b - color.b, 0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixel=""></typename>
Shinya Kitaoka 120a6e
void myMult(PIXEL &pixout, const PIXEL &pixin, const PIXEL &color) {
Shinya Kitaoka 120a6e
  static const double den = PIXEL::maxChannelValue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  pixout.r = pixin.r * (color.r / den);
Shinya Kitaoka 120a6e
  pixout.g = pixin.g * (color.g / den);
Shinya Kitaoka 120a6e
  pixout.b = pixin.b * (color.b / den);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixel=""></typename>
Shinya Kitaoka 120a6e
void myLighten(PIXEL &pixout, const PIXEL &pixin, const PIXEL &color) {
Shinya Kitaoka 120a6e
  pixout.r = pixin.r > color.r ? pixin.r : color.r;
Shinya Kitaoka 120a6e
  pixout.g = pixin.g > color.g ? pixin.g : color.g;
Shinya Kitaoka 120a6e
  pixout.b = pixin.b > color.b ? pixin.b : color.b;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixel=""></typename>
Shinya Kitaoka 120a6e
void myDarken(PIXEL &pixout, const PIXEL &pixin, const PIXEL &color) {
Shinya Kitaoka 120a6e
  pixout.r = pixin.r < color.r ? pixin.r : color.r;
Shinya Kitaoka 120a6e
  pixout.g = pixin.g < color.g ? pixin.g : color.g;
Shinya Kitaoka 120a6e
  pixout.b = pixin.b < color.b ? pixin.b : color.b;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename channel="" pixel,="" typename=""></typename>
Shinya Kitaoka 120a6e
void doLayerBlending(PIXEL *pixin, PIXEL *pixout, CHANNEL *pixmatte, int inLx,
Shinya Kitaoka 120a6e
                     int outLx, int outLy, int wrapIn, int wrapOut, int dx,
Shinya Kitaoka 120a6e
                     int dy, double transp, PIXEL color,
Shinya Kitaoka 120a6e
                     void (*pixelOp)(PIXEL &, const PIXEL &, const PIXEL &)) {
Shinya Kitaoka 120a6e
  double CROP_VAL    = PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
  CHANNEL U_CROP_VAL = PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int const_transp = CROP_VAL * transp + 0.5;
Shinya Kitaoka 120a6e
  double val_r, val_g, val_b, val_m;
Shinya Kitaoka 120a6e
  int blur_val;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  PIXEL opColor;
Shinya Kitaoka 120a6e
  double k, matte;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  CHANNEL shadow_matte;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int x, y;
Shinya Kitaoka 120a6e
  for (y = 0; y < outLy; ++y, pixin += wrapIn - outLx,
Shinya Kitaoka 120a6e
      pixout += wrapOut - outLx, pixmatte += inLx - outLx)
Shinya Kitaoka 120a6e
    for (x = 0; x < outLx; ++x, ++pixin, ++pixout, ++pixmatte) {
Shinya Kitaoka 120a6e
      if (pixin->m != 0)  // where the image is transparent, no shadow
Shinya Kitaoka 120a6e
      {
Shinya Kitaoka 120a6e
        blur_val     = *(pixmatte + dy * inLx + dx);
Shinya Kitaoka 120a6e
        shadow_matte = (blur_val) ? (int)((CROP_VAL - blur_val) * transp + 0.5)
Shinya Kitaoka 120a6e
                                  : const_transp;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        k     = (double)(CROP_VAL - shadow_matte) / CROP_VAL;
Shinya Kitaoka 120a6e
        val_r = pixin->r * k + 0.5;
Shinya Kitaoka 120a6e
        val_g = pixin->g * k + 0.5;
Shinya Kitaoka 120a6e
        val_b = pixin->b * k + 0.5;
Shinya Kitaoka 120a6e
        val_m = pixin->m;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        pixelOp(opColor, *pixin, color);
Shinya Kitaoka 120a6e
        matte = (1 - k) * (val_m / CROP_VAL);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        val_r += matte * opColor.r;
Shinya Kitaoka 120a6e
        val_g += matte * opColor.g;
Shinya Kitaoka 120a6e
        val_b += matte * opColor.b;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        pixout->r = (val_r > CROP_VAL) ? U_CROP_VAL
Shinya Kitaoka 120a6e
                                       : ((val_r < 0) ? 0 : (CHANNEL)val_r);
Shinya Kitaoka 120a6e
        pixout->g = (val_g > CROP_VAL) ? U_CROP_VAL
Shinya Kitaoka 120a6e
                                       : ((val_g < 0) ? 0 : (CHANNEL)val_g);
Shinya Kitaoka 120a6e
        pixout->b = (val_b > CROP_VAL) ? U_CROP_VAL
Shinya Kitaoka 120a6e
                                       : ((val_b < 0) ? 0 : (CHANNEL)val_b);
Shinya Kitaoka 120a6e
        pixout->m = (val_m > CROP_VAL) ? U_CROP_VAL
Shinya Kitaoka 120a6e
                                       : ((val_m < 0) ? 0 : (CHANNEL)val_m);
Shinya Kitaoka 120a6e
      } else
Shinya Kitaoka 120a6e
        *pixout = PIXEL::Transparent;
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixel=""></typename>
Toshihiro Shimizu 890ddd
void doBodyHighlight(const TRasterPT<pixel> rout, const TRasterPT<pixel> rin,</pixel></pixel>
Shinya Kitaoka 120a6e
                     TRectD rectIn, int rasInLx, int rasInLy, double frame,
Shinya Kitaoka 120a6e
                     int blur, double transp, PIXEL color, TPointD point,
Shinya Kitaoka 120a6e
                     bool invert,
Shinya Kitaoka 120a6e
                     void (*pixelOp)(PIXEL &, const PIXEL &, const PIXEL &),
Shinya Kitaoka 120a6e
                     TRasterFxPort &m_input, const TRenderSettings &ri) {
Shinya Kitaoka 120a6e
  typedef typename PIXEL::Channel CHANNEL_TYPE;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  rin->lock();
Shinya Kitaoka 120a6e
  rout->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int inLx = rin->getLx(), inLy = rin->getLy(), inWrap = rin->getWrap();
Shinya Kitaoka 120a6e
  int outLx = rout->getLx(), outLy = rout->getLy(), outWrap = rout->getWrap();
Shinya Kitaoka 120a6e
  int dx = point.x, dy = point.y;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  transp = 1.0 - transp;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  PIXEL *src_buf, *dst_buf;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  dst_buf = rout->pixels(0);
Shinya Kitaoka 120a6e
  src_buf = rin->pixels(0) + blur + blur * inWrap;
Shinya Kitaoka 120a6e
  if (dy < 0) src_buf -= dy * inWrap;
Shinya Kitaoka 120a6e
  if (dx < 0) src_buf -= dx;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // First, perform an optimized mean-convolution of the interesting part of
Shinya Kitaoka 120a6e
  // image's matte
Shinya Kitaoka 120a6e
  int matteLxLy = inLx * inLy;
Shinya Kitaoka 120a6e
  CHANNEL_TYPE *matteGreymap =
Shinya Kitaoka 120a6e
      (CHANNEL_TYPE *)malloc(matteLxLy * sizeof(CHANNEL_TYPE));
Shinya Kitaoka 120a6e
  if (!matteGreymap) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  memset(matteGreymap, 0, matteLxLy * sizeof(CHANNEL_TYPE));
Shinya Kitaoka 120a6e
  doBlur<pixel, channel_type="">(matteGreymap, rin, blur);</pixel,>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  CHANNEL_TYPE U_CROP_VAL = PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // If specified, invert the matte
Shinya Kitaoka 120a6e
  if (invert) {
Shinya Kitaoka 120a6e
    CHANNEL_TYPE *mpix, *end = matteGreymap + matteLxLy;
Shinya Kitaoka 120a6e
    for (mpix = matteGreymap; mpix < end; ++mpix) *mpix = U_CROP_VAL - *mpix;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  CHANNEL_TYPE *mattepix = matteGreymap + blur + blur * inLx;
Shinya Kitaoka 120a6e
  if (dy < 0) mattepix -= dy * inLx;
Shinya Kitaoka 120a6e
  if (dx < 0) mattepix -= dx;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  doLayerBlending(src_buf, dst_buf, mattepix, inLx, outLx, outLy, inWrap,
Shinya Kitaoka 120a6e
                  outWrap, dx, dy, transp, color, pixelOp);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  free(matteGreymap);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  rin->unlock();
Shinya Kitaoka 120a6e
  rout->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//************************************************************************
Toshihiro Shimizu 890ddd
//    BodyHighLightFx implementation
Toshihiro Shimizu 890ddd
//************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class BodyHighLightFx final : public TStandardRasterFx {
Shinya Kitaoka 120a6e
  FX_PLUGIN_DECLARATION(BodyHighLightFx)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRasterFxPort m_input;
Shinya Kitaoka 120a6e
  TIntEnumParamP m_mode;
Shinya Kitaoka 120a6e
  TPointParamP m_point;
Shinya Kitaoka 120a6e
  TDoubleParamP m_transparency;
Shinya Kitaoka 120a6e
  TDoubleParamP m_blur;
Shinya Kitaoka 120a6e
  TPixelParamP m_color;
Shinya Kitaoka 120a6e
  TBoolParamP m_invert;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  BodyHighLightFx()
Shinya Kitaoka 120a6e
      : m_point(TPointD(10.0, 10.0))
Shinya Kitaoka 120a6e
      , m_mode(new TIntEnumParam(OVER, "Over"))
Shinya Kitaoka 120a6e
      , m_transparency(0.5)
Shinya Kitaoka 120a6e
      , m_blur(2.0)
Shinya Kitaoka 120a6e
      , m_color(TPixel32::White)
Shinya Kitaoka 120a6e
      , m_invert(false) {
Shinya Kitaoka 120a6e
    m_point->getX()->setMeasureName("fxLength");
Shinya Kitaoka 120a6e
    m_point->getY()->setMeasureName("fxLength");
Shinya Kitaoka 120a6e
    m_blur->setMeasureName("fxLength");
Shinya Kitaoka 120a6e
    bindParam(this, "mode", m_mode);
Shinya Kitaoka 120a6e
    bindParam(this, "point", m_point);
Shinya Kitaoka 120a6e
    bindParam(this, "transparency", m_transparency);
Shinya Kitaoka 120a6e
    bindParam(this, "blur", m_blur);
Shinya Kitaoka 120a6e
    bindParam(this, "color", m_color);
Shinya Kitaoka 120a6e
    bindParam(this, "invert", m_invert);
Shinya Kitaoka 120a6e
    addInputPort("Source", m_input);
Shinya Kitaoka 120a6e
    m_transparency->setValueRange(0.0, 1.0);
Shinya Kitaoka 120a6e
    m_blur->setValueRange(0, (std::numeric_limits<double>::max)());</double>
Shinya Kitaoka 120a6e
    m_color->enableMatte(false);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_mode->addItem(ADD, "Add");
Shinya Kitaoka 120a6e
    m_mode->addItem(SUBTRACT, "Subtract");
Shinya Kitaoka 120a6e
    m_mode->addItem(MULTIPLY, "Multiply");
Shinya Kitaoka 120a6e
    m_mode->addItem(LIGHTEN, "Lighten");
Shinya Kitaoka 120a6e
    m_mode->addItem(DARKEN, "Darken");
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ~BodyHighLightFx(){};
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())
Shinya Kitaoka 120a6e
      return m_input->doGetBBox(frame, bBox, info);
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 38fd86
  bool canHandle(const TRenderSettings &info, double frame) override {
Shinya Kitaoka 38fd86
    return true;
Shinya Kitaoka 38fd86
  }
Shinya Kitaoka 38fd86
  void doDryCompute(TRectD &rect, double frame,
Shinya Kitaoka 38fd86
                    const TRenderSettings &info) override;
Shinya Kitaoka 473e70
  void doCompute(TTile &tile, double frame, const TRenderSettings &) override;
Shinya Kitaoka 120a6e
  int getMemoryRequirement(const TRectD &rect, double frame,
Shinya Kitaoka 473e70
                           const TRenderSettings &info) override;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void BodyHighLightFx::doDryCompute(TRectD &rect, double frame,
Shinya Kitaoka 120a6e
                                   const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  m_input->dryCompute(rect, frame, info);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double fac   = sqrt(fabs(info.m_affine.det()));
Shinya Kitaoka 120a6e
  int blur     = (int)(fac * fabs(m_blur->getValue(frame)));
Shinya Kitaoka 120a6e
  TPoint point = convert(fac * m_point->getValue(frame));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRectD rectIn = rect.enlarge(blur);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int rasInLx = tround(rectIn.getLx() + abs(point.x)) + 1;
Shinya Kitaoka 120a6e
  int rasInLy = tround(rectIn.getLy() + abs(point.y)) + 1;
Shinya Kitaoka 120a6e
  if (point.x < 0) {
Shinya Kitaoka 120a6e
    rectIn.x0 += point.x;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (point.y < 0) {
Shinya Kitaoka 120a6e
    rectIn.y0 += point.y;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  rectIn = TRectD(rectIn.getP00(), TDimensionD(rasInLx, rasInLy));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_input->dryCompute(rectIn, frame, info);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void BodyHighLightFx::doCompute(TTile &tile, double frame,
Shinya Kitaoka 120a6e
                                const TRenderSettings &ri) {
Shinya Kitaoka 120a6e
  double fac = sqrt(fabs(ri.m_affine.det()));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!m_input.isConnected()) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Compute the effective input tile
Shinya Kitaoka 120a6e
  m_input->compute(tile, frame, ri);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double transp = m_transparency->getValue(frame);
Shinya Kitaoka 120a6e
  int blur      = (int)(fac * fabs(m_blur->getValue(frame)));
Shinya Kitaoka 120a6e
  TPoint point  = convert(fac * m_point->getValue(frame));
Shinya Kitaoka 120a6e
  bool invert   = m_invert->getValue();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Build the shadow, blurred tile
Shinya Kitaoka 120a6e
  TDimension rectSize(tile.getRaster()->getSize());
Shinya Kitaoka 120a6e
  TRectD rectIn(tile.m_pos, TDimensionD(rectSize.lx, rectSize.ly));
Shinya Kitaoka 120a6e
  rectIn = rectIn.enlarge(blur);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Shift rectIn by the input 'point'
Shinya Kitaoka 120a6e
  int rasInLx = tround(rectIn.getLx() + abs(point.x)) + 1;
Shinya Kitaoka 120a6e
  int rasInLy = tround(rectIn.getLy() + abs(point.y)) + 1;
Shinya Kitaoka 120a6e
  if (point.x < 0) {
Shinya Kitaoka 120a6e
    rectIn.x0 += point.x;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    rectIn.x1 += point.x;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (point.y < 0) {
Shinya Kitaoka 120a6e
    rectIn.y0 += point.y;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    rectIn.y1 += point.y;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  const TPixel32 color = m_color->getPremultipliedValue(frame);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRaster32P raster32 = tile.getRaster();
Shinya Kitaoka 120a6e
  TRaster64P raster64 = tile.getRaster();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TTile tileIn;
Shinya Kitaoka 120a6e
  m_input->allocateAndCompute(tileIn, rectIn.getP00(),
Shinya Kitaoka 120a6e
                              TDimension(rasInLx, rasInLy), tile.getRaster(),
Shinya Kitaoka 120a6e
                              frame, ri);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Select the specified pixel operation
Shinya Kitaoka 120a6e
  void (*pixelOp32)(TPixel32 &, const TPixel32 &, const TPixel32 &);
Shinya Kitaoka 120a6e
  void (*pixelOp64)(TPixel64 &, const TPixel64 &, const TPixel64 &);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  switch (m_mode->getValue()) {
Shinya Kitaoka 120a6e
  case OVER: {
Shinya Kitaoka 120a6e
    pixelOp32 = ::myOver<tpixel32>;</tpixel32>
Shinya Kitaoka 120a6e
    pixelOp64 = ::myOver<tpixel64>;</tpixel64>
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  case ADD: {
Shinya Kitaoka 120a6e
    pixelOp32 = ::myAdd<tpixel32>;</tpixel32>
Shinya Kitaoka 120a6e
    pixelOp64 = ::myAdd<tpixel64>;</tpixel64>
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  case SUBTRACT: {
Shinya Kitaoka 120a6e
    pixelOp32 = ::mySub<tpixel32>;</tpixel32>
Shinya Kitaoka 120a6e
    pixelOp64 = ::mySub<tpixel64>;</tpixel64>
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  case MULTIPLY: {
Shinya Kitaoka 120a6e
    pixelOp32 = ::myMult<tpixel32>;</tpixel32>
Shinya Kitaoka 120a6e
    pixelOp64 = ::myMult<tpixel64>;</tpixel64>
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  case LIGHTEN: {
Shinya Kitaoka 120a6e
    pixelOp32 = ::myLighten<tpixel32>;</tpixel32>
Shinya Kitaoka 120a6e
    pixelOp64 = ::myLighten<tpixel64>;</tpixel64>
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  case DARKEN: {
Shinya Kitaoka 120a6e
    pixelOp32 = ::myDarken<tpixel32>;</tpixel32>
Shinya Kitaoka 120a6e
    pixelOp64 = ::myDarken<tpixel64>;</tpixel64>
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRaster32P rin = tileIn.getRaster();
Shinya Kitaoka 120a6e
  if (raster32)
Shinya Kitaoka 120a6e
    doBodyHighlight<tpixel32>(raster32, rin, rectIn, rasInLx, rasInLy, frame,</tpixel32>
Shinya Kitaoka 120a6e
                              blur, transp, color, convert(point), invert,
Shinya Kitaoka 120a6e
                              pixelOp32, m_input, ri);
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    TRaster64P rin = tileIn.getRaster();
Shinya Kitaoka 120a6e
    if (raster64)
Shinya Kitaoka 120a6e
      doBodyHighlight<tpixel64>(raster64, rin, rectIn, rasInLx, rasInLy, frame,</tpixel64>
Shinya Kitaoka 120a6e
                                blur, transp, toPixel64(color), convert(point),
Shinya Kitaoka 120a6e
                                invert, pixelOp64, m_input, ri);
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 BodyHighLightFx::getMemoryRequirement(const TRectD &rect, double frame,
Shinya Kitaoka 120a6e
                                          const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  int blur =
Shinya Kitaoka 120a6e
      (int)(sqrt(fabs(info.m_affine.det())) * fabs(m_blur->getValue(frame)));
Shinya Kitaoka 120a6e
  return TRasterFx::memorySize(rect.enlarge(blur), info.m_bpp);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
FX_PLUGIN_IDENTIFIER(BodyHighLightFx, "bodyHighLightFx")