shun_iwasawa a35b8f
#pragma once
shun_iwasawa a35b8f
shun_iwasawa a35b8f
/*------------------------------------
shun_iwasawa a35b8f
Iwa_BokehFx
shun_iwasawa a35b8f
Apply an off-focus effect to the source image, using user input iris image.
shun_iwasawa a35b8f
It considers characteristics of films (which is known as Hurter–Driffield
shun_iwasawa a35b8f
curves)
shun_iwasawa a35b8f
or human eye's perception (which is known as Weber–Fechner law).
shun_iwasawa a35b8f
For filtering process I used KissFFT, an FFT library by Mark Borgerding,
shun_iwasawa a35b8f
distributed with a 3-clause BSD-style license.
shun_iwasawa a35b8f
------------------------------------*/
shun_iwasawa a35b8f
shun_iwasawa a35b8f
#ifndef IWA_BOKEHFX_H
shun_iwasawa a35b8f
#define IWA_BOKEHFX_H
shun_iwasawa a35b8f
shun_iwasawa a35b8f
#include "stdfx.h"
shun_iwasawa a35b8f
#include "tfxparam.h"
shun_iwasawa a35b8f
#include "traster.h"
shun_iwasawa a35b8f
shun_iwasawa a35b8f
#include <qlist></qlist>
shun_iwasawa a35b8f
#include <qthread></qthread>
shun_iwasawa a35b8f
shun_iwasawa a35b8f
#include "tools/kiss_fftnd.h"
shun_iwasawa a35b8f
shun_iwasawa a35b8f
const int LAYER_NUM = 5;
shun_iwasawa a35b8f
shun_iwasawa a35b8f
struct double2 {
shun_iwasawa a35b8f
  double x, y;
shun_iwasawa a35b8f
};
shun_iwasawa a35b8f
struct int2 {
shun_iwasawa a35b8f
  int x, y;
shun_iwasawa a35b8f
};
shun_iwasawa a35b8f
shun_iwasawa a35b8f
class MyThread : public QThread {
shun_iwasawa a35b8f
public:
shun_iwasawa a35b8f
  enum Channel { Red = 0, Green, Blue };
shun_iwasawa a35b8f
shun_iwasawa a35b8f
private:
shun_iwasawa a35b8f
  Channel m_channel;
shun_iwasawa a35b8f
shun_iwasawa a35b8f
  volatile bool m_finished;
shun_iwasawa a35b8f
shun_iwasawa a35b8f
  TRasterP m_layerTileRas;
shun_iwasawa a35b8f
  TRasterP m_outTileRas;
shun_iwasawa a35b8f
  TRasterP m_tmpAlphaRas;
shun_iwasawa a35b8f
shun_iwasawa a35b8f
  kiss_fft_cpx *m_kissfft_comp_iris;
shun_iwasawa a35b8f
shun_iwasawa a35b8f
  float m_filmGamma;  // keep the film gamma in each thread as it is refered so
shun_iwasawa a35b8f
                      // often
shun_iwasawa a35b8f
shun_iwasawa a35b8f
  TRasterGR8P m_kissfft_comp_in_ras, m_kissfft_comp_out_ras;
shun_iwasawa a35b8f
  kiss_fft_cpx *m_kissfft_comp_in, *m_kissfft_comp_out;
shun_iwasawa a35b8f
  kiss_fftnd_cfg m_kissfft_plan_fwd, m_kissfft_plan_bkwd;
shun_iwasawa a35b8f
shun_iwasawa a35b8f
  bool m_isTerminated;
shun_iwasawa a35b8f
shun_iwasawa a35b8f
  // not used for now
shun_iwasawa a35b8f
  bool m_doLightenComp;
shun_iwasawa a35b8f
shun_iwasawa a35b8f
public:
shun_iwasawa a35b8f
  MyThread(Channel channel, TRasterP layerTileRas, TRasterP outTileRas,
shun_iwasawa a35b8f
           TRasterP tmpAlphaRas, kiss_fft_cpx *kissfft_comp_iris,
shun_iwasawa a35b8f
           float m_filmGamma,
shun_iwasawa a35b8f
           bool doLightenComp = false);  // not used for now
shun_iwasawa a35b8f
shun_iwasawa a35b8f
  // Convert the pixels from RGB values to exposures and multiply it by alpha
shun_iwasawa a35b8f
  // channel value.
shun_iwasawa a35b8f
  // Store the results in the real part of kiss_fft_cpx.
shun_iwasawa a35b8f
  template <typename pixel="" raster,="" typename=""></typename>
shun_iwasawa a35b8f
  void setLayerRaster(const RASTER srcRas, kiss_fft_cpx *dstMem,
shun_iwasawa a35b8f
                      TDimensionI dim);
shun_iwasawa a35b8f
shun_iwasawa a35b8f
  // Composite the bokeh layer to the result
shun_iwasawa a35b8f
  template 
shun_iwasawa a35b8f
            typename A_PIXEL>
shun_iwasawa a35b8f
  void compositLayerToTile(const RASTER layerRas, const RASTER outTileRas,
shun_iwasawa a35b8f
                           const A_RASTER alphaRas, TDimensionI dim,
shun_iwasawa a35b8f
                           int2 margin);
shun_iwasawa a35b8f
  void run();
shun_iwasawa a35b8f
shun_iwasawa a35b8f
  bool isFinished() { return m_finished; }
shun_iwasawa a35b8f
shun_iwasawa a35b8f
  // RGB value <--> Exposure
shun_iwasawa a35b8f
  float valueToExposure(float value);
shun_iwasawa a35b8f
  float exposureToValue(float exposure);
shun_iwasawa a35b8f
shun_iwasawa a35b8f
  // memory allocation
shun_iwasawa a35b8f
  bool init();
shun_iwasawa a35b8f
shun_iwasawa a35b8f
  void terminateThread() { m_isTerminated = true; }
shun_iwasawa a35b8f
shun_iwasawa a35b8f
  bool checkTerminationAndCleanupThread();
shun_iwasawa a35b8f
};
shun_iwasawa a35b8f
shun_iwasawa a35b8f
class Iwa_BokehFx : public TStandardRasterFx {
shun_iwasawa a35b8f
  FX_PLUGIN_DECLARATION(Iwa_BokehFx)
shun_iwasawa a35b8f
shun_iwasawa a35b8f
protected:
shun_iwasawa a35b8f
  TRasterFxPort m_iris;
shun_iwasawa a35b8f
  TDoubleParamP m_onFocusDistance;  // Focus Distance (0-1)
shun_iwasawa a35b8f
  TDoubleParamP m_bokehAmount;  // The maximum bokeh size. The size of bokeh at
shun_iwasawa a35b8f
                                // the layer separated by 1.0 from the focal
shun_iwasawa a35b8f
                                // position
shun_iwasawa a35b8f
  TDoubleParamP m_hardness;     // Film gamma
shun_iwasawa a35b8f
shun_iwasawa a35b8f
  struct LAYERPARAM {
shun_iwasawa a35b8f
    TRasterFxPort m_source;
shun_iwasawa a35b8f
    TBoolParamP m_premultiply;
shun_iwasawa a35b8f
    TDoubleParamP m_distance;  // The layer distance from the camera (0-1)
shun_iwasawa a35b8f
    TDoubleParamP m_bokehAdjustment;  // Factor for adjusting distance (= focal
shun_iwasawa a35b8f
                                      // distance - layer distance) (0-2.0)
shun_iwasawa a35b8f
  } m_layerParams[LAYER_NUM];
shun_iwasawa a35b8f
shun_iwasawa a35b8f
  // Sort source layers by distance
shun_iwasawa a35b8f
  QList<int> getSortedSourceIndices(double frame);</int>
shun_iwasawa a35b8f
  // Get the pixel size of bokehAmount ( referenced ino_blur.cpp )
shun_iwasawa a35b8f
  float getBokehPixelAmount(const double frame, const TAffine affine);
shun_iwasawa a35b8f
  // Compute the bokeh size for each layer. The source tile will be enlarged by
shun_iwasawa a35b8f
  // the largest size of them.
shun_iwasawa a35b8f
  QVector<float> getIrisSizes(const double frame,</float>
shun_iwasawa a35b8f
                              const QList<int> sourceIndices,</int>
shun_iwasawa a35b8f
                              const float bokehPixelAmount, float &maxIrisSize);
shun_iwasawa a35b8f
  //"Over" composite the layer to the output raster.
shun_iwasawa a35b8f
  void compositLayerAsIs(TTile &tile, TTile &layerTile, const double frame,
shun_iwasawa a35b8f
                         const TRenderSettings &settings, const int index);
shun_iwasawa a35b8f
  // Resize / flip the iris image according to the size ratio.
shun_iwasawa a35b8f
  // Normalize the brightness of the iris image.
shun_iwasawa a35b8f
  // Enlarge the iris to the output size.
shun_iwasawa a35b8f
  void convertIris(const float irisSize, kiss_fft_cpx *kissfft_comp_iris_before,
shun_iwasawa a35b8f
                   const TDimensionI &dimOut, const TRectD &irisBBox,
shun_iwasawa a35b8f
                   const TTile &irisTile);
shun_iwasawa a35b8f
shun_iwasawa a35b8f
  // Do FFT the alpha channel.
shun_iwasawa a35b8f
  // Forward FFT -> Multiply by the iris data -> Backward FFT
shun_iwasawa a35b8f
  void calcAlfaChannelBokeh(kiss_fft_cpx *kissfft_comp_iris, TTile &layerTile,
shun_iwasawa a35b8f
                            TRasterP tmpAlphaRas);
shun_iwasawa a35b8f
shun_iwasawa a35b8f
public:
shun_iwasawa a35b8f
  Iwa_BokehFx();
shun_iwasawa a35b8f
shun_iwasawa a35b8f
  void doCompute(TTile &tile, double frame, const TRenderSettings &settings);
shun_iwasawa a35b8f
shun_iwasawa a35b8f
  bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info);
shun_iwasawa a35b8f
shun_iwasawa a35b8f
  bool canHandle(const TRenderSettings &info, double frame);
shun_iwasawa a35b8f
};
shun_iwasawa a35b8f
shun_iwasawa a35b8f
#endif