|
Toshihiro Shimizu |
890ddd |
#include "texception.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tfxparam.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "trop.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "stdfx.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "trasterfx.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
class BlurFx : public TStandardRasterFx
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
FX_PLUGIN_DECLARATION(BlurFx)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRasterFxPort m_input;
|
|
Toshihiro Shimizu |
890ddd |
TDoubleParamP m_value;
|
|
Toshihiro Shimizu |
890ddd |
TBoolParamP m_useSSE;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
BlurFx() : m_value(20), m_useSSE(true)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_value->setMeasureName("fxLength");
|
|
Toshihiro Shimizu |
890ddd |
bindParam(this, "value", m_value);
|
|
Toshihiro Shimizu |
890ddd |
bindParam(this, "useSSE", m_useSSE, true);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
addInputPort("Source", m_input);
|
|
Toshihiro Shimizu |
890ddd |
m_value->setValueRange(0, std::numeric_limits<double>::max());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
~BlurFx(){};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_input.isConnected()) {
|
|
Toshihiro Shimizu |
890ddd |
bool ret = m_input->doGetBBox(frame, bBox, info);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double blur = fabs(m_value->getValue(frame));
|
|
Toshihiro Shimizu |
890ddd |
int brad = tceil(blur);
|
|
Toshihiro Shimizu |
890ddd |
bBox = bBox.enlarge(brad);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return ret;
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
bBox = TRectD();
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void enlarge(const TRectD &bbox, TRectD &requestedRect, int blur);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void transform(
|
|
Toshihiro Shimizu |
890ddd |
double frame,
|
|
Toshihiro Shimizu |
890ddd |
int port,
|
|
Toshihiro Shimizu |
890ddd |
const TRectD &rectOnOutput,
|
|
Toshihiro Shimizu |
890ddd |
const TRenderSettings &infoOnOutput,
|
|
Toshihiro Shimizu |
890ddd |
TRectD &rectOnInput,
|
|
Toshihiro Shimizu |
890ddd |
TRenderSettings &infoOnInput);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void doCompute(TTile &tile, double frame, const TRenderSettings &);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int getMemoryRequirement(const TRectD &rect, double frame, const TRenderSettings &info);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool canHandle(const TRenderSettings &info, double frame)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_value->getValue(frame) == 0)
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
return (isAlmostIsotropic(info.m_affine));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
FX_PLUGIN_IDENTIFIER(BlurFx, "blurFx")
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//!Calculates the geometry we need for this node computation, given
|
|
Toshihiro Shimizu |
890ddd |
//!the known input data (bbox), the requested output (requestedRect) and the blur factor.
|
|
Toshihiro Shimizu |
890ddd |
void BlurFx::enlarge(const TRectD &bbox, TRectD &requestedRect, int blur)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (bbox.isEmpty() || requestedRect.isEmpty()) {
|
|
Toshihiro Shimizu |
890ddd |
requestedRect.empty();
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//We are to find out the geometry that is useful for the fx computation.
|
|
Toshihiro Shimizu |
890ddd |
//There are some rules to follow:
|
|
Toshihiro Shimizu |
890ddd |
// a) First, the interesting output we can generate is bounded by both
|
|
Toshihiro Shimizu |
890ddd |
// the requestedRect and the blurred bbox (i.e. enlarged by the blur radius).
|
|
Toshihiro Shimizu |
890ddd |
// b) Pixels contributing to any output are necessarily part of bbox - and only
|
|
Toshihiro Shimizu |
890ddd |
// those which are blurrable into the requestedRect are useful to us
|
|
Toshihiro Shimizu |
890ddd |
// (i.e. pixels contained in its enlargement by the blur radius).
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRectD enlargedBBox(bbox.enlarge(blur));
|
|
Toshihiro Shimizu |
890ddd |
TRectD enlargedOut(requestedRect.enlarge(blur));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPointD originalP00(requestedRect.getP00());
|
|
Toshihiro Shimizu |
890ddd |
requestedRect = (enlargedOut * bbox) + (enlargedBBox * requestedRect);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Finally, make sure that the result is coherent with the original P00
|
|
Toshihiro Shimizu |
890ddd |
requestedRect -= originalP00;
|
|
Toshihiro Shimizu |
890ddd |
requestedRect.x0 = tfloor(requestedRect.x0);
|
|
Toshihiro Shimizu |
890ddd |
requestedRect.y0 = tfloor(requestedRect.y0);
|
|
Toshihiro Shimizu |
890ddd |
requestedRect.x1 = tceil(requestedRect.x1);
|
|
Toshihiro Shimizu |
890ddd |
requestedRect.y1 = tceil(requestedRect.y1);
|
|
Toshihiro Shimizu |
890ddd |
requestedRect += originalP00;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void BlurFx::transform(
|
|
Toshihiro Shimizu |
890ddd |
double frame,
|
|
Toshihiro Shimizu |
890ddd |
int port,
|
|
Toshihiro Shimizu |
890ddd |
const TRectD &rectOnOutput,
|
|
Toshihiro Shimizu |
890ddd |
const TRenderSettings &infoOnOutput,
|
|
Toshihiro Shimizu |
890ddd |
TRectD &rectOnInput,
|
|
Toshihiro Shimizu |
890ddd |
TRenderSettings &infoOnInput)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
infoOnInput = infoOnOutput;
|
|
Toshihiro Shimizu |
890ddd |
rectOnInput = rectOnOutput;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double blur = fabs(m_value->getValue(frame) * sqrt(fabs(infoOnOutput.m_affine.det())));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (blur == 0) {
|
|
Toshihiro Shimizu |
890ddd |
rectOnInput = rectOnOutput;
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int brad = tceil(blur);
|
|
Toshihiro Shimizu |
890ddd |
TRectD bbox;
|
|
Toshihiro Shimizu |
890ddd |
m_input->getBBox(frame, bbox, infoOnInput);
|
|
Toshihiro Shimizu |
890ddd |
enlarge(bbox, rectOnInput, brad);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int BlurFx::getMemoryRequirement(const TRectD &rect, double frame, const TRenderSettings &info)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
double blurValue = fabs(m_value->getValue(frame) * sqrt(fabs(info.m_affine.det())));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (blurValue == 0.0)
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int brad = tceil(blurValue);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Trop::blur is quite inefficient at the moment - it has to allocate a whole
|
|
Toshihiro Shimizu |
890ddd |
//raster of the same size of the input/output made of FLOAT QUADRUPLES...!
|
|
Toshihiro Shimizu |
890ddd |
return TRasterFx::memorySize(rect.enlarge(brad), sizeof(float) << 5);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void BlurFx::doCompute(
|
|
Toshihiro Shimizu |
890ddd |
TTile &tile,
|
|
Toshihiro Shimizu |
890ddd |
double frame,
|
|
Toshihiro Shimizu |
890ddd |
const TRenderSettings &renderSettings)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!m_input.isConnected())
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double shrink = 0.5 * (renderSettings.m_shrinkX + renderSettings.m_shrinkY);
|
|
Toshihiro Shimizu |
890ddd |
// Note: shrink is obsolete. It should be always = 1
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double blurValue = fabs(m_value->getValue(frame) * sqrt(fabs(renderSettings.m_affine.det())) / shrink);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (blurValue == 0) {
|
|
Toshihiro Shimizu |
890ddd |
//No blur will be done. The underlying fx may pass by.
|
|
Toshihiro Shimizu |
890ddd |
m_input->compute(tile, frame, renderSettings);
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int brad = tceil(blurValue);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Get the requested tile's geometry
|
|
Toshihiro Shimizu |
890ddd |
TRectD rectIn, rectOut;
|
|
Toshihiro Shimizu |
890ddd |
rectOut = TRectD(
|
|
Toshihiro Shimizu |
890ddd |
tile.m_pos, TDimensionD(tile.getRaster()->getLx(), tile.getRaster()->getLy()));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Retrieve the input interesting geometry - and ensure that something actually has
|
|
Toshihiro Shimizu |
890ddd |
//to be computed
|
|
Toshihiro Shimizu |
890ddd |
if (!m_input->getBBox(frame, rectIn, renderSettings) || rectOut.isEmpty())
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
enlarge(rectIn, rectOut, brad);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (rectOut.isEmpty())
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Finally, allocate and compute the blur argument
|
|
Toshihiro Shimizu |
890ddd |
TTile tileIn;
|
|
Toshihiro Shimizu |
890ddd |
m_input->allocateAndCompute(
|
|
Toshihiro Shimizu |
890ddd |
tileIn, rectOut.getP00(), TDimension(rectOut.getLx(), rectOut.getLy()),
|
|
Toshihiro Shimizu |
890ddd |
tile.getRaster(), frame, renderSettings);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPointD displacement(rectOut.getP00() - tile.m_pos);
|
|
Toshihiro Shimizu |
890ddd |
TRop::blur(tile.getRaster(), tileIn.getRaster(), blurValue, displacement.x, displacement.y, false);
|
|
Toshihiro Shimizu |
890ddd |
}
|