Compositor: Add option to extend image bounds when blurring

It is handy when doing some roto work and it's required to blur some
mask or overaly before alpha-overing it on top of the footage.

Quite straightforward option with the only limitation that variable
size blur is not supported.

Reviewers: campbellbarton

Subscribers: hype, sebastian_k

Differential Revision: https://developer.blender.org/D1663
This commit is contained in:
Sergey Sharybin 2015-12-09 19:31:39 +05:00
parent 73feae6f5d
commit cc55f97da9
9 changed files with 68 additions and 6 deletions

View File

@ -46,13 +46,15 @@ void BlurNode::convertToOperations(NodeConverter &converter, const CompositorCon
bool connectedSizeSocket = inputSizeSocket->isLinked();
const float size = this->getInputSocket(1)->getEditorValueFloat();
const bool extend_bounds = (editorNode->custom1 & CMP_NODEFLAG_BLUR_EXTEND_BOUNDS) != 0;
CompositorQuality quality = context.getQuality();
NodeOperation *input_operation = NULL, *output_operation = NULL;
if (data->filtertype == R_FILTER_FAST_GAUSS) {
FastGaussianBlurOperation *operationfgb = new FastGaussianBlurOperation();
operationfgb->setData(data);
operationfgb->setExtendBounds(extend_bounds);
converter.addOperation(operationfgb);
converter.mapInputSocket(getInputSocket(1), operationfgb->getInputSocket(1));
@ -77,6 +79,7 @@ void BlurNode::convertToOperations(NodeConverter &converter, const CompositorCon
operationx->setSize(1.0f);
operationx->setFalloff(PROP_SMOOTH);
operationx->setSubtract(false);
operationx->setExtendBounds(extend_bounds);
converter.addOperation(operationx);
converter.addLink(clamp->getOutputSocket(), operationx->getInputSocket(0));
@ -87,14 +90,16 @@ void BlurNode::convertToOperations(NodeConverter &converter, const CompositorCon
operationy->setSize(1.0f);
operationy->setFalloff(PROP_SMOOTH);
operationy->setSubtract(false);
operationy->setExtendBounds(extend_bounds);
converter.addOperation(operationy);
converter.addLink(operationx->getOutputSocket(), operationy->getInputSocket(0));
GaussianBlurReferenceOperation *operation = new GaussianBlurReferenceOperation();
operation->setData(data);
operation->setQuality(quality);
operation->setExtendBounds(extend_bounds);
converter.addOperation(operation);
converter.addLink(operationy->getOutputSocket(), operation->getInputSocket(1));
@ -106,7 +111,8 @@ void BlurNode::convertToOperations(NodeConverter &converter, const CompositorCon
operationx->setData(data);
operationx->setQuality(quality);
operationx->checkOpenCL();
operationx->setExtendBounds(extend_bounds);
converter.addOperation(operationx);
converter.mapInputSocket(getInputSocket(1), operationx->getInputSocket(1));
@ -114,6 +120,7 @@ void BlurNode::convertToOperations(NodeConverter &converter, const CompositorCon
operationy->setData(data);
operationy->setQuality(quality);
operationy->checkOpenCL();
operationy->setExtendBounds(extend_bounds);
converter.addOperation(operationy);
converter.mapInputSocket(getInputSocket(1), operationy->getInputSocket(1));
@ -131,7 +138,8 @@ void BlurNode::convertToOperations(NodeConverter &converter, const CompositorCon
GaussianBokehBlurOperation *operation = new GaussianBokehBlurOperation();
operation->setData(data);
operation->setQuality(quality);
operation->setExtendBounds(extend_bounds);
converter.addOperation(operation);
converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));

View File

@ -41,6 +41,7 @@ void BokehBlurNode::convertToOperations(NodeConverter &converter, const Composit
NodeInput *inputSizeSocket = this->getInputSocket(2);
bool connectedSizeSocket = inputSizeSocket->isLinked();
const bool extend_bounds = (b_node->custom1 & CMP_NODEFLAG_BLUR_EXTEND_BOUNDS) != 0;
if ((b_node->custom1 & CMP_NODEFLAG_BLUR_VARIABLE_SIZE) && connectedSizeSocket) {
VariableSizeBokehBlurOperation *operation = new VariableSizeBokehBlurOperation();
@ -58,6 +59,7 @@ void BokehBlurNode::convertToOperations(NodeConverter &converter, const Composit
else {
BokehBlurOperation *operation = new BokehBlurOperation();
operation->setQuality(context.getQuality());
operation->setExtendBounds(extend_bounds);
converter.addOperation(operation);
converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0));

View File

@ -39,6 +39,7 @@ BlurBaseOperation::BlurBaseOperation(DataType data_type) : NodeOperation()
memset(&m_data, 0, sizeof(NodeBlurData));
this->m_size = 1.0f;
this->m_sizeavailable = false;
this->m_extend_bounds = false;
}
void BlurBaseOperation::initExecution()
{
@ -174,3 +175,14 @@ void BlurBaseOperation::updateSize()
this->m_sizeavailable = true;
}
}
void BlurBaseOperation::determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2])
{
NodeOperation::determineResolution(resolution,
preferredResolution);
if (this->m_extend_bounds) {
resolution[0] += 2 * this->m_size * m_data.sizex;
resolution[1] += 2 * this->m_size * m_data.sizey;
}
}

View File

@ -55,6 +55,8 @@ protected:
float m_size;
bool m_sizeavailable;
bool m_extend_bounds;
public:
/**
* Initialize the execution
@ -69,5 +71,10 @@ public:
void setData(const NodeBlurData *data);
void setSize(float size) { this->m_size = size; this->m_sizeavailable = true; }
void setExtendBounds(bool extend_bounds) { this->m_extend_bounds = extend_bounds; }
void determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2]);
};
#endif

View File

@ -43,6 +43,8 @@ BokehBlurOperation::BokehBlurOperation() : NodeOperation()
this->m_inputProgram = NULL;
this->m_inputBokehProgram = NULL;
this->m_inputBoundingBoxReader = NULL;
this->m_extend_bounds = false;
}
void *BokehBlurOperation::initializeTileData(rcti * /*rect*/)
@ -226,3 +228,15 @@ void BokehBlurOperation::updateSize()
this->m_sizeavailable = true;
}
}
void BokehBlurOperation::determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2])
{
NodeOperation::determineResolution(resolution,
preferredResolution);
if (this->m_extend_bounds) {
const float max_dim = max(resolution[0], resolution[1]);
resolution[0] += 2 * this->m_size * max_dim / 100.0f;
resolution[1] += 2 * this->m_size * max_dim / 100.0f;
}
}

