Toshihiro Shimizu 890ddd
/*------------------------------------
Toshihiro Shimizu 890ddd
Iwa_MotionBlurCompFx
shun-iwasawa 4f5900
Motion blur fx considering the exposure of light and trajectory of the object.
shun-iwasawa 4f5900
Available to composite exposure value with background.
Toshihiro Shimizu 890ddd
//------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "iwa_motionblurfx.h"
Toshihiro Shimizu 890ddd
#include "tfxattributes.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/tstageobject.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "trop.h"
Toshihiro Shimizu 890ddd
shun-iwasawa 4f5900
/* Normalize the source image to 0 - 1 and read it into the host memory.
shun-iwasawa 4f5900
 * Check if the source image is premultiped or not here, if it is not specified
shun-iwasawa 4f5900
 * in the combo box. */
Toshihiro Shimizu 890ddd
template <typename pixel="" raster,="" typename=""></typename>
Shinya Kitaoka 120a6e
bool Iwa_MotionBlurCompFx::setSourceRaster(const RASTER srcRas, float4 *dstMem,
Shinya Kitaoka 120a6e
                                           TDimensionI dim,
Shinya Kitaoka 120a6e
                                           PremultiTypes type) {
Shinya Kitaoka 120a6e
  bool isPremultiplied = (type == SOURCE_IS_NOT_PREMUTIPLIED) ? false : true;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  float4 *chann_p = dstMem;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  float threshold = 100.0 / (float)TPixel64::maxChannelValue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int max = 0;
Shinya Kitaoka 120a6e
  for (int j = 0; j < dim.ly; j++) {
Shinya Kitaoka 120a6e
    PIXEL *pix = srcRas->pixels(j);
Shinya Kitaoka 120a6e
    for (int i = 0; i < dim.lx; i++) {
Shinya Kitaoka 120a6e
      (*chann_p).x = (float)pix->r / (float)PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      (*chann_p).y = (float)pix->g / (float)PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      (*chann_p).z = (float)pix->b / (float)PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      (*chann_p).w = (float)pix->m / (float)PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
      /* If there are pixels whose RGB values ​​are larger than the alpha
shun-iwasawa 4f5900
       * channel, determine the source is not premutiplied */
shun-iwasawa 481b59
      // CAUTION: this condition won't work properly ith HDR image pixels!
Shinya Kitaoka 120a6e
      if (type == AUTO && isPremultiplied &&
Shinya Kitaoka 120a6e
          (((*chann_p).x > (*chann_p).w && (*chann_p).x > threshold) ||
Shinya Kitaoka 120a6e
           ((*chann_p).y > (*chann_p).w && (*chann_p).y > threshold) ||
Shinya Kitaoka 120a6e
           ((*chann_p).z > (*chann_p).w && (*chann_p).z > threshold)))
Shinya Kitaoka 120a6e
        isPremultiplied = false;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      pix++;
Shinya Kitaoka 120a6e
      chann_p++;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (isPremultiplied) {
Shinya Kitaoka 120a6e
    chann_p = dstMem;
Shinya Kitaoka 120a6e
    for (int i = 0; i < dim.lx * dim.ly; i++, chann_p++) {
Shinya Kitaoka 120a6e
      if ((*chann_p).x > (*chann_p).w) (*chann_p).x = (*chann_p).w;
Shinya Kitaoka 120a6e
      if ((*chann_p).y > (*chann_p).w) (*chann_p).y = (*chann_p).w;
Shinya Kitaoka 120a6e
      if ((*chann_p).z > (*chann_p).w) (*chann_p).z = (*chann_p).w;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return isPremultiplied;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*------------------------------------------------------------
Campbell Barton d3ecc4
 Convert output result to Channel value and store it in the tile
Toshihiro Shimizu 890ddd
------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
template <typename pixel="" raster,="" typename=""></typename>
Shinya Kitaoka 120a6e
void Iwa_MotionBlurCompFx::setOutputRaster(float4 *srcMem, const RASTER dstRas,
Shinya Kitaoka 120a6e
                                           TDimensionI dim, int2 margin) {
Shinya Kitaoka 120a6e
  int out_j = 0;
Shinya Kitaoka 120a6e
  for (int j = margin.y; j < dstRas->getLy() + margin.y; j++, out_j++) {
Shinya Kitaoka 120a6e
    PIXEL *pix     = dstRas->pixels(out_j);
Shinya Kitaoka 120a6e
    float4 *chan_p = srcMem;
Shinya Kitaoka 120a6e
    chan_p += j * dim.lx + margin.x;
Shinya Kitaoka 120a6e
    for (int i = 0; i < dstRas->getLx(); i++) {
Shinya Kitaoka 120a6e
      float val;
Shinya Kitaoka 120a6e
      val    = (*chan_p).x * (float)PIXEL::maxChannelValue + 0.5f;
Shinya Kitaoka 120a6e
      pix->r = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue)
Shinya Kitaoka 120a6e
                                             ? (float)PIXEL::maxChannelValue
Shinya Kitaoka 120a6e
                                             : val);
Shinya Kitaoka 120a6e
      val    = (*chan_p).y * (float)PIXEL::maxChannelValue + 0.5f;
Shinya Kitaoka 120a6e
      pix->g = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue)
Shinya Kitaoka 120a6e
                                             ? (float)PIXEL::maxChannelValue
Shinya Kitaoka 120a6e
                                             : val);
Shinya Kitaoka 120a6e
      val    = (*chan_p).z * (float)PIXEL::maxChannelValue + 0.5f;
Shinya Kitaoka 120a6e
      pix->b = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue)
Shinya Kitaoka 120a6e
                                             ? (float)PIXEL::maxChannelValue
Shinya Kitaoka 120a6e
                                             : val);
Shinya Kitaoka 120a6e
      val    = (*chan_p).w * (float)PIXEL::maxChannelValue + 0.5f;
Shinya Kitaoka 120a6e
      pix->m = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue)
Shinya Kitaoka 120a6e
                                             ? (float)PIXEL::maxChannelValue
Shinya Kitaoka 120a6e
                                             : val);
Shinya Kitaoka 120a6e
      pix++;
Shinya Kitaoka 120a6e
      chan_p++;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
