Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp')
-rw-r--r--source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp505
1 files changed, 259 insertions, 246 deletions
diff --git a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp
index c7c0fd8e447..e375b2fe45b 100644
--- a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp
@@ -24,297 +24,310 @@
FastGaussianBlurOperation::FastGaussianBlurOperation() : BlurBaseOperation(COM_DT_COLOR)
{
- this->m_iirgaus = NULL;
+ this->m_iirgaus = NULL;
}
void FastGaussianBlurOperation::executePixel(float output[4], int x, int y, void *data)
{
- MemoryBuffer *newData = (MemoryBuffer *)data;
- newData->read(output, x, y);
+ MemoryBuffer *newData = (MemoryBuffer *)data;
+ newData->read(output, x, y);
}
-bool FastGaussianBlurOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output)
+bool FastGaussianBlurOperation::determineDependingAreaOfInterest(
+ rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output)
{
- rcti newInput;
- rcti sizeInput;
- sizeInput.xmin = 0;
- sizeInput.ymin = 0;
- sizeInput.xmax = 5;
- sizeInput.ymax = 5;
-
- NodeOperation *operation = this->getInputOperation(1);
- if (operation->determineDependingAreaOfInterest(&sizeInput, readOperation, output)) {
- return true;
- }
- else {
- if (this->m_iirgaus) {
- return false;
- }
- else {
- newInput.xmin = 0;
- newInput.ymin = 0;
- newInput.xmax = this->getWidth();
- newInput.ymax = this->getHeight();
- }
- return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
- }
+ rcti newInput;
+ rcti sizeInput;
+ sizeInput.xmin = 0;
+ sizeInput.ymin = 0;
+ sizeInput.xmax = 5;
+ sizeInput.ymax = 5;
+
+ NodeOperation *operation = this->getInputOperation(1);
+ if (operation->determineDependingAreaOfInterest(&sizeInput, readOperation, output)) {
+ return true;
+ }
+ else {
+ if (this->m_iirgaus) {
+ return false;
+ }
+ else {
+ newInput.xmin = 0;
+ newInput.ymin = 0;
+ newInput.xmax = this->getWidth();
+ newInput.ymax = this->getHeight();
+ }
+ return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
+ }
}
void FastGaussianBlurOperation::initExecution()
{
- BlurBaseOperation::initExecution();
- BlurBaseOperation::initMutex();
+ BlurBaseOperation::initExecution();
+ BlurBaseOperation::initMutex();
}
void FastGaussianBlurOperation::deinitExecution()
{
- if (this->m_iirgaus) {
- delete this->m_iirgaus;
- this->m_iirgaus = NULL;
- }
- BlurBaseOperation::deinitMutex();
+ if (this->m_iirgaus) {
+ delete this->m_iirgaus;
+ this->m_iirgaus = NULL;
+ }
+ BlurBaseOperation::deinitMutex();
}
void *FastGaussianBlurOperation::initializeTileData(rcti *rect)
{
- lockMutex();
- if (!this->m_iirgaus) {
- MemoryBuffer *newBuf = (MemoryBuffer *)this->m_inputProgram->initializeTileData(rect);
- MemoryBuffer *copy = newBuf->duplicate();
- updateSize();
-
- int c;
- this->m_sx = this->m_data.sizex * this->m_size / 2.0f;
- this->m_sy = this->m_data.sizey * this->m_size / 2.0f;
-
- if ((this->m_sx == this->m_sy) && (this->m_sx > 0.0f)) {
- for (c = 0; c < COM_NUM_CHANNELS_COLOR; ++c)
- IIR_gauss(copy, this->m_sx, c, 3);
- }
- else {
- if (this->m_sx > 0.0f) {
- for (c = 0; c < COM_NUM_CHANNELS_COLOR; ++c)
- IIR_gauss(copy, this->m_sx, c, 1);
- }
- if (this->m_sy > 0.0f) {
- for (c = 0; c < COM_NUM_CHANNELS_COLOR; ++c)
- IIR_gauss(copy, this->m_sy, c, 2);
- }
- }
- this->m_iirgaus = copy;
- }
- unlockMutex();
- return this->m_iirgaus;
+ lockMutex();
+ if (!this->m_iirgaus) {
+ MemoryBuffer *newBuf = (MemoryBuffer *)this->m_inputProgram->initializeTileData(rect);
+ MemoryBuffer *copy = newBuf->duplicate();
+ updateSize();
+
+ int c;
+ this->m_sx = this->m_data.sizex * this->m_size / 2.0f;
+ this->m_sy = this->m_data.sizey * this->m_size / 2.0f;
+
+ if ((this->m_sx == this->m_sy) && (this->m_sx > 0.0f)) {
+ for (c = 0; c < COM_NUM_CHANNELS_COLOR; ++c)
+ IIR_gauss(copy, this->m_sx, c, 3);
+ }
+ else {
+ if (this->m_sx > 0.0f) {
+ for (c = 0; c < COM_NUM_CHANNELS_COLOR; ++c)
+ IIR_gauss(copy, this->m_sx, c, 1);
+ }
+ if (this->m_sy > 0.0f) {
+ for (c = 0; c < COM_NUM_CHANNELS_COLOR; ++c)
+ IIR_gauss(copy, this->m_sy, c, 2);
+ }
+ }
+ this->m_iirgaus = copy;
+ }
+ unlockMutex();
+ return this->m_iirgaus;
}
-void FastGaussianBlurOperation::IIR_gauss(MemoryBuffer *src, float sigma, unsigned int chan, unsigned int xy)
+void FastGaussianBlurOperation::IIR_gauss(MemoryBuffer *src,
+ float sigma,
+ unsigned int chan,
+ unsigned int xy)
{
- double q, q2, sc, cf[4], tsM[9], tsu[3], tsv[3];
- double *X, *Y, *W;
- const unsigned int src_width = src->getWidth();
- const unsigned int src_height = src->getHeight();
- unsigned int x, y, sz;
- unsigned int i;
- float *buffer = src->getBuffer();
- const unsigned int num_channels = src->get_num_channels();
-
- // <0.5 not valid, though can have a possibly useful sort of sharpening effect
- if (sigma < 0.5f) return;
-
- if ((xy < 1) || (xy > 3)) xy = 3;
-
- // XXX The YVV macro defined below explicitly expects sources of at least 3x3 pixels,
- // so just skipping blur along faulty direction if src's def is below that limit!
- if (src_width < 3) xy &= ~1;
- if (src_height < 3) xy &= ~2;
- if (xy < 1) return;
-
- // see "Recursive Gabor Filtering" by Young/VanVliet
- // all factors here in double.prec. Required, because for single.prec it seems to blow up if sigma > ~200
- if (sigma >= 3.556f)
- q = 0.9804f * (sigma - 3.556f) + 2.5091f;
- else // sigma >= 0.5
- q = (0.0561f * sigma + 0.5784f) * sigma - 0.2568f;
- q2 = q * q;
- sc = (1.1668 + q) * (3.203729649 + (2.21566 + q) * q);
- // no gabor filtering here, so no complex multiplies, just the regular coefs.
- // all negated here, so as not to have to recalc Triggs/Sdika matrix
- cf[1] = q * (5.788961737 + (6.76492 + 3.0 * q) * q) / sc;
- cf[2] = -q2 * (3.38246 + 3.0 * q) / sc;
- // 0 & 3 unchanged
- cf[3] = q2 * q / sc;
- cf[0] = 1.0 - cf[1] - cf[2] - cf[3];
-
- // Triggs/Sdika border corrections,
- // it seems to work, not entirely sure if it is actually totally correct,
- // Besides J.M.Geusebroek's anigauss.c (see http://www.science.uva.nl/~mark),
- // found one other implementation by Cristoph Lampert,
- // but neither seem to be quite the same, result seems to be ok so far anyway.
- // Extra scale factor here to not have to do it in filter,
- // though maybe this had something to with the precision errors
- sc = cf[0] / ((1.0 + cf[1] - cf[2] + cf[3]) * (1.0 - cf[1] - cf[2] - cf[3]) * (1.0 + cf[2] + (cf[1] - cf[3]) * cf[3]));
- tsM[0] = sc * (-cf[3] * cf[1] + 1.0 - cf[3] * cf[3] - cf[2]);
- tsM[1] = sc * ((cf[3] + cf[1]) * (cf[2] + cf[3] * cf[1]));
- tsM[2] = sc * (cf[3] * (cf[1] + cf[3] * cf[2]));
- tsM[3] = sc * (cf[1] + cf[3] * cf[2]);
- tsM[4] = sc * (-(cf[2] - 1.0) * (cf[2] + cf[3] * cf[1]));
- tsM[5] = sc * (-(cf[3] * cf[1] + cf[3] * cf[3] + cf[2] - 1.0) * cf[3]);
- tsM[6] = sc * (cf[3] * cf[1] + cf[2] + cf[1] * cf[1] - cf[2] * cf[2]);
- tsM[7] = sc * (cf[1] * cf[2] + cf[3] * cf[2] * cf[2] - cf[1] * cf[3] * cf[3] - cf[3] * cf[3] * cf[3] - cf[3] * cf[2] + cf[3]);
- tsM[8] = sc * (cf[3] * (cf[1] + cf[3] * cf[2]));
-
-#define YVV(L) \
-{ \
- W[0] = cf[0] * X[0] + cf[1] * X[0] + cf[2] * X[0] + cf[3] * X[0]; \
- W[1] = cf[0] * X[1] + cf[1] * W[0] + cf[2] * X[0] + cf[3] * X[0]; \
- W[2] = cf[0] * X[2] + cf[1] * W[1] + cf[2] * W[0] + cf[3] * X[0]; \
- for (i = 3; i < L; i++) { \
- W[i] = cf[0] * X[i] + cf[1] * W[i - 1] + cf[2] * W[i - 2] + cf[3] * W[i - 3]; \
- } \
- tsu[0] = W[L - 1] - X[L - 1]; \
- tsu[1] = W[L - 2] - X[L - 1]; \
- tsu[2] = W[L - 3] - X[L - 1]; \
- tsv[0] = tsM[0] * tsu[0] + tsM[1] * tsu[1] + tsM[2] * tsu[2] + X[L - 1]; \
- tsv[1] = tsM[3] * tsu[0] + tsM[4] * tsu[1] + tsM[5] * tsu[2] + X[L - 1]; \
- tsv[2] = tsM[6] * tsu[0] + tsM[7] * tsu[1] + tsM[8] * tsu[2] + X[L - 1]; \
- Y[L - 1] = cf[0] * W[L - 1] + cf[1] * tsv[0] + cf[2] * tsv[1] + cf[3] * tsv[2]; \
- Y[L - 2] = cf[0] * W[L - 2] + cf[1] * Y[L - 1] + cf[2] * tsv[0] + cf[3] * tsv[1]; \
- Y[L - 3] = cf[0] * W[L - 3] + cf[1] * Y[L - 2] + cf[2] * Y[L - 1] + cf[3] * tsv[0]; \
- /* 'i != UINT_MAX' is really 'i >= 0', but necessary for unsigned int wrapping */ \
- for (i = L - 4; i != UINT_MAX; i--) { \
- Y[i] = cf[0] * W[i] + cf[1] * Y[i + 1] + cf[2] * Y[i + 2] + cf[3] * Y[i + 3]; \
- } \
-} (void)0
-
- // intermediate buffers
- sz = max(src_width, src_height);
- X = (double *)MEM_callocN(sz * sizeof(double), "IIR_gauss X buf");
- Y = (double *)MEM_callocN(sz * sizeof(double), "IIR_gauss Y buf");
- W = (double *)MEM_callocN(sz * sizeof(double), "IIR_gauss W buf");
- if (xy & 1) { // H
- int offset;
- for (y = 0; y < src_height; ++y) {
- const int yx = y * src_width;
- offset = yx * num_channels + chan;
- for (x = 0; x < src_width; ++x) {
- X[x] = buffer[offset];
- offset += num_channels;
- }
- YVV(src_width);
- offset = yx * num_channels + chan;
- for (x = 0; x < src_width; ++x) {
- buffer[offset] = Y[x];
- offset += num_channels;
- }
- }
- }
- if (xy & 2) { // V
- int offset;
- const int add = src_width * num_channels;
-
- for (x = 0; x < src_width; ++x) {
- offset = x * num_channels + chan;
- for (y = 0; y < src_height; ++y) {
- X[y] = buffer[offset];
- offset += add;
- }
- YVV(src_height);
- offset = x * num_channels + chan;
- for (y = 0; y < src_height; ++y) {
- buffer[offset] = Y[y];
- offset += add;
- }
- }
- }
-
- MEM_freeN(X);
- MEM_freeN(W);
- MEM_freeN(Y);
+ double q, q2, sc, cf[4], tsM[9], tsu[3], tsv[3];
+ double *X, *Y, *W;
+ const unsigned int src_width = src->getWidth();
+ const unsigned int src_height = src->getHeight();
+ unsigned int x, y, sz;
+ unsigned int i;
+ float *buffer = src->getBuffer();
+ const unsigned int num_channels = src->get_num_channels();
+
+ // <0.5 not valid, though can have a possibly useful sort of sharpening effect
+ if (sigma < 0.5f)
+ return;
+
+ if ((xy < 1) || (xy > 3))
+ xy = 3;
+
+ // XXX The YVV macro defined below explicitly expects sources of at least 3x3 pixels,
+ // so just skipping blur along faulty direction if src's def is below that limit!
+ if (src_width < 3)
+ xy &= ~1;
+ if (src_height < 3)
+ xy &= ~2;
+ if (xy < 1)
+ return;
+
+ // see "Recursive Gabor Filtering" by Young/VanVliet
+ // all factors here in double.prec. Required, because for single.prec it seems to blow up if sigma > ~200
+ if (sigma >= 3.556f)
+ q = 0.9804f * (sigma - 3.556f) + 2.5091f;
+ else // sigma >= 0.5
+ q = (0.0561f * sigma + 0.5784f) * sigma - 0.2568f;
+ q2 = q * q;
+ sc = (1.1668 + q) * (3.203729649 + (2.21566 + q) * q);
+ // no gabor filtering here, so no complex multiplies, just the regular coefs.
+ // all negated here, so as not to have to recalc Triggs/Sdika matrix
+ cf[1] = q * (5.788961737 + (6.76492 + 3.0 * q) * q) / sc;
+ cf[2] = -q2 * (3.38246 + 3.0 * q) / sc;
+ // 0 & 3 unchanged
+ cf[3] = q2 * q / sc;
+ cf[0] = 1.0 - cf[1] - cf[2] - cf[3];
+
+ // Triggs/Sdika border corrections,
+ // it seems to work, not entirely sure if it is actually totally correct,
+ // Besides J.M.Geusebroek's anigauss.c (see http://www.science.uva.nl/~mark),
+ // found one other implementation by Cristoph Lampert,
+ // but neither seem to be quite the same, result seems to be ok so far anyway.
+ // Extra scale factor here to not have to do it in filter,
+ // though maybe this had something to with the precision errors
+ sc = cf[0] / ((1.0 + cf[1] - cf[2] + cf[3]) * (1.0 - cf[1] - cf[2] - cf[3]) *
+ (1.0 + cf[2] + (cf[1] - cf[3]) * cf[3]));
+ tsM[0] = sc * (-cf[3] * cf[1] + 1.0 - cf[3] * cf[3] - cf[2]);
+ tsM[1] = sc * ((cf[3] + cf[1]) * (cf[2] + cf[3] * cf[1]));
+ tsM[2] = sc * (cf[3] * (cf[1] + cf[3] * cf[2]));
+ tsM[3] = sc * (cf[1] + cf[3] * cf[2]);
+ tsM[4] = sc * (-(cf[2] - 1.0) * (cf[2] + cf[3] * cf[1]));
+ tsM[5] = sc * (-(cf[3] * cf[1] + cf[3] * cf[3] + cf[2] - 1.0) * cf[3]);
+ tsM[6] = sc * (cf[3] * cf[1] + cf[2] + cf[1] * cf[1] - cf[2] * cf[2]);
+ tsM[7] = sc * (cf[1] * cf[2] + cf[3] * cf[2] * cf[2] - cf[1] * cf[3] * cf[3] -
+ cf[3] * cf[3] * cf[3] - cf[3] * cf[2] + cf[3]);
+ tsM[8] = sc * (cf[3] * (cf[1] + cf[3] * cf[2]));
+
+#define YVV(L) \
+ { \
+ W[0] = cf[0] * X[0] + cf[1] * X[0] + cf[2] * X[0] + cf[3] * X[0]; \
+ W[1] = cf[0] * X[1] + cf[1] * W[0] + cf[2] * X[0] + cf[3] * X[0]; \
+ W[2] = cf[0] * X[2] + cf[1] * W[1] + cf[2] * W[0] + cf[3] * X[0]; \
+ for (i = 3; i < L; i++) { \
+ W[i] = cf[0] * X[i] + cf[1] * W[i - 1] + cf[2] * W[i - 2] + cf[3] * W[i - 3]; \
+ } \
+ tsu[0] = W[L - 1] - X[L - 1]; \
+ tsu[1] = W[L - 2] - X[L - 1]; \
+ tsu[2] = W[L - 3] - X[L - 1]; \
+ tsv[0] = tsM[0] * tsu[0] + tsM[1] * tsu[1] + tsM[2] * tsu[2] + X[L - 1]; \
+ tsv[1] = tsM[3] * tsu[0] + tsM[4] * tsu[1] + tsM[5] * tsu[2] + X[L - 1]; \
+ tsv[2] = tsM[6] * tsu[0] + tsM[7] * tsu[1] + tsM[8] * tsu[2] + X[L - 1]; \
+ Y[L - 1] = cf[0] * W[L - 1] + cf[1] * tsv[0] + cf[2] * tsv[1] + cf[3] * tsv[2]; \
+ Y[L - 2] = cf[0] * W[L - 2] + cf[1] * Y[L - 1] + cf[2] * tsv[0] + cf[3] * tsv[1]; \
+ Y[L - 3] = cf[0] * W[L - 3] + cf[1] * Y[L - 2] + cf[2] * Y[L - 1] + cf[3] * tsv[0]; \
+ /* 'i != UINT_MAX' is really 'i >= 0', but necessary for unsigned int wrapping */ \
+ for (i = L - 4; i != UINT_MAX; i--) { \
+ Y[i] = cf[0] * W[i] + cf[1] * Y[i + 1] + cf[2] * Y[i + 2] + cf[3] * Y[i + 3]; \
+ } \
+ } \
+ (void)0
+
+ // intermediate buffers
+ sz = max(src_width, src_height);
+ X = (double *)MEM_callocN(sz * sizeof(double), "IIR_gauss X buf");
+ Y = (double *)MEM_callocN(sz * sizeof(double), "IIR_gauss Y buf");
+ W = (double *)MEM_callocN(sz * sizeof(double), "IIR_gauss W buf");
+ if (xy & 1) { // H
+ int offset;
+ for (y = 0; y < src_height; ++y) {
+ const int yx = y * src_width;
+ offset = yx * num_channels + chan;
+ for (x = 0; x < src_width; ++x) {
+ X[x] = buffer[offset];
+ offset += num_channels;
+ }
+ YVV(src_width);
+ offset = yx * num_channels + chan;
+ for (x = 0; x < src_width; ++x) {
+ buffer[offset] = Y[x];
+ offset += num_channels;
+ }
+ }
+ }
+ if (xy & 2) { // V
+ int offset;
+ const int add = src_width * num_channels;
+
+ for (x = 0; x < src_width; ++x) {
+ offset = x * num_channels + chan;
+ for (y = 0; y < src_height; ++y) {
+ X[y] = buffer[offset];
+ offset += add;
+ }
+ YVV(src_height);
+ offset = x * num_channels + chan;
+ for (y = 0; y < src_height; ++y) {
+ buffer[offset] = Y[y];
+ offset += add;
+ }
+ }
+ }
+
+ MEM_freeN(X);
+ MEM_freeN(W);
+ MEM_freeN(Y);
#undef YVV
-
}
-
///
FastGaussianBlurValueOperation::FastGaussianBlurValueOperation() : NodeOperation()
{
- this->addInputSocket(COM_DT_VALUE);
- this->addOutputSocket(COM_DT_VALUE);
- this->m_iirgaus = NULL;
- this->m_inputprogram = NULL;
- this->m_sigma = 1.0f;
- this->m_overlay = 0;
- setComplex(true);
+ this->addInputSocket(COM_DT_VALUE);
+ this->addOutputSocket(COM_DT_VALUE);
+ this->m_iirgaus = NULL;
+ this->m_inputprogram = NULL;
+ this->m_sigma = 1.0f;
+ this->m_overlay = 0;
+ setComplex(true);
}
void FastGaussianBlurValueOperation::executePixel(float output[4], int x, int y, void *data)
{
- MemoryBuffer *newData = (MemoryBuffer *)data;
- newData->read(output, x, y);
+ MemoryBuffer *newData = (MemoryBuffer *)data;
+ newData->read(output, x, y);
}
-bool FastGaussianBlurValueOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output)
+bool FastGaussianBlurValueOperation::determineDependingAreaOfInterest(
+ rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output)
{
- rcti newInput;
-
- if (this->m_iirgaus) {
- return false;
- }
- else {
- newInput.xmin = 0;
- newInput.ymin = 0;
- newInput.xmax = this->getWidth();
- newInput.ymax = this->getHeight();
- }
- return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
+ rcti newInput;
+
+ if (this->m_iirgaus) {
+ return false;
+ }
+ else {
+ newInput.xmin = 0;
+ newInput.ymin = 0;
+ newInput.xmax = this->getWidth();
+ newInput.ymax = this->getHeight();
+ }
+ return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
void FastGaussianBlurValueOperation::initExecution()
{
- this->m_inputprogram = getInputSocketReader(0);
- initMutex();
+ this->m_inputprogram = getInputSocketReader(0);
+ initMutex();
}
void FastGaussianBlurValueOperation::deinitExecution()
{
- if (this->m_iirgaus) {
- delete this->m_iirgaus;
- this->m_iirgaus = NULL;
- }
- deinitMutex();
+ if (this->m_iirgaus) {
+ delete this->m_iirgaus;
+ this->m_iirgaus = NULL;
+ }
+ deinitMutex();
}
void *FastGaussianBlurValueOperation::initializeTileData(rcti *rect)
{
- lockMutex();
- if (!this->m_iirgaus) {
- MemoryBuffer *newBuf = (MemoryBuffer *)this->m_inputprogram->initializeTileData(rect);
- MemoryBuffer *copy = newBuf->duplicate();
- FastGaussianBlurOperation::IIR_gauss(copy, this->m_sigma, 0, 3);
-
- if (this->m_overlay == FAST_GAUSS_OVERLAY_MIN) {
- float *src = newBuf->getBuffer();
- float *dst = copy->getBuffer();
- for (int i = copy->getWidth() * copy->getHeight(); i != 0; i--, src += COM_NUM_CHANNELS_VALUE, dst += COM_NUM_CHANNELS_VALUE) {
- if (*src < *dst) {
- *dst = *src;
- }
- }
- }
- else if (this->m_overlay == FAST_GAUSS_OVERLAY_MAX) {
- float *src = newBuf->getBuffer();
- float *dst = copy->getBuffer();
- for (int i = copy->getWidth() * copy->getHeight(); i != 0; i--, src += COM_NUM_CHANNELS_VALUE, dst += COM_NUM_CHANNELS_VALUE) {
- if (*src > *dst) {
- *dst = *src;
- }
- }
- }
-
-// newBuf->
-
- this->m_iirgaus = copy;
- }
- unlockMutex();
- return this->m_iirgaus;
+ lockMutex();
+ if (!this->m_iirgaus) {
+ MemoryBuffer *newBuf = (MemoryBuffer *)this->m_inputprogram->initializeTileData(rect);
+ MemoryBuffer *copy = newBuf->duplicate();
+ FastGaussianBlurOperation::IIR_gauss(copy, this->m_sigma, 0, 3);
+
+ if (this->m_overlay == FAST_GAUSS_OVERLAY_MIN) {
+ float *src = newBuf->getBuffer();
+ float *dst = copy->getBuffer();
+ for (int i = copy->getWidth() * copy->getHeight(); i != 0;
+ i--, src += COM_NUM_CHANNELS_VALUE, dst += COM_NUM_CHANNELS_VALUE) {
+ if (*src < *dst) {
+ *dst = *src;
+ }
+ }
+ }
+ else if (this->m_overlay == FAST_GAUSS_OVERLAY_MAX) {
+ float *src = newBuf->getBuffer();
+ float *dst = copy->getBuffer();
+ for (int i = copy->getWidth() * copy->getHeight(); i != 0;
+ i--, src += COM_NUM_CHANNELS_VALUE, dst += COM_NUM_CHANNELS_VALUE) {
+ if (*src > *dst) {
+ *dst = *src;
+ }
+ }
+ }
+
+ // newBuf->
+
+ this->m_iirgaus = copy;
+ }
+ unlockMutex();
+ return this->m_iirgaus;
}