tahoma2d/toonz/sources/stdfx/iwa_bokeh_util.h
2021-08-16 23:36:09 -04:00

267 lines
No EOL
8.6 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#ifndef IWA_BOKEH_UTIL_H
#define IWA_BOKEH_UTIL_H
#include "tgeometry.h"
#include "traster.h"
#include "kiss_fft.h"
#include "tools/kiss_fftnd.h"
#include "ttile.h"
#include "stdfx.h"
#include "tfxparam.h"
#include <QThread>
#include <QVector>
struct double4 {
double x, y, z, w;
};
struct double2 {
double x, y;
};
struct int2 {
int x, y;
};
namespace BokehUtils {
//------------------------------------
class MyThread : public QThread {
public:
enum Channel { Red = 0, Green, Blue };
private:
int m_channel;
volatile bool m_finished;
TRasterP m_layerTileRas;
double4* m_result;
double* m_alpha_bokeh;
kiss_fft_cpx* m_kissfft_comp_iris;
double m_layerHardness;
double m_masterHardness;
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, double4* result,
double* alpha_bokeh, kiss_fft_cpx* kissfft_comp_iris,
double layerHardness, double masterHardness = 0.0,
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);
void run();
bool isFinished() { return m_finished; }
//ƒƒƒŠŠm•Û
bool init();
void terminateThread() { m_isTerminated = true; }
bool checkTerminationAndCleanupThread();
};
//------------------------------------
class BokehRefThread : public QThread {
int m_channel;
volatile bool m_finished;
kiss_fft_cpx* m_fftcpx_channel_before;
kiss_fft_cpx* m_fftcpx_channel;
kiss_fft_cpx* m_fftcpx_alpha;
kiss_fft_cpx* m_fftcpx_iris;
double4* m_result_buff;
kiss_fftnd_cfg m_kissfft_plan_fwd, m_kissfft_plan_bkwd;
TDimensionI m_dim;
bool m_isTerminated;
public:
BokehRefThread(int channel, kiss_fft_cpx* fftcpx_channel_before,
kiss_fft_cpx* fftcpx_channel, kiss_fft_cpx* fftcpx_alpha,
kiss_fft_cpx* fftcpx_iris, double4* result_buff,
kiss_fftnd_cfg kissfft_plan_fwd,
kiss_fftnd_cfg kissfft_plan_bkwd, TDimensionI& dim);
void run() override;
bool isFinished() { return m_finished; }
void terminateThread() { m_isTerminated = true; }
};
//------------------------------------
// normalize the source raster image to 0-1 and set to dstMem
// returns true if the source is (seems to be) premultiplied
template <typename RASTER, typename PIXEL>
void setSourceRaster(const RASTER srcRas, double4* dstMem, TDimensionI dim);
// normalize brightness of the depth reference image to unsigned char
// and store into dstMem
template <typename RASTER, typename PIXEL>
void setDepthRaster(const RASTER srcRas, unsigned char* dstMem,
TDimensionI dim);
// create the depth index map
void defineSegemntDepth(
const unsigned char* indexMap_main, const unsigned char* indexMap_sub,
const double* mainSub_ratio, const unsigned char* depth_host,
const TDimensionI& dimOut, QVector<double>& segmentDepth_main,
QVector<double>& segmentDepth_sub, const double focusDepth,
int distancePrecision = 10, double nearDepth = 0.0, double farDepth = 1.0);
// convert source image value rgb -> exposure
void convertRGBToExposure(const double4* source_buff, int size,
double filmGamma);
// convert result image value exposure -> rgb
void convertExposureToRGB(const double4* result_buff, int size,
double filmGamma);
// obtain iris size from the depth value
double calcIrisSize(const double depth, const double bokehPixelAmount,
const double onFocusDistance,
const double bokehAdjustment = 1.0, double nearDepth = 0.0,
double farDepth = 1.0);
// generate the segment layer source at the current depth
// considering fillGap and doMedian options
void retrieveLayer(const double4* source_buff,
const double4* segment_layer_buff,
const unsigned char* indexMap_mainSub, int index, int lx,
int ly, bool fillGap = true, bool doMedian = false,
int margin = 0);
// normal-composite the layer as is, without filtering
void compositeAsIs(const double4* segment_layer_buff,
const double4* result_buff_mainSub, int size);
// 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 double irisSize, kiss_fft_cpx* kissfft_comp_iris_before,
const TDimensionI& dimOut, const TRectD& irisBBox,
const TTile& irisTile);
// retrieve segment layer image for each channel
void retrieveChannel(const double4* segment_layer_buff, // src
kiss_fft_cpx* fftcpx_r_before, // dst
kiss_fft_cpx* fftcpx_g_before, // dst
kiss_fft_cpx* fftcpx_b_before, // dst
kiss_fft_cpx* fftcpx_a_before, // dst
int size);
// multiply filter on channel
void multiplyFilter(kiss_fft_cpx* fftcpx_channel, // dst
kiss_fft_cpx* fftcpx_iris, // filter
int size);
// normal comosite the alpha channel
void compositeAlpha(const double4* result_buff, // dst
const kiss_fft_cpx* fftcpx_alpha, // alpha
int lx, int ly);
// interpolate main and sub exposures
// set to result
void interpolateExposureAndConvertToRGB(
const double4* result_main_buff, // result1
const double4* result_sub_buff, // result2
const double* mainSub_ratio, // ratio
const double4* result_buff, // dst
int size, double layerHardnessRatio = 1.0);
//"Over" composite the layer to the output exposure.
void compositLayerAsIs(TTile& layerTile, double4* result, TDimensionI& dimOut,
double filmGamma);
// Do FFT the alpha channel.
// Forward FFT -> Multiply by the iris data -> Backward FFT
void calcAlfaChannelBokeh(kiss_fft_cpx* kissfft_comp_iris, TTile& layerTile,
double* alpha_bokeh);
// convert to channel value and set to output
template <typename RASTER, typename PIXEL>
void setOutputRaster(double4* src, const RASTER dstRas, TDimensionI& dim,
int2 margin);
// Get the pixel size of bokehAmount ( referenced ino_blur.cpp )
double getBokehPixelAmount(const double bokehAmount, const TAffine affine);
} // namespace BokehUtils
//-----------------------------------------------------
class Iwa_BokehCommonFx : public TStandardRasterFx {
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 LayerValue {
TTile* sourceTile;
// set to false if the input image is already premultiplied.
// this parameter is now always false (assuming input images are always
// premultiplied). the value is left to keep backward compatibility
bool premultiply;
double layerHardness;
int depth_ref;
double irisSize;
double distance;
double bokehAdjustment;
double depthRange;
int distancePrecision;
bool fillGap;
bool doMedian;
};
void doFx(TTile& tile, double frame, const TRenderSettings& settings,
double bokehPixelAmount, int margin, TDimensionI& dimOut,
TRectD& irisBBox, TTile& irisTile, QList<LayerValue>& layerValues,
QMap<int, unsigned char*>& ctrls);
void doBokehRef(double4* result, double frame,
const TRenderSettings& settings, double bokehPixelAmount,
int margin, TDimensionI& dimOut, TRectD& irisBBox,
TTile& irisTile, kiss_fft_cpx* kissfft_comp_iris,
LayerValue layer, unsigned char* ctrl);
public:
Iwa_BokehCommonFx();
void doCompute(TTile& tile, double frame,
const TRenderSettings& settings) override = 0;
bool doGetBBox(double frame, TRectD& bBox,
const TRenderSettings& info) final override;
bool canHandle(const TRenderSettings& info, double frame) final override;
};
#endif