|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "stdfx.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tfxparam.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "trop.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tdoubleparam.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "trasterfx.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/* (Daniele)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
NOTE: Current LocalBlurFx is effectively flawed. Following implementation
|
|
Shinya Kitaoka |
120a6e |
relies on the idea that
|
|
Shinya Kitaoka |
120a6e |
the blurring filter is separable and therefore appliable on rows and
|
|
Shinya Kitaoka |
120a6e |
columns, in sequence.
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
It actually is not. It can be easily verified applying the fx on a
|
|
Shinya Kitaoka |
120a6e |
chessboard with a strong
|
|
Shinya Kitaoka |
120a6e |
blur intensity. The squares will be cast vertically towards blurred
|
|
Shinya Kitaoka |
120a6e |
regions.
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
Originally, this was a sub-optimal O(lx * ly * blur) algorithm. The
|
|
Shinya Kitaoka |
120a6e |
following (still separated)
|
|
Toshihiro Shimizu |
890ddd |
is O(lx * ly) using precomputed sums in an additional line.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
The 'correct' algorithm could be implemented again as O(lx * ly * blur),
|
|
Shinya Kitaoka |
120a6e |
with additional O(lx * blur)
|
|
Toshihiro Shimizu |
890ddd |
memory usage with precomputed sums along (blur) rows.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
Pixels would have to be filtered one by one, but the horizontal
|
|
Shinya Kitaoka |
120a6e |
filtering per pixel convolution row
|
|
Toshihiro Shimizu |
890ddd |
would take O(1). Thus it would be O(blur) (column filtering) per pixel.
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//********************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Local namespace stuff
|
|
Toshihiro Shimizu |
890ddd |
//********************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
namespace {
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
struct Sums {
|
|
Shinya Kitaoka |
120a6e |
std::unique_ptr<tuint64[]></tuint64[]>
|
|
Shinya Kitaoka |
120a6e |
m_sumsIX_r; //!< m_sumsIX1[i+1] = m_sumsIX1[i] + i * pix.r
|
|
Shinya Kitaoka |
120a6e |
std::unique_ptr<tuint64[]> m_sumsIX_g;</tuint64[]>
|
|
Shinya Kitaoka |
120a6e |
std::unique_ptr<tuint64[]> m_sumsIX_b;</tuint64[]>
|
|
Shinya Kitaoka |
120a6e |
std::unique_ptr<tuint64[]> m_sumsIX_m;</tuint64[]>
|
|
Shinya Kitaoka |
120a6e |
std::unique_ptr<tuint64[]> m_sumsX_r; //!< m_sumsX[i+1] = m_sumsX[i] + pix.r</tuint64[]>
|
|
Shinya Kitaoka |
120a6e |
std::unique_ptr<tuint64[]> m_sumsX_g;</tuint64[]>
|
|
Shinya Kitaoka |
120a6e |
std::unique_ptr<tuint64[]> m_sumsX_b;</tuint64[]>
|
|
Shinya Kitaoka |
120a6e |
std::unique_ptr<tuint64[]> m_sumsX_m;</tuint64[]>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
Sums(int length)
|
|
Shinya Kitaoka |
120a6e |
: m_sumsIX_r(new TUINT64[length + 1])
|
|
Shinya Kitaoka |
120a6e |
, m_sumsIX_g(new TUINT64[length + 1])
|
|
Shinya Kitaoka |
120a6e |
, m_sumsIX_b(new TUINT64[length + 1])
|
|
Shinya Kitaoka |
120a6e |
, m_sumsIX_m(new TUINT64[length + 1])
|
|
Shinya Kitaoka |
120a6e |
, m_sumsX_r(new TUINT64[length + 1])
|
|
Shinya Kitaoka |
120a6e |
, m_sumsX_g(new TUINT64[length + 1])
|
|
Shinya Kitaoka |
120a6e |
, m_sumsX_b(new TUINT64[length + 1])
|
|
Shinya Kitaoka |
120a6e |
, m_sumsX_m(new TUINT64[length + 1]) {}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
template <typename pix=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void build(Pix *line, int wrap, int n) {
|
|
Shinya Kitaoka |
120a6e |
++n;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_sumsIX_r[0] = m_sumsX_r[0] = 0;
|
|
Shinya Kitaoka |
120a6e |
m_sumsIX_g[0] = m_sumsX_g[0] = 0;
|
|
Shinya Kitaoka |
120a6e |
m_sumsIX_b[0] = m_sumsX_b[0] = 0;
|
|
Shinya Kitaoka |
120a6e |
m_sumsIX_m[0] = m_sumsX_m[0] = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
Pix *pix;
|
|
Shinya Kitaoka |
120a6e |
int i, i_1;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (pix = line, i_1 = 0, i = 1; i < n; pix += wrap, i_1 = i++) {
|
|
Shinya Kitaoka |
120a6e |
m_sumsIX_r[i] = m_sumsIX_r[i_1] + i * pix->r;
|
|
Shinya Kitaoka |
120a6e |
m_sumsIX_g[i] = m_sumsIX_g[i_1] + i * pix->g;
|
|
Shinya Kitaoka |
120a6e |
m_sumsIX_b[i] = m_sumsIX_b[i_1] + i * pix->b;
|
|
Shinya Kitaoka |
120a6e |
m_sumsIX_m[i] = m_sumsIX_m[i_1] + i * pix->m;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_sumsX_r[i] = m_sumsX_r[i_1] + pix->r;
|
|
Shinya Kitaoka |
120a6e |
m_sumsX_g[i] = m_sumsX_g[i_1] + pix->g;
|
|
Shinya Kitaoka |
120a6e |
m_sumsX_b[i] = m_sumsX_b[i_1] + pix->b;
|
|
Shinya Kitaoka |
120a6e |
m_sumsX_m[i] = m_sumsX_m[i_1] + pix->m;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename grey="" pix,="" typename=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void filterLine(Pix *lineIn, int wrapIn, Grey *lineGr, int wrapGr, Pix *lineOut,
|
|
Shinya Kitaoka |
120a6e |
int wrapOut, int length, double blurFactor, Sums &sums) {
|
|
Shinya Kitaoka |
120a6e |
// Build temporary sums
|
|
Shinya Kitaoka |
120a6e |
sums.build(lineIn, wrapIn, length);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Declare vars
|
|
Shinya Kitaoka |
120a6e |
double blur, kLeft, kRight, cLeft, cRight;
|
|
Shinya Kitaoka |
120a6e |
double blurI;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Perform line filtering
|
|
Shinya Kitaoka |
120a6e |
Pix *pixIn, *pixOut;
|
|
Shinya Kitaoka |
120a6e |
Grey *pixGr;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int i, iLeft, iRight;
|
|
Shinya Kitaoka |
120a6e |
++length;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (i = 1, pixIn = lineIn, pixGr = lineGr, pixOut = lineOut; i < length;
|
|
Shinya Kitaoka |
120a6e |
++i, pixIn += wrapIn, pixGr += wrapGr, pixOut += wrapOut) {
|
|
Shinya Kitaoka |
120a6e |
blur = pixGr->value * blurFactor; // A table of factors should be made -
|
|
Shinya Kitaoka |
120a6e |
// since we have a finite
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (blur > 0.0) {
|
|
Shinya Kitaoka |
120a6e |
blur +=
|
|
Shinya Kitaoka |
120a6e |
0.5; /*-- 0.5足すのは、注目ピクセルの半径分。例えばBlur0.5は、
|
|
Shinya Kitaoka |
120a6e |
注目ピクセルの外側0.5ピクセルボケるということなので。
|
|
Shinya Kitaoka |
120a6e |
--*/
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
blurI = (double)tfloor(blur);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double amount = blur + (2 * blur - blurI - 1) * blurI;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double dR = 1.0 / amount;
|
|
Shinya Kitaoka |
120a6e |
double ini = (blur - blurI) / amount;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
kLeft = dR;
|
|
Shinya Kitaoka |
120a6e |
cLeft = ini - dR * (i - blurI);
|
|
Shinya Kitaoka |
120a6e |
kRight = -dR;
|
|
Shinya Kitaoka |
120a6e |
cRight = blur / amount + dR * i;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// NOTE: The normalization factor with blur (not integer) would be:
|
|
Shinya Kitaoka |
120a6e |
// 1.0 / (1 + 2 * blurI - (blurI / blur) * (blurI + 1))
|
|
Shinya Kitaoka |
120a6e |
// -- could be done using a factors table
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
iLeft = std::max(i - tfloor(blur) - 1, 0);
|
|
Shinya Kitaoka |
120a6e |
iRight = std::min(i + tfloor(blur), length - 1);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
pixOut->r =
|
|
Shinya Kitaoka |
120a6e |
troundp(kLeft * (sums.m_sumsIX_r[i] - sums.m_sumsIX_r[iLeft]) +
|
|
Shinya Kitaoka |
120a6e |
kRight * (sums.m_sumsIX_r[iRight] - sums.m_sumsIX_r[i]) +
|
|
Shinya Kitaoka |
120a6e |
cLeft * (sums.m_sumsX_r[i] - sums.m_sumsX_r[iLeft]) +
|
|
Shinya Kitaoka |
120a6e |
cRight * (sums.m_sumsX_r[iRight] - sums.m_sumsX_r[i]));
|
|
Shinya Kitaoka |
120a6e |
pixOut->g =
|
|
Shinya Kitaoka |
120a6e |
troundp(kLeft * (sums.m_sumsIX_g[i] - sums.m_sumsIX_g[iLeft]) +
|
|
Shinya Kitaoka |
120a6e |
kRight * (sums.m_sumsIX_g[iRight] - sums.m_sumsIX_g[i]) +
|
|
Shinya Kitaoka |
120a6e |
cLeft * (sums.m_sumsX_g[i] - sums.m_sumsX_g[iLeft]) +
|
|
Shinya Kitaoka |
120a6e |
cRight * (sums.m_sumsX_g[iRight] - sums.m_sumsX_g[i]));
|
|
Shinya Kitaoka |
120a6e |
pixOut->b =
|
|
Shinya Kitaoka |
120a6e |
troundp(kLeft * (sums.m_sumsIX_b[i] - sums.m_sumsIX_b[iLeft]) +
|
|
Shinya Kitaoka |
120a6e |
kRight * (sums.m_sumsIX_b[iRight] - sums.m_sumsIX_b[i]) +
|
|
Shinya Kitaoka |
120a6e |
cLeft * (sums.m_sumsX_b[i] - sums.m_sumsX_b[iLeft]) +
|
|
Shinya Kitaoka |
120a6e |
cRight * (sums.m_sumsX_b[iRight] - sums.m_sumsX_b[i]));
|
|
Shinya Kitaoka |
120a6e |
pixOut->m =
|
|
Shinya Kitaoka |
120a6e |
troundp(kLeft * (sums.m_sumsIX_m[i] - sums.m_sumsIX_m[iLeft]) +
|
|
Shinya Kitaoka |
120a6e |
kRight * (sums.m_sumsIX_m[iRight] - sums.m_sumsIX_m[i]) +
|
|
Shinya Kitaoka |
120a6e |
cLeft * (sums.m_sumsX_m[i] - sums.m_sumsX_m[iLeft]) +
|
|
Shinya Kitaoka |
120a6e |
cRight * (sums.m_sumsX_m[iRight] - sums.m_sumsX_m[i]));
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
*pixOut = *pixIn;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename grey="" pix,="" typename=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void doLocalBlur(TRasterPT<pix> rin, TRasterPT<pix> rcontrol,</pix></pix>
|
|
Shinya Kitaoka |
120a6e |
TRasterPT<pix> rout, double blur, const TPoint &displacement) {</pix>
|
|
Shinya Kitaoka |
120a6e |
assert(rin->getLx() == rcontrol->getLx() &&
|
|
Shinya Kitaoka |
120a6e |
rin->getLy() == rcontrol->getLy());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
double blurFactor = blur / Grey::maxChannelValue;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
int x, y, inLx, inLy, outLx, outLy, wrapIn, wrapOut, wrapC;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
inLx = rin->getLx();
|
|
Shinya Kitaoka |
120a6e |
inLy = rin->getLy();
|
|
Shinya Kitaoka |
120a6e |
wrapIn = rin->getWrap();
|
|
Shinya Kitaoka |
120a6e |
outLx = rout->getLx();
|
|
Shinya Kitaoka |
120a6e |
outLy = rout->getLy();
|
|
Shinya Kitaoka |
120a6e |
wrapOut = rout->getWrap();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Convert the control raster to grey values (this avoids the overhead of
|
|
Shinya Kitaoka |
120a6e |
// performing the pixel-to-value
|
|
Shinya Kitaoka |
120a6e |
// conversion twice, once per line filtering)
|
|
Shinya Kitaoka |
120a6e |
TRasterPT<grey> rcontrolGrey(rcontrol->getLx(), rcontrol->getLy());</grey>
|
|
Shinya Kitaoka |
120a6e |
TRop::convert(rcontrolGrey, rcontrol);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
wrapC = rcontrolGrey->getWrap();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
Pix *lineIn, *bufIn;
|
|
Shinya Kitaoka |
120a6e |
Grey *lineC, *bufC;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Filter rin. The output filtering is still stored in rin.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
rin->lock();
|
|
Shinya Kitaoka |
120a6e |
rcontrolGrey->lock();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bufIn = rin->pixels(0);
|
|
Shinya Kitaoka |
120a6e |
bufC = rcontrolGrey->pixels(0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
Sums sums(inLx);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
for (y = 0, lineIn = bufIn, lineC = bufC; y < inLy;
|
|
Shinya Kitaoka |
120a6e |
++y, lineIn += wrapIn, lineC += wrapC) {
|
|
Shinya Kitaoka |
120a6e |
// Filter row
|
|
Shinya Kitaoka |
120a6e |
filterLine(lineIn, 1, lineC, 1, lineIn, 1, inLx, blurFactor, sums);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
Sums sums(inLy);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
for (x = 0, lineIn = bufIn, lineC = bufC; x < inLx;
|
|
Shinya Kitaoka |
120a6e |
++x, ++lineIn, ++lineC) {
|
|
Shinya Kitaoka |
120a6e |
// Filter column
|
|
Shinya Kitaoka |
120a6e |
filterLine(lineIn, wrapIn, lineC, wrapC, lineIn, wrapIn, inLy, blurFactor,
|
|
Shinya Kitaoka |
120a6e |
sums);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
rin->unlock();
|
|
Shinya Kitaoka |
120a6e |
rcontrolGrey->unlock();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Copy the interesting part of rin to rout
|
|
Shinya Kitaoka |
120a6e |
TRect rectOut(rout->getBounds() - displacement);
|
|
Shinya Kitaoka |
120a6e |
TRect rectIn(rin->getBounds() + displacement);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRop::copy(rout->extract(rectIn), rin->extract(rectOut));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
} // namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//********************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// LocalBlurFx implementation
|
|
Toshihiro Shimizu |
890ddd |
//********************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
class LocalBlurFx : public TStandardRasterFx {
|
|
Shinya Kitaoka |
120a6e |
FX_PLUGIN_DECLARATION(LocalBlurFx)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
protected:
|
|
Shinya Kitaoka |
120a6e |
TRasterFxPort m_up, m_ref;
|
|
Shinya Kitaoka |
120a6e |
TDoubleParamP m_value;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
LocalBlurFx() : m_value(20) {
|
|
Shinya Kitaoka |
120a6e |
m_value->setMeasureName("fxLength");
|
|
Shinya Kitaoka |
120a6e |
addInputPort("Source", m_up);
|
|
Shinya Kitaoka |
120a6e |
addInputPort("Reference", m_ref);
|
|
Shinya Kitaoka |
120a6e |
bindParam(this, "value", m_value);
|
|
Shinya Kitaoka |
120a6e |
m_value->setValueRange(0, (std::numeric_limits<double>::max)());</double>
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
~LocalBlurFx() {}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
bool canHandle(const TRenderSettings &info, double frame) override {
|
|
Shinya Kitaoka |
120a6e |
return (isAlmostIsotropic(info.m_affine) || m_value->getValue(frame) == 0);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) override {
|
|
Shinya Kitaoka |
120a6e |
if (m_up.isConnected()) {
|
|
Shinya Kitaoka |
120a6e |
bool ret = m_up->doGetBBox(frame, bBox, info);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double blur = fabs(m_value->getValue(frame));
|
|
Shinya Kitaoka |
120a6e |
int blurI = tceil(blur);
|
|
Shinya Kitaoka |
120a6e |
bBox = bBox.enlarge(blurI);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return ret;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
bBox = TRectD();
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
void enlarge(const TRectD &bbox, TRectD &requestedRect, int blur);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
void doDryCompute(TRectD &rect, double frame, const TRenderSettings &info) override;
|
|
Shinya Kitaoka |
473e70 |
void doCompute(TTile &tile, double frame, const TRenderSettings &info) override;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int getMemoryRequirement(const TRectD &rect, double frame,
|
|
Shinya Kitaoka |
473e70 |
const TRenderSettings &info) override;
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void LocalBlurFx::enlarge(const TRectD &bbox, TRectD &requestedRect, int blur) {
|
|
Shinya Kitaoka |
120a6e |
// See BlurFx: this is a faithful replica
|
|
Shinya Kitaoka |
120a6e |
if (bbox.isEmpty() || requestedRect.isEmpty()) {
|
|
Shinya Kitaoka |
120a6e |
requestedRect.empty();
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRectD enlargedBBox(bbox.enlarge(blur));
|
|
Shinya Kitaoka |
120a6e |
TRectD enlargedOut(requestedRect.enlarge(blur));
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TPointD originalP00(requestedRect.getP00());
|
|
Shinya Kitaoka |
120a6e |
requestedRect = (enlargedOut * bbox) + (enlargedBBox * requestedRect);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
requestedRect -= originalP00;
|
|
Shinya Kitaoka |
120a6e |
requestedRect.x0 = tfloor(requestedRect.x0);
|
|
Shinya Kitaoka |
120a6e |
requestedRect.y0 = tfloor(requestedRect.y0);
|
|
Shinya Kitaoka |
120a6e |
requestedRect.x1 = tceil(requestedRect.x1);
|
|
Shinya Kitaoka |
120a6e |
requestedRect.y1 = tceil(requestedRect.y1);
|
|
Shinya Kitaoka |
120a6e |
requestedRect += originalP00;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void LocalBlurFx::doDryCompute(TRectD &rectOut, double frame,
|
|
Shinya Kitaoka |
120a6e |
const TRenderSettings &info) {
|
|
Shinya Kitaoka |
120a6e |
// Mimics the doCompute() without actual computation.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TTile refTile;
|
|
Shinya Kitaoka |
120a6e |
bool isUp = m_up.isConnected();
|
|
Shinya Kitaoka |
120a6e |
bool isDown = m_ref.isConnected();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (!isUp) return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (!isDown) {
|
|
Shinya Kitaoka |
120a6e |
m_up->dryCompute(rectOut, frame, info);
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
double blur =
|
|
Shinya Kitaoka |
120a6e |
fabs(m_value->getValue(frame) * sqrt(fabs(info.m_affine.det())));
|
|
Shinya Kitaoka |
120a6e |
int blurI = tceil(blur);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRectD bboxIn;
|
|
Shinya Kitaoka |
120a6e |
if (!m_up->getBBox(frame, bboxIn, info) || rectOut.isEmpty()) return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRectD rectIn(rectOut);
|
|
Shinya Kitaoka |
120a6e |
enlarge(bboxIn, rectIn, blurI);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (rectIn.isEmpty()) return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
m_up->dryCompute(rectOut, frame, info);
|
|
Shinya Kitaoka |
120a6e |
m_ref->dryCompute(rectOut, frame, info);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void LocalBlurFx::doCompute(TTile &tile, double frame,
|
|
Shinya Kitaoka |
120a6e |
const TRenderSettings &info) {
|
|
Shinya Kitaoka |
120a6e |
TTile refTile;
|
|
Shinya Kitaoka |
120a6e |
bool isUp = m_up.isConnected();
|
|
Shinya Kitaoka |
120a6e |
bool isDown = m_ref.isConnected();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!isUp) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!isDown) {
|
|
Shinya Kitaoka |
120a6e |
m_up->compute(tile, frame, info);
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Generic case
|
|
Shinya Kitaoka |
120a6e |
assert(isAlmostIsotropic(info.m_affine));
|
|
Shinya Kitaoka |
120a6e |
double blur =
|
|
Shinya Kitaoka |
120a6e |
fabs(m_value->getValue(frame) * sqrt(fabs(info.m_affine.det())));
|
|
Shinya Kitaoka |
120a6e |
int blurI = tceil(blur);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Get the requested tile's geometry
|
|
Shinya Kitaoka |
120a6e |
TRectD rectOut(tile.m_pos, TDimensionD(tile.getRaster()->getLx(),
|
|
Shinya Kitaoka |
120a6e |
tile.getRaster()->getLy()));
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Retrieve the input interesting geometry - and ensure that something
|
|
Shinya Kitaoka |
120a6e |
// actually has
|
|
Shinya Kitaoka |
120a6e |
// to be computed
|
|
Shinya Kitaoka |
120a6e |
TRectD bboxIn;
|
|
Shinya Kitaoka |
120a6e |
if (!m_up->getBBox(frame, bboxIn, info) || rectOut.isEmpty()) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRectD rectIn(rectOut);
|
|
Shinya Kitaoka |
120a6e |
enlarge(bboxIn, rectIn, blurI);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (rectIn.isEmpty()) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Finally, allocate and compute the blur argument
|
|
Shinya Kitaoka |
120a6e |
TTile tileIn;
|
|
Shinya Kitaoka |
120a6e |
m_up->allocateAndCompute(tileIn, rectIn.getP00(),
|
|
Shinya Kitaoka |
120a6e |
TDimension(rectIn.getLx(), rectIn.getLy()),
|
|
Shinya Kitaoka |
120a6e |
tile.getRaster(), frame, info);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TTile tileRef;
|
|
Shinya Kitaoka |
120a6e |
m_ref->allocateAndCompute(tileRef, rectIn.getP00(),
|
|
Shinya Kitaoka |
120a6e |
TDimension(rectIn.getLx(), rectIn.getLy()),
|
|
Shinya Kitaoka |
120a6e |
tile.getRaster(), frame, info);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Perform Local Blur
|
|
Shinya Kitaoka |
120a6e |
TRasterP inRas(tileIn.getRaster());
|
|
Shinya Kitaoka |
120a6e |
TRasterP refRas(tileRef.getRaster());
|
|
Shinya Kitaoka |
120a6e |
TRasterP outRas(tile.getRaster());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRaster32P in32(inRas);
|
|
Shinya Kitaoka |
120a6e |
TRaster32P ref32(refRas);
|
|
Shinya Kitaoka |
120a6e |
TRaster32P out32(outRas);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TPoint displacement(convert(
|
|
Shinya Kitaoka |
120a6e |
rectIn.getP00() - tile.m_pos)); // inTile position relative to (out)tile
|
|
Shinya Kitaoka |
120a6e |
// The difference already has integer coordinates due to enlarge()
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (in32 && ref32 && out32)
|
|
Shinya Kitaoka |
120a6e |
doLocalBlur<tpixelrgbm32, tpixelgr8="">(in32, ref32, out32, blur,</tpixelrgbm32,>
|
|
Shinya Kitaoka |
120a6e |
displacement);
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
TRaster64P in64(inRas);
|
|
Shinya Kitaoka |
120a6e |
TRaster64P ref64(refRas);
|
|
Shinya Kitaoka |
120a6e |
TRaster64P out64(outRas);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (in64 && ref64 && out64)
|
|
Shinya Kitaoka |
120a6e |
doLocalBlur<tpixelrgbm64, tpixelgr16="">(in64, ref64, out64, blur,</tpixelrgbm64,>
|
|
Shinya Kitaoka |
120a6e |
displacement);
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
throw TException("LocalBlurFx: unsupported raster type");
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
int LocalBlurFx::getMemoryRequirement(const TRectD &rect, double frame,
|
|
Shinya Kitaoka |
120a6e |
const TRenderSettings &info) {
|
|
Shinya Kitaoka |
120a6e |
double blur =
|
|
Shinya Kitaoka |
120a6e |
fabs(m_value->getValue(frame) * sqrt(fabs(info.m_affine.det())));
|
|
Shinya Kitaoka |
120a6e |
int blurI = tceil(blur);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return 2 * TRasterFx::memorySize(rect.enlarge(blurI), info.m_bpp);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
FX_PLUGIN_IDENTIFIER(LocalBlurFx, "localBlurFx")
|