View File

@ -37,6 +37,7 @@ private:
float m_bokehMidX;
float m_bokehMidY;
float m_bokehDimension;
bool m_extend_bounds;
public:
BokehBlurOperation();
@ -64,5 +65,10 @@ public:
MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp,
list<cl_kernel> *clKernelsToCleanUp);
void setExtendBounds(bool extend_bounds) { this->m_extend_bounds = extend_bounds; }
void determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2]);
};
#endif

View File

@ -1374,6 +1374,7 @@ static void node_composit_buts_blur(uiLayout *layout, bContext *UNUSED(C), Point
uiItemR(col, ptr, "size_x", 0, IFACE_("X"), ICON_NONE);
uiItemR(col, ptr, "size_y", 0, IFACE_("Y"), ICON_NONE);
}
uiItemR(col, ptr, "use_extended_bounds", 0, NULL, ICON_NONE);
}
static void node_composit_buts_dblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@ -2207,6 +2208,7 @@ static void node_composit_buts_bokehblur(uiLayout *layout, bContext *UNUSED(C),
uiItemR(layout, ptr, "use_variable_size", 0, NULL, ICON_NONE);
// uiItemR(layout, ptr, "f_stop", 0, NULL, ICON_NONE); // UNUSED
uiItemR(layout, ptr, "blur_max", 0, NULL, ICON_NONE);
uiItemR(layout, ptr, "use_extended_bounds", 0, NULL, ICON_NONE);
}
static void node_composit_backdrop_viewer(SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y)

View File

@ -503,7 +503,8 @@ enum {
};
enum {
CMP_NODEFLAG_BLUR_VARIABLE_SIZE = (1 << 0)
CMP_NODEFLAG_BLUR_VARIABLE_SIZE = (1 << 0),
CMP_NODEFLAG_BLUR_EXTEND_BOUNDS = (1 << 1),
};
typedef struct NodeFrame {

View File

@ -4376,6 +4376,11 @@ static void def_cmp_blur(StructRNA *srna)
RNA_def_property_ui_text(prop, "Variable Size", "Support variable blur per-pixel when using an image for size input");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "use_extended_bounds", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "custom1", CMP_NODEFLAG_BLUR_EXTEND_BOUNDS);
RNA_def_property_ui_text(prop, "Extend Bounds", "Extend bounds of the input image to fully fit blurred image");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
RNA_def_struct_sdna_from(srna, "NodeBlurData", "storage");
prop = RNA_def_property(srna, "size_x", PROP_INT, PROP_NONE);
@ -6098,6 +6103,11 @@ static void def_cmp_bokehblur(StructRNA *srna)
"Support variable blur per-pixel when using an image for size input");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "use_extended_bounds", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "custom1", CMP_NODEFLAG_BLUR_EXTEND_BOUNDS);
RNA_def_property_ui_text(prop, "Extend Bounds", "Extend bounds of the input image to fully fit blurred image");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
#if 0
prop = RNA_def_property(srna, "f_stop", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "custom3");