diff options
author | Jeroen Bakker <j.bakker@atmind.nl> | 2012-07-19 15:05:18 +0400 |
---|---|---|
committer | Jeroen Bakker <j.bakker@atmind.nl> | 2012-07-19 15:05:18 +0400 |
commit | a56f4fee38e17d05964941a5edc2850c217309d7 (patch) | |
tree | e4430faf6ff15aa037f6d8fb1ede5f0afac6a376 /source | |
parent | 9c8edae7d4ef799b19f6487feb21ce7fbcf5ee07 (diff) |
Fix for
* [#32040] size-input of a blur-node is uniform for the whole picture
* [#32062] Blur node Size input is not working with
* [#32140] Blur Node using a greyscale input as size multiplier fails
to work
Node now has a new option (new compositor cannot detect if the connected
part is a single value, or an image connected).
With this option the use of a reference image to multiply the size of
the blur per pixel can be enabled/disabled.
Regards,
Jeroen
- At Mind -
Diffstat (limited to 'source')
6 files changed, 153 insertions, 103 deletions
diff --git a/source/blender/compositor/nodes/COM_BlurNode.cpp b/source/blender/compositor/nodes/COM_BlurNode.cpp index 5447652c238..9b945887ec2 100644 --- a/source/blender/compositor/nodes/COM_BlurNode.cpp +++ b/source/blender/compositor/nodes/COM_BlurNode.cpp @@ -25,9 +25,13 @@ #include "DNA_node_types.h" #include "COM_GaussianXBlurOperation.h" #include "COM_GaussianYBlurOperation.h" +#include "COM_GaussianAlphaXBlurOperation.h" +#include "COM_GaussianAlphaYBlurOperation.h" #include "COM_ExecutionSystem.h" #include "COM_GaussianBokehBlurOperation.h" #include "COM_FastGaussianBlurOperation.h" +#include "COM_MathBaseOperation.h" +#include "COM_SetValueOperation.h" BlurNode::BlurNode(bNode *editorNode) : Node(editorNode) { @@ -56,6 +60,42 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co graph->addOperation(operationfgb); addPreviewOperation(graph, operationfgb->getOutputSocket()); } + else if (editorNode->custom1 & CMP_NODEFLAG_BLUR_REFERENCE) { + MathAddOperation *clamp = new MathAddOperation(); + SetValueOperation *zero = new SetValueOperation(); + addLink(graph, zero->getOutputSocket(), clamp->getInputSocket(1)); + this->getInputSocket(1)->relinkConnections(clamp->getInputSocket(0), 1, graph); + zero->setValue(0.0f); + clamp->setUseClamp(true); + graph->addOperation(clamp); + graph->addOperation(zero); + + GaussianAlphaXBlurOperation *operationx = new GaussianAlphaXBlurOperation(); + operationx->setData(data); + operationx->setbNode(editorNode); + operationx->setQuality(quality); + operationx->setSize(1.0f); + addLink(graph, clamp->getOutputSocket(), operationx->getInputSocket(0)); + graph->addOperation(operationx); + + GaussianYBlurOperation *operationy = new GaussianYBlurOperation(); + operationy->setData(data); + operationy->setbNode(editorNode); + operationy->setQuality(quality); + operationy->setSize(1.0f); + addLink(graph, operationx->getOutputSocket(), operationy->getInputSocket(0)); + graph->addOperation(operationy); + + GaussianBlurReferenceOperation *operation = new GaussianBlurReferenceOperation(); + operation->setData(data); + operation->setbNode(editorNode); + operation->setQuality(quality); + this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph); + addLink(graph, operationy->getOutputSocket(), operation->getInputSocket(1)); + graph->addOperation(operation); + this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket()); + addPreviewOperation(graph, operation->getOutputSocket()); + } else if (!data->bokeh) { GaussianXBlurOperation *operationx = new GaussianXBlurOperation(); operationx->setData(data); diff --git a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp index 93cc39849a2..fd70d0d329a 100644 --- a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp @@ -22,7 +22,7 @@ #include "COM_GaussianBokehBlurOperation.h" #include "BLI_math.h" - +#include "MEM_guardedalloc.h" extern "C" { #include "RE_pipeline.h" } @@ -198,25 +198,20 @@ bool GaussianBokehBlurOperation::determineDependingAreaOfInterest(rcti *input, R } // reference image -GaussianBokehBlurReferenceOperation::GaussianBokehBlurReferenceOperation() : NodeOperation() +GaussianBlurReferenceOperation::GaussianBlurReferenceOperation() : BlurBaseOperation(COM_DT_COLOR) { - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_COLOR); - this->setComplex(true); - this->m_gausstab = NULL; - this->m_inputImage = NULL; - this->m_inputSize = NULL; + this->m_maintabs = NULL; } -void *GaussianBokehBlurReferenceOperation::initializeTileData(rcti *rect) +void *GaussianBlurReferenceOperation::initializeTileData(rcti *rect) { void *buffer = getInputOperation(0)->initializeTileData(NULL); return buffer; } -void GaussianBokehBlurReferenceOperation::initExecution() +void GaussianBlurReferenceOperation::initExecution() { + BlurBaseOperation::initExecution(); // setup gaustab this->m_data->image_in_width = this->getWidth(); this->m_data->image_in_height = this->getHeight(); @@ -237,100 +232,106 @@ void GaussianBokehBlurReferenceOperation::initExecution() } } + + /* horizontal */ + m_radx = (float)this->m_data->sizex; + int imgx = getWidth()/2; + if (m_radx > imgx) + m_radx = imgx; + else if (m_radx < 1) + m_radx = 1; + m_radxf = (float)m_radx; + + /* vertical */ + m_rady = (float)this->m_data->sizey; + int imgy = getHeight()/2; + if (m_rady > imgy) + m_rady = imgy; + else if (m_rady < 1) + m_rady = 1; + m_radyf = (float)m_rady; updateGauss(); - this->m_inputImage = this->getInputSocketReader(0); - this->m_inputSize = this->getInputSocketReader(1); } -void GaussianBokehBlurReferenceOperation::updateGauss() +void GaussianBlurReferenceOperation::updateGauss() { - int n; - float *dgauss; - float *ddgauss; - int j, i; - - n = (2 * radx + 1) * (2 * rady + 1); - - /* create a full filter image */ - ddgauss = new float[n]; - dgauss = ddgauss; - for (j = -rady; j <= rady; j++) { - for (i = -radx; i <= radx; i++, dgauss++) { - float fj = (float)j / radyf; - float fi = (float)i / radxf; - float dist = sqrt(fj * fj + fi * fi); - *dgauss = RE_filter_value(this->m_data->filtertype, dist); - } - } - this->m_gausstab = ddgauss; + int i; + int x = MAX2(m_radx, m_rady); + this->m_maintabs = (float**)MEM_mallocN(x * sizeof(float *), "gauss array"); + for (i = 0; i < x; i++) + m_maintabs[i] = make_gausstab(i + 1); } -void GaussianBokehBlurReferenceOperation::executePixel(float *color, int x, int y, void *data) +void GaussianBlurReferenceOperation::executePixel(float *color, int x, int y, void *data) { - float tempColor[4]; + MemoryBuffer *memorybuffer = (MemoryBuffer*)data; + float *buffer = memorybuffer->getBuffer(); + float *gausstabx, *gausstabcenty; + float *gausstaby, *gausstabcentx; + int i, j; + float *src; + register float sum, val; + float rval, gval, bval, aval; + int imgx = getWidth(); + int imgy = getHeight(); float tempSize[4]; - tempColor[0] = 0; - tempColor[1] = 0; - tempColor[2] = 0; - tempColor[3] = 0; - float multiplier_accum = 0; - MemoryBuffer *inputBuffer = (MemoryBuffer *)data; - float *buffer = inputBuffer->getBuffer(); - int bufferwidth = inputBuffer->getWidth(); - int bufferstartx = inputBuffer->getRect()->xmin; - int bufferstarty = inputBuffer->getRect()->ymin; this->m_inputSize->read(tempSize, x, y, data); - float size = tempSize[0]; - CLAMP(size, 0.0f, 1.0f); - float sizeX = ceil(this->m_data->sizex * size); - float sizeY = ceil(this->m_data->sizey * size); + float refSize = tempSize[0]; + int refradx = (int)(refSize * m_radxf); + int refrady = (int)(refSize * m_radyf); + if (refradx > m_radx) refradx = m_radx; + else if (refradx < 1) refradx = 1; + if (refrady > m_rady) refrady = m_rady; + else if (refrady < 1) refrady = 1; - if (sizeX <= 0.5f && sizeY <= 0.5f) { - this->m_inputImage->read(color, x, y, data); - return; - } - - int miny = y - sizeY; - int maxy = y + sizeY; - int minx = x - sizeX; - int maxx = x + sizeX; - miny = max(miny, inputBuffer->getRect()->ymin); - minx = max(minx, inputBuffer->getRect()->xmin); - maxy = min(maxy, inputBuffer->getRect()->ymax); - maxx = min(maxx, inputBuffer->getRect()->xmax); + if (refradx == 1 && refrady == 1) { + memorybuffer->readNoCheck(color, x, y); + } else { + int minxr = x - refradx < 0 ? -x : -refradx; + int maxxr = x + refradx > imgx ? imgx - x : refradx; + int minyr = y - refrady < 0 ? -y : -refrady; + int maxyr = y + refrady > imgy ? imgy - y : refrady; - int step = QualityStepHelper::getStep(); - int offsetadd = QualityStepHelper::getOffsetAdd(); - for (int ny = miny; ny < maxy; ny += step) { - int u = ny - y; - float uf = ((u/sizeY)*radyf)+radyf; - int indexu = uf * (radx*2+1); - int bufferindex = ((minx - bufferstartx) * 4) + ((ny - bufferstarty) * 4 * bufferwidth); - for (int nx = minx; nx < maxx; nx += step) { - int v = nx - x; - float vf = ((v/sizeX)*radxf)+radxf; - int index = indexu + vf; - const float multiplier = this->m_gausstab[index]; - madd_v4_v4fl(tempColor, &buffer[bufferindex], multiplier); - multiplier_accum += multiplier; - index += step; - bufferindex += offsetadd; + float *srcd = buffer + COM_NUMBER_OF_CHANNELS * ( (y + minyr) * imgx + x + minxr); + + gausstabx = m_maintabs[refradx - 1]; + gausstabcentx = gausstabx + refradx; + gausstaby = m_maintabs[refrady - 1]; + gausstabcenty = gausstaby + refrady; + + sum = gval = rval = bval = aval = 0.0f; + for (i = minyr; i < maxyr; i++, srcd += COM_NUMBER_OF_CHANNELS * imgx) { + src = srcd; + for (j = minxr; j < maxxr; j++, src += COM_NUMBER_OF_CHANNELS) { + + val = gausstabcenty[i] * gausstabcentx[j]; + sum += val; + rval += val * src[0]; + gval += val * src[1]; + bval += val * src[2]; + aval += val * src[3]; + } } + sum = 1.0f / sum; + color[0] = rval * sum; + color[1] = gval * sum; + color[2] = bval * sum; + color[3] = aval * sum; } - mul_v4_v4fl(color, tempColor, 1.0f / multiplier_accum); } -void GaussianBokehBlurReferenceOperation::deinitExecution() +void GaussianBlurReferenceOperation::deinitExecution() { - delete [] this->m_gausstab; - this->m_gausstab = NULL; - this->m_inputImage = NULL; - this->m_inputSize = NULL; - + int x, i; + x = MAX2(m_radx, m_rady); + for (i = 0; i < x; i++) + delete []m_maintabs[i]; + MEM_freeN(m_maintabs); + BlurBaseOperation::deinitExecution(); } -bool GaussianBokehBlurReferenceOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool GaussianBlurReferenceOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) { rcti newInput; NodeOperation *operation = this->getInputOperation(1); diff --git a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.h b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.h index 1a134c20e63..45140855464 100644 --- a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.h +++ b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.h @@ -49,22 +49,18 @@ public: bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); }; -class GaussianBokehBlurReferenceOperation : public NodeOperation, public QualityStepHelper { +class GaussianBlurReferenceOperation : public BlurBaseOperation { private: - SocketReader * m_inputImage; - SocketReader * m_inputSize; - float *m_gausstab; - NodeBlurData *m_data; + float **m_maintabs; void updateGauss(); + int m_radx; + int m_rady; + float m_radxf; + float m_radyf; - static const int radxf = 256.0f; - static const int radyf = 256.0f; - static const int radx = 256; - static const int rady = 256; - public: - GaussianBokehBlurReferenceOperation(); + GaussianBlurReferenceOperation(); void initExecution(); void *initializeTileData(rcti *rect); /** @@ -78,8 +74,6 @@ public: void deinitExecution(); bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - - void setData(NodeBlurData *data) { this->m_data = data; } }; #endif diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 87a07407ee6..134b2d6fd99 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1528,12 +1528,19 @@ static void node_composit_buts_renderlayers(uiLayout *layout, bContext *C, Point static void node_composit_buts_blur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiLayout *col, *row; + int reference; + int filter; col = uiLayoutColumn(layout, FALSE); - + filter = RNA_enum_get(ptr, "filter_type"); + reference = RNA_boolean_get(ptr, "use_reference"); + uiItemR(col, ptr, "filter_type", 0, "", ICON_NONE); - if (RNA_enum_get(ptr, "filter_type") != R_FILTER_FAST_GAUSS) { - uiItemR(col, ptr, "use_bokeh", 0, NULL, ICON_NONE); + if (filter != R_FILTER_FAST_GAUSS) { + uiItemR(col, ptr, "use_reference", 0, NULL, ICON_NONE); + if (!reference) { + uiItemR(col, ptr, "use_bokeh", 0, NULL, ICON_NONE); + } uiItemR(col, ptr, "use_gamma_correction", 0, NULL, ICON_NONE); } diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 1e2f6eabce6..a7f854f603c 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -374,6 +374,10 @@ enum { CMP_NODEFLAG_MASK_NO_FEATHER = (1 << 1) }; +enum { + CMP_NODEFLAG_BLUR_REFERENCE = (1 << 0), +}; + typedef struct NodeFrame { short flag; short label_size; diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index a72059063fd..055c8dcbebb 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -1713,6 +1713,11 @@ static void def_cmp_blur(StructRNA *srna) {0, NULL, 0, NULL, NULL} }; + prop = RNA_def_property(srna, "use_reference", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "custom1", CMP_NODEFLAG_BLUR_REFERENCE); + RNA_def_property_ui_text(prop, "Reference", "Use size socket as a reference 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); @@ -1771,7 +1776,6 @@ static void def_cmp_blur(StructRNA *srna) RNA_def_property_boolean_sdna(prop, NULL, "gamma", 1); RNA_def_property_ui_text(prop, "Gamma", "Apply filter on gamma corrected values"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - } static void def_cmp_filter(StructRNA *srna) |