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