|
shun-iwasawa |
25dc51 |
#include "iwa_glarefx.h"
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
#include "trop.h"
|
|
shun-iwasawa |
25dc51 |
#include "tdoubleparam.h"
|
|
shun-iwasawa |
25dc51 |
#include "trasterfx.h"
|
|
shun-iwasawa |
25dc51 |
#include "trasterimage.h"
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
#include "tparamuiconcept.h"
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
#include "kiss_fft.h"
|
|
shun-iwasawa |
25dc51 |
#include "iwa_cie_d65.h"
|
|
shun-iwasawa |
25dc51 |
#include "iwa_xyz.h"
|
|
shun-iwasawa |
25dc51 |
#include "iwa_simplexnoise.h"
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
#include <qpair></qpair>
|
|
shun-iwasawa |
25dc51 |
#include <qvector></qvector>
|
|
shun-iwasawa |
25dc51 |
#include <qreadwritelock></qreadwritelock>
|
|
shun-iwasawa |
25dc51 |
#include <qmutexlocker></qmutexlocker>
|
|
shun-iwasawa |
25dc51 |
#include <qmap></qmap>
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
namespace {
|
|
shun-iwasawa |
25dc51 |
// FFT coordinate -> Normal corrdinate
|
|
shun-iwasawa |
25dc51 |
inline int getCoord(int i, int j, int lx, int ly) {
|
|
shun-iwasawa |
25dc51 |
int cx = i - lx / 2;
|
|
shun-iwasawa |
25dc51 |
int cy = j - ly / 2;
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
if (cx < 0) cx += lx;
|
|
shun-iwasawa |
25dc51 |
if (cy < 0) cy += ly;
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
return cy * lx + cx;
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
}; // namespace
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
//--------------------------------------------
|
|
shun-iwasawa |
25dc51 |
// Iwa_GlareFx
|
|
shun-iwasawa |
25dc51 |
//--------------------------------------------
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
Iwa_GlareFx::Iwa_GlareFx()
|
|
shun-iwasawa |
25dc51 |
: m_renderMode(new TIntEnumParam(RendeMode_FilterPreview, "Filter Preview"))
|
|
shun-iwasawa |
25dc51 |
, m_intensity(0.0)
|
|
shun-iwasawa |
25dc51 |
, m_size(100.0)
|
|
shun-iwasawa |
25dc51 |
, m_rotation(0.0)
|
|
shun-iwasawa |
25dc51 |
, m_noise_factor(0.0)
|
|
shun-iwasawa |
25dc51 |
, m_noise_size(0.5)
|
|
shun-iwasawa |
25dc51 |
, m_noise_octave(new TIntEnumParam(1, "1"))
|
|
shun-iwasawa |
25dc51 |
, m_noise_evolution(0.0)
|
|
shun-iwasawa |
25dc51 |
, m_noise_offset(TPointD(0, 0)) {
|
|
shun-iwasawa |
25dc51 |
// Bind the common parameters
|
|
shun-iwasawa |
25dc51 |
addInputPort("Source", m_source);
|
|
shun-iwasawa |
25dc51 |
addInputPort("Iris", m_iris);
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
bindParam(this, "renderMode", m_renderMode);
|
|
shun-iwasawa |
25dc51 |
m_renderMode->addItem(RendeMode_Render, "Render");
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
bindParam(this, "intensity", m_intensity, false);
|
|
shun-iwasawa |
25dc51 |
bindParam(this, "size", m_size, false);
|
|
shun-iwasawa |
25dc51 |
m_size->setMeasureName("fxLength");
|
|
shun-iwasawa |
25dc51 |
bindParam(this, "rotation", m_rotation, false);
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
bindParam(this, "noise_factor", m_noise_factor, false);
|
|
shun-iwasawa |
25dc51 |
bindParam(this, "noise_size", m_noise_size, false);
|
|
shun-iwasawa |
25dc51 |
bindParam(this, "noise_octave", m_noise_octave, false);
|
|
shun-iwasawa |
25dc51 |
m_noise_octave->addItem(2, "2");
|
|
shun-iwasawa |
25dc51 |
m_noise_octave->addItem(3, "3");
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
bindParam(this, "noise_evolution", m_noise_evolution, false);
|
|
shun-iwasawa |
25dc51 |
bindParam(this, "noise_offset", m_noise_offset, false);
|
|
shun-iwasawa |
25dc51 |
m_noise_offset->getX()->setMeasureName("fxLength");
|
|
shun-iwasawa |
25dc51 |
m_noise_offset->getY()->setMeasureName("fxLength");
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
m_intensity->setValueRange(-5.0, 5.0);
|
|
shun-iwasawa |
25dc51 |
m_size->setValueRange(10.0, 500.0);
|
|
shun-iwasawa |
25dc51 |
m_rotation->setValueRange(-1800, 1800);
|
|
shun-iwasawa |
25dc51 |
m_noise_factor->setValueRange(0.0, 1.0);
|
|
shun-iwasawa |
25dc51 |
m_noise_size->setValueRange(0.01, 3.0);
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
//--------------------------------------------------------------
|
|
shun-iwasawa |
25dc51 |
double Iwa_GlareFx::getSizePixelAmount(const double val, const TAffine affine) {
|
|
shun-iwasawa |
25dc51 |
/*--- Convert to vector --- */
|
|
shun-iwasawa |
25dc51 |
TPointD vect;
|
|
shun-iwasawa |
25dc51 |
vect.x = val;
|
|
shun-iwasawa |
25dc51 |
vect.y = 0.0;
|
|
shun-iwasawa |
25dc51 |
/*--- Apply geometrical transformation ---*/
|
|
shun-iwasawa |
25dc51 |
// For the following lines I referred to lines 586-592 of
|
|
shun-iwasawa |
25dc51 |
// sources/stdfx/motionblurfx.cpp
|
|
shun-iwasawa |
25dc51 |
TAffine aff(affine);
|
|
shun-iwasawa |
25dc51 |
aff.a13 = aff.a23 = 0; /* ignore translation */
|
|
shun-iwasawa |
25dc51 |
vect = aff * vect;
|
|
shun-iwasawa |
25dc51 |
/*--- return the length of the vector ---*/
|
|
shun-iwasawa |
25dc51 |
return sqrt(vect.x * vect.x + vect.y * vect.y);
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
//--------------------------------------------------------------
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
void Iwa_GlareFx::doCompute(TTile& tile, double frame,
|
|
shun-iwasawa |
25dc51 |
const TRenderSettings& settings) {
|
|
shun-iwasawa |
25dc51 |
// If the iris is not connected, then do nothing
|
|
shun-iwasawa |
25dc51 |
if (!m_iris.isConnected()) {
|
|
shun-iwasawa |
25dc51 |
tile.getRaster()->clear();
|
|
shun-iwasawa |
25dc51 |
return;
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
int renderMode = m_renderMode->getValue();
|
|
shun-iwasawa |
25dc51 |
// If the source is not connected & it is render mode, then do nothing.
|
|
shun-iwasawa |
25dc51 |
if (!m_source.isConnected() && renderMode == RendeMode_Render) {
|
|
shun-iwasawa |
25dc51 |
tile.getRaster()->clear();
|
|
shun-iwasawa |
25dc51 |
return;
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
// Get the original size of Iris image
|
|
shun-iwasawa |
25dc51 |
TRectD irisBBox;
|
|
shun-iwasawa |
25dc51 |
m_iris->getBBox(frame, irisBBox, settings);
|
|
shun-iwasawa |
25dc51 |
// Compute the iris tile.
|
|
shun-iwasawa |
25dc51 |
TTile irisTile;
|
|
shun-iwasawa |
25dc51 |
m_iris->allocateAndCompute(
|
|
shun-iwasawa |
25dc51 |
irisTile, irisBBox.getP00(),
|
|
shun-iwasawa |
25dc51 |
TDimension(static_cast<int>(irisBBox.getLx() + 0.5),</int>
|
|
shun-iwasawa |
25dc51 |
static_cast<int>(irisBBox.getLy() + 0.5)),</int>
|
|
shun-iwasawa |
25dc51 |
tile.getRaster(), frame, settings);
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
double size = getSizePixelAmount(m_size->getValue(frame), settings.m_affine);
|
|
shun-iwasawa |
25dc51 |
int dimIris = int(std::ceil(size) * 2.0);
|
|
shun-iwasawa |
25dc51 |
dimIris = kiss_fft_next_fast_size(dimIris);
|
|
shun-iwasawa |
25dc51 |
while ((tile.getRaster()->getSize().lx - dimIris) % 2 != 0)
|
|
shun-iwasawa |
25dc51 |
dimIris = kiss_fft_next_fast_size(dimIris + 1);
|
|
shun-iwasawa |
25dc51 |
double irisResizeFactor = double(dimIris) * 0.5 / size;
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
kiss_fft_cpx* kissfft_comp_iris;
|
|
shun-iwasawa |
25dc51 |
// create the iris data for FFT (in the same size as the source tile)
|
|
shun-iwasawa |
25dc51 |
TRasterGR8P kissfft_comp_iris_ras(dimIris * sizeof(kiss_fft_cpx), dimIris);
|
|
shun-iwasawa |
25dc51 |
kissfft_comp_iris_ras->lock();
|
|
shun-iwasawa |
25dc51 |
kissfft_comp_iris = (kiss_fft_cpx*)kissfft_comp_iris_ras->getRawData();
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
{
|
|
shun-iwasawa |
25dc51 |
// Create the Iris image for FFT
|
|
shun-iwasawa |
25dc51 |
kiss_fft_cpx* kissfft_comp_iris_before;
|
|
shun-iwasawa |
25dc51 |
TRasterGR8P kissfft_comp_iris_before_ras(dimIris * sizeof(kiss_fft_cpx),
|
|
shun-iwasawa |
25dc51 |
dimIris);
|
|
shun-iwasawa |
25dc51 |
kissfft_comp_iris_before_ras->lock();
|
|
shun-iwasawa |
25dc51 |
kissfft_comp_iris_before =
|
|
shun-iwasawa |
25dc51 |
(kiss_fft_cpx*)kissfft_comp_iris_before_ras->getRawData();
|
|
shun-iwasawa |
25dc51 |
convertIris(kissfft_comp_iris_before, dimIris, irisBBox, irisTile);
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
// Create the FFT plan for the iris image.
|
|
shun-iwasawa |
25dc51 |
kiss_fftnd_cfg iris_kissfft_plan;
|
|
shun-iwasawa |
25dc51 |
while (1) {
|
|
shun-iwasawa |
25dc51 |
int dims[2] = {dimIris, dimIris};
|
|
shun-iwasawa |
25dc51 |
int ndims = 2;
|
|
shun-iwasawa |
25dc51 |
iris_kissfft_plan = kiss_fftnd_alloc(dims, ndims, false, 0, 0);
|
|
shun-iwasawa |
25dc51 |
if (iris_kissfft_plan != NULL) break;
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
// Do FFT the iris image.
|
|
shun-iwasawa |
25dc51 |
kiss_fftnd(iris_kissfft_plan, kissfft_comp_iris_before, kissfft_comp_iris);
|
|
shun-iwasawa |
25dc51 |
kiss_fft_free(iris_kissfft_plan);
|
|
shun-iwasawa |
25dc51 |
kissfft_comp_iris_before_ras->unlock();
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
double3* glare_pattern;
|
|
shun-iwasawa |
25dc51 |
TRasterGR8P glare_pattern_ras(dimIris * sizeof(double3), dimIris);
|
|
shun-iwasawa |
25dc51 |
glare_pattern = (double3*)glare_pattern_ras->getRawData();
|
|
shun-iwasawa |
25dc51 |
glare_pattern_ras->lock();
|
|
shun-iwasawa |
25dc51 |
// Resize the power spectrum according to each wavelength and combine into the
|
|
shun-iwasawa |
25dc51 |
// glare pattern
|
|
shun-iwasawa |
25dc51 |
double intensity = m_intensity->getValue(frame);
|
|
shun-iwasawa |
25dc51 |
powerSpectrum2GlarePattern(frame, settings.m_affine, kissfft_comp_iris,
|
|
shun-iwasawa |
25dc51 |
glare_pattern, dimIris, intensity,
|
|
shun-iwasawa |
25dc51 |
irisResizeFactor);
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
kissfft_comp_iris_ras->unlock();
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
// clear the raster memory
|
|
shun-iwasawa |
25dc51 |
tile.getRaster()->clear();
|
|
shun-iwasawa |
25dc51 |
TRaster32P ras32 = tile.getRaster();
|
|
shun-iwasawa |
25dc51 |
TRaster64P ras64 = tile.getRaster();
|
|
shun-iwasawa |
25dc51 |
if (ras32)
|
|
shun-iwasawa |
25dc51 |
ras32->fill(TPixel32::Transparent);
|
|
shun-iwasawa |
25dc51 |
else if (ras64)
|
|
shun-iwasawa |
25dc51 |
ras64->fill(TPixel64::Transparent);
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
// filter preview mode
|
|
shun-iwasawa |
25dc51 |
if (renderMode == RendeMode_FilterPreview) {
|
|
shun-iwasawa |
25dc51 |
int2 margin = {(dimIris - tile.getRaster()->getSize().lx) / 2,
|
|
shun-iwasawa |
25dc51 |
(dimIris - tile.getRaster()->getSize().ly) / 2};
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
if (ras32)
|
|
shun-iwasawa |
25dc51 |
setFilterPreviewToResult<traster32p, tpixel32="">(ras32, glare_pattern,</traster32p,>
|
|
shun-iwasawa |
25dc51 |
dimIris, margin);
|
|
shun-iwasawa |
25dc51 |
else if (ras64)
|
|
shun-iwasawa |
25dc51 |
setFilterPreviewToResult<traster64p, tpixel64="">(ras64, glare_pattern,</traster64p,>
|
|
shun-iwasawa |
25dc51 |
dimIris, margin);
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
return;
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
// render mode
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
// Range of computation
|
|
shun-iwasawa |
25dc51 |
TRectD _rectOut(tile.m_pos, TDimensionD(tile.getRaster()->getLx(),
|
|
shun-iwasawa |
25dc51 |
tile.getRaster()->getLy()));
|
|
shun-iwasawa |
25dc51 |
_rectOut = _rectOut.enlarge(static_cast<double>(dimIris / 2));</double>
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
TDimensionI dimOut(static_cast<int>(_rectOut.getLx() + 0.5),</int>
|
|
shun-iwasawa |
25dc51 |
static_cast<int>(_rectOut.getLy() + 0.5));</int>
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
// Enlarge the size to the "fast size" for kissfft which has no factors other
|
|
shun-iwasawa |
25dc51 |
// than 2,3, or 5.
|
|
shun-iwasawa |
25dc51 |
if (dimOut.lx < 10000 && dimOut.ly < 10000) {
|
|
shun-iwasawa |
25dc51 |
int new_x = kiss_fft_next_fast_size(dimOut.lx);
|
|
shun-iwasawa |
25dc51 |
int new_y = kiss_fft_next_fast_size(dimOut.ly);
|
|
shun-iwasawa |
25dc51 |
// margin should be integer
|
|
shun-iwasawa |
25dc51 |
while ((new_x - dimOut.lx) % 2 != 0)
|
|
shun-iwasawa |
25dc51 |
new_x = kiss_fft_next_fast_size(new_x + 1);
|
|
shun-iwasawa |
25dc51 |
while ((new_y - dimOut.ly) % 2 != 0)
|
|
shun-iwasawa |
25dc51 |
new_y = kiss_fft_next_fast_size(new_y + 1);
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
_rectOut = _rectOut.enlarge(static_cast<double>(new_x - dimOut.lx) / 2.0,</double>
|
|
shun-iwasawa |
25dc51 |
static_cast<double>(new_y - dimOut.ly) / 2.0);</double>
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
dimOut.lx = new_x;
|
|
shun-iwasawa |
25dc51 |
dimOut.ly = new_y;
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
kiss_fft_cpx* kissfft_comp_tmp;
|
|
shun-iwasawa |
25dc51 |
kiss_fft_cpx* kissfft_comp_glare;
|
|
shun-iwasawa |
25dc51 |
kiss_fft_cpx* kissfft_comp_source;
|
|
shun-iwasawa |
25dc51 |
TRasterGR8P kissfft_comp_tmp_ras(dimOut.lx * sizeof(kiss_fft_cpx), dimOut.ly);
|
|
shun-iwasawa |
25dc51 |
TRasterGR8P kissfft_comp_glare_ras(dimOut.lx * sizeof(kiss_fft_cpx),
|
|
shun-iwasawa |
25dc51 |
dimOut.ly);
|
|
shun-iwasawa |
25dc51 |
TRasterGR8P kissfft_comp_source_ras(dimOut.lx * sizeof(kiss_fft_cpx),
|
|
shun-iwasawa |
25dc51 |
dimOut.ly);
|
|
shun-iwasawa |
25dc51 |
kissfft_comp_tmp = (kiss_fft_cpx*)kissfft_comp_tmp_ras->getRawData();
|
|
shun-iwasawa |
25dc51 |
kissfft_comp_glare = (kiss_fft_cpx*)kissfft_comp_glare_ras->getRawData();
|
|
shun-iwasawa |
25dc51 |
kissfft_comp_source = (kiss_fft_cpx*)kissfft_comp_source_ras->getRawData();
|
|
shun-iwasawa |
25dc51 |
kissfft_comp_tmp_ras->lock();
|
|
shun-iwasawa |
25dc51 |
kissfft_comp_glare_ras->lock();
|
|
shun-iwasawa |
25dc51 |
kissfft_comp_source_ras->lock();
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
int dims[2] = {dimOut.ly, dimOut.lx};
|
|
shun-iwasawa |
25dc51 |
int ndims = 2;
|
|
shun-iwasawa |
25dc51 |
kiss_fftnd_cfg plan_fwd = kiss_fftnd_alloc(dims, ndims, false, 0, 0);
|
|
shun-iwasawa |
25dc51 |
kiss_fftnd_cfg plan_bkwd = kiss_fftnd_alloc(dims, ndims, true, 0, 0);
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
// store the source image to tmp
|
|
shun-iwasawa |
25dc51 |
{
|
|
shun-iwasawa |
25dc51 |
// obtain the source tile
|
|
shun-iwasawa |
25dc51 |
TTile sourceTile;
|
|
shun-iwasawa |
25dc51 |
m_source->allocateAndCompute(sourceTile, _rectOut.getP00(), dimOut,
|
|
shun-iwasawa |
25dc51 |
tile.getRaster(), frame, settings);
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
if (ras32)
|
|
shun-iwasawa |
25dc51 |
setSourceTileToBuffer<traster32p, tpixel32="">(sourceTile.getRaster(),</traster32p,>
|
|
shun-iwasawa |
25dc51 |
kissfft_comp_tmp);
|
|
shun-iwasawa |
25dc51 |
else if (ras64)
|
|
shun-iwasawa |
25dc51 |
setSourceTileToBuffer<traster64p, tpixel64="">(sourceTile.getRaster(),</traster64p,>
|
|
shun-iwasawa |
25dc51 |
kissfft_comp_tmp);
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
// FFT the source
|
|
shun-iwasawa |
25dc51 |
kiss_fftnd(plan_fwd, kissfft_comp_tmp, kissfft_comp_source);
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
// compute for each rgb channels
|
|
shun-iwasawa |
25dc51 |
for (int ch = 0; ch < 3; ch++) {
|
|
shun-iwasawa |
25dc51 |
kissfft_comp_tmp_ras->clear();
|
|
shun-iwasawa |
25dc51 |
// store the glare pattern to tmp
|
|
shun-iwasawa |
25dc51 |
setGlarePatternToBuffer(glare_pattern, kissfft_comp_tmp, ch, dimIris,
|
|
shun-iwasawa |
25dc51 |
dimOut);
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
// FFT the glare pattern
|
|
shun-iwasawa |
25dc51 |
kiss_fftnd(plan_fwd, kissfft_comp_tmp, kissfft_comp_glare);
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
// multiply the glare and the source
|
|
shun-iwasawa |
25dc51 |
multiplyFilter(kissfft_comp_glare, kissfft_comp_source,
|
|
shun-iwasawa |
25dc51 |
dimOut.lx * dimOut.ly);
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
// Backward-FFT the glare pattern to tmp
|
|
shun-iwasawa |
25dc51 |
kiss_fftnd(plan_bkwd, kissfft_comp_glare,
|
|
shun-iwasawa |
25dc51 |
kissfft_comp_tmp); // Backward FFT
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
// convert tmp to channel values, store it into the tile
|
|
shun-iwasawa |
25dc51 |
if (ras32)
|
|
shun-iwasawa |
25dc51 |
setChannelToResult<traster32p, tpixel32="">(ras32, kissfft_comp_tmp, ch,</traster32p,>
|
|
shun-iwasawa |
25dc51 |
dimOut);
|
|
shun-iwasawa |
25dc51 |
else if (ras64)
|
|
shun-iwasawa |
25dc51 |
setChannelToResult<traster64p, tpixel64="">(ras64, kissfft_comp_tmp, ch,</traster64p,>
|
|
shun-iwasawa |
25dc51 |
dimOut);
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
kiss_fft_free(plan_fwd);
|
|
shun-iwasawa |
25dc51 |
kiss_fft_free(plan_bkwd);
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
kissfft_comp_source_ras->unlock();
|
|
shun-iwasawa |
25dc51 |
kissfft_comp_glare_ras->unlock();
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
//------------------------------------------------
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
void Iwa_GlareFx::powerSpectrum2GlarePattern(
|
|
shun-iwasawa |
25dc51 |
const double frame, const TAffine affine, kiss_fft_cpx* spectrum,
|
|
shun-iwasawa |
25dc51 |
double3* glare, int dimIris, double intensity, double irisResizeFactor) {
|
|
shun-iwasawa |
25dc51 |
auto lerp = [](double val1, double val2, double ratio) {
|
|
shun-iwasawa |
25dc51 |
return val1 * (1.0 - ratio) + val2 * ratio;
|
|
shun-iwasawa |
25dc51 |
};
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
auto lerpGlarePtn = [&](double i, double j, double* gp) {
|
|
shun-iwasawa |
25dc51 |
int iId[2], jId[2];
|
|
shun-iwasawa |
25dc51 |
double iRatio, jRatio;
|
|
shun-iwasawa |
25dc51 |
iId[0] = int(i);
|
|
shun-iwasawa |
25dc51 |
iId[1] = (iId[0] < dimIris - 1) ? iId[0] + 1 : iId[0];
|
|
shun-iwasawa |
25dc51 |
iRatio = i - double(iId[0]);
|
|
shun-iwasawa |
25dc51 |
jId[0] = int(j);
|
|
shun-iwasawa |
25dc51 |
jId[1] = (jId[0] < dimIris - 1) ? jId[0] + 1 : jId[0];
|
|
shun-iwasawa |
25dc51 |
jRatio = j - double(jId[0]);
|
|
shun-iwasawa |
25dc51 |
if (iRatio == 0.0 && jRatio == 0.0) return gp[jId[0] * dimIris + iId[0]];
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
return lerp(lerp(gp[jId[0] * dimIris + iId[0]],
|
|
shun-iwasawa |
25dc51 |
gp[jId[0] * dimIris + iId[1]], iRatio),
|
|
shun-iwasawa |
25dc51 |
lerp(gp[jId[1] * dimIris + iId[0]],
|
|
shun-iwasawa |
25dc51 |
gp[jId[1] * dimIris + iId[1]], iRatio),
|
|
shun-iwasawa |
25dc51 |
jRatio);
|
|
shun-iwasawa |
25dc51 |
};
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
double factor =
|
|
shun-iwasawa |
25dc51 |
(m_renderMode->getValue() == RendeMode_FilterPreview) ? -5 : -11;
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
double* glarePattern_p;
|
|
shun-iwasawa |
25dc51 |
TRasterGR8P glarePattern_ras(dimIris * sizeof(double), dimIris);
|
|
shun-iwasawa |
25dc51 |
glarePattern_p = (double*)glarePattern_ras->getRawData();
|
|
shun-iwasawa |
25dc51 |
glarePattern_ras->lock();
|
|
shun-iwasawa |
25dc51 |
double* g_p = glarePattern_p;
|
|
shun-iwasawa |
25dc51 |
for (int j = 0; j < dimIris; j++) {
|
|
shun-iwasawa |
25dc51 |
for (int i = 0; i < dimIris; i++, g_p++) {
|
|
shun-iwasawa |
25dc51 |
kiss_fft_cpx sp_p = spectrum[getCoord(i, j, dimIris, dimIris)];
|
|
shun-iwasawa |
25dc51 |
(*g_p) = sqrt(sp_p.r * sp_p.r + sp_p.i * sp_p.i) *
|
|
shun-iwasawa |
25dc51 |
std::exp(intensity + factor);
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
// distort the pattern with noise here
|
|
shun-iwasawa |
25dc51 |
double noise_factor = m_noise_factor->getValue(frame);
|
|
shun-iwasawa |
25dc51 |
double rotation = m_rotation->getValue(frame);
|
|
shun-iwasawa |
25dc51 |
if (noise_factor > 0.0 || m_rotation != 0.0) {
|
|
shun-iwasawa |
25dc51 |
distortGlarePattern(frame, affine, glarePattern_p, dimIris);
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
double3* glare_xyz;
|
|
shun-iwasawa |
25dc51 |
TRasterGR8P glare_xyz_ras(dimIris * sizeof(double3), dimIris);
|
|
shun-iwasawa |
25dc51 |
glare_xyz_ras->lock();
|
|
shun-iwasawa |
25dc51 |
glare_xyz = (double3*)glare_xyz_ras->getRawData();
|
|
shun-iwasawa |
25dc51 |
glare_xyz_ras->clear();
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
double irisRadius = double(dimIris / 2);
|
|
shun-iwasawa |
25dc51 |
// accumurate xyz values for each optical wavelength
|
|
shun-iwasawa |
25dc51 |
for (int ram = 0; ram < 34; ram++) {
|
|
shun-iwasawa |
25dc51 |
double rambda = 0.38 + 0.01 * (double)ram;
|
|
shun-iwasawa |
25dc51 |
double scale = 0.55 / rambda;
|
|
shun-iwasawa |
25dc51 |
scale *= irisResizeFactor;
|
|
shun-iwasawa |
25dc51 |
for (int j = 0; j < dimIris; j++) {
|
|
shun-iwasawa |
25dc51 |
double j_scaled = (double(j) - irisRadius) * scale + irisRadius;
|
|
shun-iwasawa |
25dc51 |
if (j_scaled < 0)
|
|
shun-iwasawa |
25dc51 |
continue;
|
|
shun-iwasawa |
25dc51 |
else if (j_scaled > double(dimIris - 1))
|
|
shun-iwasawa |
25dc51 |
break;
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
double3* g_xyz_p = &glare_xyz[j * dimIris];
|
|
shun-iwasawa |
25dc51 |
for (int i = 0; i < dimIris; i++, g_xyz_p++) {
|
|
shun-iwasawa |
25dc51 |
double i_scaled = (double(i) - irisRadius) * scale + irisRadius;
|
|
shun-iwasawa |
25dc51 |
if (i_scaled < 0)
|
|
shun-iwasawa |
25dc51 |
continue;
|
|
shun-iwasawa |
25dc51 |
else if (i_scaled > double(dimIris - 1))
|
|
shun-iwasawa |
25dc51 |
break;
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
double gl = lerpGlarePtn(i_scaled, j_scaled, glarePattern_p);
|
|
shun-iwasawa |
25dc51 |
g_xyz_p->x += gl * cie_d65[ram] * xyz[ram * 3 + 0];
|
|
shun-iwasawa |
25dc51 |
g_xyz_p->y += gl * cie_d65[ram] * xyz[ram * 3 + 1];
|
|
shun-iwasawa |
25dc51 |
g_xyz_p->z += gl * cie_d65[ram] * xyz[ram * 3 + 2];
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
glarePattern_ras->unlock();
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
// convert to rgb
|
|
shun-iwasawa |
25dc51 |
double3* g_xyz_p = glare_xyz;
|
|
shun-iwasawa |
25dc51 |
double3* g_out_p = glare;
|
|
shun-iwasawa |
25dc51 |
for (int i = 0; i < dimIris * dimIris; i++, g_xyz_p++, g_out_p++) {
|
|
shun-iwasawa |
25dc51 |
(*g_out_p).x = 3.240479f * (*g_xyz_p).x - 1.537150f * (*g_xyz_p).y -
|
|
shun-iwasawa |
25dc51 |
0.498535f * (*g_xyz_p).z;
|
|
shun-iwasawa |
25dc51 |
(*g_out_p).y = -0.969256f * (*g_xyz_p).x + 1.875992f * (*g_xyz_p).y +
|
|
shun-iwasawa |
25dc51 |
0.041556f * (*g_xyz_p).z;
|
|
shun-iwasawa |
25dc51 |
(*g_out_p).z = 0.055648f * (*g_xyz_p).x - 0.204043f * (*g_xyz_p).y +
|
|
shun-iwasawa |
25dc51 |
1.057311f * (*g_xyz_p).z;
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
glare_xyz_ras->unlock();
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
//------------------------------------------------
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
void Iwa_GlareFx::distortGlarePattern(const double frame, const TAffine affine,
|
|
shun-iwasawa |
25dc51 |
double* glare, const int dimIris) {
|
|
shun-iwasawa |
25dc51 |
auto lerp = [](double val1, double val2, double ratio) {
|
|
shun-iwasawa |
25dc51 |
return val1 * (1.0 - ratio) + val2 * ratio;
|
|
shun-iwasawa |
25dc51 |
};
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
auto lerpGlarePtn = [&](double i, double j, double* gp) {
|
|
shun-iwasawa |
25dc51 |
int iId[2], jId[2];
|
|
shun-iwasawa |
25dc51 |
double iRatio, jRatio;
|
|
shun-iwasawa |
25dc51 |
iId[0] = int(i);
|
|
shun-iwasawa |
25dc51 |
iId[1] = (iId[0] < dimIris - 1) ? iId[0] + 1 : iId[0];
|
|
shun-iwasawa |
25dc51 |
iRatio = i - double(iId[0]);
|
|
shun-iwasawa |
25dc51 |
jId[0] = int(j);
|
|
shun-iwasawa |
25dc51 |
jId[1] = (jId[0] < dimIris - 1) ? jId[0] + 1 : jId[0];
|
|
shun-iwasawa |
25dc51 |
jRatio = j - double(jId[0]);
|
|
shun-iwasawa |
25dc51 |
if (iRatio == 0.0 && jRatio == 0.0) return gp[jId[0] * dimIris + iId[0]];
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
return lerp(lerp(gp[jId[0] * dimIris + iId[0]],
|
|
shun-iwasawa |
25dc51 |
gp[jId[0] * dimIris + iId[1]], iRatio),
|
|
shun-iwasawa |
25dc51 |
lerp(gp[jId[1] * dimIris + iId[0]],
|
|
shun-iwasawa |
25dc51 |
gp[jId[1] * dimIris + iId[1]], iRatio),
|
|
shun-iwasawa |
25dc51 |
jRatio);
|
|
shun-iwasawa |
25dc51 |
};
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
double size = m_noise_size->getValue(frame);
|
|
shun-iwasawa |
25dc51 |
double evolution = m_noise_evolution->getValue(frame);
|
|
shun-iwasawa |
25dc51 |
int octave = m_noise_octave->getValue();
|
|
shun-iwasawa |
25dc51 |
double noiseFactor = m_noise_factor->getValue(frame);
|
|
shun-iwasawa |
25dc51 |
double offsetFactor = 0.005;
|
|
shun-iwasawa |
25dc51 |
TPointD offset =
|
|
shun-iwasawa |
25dc51 |
TScale(offsetFactor) * affine * m_noise_offset->getValue(frame);
|
|
shun-iwasawa |
25dc51 |
double theta = m_rotation->getValue(frame) * M_PI_180;
|
|
shun-iwasawa |
25dc51 |
double cos_t = std::cos(theta);
|
|
shun-iwasawa |
25dc51 |
double sin_t = std::sin(theta);
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
QList<double> noise_intensity;</double>
|
|
shun-iwasawa |
25dc51 |
double intensity_sum = 0.0;
|
|
shun-iwasawa |
25dc51 |
double tmp_intensity = 1.0;
|
|
shun-iwasawa |
25dc51 |
for (int i = 0; i < octave; i++) {
|
|
shun-iwasawa |
25dc51 |
noise_intensity.append(tmp_intensity);
|
|
shun-iwasawa |
25dc51 |
intensity_sum += tmp_intensity;
|
|
shun-iwasawa |
25dc51 |
tmp_intensity *= 0.5;
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
for (double& n_i : noise_intensity) n_i /= intensity_sum;
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
// raster for storing the result
|
|
shun-iwasawa |
25dc51 |
double* distortedPtn_p;
|
|
shun-iwasawa |
25dc51 |
TRasterGR8P distortedPtn_ras(dimIris * sizeof(double), dimIris);
|
|
shun-iwasawa |
25dc51 |
distortedPtn_p = (double*)distortedPtn_ras->getRawData();
|
|
shun-iwasawa |
25dc51 |
distortedPtn_ras->lock();
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
double* dist_p = distortedPtn_p;
|
|
shun-iwasawa |
25dc51 |
for (int j = 0; j < dimIris; j++) {
|
|
shun-iwasawa |
25dc51 |
double v = double(j) - double(dimIris) / 2.0;
|
|
shun-iwasawa |
25dc51 |
for (int i = 0; i < dimIris; i++, dist_p++) {
|
|
shun-iwasawa |
25dc51 |
double u = double(i) - double(dimIris) / 2.0;
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
// obtain the noise coordinate
|
|
shun-iwasawa |
25dc51 |
double2 noiseUV;
|
|
shun-iwasawa |
25dc51 |
double len = std::sqrt(u * u + v * v) * size;
|
|
shun-iwasawa |
25dc51 |
noiseUV.x = (len == 0.0) ? 0.0 : u / len;
|
|
shun-iwasawa |
25dc51 |
noiseUV.y = (len == 0.0) ? 0.0 : v / len;
|
|
shun-iwasawa |
25dc51 |
double currentSize = 1.0;
|
|
shun-iwasawa |
25dc51 |
double currentEvoScale = 1.0;
|
|
shun-iwasawa |
25dc51 |
double noiseVal = 0.5;
|
|
shun-iwasawa |
25dc51 |
noiseUV.x += offset.x;
|
|
shun-iwasawa |
25dc51 |
noiseUV.y += offset.y;
|
|
shun-iwasawa |
25dc51 |
for (int oct = 0; oct < octave; oct++) {
|
|
shun-iwasawa |
25dc51 |
double2 currentNoiseUV = {noiseUV.x / currentSize,
|
|
shun-iwasawa |
25dc51 |
noiseUV.y / currentSize};
|
|
shun-iwasawa |
25dc51 |
noiseVal += noise_intensity[oct] *
|
|
shun-iwasawa |
25dc51 |
SimplexNoise::noise(currentNoiseUV.x, currentNoiseUV.y,
|
|
shun-iwasawa |
25dc51 |
evolution * currentEvoScale);
|
|
shun-iwasawa |
25dc51 |
currentSize *= 0.5;
|
|
shun-iwasawa |
25dc51 |
currentEvoScale *= 2.0;
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
double scale = 1.0 / (1.0 + (noiseVal - 1) * noiseFactor);
|
|
shun-iwasawa |
25dc51 |
double rot_u = u * cos_t - v * sin_t;
|
|
shun-iwasawa |
25dc51 |
double rot_v = u * sin_t + v * cos_t;
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
double distorted_i = rot_u * scale + double(dimIris) / 2.0;
|
|
shun-iwasawa |
25dc51 |
double distorted_j = rot_v * scale + double(dimIris) / 2.0;
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
if (distorted_i < 0.0 || distorted_i >= double(dimIris - 1) ||
|
|
shun-iwasawa |
25dc51 |
distorted_j < 0.0 || distorted_j >= double(dimIris - 1))
|
|
shun-iwasawa |
25dc51 |
(*dist_p) = 0.0;
|
|
shun-iwasawa |
25dc51 |
else
|
|
shun-iwasawa |
25dc51 |
(*dist_p) = lerpGlarePtn(distorted_i, distorted_j, glare);
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
dist_p = distortedPtn_p;
|
|
shun-iwasawa |
25dc51 |
double* gl_p = glare;
|
|
shun-iwasawa |
25dc51 |
for (int i = 0; i < dimIris * dimIris; i++, dist_p++, gl_p++)
|
|
shun-iwasawa |
25dc51 |
(*gl_p) = (*dist_p);
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
distortedPtn_ras->unlock();
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
//------------------------------------------------
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
template <typename pixel="" raster,="" typename=""></typename>
|
|
shun-iwasawa |
25dc51 |
void Iwa_GlareFx::setFilterPreviewToResult(const RASTER ras, double3* glare,
|
|
shun-iwasawa |
25dc51 |
int dimIris, int2 margin) {
|
|
shun-iwasawa |
25dc51 |
auto clamp01 = [](double chan) {
|
|
shun-iwasawa |
25dc51 |
if (chan < 0.0) return 0.0;
|
|
shun-iwasawa |
25dc51 |
if (chan > 1.0) return 1.0;
|
|
shun-iwasawa |
25dc51 |
return chan;
|
|
shun-iwasawa |
25dc51 |
};
|
|
shun-iwasawa |
25dc51 |
int j = margin.y;
|
|
shun-iwasawa |
25dc51 |
for (int out_j = 0; out_j < ras->getLy(); j++, out_j++) {
|
|
shun-iwasawa |
25dc51 |
if (j < 0)
|
|
shun-iwasawa |
25dc51 |
continue;
|
|
shun-iwasawa |
25dc51 |
else if (j >= dimIris)
|
|
shun-iwasawa |
25dc51 |
break;
|
|
shun-iwasawa |
25dc51 |
PIXEL* pix = ras->pixels(out_j);
|
|
shun-iwasawa |
25dc51 |
int i = margin.x;
|
|
shun-iwasawa |
25dc51 |
for (int out_i = 0; out_i < ras->getLx(); i++, out_i++, pix++) {
|
|
shun-iwasawa |
25dc51 |
if (i < 0)
|
|
shun-iwasawa |
25dc51 |
continue;
|
|
shun-iwasawa |
25dc51 |
else if (i >= dimIris)
|
|
shun-iwasawa |
25dc51 |
break;
|
|
shun-iwasawa |
25dc51 |
double3 gl_p = glare[j * dimIris + i];
|
|
shun-iwasawa |
25dc51 |
pix->r = (typename PIXEL::Channel)(clamp01(gl_p.x) *
|
|
shun-iwasawa |
25dc51 |
double(PIXEL::maxChannelValue));
|
|
shun-iwasawa |
25dc51 |
pix->g = (typename PIXEL::Channel)(clamp01(gl_p.y) *
|
|
shun-iwasawa |
25dc51 |
double(PIXEL::maxChannelValue));
|
|
shun-iwasawa |
25dc51 |
pix->b = (typename PIXEL::Channel)(clamp01(gl_p.z) *
|
|
shun-iwasawa |
25dc51 |
double(PIXEL::maxChannelValue));
|
|
shun-iwasawa |
25dc51 |
pix->m = PIXEL::maxChannelValue;
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
//------------------------------------------------
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
// put the source tile's brightness to fft buffer
|
|
shun-iwasawa |
25dc51 |
template <typename pixel="" raster,="" typename=""></typename>
|
|
shun-iwasawa |
25dc51 |
void Iwa_GlareFx::setSourceTileToBuffer(const RASTER ras, kiss_fft_cpx* buf) {
|
|
shun-iwasawa |
25dc51 |
kiss_fft_cpx* buf_p = buf;
|
|
shun-iwasawa |
25dc51 |
for (int j = 0; j < ras->getLy(); j++) {
|
|
shun-iwasawa |
25dc51 |
PIXEL* pix = ras->pixels(j);
|
|
shun-iwasawa |
25dc51 |
for (int i = 0; i < ras->getLx(); i++, pix++, buf_p++) {
|
|
shun-iwasawa |
25dc51 |
// Value = 0.3R 0.59G 0.11B
|
|
shun-iwasawa |
25dc51 |
(*buf_p).r = (double(pix->r) * 0.3 + double(pix->g) * 0.59 +
|
|
shun-iwasawa |
25dc51 |
double(pix->b) * 0.11) /
|
|
shun-iwasawa |
25dc51 |
double(PIXEL::maxChannelValue);
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
//------------------------------------------------
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
void Iwa_GlareFx::setGlarePatternToBuffer(const double3* glare,
|
|
shun-iwasawa |
25dc51 |
kiss_fft_cpx* buf, const int channel,
|
|
shun-iwasawa |
25dc51 |
const int dimIris,
|
|
shun-iwasawa |
25dc51 |
const TDimensionI& dimOut) {
|
|
shun-iwasawa |
25dc51 |
int margin_x = (dimOut.lx - dimIris) / 2;
|
|
shun-iwasawa |
25dc51 |
int margin_y = (dimOut.ly - dimIris) / 2;
|
|
shun-iwasawa |
25dc51 |
for (int j = margin_y; j < margin_y + dimIris; j++) {
|
|
shun-iwasawa |
25dc51 |
const double3* glare_p = &glare[(j - margin_y) * dimIris];
|
|
shun-iwasawa |
25dc51 |
kiss_fft_cpx* buf_p = &buf[j * dimOut.lx + margin_x];
|
|
shun-iwasawa |
25dc51 |
for (int i = margin_x; i < margin_x + dimIris; i++, buf_p++, glare_p++) {
|
|
shun-iwasawa |
25dc51 |
(*buf_p).r = (channel == 0)
|
|
shun-iwasawa |
25dc51 |
? (*glare_p).x
|
|
shun-iwasawa |
25dc51 |
: (channel == 1) ? (*glare_p).y : (*glare_p).z;
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
//------------------------------------------------
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
void Iwa_GlareFx::multiplyFilter(kiss_fft_cpx* glare,
|
|
shun-iwasawa |
25dc51 |
const kiss_fft_cpx* source, const int count) {
|
|
shun-iwasawa |
25dc51 |
kiss_fft_cpx* g_p = glare;
|
|
shun-iwasawa |
25dc51 |
const kiss_fft_cpx* s_p = source;
|
|
shun-iwasawa |
25dc51 |
for (int i = 0; i < count; i++, g_p++, s_p++) {
|
|
shun-iwasawa |
25dc51 |
double re = (*g_p).r * (*s_p).r - (*g_p).i * (*s_p).i;
|
|
shun-iwasawa |
25dc51 |
double im = (*g_p).r * (*s_p).i + (*s_p).r * (*g_p).i;
|
|
shun-iwasawa |
25dc51 |
(*g_p).r = re;
|
|
shun-iwasawa |
25dc51 |
(*g_p).i = im;
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
//------------------------------------------------
|
|
shun-iwasawa |
25dc51 |
template <typename pixel="" raster,="" typename=""></typename>
|
|
shun-iwasawa |
25dc51 |
void Iwa_GlareFx::setChannelToResult(const RASTER ras, kiss_fft_cpx* buf,
|
|
shun-iwasawa |
25dc51 |
int channel, const TDimensionI& dimOut) {
|
|
shun-iwasawa |
25dc51 |
auto clamp01 = [](double chan) {
|
|
shun-iwasawa |
25dc51 |
if (chan < 0.0) return 0.0;
|
|
shun-iwasawa |
25dc51 |
if (chan > 1.0) return 1.0;
|
|
shun-iwasawa |
25dc51 |
return chan;
|
|
shun-iwasawa |
25dc51 |
};
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
int margin_x = (dimOut.lx - ras->getSize().lx) / 2;
|
|
shun-iwasawa |
25dc51 |
int margin_y = (dimOut.ly - ras->getSize().ly) / 2;
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
for (int j = 0; j < ras->getLy(); j++) {
|
|
shun-iwasawa |
25dc51 |
// kiss_fft_cpx* buf_p = &buf[(j + margin_y)*dimOut.lx + margin_x];
|
|
shun-iwasawa |
25dc51 |
PIXEL* pix = ras->pixels(j);
|
|
shun-iwasawa |
25dc51 |
for (int i = 0; i < ras->getLx(); i++, pix++) {
|
|
shun-iwasawa |
25dc51 |
kiss_fft_cpx fft_val =
|
|
shun-iwasawa |
25dc51 |
buf[getCoord(i + margin_x, j + margin_y, dimOut.lx, dimOut.ly)];
|
|
shun-iwasawa |
25dc51 |
double val = fft_val.r / (dimOut.lx * dimOut.ly);
|
|
shun-iwasawa |
25dc51 |
if (channel == 0)
|
|
shun-iwasawa |
25dc51 |
pix->r = (typename PIXEL::Channel)(clamp01(val) *
|
|
shun-iwasawa |
25dc51 |
double(PIXEL::maxChannelValue));
|
|
shun-iwasawa |
25dc51 |
else if (channel == 1)
|
|
shun-iwasawa |
25dc51 |
pix->g = (typename PIXEL::Channel)(clamp01(val) *
|
|
shun-iwasawa |
25dc51 |
double(PIXEL::maxChannelValue));
|
|
shun-iwasawa |
25dc51 |
else if (channel == 2) {
|
|
shun-iwasawa |
25dc51 |
pix->b = (typename PIXEL::Channel)(clamp01(val) *
|
|
shun-iwasawa |
25dc51 |
double(PIXEL::maxChannelValue));
|
|
shun-iwasawa |
25dc51 |
pix->m = PIXEL::maxChannelValue;
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
//------------------------------------------------
|
|
shun-iwasawa |
25dc51 |
bool Iwa_GlareFx::doGetBBox(double frame, TRectD& bBox,
|
|
shun-iwasawa |
25dc51 |
const TRenderSettings& info) {
|
|
shun-iwasawa |
25dc51 |
bBox = TConsts::infiniteRectD;
|
|
shun-iwasawa |
25dc51 |
return true;
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
//------------------------------------------------
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
bool Iwa_GlareFx::canHandle(const TRenderSettings& info, double frame) {
|
|
shun-iwasawa |
25dc51 |
return false;
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
//------------------------------------------------
|
|
shun-iwasawa |
25dc51 |
// Resize / flip the iris image according to the size ratio.
|
|
shun-iwasawa |
25dc51 |
// Normalize the brightness of the iris image.
|
|
shun-iwasawa |
25dc51 |
// Enlarge the iris to the output size.
|
|
shun-iwasawa |
25dc51 |
void Iwa_GlareFx::convertIris(kiss_fft_cpx* kissfft_comp_iris_before,
|
|
shun-iwasawa |
25dc51 |
const int& dimIris, const TRectD& irisBBox,
|
|
shun-iwasawa |
25dc51 |
const TTile& irisTile) {
|
|
shun-iwasawa |
25dc51 |
// the original size of iris image
|
|
shun-iwasawa |
25dc51 |
double2 irisOrgSize = {irisBBox.getLx(), irisBBox.getLy()};
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
// add 1 pixel margins to all sides
|
|
shun-iwasawa |
25dc51 |
int2 filterSize = {(int)std::ceil(irisOrgSize.x) + 2,
|
|
shun-iwasawa |
25dc51 |
(int)std::ceil(irisOrgSize.y) + 2};
|
|
shun-iwasawa |
25dc51 |
TPointD resizeOffset((double)filterSize.x - irisOrgSize.x,
|
|
shun-iwasawa |
25dc51 |
(double)filterSize.y - irisOrgSize.y);
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
// Try to set the center of the iris to the center of the screen
|
|
shun-iwasawa |
25dc51 |
if ((dimIris - filterSize.x) % 2 == 1) filterSize.x++;
|
|
shun-iwasawa |
25dc51 |
if ((dimIris - filterSize.y) % 2 == 1) filterSize.y++;
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
TRaster64P resizedIris(TDimension(filterSize.x, filterSize.y));
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
TAffine aff;
|
|
shun-iwasawa |
25dc51 |
TPointD affOffset(0.5, 0.5);
|
|
shun-iwasawa |
25dc51 |
if (dimIris % 2 == 1) affOffset += TPointD(0.5, 0.5);
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
aff = TTranslation(resizedIris->getCenterD() + affOffset);
|
|
shun-iwasawa |
25dc51 |
aff *= TTranslation(-(irisTile.getRaster()->getCenterD() + affOffset));
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
// resample the iris
|
|
shun-iwasawa |
25dc51 |
TRop::resample(resizedIris, irisTile.getRaster(), aff);
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
// accumulated value
|
|
shun-iwasawa |
25dc51 |
float irisValAmount = 0.0;
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
int iris_j = 0;
|
|
shun-iwasawa |
25dc51 |
// Initialize
|
|
shun-iwasawa |
25dc51 |
for (int i = 0; i < dimIris * dimIris; i++) {
|
|
shun-iwasawa |
25dc51 |
kissfft_comp_iris_before[i].r = 0.0;
|
|
shun-iwasawa |
25dc51 |
kissfft_comp_iris_before[i].i = 0.0;
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
for (int j = (dimIris - filterSize.y) / 2; iris_j < filterSize.y;
|
|
shun-iwasawa |
25dc51 |
j++, iris_j++) {
|
|
shun-iwasawa |
25dc51 |
if (j < 0) continue;
|
|
shun-iwasawa |
25dc51 |
if (j >= dimIris) break;
|
|
shun-iwasawa |
25dc51 |
TPixel64* pix = resizedIris->pixels(iris_j);
|
|
shun-iwasawa |
25dc51 |
int iris_i = 0;
|
|
shun-iwasawa |
25dc51 |
for (int i = (dimIris - filterSize.x) / 2; iris_i < filterSize.x;
|
|
shun-iwasawa |
25dc51 |
i++, iris_i++) {
|
|
shun-iwasawa |
25dc51 |
if (i < 0) continue;
|
|
shun-iwasawa |
25dc51 |
if (i >= dimIris) break;
|
|
shun-iwasawa |
25dc51 |
// Value = 0.3R 0.59G 0.11B
|
|
shun-iwasawa |
25dc51 |
kissfft_comp_iris_before[j * dimIris + i].r =
|
|
shun-iwasawa |
25dc51 |
((float)pix->r * 0.3f + (float)pix->g * 0.59f +
|
|
shun-iwasawa |
25dc51 |
(float)pix->b * 0.11f) /
|
|
shun-iwasawa |
25dc51 |
(float)USHRT_MAX;
|
|
shun-iwasawa |
25dc51 |
irisValAmount += kissfft_comp_iris_before[j * dimIris + i].r;
|
|
shun-iwasawa |
25dc51 |
pix++;
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
// Normalize value
|
|
shun-iwasawa |
25dc51 |
for (int i = 0; i < dimIris * dimIris; i++) {
|
|
shun-iwasawa |
25dc51 |
kissfft_comp_iris_before[i].r /= irisValAmount;
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
void Iwa_GlareFx::getParamUIs(TParamUIConcept*& concepts, int& length) {
|
|
shun-iwasawa |
25dc51 |
concepts = new TParamUIConcept[length = 2];
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
concepts[0].m_type = TParamUIConcept::RADIUS;
|
|
shun-iwasawa |
25dc51 |
concepts[0].m_label = "Size";
|
|
shun-iwasawa |
25dc51 |
concepts[0].m_params.push_back(m_size);
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
concepts[1].m_type = TParamUIConcept::POINT;
|
|
shun-iwasawa |
25dc51 |
concepts[1].m_label = "Noise Offset";
|
|
shun-iwasawa |
25dc51 |
concepts[1].m_params.push_back(m_noise_offset);
|
|
shun-iwasawa |
25dc51 |
}
|
|
shun-iwasawa |
25dc51 |
|
|
shun-iwasawa |
25dc51 |
FX_PLUGIN_IDENTIFIER(Iwa_GlareFx, "iwa_GlareFx")
|