Toshihiro Shimizu 890ddd
#include "iwa_adjustexposurefx.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tfxparam.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*------------------------------------------------------------
Toshihiro Shimizu 890ddd
 ソース画像を0〜1に正規化してホストメモリに読み込む
Toshihiro Shimizu 890ddd
------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixel="" raster,="" typename=""></typename>
Shinya Kitaoka 120a6e
void Iwa_AdjustExposureFx::setSourceRaster(const RASTER srcRas, float4 *dstMem,
Shinya Kitaoka 120a6e
                                           TDimensionI dim) {
Shinya Kitaoka 120a6e
  float4 *chann_p = dstMem;
Shinya Kitaoka 120a6e
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
Shinya Kitaoka 120a6e
      pix++;
Shinya Kitaoka 120a6e
      chann_p++;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
shun-iwasawa 481b59
void Iwa_AdjustExposureFx::setSourceRasterF(const TRasterFP srcRas,
shun-iwasawa 481b59
                                            float4 *dstMem, TDimensionI dim) {
shun-iwasawa 481b59
  float4 *chann_p = dstMem;
shun-iwasawa 481b59
shun-iwasawa 481b59
  for (int j = 0; j < dim.ly; j++) {
shun-iwasawa 481b59
    TPixelF *pix = srcRas->pixels(j);
shun-iwasawa 481b59
    for (int i = 0; i < dim.lx; i++) {
shun-iwasawa 481b59
      (*chann_p).x = pix->r;
shun-iwasawa 481b59
      (*chann_p).y = pix->g;
shun-iwasawa 481b59
      (*chann_p).z = pix->b;
shun-iwasawa 481b59
      (*chann_p).w = pix->m;
shun-iwasawa 481b59
shun-iwasawa 481b59
      pix++;
shun-iwasawa 481b59
      chann_p++;
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
}
Toshihiro Shimizu 890ddd
/*------------------------------------------------------------
Toshihiro Shimizu 890ddd
 出力結果をChannel値に変換してタイルに格納
Toshihiro Shimizu 890ddd
------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
template <typename pixel="" raster,="" typename=""></typename>
Shinya Kitaoka 120a6e
void Iwa_AdjustExposureFx::setOutputRaster(float4 *srcMem, const RASTER dstRas,
Shinya Kitaoka 120a6e
                                           TDimensionI dim) {
Shinya Kitaoka 120a6e
  float4 *chan_p = srcMem;
Shinya Kitaoka 120a6e
  for (int j = 0; j < dim.ly; j++) {
Shinya Kitaoka 120a6e
    PIXEL *pix = dstRas->pixels(j);
Shinya Kitaoka 120a6e
    for (int i = 0; i < dim.lx; 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
Shinya Kitaoka 120a6e
      pix++;
Shinya Kitaoka 120a6e
      chan_p++;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
shun-iwasawa 481b59
void Iwa_AdjustExposureFx::setOutputRasterF(float4 *srcMem,
shun-iwasawa 481b59
                                            const TRasterFP dstRas,
shun-iwasawa 481b59
                                            TDimensionI dim) {
shun-iwasawa 481b59
  float4 *chan_p = srcMem;
shun-iwasawa 481b59
  for (int j = 0; j < dim.ly; j++) {
shun-iwasawa 481b59
    TPixelF *pix = dstRas->pixels(j);
shun-iwasawa 481b59
    for (int i = 0; i < dim.lx; 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
//------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Iwa_AdjustExposureFx::Iwa_AdjustExposureFx()
shun-iwasawa 481b59
    : m_hardness(3.3)
shun-iwasawa 481b59
    , m_scale(0.0)
shun-iwasawa 481b59
    , m_offset(0.0)
shun-iwasawa 481b59
    , m_gamma(2.2)
shun-iwasawa 481b59
    , m_gammaAdjust(0.) {
Shinya Kitaoka 120a6e
  addInputPort("Source", m_source);
Shinya Kitaoka 120a6e
  bindParam(this, "hardness", m_hardness, false);
shun-iwasawa 481b59
  bindParam(this, "gamma", m_gamma);
shun-iwasawa 481b59
  bindParam(this, "gammaAdjust", m_gammaAdjust);
Shinya Kitaoka 120a6e
  bindParam(this, "scale", m_scale, false);
Shinya Kitaoka 120a6e
  bindParam(this, "offset", m_offset, false);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_hardness->setValueRange(0.05, 20.0);
shun-iwasawa 481b59
  m_gamma->setValueRange(1.0, 10.0);
shun-iwasawa 481b59
  m_gammaAdjust->setValueRange(-5., 5.);
Shinya Kitaoka 120a6e
  m_scale->setValueRange(-10.0, 10.0);
Shinya Kitaoka 120a6e
  m_offset->setValueRange(-0.5, 0.5);
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_AdjustExposureFx::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_AdjustExposureFx::doCompute(TTile &tile, double frame,
Shinya Kitaoka 120a6e
                                     const TRenderSettings &settings) {
Shinya Kitaoka 120a6e
  /*- Sourceが無ければreturn -*/
Shinya Kitaoka 120a6e
  if (!m_source.isConnected()) {
Shinya Kitaoka 120a6e
    tile.getRaster()->clear();
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  double gamma;
shun-iwasawa 481b59
  if (getFxVersion() == 1)  // hardness
shun-iwasawa 481b59
    gamma = 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
Shinya Kitaoka 120a6e
  m_source->compute(tile, frame, settings);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TDimensionI dim(tile.getRaster()->getSize());
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  if (TRasterFP rasF = tile.getRaster()) {
shun-iwasawa 481b59
    if (getFxVersion() == 1)
shun-iwasawa 481b59
      doFloatCompute(rasF, frame, dim,
shun-iwasawa 481b59
                     HardnessBasedConverter(gamma, settings.m_colorSpaceGamma,
shun-iwasawa 481b59
                                            tile.getRaster()->isLinear()));
shun-iwasawa 481b59
    else
shun-iwasawa 481b59
      doFloatCompute(rasF, frame, dim, GammaBasedConverter(gamma));
shun-iwasawa 481b59
    return;
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
shun-iwasawa 481b59
  float4 *tile_host;
shun-iwasawa 481b59
Shinya Kitaoka 120a6e
  /*- ホストメモリ確保 -*/
Shinya Kitaoka 120a6e
  TRasterGR8P tile_host_ras(sizeof(float4) * dim.lx, dim.ly);
Shinya Kitaoka 120a6e
  tile_host_ras->lock();
Shinya Kitaoka 120a6e
  tile_host = (float4 *)tile_host_ras->getRawData();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRaster32P ras32 = tile.getRaster();
Shinya Kitaoka 120a6e
  TRaster64P ras64 = tile.getRaster();
shun-iwasawa 481b59
Shinya Kitaoka 120a6e
  if (ras32)
Shinya Kitaoka 120a6e
    setSourceRaster<traster32p, tpixel32="">(ras32, tile_host, dim);</traster32p,>
Shinya Kitaoka 120a6e
  else if (ras64)
Shinya Kitaoka 120a6e
    setSourceRaster<traster64p, tpixel64="">(ras64, tile_host, dim);</traster64p,>
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  if (getFxVersion() == 1)
shun-iwasawa 481b59
    doCompute_CPU(frame, dim, tile_host,
shun-iwasawa 481b59
                  HardnessBasedConverter(gamma, settings.m_colorSpaceGamma,
shun-iwasawa 481b59
                                         tile.getRaster()->isLinear()));
shun-iwasawa 481b59
  else
shun-iwasawa 481b59
    doCompute_CPU(frame, dim, tile_host, GammaBasedConverter(gamma));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*-  出力結果をチャンネル値に変換 -*/
Shinya Kitaoka 120a6e
  tile.getRaster()->clear();
Shinya Kitaoka 120a6e
  if (ras32)
Shinya Kitaoka 120a6e
    setOutputRaster<traster32p, tpixel32="">(tile_host, ras32, dim);</traster32p,>
Shinya Kitaoka 120a6e
  else if (ras64)
Shinya Kitaoka 120a6e
    setOutputRaster<traster64p, tpixel64="">(tile_host, ras64, dim);</traster64p,>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  tile_host_ras->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------
Toshihiro Shimizu 890ddd
shun-iwasawa 481b59
void Iwa_AdjustExposureFx::doCompute_CPU(double frame, TDimensionI &dim,
shun-iwasawa 481b59
                                         float4 *tile_host,
shun-iwasawa 481b59
                                         const ExposureConverter &conv) {
shun-iwasawa 481b59
  float scale  = (float)m_scale->getValue(frame);
shun-iwasawa 481b59
  float offset = (float)m_offset->getValue(frame);
Shinya Kitaoka 120a6e
shun-iwasawa 481b59
  float exposureOffset = (conv.valueToExposure(std::abs(offset) + 0.5) -
shun-iwasawa 481b59
                          conv.valueToExposure(0.5)) *
Shinya Kitaoka 120a6e
                         ((offset < 0.0f) ? -1.0f : 1.0f);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  float4 *pix = tile_host;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int size = dim.lx * dim.ly;
Shinya Kitaoka 120a6e
  for (int i = 0; i < size; i++, pix++) {
Shinya Kitaoka 120a6e
    /*- RGB->Exposure -*/
shun-iwasawa 481b59
    pix->x = conv.valueToExposure(pix->x);
shun-iwasawa 481b59
    pix->y = conv.valueToExposure(pix->y);
shun-iwasawa 481b59
    pix->z = conv.valueToExposure(pix->z);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /*- スケール -*/
Shinya Kitaoka 120a6e
    pix->x *= powf(10, scale);
Shinya Kitaoka 120a6e
    pix->y *= powf(10, scale);
Shinya Kitaoka 120a6e
    pix->z *= powf(10, scale);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /*- オフセット -*/
Shinya Kitaoka 120a6e
    pix->x += exposureOffset;
Shinya Kitaoka 120a6e
    pix->y += exposureOffset;
Shinya Kitaoka 120a6e
    pix->z += exposureOffset;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /*- Exposure->RGB -*/
shun-iwasawa 481b59
    pix->x = (pix->x < 0.0f) ? 0.0f : conv.exposureToValue(pix->x);
shun-iwasawa 481b59
    pix->y = (pix->y < 0.0f) ? 0.0f : conv.exposureToValue(pix->y);
shun-iwasawa 481b59
    pix->z = (pix->z < 0.0f) ? 0.0f : conv.exposureToValue(pix->z);
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
}
shun-iwasawa 481b59
shun-iwasawa 481b59
//------------------------------------------------
shun-iwasawa 481b59
shun-iwasawa 481b59
void Iwa_AdjustExposureFx::doFloatCompute(const TRasterFP rasD, double frame,
shun-iwasawa 481b59
                                          TDimensionI &dim,
shun-iwasawa 481b59
                                          const ExposureConverter &conv) {
shun-iwasawa 481b59
  double scale          = m_scale->getValue(frame);
shun-iwasawa 481b59
  double offset         = m_offset->getValue(frame);
shun-iwasawa 481b59
  double exposureOffset = (conv.valueToExposure(std::abs(offset) + 0.5) -
shun-iwasawa 481b59
                           conv.valueToExposure(0.5)) *
shun-iwasawa 481b59
                          ((offset < 0.) ? -1. : 1.);
shun-iwasawa 481b59
shun-iwasawa 481b59
  for (int j = 0; j < dim.ly; j++) {
shun-iwasawa 481b59
    TPixelF *pix = rasD->pixels(j);
shun-iwasawa 481b59
    for (int i = 0; i < dim.lx; i++) {
shun-iwasawa 481b59
      for (int c = 0; c < 3; c++) {
shun-iwasawa 481b59
        float *val = (c == 0) ? &pix->r : (c == 1) ? &pix->g : &pix->b;
shun-iwasawa 481b59
        /*- RGB->Exposure -*/
shun-iwasawa 481b59
        *val = conv.valueToExposure(*val);
shun-iwasawa 481b59
        /*- スケール -*/
shun-iwasawa 481b59
        *val *= pow(10.0, scale);
shun-iwasawa 481b59
        /*- オフセット -*/
shun-iwasawa 481b59
        *val += exposureOffset;
shun-iwasawa 481b59
        /*- Exposure->RGB -*/
shun-iwasawa 481b59
        *val = (*val < 0.f) ? 0.f : conv.exposureToValue(*val);
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
      pix++;
shun-iwasawa 481b59
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool Iwa_AdjustExposureFx::doGetBBox(double frame, TRectD &bBox,
Shinya Kitaoka 120a6e
                                     const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  if (m_source.isConnected()) {
Shinya Kitaoka 120a6e
    bool ret = m_source->doGetBBox(frame, bBox, info);
Shinya Kitaoka 120a6e
    return ret;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    bBox = TRectD();
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool Iwa_AdjustExposureFx::canHandle(const TRenderSettings &info,
Shinya Kitaoka 120a6e
                                     double frame) {
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
shun-iwasawa 481b59
//------------------------------------------------
shun-iwasawa 481b59
shun-iwasawa 481b59
bool Iwa_AdjustExposureFx::toBeComputedInLinearColorSpace(
shun-iwasawa 481b59
    bool settingsIsLinear, bool tileIsLinear) const {
shun-iwasawa 481b59
  // 下流がリニア計算するかどうかで判断。これで変換を最小限にできるか…?
shun-iwasawa 481b59
  return tileIsLinear;
shun-iwasawa 481b59
}
shun-iwasawa 481b59
Toshihiro Shimizu 890ddd
FX_PLUGIN_IDENTIFIER(Iwa_AdjustExposureFx, "iwa_AdjustExposureFx")