|
shun-iwasawa |
b82200 |
/*------------------------------------
|
|
shun-iwasawa |
b82200 |
Iwa_BarrelDistortFx
|
|
shun-iwasawa |
b82200 |
Generates the barrel/pincushion distort.
|
|
shun-iwasawa |
b82200 |
Based on an approximated model for radial distortion
|
|
shun-iwasawa |
b82200 |
by Fitzgibbon, 2001
|
|
shun-iwasawa |
b82200 |
------------------------------------*/
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
#include "stdfx.h"
|
|
shun-iwasawa |
b82200 |
#include "tfxparam.h"
|
|
shun-iwasawa |
b82200 |
#include "tparamset.h"
|
|
shun-iwasawa |
b82200 |
#include "tparamuiconcept.h"
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
#include <qvector2d></qvector2d>
|
|
shun-iwasawa |
b82200 |
#include <qpointf></qpointf>
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
namespace {
|
|
shun-iwasawa |
b82200 |
struct float4 {
|
|
shun-iwasawa |
b82200 |
float x, y, z, w;
|
|
shun-iwasawa |
b82200 |
};
|
|
shun-iwasawa |
b82200 |
/*------------------------------------------------------------
|
|
shun-iwasawa |
b82200 |
read the source image, normalize to 0 - 1
|
|
shun-iwasawa |
b82200 |
------------------------------------------------------------*/
|
|
shun-iwasawa |
b82200 |
template <typename pixel="" raster,="" typename=""></typename>
|
|
shun-iwasawa |
b82200 |
void setSourceRaster(const RASTER srcRas, float4 *dstMem, TDimensionI dim) {
|
|
shun-iwasawa |
b82200 |
float4 *chann_p = dstMem;
|
|
shun-iwasawa |
b82200 |
for (int j = 0; j < dim.ly; j++) {
|
|
shun-iwasawa |
b82200 |
PIXEL *pix = srcRas->pixels(j);
|
|
shun-iwasawa |
b82200 |
for (int i = 0; i < dim.lx; i++, pix++, chann_p++) {
|
|
shun-iwasawa |
b82200 |
(*chann_p).x = (float)pix->r / (float)PIXEL::maxChannelValue;
|
|
shun-iwasawa |
b82200 |
(*chann_p).y = (float)pix->g / (float)PIXEL::maxChannelValue;
|
|
shun-iwasawa |
b82200 |
(*chann_p).z = (float)pix->b / (float)PIXEL::maxChannelValue;
|
|
shun-iwasawa |
b82200 |
(*chann_p).w = (float)pix->m / (float)PIXEL::maxChannelValue;
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
/*------------------------------------------------------------
|
|
shun-iwasawa |
b82200 |
convert the result to channel value and store to the output raster
|
|
shun-iwasawa |
b82200 |
------------------------------------------------------------*/
|
|
shun-iwasawa |
b82200 |
template <typename pixel="" raster,="" typename=""></typename>
|
|
shun-iwasawa |
b82200 |
void setOutputRaster(float4 *srcMem, const RASTER dstRas) {
|
|
shun-iwasawa |
b82200 |
dstRas->fill(PIXEL::Transparent);
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
float4 *chan_p = srcMem;
|
|
shun-iwasawa |
b82200 |
for (int j = 0; j < dstRas->getLy(); j++) {
|
|
shun-iwasawa |
b82200 |
PIXEL *pix = dstRas->pixels(j);
|
|
shun-iwasawa |
b82200 |
for (int i = 0; i < dstRas->getLx(); i++, chan_p++, pix++) {
|
|
shun-iwasawa |
b82200 |
float val;
|
|
shun-iwasawa |
b82200 |
val = (*chan_p).x * (float)PIXEL::maxChannelValue + 0.5f;
|
|
shun-iwasawa |
b82200 |
pix->r = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue)
|
|
shun-iwasawa |
b82200 |
? (float)PIXEL::maxChannelValue
|
|
shun-iwasawa |
b82200 |
: val);
|
|
shun-iwasawa |
b82200 |
val = (*chan_p).y * (float)PIXEL::maxChannelValue + 0.5f;
|
|
shun-iwasawa |
b82200 |
pix->g = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue)
|
|
shun-iwasawa |
b82200 |
? (float)PIXEL::maxChannelValue
|
|
shun-iwasawa |
b82200 |
: val);
|
|
shun-iwasawa |
b82200 |
val = (*chan_p).z * (float)PIXEL::maxChannelValue + 0.5f;
|
|
shun-iwasawa |
b82200 |
pix->b = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue)
|
|
shun-iwasawa |
b82200 |
? (float)PIXEL::maxChannelValue
|
|
shun-iwasawa |
b82200 |
: val);
|
|
shun-iwasawa |
b82200 |
val = (*chan_p).w * (float)PIXEL::maxChannelValue + 0.5f;
|
|
shun-iwasawa |
b82200 |
pix->m = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue)
|
|
shun-iwasawa |
b82200 |
? (float)PIXEL::maxChannelValue
|
|
shun-iwasawa |
b82200 |
: val);
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
481b59 |
template <>
|
|
shun-iwasawa |
481b59 |
void setOutputRaster<trasterfp, tpixelf="">(float4 *srcMem,</trasterfp,>
|
|
shun-iwasawa |
481b59 |
const TRasterFP dstRas) {
|
|
shun-iwasawa |
481b59 |
dstRas->fill(TPixelF::Transparent);
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
float4 *chan_p = srcMem;
|
|
shun-iwasawa |
481b59 |
for (int j = 0; j < dstRas->getLy(); j++) {
|
|
shun-iwasawa |
481b59 |
TPixelF *pix = dstRas->pixels(j);
|
|
shun-iwasawa |
481b59 |
for (int i = 0; i < dstRas->getLx(); i++, chan_p++, pix++) {
|
|
shun-iwasawa |
481b59 |
pix->r = (*chan_p).x;
|
|
shun-iwasawa |
481b59 |
pix->g = (*chan_p).y;
|
|
shun-iwasawa |
481b59 |
pix->b = (*chan_p).z;
|
|
shun-iwasawa |
481b59 |
pix->m = (*chan_p).w;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
b82200 |
float4 getSource_CPU(float4 *source_host, TDimensionI &dim, int pos_x,
|
|
shun-iwasawa |
b82200 |
int pos_y) {
|
|
shun-iwasawa |
b82200 |
if (pos_x < 0 || pos_x >= dim.lx || pos_y < 0 || pos_y >= dim.ly)
|
|
shun-iwasawa |
b82200 |
return float4{0.0f, 0.0f, 0.0f, 0.0f};
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
return source_host[pos_y * dim.lx + pos_x];
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
float4 interp_CPU(float4 val1, float4 val2, float ratio) {
|
|
shun-iwasawa |
b82200 |
return float4{(1.0f - ratio) * val1.x + ratio * val2.x,
|
|
shun-iwasawa |
b82200 |
(1.0f - ratio) * val1.y + ratio * val2.y,
|
|
shun-iwasawa |
b82200 |
(1.0f - ratio) * val1.z + ratio * val2.z,
|
|
shun-iwasawa |
b82200 |
(1.0f - ratio) * val1.w + ratio * val2.w};
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
float adjustExposure(float source, float distance, float amount, float gamma,
|
|
shun-iwasawa |
b82200 |
float midpoint) {
|
|
shun-iwasawa |
b82200 |
float scale = (distance < midpoint)
|
|
shun-iwasawa |
b82200 |
? 0.0f
|
|
shun-iwasawa |
b82200 |
: amount * (distance - midpoint) / (1.0f - midpoint);
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
float ret = powf(10, (source - 0.5f) * gamma);
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
ret *= powf(10, scale);
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
ret = log10f(ret) / gamma + 0.5f;
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
return (ret > 1.0f) ? 1.0f : ((ret < 0.0f) ? 0.0f : ret);
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
481b59 |
}; // namespace
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
class Iwa_BarrelDistortFx final : public TStandardRasterFx {
|
|
shun-iwasawa |
b82200 |
FX_PLUGIN_DECLARATION(Iwa_BarrelDistortFx)
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
TRasterFxPort m_source;
|
|
shun-iwasawa |
b82200 |
TPointParamP m_point;
|
|
shun-iwasawa |
b82200 |
TDoubleParamP m_distortion;
|
|
shun-iwasawa |
b82200 |
TDoubleParamP m_distortionAspect;
|
|
shun-iwasawa |
b82200 |
TDoubleParamP m_precision;
|
|
shun-iwasawa |
b82200 |
TDoubleParamP m_chromaticAberration;
|
|
shun-iwasawa |
b82200 |
TDoubleParamP m_vignetteAmount;
|
|
shun-iwasawa |
b82200 |
TDoubleParamP m_vignetteGamma;
|
|
shun-iwasawa |
b82200 |
TDoubleParamP m_vignetteMidpoint;
|
|
shun-iwasawa |
b82200 |
TDoubleParamP m_scale;
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
public:
|
|
shun-iwasawa |
b82200 |
Iwa_BarrelDistortFx()
|
|
shun-iwasawa |
b82200 |
: m_point(TPointD(0.0, 0.0))
|
|
shun-iwasawa |
b82200 |
, m_distortion(0.0)
|
|
shun-iwasawa |
b82200 |
, m_distortionAspect(1.0)
|
|
shun-iwasawa |
b82200 |
, m_precision(1.0)
|
|
shun-iwasawa |
b82200 |
, m_chromaticAberration(0.0)
|
|
shun-iwasawa |
b82200 |
, m_vignetteAmount(0.0)
|
|
shun-iwasawa |
b82200 |
, m_vignetteGamma(1.0)
|
|
shun-iwasawa |
b82200 |
, m_vignetteMidpoint(0.5)
|
|
shun-iwasawa |
b82200 |
, m_scale(1.0) {
|
|
shun-iwasawa |
b82200 |
m_point->getX()->setMeasureName("fxLength");
|
|
shun-iwasawa |
b82200 |
m_point->getY()->setMeasureName("fxLength");
|
|
shun-iwasawa |
b82200 |
bindParam(this, "center", m_point);
|
|
shun-iwasawa |
b82200 |
bindParam(this, "distortion", m_distortion);
|
|
shun-iwasawa |
b82200 |
bindParam(this, "distortionAspect", m_distortionAspect);
|
|
shun-iwasawa |
b82200 |
bindParam(this, "precision", m_precision);
|
|
shun-iwasawa |
b82200 |
bindParam(this, "chromaticAberration", m_chromaticAberration);
|
|
shun-iwasawa |
b82200 |
bindParam(this, "vignetteAmount", m_vignetteAmount);
|
|
shun-iwasawa |
b82200 |
bindParam(this, "vignetteGamma", m_vignetteGamma);
|
|
shun-iwasawa |
b82200 |
bindParam(this, "vignetteMidpoint", m_vignetteMidpoint);
|
|
shun-iwasawa |
b82200 |
bindParam(this, "scale", m_scale);
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
addInputPort("Source", m_source);
|
|
shun-iwasawa |
b82200 |
m_distortion->setValueRange(-2.0, 2.0);
|
|
shun-iwasawa |
b82200 |
m_distortionAspect->setValueRange(0.2, 5.0);
|
|
shun-iwasawa |
b82200 |
m_precision->setValueRange(1.0, 3.0);
|
|
shun-iwasawa |
b82200 |
m_chromaticAberration->setValueRange(-0.1, 0.1);
|
|
shun-iwasawa |
b82200 |
m_vignetteAmount->setValueRange(-1.0, 1.0);
|
|
shun-iwasawa |
b82200 |
m_vignetteGamma->setValueRange(0.05, 20.0);
|
|
shun-iwasawa |
b82200 |
m_vignetteMidpoint->setValueRange(0.0, 1.0);
|
|
shun-iwasawa |
b82200 |
m_scale->setValueRange(0.1, 2.0);
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
enableComputeInFloat(true);
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
~Iwa_BarrelDistortFx(){};
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
bool doGetBBox(double frame, TRectD &bBox,
|
|
shun-iwasawa |
b82200 |
const TRenderSettings &info) override {
|
|
shun-iwasawa |
b82200 |
if (m_source.isConnected()) {
|
|
shun-iwasawa |
481b59 |
bool ret = m_source->doGetBBox(frame, bBox, info);
|
|
shun-iwasawa |
b82200 |
if (ret) bBox = TConsts::infiniteRectD;
|
|
shun-iwasawa |
b82200 |
return ret;
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
return false;
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
void doCompute(TTile &tile, double frame, const TRenderSettings &) override;
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
void doCompute_CPU(TPointD &point, TPointD &sourcePoint, float dist,
|
|
shun-iwasawa |
b82200 |
float distAspect, float4 *source_host, float4 *result_host,
|
|
shun-iwasawa |
4734f8 |
TRectD &rectOut, TDimensionI &sourceDim, TPointD &offset,
|
|
shun-iwasawa |
4734f8 |
float precision, double vignetteAmount,
|
|
shun-iwasawa |
4734f8 |
double vignetteGamma, double vignetteMidpoint, float scale,
|
|
shun-iwasawa |
4734f8 |
const TRenderSettings &ri);
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
void doCompute_chroma_CPU(TPointD &point, TPointD &sourcePoint, float dist,
|
|
shun-iwasawa |
b82200 |
float distAspect, float chroma, float4 *source_host,
|
|
shun-iwasawa |
4734f8 |
float4 *result_host, TRectD &rectOut,
|
|
shun-iwasawa |
b82200 |
TDimensionI &sourceDim, TPointD &offset,
|
|
shun-iwasawa |
b82200 |
float precision, double vignetteAmount,
|
|
shun-iwasawa |
b82200 |
double vignetteGamma, double vignetteMidpoint,
|
|
shun-iwasawa |
4734f8 |
float scale, const TRenderSettings &ri);
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
bool canHandle(const TRenderSettings &info, double frame) override {
|
|
shun-iwasawa |
b82200 |
return false;
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
void getParamUIs(TParamUIConcept *&concepts, int &length) override {
|
|
shun-iwasawa |
b82200 |
concepts = new TParamUIConcept[length = 1];
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
concepts[0].m_type = TParamUIConcept::POINT;
|
|
shun-iwasawa |
b82200 |
concepts[0].m_label = "Center";
|
|
shun-iwasawa |
b82200 |
concepts[0].m_params.push_back(m_point);
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
};
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
//------------------------------------------------------------------
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
void Iwa_BarrelDistortFx::doCompute(TTile &tile, double frame,
|
|
shun-iwasawa |
b82200 |
const TRenderSettings &ri) {
|
|
shun-iwasawa |
b82200 |
if (!m_source.isConnected()) return;
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
TPointD point = m_point->getValue(frame);
|
|
shun-iwasawa |
b82200 |
TAffine aff = ri.m_affine;
|
|
shun-iwasawa |
b82200 |
// convert the coordinate to with origin at bottom-left corner of the camera
|
|
shun-iwasawa |
4734f8 |
point = aff * point +
|
|
shun-iwasawa |
b82200 |
TPointD(ri.m_cameraBox.getLx() / 2.0, ri.m_cameraBox.getLy() / 2.0);
|
|
shun-iwasawa |
b82200 |
double dist = m_distortion->getValue(frame);
|
|
shun-iwasawa |
b82200 |
double distAspect = m_distortionAspect->getValue(frame);
|
|
shun-iwasawa |
b82200 |
double scale = m_scale->getValue(frame);
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
TRectD rectOut(tile.m_pos, TDimensionD(tile.getRaster()->getLx(),
|
|
shun-iwasawa |
b82200 |
tile.getRaster()->getLy()));
|
|
shun-iwasawa |
b82200 |
TDimensionI outDim(rectOut.getLx(), rectOut.getLy());
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
float precision = m_precision->getValue(frame);
|
|
shun-iwasawa |
b82200 |
TRenderSettings source_ri(ri);
|
|
shun-iwasawa |
b82200 |
TPointD sourcePoint(point);
|
|
shun-iwasawa |
b82200 |
if (precision > 1.0) {
|
|
shun-iwasawa |
b82200 |
source_ri.m_affine *= TScale(precision, precision);
|
|
shun-iwasawa |
4734f8 |
sourcePoint = source_ri.m_affine * m_point->getValue(frame) +
|
|
shun-iwasawa |
b82200 |
TPointD(source_ri.m_cameraBox.getLx() / 2.0,
|
|
shun-iwasawa |
b82200 |
source_ri.m_cameraBox.getLy() / 2.0);
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
TRectD sourceBBox;
|
|
shun-iwasawa |
b82200 |
m_source->getBBox(frame, sourceBBox, source_ri);
|
|
shun-iwasawa |
b82200 |
TDimensionI sourceDim;
|
|
shun-iwasawa |
b82200 |
if (sourceBBox == TConsts::infiniteRectD) {
|
|
shun-iwasawa |
b82200 |
TPointD tileOffset = tile.m_pos + tile.getRaster()->getCenterD();
|
|
shun-iwasawa |
b82200 |
sourceBBox = TRectD(TPointD(source_ri.m_cameraBox.x0 + tileOffset.x,
|
|
shun-iwasawa |
481b59 |
source_ri.m_cameraBox.y0 + tileOffset.y),
|
|
shun-iwasawa |
481b59 |
TDimensionD(source_ri.m_cameraBox.getLx(),
|
|
shun-iwasawa |
481b59 |
source_ri.m_cameraBox.getLy()));
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
sourceDim.lx = std::ceil(sourceBBox.getLx());
|
|
shun-iwasawa |
b82200 |
sourceDim.ly = std::ceil(sourceBBox.getLy());
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
TTile sourceTile;
|
|
shun-iwasawa |
b82200 |
m_source->allocateAndCompute(sourceTile, sourceBBox.getP00(), sourceDim,
|
|
shun-iwasawa |
b82200 |
tile.getRaster(), frame, source_ri);
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
float4 *source_host;
|
|
shun-iwasawa |
b82200 |
TRasterGR8P source_host_ras(sourceDim.lx * sizeof(float4), sourceDim.ly);
|
|
shun-iwasawa |
b82200 |
source_host_ras->lock();
|
|
shun-iwasawa |
b82200 |
source_host = (float4 *)source_host_ras->getRawData();
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
TRaster32P ras32 = (TRaster32P)sourceTile.getRaster();
|
|
shun-iwasawa |
b82200 |
TRaster64P ras64 = (TRaster64P)sourceTile.getRaster();
|
|
shun-iwasawa |
481b59 |
TRasterFP rasF = (TRasterFP)sourceTile.getRaster();
|
|
shun-iwasawa |
b82200 |
if (ras32)
|
|
shun-iwasawa |
b82200 |
setSourceRaster<traster32p, tpixel32="">(ras32, source_host, sourceDim);</traster32p,>
|
|
shun-iwasawa |
b82200 |
else if (ras64)
|
|
shun-iwasawa |
b82200 |
setSourceRaster<traster64p, tpixel64="">(ras64, source_host, sourceDim);</traster64p,>
|
|
shun-iwasawa |
481b59 |
else if (rasF)
|
|
shun-iwasawa |
481b59 |
setSourceRaster<trasterfp, tpixelf="">(rasF, source_host, sourceDim);</trasterfp,>
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
TRasterGR8P result_host_ras(outDim.lx * sizeof(float4), outDim.ly);
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
// memory to store the result
|
|
shun-iwasawa |
b82200 |
float4 *result_host;
|
|
shun-iwasawa |
b82200 |
result_host_ras->lock();
|
|
shun-iwasawa |
b82200 |
result_host = (float4 *)result_host_ras->getRawData();
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
4734f8 |
TPointD offset = sourceTile.m_pos + TPointD(ri.m_cameraBox.getLx() / 2.0,
|
|
shun-iwasawa |
4734f8 |
ri.m_cameraBox.getLy() / 2.0);
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
double vignetteAmount = m_vignetteAmount->getValue(frame);
|
|
shun-iwasawa |
b82200 |
double vignetteGamma = m_vignetteGamma->getValue(frame);
|
|
shun-iwasawa |
b82200 |
double vignetteMidpoint = m_vignetteMidpoint->getValue(frame);
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
double chroma = m_chromaticAberration->getValue(frame);
|
|
shun-iwasawa |
b82200 |
if (areAlmostEqual(chroma, 0.0))
|
|
shun-iwasawa |
b82200 |
doCompute_CPU(point, sourcePoint, dist, distAspect, source_host,
|
|
shun-iwasawa |
4734f8 |
result_host, rectOut, sourceDim, offset, precision,
|
|
shun-iwasawa |
4734f8 |
vignetteAmount, vignetteGamma, vignetteMidpoint, scale, ri);
|
|
shun-iwasawa |
b82200 |
else
|
|
shun-iwasawa |
b82200 |
doCompute_chroma_CPU(point, sourcePoint, dist, distAspect, chroma,
|
|
shun-iwasawa |
4734f8 |
source_host, result_host, rectOut, sourceDim, offset,
|
|
shun-iwasawa |
b82200 |
precision, vignetteAmount, vignetteGamma,
|
|
shun-iwasawa |
4734f8 |
vignetteMidpoint, scale, ri);
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
source_host_ras->unlock();
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
// convert the result to channel value and store to the output raster
|
|
shun-iwasawa |
b82200 |
TRaster32P outRas32 = (TRaster32P)tile.getRaster();
|
|
shun-iwasawa |
b82200 |
TRaster64P outRas64 = (TRaster64P)tile.getRaster();
|
|
shun-iwasawa |
481b59 |
TRasterFP outRasF = (TRasterFP)tile.getRaster();
|
|
shun-iwasawa |
b82200 |
if (outRas32)
|
|
shun-iwasawa |
b82200 |
setOutputRaster<traster32p, tpixel32="">(result_host, outRas32);</traster32p,>
|
|
shun-iwasawa |
b82200 |
else if (outRas64)
|
|
shun-iwasawa |
b82200 |
setOutputRaster<traster64p, tpixel64="">(result_host, outRas64);</traster64p,>
|
|
shun-iwasawa |
481b59 |
else if (outRasF)
|
|
shun-iwasawa |
481b59 |
setOutputRaster<trasterfp, tpixelf="">(result_host, outRasF);</trasterfp,>
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
result_host_ras->unlock();
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
//------------------------------------------------------------------
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
void Iwa_BarrelDistortFx::doCompute_CPU(
|
|
shun-iwasawa |
b82200 |
TPointD &point, TPointD &sourcePoint, float dist, float distAspect,
|
|
shun-iwasawa |
4734f8 |
float4 *source_host, float4 *result_host, TRectD &rectOut,
|
|
shun-iwasawa |
b82200 |
TDimensionI &sourceDim, TPointD &offset, float precision,
|
|
shun-iwasawa |
b82200 |
double vignetteAmount, double vignetteGamma, double vignetteMidpoint,
|
|
shun-iwasawa |
4734f8 |
float scale, const TRenderSettings &ri) {
|
|
shun-iwasawa |
4734f8 |
float4 *result_p = result_host;
|
|
shun-iwasawa |
4734f8 |
float squaredSize =
|
|
shun-iwasawa |
4734f8 |
(float)(ri.m_cameraBox.getLx() * ri.m_cameraBox.getLy()) * 0.25f;
|
|
shun-iwasawa |
4734f8 |
|
|
shun-iwasawa |
b82200 |
QPointF offsetCenter(sourcePoint.x - offset.x, sourcePoint.y - offset.y);
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
bool doVignette = !areAlmostEqual(vignetteAmount, 0.0);
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
// Only the case of barrel distortion (dist < 0) , decrease the sample
|
|
shun-iwasawa |
b82200 |
// position.
|
|
shun-iwasawa |
b82200 |
// It will enlarge the result image.
|
|
shun-iwasawa |
b82200 |
// Such adjustment can be seen in Lens Correction feature of PhotoShop.
|
|
shun-iwasawa |
b82200 |
float sizeAdjust = (dist < 0.0f) ? (1.0f + dist) : 1.0f;
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
QVector2D distAspectVec(1, 1);
|
|
shun-iwasawa |
b82200 |
if (distAspect > 0.0f && distAspect != 1.0f) {
|
|
shun-iwasawa |
b82200 |
float aspectSqrt = std::sqrt(distAspect);
|
|
shun-iwasawa |
b82200 |
if (dist < 0.0f)
|
|
shun-iwasawa |
b82200 |
distAspectVec = QVector2D(1.0 / aspectSqrt, aspectSqrt);
|
|
shun-iwasawa |
b82200 |
else
|
|
shun-iwasawa |
b82200 |
distAspectVec = QVector2D(aspectSqrt, 1.0 / aspectSqrt);
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
4734f8 |
TPointD outImgOrigin =
|
|
shun-iwasawa |
4734f8 |
rectOut.getP00() +
|
|
shun-iwasawa |
4734f8 |
TPointD(ri.m_cameraBox.getLx() / 2.0, ri.m_cameraBox.getLy() / 2.0);
|
|
shun-iwasawa |
4734f8 |
|
|
shun-iwasawa |
4734f8 |
for (int j = 0; j < (int)rectOut.getLy(); j++) {
|
|
shun-iwasawa |
4734f8 |
for (int i = 0; i < (int)rectOut.getLx(); i++, result_p++) {
|
|
shun-iwasawa |
4734f8 |
QVector2D ru(QPointF((float)i, (float)j) +
|
|
shun-iwasawa |
4734f8 |
QPointF(outImgOrigin.x, outImgOrigin.y) -
|
|
shun-iwasawa |
4734f8 |
QPointF(point.x, point.y));
|
|
shun-iwasawa |
b82200 |
// apply global scaling
|
|
shun-iwasawa |
b82200 |
ru /= scale;
|
|
shun-iwasawa |
b82200 |
float val = (ru * distAspectVec).lengthSquared() / squaredSize;
|
|
shun-iwasawa |
b82200 |
if (dist > 0.0f && val > 1.0f / dist) {
|
|
shun-iwasawa |
b82200 |
(*result_p) = {0.0f, 0.0f, 0.0f, 0.0f};
|
|
shun-iwasawa |
b82200 |
continue;
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
float distortRatio = sizeAdjust / (1.0f + dist * val);
|
|
shun-iwasawa |
b82200 |
QVector2D rd = distortRatio * ru;
|
|
shun-iwasawa |
b82200 |
QPointF samplePos = offsetCenter + rd.toPointF() * precision;
|
|
shun-iwasawa |
b82200 |
if (samplePos.x() <= -1.0f || samplePos.x() >= (float)(sourceDim.lx) ||
|
|
shun-iwasawa |
b82200 |
samplePos.y() <= -1.0f || samplePos.y() >= (float)(sourceDim.ly)) {
|
|
shun-iwasawa |
b82200 |
(*result_p) = {0.0f, 0.0f, 0.0f, 0.0f};
|
|
shun-iwasawa |
b82200 |
continue;
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
QPoint pos(std::floor(samplePos.x()), std::floor(samplePos.y()));
|
|
shun-iwasawa |
b82200 |
QPointF ratio(samplePos.x() - (float)pos.x(),
|
|
shun-iwasawa |
b82200 |
samplePos.y() - (float)pos.y());
|
|
shun-iwasawa |
b82200 |
(*result_p) = interp_CPU(
|
|
shun-iwasawa |
b82200 |
interp_CPU(
|
|
shun-iwasawa |
b82200 |
getSource_CPU(source_host, sourceDim, pos.x(), pos.y()),
|
|
shun-iwasawa |
b82200 |
getSource_CPU(source_host, sourceDim, pos.x() + 1, pos.y()),
|
|
shun-iwasawa |
b82200 |
ratio.x()),
|
|
shun-iwasawa |
b82200 |
interp_CPU(
|
|
shun-iwasawa |
b82200 |
getSource_CPU(source_host, sourceDim, pos.x(), pos.y() + 1),
|
|
shun-iwasawa |
b82200 |
getSource_CPU(source_host, sourceDim, pos.x() + 1, pos.y() + 1),
|
|
shun-iwasawa |
b82200 |
ratio.x()),
|
|
shun-iwasawa |
b82200 |
ratio.y());
|
|
shun-iwasawa |
b82200 |
if (doVignette) {
|
|
shun-iwasawa |
b82200 |
float distance = distortRatio * distortRatio * val;
|
|
shun-iwasawa |
b82200 |
(*result_p).x = adjustExposure((*result_p).x, distance, vignetteAmount,
|
|
shun-iwasawa |
481b59 |
vignetteGamma, vignetteMidpoint);
|
|
shun-iwasawa |
481b59 |
(*result_p).y = adjustExposure((*result_p).y, distance, vignetteAmount,
|
|
shun-iwasawa |
481b59 |
vignetteGamma, vignetteMidpoint);
|
|
shun-iwasawa |
481b59 |
(*result_p).z = adjustExposure((*result_p).z, distance, vignetteAmount,
|
|
shun-iwasawa |
481b59 |
vignetteGamma, vignetteMidpoint);
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
//------------------------------------------------------------------
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
void Iwa_BarrelDistortFx::doCompute_chroma_CPU(
|
|
shun-iwasawa |
b82200 |
TPointD &point, TPointD &sourcePoint, float dist, float distAspect,
|
|
shun-iwasawa |
4734f8 |
float chroma, float4 *source_host, float4 *result_host, TRectD &rectOut,
|
|
shun-iwasawa |
b82200 |
TDimensionI &sourceDim, TPointD &offset, float precision,
|
|
shun-iwasawa |
b82200 |
double vignetteAmount, double vignetteGamma, double vignetteMidpoint,
|
|
shun-iwasawa |
4734f8 |
float scale, const TRenderSettings &ri) {
|
|
shun-iwasawa |
4734f8 |
float4 *result_p = result_host;
|
|
shun-iwasawa |
4734f8 |
float squaredSize =
|
|
shun-iwasawa |
4734f8 |
(float)(ri.m_cameraBox.getLx() * ri.m_cameraBox.getLy()) * 0.25f;
|
|
shun-iwasawa |
b82200 |
QPointF offsetCenter(sourcePoint.x - offset.x, sourcePoint.y - offset.y);
|
|
shun-iwasawa |
b82200 |
float dist_ch[3] = {dist + chroma, dist, dist - chroma};
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
bool doVignette = !areAlmostEqual(vignetteAmount, 0.0);
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
// Only the case of barrel distortion (dist < 0) , decrease the sample
|
|
shun-iwasawa |
b82200 |
// position.
|
|
shun-iwasawa |
b82200 |
// It will enlarge the result image.
|
|
shun-iwasawa |
b82200 |
// Such adjustment can be seen in Lens Correction feature of PhotoShop.
|
|
shun-iwasawa |
b82200 |
float sizeAdjust = (dist < 0.0f) ? (1.0f + dist) : 1.0f;
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
QVector2D distAspectVec(1, 1);
|
|
shun-iwasawa |
b82200 |
if (distAspect > 0.0f && distAspect != 1.0f) {
|
|
shun-iwasawa |
b82200 |
float aspectSqrt = std::sqrt(distAspect);
|
|
shun-iwasawa |
b82200 |
if (dist < 0.0f)
|
|
shun-iwasawa |
b82200 |
distAspectVec = QVector2D(1.0 / aspectSqrt, aspectSqrt);
|
|
shun-iwasawa |
b82200 |
else
|
|
shun-iwasawa |
b82200 |
distAspectVec = QVector2D(aspectSqrt, 1.0 / aspectSqrt);
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
4734f8 |
TPointD outImgOrigin =
|
|
shun-iwasawa |
4734f8 |
rectOut.getP00() +
|
|
shun-iwasawa |
4734f8 |
TPointD(ri.m_cameraBox.getLx() / 2.0, ri.m_cameraBox.getLy() / 2.0);
|
|
shun-iwasawa |
4734f8 |
|
|
shun-iwasawa |
4734f8 |
for (int j = 0; j < (int)rectOut.getLy(); j++) {
|
|
shun-iwasawa |
4734f8 |
for (int i = 0; i < (int)rectOut.getLx(); i++, result_p++) {
|
|
shun-iwasawa |
b82200 |
for (int c = 0; c < 3; c++) {
|
|
shun-iwasawa |
4734f8 |
QVector2D ru(QPointF((float)i, (float)j) +
|
|
shun-iwasawa |
4734f8 |
QPointF(outImgOrigin.x, outImgOrigin.y) -
|
|
shun-iwasawa |
4734f8 |
QPointF(point.x, point.y));
|
|
shun-iwasawa |
b82200 |
// apply global scaling
|
|
shun-iwasawa |
b82200 |
ru /= scale;
|
|
shun-iwasawa |
b82200 |
float val = (ru * distAspectVec).lengthSquared() / squaredSize;
|
|
shun-iwasawa |
b82200 |
if (dist_ch[c] > 0.0f && val > 1.0f / dist_ch[c]) {
|
|
shun-iwasawa |
b82200 |
(*result_p) = {0.0f, 0.0f, 0.0f, 0.0f};
|
|
shun-iwasawa |
b82200 |
continue;
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
float distortRatio = sizeAdjust / (1.0f + dist_ch[c] * val);
|
|
shun-iwasawa |
b82200 |
QVector2D rd = distortRatio * ru;
|
|
shun-iwasawa |
b82200 |
QPointF samplePos = offsetCenter + rd.toPointF() * precision;
|
|
shun-iwasawa |
b82200 |
if (samplePos.x() <= -1.0f || samplePos.x() >= (float)(sourceDim.lx) ||
|
|
shun-iwasawa |
b82200 |
samplePos.y() <= -1.0f || samplePos.y() >= (float)(sourceDim.ly)) {
|
|
shun-iwasawa |
b82200 |
(*result_p) = {0.0f, 0.0f, 0.0f, 0.0f};
|
|
shun-iwasawa |
b82200 |
continue;
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
QPoint pos(std::floor(samplePos.x()), std::floor(samplePos.y()));
|
|
shun-iwasawa |
b82200 |
QPointF ratio(samplePos.x() - (float)pos.x(),
|
|
shun-iwasawa |
b82200 |
samplePos.y() - (float)pos.y());
|
|
shun-iwasawa |
b82200 |
float4 result_tmp = interp_CPU(
|
|
shun-iwasawa |
b82200 |
interp_CPU(
|
|
shun-iwasawa |
b82200 |
getSource_CPU(source_host, sourceDim, pos.x(), pos.y()),
|
|
shun-iwasawa |
b82200 |
getSource_CPU(source_host, sourceDim, pos.x() + 1, pos.y()),
|
|
shun-iwasawa |
b82200 |
ratio.x()),
|
|
shun-iwasawa |
b82200 |
interp_CPU(
|
|
shun-iwasawa |
b82200 |
getSource_CPU(source_host, sourceDim, pos.x(), pos.y() + 1),
|
|
shun-iwasawa |
b82200 |
getSource_CPU(source_host, sourceDim, pos.x() + 1, pos.y() + 1),
|
|
shun-iwasawa |
b82200 |
ratio.x()),
|
|
shun-iwasawa |
b82200 |
ratio.y());
|
|
shun-iwasawa |
b82200 |
switch (c) {
|
|
shun-iwasawa |
b82200 |
case 0:
|
|
shun-iwasawa |
b82200 |
(*result_p).x = result_tmp.x;
|
|
shun-iwasawa |
b82200 |
if (doVignette)
|
|
shun-iwasawa |
b82200 |
(*result_p).x =
|
|
shun-iwasawa |
b82200 |
adjustExposure((*result_p).x, distortRatio * distortRatio * val,
|
|
shun-iwasawa |
b82200 |
vignetteAmount, vignetteGamma, vignetteMidpoint);
|
|
shun-iwasawa |
b82200 |
break;
|
|
shun-iwasawa |
b82200 |
case 1:
|
|
shun-iwasawa |
b82200 |
(*result_p).y = result_tmp.y;
|
|
shun-iwasawa |
b82200 |
(*result_p).w = result_tmp.w;
|
|
shun-iwasawa |
b82200 |
if (doVignette)
|
|
shun-iwasawa |
b82200 |
(*result_p).y =
|
|
shun-iwasawa |
b82200 |
adjustExposure((*result_p).y, distortRatio * distortRatio * val,
|
|
shun-iwasawa |
b82200 |
vignetteAmount, vignetteGamma, vignetteMidpoint);
|
|
shun-iwasawa |
b82200 |
break;
|
|
shun-iwasawa |
b82200 |
case 2:
|
|
shun-iwasawa |
b82200 |
(*result_p).z = result_tmp.z;
|
|
shun-iwasawa |
b82200 |
if (doVignette)
|
|
shun-iwasawa |
b82200 |
(*result_p).z =
|
|
shun-iwasawa |
b82200 |
adjustExposure((*result_p).z, distortRatio * distortRatio * val,
|
|
shun-iwasawa |
b82200 |
vignetteAmount, vignetteGamma, vignetteMidpoint);
|
|
shun-iwasawa |
b82200 |
break;
|
|
shun-iwasawa |
b82200 |
default:
|
|
shun-iwasawa |
b82200 |
break;
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
}
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
//------------------------------------------------------------------
|
|
shun-iwasawa |
b82200 |
|
|
shun-iwasawa |
b82200 |
FX_PLUGIN_IDENTIFIER(Iwa_BarrelDistortFx, "iwa_BarrelDistortFx")
|