Fix various compiler warnings.
[blender-staging.git] / source / blender / compositor / operations / COM_GaussianBokehBlurOperation.cpp
index b38ed28cd6ad499b289e654c9c849aace0a42c1c..7c4132238e349016815eabd5782406a71f5b4e7f 100644 (file)
 
 #include "COM_GaussianBokehBlurOperation.h"
 #include "BLI_math.h"
-
+#include "MEM_guardedalloc.h"
 extern "C" {
-       #include "RE_pipeline.h"
+#  include "RE_pipeline.h"
 }
 
-GaussianBokehBlurOperation::GaussianBokehBlurOperation() : BlurBaseOperation()
+GaussianBokehBlurOperation::GaussianBokehBlurOperation() : BlurBaseOperation(COM_DT_COLOR)
 {
-       this->gausstab = NULL;
+       this->m_gausstab = NULL;
 }
 
-void *GaussianBokehBlurOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers)
+void *GaussianBokehBlurOperation::initializeTileData(rcti * /*rect*/)
 {
-       if (!sizeavailable) {
-               updateGauss(memoryBuffers);
+       lockMutex();
+       if (!this->m_sizeavailable) {
+               updateGauss();
        }
-       void *buffer = getInputOperation(0)->initializeTileData(NULL, memoryBuffers);
+       void *buffer = getInputOperation(0)->initializeTileData(NULL);
+       unlockMutex();
        return buffer;
 }
 
@@ -45,115 +47,123 @@ void GaussianBokehBlurOperation::initExecution()
 {
        BlurBaseOperation::initExecution();
 
-       if (this->sizeavailable) {
-               updateGauss(NULL);
+       initMutex();
+
+       if (this->m_sizeavailable) {
+               updateGauss();
        }
 }
 
-void GaussianBokehBlurOperation::updateGauss(MemoryBuffer **memoryBuffers)
+void GaussianBokehBlurOperation::updateGauss()
 {
-       if (this->gausstab == NULL) {
+       if (this->m_gausstab == NULL) {
                float radxf;
                float radyf;
                int n;
                float *dgauss;
                float *ddgauss;
-               float val;
                int j, i;
                const float width = this->getWidth();
                const float height = this->getHeight();
-               if (!sizeavailable) {
-                       updateSize(memoryBuffers);
+               if (!this->m_sizeavailable) {
+                       updateSize();
                }
-               radxf = size * (float)this->data->sizex;
-               if (radxf > width / 2.0f)
-                       radxf = width / 2.0f;
-               else if (radxf < 1.0f)
-                       radxf = 1.0f;
+               radxf = this->m_size * (float)this->m_data.sizex;
+               CLAMP(radxf, 0.0f, width / 2.0f);
        
                /* vertical */
-               radyf = size * (float)this->data->sizey;
-               if (radyf > height / 2.0f)
-                       radyf = height / 2.0f;
-               else if (radyf < 1.0f)
-                       radyf = 1.0f;
+               radyf = this->m_size * (float)this->m_data.sizey;
+               CLAMP(radyf, 0.0f, height / 2.0f);
        
-               radx = ceil(radxf);
-               rady = ceil(radyf);
-       
-               n = (2 * radx + 1) * (2 * rady + 1);
+               this->m_radx = ceil(radxf);
+               this->m_rady = ceil(radyf);
+               
+               int ddwidth = 2 * this->m_radx + 1;
+               int ddheight = 2 * this->m_rady + 1;
+               n = ddwidth * ddheight;
        
                /* create a full filter image */
-               ddgauss = new float[n];
+               ddgauss = (float *)MEM_mallocN(sizeof(float) * n, __func__);
                dgauss = ddgauss;
-               val = 0.0f;
-               for (j = -rady; j <= rady; j++) {
-                       for (i = -radx; i <= radx; i++, dgauss++) {
-                               float fj = (float)j / radyf;
-                               float fi = (float)i / radxf;
+               float sum = 0.0f;
+               float facx = (radxf > 0.0f ? 1.0f / radxf : 0.0f);
+               float facy = (radyf > 0.0f ? 1.0f / radyf : 0.0f);
+               for (j = -this->m_rady; j <= this->m_rady; j++) {
+                       for (i = -this->m_radx; i <= this->m_radx; i++, dgauss++) {
+                               float fj = (float)j * facy;
+                               float fi = (float)i * facx;
                                float dist = sqrt(fj * fj + fi * fi);
-                               *dgauss = RE_filter_value(this->data->filtertype, dist);
+                               *dgauss = RE_filter_value(this->m_data.filtertype, dist);
                                
-                               val += *dgauss;
+                               sum += *dgauss;
                        }
                }
-               if (val != 0.0f) {
-                       val = 1.0f / val;
+
+               if (sum > 0.0f) {
+                       /* normalize */
+                       float norm = 1.0f / sum;
                        for (j = n - 1; j >= 0; j--)
-                               ddgauss[j] *= val;
+                               ddgauss[j] *= norm;
+               }
+               else {
+                       int center = m_rady * ddwidth + m_radx;
+                       ddgauss[center] = 1.0f;
                }
-               else ddgauss[4] = 1.0f;
                
-               gausstab = ddgauss;
+               this->m_gausstab = ddgauss;
        }
 }
 
-void GaussianBokehBlurOperation::executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data)
+void GaussianBokehBlurOperation::executePixel(float output[4], int x, int y, void *data)
 {
        float tempColor[4];
        tempColor[0] = 0;
        tempColor[1] = 0;
        tempColor[2] = 0;
        tempColor[3] = 0;
-       float overallmultiplyer = 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;
 
-       int miny = y - this->rady;
-       int maxy = y + this->rady;
-       int minx = x - this->radx;
-       int maxx = x + this->radx;
-       miny = max(miny, inputBuffer->getRect()->ymin);
-       minx = max(minx, inputBuffer->getRect()->xmin);
-       maxy = min(maxy, inputBuffer->getRect()->ymax);
-       maxx = min(maxx, inputBuffer->getRect()->xmax);
+       rcti &rect = *inputBuffer->getRect();
+       int ymin = max_ii(y - this->m_rady, rect.ymin);
+       int ymax = min_ii(y + this->m_rady + 1,  rect.ymax);
+       int xmin = max_ii(x - this->m_radx, rect.xmin);
+       int xmax = min_ii(x + this->m_radx + 1,  rect.xmax);
 
        int index;
        int step = QualityStepHelper::getStep();
        int offsetadd = QualityStepHelper::getOffsetAdd();
-       for (int ny = miny; ny < maxy; ny += step) {
-               index = ((ny - y) + this->rady) * (this->radx * 2 + 1) + (minx - x + this->radx);
-               int bufferindex = ((minx - bufferstartx) * 4) + ((ny - bufferstarty) * 4 * bufferwidth);
-               for (int nx = minx; nx < maxx; nx += step) {
-                       const float multiplyer = gausstab[index];
-                       madd_v4_v4fl(tempColor, &buffer[bufferindex], multiplyer);
-                       overallmultiplyer += multiplyer;
+       const int addConst = (xmin - x + this->m_radx);
+       const int mulConst = (this->m_radx * 2 + 1);
+       for (int ny = ymin; ny < ymax; ny += step) {
+               index = ((ny - y) + this->m_rady) * mulConst + addConst;
+               int bufferindex = ((xmin - bufferstartx) * 4) + ((ny - bufferstarty) * 4 * bufferwidth);
+               for (int nx = xmin; nx < xmax; nx += step) {
+                       const float multiplier = this->m_gausstab[index];
+                       madd_v4_v4fl(tempColor, &buffer[bufferindex], multiplier);
+                       multiplier_accum += multiplier;
                        index += step;
                        bufferindex += offsetadd;
                }
        }
 
-       mul_v4_v4fl(color, tempColor, 1.0f / overallmultiplyer);
+       mul_v4_v4fl(output, tempColor, 1.0f / multiplier_accum);
 }
 
 void GaussianBokehBlurOperation::deinitExecution()
 {
        BlurBaseOperation::deinitExecution();
-       delete [] this->gausstab;
-       this->gausstab = NULL;
+
+       if (this->m_gausstab) {
+               MEM_freeN(this->m_gausstab);
+               this->m_gausstab = NULL;
+       }
+
+       deinitMutex();
 }
 
 bool GaussianBokehBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
@@ -170,15 +180,15 @@ bool GaussianBokehBlurOperation::determineDependingAreaOfInterest(rcti *input, R
                return true;
        }
        else {
-               if (this->sizeavailable && this->gausstab != NULL) {
+               if (this->m_sizeavailable && this->m_gausstab != NULL) {
                        newInput.xmin = 0;
                        newInput.ymin = 0;
                        newInput.xmax = this->getWidth();
                        newInput.ymax = this->getHeight();
                }
                else {
-                       int addx = radx;
-                       int addy = rady;
+                       int addx = this->m_radx;
+                       int addy = this->m_rady;
                        newInput.xmax = input->xmax + addx;
                        newInput.xmin = input->xmin - addx;
                        newInput.ymax = input->ymax + addy;
@@ -188,3 +198,160 @@ bool GaussianBokehBlurOperation::determineDependingAreaOfInterest(rcti *input, R
                return BlurBaseOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
        }
 }
+
+// reference image
+GaussianBlurReferenceOperation::GaussianBlurReferenceOperation() : BlurBaseOperation(COM_DT_COLOR)
+{
+       this->m_maintabs = NULL;
+}
+
+void *GaussianBlurReferenceOperation::initializeTileData(rcti * /*rect*/)
+{
+       void *buffer = getInputOperation(0)->initializeTileData(NULL);
+       return buffer;
+}
+
+void GaussianBlurReferenceOperation::initExecution()
+{
+       BlurBaseOperation::initExecution();
+       // setup gaustab
+       this->m_data.image_in_width = this->getWidth();
+       this->m_data.image_in_height = this->getHeight();
+       if (this->m_data.relative) {
+               switch (this->m_data.aspect) {
+                       case CMP_NODE_BLUR_ASPECT_NONE:
+                               this->m_data.sizex = (int)(this->m_data.percentx * 0.01f * this->m_data.image_in_width);
+                               this->m_data.sizey = (int)(this->m_data.percenty * 0.01f * this->m_data.image_in_height);
+                               break;
+                       case CMP_NODE_BLUR_ASPECT_Y:
+                               this->m_data.sizex = (int)(this->m_data.percentx * 0.01f * this->m_data.image_in_width);
+                               this->m_data.sizey = (int)(this->m_data.percenty * 0.01f * this->m_data.image_in_width);
+                               break;
+                       case CMP_NODE_BLUR_ASPECT_X:
+                               this->m_data.sizex = (int)(this->m_data.percentx * 0.01f * this->m_data.image_in_height);
+                               this->m_data.sizey = (int)(this->m_data.percenty * 0.01f * this->m_data.image_in_height);
+                               break;
+               }
+       }
+       
+       
+       /* horizontal */
+       m_filtersizex = (float)this->m_data.sizex;
+       int imgx = getWidth() / 2;
+       if (m_filtersizex > imgx)
+               m_filtersizex = imgx;
+       else if (m_filtersizex < 1)
+               m_filtersizex = 1;
+       m_radx = (float)m_filtersizex;
+
+       /* vertical */
+       m_filtersizey = (float)this->m_data.sizey;
+       int imgy = getHeight() / 2;
+       if (m_filtersizey > imgy)
+               m_filtersizey = imgy;
+       else if (m_filtersizey < 1)
+               m_filtersizey = 1;
+       m_rady = (float)m_filtersizey;
+       updateGauss();
+}
+
+void GaussianBlurReferenceOperation::updateGauss()
+{
+       int i;
+       int x = max(m_filtersizex, m_filtersizey);
+       m_maintabs = (float **)MEM_mallocN(x * sizeof(float *), "gauss array");
+       for (i = 0; i < x; i++) {
+               m_maintabs[i] = make_gausstab(i + 1, i + 1);
+       }
+}
+
+void GaussianBlurReferenceOperation::executePixel(float output[4], int x, int y, void *data)
+{
+       MemoryBuffer *memorybuffer = (MemoryBuffer *)data;
+       float *buffer = memorybuffer->getBuffer();
+       float *gausstabx, *gausstabcenty;
+       float *gausstaby, *gausstabcentx;
+       int i, j;
+       float *src;
+       float sum, val;
+       float rval, gval, bval, aval;
+       int imgx = getWidth();
+       int imgy = getHeight();
+       float tempSize[4];
+       this->m_inputSize->read(tempSize, x, y, data);
+       float refSize = tempSize[0];
+       int refradx = (int)(refSize * m_radx);
+       int refrady = (int)(refSize * m_rady);
+       if (refradx > m_filtersizex) refradx = m_filtersizex;
+       else if (refradx < 1) refradx = 1;
+       if (refrady > m_filtersizey) refrady = m_filtersizey;
+       else if (refrady < 1) refrady = 1;
+
+       if (refradx == 1 && refrady == 1) {
+               memorybuffer->readNoCheck(output, 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;
+
+               float *srcd = buffer + COM_NUM_CHANNELS_COLOR * ( (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_NUM_CHANNELS_COLOR * imgx) {
+                       src = srcd;
+                       for (j = minxr; j < maxxr; j++, src += COM_NUM_CHANNELS_COLOR) {
+                       
+                               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;
+               output[0] = rval * sum;
+               output[1] = gval * sum;
+               output[2] = bval * sum;
+               output[3] = aval * sum;
+       }
+
+}
+
+void GaussianBlurReferenceOperation::deinitExecution()
+{
+       int x, i;
+       x = max(this->m_filtersizex, this->m_filtersizey);
+       for (i = 0; i < x; i++) {
+               MEM_freeN(this->m_maintabs[i]);
+       }
+       MEM_freeN(this->m_maintabs);
+       BlurBaseOperation::deinitExecution();
+}
+
+bool GaussianBlurReferenceOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
+{
+       rcti newInput;
+       NodeOperation *operation = this->getInputOperation(1);
+       
+       if (operation->determineDependingAreaOfInterest(input, readOperation, output)) {
+               return true;
+       }
+       else {
+               int addx = this->m_data.sizex + 2;
+               int addy = this->m_data.sizey + 2;
+               newInput.xmax = input->xmax + addx;
+               newInput.xmin = input->xmin - addx;
+               newInput.ymax = input->ymax + addy;
+               newInput.ymin = input->ymin - addy;
+               return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
+       }
+}
+