shun-iwasawa 481b59
template <>
shun-iwasawa 481b59
void Iwa_MotionBlurCompFx::setOutputRaster<trasterfp, tpixelf="">(</trasterfp,>
shun-iwasawa 481b59
    float4 *srcMem, const TRasterFP dstRas, TDimensionI dim, int2 margin) {
shun-iwasawa 481b59
  int out_j = 0;
shun-iwasawa 481b59
  for (int j = margin.y; j < dstRas->getLy() + margin.y; j++, out_j++) {
shun-iwasawa 481b59
    TPixelF *pix   = dstRas->pixels(out_j);
shun-iwasawa 481b59
    float4 *chan_p = srcMem;
shun-iwasawa 481b59
    chan_p += j * dim.lx + margin.x;
shun-iwasawa 481b59
    for (int i = 0; i < dstRas->getLx(); i++) {
shun-iwasawa 481b59
      pix->r = (*chan_p).x;
shun-iwasawa 481b59
      pix->g = (*chan_p).y;
shun-iwasawa 481b59
      pix->b = (*chan_p).z;
shun-iwasawa 481b59
      pix->m = (*chan_p).w;
shun-iwasawa 481b59
      pix++;
shun-iwasawa 481b59
      chan_p++;
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
}
shun-iwasawa 481b59
Toshihiro Shimizu 890ddd
/*------------------------------------------------------------
Campbell Barton d3ecc4
 Create and normalize filters
Toshihiro Shimizu 890ddd
------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void Iwa_MotionBlurCompFx::makeMotionBlurFilter_CPU(
Shinya Kitaoka 120a6e
    float *filter_p, TDimensionI &filterDim, int marginLeft, int marginBottom,
Shinya Kitaoka 120a6e
    float4 *pointsTable, int pointAmount, float startValue, float startCurve,
Shinya Kitaoka 120a6e
    float endValue, float endCurve) {
shun-iwasawa 4f5900
  /* Variable for adding filter value*/
Shinya Kitaoka 120a6e
  float fil_val_sum = 0.0f;
shun-iwasawa 4f5900
  /* The current filter position to be looped in the 'for' statement */
Shinya Kitaoka 120a6e
  float *current_fil_p = filter_p;
shun-iwasawa 4f5900
  /* For each coordinate in the filter */
Shinya Kitaoka 120a6e
  for (int fily = 0; fily < filterDim.ly; fily++) {
Shinya Kitaoka 120a6e
    for (int filx = 0; filx < filterDim.lx; filx++, current_fil_p++) {
Campbell Barton d3ecc4
      /* Get filter coordinates */
Shinya Kitaoka 120a6e
      float2 pos = {static_cast<float>(filx - marginLeft),</float>
Shinya Kitaoka 120a6e
                    static_cast<float>(fily - marginBottom)};</float>
shun-iwasawa 4f5900
      /* Value to be updated */
Shinya Kitaoka 120a6e
      float nearestDist2         = 100.0f;
Shinya Kitaoka 120a6e
      int nearestIndex           = -1;
Shinya Kitaoka 120a6e
      float nearestFramePosRatio = 0.0f;
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
      /* Find the nearest point for each pair of sample points */
Shinya Kitaoka 120a6e
      for (int v = 0; v < pointAmount - 1; v++) {
Shinya Kitaoka 120a6e
        float4 p0 = pointsTable[v];
Shinya Kitaoka 120a6e
        float4 p1 = pointsTable[v + 1];
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
        /* If it is not within the range, continue */
Shinya Kitaoka 120a6e
        if (pos.x < std::min(p0.x, p1.x) - 1.0f ||
Shinya Kitaoka 120a6e
            pos.x > std::max(p0.x, p1.x) + 1.0f ||
Shinya Kitaoka 120a6e
            pos.y < std::min(p0.y, p1.y) - 1.0f ||
Shinya Kitaoka 120a6e
            pos.y > std::max(p0.y, p1.y) + 1.0f)
Shinya Kitaoka 120a6e
          continue;
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
        /* Since it is within the range, obtain the distance between the line
Campbell Barton d3ecc4
         * segment and the point. */
shun-iwasawa 4f5900
        /* Calculate the inner product of 'p0'->sampling point and 'p0'->'p1' */
Shinya Kitaoka 120a6e
        float2 vec_p0_sample = {static_cast<float>(pos.x - p0.x),</float>
Shinya Kitaoka 120a6e
                                static_cast<float>(pos.y - p0.y)};</float>
shun-iwasawa 481b59
        float2 vec_p0_p1     = {static_cast<float>(p1.x - p0.x),</float>
shun-iwasawa 481b59
                                static_cast<float>(p1.y - p0.y)};</float>
Shinya Kitaoka 120a6e
        float dot =
Shinya Kitaoka 120a6e
            vec_p0_sample.x * vec_p0_p1.x + vec_p0_sample.y * vec_p0_p1.y;
shun-iwasawa 4f5900
        /* Calculate the square of distance */
Shinya Kitaoka 120a6e
        float dist2;
Shinya Kitaoka 120a6e
        float framePosRatio;
shun-iwasawa 4f5900
        /* If it is before 'p0' */
Shinya Kitaoka 120a6e
        if (dot <= 0.0f) {
Shinya Kitaoka 120a6e
          dist2 = vec_p0_sample.x * vec_p0_sample.x +
Shinya Kitaoka 120a6e
                  vec_p0_sample.y * vec_p0_sample.y;
Shinya Kitaoka 120a6e
          framePosRatio = 0.0f;
Shinya Kitaoka 120a6e
        } else {
Campbell Barton d3ecc4
          /* Calculate the square of the length of the trajectory vector */
Shinya Kitaoka 120a6e
          float length2 = p0.z * p0.z;
Shinya Kitaoka 120a6e
shun-iwasawa 4f5900
          /* If it is between 'p0' and 'p1'
shun-iwasawa 4f5900
           * If the trajectory at p is a point,
shun-iwasawa 4f5900
           * 'length2' becomes 0, so it will never fall into this condition.
Campbell Barton d3ecc4
           * So, there should not be worry of becoming ZeroDivide. */
Shinya Kitaoka 120a6e
          if (dot < length2) {
Shinya Kitaoka 120a6e
            float p0_sample_dist2 = vec_p0_sample.x * vec_p0_sample.x +
Shinya Kitaoka 120a6e
                                    vec_p0_sample.y * vec_p0_sample.y;
Shinya Kitaoka 120a6e
            dist2         = p0_sample_dist2 - dot * dot / length2;
Shinya Kitaoka 120a6e
            framePosRatio = dot / length2;
Shinya Kitaoka 120a6e
          }
shun-iwasawa 4f5900
          /* If it is before 'p1' */
Shinya Kitaoka 120a6e
          else {
Shinya Kitaoka 120a6e
            float2 vec_p1_sample = {pos.x - p1.x, pos.y - p1.y};
Shinya Kitaoka 120a6e
            dist2                = vec_p1_sample.x * vec_p1_sample.x +
Shinya Kitaoka 120a6e
                    vec_p1_sample.y * vec_p1_sample.y;
Shinya Kitaoka 120a6e
            framePosRatio = 1.0f;
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Campbell Barton d3ecc4
        /* If the distance is farther than (√ 2 + 1) / 2, continue
shun-iwasawa 4f5900
         * Because it is a comparison with dist2, the value is squared */
Shinya Kitaoka 120a6e
        if (dist2 > 1.4571f) continue;
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
        /* Update if distance is closer */
Shinya Kitaoka 120a6e
        if (dist2 < nearestDist2) {
Shinya Kitaoka 120a6e
          nearestDist2         = dist2;
Shinya Kitaoka 120a6e
          nearestIndex         = v;
Shinya Kitaoka 120a6e
          nearestFramePosRatio = framePosRatio;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
shun-iwasawa 4f5900
      /* If neighborhood vector of the current pixel can not be found,
shun-iwasawa 4f5900
       * set the filter value to 0 and return */
Shinya Kitaoka 120a6e
      if (nearestIndex == -1) {
Shinya Kitaoka 120a6e
        *current_fil_p = 0.0f;
Shinya Kitaoka 120a6e
        continue;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
shun-iwasawa 4f5900
      /* Count how many subpixels (16 * 16) of the current pixel
shun-iwasawa 4f5900
       * are in the range 0.5 from the neighborhood vector.
Campbell Barton d3ecc4
       */
Shinya Kitaoka 120a6e
      int count  = 0;
Shinya Kitaoka 120a6e
      float4 np0 = pointsTable[nearestIndex];
Shinya Kitaoka 120a6e
      float4 np1 = pointsTable[nearestIndex + 1];
Shinya Kitaoka 120a6e
      for (int yy = 0; yy < 16; yy++) {
shun-iwasawa 4f5900
        /* Y coordinate of the subpixel */
Shinya Kitaoka 120a6e
        float subPosY = pos.y + ((float)yy - 7.5f) / 16.0f;
Shinya Kitaoka 120a6e
        for (int xx = 0; xx < 16; xx++) {
shun-iwasawa 4f5900
          /* X coordinate of the subpixel */
Shinya Kitaoka 120a6e
          float subPosX = pos.x + ((float)xx - 7.5f) / 16.0f;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          float2 vec_np0_sub = {subPosX - np0.x, subPosY - np0.y};
Shinya Kitaoka 120a6e
          float2 vec_np0_np1 = {np1.x - np0.x, np1.y - np0.y};
Shinya Kitaoka 120a6e
          float dot =
Shinya Kitaoka 120a6e
              vec_np0_sub.x * vec_np0_np1.x + vec_np0_sub.y * vec_np0_np1.y;
shun-iwasawa 4f5900
          /* Calculate the square of the distance */
Shinya Kitaoka 120a6e
          float dist2;
shun-iwasawa 4f5900
          /* If it is before 'p0' */
Shinya Kitaoka 120a6e
          if (dot <= 0.0f)
Shinya Kitaoka 120a6e
            dist2 =
Shinya Kitaoka 120a6e
                vec_np0_sub.x * vec_np0_sub.x + vec_np0_sub.y * vec_np0_sub.y;
Shinya Kitaoka 120a6e
          else {
Campbell Barton d3ecc4
            /* Compute the square of the length of the trajectory vector */
Shinya Kitaoka 120a6e
            float length2 = np0.z * np0.z;
shun-iwasawa 4f5900
            /* If it is between 'p0' and 'p1' */
Shinya Kitaoka 120a6e
            if (dot < length2) {
Shinya Kitaoka 120a6e
              float np0_sub_dist2 =
Shinya Kitaoka 120a6e
                  vec_np0_sub.x * vec_np0_sub.x + vec_np0_sub.y * vec_np0_sub.y;
Shinya Kitaoka 120a6e
              dist2 = np0_sub_dist2 - dot * dot / length2;
Shinya Kitaoka 120a6e
            }
Campbell Barton d3ecc4
            /* if it is before 'p1' */
Shinya Kitaoka 120a6e
            else {
Shinya Kitaoka 120a6e
              float2 vec_np1_sub = {subPosX - np1.x, subPosY - np1.y};
Shinya Kitaoka 120a6e
              dist2 =
Shinya Kitaoka 120a6e
                  vec_np1_sub.x * vec_np1_sub.x + vec_np1_sub.y * vec_np1_sub.y;
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
          }
shun-iwasawa 4f5900
          /* Increment count if squared distance is less than 0.25 */
Shinya Kitaoka 120a6e
          if (dist2 <= 0.25f) count++;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
shun-iwasawa 4f5900
      /* 'safeguard' - If the count is 0, set the field value to 0 and return.
shun-iwasawa 4f5900
       */
Shinya Kitaoka 120a6e
      if (count == 0) {
Shinya Kitaoka 120a6e
        *current_fil_p = 0.0f;
Shinya Kitaoka 120a6e
        continue;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
shun-iwasawa 4f5900
      /* Count is 256 at a maximum */
Shinya Kitaoka 120a6e
      float countRatio = (float)count / 256.0f;
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
      /* The brightness of the filter value is inversely proportional
Campbell Barton d3ecc4
       * to the area of ​​the line of width 1 made by the vector.
Campbell Barton d3ecc4
       *
Campbell Barton d3ecc4
       * Since there are semicircular caps with radius 0.5
shun-iwasawa 4f5900
       * before and after the vector, it will never be 0-divide
shun-iwasawa 4f5900
       * even if the length of vector is 0.
Campbell Barton d3ecc4
       */
Shinya Kitaoka 120a6e
shun-iwasawa 4f5900
      /* Area of the neighborhood vector when width = 1 */
Shinya Kitaoka 120a6e
      float vecMenseki = 0.25f * 3.14159265f + np0.z;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //-----------------
Campbell Barton d3ecc4
      /* Next, get the value of the gamma strength */
Campbell Barton d3ecc4
      /* Offset value of the frame of the neighbor point */
Shinya Kitaoka 120a6e
      float curveValue;
Shinya Kitaoka 120a6e
      float frameOffset =
Shinya Kitaoka 120a6e
          np0.w * (1.0f - nearestFramePosRatio) + np1.w * nearestFramePosRatio;
Campbell Barton d3ecc4
      /* If the frame is exactly at the frame origin,
shun-iwasawa 4f5900
       * or there is no attenuation value, set curveValue to 1 */
Shinya Kitaoka 120a6e
      if (frameOffset == 0.0f || (frameOffset < 0.0f && startValue == 1.0f) ||
Shinya Kitaoka 120a6e
          (frameOffset > 0.0f && endValue == 1.0f))
Shinya Kitaoka 120a6e
        curveValue = 1.0f;
Shinya Kitaoka 120a6e
      else {
Campbell Barton d3ecc4
        /* Change according to positive / negative of offset */
Shinya Kitaoka 120a6e
        float value, curve, ratio;
Campbell Barton d3ecc4
        if (frameOffset < 0.0f) /* Start side */
Shinya Kitaoka 120a6e
        {
Shinya Kitaoka 120a6e
          value = startValue;
Shinya Kitaoka 120a6e
          curve = startCurve;
Shinya Kitaoka 120a6e
          ratio = 1.0f - (frameOffset / pointsTable[0].w);
Shinya Kitaoka 120a6e
        } else {
Shinya Kitaoka 120a6e
          value = endValue;
Shinya Kitaoka 120a6e
          curve = endCurve;
Shinya Kitaoka 120a6e
          ratio = 1.0f - (frameOffset / pointsTable[pointAmount - 1].w);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        curveValue = value + (1.0f - value) * powf(ratio, 1.0f / curve);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      //-----------------
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
      /* Store field value */
Shinya Kitaoka 120a6e
      *current_fil_p = curveValue * countRatio / vecMenseki;
Shinya Kitaoka 120a6e
      fil_val_sum += *current_fil_p;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
  /* Normalization */
Shinya Kitaoka 120a6e
  current_fil_p = filter_p;
Shinya Kitaoka 120a6e
  for (int f = 0; f < filterDim.lx * filterDim.ly; f++, current_fil_p++) {
Shinya Kitaoka 120a6e
    *current_fil_p /= fil_val_sum;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*------------------------------------------------------------
Campbell Barton d3ecc4
 Create afterimage filter and normalize
Toshihiro Shimizu 890ddd
------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void Iwa_MotionBlurCompFx::makeZanzoFilter_CPU(
Shinya Kitaoka 120a6e
    float *filter_p, TDimensionI &filterDim, int marginLeft, int marginBottom,
Shinya Kitaoka 120a6e
    float4 *pointsTable, int pointAmount, float startValue, float startCurve,
Shinya Kitaoka 120a6e
    float endValue, float endCurve) {
Campbell Barton d3ecc4
  /* Variable for adding filter value */
Shinya Kitaoka 120a6e
  float fil_val_sum = 0.0f;
shun-iwasawa 4f5900
  /* The current filter position to be looped in the 'for' statement */
Shinya Kitaoka 120a6e
  float *current_fil_p = filter_p;
shun-iwasawa 4f5900
  /* For each coordinate in the filter */
Shinya Kitaoka 120a6e
  for (int fily = 0; fily < filterDim.ly; fily++) {
Shinya Kitaoka 120a6e
    for (int filx = 0; filx < filterDim.lx; filx++, current_fil_p++) {
Campbell Barton d3ecc4
      /* Get filter coordinates */
Shinya Kitaoka 120a6e
      float2 pos = {(float)(filx - marginLeft), (float)(fily - marginBottom)};
shun-iwasawa 4f5900
      /* Variable to be accumulated */
Shinya Kitaoka 120a6e
      float filter_sum = 0.0f;
shun-iwasawa 4f5900
      /* Measure the distance for each sample point and accumulate the density
shun-iwasawa 4f5900
       */
Shinya Kitaoka 120a6e
      for (int v = 0; v < pointAmount; v++) {
Shinya Kitaoka 120a6e
        float4 p0 = pointsTable[v];
Campbell Barton d3ecc4
        /* If it is not within the distance 1 around the coordinates of 'p0',
Campbell Barton d3ecc4
         * continue */
Shinya Kitaoka 120a6e
        if (pos.x < p0.x - 1.0f || pos.x > p0.x + 1.0f || pos.y < p0.y - 1.0f ||
Shinya Kitaoka 120a6e
            pos.y > p0.y + 1.0f)
Shinya Kitaoka 120a6e
          continue;
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
        /* Linear interpolation with 4 neighboring pixels */
Rozhuk Ivan 823a31
        float xRatio = 1.0f - std::abs(pos.x - p0.x);
Rozhuk Ivan 823a31
        float yRatio = 1.0f - std::abs(pos.y - p0.y);
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
        /* Next, get the value of the gamma strength */
Campbell Barton d3ecc4
        /* Offset value of the frame of the neighbor point */
Shinya Kitaoka 120a6e
        float curveValue;
Shinya Kitaoka 120a6e
        float frameOffset = p0.w;
Campbell Barton d3ecc4
        /* If the frame is exactly at the frame origin,
shun-iwasawa 481b59
         * or there is no attenuation value, set curveValue to 1 */
Shinya Kitaoka 120a6e
        if (frameOffset == 0.0f || (frameOffset < 0.0f && startValue == 1.0f) ||
Shinya Kitaoka 120a6e
            (frameOffset > 0.0f && endValue == 1.0f))
Shinya Kitaoka 120a6e
          curveValue = 1.0f;
Shinya Kitaoka 120a6e
        else {
Campbell Barton d3ecc4
          /* Change according to positive / negative of offset */
Shinya Kitaoka 120a6e
          float value, curve, ratio;
Campbell Barton d3ecc4
          if (frameOffset < 0.0f) /* Start side */
Shinya Kitaoka 120a6e
          {
Shinya Kitaoka 120a6e
            value = startValue;
Shinya Kitaoka 120a6e
            curve = startCurve;
Shinya Kitaoka 120a6e
            ratio = 1.0f - (frameOffset / pointsTable[0].w);
Shinya Kitaoka 120a6e
          } else {
Shinya Kitaoka 120a6e
            value = endValue;
Shinya Kitaoka 120a6e
            curve = endCurve;
Shinya Kitaoka 120a6e
            ratio = 1.0f - (frameOffset / pointsTable[pointAmount - 1].w);
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          curveValue = value + (1.0f - value) * powf(ratio, 1.0f / curve);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        //-----------------
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
        /* Filter value integration */
Shinya Kitaoka 120a6e
        filter_sum += xRatio * yRatio * curveValue;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
      /* Store value */
Shinya Kitaoka 120a6e
      *current_fil_p = filter_sum;
Shinya Kitaoka 120a6e
      fil_val_sum += *current_fil_p;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
  /* Normalization */
Shinya Kitaoka 120a6e
  current_fil_p = filter_p;
Shinya Kitaoka 120a6e
  for (int f = 0; f < filterDim.lx * filterDim.ly; f++, current_fil_p++) {
Shinya Kitaoka 120a6e
    *current_fil_p /= fil_val_sum;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*------------------------------------------------------------
shun-iwasawa 4f5900
 Unpremultiply -> convert to exposure value -> premultiply
Toshihiro Shimizu 890ddd
------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void Iwa_MotionBlurCompFx::convertRGBtoExposure_CPU(
shun-iwasawa 481b59
    float4 *in_tile_p, TDimensionI &dim, const ExposureConverter &conv,
Shinya Kitaoka 120a6e
    bool sourceIsPremultiplied) {
Shinya Kitaoka 120a6e
  float4 *cur_tile_p = in_tile_p;
Shinya Kitaoka 120a6e
  for (int i = 0; i < dim.lx * dim.ly; i++, cur_tile_p++) {
shun-iwasawa 4f5900
    /* if alpha is 0, return */
Shinya Kitaoka 120a6e
    if (cur_tile_p->w == 0.0f) {
Shinya Kitaoka 120a6e
      cur_tile_p->x = 0.0f;
Shinya Kitaoka 120a6e
      cur_tile_p->y = 0.0f;
Shinya Kitaoka 120a6e
      cur_tile_p->z = 0.0f;
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
shun-iwasawa 4f5900
    /* Unpremultiply on sources that are premultiplied, such as regular Level.
shun-iwasawa 4f5900
     * It is not done for 'digital overlay' (image with alpha mask added by
shun-iwasawa 4f5900
     * using Photoshop, as known as 'DigiBook' in Japanese animation industry)
shun-iwasawa 4f5900
     * etc. */
Shinya Kitaoka 120a6e
    if (sourceIsPremultiplied) {
shun-iwasawa 4f5900
      /* unpremultiply */
Shinya Kitaoka 120a6e
      cur_tile_p->x /= cur_tile_p->w;
Shinya Kitaoka 120a6e
      cur_tile_p->y /= cur_tile_p->w;
Shinya Kitaoka 120a6e
      cur_tile_p->z /= cur_tile_p->w;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
shun-iwasawa 4f5900
    /* convert RGB to Exposure */
shun-iwasawa 481b59
    cur_tile_p->x = conv.valueToExposure(cur_tile_p->x);
shun-iwasawa 481b59
    cur_tile_p->y = conv.valueToExposure(cur_tile_p->y);
shun-iwasawa 481b59
    cur_tile_p->z = conv.valueToExposure(cur_tile_p->z);
Shinya Kitaoka 120a6e
shun-iwasawa 4f5900
    /* Then multiply with the alpha channel */
Shinya Kitaoka 120a6e
    cur_tile_p->x *= cur_tile_p->w;
Shinya Kitaoka 120a6e
    cur_tile_p->y *= cur_tile_p->w;
Shinya Kitaoka 120a6e
    cur_tile_p->z *= cur_tile_p->w;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*------------------------------------------------------------
Campbell Barton d3ecc4
 Filter and blur exposure values
shun-iwasawa 4f5900
 Loop for the range of 'outDim'.
Toshihiro Shimizu 890ddd
------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void Iwa_MotionBlurCompFx::applyBlurFilter_CPU(
Shinya Kitaoka 120a6e
    float4 *in_tile_p, float4 *out_tile_p, TDimensionI &enlargedDim,
Shinya Kitaoka 120a6e
    float *filter_p, TDimensionI &filterDim, int marginLeft, int marginBottom,
Shinya Kitaoka 120a6e
    int marginRight, int marginTop, TDimensionI &outDim) {
Shinya Kitaoka 120a6e
  for (int i = 0; i < outDim.lx * outDim.ly; i++) {
Campbell Barton d3ecc4
    /* in_tile_dev and out_tile_dev contain data with dimensions lx * ly.
shun-iwasawa 4f5900
     * So, convert i to coordinates for output. */
Shinya Kitaoka 120a6e
    int2 outPos  = {i % outDim.lx + marginRight, i / outDim.lx + marginTop};
Shinya Kitaoka 120a6e
    int outIndex = outPos.y * enlargedDim.lx + outPos.x;
Campbell Barton d3ecc4
    /* put the result in out_tile_dev [outIndex] */
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
    /* Prepare a container to accumulate values ​​- */
Shinya Kitaoka 120a6e
    float4 value = {0.0f, 0.0f, 0.0f, 0.0f};
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
    /* Loop by filter size.
shun-iwasawa 4f5900
     * Note that the filter is used to 'collect' pixels at sample points
shun-iwasawa 4f5900
     * so flip the filter vertically and horizontally and sample it */
Shinya Kitaoka 120a6e
    int filterIndex = 0;
Shinya Kitaoka 120a6e
    for (int fily = -marginBottom; fily < filterDim.ly - marginBottom; fily++) {
shun-iwasawa 4f5900
      /* Sample coordinates and index of the end of this scan line */
Shinya Kitaoka 120a6e
      int2 samplePos  = {outPos.x + marginLeft, outPos.y - fily};
Shinya Kitaoka 120a6e
      int sampleIndex = samplePos.y * enlargedDim.lx + samplePos.x;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      for (int filx = -marginLeft; filx < filterDim.lx - marginLeft;
Shinya Kitaoka 120a6e
           filx++, filterIndex++, sampleIndex--) {
shun-iwasawa 4f5900
        /* If the filter value is 0 or the sample pixel is transparent, continue
Campbell Barton d3ecc4
         */
Shinya Kitaoka 120a6e
        if (filter_p[filterIndex] == 0.0f || in_tile_p[sampleIndex].w == 0.0f)
Shinya Kitaoka 120a6e
          continue;
Campbell Barton d3ecc4
        /* multiply the sample point value by the filter value and integrate */
Shinya Kitaoka 120a6e
        value.x += in_tile_p[sampleIndex].x * filter_p[filterIndex];
Shinya Kitaoka 120a6e
        value.y += in_tile_p[sampleIndex].y * filter_p[filterIndex];
Shinya Kitaoka 120a6e
        value.z += in_tile_p[sampleIndex].z * filter_p[filterIndex];
Shinya Kitaoka 120a6e
        value.w += in_tile_p[sampleIndex].w * filter_p[filterIndex];
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    out_tile_p[outIndex].x = value.x;
Shinya Kitaoka 120a6e
    out_tile_p[outIndex].y = value.y;
Shinya Kitaoka 120a6e
    out_tile_p[outIndex].z = value.z;
Shinya Kitaoka 120a6e
    out_tile_p[outIndex].w = value.w;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*------------------------------------------------------------
shun-iwasawa 4f5900
 Unpremultiply the exposure value
shun-iwasawa 4f5900
 -> convert back to RGB value (0 to 1)
shun-iwasawa 4f5900
 -> premultiply
Toshihiro Shimizu 890ddd
------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
shun-iwasawa 481b59
void Iwa_MotionBlurCompFx::convertExposureToRGB_CPU(
shun-iwasawa 481b59
    float4 *out_tile_p, TDimensionI &dim, const ExposureConverter &conv) {
Shinya Kitaoka 120a6e
  float4 *cur_tile_p = out_tile_p;
Shinya Kitaoka 120a6e
  for (int i = 0; i < dim.lx * dim.ly; i++, cur_tile_p++) {
Campbell Barton d3ecc4
    /* if alpha is 0 return */
Shinya Kitaoka 120a6e
    if (cur_tile_p->w == 0.0f) {
Shinya Kitaoka 120a6e
      cur_tile_p->x = 0.0f;
Shinya Kitaoka 120a6e
      cur_tile_p->y = 0.0f;
Shinya Kitaoka 120a6e
      cur_tile_p->z = 0.0f;
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
shun-iwasawa 4f5900
    // unpremultiply
Shinya Kitaoka 120a6e
    cur_tile_p->x /= cur_tile_p->w;
Shinya Kitaoka 120a6e
    cur_tile_p->y /= cur_tile_p->w;
Shinya Kitaoka 120a6e
    cur_tile_p->z /= cur_tile_p->w;
Shinya Kitaoka 120a6e
shun-iwasawa 4f5900
    /* Convert Exposure to RGB value */
shun-iwasawa 481b59
    cur_tile_p->x = conv.exposureToValue(cur_tile_p->x);
shun-iwasawa 481b59
    cur_tile_p->y = conv.exposureToValue(cur_tile_p->y);
shun-iwasawa 481b59
    cur_tile_p->z = conv.exposureToValue(cur_tile_p->z);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // multiply
Shinya Kitaoka 120a6e
    cur_tile_p->x *= cur_tile_p->w;
Shinya Kitaoka 120a6e
    cur_tile_p->y *= cur_tile_p->w;
Shinya Kitaoka 120a6e
    cur_tile_p->z *= cur_tile_p->w;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*------------------------------------------------------------
shun-iwasawa 4f5900
 If there is a background, and the foreground does not move, simply over
Toshihiro Shimizu 890ddd
------------------------------------------------------------*/
Shinya Kitaoka 120a6e
void Iwa_MotionBlurCompFx::composeWithNoMotion(
Shinya Kitaoka 120a6e
    TTile &tile, double frame, const TRenderSettings &settings) {
Shinya Kitaoka 120a6e
  assert(m_background.isConnected());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_background->compute(tile, frame, settings);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TTile fore_tile;
Shinya Kitaoka 120a6e
  m_input->allocateAndCompute(fore_tile, tile.m_pos,
Shinya Kitaoka 120a6e
                              tile.getRaster()->getSize(), tile.getRaster(),
Shinya Kitaoka 120a6e
                              frame, settings);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRasterP up(fore_tile.getRaster()), down(tile.getRaster());
Shinya Kitaoka 120a6e
  TRop::over(down, up);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*------------------------------------------------------------
shun-iwasawa 4f5900
  Convert background to exposure value and over it
Toshihiro Shimizu 890ddd
------------------------------------------------------------*/
Shinya Kitaoka 120a6e
void Iwa_MotionBlurCompFx::composeBackgroundExposure_CPU(
Shinya Kitaoka 120a6e
    float4 *out_tile_p, TDimensionI &enlargedDimIn, int marginRight,
shun-iwasawa 481b59
    int marginTop, TTile &back_tile, TDimensionI &dimOut,
shun-iwasawa 481b59
    const ExposureConverter &conv) {
Campbell Barton d3ecc4
  /* Memory allocation of host */
Shinya Kitaoka 120a6e
  TRasterGR8P background_host_ras(sizeof(float4) * dimOut.lx, dimOut.ly);
Shinya Kitaoka 120a6e
  background_host_ras->lock();
Shinya Kitaoka 120a6e
  float4 *background_host = (float4 *)background_host_ras->getRawData();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool bgIsPremultiplied;
Shinya Kitaoka 120a6e
shun-iwasawa 4f5900
  /* normalize the background image to 0 - 1 and read it into the host memory
Campbell Barton d3ecc4
   */
Shinya Kitaoka 120a6e
  TRaster32P backRas32 = (TRaster32P)back_tile.getRaster();
Shinya Kitaoka 120a6e
  TRaster64P backRas64 = (TRaster64P)back_tile.getRaster();
shun-iwasawa 481b59
  TRasterFP backRasF   = (TRasterFP)back_tile.getRaster();
Shinya Kitaoka 120a6e
  if (backRas32)
Shinya Kitaoka 120a6e
    bgIsPremultiplied = setSourceRaster<traster32p, tpixel32="">(</traster32p,>
Shinya Kitaoka 120a6e
        backRas32, background_host, dimOut);
Shinya Kitaoka 120a6e
  else if (backRas64)
Shinya Kitaoka 120a6e
    bgIsPremultiplied = setSourceRaster<traster64p, tpixel64="">(</traster64p,>
Shinya Kitaoka 120a6e
        backRas64, background_host, dimOut);
shun-iwasawa 481b59
  else if (backRasF)
shun-iwasawa 481b59
    bgIsPremultiplied =
shun-iwasawa 481b59
        setSourceRaster<trasterfp, tpixelf="">(backRasF, background_host, dimOut);</trasterfp,>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  float4 *bg_p = background_host;
Shinya Kitaoka 120a6e
  float4 *out_p;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (int j = 0; j < dimOut.ly; j++) {
Shinya Kitaoka 120a6e
    out_p = out_tile_p + ((marginTop + j) * enlargedDimIn.lx + marginRight);
Shinya Kitaoka 120a6e
    for (int i = 0; i < dimOut.lx; i++, bg_p++, out_p++) {
Campbell Barton d3ecc4
      /* if upper layer is completely opaque continue */
Shinya Kitaoka 120a6e
      if ((*out_p).w >= 1.0f) continue;
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
      /* even if the lower layer is completely transparent continue */
Shinya Kitaoka 120a6e
      if ((*bg_p).w < 0.0001f) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      float3 bgExposure = {(*bg_p).x, (*bg_p).y, (*bg_p).z};
Shinya Kitaoka 120a6e
shun-iwasawa 4f5900
      /* Unpremultiply on sources that are premultiplied, such as regular Level.
shun-iwasawa 4f5900
       * It is not done for 'digital overlay' (image with alpha mask added by
shun-iwasawa 4f5900
       * using Photoshop, as known as 'DigiBook' in Japanese animation industry)
shun-iwasawa 4f5900
       * etc.
shun-iwasawa 481b59
       */
Shinya Kitaoka 120a6e
      if (bgIsPremultiplied) {
shun-iwasawa 4f5900
        // Unpremultiply
Shinya Kitaoka 120a6e
        bgExposure.x /= (*bg_p).w;
Shinya Kitaoka 120a6e
        bgExposure.y /= (*bg_p).w;
Shinya Kitaoka 120a6e
        bgExposure.z /= (*bg_p).w;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
      /* Set RGB value to Exposure*/
shun-iwasawa 481b59
      bgExposure.x = conv.valueToExposure(bgExposure.x);
shun-iwasawa 481b59
      bgExposure.y = conv.valueToExposure(bgExposure.y);
shun-iwasawa 481b59
      bgExposure.z = conv.valueToExposure(bgExposure.z);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // multiply
Shinya Kitaoka 120a6e
      bgExposure.x *= (*bg_p).w;
Shinya Kitaoka 120a6e
      bgExposure.y *= (*bg_p).w;
Shinya Kitaoka 120a6e
      bgExposure.z *= (*bg_p).w;
Shinya Kitaoka 120a6e
luz paz 5d417b
      /* Over composite with front layers */
Shinya Kitaoka 120a6e
      (*out_p).x = (*out_p).x + bgExposure.x * (1.0f - (*out_p).w);
Shinya Kitaoka 120a6e
      (*out_p).y = (*out_p).y + bgExposure.y * (1.0f - (*out_p).w);
Shinya Kitaoka 120a6e
      (*out_p).z = (*out_p).z + bgExposure.z * (1.0f - (*out_p).w);
shun-iwasawa 4f5900
      /* Alpha value also over-composited */
Shinya Kitaoka 120a6e
      (*out_p).w = (*out_p).w + (*bg_p).w * (1.0f - (*out_p).w);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  background_host_ras->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Iwa_MotionBlurCompFx::Iwa_MotionBlurCompFx()
Shinya Kitaoka 120a6e
    : m_hardness(0.3)
shun-iwasawa 481b59
    , m_gamma(2.2)
shun-iwasawa 481b59
    , m_gammaAdjust(0.)
Campbell Barton d3ecc4
    /* Parameters for blurring left and right */
Shinya Kitaoka 120a6e
    , m_startValue(1.0)
Shinya Kitaoka 120a6e
    , m_startCurve(1.0)
Shinya Kitaoka 120a6e
    , m_endValue(1.0)
Shinya Kitaoka 120a6e
    , m_endCurve(1.0)
Shinya Kitaoka 120a6e
    , m_zanzoMode(false)
Shinya Kitaoka 120a6e
    , m_premultiType(new TIntEnumParam(AUTO, "Auto")) {
Campbell Barton d3ecc4
  /* Bind common parameters */
Shinya Kitaoka 120a6e
  addInputPort("Source", m_input);
Shinya Kitaoka 120a6e
  addInputPort("Back", m_background);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bindParam(this, "hardness", m_hardness);
shun-iwasawa 481b59
  bindParam(this, "gamma", m_gamma);
shun-iwasawa 481b59
  bindParam(this, "gammaAdjust", m_gammaAdjust);
Shinya Kitaoka 120a6e
  bindParam(this, "shutterStart", m_shutterStart);
Shinya Kitaoka 120a6e
  bindParam(this, "shutterEnd", m_shutterEnd);
Shinya Kitaoka 120a6e
  bindParam(this, "traceResolution", m_traceResolution);
Shinya Kitaoka 120a6e
  bindParam(this, "motionObjectType", m_motionObjectType);
Shinya Kitaoka 120a6e
  bindParam(this, "motionObjectIndex", m_motionObjectIndex);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bindParam(this, "startValue", m_startValue);
Shinya Kitaoka 120a6e
  bindParam(this, "startCurve", m_startCurve);
Shinya Kitaoka 120a6e
  bindParam(this, "endValue", m_endValue);
Shinya Kitaoka 120a6e
  bindParam(this, "endCurve", m_endCurve);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bindParam(this, "zanzoMode", m_zanzoMode);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bindParam(this, "premultiType", m_premultiType);
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
  /* Common parameter range setting */
Shinya Kitaoka 120a6e
  m_hardness->setValueRange(0.05, 10.0);
shun-iwasawa 481b59
  m_gamma->setValueRange(1.0, 10.0);
shun-iwasawa 481b59
  m_gammaAdjust->setValueRange(-5., 5.);
Shinya Kitaoka 120a6e
  m_startValue->setValueRange(0.0, 1.0);
Shinya Kitaoka 120a6e
  m_startCurve->setValueRange(0.1, 10.0);
Shinya Kitaoka 120a6e
  m_endValue->setValueRange(0.0, 1.0);
Shinya Kitaoka 120a6e
  m_endCurve->setValueRange(0.1, 10.0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_premultiType->addItem(SOURCE_IS_PREMULTIPLIED, "Source is premultiplied");
Shinya Kitaoka 120a6e
  m_premultiType->addItem(SOURCE_IS_NOT_PREMUTIPLIED,
Shinya Kitaoka 120a6e
                          "Source is NOT premultiplied");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  getAttributes()->setIsSpeedAware(true);
shun-iwasawa 481b59
  enableComputeInFloat(true);
shun-iwasawa 481b59
shun-iwasawa 481b59
  // Version 1: Exposure is computed by using Hardness
shun-iwasawa 481b59
  //            E = std::pow(10.0, (value - 0.5) / hardness)
shun-iwasawa 481b59
  // Version 2: Exposure is computed by using Gamma, for easier combination with
shun-iwasawa 481b59
  // the linear color space
shun-iwasawa 481b59
  //            E = std::pow(value, gamma)
shun-iwasawa 481b59
  // Version 3: Gamma is computed by rs.m_colorSpaceGamma + gammaAdjust
shun-iwasawa 481b59
  // this must be called after binding the parameters (see onFxVersionSet())
shun-iwasawa 481b59
  setFxVersion(3);
shun-iwasawa 481b59
}
shun-iwasawa 481b59
shun-iwasawa 481b59
//--------------------------------------------
shun-iwasawa 481b59
shun-iwasawa 481b59
void Iwa_MotionBlurCompFx::onFxVersionSet() {
shun-iwasawa 481b59
  if (getFxVersion() == 1) {  // use hardness
shun-iwasawa 481b59
    getParams()->getParamVar("hardness")->setIsHidden(false);
shun-iwasawa 481b59
    getParams()->getParamVar("gamma")->setIsHidden(true);
shun-iwasawa 481b59
    getParams()->getParamVar("gammaAdjust")->setIsHidden(true);
shun-iwasawa 481b59
    return;
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
  getParams()->getParamVar("hardness")->setIsHidden(true);
shun-iwasawa 481b59
shun-iwasawa 481b59
  bool useGamma = getFxVersion() == 2;
shun-iwasawa 481b59
  if (useGamma) {
shun-iwasawa 481b59
    // Automatically update version
shun-iwasawa 481b59
    if (m_gamma->getKeyframeCount() == 0 &&
shun-iwasawa 481b59
        areAlmostEqual(m_gamma->getDefaultValue(), 2.2)) {
shun-iwasawa 481b59
      useGamma = false;
shun-iwasawa 481b59
      setFxVersion(3);
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
  getParams()->getParamVar("gamma")->setIsHidden(!useGamma);
shun-iwasawa 481b59
  getParams()->getParamVar("gammaAdjust")->setIsHidden(useGamma);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void Iwa_MotionBlurCompFx::doCompute(TTile &tile, double frame,
Shinya Kitaoka 120a6e
                                     const TRenderSettings &settings) {
Campbell Barton d3ecc4
  /* Do not process if not connected */
Shinya Kitaoka 120a6e
  if (!m_input.isConnected() && !m_background.isConnected()) {
Shinya Kitaoka 120a6e
    tile.getRaster()->clear();
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Campbell Barton d3ecc4
  /* For BG only connection */
Shinya Kitaoka 120a6e
  if (!m_input.isConnected()) {
Shinya Kitaoka 120a6e
    m_background->compute(tile, frame, settings);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
shun-iwasawa 4f5900
  /* Get parameters */
Shinya Kitaoka 120a6e
  QList<tpointd> points = getAttributes()->getMotionPoints();</tpointd>
shun-iwasawa 481b59
  double gamma;
shun-iwasawa 481b59
  // The hardness value had been used inversely with the bokeh fxs.
shun-iwasawa 481b59
  // Now the convertion functions are shared with the bokeh fxs,
shun-iwasawa 481b59
  // so we need to change the hardness to reciprocal in order to obtain
shun-iwasawa 481b59
  // the same result as previous versions.
shun-iwasawa 481b59
  if (getFxVersion() == 1)
shun-iwasawa 481b59
    gamma = 1. / m_hardness->getValue(frame);
shun-iwasawa 481b59
  else {  // gamma
shun-iwasawa 481b59
    if (getFxVersion() == 2)
shun-iwasawa 481b59
      gamma = m_gamma->getValue(frame);
shun-iwasawa 481b59
    else
shun-iwasawa 481b59
      gamma = std::max(
shun-iwasawa 481b59
          1., settings.m_colorSpaceGamma + m_gammaAdjust->getValue(frame));
shun-iwasawa 481b59
    if (tile.getRaster()->isLinear()) gamma /= settings.m_colorSpaceGamma;
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
  double shutterStart = m_shutterStart->getValue(frame);
shun-iwasawa 481b59
  double shutterEnd   = m_shutterEnd->getValue(frame);
shun-iwasawa 481b59
  int traceResolution = m_traceResolution->getValue();
shun-iwasawa 481b59
  float startValue    = (float)m_startValue->getValue(frame);
shun-iwasawa 481b59
  float startCurve    = (float)m_startCurve->getValue(frame);
shun-iwasawa 481b59
  float endValue      = (float)m_endValue->getValue(frame);
shun-iwasawa 481b59
  float endCurve      = (float)m_endCurve->getValue(frame);
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
  /* Do not process if there are no more than two trajectory data */
Shinya Kitaoka 120a6e
  if (points.size() < 2) {
Shinya Kitaoka 120a6e
    if (!m_background.isConnected()) m_input->compute(tile, frame, settings);
Campbell Barton d3ecc4
    /* If there is a background and the foreground does not move, simply over */
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      composeWithNoMotion(tile, frame, settings);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
shun-iwasawa 4f5900
  /* Get display area */
Shinya Kitaoka 120a6e
  TRectD bBox =
Campbell Barton d3ecc4
      TRectD(tile.m_pos /* Render position on Pixel unit */
Shinya Kitaoka 120a6e
             ,
Campbell Barton d3ecc4
             TDimensionD(/* Size of Render image (Pixel unit) */
Shinya Kitaoka 120a6e
                         tile.getRaster()->getLx(), tile.getRaster()->getLy()));
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
  /* Get upper, lower, left and right margin */
Shinya Kitaoka 120a6e
  double minX = 0.0;
Shinya Kitaoka 120a6e
  double maxX = 0.0;
Shinya Kitaoka 120a6e
  double minY = 0.0;
Shinya Kitaoka 120a6e
  double maxY = 0.0;
Shinya Kitaoka 120a6e
  for (int p = 0; p < points.size(); p++) {
Shinya Kitaoka 120a6e
    if (points.at(p).x > maxX) maxX = points.at(p).x;
Shinya Kitaoka 120a6e
    if (points.at(p).x < minX) minX = points.at(p).x;
Shinya Kitaoka 120a6e
    if (points.at(p).y > maxY) maxY = points.at(p).y;
Shinya Kitaoka 120a6e
    if (points.at(p).y < minY) minY = points.at(p).y;
Shinya Kitaoka 120a6e
  }
Rozhuk Ivan 823a31
  int marginLeft   = (int)ceil(std::abs(minX));
Rozhuk Ivan 823a31
  int marginRight  = (int)ceil(std::abs(maxX));
Rozhuk Ivan 823a31
  int marginTop    = (int)ceil(std::abs(maxY));
Rozhuk Ivan 823a31
  int marginBottom = (int)ceil(std::abs(minY));
Shinya Kitaoka 120a6e
shun-iwasawa 4f5900
  /* Return the input tile as-is if there is not movement
shun-iwasawa 481b59
   * (= filter margins are all 0). */
Shinya Kitaoka 120a6e
  if (marginLeft == 0 && marginRight == 0 && marginTop == 0 &&
Shinya Kitaoka 120a6e
      marginBottom == 0) {
Shinya Kitaoka 120a6e
    if (!m_background.isConnected()) m_input->compute(tile, frame, settings);
shun-iwasawa 4f5900
    /* If there is a background, and the foreground does not move, simply over
shun-iwasawa 4f5900
     */
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      composeWithNoMotion(tile, frame, settings);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
shun-iwasawa 4f5900
  /* resize the bbox with the upper/lower/left/right inverted margins.
Campbell Barton d3ecc4
   */
Shinya Kitaoka 120a6e
  TRectD enlargedBBox(bBox.x0 - (double)marginRight,
Shinya Kitaoka 120a6e
                      bBox.y0 - (double)marginTop, bBox.x1 + (double)marginLeft,
Shinya Kitaoka 120a6e
                      bBox.y1 + (double)marginBottom);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // std::cout<<"Margin Left:"<
Shinya Kitaoka 120a6e
  //	" Bottom:"<
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
  TDimensionI enlargedDimIn(/* Rounded to the nearest Pixel */
Shinya Kitaoka 120a6e
                            (int)(enlargedBBox.getLx() + 0.5),
Shinya Kitaoka 120a6e
                            (int)(enlargedBBox.getLy() + 0.5));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TTile enlarge_tile;
Shinya Kitaoka 120a6e
  m_input->allocateAndCompute(enlarge_tile, enlargedBBox.getP00(),
Shinya Kitaoka 120a6e
                              enlargedDimIn, tile.getRaster(), frame, settings);
Shinya Kitaoka 120a6e
shun-iwasawa 4f5900
  /* If background is required */
Shinya Kitaoka 120a6e
  TTile back_Tile;
Shinya Kitaoka 120a6e
  if (m_background.isConnected()) {
Shinya Kitaoka 120a6e
    m_background->allocateAndCompute(back_Tile, tile.m_pos,
Shinya Kitaoka 120a6e
                                     tile.getRaster()->getSize(),
Shinya Kitaoka 120a6e
                                     tile.getRaster(), frame, settings);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //-------------------------------------------------------
Campbell Barton d3ecc4
  /* Compute range */
Shinya Kitaoka 120a6e
  TDimensionI dimOut(tile.getRaster()->getLx(), tile.getRaster()->getLy());
Shinya Kitaoka 120a6e
  TDimensionI filterDim(marginLeft + marginRight + 1,
Shinya Kitaoka 120a6e
                        marginTop + marginBottom + 1);
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
  /* Release of pointsTable is done within each doCompute */
Shinya Kitaoka 120a6e
  int pointAmount     = points.size();
Shinya Kitaoka 120a6e
  float4 *pointsTable = new float4[pointAmount];
Shinya Kitaoka 120a6e
  float dt = (float)(shutterStart + shutterEnd) / (float)traceResolution;
Shinya Kitaoka 120a6e
  for (int p = 0; p < pointAmount; p++) {
Shinya Kitaoka 120a6e
    pointsTable[p].x = (float)points.at(p).x;
Shinya Kitaoka 120a6e
    pointsTable[p].y = (float)points.at(p).y;
shun-iwasawa 4f5900
    /* z stores the distance of p -> p + 1 vector */
Shinya Kitaoka 120a6e
    if (p < pointAmount - 1) {
shun-iwasawa 481b59
      float2 vec       = {(float)(points.at(p + 1).x - points.at(p).x),
shun-iwasawa 481b59
                          (float)(points.at(p + 1).y - points.at(p).y)};
Shinya Kitaoka 120a6e
      pointsTable[p].z = sqrtf(vec.x * vec.x + vec.y * vec.y);
Shinya Kitaoka 120a6e
    }
shun-iwasawa 4f5900
    /* w stores shutter time offset */
Shinya Kitaoka 120a6e
    pointsTable[p].w = -(float)shutterStart + (float)p * dt;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  doCompute_CPU(tile, frame, settings, pointsTable, pointAmount, gamma,
Shinya Kitaoka 120a6e
                shutterStart, shutterEnd, traceResolution, startValue,
Shinya Kitaoka 120a6e
                startCurve, endValue, endCurve, marginLeft, marginRight,
Shinya Kitaoka 120a6e
                marginTop, marginBottom, enlargedDimIn, enlarge_tile, dimOut,
Shinya Kitaoka 120a6e
                filterDim, back_Tile);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void Iwa_MotionBlurCompFx::doCompute_CPU(
Shinya Kitaoka 120a6e
    TTile &tile, double frame, const TRenderSettings &settings,
shun-iwasawa 481b59
    float4 *pointsTable, int pointAmount, double gamma, double shutterStart,
Shinya Kitaoka 120a6e
    double shutterEnd, int traceResolution, float startValue, float startCurve,
Shinya Kitaoka 120a6e
    float endValue, float endCurve, int marginLeft, int marginRight,
Shinya Kitaoka 120a6e
    int marginTop, int marginBottom, TDimensionI &enlargedDimIn,
Shinya Kitaoka 120a6e
    TTile &enlarge_tile, TDimensionI &dimOut, TDimensionI &filterDim,
Shinya Kitaoka 120a6e
    TTile &back_tile) {
Campbell Barton d3ecc4
  /* Processing memory */
Campbell Barton d3ecc4
  float4 *in_tile_p;  /* With margin */
Campbell Barton d3ecc4
  float4 *out_tile_p; /* With margin */
Campbell Barton d3ecc4
  /* Filter */
Shinya Kitaoka 120a6e
  float *filter_p;
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
  /* Memory allocation */
Shinya Kitaoka 120a6e
  TRasterGR8P in_tile_ras(sizeof(float4) * enlargedDimIn.lx, enlargedDimIn.ly);
Shinya Kitaoka 120a6e
  in_tile_ras->lock();
Shinya Kitaoka 120a6e
  in_tile_p = (float4 *)in_tile_ras->getRawData();
Shinya Kitaoka 120a6e
  TRasterGR8P out_tile_ras(sizeof(float4) * enlargedDimIn.lx, enlargedDimIn.ly);
Shinya Kitaoka 120a6e
  out_tile_ras->lock();
Shinya Kitaoka 120a6e
  out_tile_p = (float4 *)out_tile_ras->getRawData();
Shinya Kitaoka 120a6e
  TRasterGR8P filter_ras(sizeof(float) * filterDim.lx, filterDim.ly);
Shinya Kitaoka 120a6e
  filter_ras->lock();
Shinya Kitaoka 120a6e
  filter_p = (float *)filter_ras->getRawData();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool sourceIsPremultiplied;
shun-iwasawa 4f5900
  /* normalize the source image to 0 - 1 and read it into memory */
Shinya Kitaoka 120a6e
  TRaster32P ras32 = (TRaster32P)enlarge_tile.getRaster();
Shinya Kitaoka 120a6e
  TRaster64P ras64 = (TRaster64P)enlarge_tile.getRaster();
shun-iwasawa 481b59
  TRasterFP rasF   = (TRasterFP)enlarge_tile.getRaster();
Shinya Kitaoka 120a6e
  if (ras32)
Shinya Kitaoka 120a6e
    sourceIsPremultiplied = setSourceRaster<traster32p, tpixel32="">(</traster32p,>
Shinya Kitaoka 120a6e
        ras32, in_tile_p, enlargedDimIn,
Shinya Kitaoka 120a6e
        (PremultiTypes)m_premultiType->getValue());
Shinya Kitaoka 120a6e
  else if (ras64)
Shinya Kitaoka 120a6e
    sourceIsPremultiplied = setSourceRaster<traster64p, tpixel64="">(</traster64p,>
Shinya Kitaoka 120a6e
        ras64, in_tile_p, enlargedDimIn,
Shinya Kitaoka 120a6e
        (PremultiTypes)m_premultiType->getValue());
shun-iwasawa 481b59
  else if (rasF)
shun-iwasawa 481b59
    sourceIsPremultiplied = setSourceRaster<trasterfp, tpixelf="">(</trasterfp,>
shun-iwasawa 481b59
        rasF, in_tile_p, enlargedDimIn,
shun-iwasawa 481b59
        (PremultiTypes)m_premultiType->getValue());
Shinya Kitaoka 120a6e
shun-iwasawa 4f5900
  /* When afterimage mode is off */
Shinya Kitaoka 120a6e
  if (!m_zanzoMode->getValue()) {
Campbell Barton d3ecc4
    /* Create and normalize filters */
Shinya Kitaoka 120a6e
    makeMotionBlurFilter_CPU(filter_p, filterDim, marginLeft, marginBottom,
Shinya Kitaoka 120a6e
                             pointsTable, pointAmount, startValue, startCurve,
Shinya Kitaoka 120a6e
                             endValue, endCurve);
Shinya Kitaoka 120a6e
  }
shun-iwasawa 4f5900
  /* When afterimage mode is ON */
Shinya Kitaoka 120a6e
  else {
shun-iwasawa 4f5900
    /* Create / normalize the afterimage filter */
Shinya Kitaoka 120a6e
    makeZanzoFilter_CPU(filter_p, filterDim, marginLeft, marginBottom,
Shinya Kitaoka 120a6e
                        pointsTable, pointAmount, startValue, startCurve,
Shinya Kitaoka 120a6e
                        endValue, endCurve);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  delete[] pointsTable;
Shinya Kitaoka 120a6e
shun-iwasawa 4f5900
  /* Unpremultiply RGB value (0 to 1)
Campbell Barton d3ecc4
   * -> convert it to exposure value
Campbell Barton d3ecc4
   * -> premultiply again
Campbell Barton d3ecc4
   */
shun-iwasawa 481b59
  if (getFxVersion() == 1)
shun-iwasawa 481b59
    convertRGBtoExposure_CPU(
shun-iwasawa 481b59
        in_tile_p, enlargedDimIn,
shun-iwasawa 481b59
        HardnessBasedConverter(gamma, settings.m_colorSpaceGamma,
shun-iwasawa 481b59
                               enlarge_tile.getRaster()->isLinear()),
shun-iwasawa 481b59
        sourceIsPremultiplied);
shun-iwasawa 481b59
  else
shun-iwasawa 481b59
    convertRGBtoExposure_CPU(in_tile_p, enlargedDimIn,
shun-iwasawa 481b59
                             GammaBasedConverter(gamma), sourceIsPremultiplied);
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
  /* Filter and blur exposure value */
Shinya Kitaoka 120a6e
  applyBlurFilter_CPU(in_tile_p, out_tile_p, enlargedDimIn, filter_p, filterDim,
Shinya Kitaoka 120a6e
                      marginLeft, marginBottom, marginRight, marginTop, dimOut);
Campbell Barton d3ecc4
  /* Memory release */
Shinya Kitaoka 120a6e
  in_tile_ras->unlock();
Shinya Kitaoka 120a6e
  filter_ras->unlock();
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
  /* If there is a background, do Exposure multiplication */
Shinya Kitaoka 120a6e
  if (m_background.isConnected()) {
shun-iwasawa 481b59
    if (getFxVersion() == 1)
shun-iwasawa 481b59
      composeBackgroundExposure_CPU(
shun-iwasawa 481b59
          out_tile_p, enlargedDimIn, marginRight, marginTop, back_tile, dimOut,
shun-iwasawa 481b59
          HardnessBasedConverter(gamma, settings.m_colorSpaceGamma,
shun-iwasawa 481b59
                                 tile.getRaster()->isLinear()));
shun-iwasawa 481b59
    else
shun-iwasawa 481b59
      composeBackgroundExposure_CPU(out_tile_p, enlargedDimIn, marginRight,
shun-iwasawa 481b59
                                    marginTop, back_tile, dimOut,
shun-iwasawa 481b59
                                    GammaBasedConverter(gamma));
Shinya Kitaoka 120a6e
  }
shun-iwasawa 4f5900
  /* Unpremultiply the exposure value
shun-iwasawa 4f5900
   * -> convert back to RGB value (0 to 1)
shun-iwasawa 4f5900
   * -> premultiply */
shun-iwasawa 481b59
  if (getFxVersion() == 1)
shun-iwasawa 481b59
    convertExposureToRGB_CPU(
shun-iwasawa 481b59
        out_tile_p, enlargedDimIn,
shun-iwasawa 481b59
        HardnessBasedConverter(gamma, settings.m_colorSpaceGamma,
shun-iwasawa 481b59
                               tile.getRaster()->isLinear()));
shun-iwasawa 481b59
  else
shun-iwasawa 481b59
    convertExposureToRGB_CPU(out_tile_p, enlargedDimIn,
shun-iwasawa 481b59
                             GammaBasedConverter(gamma));
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
  /* Clear raster */
Shinya Kitaoka 120a6e
  tile.getRaster()->clear();
Shinya Kitaoka 120a6e
  TRaster32P outRas32 = (TRaster32P)tile.getRaster();
Shinya Kitaoka 120a6e
  TRaster64P outRas64 = (TRaster64P)tile.getRaster();
shun-iwasawa 481b59
  TRasterFP outRasF   = (TRasterFP)tile.getRaster();
Shinya Kitaoka 120a6e
  int2 margin         = {marginRight, marginTop};
Shinya Kitaoka 120a6e
  if (outRas32)
Shinya Kitaoka 120a6e
    setOutputRaster<traster32p, tpixel32="">(out_tile_p, outRas32, enlargedDimIn,</traster32p,>
Shinya Kitaoka 120a6e
                                          margin);
Shinya Kitaoka 120a6e
  else if (outRas64)
Shinya Kitaoka 120a6e
    setOutputRaster<traster64p, tpixel64="">(out_tile_p, outRas64, enlargedDimIn,</traster64p,>
Shinya Kitaoka 120a6e
                                          margin);
shun-iwasawa 481b59
  else if (outRasF)
shun-iwasawa 481b59
    setOutputRaster<trasterfp, tpixelf="">(out_tile_p, outRasF, enlargedDimIn,</trasterfp,>
shun-iwasawa 481b59
                                        margin);
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
  /* Memory release */
Shinya Kitaoka 120a6e
  out_tile_ras->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool Iwa_MotionBlurCompFx::doGetBBox(double frame, TRectD &bBox,
Shinya Kitaoka 120a6e
                                     const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  if (!m_input.isConnected() && !m_background.isConnected()) {
Shinya Kitaoka 120a6e
    bBox = TRectD();
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
luz paz 6454c4
  /* Rough implementation - return infinite size if the background is connected
shun-iwasawa 4f5900
   */
Shinya Kitaoka 120a6e
  if (m_background.isConnected()) {
Shinya Kitaoka 120a6e
    bool _ret = m_background->doGetBBox(frame, bBox, info);
Shinya Kitaoka 120a6e
    bBox      = TConsts::infiniteRectD;
Shinya Kitaoka 120a6e
    return _ret;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool ret = m_input->doGetBBox(frame, bBox, info);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (bBox == TConsts::infiniteRectD) return true;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  QList<tpointd> points = getAttributes()->getMotionPoints();</tpointd>
shun-iwasawa 4f5900
  /* Compute the margin from the bounding box of the moved trajectory */
shun-iwasawa 4f5900
  /* Obtain the maximum absolute value of the coordinates of each trajectory
shun-iwasawa 4f5900
   * point */
shun-iwasawa 4f5900
  /* Get upper, lower, left and right margins */
Shinya Kitaoka 120a6e
  double minX = 0.0;
Shinya Kitaoka 120a6e
  double maxX = 0.0;
Shinya Kitaoka 120a6e
  double minY = 0.0;
Shinya Kitaoka 120a6e
  double maxY = 0.0;
Shinya Kitaoka 120a6e
  for (int p = 0; p < points.size(); p++) {
Shinya Kitaoka 120a6e
    if (points.at(p).x > maxX) maxX = points.at(p).x;
Shinya Kitaoka 120a6e
    if (points.at(p).x < minX) minX = points.at(p).x;
Shinya Kitaoka 120a6e
    if (points.at(p).y > maxY) maxY = points.at(p).y;
Shinya Kitaoka 120a6e
    if (points.at(p).y < minY) minY = points.at(p).y;
Shinya Kitaoka 120a6e
  }
Rozhuk Ivan 823a31
  int marginLeft   = (int)ceil(std::abs(minX));
Rozhuk Ivan 823a31
  int marginRight  = (int)ceil(std::abs(maxX));
Rozhuk Ivan 823a31
  int marginTop    = (int)ceil(std::abs(maxY));
Rozhuk Ivan 823a31
  int marginBottom = (int)ceil(std::abs(minY));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRectD enlargedBBox(
Shinya Kitaoka 120a6e
      bBox.x0 - (double)marginLeft, bBox.y0 - (double)marginBottom,
Shinya Kitaoka 120a6e
      bBox.x1 + (double)marginRight, bBox.y1 + (double)marginTop);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bBox = enlargedBBox;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return ret;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool Iwa_MotionBlurCompFx::canHandle(const TRenderSettings &info,
Shinya Kitaoka 120a6e
                                     double frame) {
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*------------------------------------------------------------
Campbell Barton d3ecc4
 Since there is a possibility that the reference object is moving,
shun-iwasawa 4f5900
 Change the alias every frame
Toshihiro Shimizu 890ddd
------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::string Iwa_MotionBlurCompFx::getAlias(double frame,
Shinya Kitaoka 120a6e
                                           const TRenderSettings &info) const {
Shinya Kitaoka 120a6e
  std::string alias = getFxType();
Shinya Kitaoka 120a6e
  alias += "[";
Shinya Kitaoka 120a6e
Campbell Barton d3ecc4
  // alias of the effects related to the input ports separated by commas
Campbell Barton d3ecc4
  // a port that is not connected to an alias blank (empty string)
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = 0; i < getInputPortCount(); i++) {
Shinya Kitaoka 120a6e
    TFxPort *port = getInputPort(i);
Shinya Kitaoka 120a6e
    if (port->isConnected()) {
Shinya Kitaoka 120a6e
      TRasterFxP ifx = port->getFx();
Shinya Kitaoka 120a6e
      assert(ifx);
Shinya Kitaoka 120a6e
      alias += ifx->getAlias(frame, info);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    alias += ",";
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::string paramalias("");
Shinya Kitaoka 120a6e
  for (i = 0; i < getParams()->getParamCount(); i++) {
Shinya Kitaoka 120a6e
    TParam *param = getParams()->getParam(i);
Shinya Kitaoka 120a6e
    paramalias += param->getName() + "=" + param->getValueAlias(frame, 3);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  unsigned long id = getIdentifier();
Shinya Kitaoka 120a6e
  return alias + std::to_string(frame) + "," + std::to_string(id) + paramalias +
Shinya Kitaoka 120a6e
         "]";
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
shun-iwasawa 481b59
//------------------------------------------------------------
shun-iwasawa 481b59
shun-iwasawa 481b59
bool Iwa_MotionBlurCompFx::toBeComputedInLinearColorSpace(
shun-iwasawa 481b59
    bool settingsIsLinear, bool tileIsLinear) const {
shun-iwasawa 481b59
  return settingsIsLinear;
shun-iwasawa 481b59
}
shun-iwasawa 481b59
Toshihiro Shimizu 890ddd
FX_PLUGIN_IDENTIFIER(Iwa_MotionBlurCompFx, "iwa_MotionBlurCompFx")