Fix for
authorJeroen Bakker <j.bakker@atmind.nl>
Thu, 19 Jul 2012 11:05:18 +0000 (11:05 +0000)
committerJeroen Bakker <j.bakker@atmind.nl>
Thu, 19 Jul 2012 11:05:18 +0000 (11:05 +0000)
 * [#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 -

source/blender/compositor/nodes/COM_BlurNode.cpp
source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp
source/blender/compositor/operations/COM_GaussianBokehBlurOperation.h
source/blender/editors/space_node/drawnode.c
source/blender/makesdna/DNA_node_types.h
source/blender/makesrna/intern/rna_nodetree.c

index 5447652c238a5af65640259ae066dc38ce33fd2a..9b945887ec2e0e1020950f2936e6b3580f26ca0f 100644 (file)
 #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);
index 93cc39849a29cea0c7e44b36fb7657a8e71a9476..fd70d0d329a15e3e999ab13c6c6196e8fe95110b 100644 (file)
@@ -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);
index 1a134c20e630385557621b43c7d1b6a85e8a43a7..4514085546487a177b293ef85f9445c4b9a287c6 100644 (file)
@@ -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
index 87a07407ee6f74b5025df64d9eb2ebb5bbaf8617..134b2d6fd990972ca7ae75e320b78dbfaf40afb0 100644 (file)
@@ -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);
        }
        
index 1e2f6eabce69c94039ae70af3fab1c3c5ae7d337..a7f854f603cd22bb7fc78a8e13251fa01a056981 100644 (file)
@@ -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;
index a72059063fd9e1455eb2154c664acf1aedecd8c4..055c8dcbebbdaee624e2e9423ac4161755fd68f7 100644 (file)
@@ -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)