Differential D11791 Diff 40164 source/blender/compositor/operations/COM_FastGaussianBlurOperation.cc
Changeset View
Changeset View
Standalone View
Standalone View
source/blender/compositor/operations/COM_FastGaussianBlurOperation.cc
| Show First 20 Lines • Show All 120 Lines • ▼ Show 20 Lines | void FastGaussianBlurOperation::IIR_gauss(MemoryBuffer *src, | ||||
| double *X, *Y, *W; | double *X, *Y, *W; | ||||
| const unsigned int src_width = src->getWidth(); | const unsigned int src_width = src->getWidth(); | ||||
| const unsigned int src_height = src->getHeight(); | const unsigned int src_height = src->getHeight(); | ||||
| unsigned int x, y, sz; | unsigned int x, y, sz; | ||||
| unsigned int i; | unsigned int i; | ||||
| float *buffer = src->getBuffer(); | float *buffer = src->getBuffer(); | ||||
| const uint8_t num_channels = src->get_num_channels(); | const uint8_t num_channels = src->get_num_channels(); | ||||
| // <0.5 not valid, though can have a possibly useful sort of sharpening effect | /* <0.5 not valid, though can have a possibly useful sort of sharpening effect. */ | ||||
| if (sigma < 0.5f) { | if (sigma < 0.5f) { | ||||
| return; | return; | ||||
| } | } | ||||
| if ((xy < 1) || (xy > 3)) { | if ((xy < 1) || (xy > 3)) { | ||||
| xy = 3; | xy = 3; | ||||
| } | } | ||||
| // XXX The YVV macro defined below explicitly expects sources of at least 3x3 pixels, | /* 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! | * so just skipping blur along faulty direction if src's def is below that limit! */ | ||||
| if (src_width < 3) { | if (src_width < 3) { | ||||
| xy &= ~1; | xy &= ~1; | ||||
| } | } | ||||
| if (src_height < 3) { | if (src_height < 3) { | ||||
| xy &= ~2; | xy &= ~2; | ||||
| } | } | ||||
| if (xy < 1) { | if (xy < 1) { | ||||
| return; | return; | ||||
| } | } | ||||
| // see "Recursive Gabor Filtering" by Young/VanVliet | /* See "Recursive Gabor Filtering" by Young/VanVliet | ||||
| // all factors here in double.prec. | * all factors here in double-precision. | ||||
| // Required, because for single.prec it seems to blow up if sigma > ~200 | * Required, because for single-precision floating point seems to blow up if `sigma > ~200`. */ | ||||
| if (sigma >= 3.556f) { | if (sigma >= 3.556f) { | ||||
| q = 0.9804f * (sigma - 3.556f) + 2.5091f; | q = 0.9804f * (sigma - 3.556f) + 2.5091f; | ||||
| } | } | ||||
| else { // sigma >= 0.5 | else { /* `sigma >= 0.5`. */ | ||||
| q = (0.0561f * sigma + 0.5784f) * sigma - 0.2568f; | q = (0.0561f * sigma + 0.5784f) * sigma - 0.2568f; | ||||
| } | } | ||||
| q2 = q * q; | q2 = q * q; | ||||
| sc = (1.1668 + q) * (3.203729649 + (2.21566 + q) * q); | sc = (1.1668 + q) * (3.203729649 + (2.21566 + q) * q); | ||||
| // no gabor filtering here, so no complex multiplies, just the regular coefs. | /* No gabor filtering here, so no complex multiplies, just the regular coefficients. | ||||
| // all negated here, so as not to have to recalc Triggs/Sdika matrix | * 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[1] = q * (5.788961737 + (6.76492 + 3.0 * q) * q) / sc; | ||||
| cf[2] = -q2 * (3.38246 + 3.0 * q) / sc; | cf[2] = -q2 * (3.38246 + 3.0 * q) / sc; | ||||
| // 0 & 3 unchanged | /* 0 & 3 unchanged. */ | ||||
| cf[3] = q2 * q / sc; | cf[3] = q2 * q / sc; | ||||
| cf[0] = 1.0 - cf[1] - cf[2] - cf[3]; | cf[0] = 1.0 - cf[1] - cf[2] - cf[3]; | ||||
| // Triggs/Sdika border corrections, | /* Triggs/Sdika border corrections, | ||||
| // it seems to work, not entirely sure if it is actually totally correct, | * 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), | * Besides J.M.Geusebroek's `anigauss.c` (see http://www.science.uva.nl/~mark), | ||||
| // found one other implementation by Cristoph Lampert, | * found one other implementation by Cristoph Lampert, | ||||
| // but neither seem to be quite the same, result seems to be ok so far anyway. | * 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, | * Extra scale factor here to not have to do it in filter, | ||||
| // though maybe this had something to with the precision errors | * 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]) * | 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])); | (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[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[1] = sc * ((cf[3] + cf[1]) * (cf[2] + cf[3] * cf[1])); | ||||
| tsM[2] = sc * (cf[3] * (cf[1] + cf[3] * cf[2])); | tsM[2] = sc * (cf[3] * (cf[1] + cf[3] * cf[2])); | ||||
| tsM[3] = sc * (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[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[5] = sc * (-(cf[3] * cf[1] + cf[3] * cf[3] + cf[2] - 1.0) * cf[3]); | ||||
| Show All 21 Lines | #define YVV(L) \ | ||||
| Y[L - 3] = cf[0] * W[L - 3] + cf[1] * Y[L - 2] + cf[2] * Y[L - 1] + cf[3] * tsv[0]; \ | 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 */ \ | /* 'i != UINT_MAX' is really 'i >= 0', but necessary for unsigned int wrapping */ \ | ||||
| for (i = L - 4; i != UINT_MAX; i--) { \ | 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]; \ | Y[i] = cf[0] * W[i] + cf[1] * Y[i + 1] + cf[2] * Y[i + 2] + cf[3] * Y[i + 3]; \ | ||||
| } \ | } \ | ||||
| } \ | } \ | ||||
| (void)0 | (void)0 | ||||
| // intermediate buffers | /* Intermediate buffers. */ | ||||
| sz = MAX2(src_width, src_height); | sz = MAX2(src_width, src_height); | ||||
| X = (double *)MEM_callocN(sz * sizeof(double), "IIR_gauss X buf"); | X = (double *)MEM_callocN(sz * sizeof(double), "IIR_gauss X buf"); | ||||
| Y = (double *)MEM_callocN(sz * sizeof(double), "IIR_gauss Y buf"); | Y = (double *)MEM_callocN(sz * sizeof(double), "IIR_gauss Y buf"); | ||||
| W = (double *)MEM_callocN(sz * sizeof(double), "IIR_gauss W buf"); | W = (double *)MEM_callocN(sz * sizeof(double), "IIR_gauss W buf"); | ||||
| if (xy & 1) { // H | if (xy & 1) { /* H. */ | ||||
| int offset; | int offset; | ||||
| for (y = 0; y < src_height; y++) { | for (y = 0; y < src_height; y++) { | ||||
| const int yx = y * src_width; | const int yx = y * src_width; | ||||
| offset = yx * num_channels + chan; | offset = yx * num_channels + chan; | ||||
| for (x = 0; x < src_width; x++) { | for (x = 0; x < src_width; x++) { | ||||
| X[x] = buffer[offset]; | X[x] = buffer[offset]; | ||||
| offset += num_channels; | offset += num_channels; | ||||
| } | } | ||||
| YVV(src_width); | YVV(src_width); | ||||
| offset = yx * num_channels + chan; | offset = yx * num_channels + chan; | ||||
| for (x = 0; x < src_width; x++) { | for (x = 0; x < src_width; x++) { | ||||
| buffer[offset] = Y[x]; | buffer[offset] = Y[x]; | ||||
| offset += num_channels; | offset += num_channels; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (xy & 2) { // V | if (xy & 2) { /* V. */ | ||||
| int offset; | int offset; | ||||
| const int add = src_width * num_channels; | const int add = src_width * num_channels; | ||||
| for (x = 0; x < src_width; x++) { | for (x = 0; x < src_width; x++) { | ||||
| offset = x * num_channels + chan; | offset = x * num_channels + chan; | ||||
| for (y = 0; y < src_height; y++) { | for (y = 0; y < src_height; y++) { | ||||
| X[y] = buffer[offset]; | X[y] = buffer[offset]; | ||||
| offset += add; | offset += add; | ||||
| } | } | ||||
| YVV(src_height); | YVV(src_height); | ||||
| offset = x * num_channels + chan; | offset = x * num_channels + chan; | ||||
| for (y = 0; y < src_height; y++) { | for (y = 0; y < src_height; y++) { | ||||
| buffer[offset] = Y[y]; | buffer[offset] = Y[y]; | ||||
| offset += add; | offset += add; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| MEM_freeN(X); | MEM_freeN(X); | ||||
| MEM_freeN(W); | MEM_freeN(W); | ||||
| MEM_freeN(Y); | MEM_freeN(Y); | ||||
| #undef YVV | #undef YVV | ||||
| } | } | ||||
| /// | |||||
| FastGaussianBlurValueOperation::FastGaussianBlurValueOperation() | FastGaussianBlurValueOperation::FastGaussianBlurValueOperation() | ||||
| { | { | ||||
| this->addInputSocket(DataType::Value); | this->addInputSocket(DataType::Value); | ||||
| this->addOutputSocket(DataType::Value); | this->addOutputSocket(DataType::Value); | ||||
| this->m_iirgaus = nullptr; | this->m_iirgaus = nullptr; | ||||
| this->m_inputprogram = nullptr; | this->m_inputprogram = nullptr; | ||||
| this->m_sigma = 1.0f; | this->m_sigma = 1.0f; | ||||
| this->m_overlay = 0; | this->m_overlay = 0; | ||||
| ▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | else if (this->m_overlay == FAST_GAUSS_OVERLAY_MAX) { | ||||
| for (int i = copy->getWidth() * copy->getHeight(); i != 0; | for (int i = copy->getWidth() * copy->getHeight(); i != 0; | ||||
| i--, src += COM_DATA_TYPE_VALUE_CHANNELS, dst += COM_DATA_TYPE_VALUE_CHANNELS) { | i--, src += COM_DATA_TYPE_VALUE_CHANNELS, dst += COM_DATA_TYPE_VALUE_CHANNELS) { | ||||
| if (*src > *dst) { | if (*src > *dst) { | ||||
| *dst = *src; | *dst = *src; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| // newBuf-> | |||||
| this->m_iirgaus = copy; | this->m_iirgaus = copy; | ||||
| } | } | ||||
| unlockMutex(); | unlockMutex(); | ||||
| return this->m_iirgaus; | return this->m_iirgaus; | ||||
| } | } | ||||
| } // namespace blender::compositor | } // namespace blender::compositor | ||||