|
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
|