diff options
Diffstat (limited to 'source/blender/compositor/operations')
224 files changed, 17337 insertions, 15526 deletions
diff --git a/source/blender/compositor/operations/COM_AlphaOverKeyOperation.cpp b/source/blender/compositor/operations/COM_AlphaOverKeyOperation.cpp index 8c483f9ff23..1be5ef1f2df 100644 --- a/source/blender/compositor/operations/COM_AlphaOverKeyOperation.cpp +++ b/source/blender/compositor/operations/COM_AlphaOverKeyOperation.cpp @@ -20,32 +20,35 @@ AlphaOverKeyOperation::AlphaOverKeyOperation() : MixBaseOperation() { - /* pass */ + /* pass */ } -void AlphaOverKeyOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void AlphaOverKeyOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor1[4]; - float inputOverColor[4]; - float value[4]; + float inputColor1[4]; + float inputOverColor[4]; + float value[4]; - this->m_inputValueOperation->readSampled(value, x, y, sampler); - this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); - this->m_inputColor2Operation->readSampled(inputOverColor, x, y, sampler); + this->m_inputValueOperation->readSampled(value, x, y, sampler); + this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); + this->m_inputColor2Operation->readSampled(inputOverColor, x, y, sampler); - if (inputOverColor[3] <= 0.0f) { - copy_v4_v4(output, inputColor1); - } - else if (value[0] == 1.0f && inputOverColor[3] >= 1.0f) { - copy_v4_v4(output, inputOverColor); - } - else { - float premul = value[0] * inputOverColor[3]; - float mul = 1.0f - premul; + if (inputOverColor[3] <= 0.0f) { + copy_v4_v4(output, inputColor1); + } + else if (value[0] == 1.0f && inputOverColor[3] >= 1.0f) { + copy_v4_v4(output, inputOverColor); + } + else { + float premul = value[0] * inputOverColor[3]; + float mul = 1.0f - premul; - output[0] = (mul * inputColor1[0]) + premul * inputOverColor[0]; - output[1] = (mul * inputColor1[1]) + premul * inputOverColor[1]; - output[2] = (mul * inputColor1[2]) + premul * inputOverColor[2]; - output[3] = (mul * inputColor1[3]) + value[0] * inputOverColor[3]; - } + output[0] = (mul * inputColor1[0]) + premul * inputOverColor[0]; + output[1] = (mul * inputColor1[1]) + premul * inputOverColor[1]; + output[2] = (mul * inputColor1[2]) + premul * inputOverColor[2]; + output[3] = (mul * inputColor1[3]) + value[0] * inputOverColor[3]; + } } diff --git a/source/blender/compositor/operations/COM_AlphaOverKeyOperation.h b/source/blender/compositor/operations/COM_AlphaOverKeyOperation.h index 85b9ceed6be..a4475bc2fbc 100644 --- a/source/blender/compositor/operations/COM_AlphaOverKeyOperation.h +++ b/source/blender/compositor/operations/COM_AlphaOverKeyOperation.h @@ -20,21 +20,20 @@ #define __COM_ALPHAOVERKEYOPERATION_H__ #include "COM_MixOperation.h" - /** * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ class AlphaOverKeyOperation : public MixBaseOperation { -public: - /** - * Default constructor - */ - AlphaOverKeyOperation(); + public: + /** + * Default constructor + */ + AlphaOverKeyOperation(); - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; #endif diff --git a/source/blender/compositor/operations/COM_AlphaOverMixedOperation.cpp b/source/blender/compositor/operations/COM_AlphaOverMixedOperation.cpp index 0c7738e6c23..513158dcff6 100644 --- a/source/blender/compositor/operations/COM_AlphaOverMixedOperation.cpp +++ b/source/blender/compositor/operations/COM_AlphaOverMixedOperation.cpp @@ -20,33 +20,36 @@ AlphaOverMixedOperation::AlphaOverMixedOperation() : MixBaseOperation() { - this->m_x = 0.0f; + this->m_x = 0.0f; } -void AlphaOverMixedOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void AlphaOverMixedOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor1[4]; - float inputOverColor[4]; - float value[4]; + float inputColor1[4]; + float inputOverColor[4]; + float value[4]; - this->m_inputValueOperation->readSampled(value, x, y, sampler); - this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); - this->m_inputColor2Operation->readSampled(inputOverColor, x, y, sampler); + this->m_inputValueOperation->readSampled(value, x, y, sampler); + this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); + this->m_inputColor2Operation->readSampled(inputOverColor, x, y, sampler); - if (inputOverColor[3] <= 0.0f) { - copy_v4_v4(output, inputColor1); - } - else if (value[0] == 1.0f && inputOverColor[3] >= 1.0f) { - copy_v4_v4(output, inputOverColor); - } - else { - float addfac = 1.0f - this->m_x + inputOverColor[3] * this->m_x; - float premul = value[0] * addfac; - float mul = 1.0f - value[0] * inputOverColor[3]; + if (inputOverColor[3] <= 0.0f) { + copy_v4_v4(output, inputColor1); + } + else if (value[0] == 1.0f && inputOverColor[3] >= 1.0f) { + copy_v4_v4(output, inputOverColor); + } + else { + float addfac = 1.0f - this->m_x + inputOverColor[3] * this->m_x; + float premul = value[0] * addfac; + float mul = 1.0f - value[0] * inputOverColor[3]; - output[0] = (mul * inputColor1[0]) + premul * inputOverColor[0]; - output[1] = (mul * inputColor1[1]) + premul * inputOverColor[1]; - output[2] = (mul * inputColor1[2]) + premul * inputOverColor[2]; - output[3] = (mul * inputColor1[3]) + value[0] * inputOverColor[3]; - } + output[0] = (mul * inputColor1[0]) + premul * inputOverColor[0]; + output[1] = (mul * inputColor1[1]) + premul * inputOverColor[1]; + output[2] = (mul * inputColor1[2]) + premul * inputOverColor[2]; + output[3] = (mul * inputColor1[3]) + value[0] * inputOverColor[3]; + } } diff --git a/source/blender/compositor/operations/COM_AlphaOverMixedOperation.h b/source/blender/compositor/operations/COM_AlphaOverMixedOperation.h index 118aa426404..88fa3d963f4 100644 --- a/source/blender/compositor/operations/COM_AlphaOverMixedOperation.h +++ b/source/blender/compositor/operations/COM_AlphaOverMixedOperation.h @@ -20,25 +20,28 @@ #define __COM_ALPHAOVERMIXEDOPERATION_H__ #include "COM_MixOperation.h" - /** * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ class AlphaOverMixedOperation : public MixBaseOperation { -private: - float m_x; -public: - /** - * Default constructor - */ - AlphaOverMixedOperation(); + private: + float m_x; + + public: + /** + * Default constructor + */ + AlphaOverMixedOperation(); - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - void setX(float x) { this->m_x = x; } + void setX(float x) + { + this->m_x = x; + } }; #endif diff --git a/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.cpp b/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.cpp index f482814481d..8e5bce7221f 100644 --- a/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.cpp +++ b/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.cpp @@ -20,32 +20,35 @@ AlphaOverPremultiplyOperation::AlphaOverPremultiplyOperation() : MixBaseOperation() { - /* pass */ + /* pass */ } -void AlphaOverPremultiplyOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void AlphaOverPremultiplyOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor1[4]; - float inputOverColor[4]; - float value[4]; + float inputColor1[4]; + float inputOverColor[4]; + float value[4]; - this->m_inputValueOperation->readSampled(value, x, y, sampler); - this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); - this->m_inputColor2Operation->readSampled(inputOverColor, x, y, sampler); + this->m_inputValueOperation->readSampled(value, x, y, sampler); + this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); + this->m_inputColor2Operation->readSampled(inputOverColor, x, y, sampler); - /* Zero alpha values should still permit an add of RGB data */ - if (inputOverColor[3] < 0.0f) { - copy_v4_v4(output, inputColor1); - } - else if (value[0] == 1.0f && inputOverColor[3] >= 1.0f) { - copy_v4_v4(output, inputOverColor); - } - else { - float mul = 1.0f - value[0] * inputOverColor[3]; + /* Zero alpha values should still permit an add of RGB data */ + if (inputOverColor[3] < 0.0f) { + copy_v4_v4(output, inputColor1); + } + else if (value[0] == 1.0f && inputOverColor[3] >= 1.0f) { + copy_v4_v4(output, inputOverColor); + } + else { + float mul = 1.0f - value[0] * inputOverColor[3]; - output[0] = (mul * inputColor1[0]) + value[0] * inputOverColor[0]; - output[1] = (mul * inputColor1[1]) + value[0] * inputOverColor[1]; - output[2] = (mul * inputColor1[2]) + value[0] * inputOverColor[2]; - output[3] = (mul * inputColor1[3]) + value[0] * inputOverColor[3]; - } + output[0] = (mul * inputColor1[0]) + value[0] * inputOverColor[0]; + output[1] = (mul * inputColor1[1]) + value[0] * inputOverColor[1]; + output[2] = (mul * inputColor1[2]) + value[0] * inputOverColor[2]; + output[3] = (mul * inputColor1[3]) + value[0] * inputOverColor[3]; + } } diff --git a/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h b/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h index bf0e53c87e4..4ef5f9d996e 100644 --- a/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h +++ b/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h @@ -20,22 +20,20 @@ #define __COM_ALPHAOVERPREMULTIPLYOPERATION_H__ #include "COM_MixOperation.h" - /** * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ class AlphaOverPremultiplyOperation : public MixBaseOperation { -public: - /** - * Default constructor - */ - AlphaOverPremultiplyOperation(); - - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + /** + * Default constructor + */ + AlphaOverPremultiplyOperation(); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; #endif diff --git a/source/blender/compositor/operations/COM_AntiAliasOperation.cpp b/source/blender/compositor/operations/COM_AntiAliasOperation.cpp index a33fe6bcdb0..94514c64e08 100644 --- a/source/blender/compositor/operations/COM_AntiAliasOperation.cpp +++ b/source/blender/compositor/operations/COM_AntiAliasOperation.cpp @@ -23,126 +23,165 @@ #include "MEM_guardedalloc.h" extern "C" { -# include "RE_render_ext.h" +#include "RE_render_ext.h" } - /* An implementation of the Scale3X edge-extrapolation algorithm. * * Code from GIMP plugin, based on code from Adam D. Moss (adam@gimp.org) * licensed by the MIT license. */ -static int extrapolate9(float *E0, float *E1, float *E2, - float *E3, float *E4, float *E5, - float *E6, float *E7, float *E8, - const float *A, const float *B, const float *C, - const float *D, const float *E, const float *F, - const float *G, const float *H, const float *I) +static int extrapolate9(float *E0, + float *E1, + float *E2, + float *E3, + float *E4, + float *E5, + float *E6, + float *E7, + float *E8, + const float *A, + const float *B, + const float *C, + const float *D, + const float *E, + const float *F, + const float *G, + const float *H, + const float *I) { #define PEQ(X, Y) (fabsf(*X - *Y) < 1e-3f) -#define PCPY(DST, SRC) do { *DST = *SRC; } while (0) - if ((!PEQ(B, H)) && (!PEQ(D, F))) { - if (PEQ(D, B)) PCPY(E0, D); else PCPY(E0, E); - if ((PEQ(D, B) && !PEQ(E, C)) || (PEQ(B, F) && !PEQ(E, A))) - PCPY(E1, B); else PCPY(E1, E); - if (PEQ(B, F)) PCPY(E2, F); else PCPY(E2, E); - if ((PEQ(D, B) && !PEQ(E, G)) || (PEQ(D, H) && !PEQ(E, A))) - PCPY(E3, D); else PCPY(E3, E); - PCPY(E4, E); - if ((PEQ(B, F) && !PEQ(E, I)) || (PEQ(H, F) && !PEQ(E, C))) - PCPY(E5, F); else PCPY(E5, E); - if (PEQ(D, H)) PCPY(E6, D); else PCPY(E6, E); - if ((PEQ(D, H) && !PEQ(E, I)) || (PEQ(H, F) && !PEQ(E, G))) - PCPY(E7, H); else PCPY(E7, E); - if (PEQ(H, F)) PCPY(E8, F); else PCPY(E8, E); - return 1; - } - else { - return 0; - } +#define PCPY(DST, SRC) \ + do { \ + *DST = *SRC; \ + } while (0) + if ((!PEQ(B, H)) && (!PEQ(D, F))) { + if (PEQ(D, B)) + PCPY(E0, D); + else + PCPY(E0, E); + if ((PEQ(D, B) && !PEQ(E, C)) || (PEQ(B, F) && !PEQ(E, A))) + PCPY(E1, B); + else + PCPY(E1, E); + if (PEQ(B, F)) + PCPY(E2, F); + else + PCPY(E2, E); + if ((PEQ(D, B) && !PEQ(E, G)) || (PEQ(D, H) && !PEQ(E, A))) + PCPY(E3, D); + else + PCPY(E3, E); + PCPY(E4, E); + if ((PEQ(B, F) && !PEQ(E, I)) || (PEQ(H, F) && !PEQ(E, C))) + PCPY(E5, F); + else + PCPY(E5, E); + if (PEQ(D, H)) + PCPY(E6, D); + else + PCPY(E6, E); + if ((PEQ(D, H) && !PEQ(E, I)) || (PEQ(H, F) && !PEQ(E, G))) + PCPY(E7, H); + else + PCPY(E7, E); + if (PEQ(H, F)) + PCPY(E8, F); + else + PCPY(E8, E); + return 1; + } + else { + return 0; + } #undef PEQ #undef PCPY } AntiAliasOperation::AntiAliasOperation() : NodeOperation() { - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_VALUE); - this->m_valueReader = NULL; - this->setComplex(true); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_VALUE); + this->m_valueReader = NULL; + this->setComplex(true); } void AntiAliasOperation::initExecution() { - this->m_valueReader = this->getInputSocketReader(0); + this->m_valueReader = this->getInputSocketReader(0); } -void AntiAliasOperation::executePixel(float output[4], - int x, int y, - void *data) +void AntiAliasOperation::executePixel(float output[4], int x, int y, void *data) { - MemoryBuffer *input_buffer = (MemoryBuffer *)data; - const int buffer_width = input_buffer->getWidth(), - buffer_height = input_buffer->getHeight(); - if (y < 0 || y >= buffer_height || x < 0 || x >= buffer_width) { - output[0] = 0.0f; - } - else { - const float *buffer = input_buffer->getBuffer(); - const float *row_curr = &buffer[y * buffer_width]; - if (x == 0 || x == buffer_width - 1 || - y == 0 || y == buffer_height - 1) - { - output[0] = row_curr[x]; - return; - } - const float *row_prev = &buffer[(y - 1) * buffer_width], - *row_next = &buffer[(y + 1) * buffer_width]; - float ninepix[9]; - if (extrapolate9(&ninepix[0], &ninepix[1], &ninepix[2], - &ninepix[3], &ninepix[4], &ninepix[5], - &ninepix[6], &ninepix[7], &ninepix[8], - &row_prev[x - 1], &row_prev[x], &row_prev[x + 1], - &row_curr[x - 1], &row_curr[x], &row_curr[x + 1], - &row_next[x - 1], &row_next[x], &row_next[x + 1])) - { - /* Some rounding magic to so make weighting correct with the - * original coefficients. - */ - unsigned char result = ((3 * ninepix[0] + 5 * ninepix[1] + 3 * ninepix[2] + - 5 * ninepix[3] + 6 * ninepix[4] + 5 * ninepix[5] + - 3 * ninepix[6] + 5 * ninepix[7] + 3 * ninepix[8]) * 255.0f + - 19.0f) / 38.0f; - output[0] = result / 255.0f; - } - else { - output[0] = row_curr[x]; - } - } + MemoryBuffer *input_buffer = (MemoryBuffer *)data; + const int buffer_width = input_buffer->getWidth(), buffer_height = input_buffer->getHeight(); + if (y < 0 || y >= buffer_height || x < 0 || x >= buffer_width) { + output[0] = 0.0f; + } + else { + const float *buffer = input_buffer->getBuffer(); + const float *row_curr = &buffer[y * buffer_width]; + if (x == 0 || x == buffer_width - 1 || y == 0 || y == buffer_height - 1) { + output[0] = row_curr[x]; + return; + } + const float *row_prev = &buffer[(y - 1) * buffer_width], + *row_next = &buffer[(y + 1) * buffer_width]; + float ninepix[9]; + if (extrapolate9(&ninepix[0], + &ninepix[1], + &ninepix[2], + &ninepix[3], + &ninepix[4], + &ninepix[5], + &ninepix[6], + &ninepix[7], + &ninepix[8], + &row_prev[x - 1], + &row_prev[x], + &row_prev[x + 1], + &row_curr[x - 1], + &row_curr[x], + &row_curr[x + 1], + &row_next[x - 1], + &row_next[x], + &row_next[x + 1])) { + /* Some rounding magic to so make weighting correct with the + * original coefficients. + */ + unsigned char result = ((3 * ninepix[0] + 5 * ninepix[1] + 3 * ninepix[2] + 5 * ninepix[3] + + 6 * ninepix[4] + 5 * ninepix[5] + 3 * ninepix[6] + 5 * ninepix[7] + + 3 * ninepix[8]) * + 255.0f + + 19.0f) / + 38.0f; + output[0] = result / 255.0f; + } + else { + output[0] = row_curr[x]; + } + } } void AntiAliasOperation::deinitExecution() { - this->m_valueReader = NULL; + this->m_valueReader = NULL; } -bool AntiAliasOperation::determineDependingAreaOfInterest( - rcti *input, - ReadBufferOperation *readOperation, - rcti *output) +bool AntiAliasOperation::determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output) { - rcti imageInput; - NodeOperation *operation = getInputOperation(0); - imageInput.xmax = input->xmax + 1; - imageInput.xmin = input->xmin - 1; - imageInput.ymax = input->ymax + 1; - imageInput.ymin = input->ymin - 1; - return operation->determineDependingAreaOfInterest(&imageInput, - readOperation, - output); + rcti imageInput; + NodeOperation *operation = getInputOperation(0); + imageInput.xmax = input->xmax + 1; + imageInput.xmin = input->xmin - 1; + imageInput.ymax = input->ymax + 1; + imageInput.ymin = input->ymin - 1; + return operation->determineDependingAreaOfInterest(&imageInput, readOperation, output); } void *AntiAliasOperation::initializeTileData(rcti *rect) { - return getInputOperation(0)->initializeTileData(rect); + return getInputOperation(0)->initializeTileData(rect); } diff --git a/source/blender/compositor/operations/COM_AntiAliasOperation.h b/source/blender/compositor/operations/COM_AntiAliasOperation.h index d589be8a7dd..6141fb92c3f 100644 --- a/source/blender/compositor/operations/COM_AntiAliasOperation.h +++ b/source/blender/compositor/operations/COM_AntiAliasOperation.h @@ -27,30 +27,33 @@ * \ingroup operation */ class AntiAliasOperation : public NodeOperation { -protected: - /** - * \brief Cached reference to the reader - */ - SocketReader *m_valueReader; -public: - AntiAliasOperation(); + protected: + /** + * \brief Cached reference to the reader + */ + SocketReader *m_valueReader; - /** - * the inner loop of this program - */ - void executePixel(float output[4], int x, int y, void *data); + public: + AntiAliasOperation(); - /** - * Initialize the execution - */ - void initExecution(); + /** + * the inner loop of this program + */ + void executePixel(float output[4], int x, int y, void *data); - void *initializeTileData(rcti *rect); + /** + * Initialize the execution + */ + void initExecution(); - /** - * Deinitialize the execution - */ - void deinitExecution(); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + void *initializeTileData(rcti *rect); + + /** + * Deinitialize the execution + */ + void deinitExecution(); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); }; #endif diff --git a/source/blender/compositor/operations/COM_BilateralBlurOperation.cpp b/source/blender/compositor/operations/COM_BilateralBlurOperation.cpp index f866eac8ae3..5628c575b70 100644 --- a/source/blender/compositor/operations/COM_BilateralBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_BilateralBlurOperation.cpp @@ -20,93 +20,96 @@ #include "BLI_math.h" extern "C" { -# include "RE_pipeline.h" +#include "RE_pipeline.h" } BilateralBlurOperation::BilateralBlurOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - this->setComplex(true); + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); + this->setComplex(true); - this->m_inputColorProgram = NULL; - this->m_inputDeterminatorProgram = NULL; + this->m_inputColorProgram = NULL; + this->m_inputDeterminatorProgram = NULL; } void BilateralBlurOperation::initExecution() { - this->m_inputColorProgram = getInputSocketReader(0); - this->m_inputDeterminatorProgram = getInputSocketReader(1); - this->m_space = this->m_data->sigma_space + this->m_data->iter; - QualityStepHelper::initExecution(COM_QH_INCREASE); + this->m_inputColorProgram = getInputSocketReader(0); + this->m_inputDeterminatorProgram = getInputSocketReader(1); + this->m_space = this->m_data->sigma_space + this->m_data->iter; + QualityStepHelper::initExecution(COM_QH_INCREASE); } void BilateralBlurOperation::executePixel(float output[4], int x, int y, void *data) { - // read the determinator color at x, y, this will be used as the reference color for the determinator - float determinatorReferenceColor[4]; - float determinator[4]; - float tempColor[4]; - float blurColor[4]; - float blurDivider; - float space = this->m_space; - float sigmacolor = this->m_data->sigma_color; - int minx = floor(x - space); - int maxx = ceil(x + space); - int miny = floor(y - space); - int maxy = ceil(y + space); - float deltaColor; - this->m_inputDeterminatorProgram->read(determinatorReferenceColor, x, y, data); + // read the determinator color at x, y, this will be used as the reference color for the determinator + float determinatorReferenceColor[4]; + float determinator[4]; + float tempColor[4]; + float blurColor[4]; + float blurDivider; + float space = this->m_space; + float sigmacolor = this->m_data->sigma_color; + int minx = floor(x - space); + int maxx = ceil(x + space); + int miny = floor(y - space); + int maxy = ceil(y + space); + float deltaColor; + this->m_inputDeterminatorProgram->read(determinatorReferenceColor, x, y, data); - zero_v4(blurColor); - blurDivider = 0.0f; - /* TODO(sergey): This isn't really good bilateral filter, it should be - * using gaussian bell for weights. Also sigma_color doesn't seem to be - * used correct at all. - */ - for (int yi = miny; yi < maxy; yi += QualityStepHelper::getStep()) { - for (int xi = minx; xi < maxx; xi += QualityStepHelper::getStep()) { - // read determinator - this->m_inputDeterminatorProgram->read(determinator, xi, yi, data); - deltaColor = (fabsf(determinatorReferenceColor[0] - determinator[0]) + - fabsf(determinatorReferenceColor[1] - determinator[1]) + - fabsf(determinatorReferenceColor[2] - determinator[2])); // do not take the alpha channel into account - if (deltaColor < sigmacolor) { - // add this to the blur - this->m_inputColorProgram->read(tempColor, xi, yi, data); - add_v4_v4(blurColor, tempColor); - blurDivider += 1.0f; - } - } - } + zero_v4(blurColor); + blurDivider = 0.0f; + /* TODO(sergey): This isn't really good bilateral filter, it should be + * using gaussian bell for weights. Also sigma_color doesn't seem to be + * used correct at all. + */ + for (int yi = miny; yi < maxy; yi += QualityStepHelper::getStep()) { + for (int xi = minx; xi < maxx; xi += QualityStepHelper::getStep()) { + // read determinator + this->m_inputDeterminatorProgram->read(determinator, xi, yi, data); + deltaColor = (fabsf(determinatorReferenceColor[0] - determinator[0]) + + fabsf(determinatorReferenceColor[1] - determinator[1]) + + fabsf(determinatorReferenceColor[2] - + determinator[2])); // do not take the alpha channel into account + if (deltaColor < sigmacolor) { + // add this to the blur + this->m_inputColorProgram->read(tempColor, xi, yi, data); + add_v4_v4(blurColor, tempColor); + blurDivider += 1.0f; + } + } + } - if (blurDivider > 0.0f) { - mul_v4_v4fl(output, blurColor, 1.0f / blurDivider); - } - else { - output[0] = 0.0f; - output[1] = 0.0f; - output[2] = 0.0f; - output[3] = 1.0f; - } + if (blurDivider > 0.0f) { + mul_v4_v4fl(output, blurColor, 1.0f / blurDivider); + } + else { + output[0] = 0.0f; + output[1] = 0.0f; + output[2] = 0.0f; + output[3] = 1.0f; + } } void BilateralBlurOperation::deinitExecution() { - this->m_inputColorProgram = NULL; - this->m_inputDeterminatorProgram = NULL; + this->m_inputColorProgram = NULL; + this->m_inputDeterminatorProgram = NULL; } -bool BilateralBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool BilateralBlurOperation::determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output) { - rcti newInput; - int add = ceil(this->m_space) + 1; + rcti newInput; + int add = ceil(this->m_space) + 1; - newInput.xmax = input->xmax + (add); - newInput.xmin = input->xmin - (add); - newInput.ymax = input->ymax + (add); - newInput.ymin = input->ymin - (add); + newInput.xmax = input->xmax + (add); + newInput.xmin = input->xmin - (add); + newInput.ymax = input->ymax + (add); + newInput.ymin = input->ymin - (add); - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } diff --git a/source/blender/compositor/operations/COM_BilateralBlurOperation.h b/source/blender/compositor/operations/COM_BilateralBlurOperation.h index e0275beca50..c3482005d8c 100644 --- a/source/blender/compositor/operations/COM_BilateralBlurOperation.h +++ b/source/blender/compositor/operations/COM_BilateralBlurOperation.h @@ -22,32 +22,37 @@ #include "COM_QualityStepHelper.h" class BilateralBlurOperation : public NodeOperation, public QualityStepHelper { -private: - SocketReader *m_inputColorProgram; - SocketReader *m_inputDeterminatorProgram; - NodeBilateralBlurData *m_data; - float m_space; - -public: - BilateralBlurOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], int x, int y, void *data); - - /** - * Initialize the execution - */ - void initExecution(); - - /** - * Deinitialize the execution - */ - void deinitExecution(); - - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - - void setData(NodeBilateralBlurData *data) { this->m_data = data; } + private: + SocketReader *m_inputColorProgram; + SocketReader *m_inputDeterminatorProgram; + NodeBilateralBlurData *m_data; + float m_space; + + public: + BilateralBlurOperation(); + + /** + * the inner loop of this program + */ + void executePixel(float output[4], int x, int y, void *data); + + /** + * Initialize the execution + */ + void initExecution(); + + /** + * Deinitialize the execution + */ + void deinitExecution(); + + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + + void setData(NodeBilateralBlurData *data) + { + this->m_data = data; + } }; #endif diff --git a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp index d1a55de1431..aca98085a3e 100644 --- a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp @@ -21,82 +21,81 @@ #include "MEM_guardedalloc.h" extern "C" { -# include "RE_pipeline.h" +#include "RE_pipeline.h" } BlurBaseOperation::BlurBaseOperation(DataType data_type) : NodeOperation() { - /* data_type is almost always COM_DT_COLOR except for alpha-blur */ - this->addInputSocket(data_type); - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(data_type); - this->setComplex(true); - this->m_inputProgram = NULL; - memset(&m_data, 0, sizeof(NodeBlurData)); - this->m_size = 1.0f; - this->m_sizeavailable = false; - this->m_extend_bounds = false; + /* data_type is almost always COM_DT_COLOR except for alpha-blur */ + this->addInputSocket(data_type); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(data_type); + this->setComplex(true); + this->m_inputProgram = NULL; + memset(&m_data, 0, sizeof(NodeBlurData)); + this->m_size = 1.0f; + this->m_sizeavailable = false; + this->m_extend_bounds = false; } void BlurBaseOperation::initExecution() { - this->m_inputProgram = this->getInputSocketReader(0); - this->m_inputSize = this->getInputSocketReader(1); - 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; - } - } - - QualityStepHelper::initExecution(COM_QH_MULTIPLY); - + this->m_inputProgram = this->getInputSocketReader(0); + this->m_inputSize = this->getInputSocketReader(1); + 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; + } + } + + QualityStepHelper::initExecution(COM_QH_MULTIPLY); } float *BlurBaseOperation::make_gausstab(float rad, int size) { - float *gausstab, sum, val; - int i, n; + float *gausstab, sum, val; + int i, n; - n = 2 * size + 1; + n = 2 * size + 1; - gausstab = (float *)MEM_mallocN(sizeof(float) * n, __func__); + gausstab = (float *)MEM_mallocN(sizeof(float) * n, __func__); - sum = 0.0f; - float fac = (rad > 0.0f ? 1.0f / rad : 0.0f); - for (i = -size; i <= size; i++) { - val = RE_filter_value(this->m_data.filtertype, (float)i * fac); - sum += val; - gausstab[i + size] = val; - } + sum = 0.0f; + float fac = (rad > 0.0f ? 1.0f / rad : 0.0f); + for (i = -size; i <= size; i++) { + val = RE_filter_value(this->m_data.filtertype, (float)i * fac); + sum += val; + gausstab[i + size] = val; + } - sum = 1.0f / sum; - for (i = 0; i < n; i++) - gausstab[i] *= sum; + sum = 1.0f / sum; + for (i = 0; i < n; i++) + gausstab[i] *= sum; - return gausstab; + return gausstab; } #ifdef __SSE2__ __m128 *BlurBaseOperation::convert_gausstab_sse(const float *gausstab, int size) { - int n = 2 * size + 1; - __m128 *gausstab_sse = (__m128 *) MEM_mallocN_aligned(sizeof(__m128) * n, 16, "gausstab sse"); - for (int i = 0; i < n; ++i) { - gausstab_sse[i] = _mm_set1_ps(gausstab[i]); - } - return gausstab_sse; + int n = 2 * size + 1; + __m128 *gausstab_sse = (__m128 *)MEM_mallocN_aligned(sizeof(__m128) * n, 16, "gausstab sse"); + for (int i = 0; i < n; ++i) { + gausstab_sse[i] = _mm_set1_ps(gausstab[i]); + } + return gausstab_sse; } #endif @@ -104,81 +103,80 @@ __m128 *BlurBaseOperation::convert_gausstab_sse(const float *gausstab, int size) * 'ease' is applied after, looks nicer */ float *BlurBaseOperation::make_dist_fac_inverse(float rad, int size, int falloff) { - float *dist_fac_invert, val; - int i, n; - - n = 2 * size + 1; - - dist_fac_invert = (float *)MEM_mallocN(sizeof(float) * n, __func__); - - float fac = (rad > 0.0f ? 1.0f / rad : 0.0f); - for (i = -size; i <= size; i++) { - val = 1.0f - fabsf((float)i * fac); - - /* keep in sync with rna_enum_proportional_falloff_curve_only_items */ - switch (falloff) { - case PROP_SMOOTH: - /* ease - gives less hard lines for dilate/erode feather */ - val = (3.0f * val * val - 2.0f * val * val * val); - break; - case PROP_SPHERE: - val = sqrtf(2.0f * val - val * val); - break; - case PROP_ROOT: - val = sqrtf(val); - break; - case PROP_SHARP: - val = val * val; - break; - case PROP_INVSQUARE: - val = val * (2.0f - val); - break; - case PROP_LIN: - /* fall-through */ + float *dist_fac_invert, val; + int i, n; + + n = 2 * size + 1; + + dist_fac_invert = (float *)MEM_mallocN(sizeof(float) * n, __func__); + + float fac = (rad > 0.0f ? 1.0f / rad : 0.0f); + for (i = -size; i <= size; i++) { + val = 1.0f - fabsf((float)i * fac); + + /* keep in sync with rna_enum_proportional_falloff_curve_only_items */ + switch (falloff) { + case PROP_SMOOTH: + /* ease - gives less hard lines for dilate/erode feather */ + val = (3.0f * val * val - 2.0f * val * val * val); + break; + case PROP_SPHERE: + val = sqrtf(2.0f * val - val * val); + break; + case PROP_ROOT: + val = sqrtf(val); + break; + case PROP_SHARP: + val = val * val; + break; + case PROP_INVSQUARE: + val = val * (2.0f - val); + break; + case PROP_LIN: + /* fall-through */ #ifndef NDEBUG - case -1: - /* uninitialized! */ - BLI_assert(0); - break; + case -1: + /* uninitialized! */ + BLI_assert(0); + break; #endif - default: - /* nothing */ - break; - } - dist_fac_invert[i + size] = val; - } - - return dist_fac_invert; + default: + /* nothing */ + break; + } + dist_fac_invert[i + size] = val; + } + + return dist_fac_invert; } void BlurBaseOperation::deinitExecution() { - this->m_inputProgram = NULL; - this->m_inputSize = NULL; + this->m_inputProgram = NULL; + this->m_inputSize = NULL; } void BlurBaseOperation::setData(const NodeBlurData *data) { - memcpy(&m_data, data, sizeof(NodeBlurData)); + memcpy(&m_data, data, sizeof(NodeBlurData)); } void BlurBaseOperation::updateSize() { - if (!this->m_sizeavailable) { - float result[4]; - this->getInputSocketReader(1)->readSampled(result, 0, 0, COM_PS_NEAREST); - this->m_size = result[0]; - this->m_sizeavailable = true; - } + if (!this->m_sizeavailable) { + float result[4]; + this->getInputSocketReader(1)->readSampled(result, 0, 0, COM_PS_NEAREST); + this->m_size = result[0]; + this->m_sizeavailable = true; + } } void BlurBaseOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) { - NodeOperation::determineResolution(resolution, - preferredResolution); - if (this->m_extend_bounds) { - resolution[0] += 2 * this->m_size * m_data.sizex; - resolution[1] += 2 * this->m_size * m_data.sizey; - } + NodeOperation::determineResolution(resolution, preferredResolution); + if (this->m_extend_bounds) { + resolution[0] += 2 * this->m_size * m_data.sizex; + resolution[1] += 2 * this->m_size * m_data.sizey; + } } diff --git a/source/blender/compositor/operations/COM_BlurBaseOperation.h b/source/blender/compositor/operations/COM_BlurBaseOperation.h index a2bac326d59..07893c19126 100644 --- a/source/blender/compositor/operations/COM_BlurBaseOperation.h +++ b/source/blender/compositor/operations/COM_BlurBaseOperation.h @@ -28,49 +28,53 @@ #endif class BlurBaseOperation : public NodeOperation, public QualityStepHelper { -private: - -protected: - - BlurBaseOperation(DataType data_type); - float *make_gausstab(float rad, int size); + private: + protected: + BlurBaseOperation(DataType data_type); + float *make_gausstab(float rad, int size); #ifdef __SSE2__ - __m128 *convert_gausstab_sse(const float *gaustab, int size); + __m128 *convert_gausstab_sse(const float *gaustab, int size); #endif - float *make_dist_fac_inverse(float rad, int size, int falloff); + float *make_dist_fac_inverse(float rad, int size, int falloff); - void updateSize(); + void updateSize(); - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputProgram; - SocketReader *m_inputSize; - NodeBlurData m_data; + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputProgram; + SocketReader *m_inputSize; + NodeBlurData m_data; - float m_size; - bool m_sizeavailable; + float m_size; + bool m_sizeavailable; - bool m_extend_bounds; + bool m_extend_bounds; -public: - /** - * Initialize the execution - */ - void initExecution(); + public: + /** + * Initialize the execution + */ + void initExecution(); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Deinitialize the execution + */ + void deinitExecution(); - void setData(const NodeBlurData *data); + void setData(const NodeBlurData *data); - void setSize(float size) { this->m_size = size; this->m_sizeavailable = true; } + void setSize(float size) + { + this->m_size = size; + this->m_sizeavailable = true; + } - void setExtendBounds(bool extend_bounds) { this->m_extend_bounds = extend_bounds; } + void setExtendBounds(bool extend_bounds) + { + this->m_extend_bounds = extend_bounds; + } - void determineResolution(unsigned int resolution[2], - unsigned int preferredResolution[2]); + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); }; #endif diff --git a/source/blender/compositor/operations/COM_BokehBlurOperation.cpp b/source/blender/compositor/operations/COM_BokehBlurOperation.cpp index b6e0779c206..4d858934796 100644 --- a/source/blender/compositor/operations/COM_BokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_BokehBlurOperation.cpp @@ -21,218 +21,224 @@ #include "COM_OpenCLDevice.h" extern "C" { -# include "RE_pipeline.h" +#include "RE_pipeline.h" } BokehBlurOperation::BokehBlurOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_COLOR); - this->setComplex(true); - this->setOpenCL(true); - - this->m_size = 1.0f; - this->m_sizeavailable = false; - this->m_inputProgram = NULL; - this->m_inputBokehProgram = NULL; - this->m_inputBoundingBoxReader = NULL; - - this->m_extend_bounds = false; + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_COLOR); + this->setComplex(true); + this->setOpenCL(true); + + this->m_size = 1.0f; + this->m_sizeavailable = false; + this->m_inputProgram = NULL; + this->m_inputBokehProgram = NULL; + this->m_inputBoundingBoxReader = NULL; + + this->m_extend_bounds = false; } void *BokehBlurOperation::initializeTileData(rcti * /*rect*/) { - lockMutex(); - if (!this->m_sizeavailable) { - updateSize(); - } - void *buffer = getInputOperation(0)->initializeTileData(NULL); - unlockMutex(); - return buffer; + lockMutex(); + if (!this->m_sizeavailable) { + updateSize(); + } + void *buffer = getInputOperation(0)->initializeTileData(NULL); + unlockMutex(); + return buffer; } void BokehBlurOperation::initExecution() { - initMutex(); - this->m_inputProgram = getInputSocketReader(0); - this->m_inputBokehProgram = getInputSocketReader(1); - this->m_inputBoundingBoxReader = getInputSocketReader(2); + initMutex(); + this->m_inputProgram = getInputSocketReader(0); + this->m_inputBokehProgram = getInputSocketReader(1); + this->m_inputBoundingBoxReader = getInputSocketReader(2); - int width = this->m_inputBokehProgram->getWidth(); - int height = this->m_inputBokehProgram->getHeight(); + int width = this->m_inputBokehProgram->getWidth(); + int height = this->m_inputBokehProgram->getHeight(); - float dimension = min(width, height); + float dimension = min(width, height); - this->m_bokehMidX = width / 2.0f; - this->m_bokehMidY = height / 2.0f; - this->m_bokehDimension = dimension / 2.0f; - QualityStepHelper::initExecution(COM_QH_INCREASE); + this->m_bokehMidX = width / 2.0f; + this->m_bokehMidY = height / 2.0f; + this->m_bokehDimension = dimension / 2.0f; + QualityStepHelper::initExecution(COM_QH_INCREASE); } void BokehBlurOperation::executePixel(float output[4], int x, int y, void *data) { - float color_accum[4]; - float tempBoundingBox[4]; - float bokeh[4]; - - this->m_inputBoundingBoxReader->readSampled(tempBoundingBox, x, y, COM_PS_NEAREST); - if (tempBoundingBox[0] > 0.0f) { - float multiplier_accum[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - MemoryBuffer *inputBuffer = (MemoryBuffer *)data; - float *buffer = inputBuffer->getBuffer(); - int bufferwidth = inputBuffer->getWidth(); - int bufferstartx = inputBuffer->getRect()->xmin; - int bufferstarty = inputBuffer->getRect()->ymin; - const float max_dim = max(this->getWidth(), this->getHeight()); - int pixelSize = this->m_size * max_dim / 100.0f; - zero_v4(color_accum); - - if (pixelSize < 2) { - this->m_inputProgram->readSampled(color_accum, x, y, COM_PS_NEAREST); - multiplier_accum[0] = 1.0f; - multiplier_accum[1] = 1.0f; - multiplier_accum[2] = 1.0f; - multiplier_accum[3] = 1.0f; - } - int miny = y - pixelSize; - int maxy = y + pixelSize; - int minx = x - pixelSize; - int maxx = x + pixelSize; - miny = max(miny, inputBuffer->getRect()->ymin); - minx = max(minx, inputBuffer->getRect()->xmin); - maxy = min(maxy, inputBuffer->getRect()->ymax); - maxx = min(maxx, inputBuffer->getRect()->xmax); - - - int step = getStep(); - int offsetadd = getOffsetAdd() * COM_NUM_CHANNELS_COLOR; - - float m = this->m_bokehDimension / pixelSize; - for (int ny = miny; ny < maxy; ny += step) { - int bufferindex = ((minx - bufferstartx) * COM_NUM_CHANNELS_COLOR) + ((ny - bufferstarty) * COM_NUM_CHANNELS_COLOR * bufferwidth); - for (int nx = minx; nx < maxx; nx += step) { - float u = this->m_bokehMidX - (nx - x) * m; - float v = this->m_bokehMidY - (ny - y) * m; - this->m_inputBokehProgram->readSampled(bokeh, u, v, COM_PS_NEAREST); - madd_v4_v4v4(color_accum, bokeh, &buffer[bufferindex]); - add_v4_v4(multiplier_accum, bokeh); - bufferindex += offsetadd; - } - } - output[0] = color_accum[0] * (1.0f / multiplier_accum[0]); - output[1] = color_accum[1] * (1.0f / multiplier_accum[1]); - output[2] = color_accum[2] * (1.0f / multiplier_accum[2]); - output[3] = color_accum[3] * (1.0f / multiplier_accum[3]); - } - else { - this->m_inputProgram->readSampled(output, x, y, COM_PS_NEAREST); - } + float color_accum[4]; + float tempBoundingBox[4]; + float bokeh[4]; + + this->m_inputBoundingBoxReader->readSampled(tempBoundingBox, x, y, COM_PS_NEAREST); + if (tempBoundingBox[0] > 0.0f) { + float multiplier_accum[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + MemoryBuffer *inputBuffer = (MemoryBuffer *)data; + float *buffer = inputBuffer->getBuffer(); + int bufferwidth = inputBuffer->getWidth(); + int bufferstartx = inputBuffer->getRect()->xmin; + int bufferstarty = inputBuffer->getRect()->ymin; + const float max_dim = max(this->getWidth(), this->getHeight()); + int pixelSize = this->m_size * max_dim / 100.0f; + zero_v4(color_accum); + + if (pixelSize < 2) { + this->m_inputProgram->readSampled(color_accum, x, y, COM_PS_NEAREST); + multiplier_accum[0] = 1.0f; + multiplier_accum[1] = 1.0f; + multiplier_accum[2] = 1.0f; + multiplier_accum[3] = 1.0f; + } + int miny = y - pixelSize; + int maxy = y + pixelSize; + int minx = x - pixelSize; + int maxx = x + pixelSize; + miny = max(miny, inputBuffer->getRect()->ymin); + minx = max(minx, inputBuffer->getRect()->xmin); + maxy = min(maxy, inputBuffer->getRect()->ymax); + maxx = min(maxx, inputBuffer->getRect()->xmax); + + int step = getStep(); + int offsetadd = getOffsetAdd() * COM_NUM_CHANNELS_COLOR; + + float m = this->m_bokehDimension / pixelSize; + for (int ny = miny; ny < maxy; ny += step) { + int bufferindex = ((minx - bufferstartx) * COM_NUM_CHANNELS_COLOR) + + ((ny - bufferstarty) * COM_NUM_CHANNELS_COLOR * bufferwidth); + for (int nx = minx; nx < maxx; nx += step) { + float u = this->m_bokehMidX - (nx - x) * m; + float v = this->m_bokehMidY - (ny - y) * m; + this->m_inputBokehProgram->readSampled(bokeh, u, v, COM_PS_NEAREST); + madd_v4_v4v4(color_accum, bokeh, &buffer[bufferindex]); + add_v4_v4(multiplier_accum, bokeh); + bufferindex += offsetadd; + } + } + output[0] = color_accum[0] * (1.0f / multiplier_accum[0]); + output[1] = color_accum[1] * (1.0f / multiplier_accum[1]); + output[2] = color_accum[2] * (1.0f / multiplier_accum[2]); + output[3] = color_accum[3] * (1.0f / multiplier_accum[3]); + } + else { + this->m_inputProgram->readSampled(output, x, y, COM_PS_NEAREST); + } } void BokehBlurOperation::deinitExecution() { - deinitMutex(); - this->m_inputProgram = NULL; - this->m_inputBokehProgram = NULL; - this->m_inputBoundingBoxReader = NULL; + deinitMutex(); + this->m_inputProgram = NULL; + this->m_inputBokehProgram = NULL; + this->m_inputBoundingBoxReader = NULL; } -bool BokehBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool BokehBlurOperation::determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output) { - rcti newInput; - rcti bokehInput; - const float max_dim = max(this->getWidth(), this->getHeight()); - - if (this->m_sizeavailable) { - newInput.xmax = input->xmax + (this->m_size * max_dim / 100.0f); - newInput.xmin = input->xmin - (this->m_size * max_dim / 100.0f); - newInput.ymax = input->ymax + (this->m_size * max_dim / 100.0f); - newInput.ymin = input->ymin - (this->m_size * max_dim / 100.0f); - } - else { - newInput.xmax = input->xmax + (10.0f * max_dim / 100.0f); - newInput.xmin = input->xmin - (10.0f * max_dim / 100.0f); - newInput.ymax = input->ymax + (10.0f * max_dim / 100.0f); - newInput.ymin = input->ymin - (10.0f * max_dim / 100.0f); - } - - NodeOperation *operation = getInputOperation(1); - bokehInput.xmax = operation->getWidth(); - bokehInput.xmin = 0; - bokehInput.ymax = operation->getHeight(); - bokehInput.ymin = 0; - if (operation->determineDependingAreaOfInterest(&bokehInput, readOperation, output) ) { - return true; - } - operation = getInputOperation(0); - if (operation->determineDependingAreaOfInterest(&newInput, readOperation, output) ) { - return true; - } - operation = getInputOperation(2); - if (operation->determineDependingAreaOfInterest(input, readOperation, output) ) { - return true; - } - if (!this->m_sizeavailable) { - rcti sizeInput; - sizeInput.xmin = 0; - sizeInput.ymin = 0; - sizeInput.xmax = 5; - sizeInput.ymax = 5; - operation = getInputOperation(3); - if (operation->determineDependingAreaOfInterest(&sizeInput, readOperation, output) ) { - return true; - } - } - return false; + rcti newInput; + rcti bokehInput; + const float max_dim = max(this->getWidth(), this->getHeight()); + + if (this->m_sizeavailable) { + newInput.xmax = input->xmax + (this->m_size * max_dim / 100.0f); + newInput.xmin = input->xmin - (this->m_size * max_dim / 100.0f); + newInput.ymax = input->ymax + (this->m_size * max_dim / 100.0f); + newInput.ymin = input->ymin - (this->m_size * max_dim / 100.0f); + } + else { + newInput.xmax = input->xmax + (10.0f * max_dim / 100.0f); + newInput.xmin = input->xmin - (10.0f * max_dim / 100.0f); + newInput.ymax = input->ymax + (10.0f * max_dim / 100.0f); + newInput.ymin = input->ymin - (10.0f * max_dim / 100.0f); + } + + NodeOperation *operation = getInputOperation(1); + bokehInput.xmax = operation->getWidth(); + bokehInput.xmin = 0; + bokehInput.ymax = operation->getHeight(); + bokehInput.ymin = 0; + if (operation->determineDependingAreaOfInterest(&bokehInput, readOperation, output)) { + return true; + } + operation = getInputOperation(0); + if (operation->determineDependingAreaOfInterest(&newInput, readOperation, output)) { + return true; + } + operation = getInputOperation(2); + if (operation->determineDependingAreaOfInterest(input, readOperation, output)) { + return true; + } + if (!this->m_sizeavailable) { + rcti sizeInput; + sizeInput.xmin = 0; + sizeInput.ymin = 0; + sizeInput.xmax = 5; + sizeInput.ymax = 5; + operation = getInputOperation(3); + if (operation->determineDependingAreaOfInterest(&sizeInput, readOperation, output)) { + return true; + } + } + return false; } void BokehBlurOperation::executeOpenCL(OpenCLDevice *device, - MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, - MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, + MemoryBuffer *outputMemoryBuffer, + cl_mem clOutputBuffer, + MemoryBuffer **inputMemoryBuffers, + list<cl_mem> *clMemToCleanUp, list<cl_kernel> * /*clKernelsToCleanUp*/) { - cl_kernel kernel = device->COM_clCreateKernel("bokehBlurKernel", NULL); - if (!this->m_sizeavailable) { - updateSize(); - } - const float max_dim = max(this->getWidth(), this->getHeight()); - cl_int radius = this->m_size * max_dim / 100.0f; - cl_int step = this->getStep(); - - device->COM_clAttachMemoryBufferToKernelParameter(kernel, 0, -1, clMemToCleanUp, inputMemoryBuffers, this->m_inputBoundingBoxReader); - device->COM_clAttachMemoryBufferToKernelParameter(kernel, 1, 4, clMemToCleanUp, inputMemoryBuffers, this->m_inputProgram); - device->COM_clAttachMemoryBufferToKernelParameter(kernel, 2, -1, clMemToCleanUp, inputMemoryBuffers, this->m_inputBokehProgram); - device->COM_clAttachOutputMemoryBufferToKernelParameter(kernel, 3, clOutputBuffer); - device->COM_clAttachMemoryBufferOffsetToKernelParameter(kernel, 5, outputMemoryBuffer); - clSetKernelArg(kernel, 6, sizeof(cl_int), &radius); - clSetKernelArg(kernel, 7, sizeof(cl_int), &step); - device->COM_clAttachSizeToKernelParameter(kernel, 8, this); - - device->COM_clEnqueueRange(kernel, outputMemoryBuffer, 9, this); + cl_kernel kernel = device->COM_clCreateKernel("bokehBlurKernel", NULL); + if (!this->m_sizeavailable) { + updateSize(); + } + const float max_dim = max(this->getWidth(), this->getHeight()); + cl_int radius = this->m_size * max_dim / 100.0f; + cl_int step = this->getStep(); + + device->COM_clAttachMemoryBufferToKernelParameter( + kernel, 0, -1, clMemToCleanUp, inputMemoryBuffers, this->m_inputBoundingBoxReader); + device->COM_clAttachMemoryBufferToKernelParameter( + kernel, 1, 4, clMemToCleanUp, inputMemoryBuffers, this->m_inputProgram); + device->COM_clAttachMemoryBufferToKernelParameter( + kernel, 2, -1, clMemToCleanUp, inputMemoryBuffers, this->m_inputBokehProgram); + device->COM_clAttachOutputMemoryBufferToKernelParameter(kernel, 3, clOutputBuffer); + device->COM_clAttachMemoryBufferOffsetToKernelParameter(kernel, 5, outputMemoryBuffer); + clSetKernelArg(kernel, 6, sizeof(cl_int), &radius); + clSetKernelArg(kernel, 7, sizeof(cl_int), &step); + device->COM_clAttachSizeToKernelParameter(kernel, 8, this); + + device->COM_clEnqueueRange(kernel, outputMemoryBuffer, 9, this); } void BokehBlurOperation::updateSize() { - if (!this->m_sizeavailable) { - float result[4]; - this->getInputSocketReader(3)->readSampled(result, 0, 0, COM_PS_NEAREST); - this->m_size = result[0]; - CLAMP(this->m_size, 0.0f, 10.0f); - this->m_sizeavailable = true; - } + if (!this->m_sizeavailable) { + float result[4]; + this->getInputSocketReader(3)->readSampled(result, 0, 0, COM_PS_NEAREST); + this->m_size = result[0]; + CLAMP(this->m_size, 0.0f, 10.0f); + this->m_sizeavailable = true; + } } void BokehBlurOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) { - NodeOperation::determineResolution(resolution, - preferredResolution); - if (this->m_extend_bounds) { - const float max_dim = max(resolution[0], resolution[1]); - resolution[0] += 2 * this->m_size * max_dim / 100.0f; - resolution[1] += 2 * this->m_size * max_dim / 100.0f; - } + NodeOperation::determineResolution(resolution, preferredResolution); + if (this->m_extend_bounds) { + const float max_dim = max(resolution[0], resolution[1]); + resolution[0] += 2 * this->m_size * max_dim / 100.0f; + resolution[1] += 2 * this->m_size * max_dim / 100.0f; + } } diff --git a/source/blender/compositor/operations/COM_BokehBlurOperation.h b/source/blender/compositor/operations/COM_BokehBlurOperation.h index ec46adee637..4f594f16cb4 100644 --- a/source/blender/compositor/operations/COM_BokehBlurOperation.h +++ b/source/blender/compositor/operations/COM_BokehBlurOperation.h @@ -23,48 +23,59 @@ #include "COM_QualityStepHelper.h" class BokehBlurOperation : public NodeOperation, public QualityStepHelper { -private: - SocketReader *m_inputProgram; - SocketReader *m_inputBokehProgram; - SocketReader *m_inputBoundingBoxReader; - void updateSize(); - float m_size; - bool m_sizeavailable; - float m_bokehMidX; - float m_bokehMidY; - float m_bokehDimension; - bool m_extend_bounds; -public: - BokehBlurOperation(); + private: + SocketReader *m_inputProgram; + SocketReader *m_inputBokehProgram; + SocketReader *m_inputBoundingBoxReader; + void updateSize(); + float m_size; + bool m_sizeavailable; + float m_bokehMidX; + float m_bokehMidY; + float m_bokehDimension; + bool m_extend_bounds; - void *initializeTileData(rcti *rect); - /** - * the inner loop of this program - */ - void executePixel(float output[4], int x, int y, void *data); + public: + BokehBlurOperation(); - /** - * Initialize the execution - */ - void initExecution(); + void *initializeTileData(rcti *rect); + /** + * the inner loop of this program + */ + void executePixel(float output[4], int x, int y, void *data); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Initialize the execution + */ + void initExecution(); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + /** + * Deinitialize the execution + */ + void deinitExecution(); - void setSize(float size) { this->m_size = size; this->m_sizeavailable = true; } + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); - void executeOpenCL(OpenCLDevice *device, - MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, - MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, - list<cl_kernel> *clKernelsToCleanUp); + void setSize(float size) + { + this->m_size = size; + this->m_sizeavailable = true; + } - void setExtendBounds(bool extend_bounds) { this->m_extend_bounds = extend_bounds; } + void executeOpenCL(OpenCLDevice *device, + MemoryBuffer *outputMemoryBuffer, + cl_mem clOutputBuffer, + MemoryBuffer **inputMemoryBuffers, + list<cl_mem> *clMemToCleanUp, + list<cl_kernel> *clKernelsToCleanUp); - void determineResolution(unsigned int resolution[2], - unsigned int preferredResolution[2]); + void setExtendBounds(bool extend_bounds) + { + this->m_extend_bounds = extend_bounds; + } + + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); }; #endif diff --git a/source/blender/compositor/operations/COM_BokehImageOperation.cpp b/source/blender/compositor/operations/COM_BokehImageOperation.cpp index 6d02f5eb64e..3fd9a77d879 100644 --- a/source/blender/compositor/operations/COM_BokehImageOperation.cpp +++ b/source/blender/compositor/operations/COM_BokehImageOperation.cpp @@ -21,99 +21,106 @@ BokehImageOperation::BokehImageOperation() : NodeOperation() { - this->addOutputSocket(COM_DT_COLOR); - this->m_deleteData = false; + this->addOutputSocket(COM_DT_COLOR); + this->m_deleteData = false; } void BokehImageOperation::initExecution() { - this->m_center[0] = getWidth() / 2; - this->m_center[1] = getHeight() / 2; - this->m_inverseRounding = 1.0f - this->m_data->rounding; - this->m_circularDistance = getWidth() / 2; - this->m_flapRad = (float)(M_PI * 2) / this->m_data->flaps; - this->m_flapRadAdd = this->m_data->angle; - while (this->m_flapRadAdd < 0.0f) { - this->m_flapRadAdd += (float)(M_PI * 2.0); - } - while (this->m_flapRadAdd > (float)M_PI) { - this->m_flapRadAdd -= (float)(M_PI * 2.0); - } + this->m_center[0] = getWidth() / 2; + this->m_center[1] = getHeight() / 2; + this->m_inverseRounding = 1.0f - this->m_data->rounding; + this->m_circularDistance = getWidth() / 2; + this->m_flapRad = (float)(M_PI * 2) / this->m_data->flaps; + this->m_flapRadAdd = this->m_data->angle; + while (this->m_flapRadAdd < 0.0f) { + this->m_flapRadAdd += (float)(M_PI * 2.0); + } + while (this->m_flapRadAdd > (float)M_PI) { + this->m_flapRadAdd -= (float)(M_PI * 2.0); + } } void BokehImageOperation::detemineStartPointOfFlap(float r[2], int flapNumber, float distance) { - r[0] = sinf(this->m_flapRad * flapNumber + this->m_flapRadAdd) * distance + this->m_center[0]; - r[1] = cosf(this->m_flapRad * flapNumber + this->m_flapRadAdd) * distance + this->m_center[1]; + r[0] = sinf(this->m_flapRad * flapNumber + this->m_flapRadAdd) * distance + this->m_center[0]; + r[1] = cosf(this->m_flapRad * flapNumber + this->m_flapRadAdd) * distance + this->m_center[1]; } float BokehImageOperation::isInsideBokeh(float distance, float x, float y) { - float insideBokeh = 0.0f; - const float deltaX = x - this->m_center[0]; - const float deltaY = y - this->m_center[1]; - float closestPoint[2]; - float lineP1[2]; - float lineP2[2]; - float point[2]; - point[0] = x; - point[1] = y; + float insideBokeh = 0.0f; + const float deltaX = x - this->m_center[0]; + const float deltaY = y - this->m_center[1]; + float closestPoint[2]; + float lineP1[2]; + float lineP2[2]; + float point[2]; + point[0] = x; + point[1] = y; - const float distanceToCenter = len_v2v2(point, this->m_center); - const float bearing = (atan2f(deltaX, deltaY) + (float)(M_PI * 2.0)); - int flapNumber = (int)((bearing - this->m_flapRadAdd) / this->m_flapRad); + const float distanceToCenter = len_v2v2(point, this->m_center); + const float bearing = (atan2f(deltaX, deltaY) + (float)(M_PI * 2.0)); + int flapNumber = (int)((bearing - this->m_flapRadAdd) / this->m_flapRad); - detemineStartPointOfFlap(lineP1, flapNumber, distance); - detemineStartPointOfFlap(lineP2, flapNumber + 1, distance); - closest_to_line_v2(closestPoint, point, lineP1, lineP2); + detemineStartPointOfFlap(lineP1, flapNumber, distance); + detemineStartPointOfFlap(lineP2, flapNumber + 1, distance); + closest_to_line_v2(closestPoint, point, lineP1, lineP2); - const float distanceLineToCenter = len_v2v2(this->m_center, closestPoint); - const float distanceRoundingToCenter = this->m_inverseRounding * distanceLineToCenter + this->m_data->rounding * distance; + const float distanceLineToCenter = len_v2v2(this->m_center, closestPoint); + const float distanceRoundingToCenter = this->m_inverseRounding * distanceLineToCenter + + this->m_data->rounding * distance; - const float catadioptricDistanceToCenter = distanceRoundingToCenter * this->m_data->catadioptric; - if (distanceRoundingToCenter >= distanceToCenter && catadioptricDistanceToCenter <= distanceToCenter) { - if (distanceRoundingToCenter - distanceToCenter < 1.0f) { - insideBokeh = (distanceRoundingToCenter - distanceToCenter); - } - else if (this->m_data->catadioptric != 0.0f && distanceToCenter - catadioptricDistanceToCenter < 1.0f) { - insideBokeh = (distanceToCenter - catadioptricDistanceToCenter); - } - else { - insideBokeh = 1.0f; - } - } - return insideBokeh; + const float catadioptricDistanceToCenter = distanceRoundingToCenter * this->m_data->catadioptric; + if (distanceRoundingToCenter >= distanceToCenter && + catadioptricDistanceToCenter <= distanceToCenter) { + if (distanceRoundingToCenter - distanceToCenter < 1.0f) { + insideBokeh = (distanceRoundingToCenter - distanceToCenter); + } + else if (this->m_data->catadioptric != 0.0f && + distanceToCenter - catadioptricDistanceToCenter < 1.0f) { + insideBokeh = (distanceToCenter - catadioptricDistanceToCenter); + } + else { + insideBokeh = 1.0f; + } + } + return insideBokeh; } -void BokehImageOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) +void BokehImageOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler /*sampler*/) { - float shift = this->m_data->lensshift; - float shift2 = shift / 2.0f; - float distance = this->m_circularDistance; - float insideBokehMax = isInsideBokeh(distance, x, y); - float insideBokehMed = isInsideBokeh(distance - fabsf(shift2 * distance), x, y); - float insideBokehMin = isInsideBokeh(distance - fabsf(shift * distance), x, y); - if (shift < 0) { - output[0] = insideBokehMax; - output[1] = insideBokehMed; - output[2] = insideBokehMin; - } - else { - output[0] = insideBokehMin; - output[1] = insideBokehMed; - output[2] = insideBokehMax; - } - output[3] = (insideBokehMax + insideBokehMed + insideBokehMin) / 3.0f; + float shift = this->m_data->lensshift; + float shift2 = shift / 2.0f; + float distance = this->m_circularDistance; + float insideBokehMax = isInsideBokeh(distance, x, y); + float insideBokehMed = isInsideBokeh(distance - fabsf(shift2 * distance), x, y); + float insideBokehMin = isInsideBokeh(distance - fabsf(shift * distance), x, y); + if (shift < 0) { + output[0] = insideBokehMax; + output[1] = insideBokehMed; + output[2] = insideBokehMin; + } + else { + output[0] = insideBokehMin; + output[1] = insideBokehMed; + output[2] = insideBokehMax; + } + output[3] = (insideBokehMax + insideBokehMed + insideBokehMin) / 3.0f; } void BokehImageOperation::deinitExecution() { - if (this->m_deleteData) { - if (this->m_data) { - delete this->m_data; - this->m_data = NULL; - } - } + if (this->m_deleteData) { + if (this->m_data) { + delete this->m_data; + this->m_data = NULL; + } + } } -void BokehImageOperation::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2]) +void BokehImageOperation::determineResolution(unsigned int resolution[2], + unsigned int /*preferredResolution*/[2]) { - resolution[0] = COM_BLUR_BOKEH_PIXELS; - resolution[1] = COM_BLUR_BOKEH_PIXELS; + resolution[0] = COM_BLUR_BOKEH_PIXELS; + resolution[1] = COM_BLUR_BOKEH_PIXELS; } diff --git a/source/blender/compositor/operations/COM_BokehImageOperation.h b/source/blender/compositor/operations/COM_BokehImageOperation.h index 445dea88cb7..58a1e2f85d8 100644 --- a/source/blender/compositor/operations/COM_BokehImageOperation.h +++ b/source/blender/compositor/operations/COM_BokehImageOperation.h @@ -47,98 +47,105 @@ * With a simple compare it can be detected if the evaluated pixel is between the outer and inner edge. */ class BokehImageOperation : public NodeOperation { -private: - /** - * \brief Settings of the bokeh image - */ - NodeBokehImage *m_data; - - /** - * \brief precalced center of the image - */ - float m_center[2]; - - /** - * \brief 1.0-rounding - */ - float m_inverseRounding; - - /** - * \brief distance of a full circle lens - */ - float m_circularDistance; - - /** - * \brief radius when the first flap starts - */ - float m_flapRad; - - /** - * \brief radians of a single flap - */ - float m_flapRadAdd; - - /** - * \brief should the m_data field by deleted when this operation is finished - */ - bool m_deleteData; - - /** - * \brief determine the coordinate of a flap cornder - * - * \param r: result in bokehimage space are stored [x,y] - * \param flapNumber: the flap number to calculate - * \param distance: the lens distance is used to simulate lens shifts - */ - void detemineStartPointOfFlap(float r[2], int flapNumber, float distance); - - /** - * \brief Determine if a coordinate is inside the bokeh image - * - * \param distance: the distance that will be used. This parameter is modified a bit to mimic lens shifts - * \param x: the x coordinate of the pixel to evaluate - * \param y: the y coordinate of the pixel to evaluate - * \return float range 0..1 0 is completely outside - */ - float isInsideBokeh(float distance, float x, float y); -public: - BokehImageOperation(); - - /** - * \brief the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - - /** - * \brief Initialize the execution - */ - void initExecution(); - - /** - * \brief Deinitialize the execution - */ - void deinitExecution(); - - /** - * \brief determine the resolution of this operation. currently fixed at [COM_BLUR_BOKEH_PIXELS, COM_BLUR_BOKEH_PIXELS] - * \param resolution: - * \param preferredResolution: - */ - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); - - /** - * \brief set the node data - * \param data: - */ - void setData(NodeBokehImage *data) { this->m_data = data; } - - /** - * \brief deleteDataOnFinish - * - * There are cases that the compositor uses this operation on its own (see defocus node) - * the deleteDataOnFinish must only be called when the data has been created by the compositor. - *It should not be called when the data has been created by the node-editor/user. - */ - void deleteDataOnFinish() { this->m_deleteData = true; } + private: + /** + * \brief Settings of the bokeh image + */ + NodeBokehImage *m_data; + + /** + * \brief precalced center of the image + */ + float m_center[2]; + + /** + * \brief 1.0-rounding + */ + float m_inverseRounding; + + /** + * \brief distance of a full circle lens + */ + float m_circularDistance; + + /** + * \brief radius when the first flap starts + */ + float m_flapRad; + + /** + * \brief radians of a single flap + */ + float m_flapRadAdd; + + /** + * \brief should the m_data field by deleted when this operation is finished + */ + bool m_deleteData; + + /** + * \brief determine the coordinate of a flap cornder + * + * \param r: result in bokehimage space are stored [x,y] + * \param flapNumber: the flap number to calculate + * \param distance: the lens distance is used to simulate lens shifts + */ + void detemineStartPointOfFlap(float r[2], int flapNumber, float distance); + + /** + * \brief Determine if a coordinate is inside the bokeh image + * + * \param distance: the distance that will be used. This parameter is modified a bit to mimic lens shifts + * \param x: the x coordinate of the pixel to evaluate + * \param y: the y coordinate of the pixel to evaluate + * \return float range 0..1 0 is completely outside + */ + float isInsideBokeh(float distance, float x, float y); + + public: + BokehImageOperation(); + + /** + * \brief the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + + /** + * \brief Initialize the execution + */ + void initExecution(); + + /** + * \brief Deinitialize the execution + */ + void deinitExecution(); + + /** + * \brief determine the resolution of this operation. currently fixed at [COM_BLUR_BOKEH_PIXELS, COM_BLUR_BOKEH_PIXELS] + * \param resolution: + * \param preferredResolution: + */ + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); + + /** + * \brief set the node data + * \param data: + */ + void setData(NodeBokehImage *data) + { + this->m_data = data; + } + + /** + * \brief deleteDataOnFinish + * + * There are cases that the compositor uses this operation on its own (see defocus node) + * the deleteDataOnFinish must only be called when the data has been created by the compositor. + *It should not be called when the data has been created by the node-editor/user. + */ + void deleteDataOnFinish() + { + this->m_deleteData = true; + } }; #endif diff --git a/source/blender/compositor/operations/COM_BoxMaskOperation.cpp b/source/blender/compositor/operations/COM_BoxMaskOperation.cpp index 6328b983489..c5f0108bf5a 100644 --- a/source/blender/compositor/operations/COM_BoxMaskOperation.cpp +++ b/source/blender/compositor/operations/COM_BoxMaskOperation.cpp @@ -22,91 +22,89 @@ BoxMaskOperation::BoxMaskOperation() : NodeOperation() { - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_VALUE); - this->m_inputMask = NULL; - this->m_inputValue = NULL; - this->m_cosine = 0.0f; - this->m_sine = 0.0f; + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_VALUE); + this->m_inputMask = NULL; + this->m_inputValue = NULL; + this->m_cosine = 0.0f; + this->m_sine = 0.0f; } void BoxMaskOperation::initExecution() { - this->m_inputMask = this->getInputSocketReader(0); - this->m_inputValue = this->getInputSocketReader(1); - const double rad = (double)this->m_data->rotation; - this->m_cosine = cos(rad); - this->m_sine = sin(rad); - this->m_aspectRatio = ((float)this->getWidth()) / this->getHeight(); + this->m_inputMask = this->getInputSocketReader(0); + this->m_inputValue = this->getInputSocketReader(1); + const double rad = (double)this->m_data->rotation; + this->m_cosine = cos(rad); + this->m_sine = sin(rad); + this->m_aspectRatio = ((float)this->getWidth()) / this->getHeight(); } void BoxMaskOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { - float inputMask[4]; - float inputValue[4]; + float inputMask[4]; + float inputValue[4]; - float rx = x / this->getWidth(); - float ry = y / this->getHeight(); + float rx = x / this->getWidth(); + float ry = y / this->getHeight(); - const float dy = (ry - this->m_data->y) / this->m_aspectRatio; - const float dx = rx - this->m_data->x; - rx = this->m_data->x + (this->m_cosine * dx + this->m_sine * dy); - ry = this->m_data->y + (-this->m_sine * dx + this->m_cosine * dy); + const float dy = (ry - this->m_data->y) / this->m_aspectRatio; + const float dx = rx - this->m_data->x; + rx = this->m_data->x + (this->m_cosine * dx + this->m_sine * dy); + ry = this->m_data->y + (-this->m_sine * dx + this->m_cosine * dy); - this->m_inputMask->readSampled(inputMask, x, y, sampler); - this->m_inputValue->readSampled(inputValue, x, y, sampler); + this->m_inputMask->readSampled(inputMask, x, y, sampler); + this->m_inputValue->readSampled(inputValue, x, y, sampler); - float halfHeight = this->m_data->height / 2.0f; - float halfWidth = this->m_data->width / 2.0f; - bool inside = (rx > this->m_data->x - halfWidth && - rx < this->m_data->x + halfWidth && - ry > this->m_data->y - halfHeight && - ry < this->m_data->y + halfHeight); + float halfHeight = this->m_data->height / 2.0f; + float halfWidth = this->m_data->width / 2.0f; + bool inside = (rx > this->m_data->x - halfWidth && rx < this->m_data->x + halfWidth && + ry > this->m_data->y - halfHeight && ry < this->m_data->y + halfHeight); - switch (this->m_maskType) { - case CMP_NODE_MASKTYPE_ADD: - if (inside) { - output[0] = max(inputMask[0], inputValue[0]); - } - else { - output[0] = inputMask[0]; - } - break; - case CMP_NODE_MASKTYPE_SUBTRACT: - if (inside) { - output[0] = inputMask[0] - inputValue[0]; - CLAMP(output[0], 0, 1); - } - else { - output[0] = inputMask[0]; - } - break; - case CMP_NODE_MASKTYPE_MULTIPLY: - if (inside) { - output[0] = inputMask[0] * inputValue[0]; - } - else { - output[0] = 0; - } - break; - case CMP_NODE_MASKTYPE_NOT: - if (inside) { - if (inputMask[0] > 0.0f) { - output[0] = 0; - } - else { - output[0] = inputValue[0]; - } - } - else { - output[0] = inputMask[0]; - } - break; - } + switch (this->m_maskType) { + case CMP_NODE_MASKTYPE_ADD: + if (inside) { + output[0] = max(inputMask[0], inputValue[0]); + } + else { + output[0] = inputMask[0]; + } + break; + case CMP_NODE_MASKTYPE_SUBTRACT: + if (inside) { + output[0] = inputMask[0] - inputValue[0]; + CLAMP(output[0], 0, 1); + } + else { + output[0] = inputMask[0]; + } + break; + case CMP_NODE_MASKTYPE_MULTIPLY: + if (inside) { + output[0] = inputMask[0] * inputValue[0]; + } + else { + output[0] = 0; + } + break; + case CMP_NODE_MASKTYPE_NOT: + if (inside) { + if (inputMask[0] > 0.0f) { + output[0] = 0; + } + else { + output[0] = inputValue[0]; + } + } + else { + output[0] = inputMask[0]; + } + break; + } } void BoxMaskOperation::deinitExecution() { - this->m_inputMask = NULL; - this->m_inputValue = NULL; + this->m_inputMask = NULL; + this->m_inputValue = NULL; } diff --git a/source/blender/compositor/operations/COM_BoxMaskOperation.h b/source/blender/compositor/operations/COM_BoxMaskOperation.h index f5134de7211..f770922ee7c 100644 --- a/source/blender/compositor/operations/COM_BoxMaskOperation.h +++ b/source/blender/compositor/operations/COM_BoxMaskOperation.h @@ -20,42 +20,47 @@ #define __COM_BOXMASKOPERATION_H__ #include "COM_NodeOperation.h" - class BoxMaskOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputMask; - SocketReader *m_inputValue; + private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputMask; + SocketReader *m_inputValue; - float m_sine; - float m_cosine; - float m_aspectRatio; - int m_maskType; + float m_sine; + float m_cosine; + float m_aspectRatio; + int m_maskType; - NodeBoxMask *m_data; -public: - BoxMaskOperation(); + NodeBoxMask *m_data; - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + BoxMaskOperation(); - /** - * Initialize the execution - */ - void initExecution(); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Initialize the execution + */ + void initExecution(); - void setData(NodeBoxMask *data) { this->m_data = data; } + /** + * Deinitialize the execution + */ + void deinitExecution(); - void setMaskType(int maskType) { this->m_maskType = maskType; } + void setData(NodeBoxMask *data) + { + this->m_data = data; + } + void setMaskType(int maskType) + { + this->m_maskType = maskType; + } }; #endif diff --git a/source/blender/compositor/operations/COM_BrightnessOperation.cpp b/source/blender/compositor/operations/COM_BrightnessOperation.cpp index dedea363163..81df85daf28 100644 --- a/source/blender/compositor/operations/COM_BrightnessOperation.cpp +++ b/source/blender/compositor/operations/COM_BrightnessOperation.cpp @@ -20,68 +20,71 @@ BrightnessOperation::BrightnessOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_COLOR); - this->m_inputProgram = NULL; - this->m_use_premultiply = false; + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_COLOR); + this->m_inputProgram = NULL; + this->m_use_premultiply = false; } void BrightnessOperation::setUsePremultiply(bool use_premultiply) { - this->m_use_premultiply = use_premultiply; + this->m_use_premultiply = use_premultiply; } void BrightnessOperation::initExecution() { - this->m_inputProgram = this->getInputSocketReader(0); - this->m_inputBrightnessProgram = this->getInputSocketReader(1); - this->m_inputContrastProgram = this->getInputSocketReader(2); + this->m_inputProgram = this->getInputSocketReader(0); + this->m_inputBrightnessProgram = this->getInputSocketReader(1); + this->m_inputContrastProgram = this->getInputSocketReader(2); } -void BrightnessOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void BrightnessOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue[4]; - float a, b; - float inputBrightness[4]; - float inputContrast[4]; - this->m_inputProgram->readSampled(inputValue, x, y, sampler); - this->m_inputBrightnessProgram->readSampled(inputBrightness, x, y, sampler); - this->m_inputContrastProgram->readSampled(inputContrast, x, y, sampler); - float brightness = inputBrightness[0]; - float contrast = inputContrast[0]; - brightness /= 100.0f; - float delta = contrast / 200.0f; - a = 1.0f - delta * 2.0f; - /* - * The algorithm is by Werner D. Streidt - * (http://visca.com/ffactory/archives/5-99/msg00021.html) - * Extracted of OpenCV demhist.c - */ - if (contrast > 0) { - a = 1.0f / a; - b = a * (brightness - delta); - } - else { - delta *= -1; - b = a * (brightness + delta); - } - if (this->m_use_premultiply) { - premul_to_straight_v4(inputValue); - } - output[0] = a * inputValue[0] + b; - output[1] = a * inputValue[1] + b; - output[2] = a * inputValue[2] + b; - output[3] = inputValue[3]; - if (this->m_use_premultiply) { - straight_to_premul_v4(output); - } + float inputValue[4]; + float a, b; + float inputBrightness[4]; + float inputContrast[4]; + this->m_inputProgram->readSampled(inputValue, x, y, sampler); + this->m_inputBrightnessProgram->readSampled(inputBrightness, x, y, sampler); + this->m_inputContrastProgram->readSampled(inputContrast, x, y, sampler); + float brightness = inputBrightness[0]; + float contrast = inputContrast[0]; + brightness /= 100.0f; + float delta = contrast / 200.0f; + a = 1.0f - delta * 2.0f; + /* + * The algorithm is by Werner D. Streidt + * (http://visca.com/ffactory/archives/5-99/msg00021.html) + * Extracted of OpenCV demhist.c + */ + if (contrast > 0) { + a = 1.0f / a; + b = a * (brightness - delta); + } + else { + delta *= -1; + b = a * (brightness + delta); + } + if (this->m_use_premultiply) { + premul_to_straight_v4(inputValue); + } + output[0] = a * inputValue[0] + b; + output[1] = a * inputValue[1] + b; + output[2] = a * inputValue[2] + b; + output[3] = inputValue[3]; + if (this->m_use_premultiply) { + straight_to_premul_v4(output); + } } void BrightnessOperation::deinitExecution() { - this->m_inputProgram = NULL; - this->m_inputBrightnessProgram = NULL; - this->m_inputContrastProgram = NULL; + this->m_inputProgram = NULL; + this->m_inputBrightnessProgram = NULL; + this->m_inputContrastProgram = NULL; } diff --git a/source/blender/compositor/operations/COM_BrightnessOperation.h b/source/blender/compositor/operations/COM_BrightnessOperation.h index 45aa7be48f3..df6b3ef7b6e 100644 --- a/source/blender/compositor/operations/COM_BrightnessOperation.h +++ b/source/blender/compositor/operations/COM_BrightnessOperation.h @@ -20,36 +20,35 @@ #define __COM_BRIGHTNESSOPERATION_H__ #include "COM_NodeOperation.h" - class BrightnessOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputProgram; - SocketReader *m_inputBrightnessProgram; - SocketReader *m_inputContrastProgram; - - bool m_use_premultiply; - -public: - BrightnessOperation(); - - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - - /** - * Initialize the execution - */ - void initExecution(); - - /** - * Deinitialize the execution - */ - void deinitExecution(); - - void setUsePremultiply(bool use_premultiply); + private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputProgram; + SocketReader *m_inputBrightnessProgram; + SocketReader *m_inputContrastProgram; + + bool m_use_premultiply; + + public: + BrightnessOperation(); + + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + + /** + * Initialize the execution + */ + void initExecution(); + + /** + * Deinitialize the execution + */ + void deinitExecution(); + + void setUsePremultiply(bool use_premultiply); }; #endif diff --git a/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp b/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp index 2bc3efc60e4..5d01154bbda 100644 --- a/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp +++ b/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp @@ -26,103 +26,104 @@ extern "C" { CalculateMeanOperation::CalculateMeanOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); - this->addOutputSocket(COM_DT_VALUE); - this->m_imageReader = NULL; - this->m_iscalculated = false; - this->m_setting = 1; - this->setComplex(true); + this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); + this->addOutputSocket(COM_DT_VALUE); + this->m_imageReader = NULL; + this->m_iscalculated = false; + this->m_setting = 1; + this->setComplex(true); } void CalculateMeanOperation::initExecution() { - this->m_imageReader = this->getInputSocketReader(0); - this->m_iscalculated = false; - NodeOperation::initMutex(); + this->m_imageReader = this->getInputSocketReader(0); + this->m_iscalculated = false; + NodeOperation::initMutex(); } -void CalculateMeanOperation::executePixel(float output[4], - int /*x*/, int /*y*/, - void * /*data*/) +void CalculateMeanOperation::executePixel(float output[4], int /*x*/, int /*y*/, void * /*data*/) { - output[0] = this->m_result; + output[0] = this->m_result; } void CalculateMeanOperation::deinitExecution() { - this->m_imageReader = NULL; - NodeOperation::deinitMutex(); + this->m_imageReader = NULL; + NodeOperation::deinitMutex(); } -bool CalculateMeanOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output) +bool CalculateMeanOperation::determineDependingAreaOfInterest(rcti * /*input*/, + ReadBufferOperation *readOperation, + rcti *output) { - rcti imageInput; - if (this->m_iscalculated) { - return false; - } - NodeOperation *operation = getInputOperation(0); - imageInput.xmax = operation->getWidth(); - imageInput.xmin = 0; - imageInput.ymax = operation->getHeight(); - imageInput.ymin = 0; - if (operation->determineDependingAreaOfInterest(&imageInput, readOperation, output) ) { - return true; - } - return false; + rcti imageInput; + if (this->m_iscalculated) { + return false; + } + NodeOperation *operation = getInputOperation(0); + imageInput.xmax = operation->getWidth(); + imageInput.xmin = 0; + imageInput.ymax = operation->getHeight(); + imageInput.ymin = 0; + if (operation->determineDependingAreaOfInterest(&imageInput, readOperation, output)) { + return true; + } + return false; } void *CalculateMeanOperation::initializeTileData(rcti *rect) { - lockMutex(); - if (!this->m_iscalculated) { - MemoryBuffer *tile = (MemoryBuffer *)this->m_imageReader->initializeTileData(rect); - calculateMean(tile); - this->m_iscalculated = true; - } - unlockMutex(); - return NULL; + lockMutex(); + if (!this->m_iscalculated) { + MemoryBuffer *tile = (MemoryBuffer *)this->m_imageReader->initializeTileData(rect); + calculateMean(tile); + this->m_iscalculated = true; + } + unlockMutex(); + return NULL; } void CalculateMeanOperation::calculateMean(MemoryBuffer *tile) { - this->m_result = 0.0f; - float *buffer = tile->getBuffer(); - int size = tile->getWidth() * tile->getHeight(); - int pixels = 0; - float sum = 0.0f; - for (int i = 0, offset = 0; i < size; i++, offset += 4) { - if (buffer[offset + 3] > 0) { - pixels++; + this->m_result = 0.0f; + float *buffer = tile->getBuffer(); + int size = tile->getWidth() * tile->getHeight(); + int pixels = 0; + float sum = 0.0f; + for (int i = 0, offset = 0; i < size; i++, offset += 4) { + if (buffer[offset + 3] > 0) { + pixels++; - switch (this->m_setting) { - case 1: - { - sum += IMB_colormanagement_get_luminance(&buffer[offset]); - break; - } - case 2: - { - sum += buffer[offset]; - break; - } - case 3: - { - sum += buffer[offset + 1]; - break; - } - case 4: - { - sum += buffer[offset + 2]; - break; - } - case 5: - { - float yuv[3]; - rgb_to_yuv(buffer[offset], buffer[offset + 1], buffer[offset + 2], &yuv[0], &yuv[1], &yuv[2], BLI_YUV_ITU_BT709); - sum += yuv[0]; - break; - } - } - } - } - this->m_result = sum / pixels; + switch (this->m_setting) { + case 1: { + sum += IMB_colormanagement_get_luminance(&buffer[offset]); + break; + } + case 2: { + sum += buffer[offset]; + break; + } + case 3: { + sum += buffer[offset + 1]; + break; + } + case 4: { + sum += buffer[offset + 2]; + break; + } + case 5: { + float yuv[3]; + rgb_to_yuv(buffer[offset], + buffer[offset + 1], + buffer[offset + 2], + &yuv[0], + &yuv[1], + &yuv[2], + BLI_YUV_ITU_BT709); + sum += yuv[0]; + break; + } + } + } + } + this->m_result = sum / pixels; } diff --git a/source/blender/compositor/operations/COM_CalculateMeanOperation.h b/source/blender/compositor/operations/COM_CalculateMeanOperation.h index 54c09007dc6..38d68b2a6fd 100644 --- a/source/blender/compositor/operations/COM_CalculateMeanOperation.h +++ b/source/blender/compositor/operations/COM_CalculateMeanOperation.h @@ -26,40 +26,45 @@ * \ingroup operation */ class CalculateMeanOperation : public NodeOperation { -protected: - /** - * \brief Cached reference to the reader - */ - SocketReader *m_imageReader; + protected: + /** + * \brief Cached reference to the reader + */ + SocketReader *m_imageReader; - bool m_iscalculated; - float m_result; - int m_setting; + bool m_iscalculated; + float m_result; + int m_setting; -public: - CalculateMeanOperation(); + public: + CalculateMeanOperation(); - /** - * the inner loop of this program - */ - void executePixel(float output[4], int x, int y, void *data); + /** + * the inner loop of this program + */ + void executePixel(float output[4], int x, int y, void *data); - /** - * Initialize the execution - */ - void initExecution(); + /** + * Initialize the execution + */ + void initExecution(); - void *initializeTileData(rcti *rect); + void *initializeTileData(rcti *rect); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Deinitialize the execution + */ + void deinitExecution(); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - void setSetting(int setting) { this->m_setting = setting; } + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + void setSetting(int setting) + { + this->m_setting = setting; + } -protected: - void calculateMean(MemoryBuffer *tile); + protected: + void calculateMean(MemoryBuffer *tile); }; #endif diff --git a/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp b/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp index 7fa1929889c..dfe1a936c9c 100644 --- a/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp +++ b/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp @@ -24,75 +24,83 @@ extern "C" { #include "IMB_colormanagement.h" } -CalculateStandardDeviationOperation::CalculateStandardDeviationOperation() : CalculateMeanOperation() +CalculateStandardDeviationOperation::CalculateStandardDeviationOperation() + : CalculateMeanOperation() { - /* pass */ + /* pass */ } void CalculateStandardDeviationOperation::executePixel(float output[4], - int /*x*/, int /*y*/, + int /*x*/, + int /*y*/, void * /*data*/) { - output[0] = this->m_standardDeviation; + output[0] = this->m_standardDeviation; } void *CalculateStandardDeviationOperation::initializeTileData(rcti *rect) { - lockMutex(); - if (!this->m_iscalculated) { - MemoryBuffer *tile = (MemoryBuffer *)this->m_imageReader->initializeTileData(rect); - CalculateMeanOperation::calculateMean(tile); - this->m_standardDeviation = 0.0f; - float *buffer = tile->getBuffer(); - int size = tile->getWidth() * tile->getHeight(); - int pixels = 0; - float sum = 0.0f; - float mean = this->m_result; - for (int i = 0, offset = 0; i < size; i++, offset += 4) { - if (buffer[offset + 3] > 0) { - pixels++; + lockMutex(); + if (!this->m_iscalculated) { + MemoryBuffer *tile = (MemoryBuffer *)this->m_imageReader->initializeTileData(rect); + CalculateMeanOperation::calculateMean(tile); + this->m_standardDeviation = 0.0f; + float *buffer = tile->getBuffer(); + int size = tile->getWidth() * tile->getHeight(); + int pixels = 0; + float sum = 0.0f; + float mean = this->m_result; + for (int i = 0, offset = 0; i < size; i++, offset += 4) { + if (buffer[offset + 3] > 0) { + pixels++; - switch (this->m_setting) { - case 1: /* rgb combined */ - { - float value = IMB_colormanagement_get_luminance(&buffer[offset]); - sum += (value - mean) * (value - mean); - break; - } - case 2: /* red */ - { - float value = buffer[offset]; - sum += value; - sum += (value - mean) * (value - mean); - break; - } - case 3: /* green */ - { - float value = buffer[offset + 1]; - sum += value; - sum += (value - mean) * (value - mean); - break; - } - case 4: /* blue */ - { - float value = buffer[offset + 2]; - sum += value; - sum += (value - mean) * (value - mean); - break; - } - case 5: /* luminance */ - { - float yuv[3]; - rgb_to_yuv(buffer[offset], buffer[offset + 1], buffer[offset + 2], &yuv[0], &yuv[1], &yuv[2], BLI_YUV_ITU_BT709); - sum += (yuv[0] - mean) * (yuv[0] - mean); - break; - } - } - } - } - this->m_standardDeviation = sqrt(sum / (float)(pixels - 1)); - this->m_iscalculated = true; - } - unlockMutex(); - return NULL; + switch (this->m_setting) { + case 1: /* rgb combined */ + { + float value = IMB_colormanagement_get_luminance(&buffer[offset]); + sum += (value - mean) * (value - mean); + break; + } + case 2: /* red */ + { + float value = buffer[offset]; + sum += value; + sum += (value - mean) * (value - mean); + break; + } + case 3: /* green */ + { + float value = buffer[offset + 1]; + sum += value; + sum += (value - mean) * (value - mean); + break; + } + case 4: /* blue */ + { + float value = buffer[offset + 2]; + sum += value; + sum += (value - mean) * (value - mean); + break; + } + case 5: /* luminance */ + { + float yuv[3]; + rgb_to_yuv(buffer[offset], + buffer[offset + 1], + buffer[offset + 2], + &yuv[0], + &yuv[1], + &yuv[2], + BLI_YUV_ITU_BT709); + sum += (yuv[0] - mean) * (yuv[0] - mean); + break; + } + } + } + } + this->m_standardDeviation = sqrt(sum / (float)(pixels - 1)); + this->m_iscalculated = true; + } + unlockMutex(); + return NULL; } diff --git a/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.h b/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.h index bc0bd669ebc..3f5c0896221 100644 --- a/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.h +++ b/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.h @@ -26,18 +26,17 @@ * \ingroup operation */ class CalculateStandardDeviationOperation : public CalculateMeanOperation { -protected: - float m_standardDeviation; + protected: + float m_standardDeviation; -public: - CalculateStandardDeviationOperation(); + public: + CalculateStandardDeviationOperation(); - /** - * the inner loop of this program - */ - void executePixel(float output[4], int x, int y, void *data); - - void *initializeTileData(rcti *rect); + /** + * the inner loop of this program + */ + void executePixel(float output[4], int x, int y, void *data); + void *initializeTileData(rcti *rect); }; #endif diff --git a/source/blender/compositor/operations/COM_ChangeHSVOperation.cpp b/source/blender/compositor/operations/COM_ChangeHSVOperation.cpp index 7481a3bebb4..a2554cd60de 100644 --- a/source/blender/compositor/operations/COM_ChangeHSVOperation.cpp +++ b/source/blender/compositor/operations/COM_ChangeHSVOperation.cpp @@ -20,44 +20,49 @@ ChangeHSVOperation::ChangeHSVOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_COLOR); - this->m_inputOperation = NULL; + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_COLOR); + this->m_inputOperation = NULL; } void ChangeHSVOperation::initExecution() { - this->m_inputOperation = getInputSocketReader(0); - this->m_hueOperation = getInputSocketReader(1); - this->m_saturationOperation = getInputSocketReader(2); - this->m_valueOperation = getInputSocketReader(3); + this->m_inputOperation = getInputSocketReader(0); + this->m_hueOperation = getInputSocketReader(1); + this->m_saturationOperation = getInputSocketReader(2); + this->m_valueOperation = getInputSocketReader(3); } void ChangeHSVOperation::deinitExecution() { - this->m_inputOperation = NULL; - this->m_hueOperation = NULL; - this->m_saturationOperation = NULL; - this->m_valueOperation = NULL; + this->m_inputOperation = NULL; + this->m_hueOperation = NULL; + this->m_saturationOperation = NULL; + this->m_valueOperation = NULL; } -void ChangeHSVOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ChangeHSVOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor1[4]; - float hue[4], saturation[4], value[4]; + float inputColor1[4]; + float hue[4], saturation[4], value[4]; - this->m_inputOperation->readSampled(inputColor1, x, y, sampler); - this->m_hueOperation->readSampled(hue, x, y, sampler); - this->m_saturationOperation->readSampled(saturation, x, y, sampler); - this->m_valueOperation->readSampled(value, x, y, sampler); + this->m_inputOperation->readSampled(inputColor1, x, y, sampler); + this->m_hueOperation->readSampled(hue, x, y, sampler); + this->m_saturationOperation->readSampled(saturation, x, y, sampler); + this->m_valueOperation->readSampled(value, x, y, sampler); - output[0] = inputColor1[0] + (hue[0] - 0.5f); - if (output[0] > 1.0f) output[0] -= 1.0f; - else if (output[0] < 0.0f) output[0] += 1.0f; - output[1] = inputColor1[1] * saturation[0]; - output[2] = inputColor1[2] * value[0]; - output[3] = inputColor1[3]; + output[0] = inputColor1[0] + (hue[0] - 0.5f); + if (output[0] > 1.0f) + output[0] -= 1.0f; + else if (output[0] < 0.0f) + output[0] += 1.0f; + output[1] = inputColor1[1] * saturation[0]; + output[2] = inputColor1[2] * value[0]; + output[3] = inputColor1[3]; } diff --git a/source/blender/compositor/operations/COM_ChangeHSVOperation.h b/source/blender/compositor/operations/COM_ChangeHSVOperation.h index 80855cb73a9..3898345f922 100644 --- a/source/blender/compositor/operations/COM_ChangeHSVOperation.h +++ b/source/blender/compositor/operations/COM_ChangeHSVOperation.h @@ -20,31 +20,29 @@ #define __COM_CHANGEHSVOPERATION_H__ #include "COM_MixOperation.h" - /** * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ class ChangeHSVOperation : public NodeOperation { -private: - SocketReader *m_inputOperation; - SocketReader *m_hueOperation; - SocketReader *m_saturationOperation; - SocketReader *m_valueOperation; - -public: - /** - * Default constructor - */ - ChangeHSVOperation(); + private: + SocketReader *m_inputOperation; + SocketReader *m_hueOperation; + SocketReader *m_saturationOperation; + SocketReader *m_valueOperation; - void initExecution(); - void deinitExecution(); + public: + /** + * Default constructor + */ + ChangeHSVOperation(); - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void initExecution(); + void deinitExecution(); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; #endif diff --git a/source/blender/compositor/operations/COM_ChannelMatteOperation.cpp b/source/blender/compositor/operations/COM_ChannelMatteOperation.cpp index 1e3808a80cc..cbd46ea71f8 100644 --- a/source/blender/compositor/operations/COM_ChannelMatteOperation.cpp +++ b/source/blender/compositor/operations/COM_ChannelMatteOperation.cpp @@ -21,102 +21,100 @@ ChannelMatteOperation::ChannelMatteOperation() : NodeOperation() { - addInputSocket(COM_DT_COLOR); - addOutputSocket(COM_DT_VALUE); + addInputSocket(COM_DT_COLOR); + addOutputSocket(COM_DT_VALUE); - this->m_inputImageProgram = NULL; + this->m_inputImageProgram = NULL; } void ChannelMatteOperation::initExecution() { - this->m_inputImageProgram = this->getInputSocketReader(0); + this->m_inputImageProgram = this->getInputSocketReader(0); - this->m_limit_range = this->m_limit_max - this->m_limit_min; + this->m_limit_range = this->m_limit_max - this->m_limit_min; - switch (this->m_limit_method) { - /* SINGLE */ - case 0: - { - /* 123 / RGB / HSV / YUV / YCC */ - const int matte_channel = this->m_matte_channel - 1; - const int limit_channel = this->m_limit_channel - 1; - this->m_ids[0] = matte_channel; - this->m_ids[1] = limit_channel; - this->m_ids[2] = limit_channel; - break; - } - /* MAX */ - case 1: - { - switch (this->m_matte_channel) { - case 1: - { - this->m_ids[0] = 0; - this->m_ids[1] = 1; - this->m_ids[2] = 2; - break; - } - case 2: - { - this->m_ids[0] = 1; - this->m_ids[1] = 0; - this->m_ids[2] = 2; - break; - } - case 3: - { - this->m_ids[0] = 2; - this->m_ids[1] = 0; - this->m_ids[2] = 1; - break; - } - default: - break; - } - break; - } - default: - break; - } + switch (this->m_limit_method) { + /* SINGLE */ + case 0: { + /* 123 / RGB / HSV / YUV / YCC */ + const int matte_channel = this->m_matte_channel - 1; + const int limit_channel = this->m_limit_channel - 1; + this->m_ids[0] = matte_channel; + this->m_ids[1] = limit_channel; + this->m_ids[2] = limit_channel; + break; + } + /* MAX */ + case 1: { + switch (this->m_matte_channel) { + case 1: { + this->m_ids[0] = 0; + this->m_ids[1] = 1; + this->m_ids[2] = 2; + break; + } + case 2: { + this->m_ids[0] = 1; + this->m_ids[1] = 0; + this->m_ids[2] = 2; + break; + } + case 3: { + this->m_ids[0] = 2; + this->m_ids[1] = 0; + this->m_ids[2] = 1; + break; + } + default: + break; + } + break; + } + default: + break; + } } void ChannelMatteOperation::deinitExecution() { - this->m_inputImageProgram = NULL; + this->m_inputImageProgram = NULL; } -void ChannelMatteOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ChannelMatteOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inColor[4]; - float alpha; + float inColor[4]; + float alpha; - const float limit_max = this->m_limit_max; - const float limit_min = this->m_limit_min; - const float limit_range = this->m_limit_range; + const float limit_max = this->m_limit_max; + const float limit_min = this->m_limit_min; + const float limit_range = this->m_limit_range; - this->m_inputImageProgram->readSampled(inColor, x, y, sampler); + this->m_inputImageProgram->readSampled(inColor, x, y, sampler); - /* matte operation */ - alpha = inColor[this->m_ids[0]] - max(inColor[this->m_ids[1]], inColor[this->m_ids[2]]); + /* matte operation */ + alpha = inColor[this->m_ids[0]] - max(inColor[this->m_ids[1]], inColor[this->m_ids[2]]); - /* flip because 0.0 is transparent, not 1.0 */ - alpha = 1.0f - alpha; + /* flip because 0.0 is transparent, not 1.0 */ + alpha = 1.0f - alpha; - /* test range */ - if (alpha > limit_max) { - alpha = inColor[3]; /*whatever it was prior */ - } - else if (alpha < limit_min) { - alpha = 0.0f; - } - else { /*blend */ - alpha = (alpha - limit_min) / limit_range; - } + /* test range */ + if (alpha > limit_max) { + alpha = inColor[3]; /*whatever it was prior */ + } + else if (alpha < limit_min) { + alpha = 0.0f; + } + else { /*blend */ + alpha = (alpha - limit_min) / limit_range; + } - /* store matte(alpha) value in [0] to go with - * COM_SetAlphaOperation and the Value output - */ + /* store matte(alpha) value in [0] to go with + * COM_SetAlphaOperation and the Value output + */ - /* don't make something that was more transparent less transparent */ - output[0] = min(alpha, inColor[3]); + /* don't make something that was more transparent less transparent */ + output[0] = min(alpha, inColor[3]); } diff --git a/source/blender/compositor/operations/COM_ChannelMatteOperation.h b/source/blender/compositor/operations/COM_ChannelMatteOperation.h index 152dd78a6b3..ad88b41cc91 100644 --- a/source/blender/compositor/operations/COM_ChannelMatteOperation.h +++ b/source/blender/compositor/operations/COM_ChannelMatteOperation.h @@ -20,54 +20,54 @@ #define __COM_CHANNELMATTEOPERATION_H__ #include "COM_MixOperation.h" - /** * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ class ChannelMatteOperation : public NodeOperation { -private: - SocketReader *m_inputImageProgram; + private: + SocketReader *m_inputImageProgram; + + /* int m_color_space; */ /* node->custom1 */ /* UNUSED */ /* TODO ? */ + int m_matte_channel; /* node->custom2 */ + int m_limit_method; /* node->algorithm */ + int m_limit_channel; /* node->channel */ + float m_limit_max; /* node->storage->t1 */ + float m_limit_min; /* node->storage->t2 */ - /* int m_color_space; */ /* node->custom1 */ /* UNUSED */ /* TODO ? */ - int m_matte_channel; /* node->custom2 */ - int m_limit_method; /* node->algorithm */ - int m_limit_channel; /* node->channel */ - float m_limit_max; /* node->storage->t1 */ - float m_limit_min; /* node->storage->t2 */ + float m_limit_range; - float m_limit_range; + /** ids to use for the operations (max and simple) + * alpha = in[ids[0]] - max(in[ids[1]], in[ids[2]]) + * the simple operation is using: + * alpha = in[ids[0]] - in[ids[1]] + * but to use the same formula and operation for both we do: + * ids[2] = ids[1] + * alpha = in[ids[0]] - max(in[ids[1]], in[ids[2]]) + */ + int m_ids[3]; - /** ids to use for the operations (max and simple) - * alpha = in[ids[0]] - max(in[ids[1]], in[ids[2]]) - * the simple operation is using: - * alpha = in[ids[0]] - in[ids[1]] - * but to use the same formula and operation for both we do: - * ids[2] = ids[1] - * alpha = in[ids[0]] - max(in[ids[1]], in[ids[2]]) - */ - int m_ids[3]; -public: - /** - * Default constructor - */ - ChannelMatteOperation(); + public: + /** + * Default constructor + */ + ChannelMatteOperation(); - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - void initExecution(); - void deinitExecution(); + void initExecution(); + void deinitExecution(); - void setSettings(NodeChroma *nodeChroma, const int custom2) - { - this->m_limit_max = nodeChroma->t1; - this->m_limit_min = nodeChroma->t2; - this->m_limit_method = nodeChroma->algorithm; - this->m_limit_channel = nodeChroma->channel; - this->m_matte_channel = custom2; - } + void setSettings(NodeChroma *nodeChroma, const int custom2) + { + this->m_limit_max = nodeChroma->t1; + this->m_limit_min = nodeChroma->t2; + this->m_limit_method = nodeChroma->algorithm; + this->m_limit_channel = nodeChroma->channel; + this->m_matte_channel = custom2; + } }; #endif diff --git a/source/blender/compositor/operations/COM_ChromaMatteOperation.cpp b/source/blender/compositor/operations/COM_ChromaMatteOperation.cpp index 05a184a4b58..62dc74d2092 100644 --- a/source/blender/compositor/operations/COM_ChromaMatteOperation.cpp +++ b/source/blender/compositor/operations/COM_ChromaMatteOperation.cpp @@ -21,87 +21,90 @@ ChromaMatteOperation::ChromaMatteOperation() : NodeOperation() { - addInputSocket(COM_DT_COLOR); - addInputSocket(COM_DT_COLOR); - addOutputSocket(COM_DT_VALUE); + addInputSocket(COM_DT_COLOR); + addInputSocket(COM_DT_COLOR); + addOutputSocket(COM_DT_VALUE); - this->m_inputImageProgram = NULL; - this->m_inputKeyProgram = NULL; + this->m_inputImageProgram = NULL; + this->m_inputKeyProgram = NULL; } void ChromaMatteOperation::initExecution() { - this->m_inputImageProgram = this->getInputSocketReader(0); - this->m_inputKeyProgram = this->getInputSocketReader(1); + this->m_inputImageProgram = this->getInputSocketReader(0); + this->m_inputKeyProgram = this->getInputSocketReader(1); } void ChromaMatteOperation::deinitExecution() { - this->m_inputImageProgram = NULL; - this->m_inputKeyProgram = NULL; + this->m_inputImageProgram = NULL; + this->m_inputKeyProgram = NULL; } -void ChromaMatteOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ChromaMatteOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inKey[4]; - float inImage[4]; - - const float acceptance = this->m_settings->t1; /* in radians */ - const float cutoff = this->m_settings->t2; /* in radians */ - const float gain = this->m_settings->fstrength; - - float x_angle, z_angle, alpha; - float theta, beta; - float kfg; - - this->m_inputKeyProgram->readSampled(inKey, x, y, sampler); - this->m_inputImageProgram->readSampled(inImage, x, y, sampler); - - /* store matte(alpha) value in [0] to go with - * COM_SetAlphaOperation and the Value output - */ - - /* Algorithm from book "Video Demistified," does not include the spill reduction part */ - /* find theta, the angle that the color space should be rotated based on key */ - - /* rescale to -1.0..1.0 */ - // inImage[0] = (inImage[0] * 2.0f) - 1.0f; // UNUSED - inImage[1] = (inImage[1] * 2.0f) - 1.0f; - inImage[2] = (inImage[2] * 2.0f) - 1.0f; - - // inKey[0] = (inKey[0] * 2.0f) - 1.0f; // UNUSED - inKey[1] = (inKey[1] * 2.0f) - 1.0f; - inKey[2] = (inKey[2] * 2.0f) - 1.0f; - - theta = atan2(inKey[2], inKey[1]); - - /*rotate the cb and cr into x/z space */ - x_angle = inImage[1] * cosf(theta) + inImage[2] * sinf(theta); - z_angle = inImage[2] * cosf(theta) - inImage[1] * sinf(theta); - - /*if within the acceptance angle */ - /* if kfg is <0 then the pixel is outside of the key color */ - kfg = x_angle - (fabsf(z_angle) / tanf(acceptance / 2.0f)); - - if (kfg > 0.0f) { /* found a pixel that is within key color */ - alpha = 1.0f - (kfg / gain); - - beta = atan2(z_angle, x_angle); - - /* if beta is within the cutoff angle */ - if (fabsf(beta) < (cutoff / 2.0f)) { - alpha = 0.0f; - } - - /* don't make something that was more transparent less transparent */ - if (alpha < inImage[3]) { - output[0] = alpha; - } - else { - output[0] = inImage[3]; - } - } - else { /*pixel is outside key color */ - output[0] = inImage[3]; /* make pixel just as transparent as it was before */ - } + float inKey[4]; + float inImage[4]; + + const float acceptance = this->m_settings->t1; /* in radians */ + const float cutoff = this->m_settings->t2; /* in radians */ + const float gain = this->m_settings->fstrength; + + float x_angle, z_angle, alpha; + float theta, beta; + float kfg; + + this->m_inputKeyProgram->readSampled(inKey, x, y, sampler); + this->m_inputImageProgram->readSampled(inImage, x, y, sampler); + + /* store matte(alpha) value in [0] to go with + * COM_SetAlphaOperation and the Value output + */ + + /* Algorithm from book "Video Demistified," does not include the spill reduction part */ + /* find theta, the angle that the color space should be rotated based on key */ + + /* rescale to -1.0..1.0 */ + // inImage[0] = (inImage[0] * 2.0f) - 1.0f; // UNUSED + inImage[1] = (inImage[1] * 2.0f) - 1.0f; + inImage[2] = (inImage[2] * 2.0f) - 1.0f; + + // inKey[0] = (inKey[0] * 2.0f) - 1.0f; // UNUSED + inKey[1] = (inKey[1] * 2.0f) - 1.0f; + inKey[2] = (inKey[2] * 2.0f) - 1.0f; + + theta = atan2(inKey[2], inKey[1]); + + /*rotate the cb and cr into x/z space */ + x_angle = inImage[1] * cosf(theta) + inImage[2] * sinf(theta); + z_angle = inImage[2] * cosf(theta) - inImage[1] * sinf(theta); + + /*if within the acceptance angle */ + /* if kfg is <0 then the pixel is outside of the key color */ + kfg = x_angle - (fabsf(z_angle) / tanf(acceptance / 2.0f)); + + if (kfg > 0.0f) { /* found a pixel that is within key color */ + alpha = 1.0f - (kfg / gain); + + beta = atan2(z_angle, x_angle); + + /* if beta is within the cutoff angle */ + if (fabsf(beta) < (cutoff / 2.0f)) { + alpha = 0.0f; + } + + /* don't make something that was more transparent less transparent */ + if (alpha < inImage[3]) { + output[0] = alpha; + } + else { + output[0] = inImage[3]; + } + } + else { /*pixel is outside key color */ + output[0] = inImage[3]; /* make pixel just as transparent as it was before */ + } } diff --git a/source/blender/compositor/operations/COM_ChromaMatteOperation.h b/source/blender/compositor/operations/COM_ChromaMatteOperation.h index 7782ed7e1fa..58da839823d 100644 --- a/source/blender/compositor/operations/COM_ChromaMatteOperation.h +++ b/source/blender/compositor/operations/COM_ChromaMatteOperation.h @@ -20,30 +20,33 @@ #define __COM_CHROMAMATTEOPERATION_H__ #include "COM_MixOperation.h" - /** * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ class ChromaMatteOperation : public NodeOperation { -private: - NodeChroma *m_settings; - SocketReader *m_inputImageProgram; - SocketReader *m_inputKeyProgram; -public: - /** - * Default constructor - */ - ChromaMatteOperation(); + private: + NodeChroma *m_settings; + SocketReader *m_inputImageProgram; + SocketReader *m_inputKeyProgram; + + public: + /** + * Default constructor + */ + ChromaMatteOperation(); - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - void initExecution(); - void deinitExecution(); + void initExecution(); + void deinitExecution(); - void setSettings(NodeChroma *nodeChroma) { this->m_settings = nodeChroma; } + void setSettings(NodeChroma *nodeChroma) + { + this->m_settings = nodeChroma; + } }; #endif diff --git a/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cpp b/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cpp index 8debf01417e..f957186a652 100644 --- a/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cpp +++ b/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cpp @@ -21,51 +21,60 @@ inline float colorbalance_cdl(float in, float offset, float power, float slope) { - float x = in * slope + offset; + float x = in * slope + offset; - /* prevent NaN */ - if (x < 0.0f) x = 0.0f; + /* prevent NaN */ + if (x < 0.0f) + x = 0.0f; - return powf(x, power); + return powf(x, power); } ColorBalanceASCCDLOperation::ColorBalanceASCCDLOperation() : NodeOperation() { - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - this->m_inputValueOperation = NULL; - this->m_inputColorOperation = NULL; - this->setResolutionInputSocketIndex(1); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); + this->m_inputValueOperation = NULL; + this->m_inputColorOperation = NULL; + this->setResolutionInputSocketIndex(1); } void ColorBalanceASCCDLOperation::initExecution() { - this->m_inputValueOperation = this->getInputSocketReader(0); - this->m_inputColorOperation = this->getInputSocketReader(1); + this->m_inputValueOperation = this->getInputSocketReader(0); + this->m_inputColorOperation = this->getInputSocketReader(1); } -void ColorBalanceASCCDLOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ColorBalanceASCCDLOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor[4]; - float value[4]; + float inputColor[4]; + float value[4]; - this->m_inputValueOperation->readSampled(value, x, y, sampler); - this->m_inputColorOperation->readSampled(inputColor, x, y, sampler); + this->m_inputValueOperation->readSampled(value, x, y, sampler); + this->m_inputColorOperation->readSampled(inputColor, x, y, sampler); - float fac = value[0]; - fac = min(1.0f, fac); - const float mfac = 1.0f - fac; - - output[0] = mfac * inputColor[0] + fac * colorbalance_cdl(inputColor[0], this->m_offset[0], this->m_power[0], this->m_slope[0]); - output[1] = mfac * inputColor[1] + fac * colorbalance_cdl(inputColor[1], this->m_offset[1], this->m_power[1], this->m_slope[1]); - output[2] = mfac * inputColor[2] + fac * colorbalance_cdl(inputColor[2], this->m_offset[2], this->m_power[2], this->m_slope[2]); - output[3] = inputColor[3]; + float fac = value[0]; + fac = min(1.0f, fac); + const float mfac = 1.0f - fac; + output[0] = mfac * inputColor[0] + + fac * colorbalance_cdl( + inputColor[0], this->m_offset[0], this->m_power[0], this->m_slope[0]); + output[1] = mfac * inputColor[1] + + fac * colorbalance_cdl( + inputColor[1], this->m_offset[1], this->m_power[1], this->m_slope[1]); + output[2] = mfac * inputColor[2] + + fac * colorbalance_cdl( + inputColor[2], this->m_offset[2], this->m_power[2], this->m_slope[2]); + output[3] = inputColor[3]; } void ColorBalanceASCCDLOperation::deinitExecution() { - this->m_inputValueOperation = NULL; - this->m_inputColorOperation = NULL; + this->m_inputValueOperation = NULL; + this->m_inputColorOperation = NULL; } diff --git a/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.h b/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.h index 1ce0ec71538..fd1d51a293b 100644 --- a/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.h +++ b/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.h @@ -25,40 +25,49 @@ * it assumes we are in sRGB color space. */ class ColorBalanceASCCDLOperation : public NodeOperation { -protected: - /** - * Prefetched reference to the inputProgram - */ - SocketReader *m_inputValueOperation; - SocketReader *m_inputColorOperation; + protected: + /** + * Prefetched reference to the inputProgram + */ + SocketReader *m_inputValueOperation; + SocketReader *m_inputColorOperation; - float m_offset[3]; - float m_power[3]; - float m_slope[3]; + float m_offset[3]; + float m_power[3]; + float m_slope[3]; -public: - /** - * Default constructor - */ - ColorBalanceASCCDLOperation(); + public: + /** + * Default constructor + */ + ColorBalanceASCCDLOperation(); - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - /** - * Initialize the execution - */ - void initExecution(); + /** + * Initialize the execution + */ + void initExecution(); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Deinitialize the execution + */ + void deinitExecution(); - void setOffset(float offset[3]) { copy_v3_v3(this->m_offset, offset); } - void setPower(float power[3]) { copy_v3_v3(this->m_power, power); } - void setSlope(float slope[3]) { copy_v3_v3(this->m_slope, slope); } + void setOffset(float offset[3]) + { + copy_v3_v3(this->m_offset, offset); + } + void setPower(float power[3]) + { + copy_v3_v3(this->m_power, power); + } + void setSlope(float slope[3]) + { + copy_v3_v3(this->m_slope, slope); + } }; #endif diff --git a/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cpp b/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cpp index 5b048dfe405..48807e9218d 100644 --- a/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cpp +++ b/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cpp @@ -19,58 +19,66 @@ #include "COM_ColorBalanceLGGOperation.h" #include "BLI_math.h" - inline float colorbalance_lgg(float in, float lift_lgg, float gamma_inv, float gain) { - /* 1:1 match with the sequencer with linear/srgb conversions, the conversion isnt pretty - * but best keep it this way, sice testing for durian shows a similar calculation - * without lin/srgb conversions gives bad results (over-saturated shadows) with colors - * slightly below 1.0. some correction can be done but it ends up looking bad for shadows or lighter tones - campbell */ - float x = (((linearrgb_to_srgb(in) - 1.0f) * lift_lgg) + 1.0f) * gain; + /* 1:1 match with the sequencer with linear/srgb conversions, the conversion isnt pretty + * but best keep it this way, sice testing for durian shows a similar calculation + * without lin/srgb conversions gives bad results (over-saturated shadows) with colors + * slightly below 1.0. some correction can be done but it ends up looking bad for shadows or lighter tones - campbell */ + float x = (((linearrgb_to_srgb(in) - 1.0f) * lift_lgg) + 1.0f) * gain; - /* prevent NaN */ - if (x < 0.0f) x = 0.0f; + /* prevent NaN */ + if (x < 0.0f) + x = 0.0f; - return powf(srgb_to_linearrgb(x), gamma_inv); + return powf(srgb_to_linearrgb(x), gamma_inv); } ColorBalanceLGGOperation::ColorBalanceLGGOperation() : NodeOperation() { - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - this->m_inputValueOperation = NULL; - this->m_inputColorOperation = NULL; - this->setResolutionInputSocketIndex(1); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); + this->m_inputValueOperation = NULL; + this->m_inputColorOperation = NULL; + this->setResolutionInputSocketIndex(1); } void ColorBalanceLGGOperation::initExecution() { - this->m_inputValueOperation = this->getInputSocketReader(0); - this->m_inputColorOperation = this->getInputSocketReader(1); + this->m_inputValueOperation = this->getInputSocketReader(0); + this->m_inputColorOperation = this->getInputSocketReader(1); } -void ColorBalanceLGGOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ColorBalanceLGGOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor[4]; - float value[4]; - - this->m_inputValueOperation->readSampled(value, x, y, sampler); - this->m_inputColorOperation->readSampled(inputColor, x, y, sampler); + float inputColor[4]; + float value[4]; - float fac = value[0]; - fac = min(1.0f, fac); - const float mfac = 1.0f - fac; + this->m_inputValueOperation->readSampled(value, x, y, sampler); + this->m_inputColorOperation->readSampled(inputColor, x, y, sampler); - output[0] = mfac * inputColor[0] + fac * colorbalance_lgg(inputColor[0], this->m_lift[0], this->m_gamma_inv[0], this->m_gain[0]); - output[1] = mfac * inputColor[1] + fac * colorbalance_lgg(inputColor[1], this->m_lift[1], this->m_gamma_inv[1], this->m_gain[1]); - output[2] = mfac * inputColor[2] + fac * colorbalance_lgg(inputColor[2], this->m_lift[2], this->m_gamma_inv[2], this->m_gain[2]); - output[3] = inputColor[3]; + float fac = value[0]; + fac = min(1.0f, fac); + const float mfac = 1.0f - fac; + output[0] = mfac * inputColor[0] + + fac * colorbalance_lgg( + inputColor[0], this->m_lift[0], this->m_gamma_inv[0], this->m_gain[0]); + output[1] = mfac * inputColor[1] + + fac * colorbalance_lgg( + inputColor[1], this->m_lift[1], this->m_gamma_inv[1], this->m_gain[1]); + output[2] = mfac * inputColor[2] + + fac * colorbalance_lgg( + inputColor[2], this->m_lift[2], this->m_gamma_inv[2], this->m_gain[2]); + output[3] = inputColor[3]; } void ColorBalanceLGGOperation::deinitExecution() { - this->m_inputValueOperation = NULL; - this->m_inputColorOperation = NULL; + this->m_inputValueOperation = NULL; + this->m_inputColorOperation = NULL; } diff --git a/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.h b/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.h index 2a96f7fdf01..a2d4b4cd13a 100644 --- a/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.h +++ b/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.h @@ -20,46 +20,54 @@ #define __COM_COLORBALANCELGGOPERATION_H__ #include "COM_NodeOperation.h" - /** * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ class ColorBalanceLGGOperation : public NodeOperation { -protected: - /** - * Prefetched reference to the inputProgram - */ - SocketReader *m_inputValueOperation; - SocketReader *m_inputColorOperation; + protected: + /** + * Prefetched reference to the inputProgram + */ + SocketReader *m_inputValueOperation; + SocketReader *m_inputColorOperation; - float m_gain[3]; - float m_lift[3]; - float m_gamma_inv[3]; + float m_gain[3]; + float m_lift[3]; + float m_gamma_inv[3]; -public: - /** - * Default constructor - */ - ColorBalanceLGGOperation(); + public: + /** + * Default constructor + */ + ColorBalanceLGGOperation(); - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - /** - * Initialize the execution - */ - void initExecution(); + /** + * Initialize the execution + */ + void initExecution(); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Deinitialize the execution + */ + void deinitExecution(); - void setGain(const float gain[3]) { copy_v3_v3(this->m_gain, gain); } - void setLift(const float lift[3]) { copy_v3_v3(this->m_lift, lift); } - void setGammaInv(const float gamma_inv[3]) { copy_v3_v3(this->m_gamma_inv, gamma_inv); } + void setGain(const float gain[3]) + { + copy_v3_v3(this->m_gain, gain); + } + void setLift(const float lift[3]) + { + copy_v3_v3(this->m_lift, lift); + } + void setGammaInv(const float gamma_inv[3]) + { + copy_v3_v3(this->m_gamma_inv, gamma_inv); + } }; #endif diff --git a/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp b/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp index 821f1cbb44e..a90a3e234d8 100644 --- a/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp +++ b/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp @@ -25,118 +25,130 @@ extern "C" { ColorCorrectionOperation::ColorCorrectionOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_COLOR); - this->m_inputImage = NULL; - this->m_inputMask = NULL; - this->m_redChannelEnabled = true; - this->m_greenChannelEnabled = true; - this->m_blueChannelEnabled = true; + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_COLOR); + this->m_inputImage = NULL; + this->m_inputMask = NULL; + this->m_redChannelEnabled = true; + this->m_greenChannelEnabled = true; + this->m_blueChannelEnabled = true; } void ColorCorrectionOperation::initExecution() { - this->m_inputImage = this->getInputSocketReader(0); - this->m_inputMask = this->getInputSocketReader(1); + this->m_inputImage = this->getInputSocketReader(0); + this->m_inputMask = this->getInputSocketReader(1); } -void ColorCorrectionOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ColorCorrectionOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputImageColor[4]; - float inputMask[4]; - this->m_inputImage->readSampled(inputImageColor, x, y, sampler); - this->m_inputMask->readSampled(inputMask, x, y, sampler); - - float level = (inputImageColor[0] + inputImageColor[1] + inputImageColor[2]) / 3.0f; - float contrast = this->m_data->master.contrast; - float saturation = this->m_data->master.saturation; - float gamma = this->m_data->master.gamma; - float gain = this->m_data->master.gain; - float lift = this->m_data->master.lift; - float r, g, b; - - float value = inputMask[0]; - value = min(1.0f, value); - const float mvalue = 1.0f - value; - - float levelShadows = 0.0; - float levelMidtones = 0.0; - float levelHighlights = 0.0; + float inputImageColor[4]; + float inputMask[4]; + this->m_inputImage->readSampled(inputImageColor, x, y, sampler); + this->m_inputMask->readSampled(inputMask, x, y, sampler); + + float level = (inputImageColor[0] + inputImageColor[1] + inputImageColor[2]) / 3.0f; + float contrast = this->m_data->master.contrast; + float saturation = this->m_data->master.saturation; + float gamma = this->m_data->master.gamma; + float gain = this->m_data->master.gain; + float lift = this->m_data->master.lift; + float r, g, b; + + float value = inputMask[0]; + value = min(1.0f, value); + const float mvalue = 1.0f - value; + + float levelShadows = 0.0; + float levelMidtones = 0.0; + float levelHighlights = 0.0; #define MARGIN 0.10f #define MARGIN_DIV (0.5f / MARGIN) - if (level < this->m_data->startmidtones - MARGIN) { - levelShadows = 1.0f; - } - else if (level < this->m_data->startmidtones + MARGIN) { - levelMidtones = ((level - this->m_data->startmidtones) * MARGIN_DIV) + 0.5f; - levelShadows = 1.0f - levelMidtones; - } - else if (level < this->m_data->endmidtones - MARGIN) { - levelMidtones = 1.0f; - } - else if (level < this->m_data->endmidtones + MARGIN) { - levelHighlights = ((level - this->m_data->endmidtones) * MARGIN_DIV) + 0.5f; - levelMidtones = 1.0f - levelHighlights; - } - else { - levelHighlights = 1.0f; - } + if (level < this->m_data->startmidtones - MARGIN) { + levelShadows = 1.0f; + } + else if (level < this->m_data->startmidtones + MARGIN) { + levelMidtones = ((level - this->m_data->startmidtones) * MARGIN_DIV) + 0.5f; + levelShadows = 1.0f - levelMidtones; + } + else if (level < this->m_data->endmidtones - MARGIN) { + levelMidtones = 1.0f; + } + else if (level < this->m_data->endmidtones + MARGIN) { + levelHighlights = ((level - this->m_data->endmidtones) * MARGIN_DIV) + 0.5f; + levelMidtones = 1.0f - levelHighlights; + } + else { + levelHighlights = 1.0f; + } #undef MARGIN #undef MARGIN_DIV - contrast *= (levelShadows * this->m_data->shadows.contrast) + (levelMidtones * this->m_data->midtones.contrast) + (levelHighlights * this->m_data->highlights.contrast); - saturation *= (levelShadows * this->m_data->shadows.saturation) + (levelMidtones * this->m_data->midtones.saturation) + (levelHighlights * this->m_data->highlights.saturation); - gamma *= (levelShadows * this->m_data->shadows.gamma) + (levelMidtones * this->m_data->midtones.gamma) + (levelHighlights * this->m_data->highlights.gamma); - gain *= (levelShadows * this->m_data->shadows.gain) + (levelMidtones * this->m_data->midtones.gain) + (levelHighlights * this->m_data->highlights.gain); - lift += (levelShadows * this->m_data->shadows.lift) + (levelMidtones * this->m_data->midtones.lift) + (levelHighlights * this->m_data->highlights.lift); - - float invgamma = 1.0f / gamma; - float luma = IMB_colormanagement_get_luminance(inputImageColor); - - r = inputImageColor[0]; - g = inputImageColor[1]; - b = inputImageColor[2]; - - r = (luma + saturation * (r - luma)); - g = (luma + saturation * (g - luma)); - b = (luma + saturation * (b - luma)); - - r = 0.5f + ((r - 0.5f) * contrast); - g = 0.5f + ((g - 0.5f) * contrast); - b = 0.5f + ((b - 0.5f) * contrast); - - r = powf(r * gain + lift, invgamma); - g = powf(g * gain + lift, invgamma); - b = powf(b * gain + lift, invgamma); - - - // mix with mask - r = mvalue * inputImageColor[0] + value * r; - g = mvalue * inputImageColor[1] + value * g; - b = mvalue * inputImageColor[2] + value * b; - - if (this->m_redChannelEnabled) { - output[0] = r; - } - else { - output[0] = inputImageColor[0]; - } - if (this->m_greenChannelEnabled) { - output[1] = g; - } - else { - output[1] = inputImageColor[1]; - } - if (this->m_blueChannelEnabled) { - output[2] = b; - } - else { - output[2] = inputImageColor[2]; - } - output[3] = inputImageColor[3]; + contrast *= (levelShadows * this->m_data->shadows.contrast) + + (levelMidtones * this->m_data->midtones.contrast) + + (levelHighlights * this->m_data->highlights.contrast); + saturation *= (levelShadows * this->m_data->shadows.saturation) + + (levelMidtones * this->m_data->midtones.saturation) + + (levelHighlights * this->m_data->highlights.saturation); + gamma *= (levelShadows * this->m_data->shadows.gamma) + + (levelMidtones * this->m_data->midtones.gamma) + + (levelHighlights * this->m_data->highlights.gamma); + gain *= (levelShadows * this->m_data->shadows.gain) + + (levelMidtones * this->m_data->midtones.gain) + + (levelHighlights * this->m_data->highlights.gain); + lift += (levelShadows * this->m_data->shadows.lift) + + (levelMidtones * this->m_data->midtones.lift) + + (levelHighlights * this->m_data->highlights.lift); + + float invgamma = 1.0f / gamma; + float luma = IMB_colormanagement_get_luminance(inputImageColor); + + r = inputImageColor[0]; + g = inputImageColor[1]; + b = inputImageColor[2]; + + r = (luma + saturation * (r - luma)); + g = (luma + saturation * (g - luma)); + b = (luma + saturation * (b - luma)); + + r = 0.5f + ((r - 0.5f) * contrast); + g = 0.5f + ((g - 0.5f) * contrast); + b = 0.5f + ((b - 0.5f) * contrast); + + r = powf(r * gain + lift, invgamma); + g = powf(g * gain + lift, invgamma); + b = powf(b * gain + lift, invgamma); + + // mix with mask + r = mvalue * inputImageColor[0] + value * r; + g = mvalue * inputImageColor[1] + value * g; + b = mvalue * inputImageColor[2] + value * b; + + if (this->m_redChannelEnabled) { + output[0] = r; + } + else { + output[0] = inputImageColor[0]; + } + if (this->m_greenChannelEnabled) { + output[1] = g; + } + else { + output[1] = inputImageColor[1]; + } + if (this->m_blueChannelEnabled) { + output[2] = b; + } + else { + output[2] = inputImageColor[2]; + } + output[3] = inputImageColor[3]; } void ColorCorrectionOperation::deinitExecution() { - this->m_inputImage = NULL; - this->m_inputMask = NULL; + this->m_inputImage = NULL; + this->m_inputMask = NULL; } diff --git a/source/blender/compositor/operations/COM_ColorCorrectionOperation.h b/source/blender/compositor/operations/COM_ColorCorrectionOperation.h index 7bc85aa6f3e..ec9632acc7c 100644 --- a/source/blender/compositor/operations/COM_ColorCorrectionOperation.h +++ b/source/blender/compositor/operations/COM_ColorCorrectionOperation.h @@ -20,41 +20,52 @@ #define __COM_COLORCORRECTIONOPERATION_H__ #include "COM_NodeOperation.h" - class ColorCorrectionOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputImage; - SocketReader *m_inputMask; - NodeColorCorrection *m_data; - - bool m_redChannelEnabled; - bool m_greenChannelEnabled; - bool m_blueChannelEnabled; - -public: - ColorCorrectionOperation(); - - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - - /** - * Initialize the execution - */ - void initExecution(); - - /** - * Deinitialize the execution - */ - void deinitExecution(); - - void setData(NodeColorCorrection *data) { this->m_data = data; } - void setRedChannelEnabled(bool enabled) { this->m_redChannelEnabled = enabled; } - void setGreenChannelEnabled(bool enabled) { this->m_greenChannelEnabled = enabled; } - void setBlueChannelEnabled(bool enabled) { this->m_blueChannelEnabled = enabled; } + private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputImage; + SocketReader *m_inputMask; + NodeColorCorrection *m_data; + + bool m_redChannelEnabled; + bool m_greenChannelEnabled; + bool m_blueChannelEnabled; + + public: + ColorCorrectionOperation(); + + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + + /** + * Initialize the execution + */ + void initExecution(); + + /** + * Deinitialize the execution + */ + void deinitExecution(); + + void setData(NodeColorCorrection *data) + { + this->m_data = data; + } + void setRedChannelEnabled(bool enabled) + { + this->m_redChannelEnabled = enabled; + } + void setGreenChannelEnabled(bool enabled) + { + this->m_greenChannelEnabled = enabled; + } + void setBlueChannelEnabled(bool enabled) + { + this->m_blueChannelEnabled = enabled; + } }; #endif diff --git a/source/blender/compositor/operations/COM_ColorCurveOperation.cpp b/source/blender/compositor/operations/COM_ColorCurveOperation.cpp index 51fbb4ebde4..e25ef49cf28 100644 --- a/source/blender/compositor/operations/COM_ColorCurveOperation.cpp +++ b/source/blender/compositor/operations/COM_ColorCurveOperation.cpp @@ -21,136 +21,138 @@ #ifdef __cplusplus extern "C" { #endif -# include "BKE_colortools.h" +#include "BKE_colortools.h" #ifdef __cplusplus } -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif ColorCurveOperation::ColorCurveOperation() : CurveBaseOperation() { - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - - this->m_inputFacProgram = NULL; - this->m_inputImageProgram = NULL; - this->m_inputBlackProgram = NULL; - this->m_inputWhiteProgram = NULL; - - this->setResolutionInputSocketIndex(1); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); + + this->m_inputFacProgram = NULL; + this->m_inputImageProgram = NULL; + this->m_inputBlackProgram = NULL; + this->m_inputWhiteProgram = NULL; + + this->setResolutionInputSocketIndex(1); } void ColorCurveOperation::initExecution() { - CurveBaseOperation::initExecution(); - this->m_inputFacProgram = this->getInputSocketReader(0); - this->m_inputImageProgram = this->getInputSocketReader(1); - this->m_inputBlackProgram = this->getInputSocketReader(2); - this->m_inputWhiteProgram = this->getInputSocketReader(3); - - curvemapping_premultiply(this->m_curveMapping, 0); + CurveBaseOperation::initExecution(); + this->m_inputFacProgram = this->getInputSocketReader(0); + this->m_inputImageProgram = this->getInputSocketReader(1); + this->m_inputBlackProgram = this->getInputSocketReader(2); + this->m_inputWhiteProgram = this->getInputSocketReader(3); + curvemapping_premultiply(this->m_curveMapping, 0); } -void ColorCurveOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ColorCurveOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - CurveMapping *cumap = this->m_curveMapping; - - float fac[4]; - float image[4]; - - /* local versions of cumap->black, cumap->white, cumap->bwmul */ - float black[4]; - float white[4]; - float bwmul[3]; - - this->m_inputBlackProgram->readSampled(black, x, y, sampler); - this->m_inputWhiteProgram->readSampled(white, x, y, sampler); - - /* get our own local bwmul value, - * since we can't be threadsafe and use cumap->bwmul & friends */ - curvemapping_set_black_white_ex(black, white, bwmul); - - this->m_inputFacProgram->readSampled(fac, x, y, sampler); - this->m_inputImageProgram->readSampled(image, x, y, sampler); - - if (*fac >= 1.0f) { - curvemapping_evaluate_premulRGBF_ex(cumap, output, image, - black, bwmul); - } - else if (*fac <= 0.0f) { - copy_v3_v3(output, image); - } - else { - float col[4]; - curvemapping_evaluate_premulRGBF_ex(cumap, col, image, - black, bwmul); - interp_v3_v3v3(output, image, col, *fac); - } - output[3] = image[3]; + CurveMapping *cumap = this->m_curveMapping; + + float fac[4]; + float image[4]; + + /* local versions of cumap->black, cumap->white, cumap->bwmul */ + float black[4]; + float white[4]; + float bwmul[3]; + + this->m_inputBlackProgram->readSampled(black, x, y, sampler); + this->m_inputWhiteProgram->readSampled(white, x, y, sampler); + + /* get our own local bwmul value, + * since we can't be threadsafe and use cumap->bwmul & friends */ + curvemapping_set_black_white_ex(black, white, bwmul); + + this->m_inputFacProgram->readSampled(fac, x, y, sampler); + this->m_inputImageProgram->readSampled(image, x, y, sampler); + + if (*fac >= 1.0f) { + curvemapping_evaluate_premulRGBF_ex(cumap, output, image, black, bwmul); + } + else if (*fac <= 0.0f) { + copy_v3_v3(output, image); + } + else { + float col[4]; + curvemapping_evaluate_premulRGBF_ex(cumap, col, image, black, bwmul); + interp_v3_v3v3(output, image, col, *fac); + } + output[3] = image[3]; } void ColorCurveOperation::deinitExecution() { - CurveBaseOperation::deinitExecution(); - this->m_inputFacProgram = NULL; - this->m_inputImageProgram = NULL; - this->m_inputBlackProgram = NULL; - this->m_inputWhiteProgram = NULL; + CurveBaseOperation::deinitExecution(); + this->m_inputFacProgram = NULL; + this->m_inputImageProgram = NULL; + this->m_inputBlackProgram = NULL; + this->m_inputWhiteProgram = NULL; } - // Constant level curve mapping ConstantLevelColorCurveOperation::ConstantLevelColorCurveOperation() : CurveBaseOperation() { - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); - this->m_inputFacProgram = NULL; - this->m_inputImageProgram = NULL; + this->m_inputFacProgram = NULL; + this->m_inputImageProgram = NULL; - this->setResolutionInputSocketIndex(1); + this->setResolutionInputSocketIndex(1); } void ConstantLevelColorCurveOperation::initExecution() { - CurveBaseOperation::initExecution(); - this->m_inputFacProgram = this->getInputSocketReader(0); - this->m_inputImageProgram = this->getInputSocketReader(1); + CurveBaseOperation::initExecution(); + this->m_inputFacProgram = this->getInputSocketReader(0); + this->m_inputImageProgram = this->getInputSocketReader(1); - curvemapping_premultiply(this->m_curveMapping, 0); + curvemapping_premultiply(this->m_curveMapping, 0); - curvemapping_set_black_white(this->m_curveMapping, this->m_black, this->m_white); + curvemapping_set_black_white(this->m_curveMapping, this->m_black, this->m_white); } -void ConstantLevelColorCurveOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ConstantLevelColorCurveOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float fac[4]; - float image[4]; - - this->m_inputFacProgram->readSampled(fac, x, y, sampler); - this->m_inputImageProgram->readSampled(image, x, y, sampler); - - if (*fac >= 1.0f) { - curvemapping_evaluate_premulRGBF(this->m_curveMapping, output, image); - } - else if (*fac <= 0.0f) { - copy_v3_v3(output, image); - } - else { - float col[4]; - curvemapping_evaluate_premulRGBF(this->m_curveMapping, col, image); - interp_v3_v3v3(output, image, col, *fac); - } - output[3] = image[3]; + float fac[4]; + float image[4]; + + this->m_inputFacProgram->readSampled(fac, x, y, sampler); + this->m_inputImageProgram->readSampled(image, x, y, sampler); + + if (*fac >= 1.0f) { + curvemapping_evaluate_premulRGBF(this->m_curveMapping, output, image); + } + else if (*fac <= 0.0f) { + copy_v3_v3(output, image); + } + else { + float col[4]; + curvemapping_evaluate_premulRGBF(this->m_curveMapping, col, image); + interp_v3_v3v3(output, image, col, *fac); + } + output[3] = image[3]; } void ConstantLevelColorCurveOperation::deinitExecution() { - CurveBaseOperation::deinitExecution(); - this->m_inputFacProgram = NULL; - this->m_inputImageProgram = NULL; + CurveBaseOperation::deinitExecution(); + this->m_inputFacProgram = NULL; + this->m_inputImageProgram = NULL; } diff --git a/source/blender/compositor/operations/COM_ColorCurveOperation.h b/source/blender/compositor/operations/COM_ColorCurveOperation.h index a1f07fedb50..1d6a9185732 100644 --- a/source/blender/compositor/operations/COM_ColorCurveOperation.h +++ b/source/blender/compositor/operations/COM_ColorCurveOperation.h @@ -23,63 +23,70 @@ #include "COM_CurveBaseOperation.h" class ColorCurveOperation : public CurveBaseOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputFacProgram; - SocketReader *m_inputImageProgram; - SocketReader *m_inputBlackProgram; - SocketReader *m_inputWhiteProgram; -public: - ColorCurveOperation(); + private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputFacProgram; + SocketReader *m_inputImageProgram; + SocketReader *m_inputBlackProgram; + SocketReader *m_inputWhiteProgram; - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + ColorCurveOperation(); - /** - * Initialize the execution - */ - void initExecution(); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Initialize the execution + */ + void initExecution(); + + /** + * Deinitialize the execution + */ + void deinitExecution(); }; class ConstantLevelColorCurveOperation : public CurveBaseOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputFacProgram; - SocketReader *m_inputImageProgram; - float m_black[3]; - float m_white[3]; + private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputFacProgram; + SocketReader *m_inputImageProgram; + float m_black[3]; + float m_white[3]; -public: - ConstantLevelColorCurveOperation(); + public: + ConstantLevelColorCurveOperation(); - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - /** - * Initialize the execution - */ - void initExecution(); + /** + * Initialize the execution + */ + void initExecution(); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Deinitialize the execution + */ + void deinitExecution(); - void setBlackLevel(float black[3]) { copy_v3_v3(this->m_black, black); } - void setWhiteLevel(float white[3]) { copy_v3_v3(this->m_white, white); } + void setBlackLevel(float black[3]) + { + copy_v3_v3(this->m_black, black); + } + void setWhiteLevel(float white[3]) + { + copy_v3_v3(this->m_white, white); + } }; #endif diff --git a/source/blender/compositor/operations/COM_ColorMatteOperation.cpp b/source/blender/compositor/operations/COM_ColorMatteOperation.cpp index fbc8eef0ec9..90b7f4a63b5 100644 --- a/source/blender/compositor/operations/COM_ColorMatteOperation.cpp +++ b/source/blender/compositor/operations/COM_ColorMatteOperation.cpp @@ -21,61 +21,61 @@ ColorMatteOperation::ColorMatteOperation() : NodeOperation() { - addInputSocket(COM_DT_COLOR); - addInputSocket(COM_DT_COLOR); - addOutputSocket(COM_DT_VALUE); + addInputSocket(COM_DT_COLOR); + addInputSocket(COM_DT_COLOR); + addOutputSocket(COM_DT_VALUE); - this->m_inputImageProgram = NULL; - this->m_inputKeyProgram = NULL; + this->m_inputImageProgram = NULL; + this->m_inputKeyProgram = NULL; } void ColorMatteOperation::initExecution() { - this->m_inputImageProgram = this->getInputSocketReader(0); - this->m_inputKeyProgram = this->getInputSocketReader(1); + this->m_inputImageProgram = this->getInputSocketReader(0); + this->m_inputKeyProgram = this->getInputSocketReader(1); } void ColorMatteOperation::deinitExecution() { - this->m_inputImageProgram = NULL; - this->m_inputKeyProgram = NULL; + this->m_inputImageProgram = NULL; + this->m_inputKeyProgram = NULL; } -void ColorMatteOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ColorMatteOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inColor[4]; - float inKey[4]; + float inColor[4]; + float inKey[4]; - const float hue = this->m_settings->t1; - const float sat = this->m_settings->t2; - const float val = this->m_settings->t3; + const float hue = this->m_settings->t1; + const float sat = this->m_settings->t2; + const float val = this->m_settings->t3; - float h_wrap; + float h_wrap; - this->m_inputImageProgram->readSampled(inColor, x, y, sampler); - this->m_inputKeyProgram->readSampled(inKey, x, y, sampler); + this->m_inputImageProgram->readSampled(inColor, x, y, sampler); + this->m_inputKeyProgram->readSampled(inKey, x, y, sampler); + /* store matte(alpha) value in [0] to go with + * COM_SetAlphaOperation and the Value output + */ - /* store matte(alpha) value in [0] to go with - * COM_SetAlphaOperation and the Value output - */ + if ( + /* do hue last because it needs to wrap, and does some more checks */ - if ( - /* do hue last because it needs to wrap, and does some more checks */ + /* sat */ (fabsf(inColor[1] - inKey[1]) < sat) && + /* val */ (fabsf(inColor[2] - inKey[2]) < val) && - /* sat */ (fabsf(inColor[1] - inKey[1]) < sat) && - /* val */ (fabsf(inColor[2] - inKey[2]) < val) && + /* multiply by 2 because it wraps on both sides of the hue, + * otherwise 0.5 would key all hue's */ - /* multiply by 2 because it wraps on both sides of the hue, - * otherwise 0.5 would key all hue's */ + /* hue */ ((h_wrap = 2.0f * fabsf(inColor[0] - inKey[0])) < hue || (2.0f - h_wrap) < hue)) { + output[0] = 0.0f; /* make transparent */ + } - /* hue */ ((h_wrap = 2.0f * fabsf(inColor[0] - inKey[0])) < hue || (2.0f - h_wrap) < hue) - ) - { - output[0] = 0.0f; /* make transparent */ - } - - else { /*pixel is outside key color */ - output[0] = inColor[3]; /* make pixel just as transparent as it was before */ - } + else { /*pixel is outside key color */ + output[0] = inColor[3]; /* make pixel just as transparent as it was before */ + } } diff --git a/source/blender/compositor/operations/COM_ColorMatteOperation.h b/source/blender/compositor/operations/COM_ColorMatteOperation.h index 5fe92292382..7e8a0e295e1 100644 --- a/source/blender/compositor/operations/COM_ColorMatteOperation.h +++ b/source/blender/compositor/operations/COM_ColorMatteOperation.h @@ -20,30 +20,33 @@ #define __COM_COLORMATTEOPERATION_H__ #include "COM_MixOperation.h" - /** * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ class ColorMatteOperation : public NodeOperation { -private: - NodeChroma *m_settings; - SocketReader *m_inputImageProgram; - SocketReader *m_inputKeyProgram; -public: - /** - * Default constructor - */ - ColorMatteOperation(); + private: + NodeChroma *m_settings; + SocketReader *m_inputImageProgram; + SocketReader *m_inputKeyProgram; + + public: + /** + * Default constructor + */ + ColorMatteOperation(); - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - void initExecution(); - void deinitExecution(); + void initExecution(); + void deinitExecution(); - void setSettings(NodeChroma *nodeChroma) { this->m_settings = nodeChroma; } + void setSettings(NodeChroma *nodeChroma) + { + this->m_settings = nodeChroma; + } }; #endif diff --git a/source/blender/compositor/operations/COM_ColorRampOperation.cpp b/source/blender/compositor/operations/COM_ColorRampOperation.cpp index 238c22c426f..f2c153c5d30 100644 --- a/source/blender/compositor/operations/COM_ColorRampOperation.cpp +++ b/source/blender/compositor/operations/COM_ColorRampOperation.cpp @@ -21,33 +21,36 @@ #ifdef __cplusplus extern "C" { #endif -# include "BKE_colorband.h" +#include "BKE_colorband.h" #ifdef __cplusplus } #endif ColorRampOperation::ColorRampOperation() : NodeOperation() { - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_COLOR); - this->m_inputProgram = NULL; - this->m_colorBand = NULL; + this->m_inputProgram = NULL; + this->m_colorBand = NULL; } void ColorRampOperation::initExecution() { - this->m_inputProgram = this->getInputSocketReader(0); + this->m_inputProgram = this->getInputSocketReader(0); } -void ColorRampOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ColorRampOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float values[4]; + float values[4]; - this->m_inputProgram->readSampled(values, x, y, sampler); - BKE_colorband_evaluate(this->m_colorBand, values[0], output); + this->m_inputProgram->readSampled(values, x, y, sampler); + BKE_colorband_evaluate(this->m_colorBand, values[0], output); } void ColorRampOperation::deinitExecution() { - this->m_inputProgram = NULL; + this->m_inputProgram = NULL; } diff --git a/source/blender/compositor/operations/COM_ColorRampOperation.h b/source/blender/compositor/operations/COM_ColorRampOperation.h index 9e313e9d439..3e2acda1d10 100644 --- a/source/blender/compositor/operations/COM_ColorRampOperation.h +++ b/source/blender/compositor/operations/COM_ColorRampOperation.h @@ -22,32 +22,34 @@ #include "DNA_texture_types.h" class ColorRampOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputProgram; - ColorBand *m_colorBand; -public: - ColorRampOperation(); + private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputProgram; + ColorBand *m_colorBand; - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + ColorRampOperation(); - /** - * Initialize the execution - */ - void initExecution(); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Initialize the execution + */ + void initExecution(); - void setColorBand(ColorBand *colorBand) { - this->m_colorBand = colorBand; - } + /** + * Deinitialize the execution + */ + void deinitExecution(); + + void setColorBand(ColorBand *colorBand) + { + this->m_colorBand = colorBand; + } }; #endif diff --git a/source/blender/compositor/operations/COM_ColorSpillOperation.cpp b/source/blender/compositor/operations/COM_ColorSpillOperation.cpp index 656ec1a7439..99ab6105934 100644 --- a/source/blender/compositor/operations/COM_ColorSpillOperation.cpp +++ b/source/blender/compositor/operations/COM_ColorSpillOperation.cpp @@ -22,90 +22,96 @@ ColorSpillOperation::ColorSpillOperation() : NodeOperation() { - addInputSocket(COM_DT_COLOR); - addInputSocket(COM_DT_VALUE); - addOutputSocket(COM_DT_COLOR); + addInputSocket(COM_DT_COLOR); + addInputSocket(COM_DT_VALUE); + addOutputSocket(COM_DT_COLOR); - this->m_inputImageReader = NULL; - this->m_inputFacReader = NULL; - this->m_spillChannel = 1; // GREEN - this->m_spillMethod = 0; + this->m_inputImageReader = NULL; + this->m_inputFacReader = NULL; + this->m_spillChannel = 1; // GREEN + this->m_spillMethod = 0; } void ColorSpillOperation::initExecution() { - this->m_inputImageReader = this->getInputSocketReader(0); - this->m_inputFacReader = this->getInputSocketReader(1); - if (this->m_spillChannel == 0) { - this->m_rmut = -1.0f; - this->m_gmut = 1.0f; - this->m_bmut = 1.0f; - this->m_channel2 = 1; - this->m_channel3 = 2; - if (this->m_settings->unspill == 0) { - this->m_settings->uspillr = 1.0f; - this->m_settings->uspillg = 0.0f; - this->m_settings->uspillb = 0.0f; - } - } - else if (this->m_spillChannel == 1) { - this->m_rmut = 1.0f; - this->m_gmut = -1.0f; - this->m_bmut = 1.0f; - this->m_channel2 = 0; - this->m_channel3 = 2; - if (this->m_settings->unspill == 0) { - this->m_settings->uspillr = 0.0f; - this->m_settings->uspillg = 1.0f; - this->m_settings->uspillb = 0.0f; - } - } - else { - this->m_rmut = 1.0f; - this->m_gmut = 1.0f; - this->m_bmut = -1.0f; + this->m_inputImageReader = this->getInputSocketReader(0); + this->m_inputFacReader = this->getInputSocketReader(1); + if (this->m_spillChannel == 0) { + this->m_rmut = -1.0f; + this->m_gmut = 1.0f; + this->m_bmut = 1.0f; + this->m_channel2 = 1; + this->m_channel3 = 2; + if (this->m_settings->unspill == 0) { + this->m_settings->uspillr = 1.0f; + this->m_settings->uspillg = 0.0f; + this->m_settings->uspillb = 0.0f; + } + } + else if (this->m_spillChannel == 1) { + this->m_rmut = 1.0f; + this->m_gmut = -1.0f; + this->m_bmut = 1.0f; + this->m_channel2 = 0; + this->m_channel3 = 2; + if (this->m_settings->unspill == 0) { + this->m_settings->uspillr = 0.0f; + this->m_settings->uspillg = 1.0f; + this->m_settings->uspillb = 0.0f; + } + } + else { + this->m_rmut = 1.0f; + this->m_gmut = 1.0f; + this->m_bmut = -1.0f; - this->m_channel2 = 0; - this->m_channel3 = 1; - if (this->m_settings->unspill == 0) { - this->m_settings->uspillr = 0.0f; - this->m_settings->uspillg = 0.0f; - this->m_settings->uspillb = 1.0f; - } - } + this->m_channel2 = 0; + this->m_channel3 = 1; + if (this->m_settings->unspill == 0) { + this->m_settings->uspillr = 0.0f; + this->m_settings->uspillg = 0.0f; + this->m_settings->uspillb = 1.0f; + } + } } void ColorSpillOperation::deinitExecution() { - this->m_inputImageReader = NULL; - this->m_inputFacReader = NULL; + this->m_inputImageReader = NULL; + this->m_inputFacReader = NULL; } -void ColorSpillOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ColorSpillOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float fac[4]; - float input[4]; - this->m_inputFacReader->readSampled(fac, x, y, sampler); - this->m_inputImageReader->readSampled(input, x, y, sampler); - float rfac = min(1.0f, fac[0]); - float map; + float fac[4]; + float input[4]; + this->m_inputFacReader->readSampled(fac, x, y, sampler); + this->m_inputImageReader->readSampled(input, x, y, sampler); + float rfac = min(1.0f, fac[0]); + float map; - switch (this->m_spillMethod) { - case 0: /* simple */ - map = rfac * (input[this->m_spillChannel] - (this->m_settings->limscale * input[this->m_settings->limchan])); - break; - default: /* average */ - map = rfac * (input[this->m_spillChannel] - (this->m_settings->limscale * AVG(input[this->m_channel2], input[this->m_channel3]))); - break; - } + switch (this->m_spillMethod) { + case 0: /* simple */ + map = rfac * (input[this->m_spillChannel] - + (this->m_settings->limscale * input[this->m_settings->limchan])); + break; + default: /* average */ + map = rfac * + (input[this->m_spillChannel] - + (this->m_settings->limscale * AVG(input[this->m_channel2], input[this->m_channel3]))); + break; + } - if (map > 0.0f) { - output[0] = input[0] + this->m_rmut * (this->m_settings->uspillr * map); - output[1] = input[1] + this->m_gmut * (this->m_settings->uspillg * map); - output[2] = input[2] + this->m_bmut * (this->m_settings->uspillb * map); - output[3] = input[3]; - } - else { - copy_v4_v4(output, input); - } + if (map > 0.0f) { + output[0] = input[0] + this->m_rmut * (this->m_settings->uspillr * map); + output[1] = input[1] + this->m_gmut * (this->m_settings->uspillg * map); + output[2] = input[2] + this->m_bmut * (this->m_settings->uspillb * map); + output[3] = input[3]; + } + else { + copy_v4_v4(output, input); + } } diff --git a/source/blender/compositor/operations/COM_ColorSpillOperation.h b/source/blender/compositor/operations/COM_ColorSpillOperation.h index 6682abdc4ec..73f4f5b045d 100644 --- a/source/blender/compositor/operations/COM_ColorSpillOperation.h +++ b/source/blender/compositor/operations/COM_ColorSpillOperation.h @@ -25,34 +25,44 @@ * it assumes we are in sRGB color space. */ class ColorSpillOperation : public NodeOperation { -protected: - NodeColorspill *m_settings; - SocketReader *m_inputImageReader; - SocketReader *m_inputFacReader; - int m_spillChannel; - int m_spillMethod; - int m_channel2; - int m_channel3; - float m_rmut, m_gmut, m_bmut; -public: - /** - * Default constructor - */ - ColorSpillOperation(); - - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - - void initExecution(); - void deinitExecution(); - - void setSettings(NodeColorspill *nodeColorSpill) { this->m_settings = nodeColorSpill; } - void setSpillChannel(int channel) { this->m_spillChannel = channel; } - void setSpillMethod(int method) { this->m_spillMethod = method; } - - float calculateMapValue(float fac, float *input); + protected: + NodeColorspill *m_settings; + SocketReader *m_inputImageReader; + SocketReader *m_inputFacReader; + int m_spillChannel; + int m_spillMethod; + int m_channel2; + int m_channel3; + float m_rmut, m_gmut, m_bmut; + + public: + /** + * Default constructor + */ + ColorSpillOperation(); + + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + + void initExecution(); + void deinitExecution(); + + void setSettings(NodeColorspill *nodeColorSpill) + { + this->m_settings = nodeColorSpill; + } + void setSpillChannel(int channel) + { + this->m_spillChannel = channel; + } + void setSpillMethod(int method) + { + this->m_spillMethod = method; + } + + float calculateMapValue(float fac, float *input); }; #endif diff --git a/source/blender/compositor/operations/COM_CompositorOperation.cpp b/source/blender/compositor/operations/COM_CompositorOperation.cpp index 7d124e41a45..018b1662e0f 100644 --- a/source/blender/compositor/operations/COM_CompositorOperation.cpp +++ b/source/blender/compositor/operations/COM_CompositorOperation.cpp @@ -22,215 +22,220 @@ #include "BKE_image.h" extern "C" { -# include "BLI_threads.h" -# include "RE_pipeline.h" -# include "RE_shader_ext.h" -# include "RE_render_ext.h" -# include "MEM_guardedalloc.h" -# include "render_types.h" +#include "BLI_threads.h" +#include "RE_pipeline.h" +#include "RE_shader_ext.h" +#include "RE_render_ext.h" +#include "MEM_guardedalloc.h" +#include "render_types.h" } #include "PIL_time.h" - CompositorOperation::CompositorOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_VALUE); - - this->setRenderData(NULL); - this->m_outputBuffer = NULL; - this->m_depthBuffer = NULL; - this->m_imageInput = NULL; - this->m_alphaInput = NULL; - this->m_depthInput = NULL; - - this->m_useAlphaInput = false; - this->m_active = false; - - this->m_scene = NULL; - this->m_sceneName[0] = '\0'; - this->m_viewName = NULL; + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + + this->setRenderData(NULL); + this->m_outputBuffer = NULL; + this->m_depthBuffer = NULL; + this->m_imageInput = NULL; + this->m_alphaInput = NULL; + this->m_depthInput = NULL; + + this->m_useAlphaInput = false; + this->m_active = false; + + this->m_scene = NULL; + this->m_sceneName[0] = '\0'; + this->m_viewName = NULL; } void CompositorOperation::initExecution() { - if (!this->m_active) - return; - - // When initializing the tree during initial load the width and height can be zero. - this->m_imageInput = getInputSocketReader(0); - this->m_alphaInput = getInputSocketReader(1); - this->m_depthInput = getInputSocketReader(2); - if (this->getWidth() * this->getHeight() != 0) { - this->m_outputBuffer = (float *) MEM_callocN(this->getWidth() * this->getHeight() * 4 * sizeof(float), "CompositorOperation"); - } - if (this->m_depthInput != NULL) { - this->m_depthBuffer = (float *) MEM_callocN(this->getWidth() * this->getHeight() * sizeof(float), "CompositorOperation"); - } + if (!this->m_active) + return; + + // When initializing the tree during initial load the width and height can be zero. + this->m_imageInput = getInputSocketReader(0); + this->m_alphaInput = getInputSocketReader(1); + this->m_depthInput = getInputSocketReader(2); + if (this->getWidth() * this->getHeight() != 0) { + this->m_outputBuffer = (float *)MEM_callocN( + this->getWidth() * this->getHeight() * 4 * sizeof(float), "CompositorOperation"); + } + if (this->m_depthInput != NULL) { + this->m_depthBuffer = (float *)MEM_callocN( + this->getWidth() * this->getHeight() * sizeof(float), "CompositorOperation"); + } } void CompositorOperation::deinitExecution() { - if (!this->m_active) - return; - - if (!isBreaked()) { - Render *re = RE_GetSceneRender(this->m_scene); - RenderResult *rr = RE_AcquireResultWrite(re); - - if (rr) { - RenderView *rv = RE_RenderViewGetByName(rr, this->m_viewName); - - if (rv->rectf != NULL) { - MEM_freeN(rv->rectf); - } - rv->rectf = this->m_outputBuffer; - if (rv->rectz != NULL) { - MEM_freeN(rv->rectz); - } - rv->rectz = this->m_depthBuffer; - rr->have_combined = true; - } - else { - if (this->m_outputBuffer) { - MEM_freeN(this->m_outputBuffer); - } - if (this->m_depthBuffer) { - MEM_freeN(this->m_depthBuffer); - } - } - - if (re) { - RE_ReleaseResult(re); - re = NULL; - } - - BLI_thread_lock(LOCK_DRAW_IMAGE); - BKE_image_signal(G.main, BKE_image_verify_viewer(G.main, IMA_TYPE_R_RESULT, "Render Result"), NULL, IMA_SIGNAL_FREE); - BLI_thread_unlock(LOCK_DRAW_IMAGE); - } - else { - if (this->m_outputBuffer) { - MEM_freeN(this->m_outputBuffer); - } - if (this->m_depthBuffer) { - MEM_freeN(this->m_depthBuffer); - } - } - - this->m_outputBuffer = NULL; - this->m_depthBuffer = NULL; - this->m_imageInput = NULL; - this->m_alphaInput = NULL; - this->m_depthInput = NULL; + if (!this->m_active) + return; + + if (!isBreaked()) { + Render *re = RE_GetSceneRender(this->m_scene); + RenderResult *rr = RE_AcquireResultWrite(re); + + if (rr) { + RenderView *rv = RE_RenderViewGetByName(rr, this->m_viewName); + + if (rv->rectf != NULL) { + MEM_freeN(rv->rectf); + } + rv->rectf = this->m_outputBuffer; + if (rv->rectz != NULL) { + MEM_freeN(rv->rectz); + } + rv->rectz = this->m_depthBuffer; + rr->have_combined = true; + } + else { + if (this->m_outputBuffer) { + MEM_freeN(this->m_outputBuffer); + } + if (this->m_depthBuffer) { + MEM_freeN(this->m_depthBuffer); + } + } + + if (re) { + RE_ReleaseResult(re); + re = NULL; + } + + BLI_thread_lock(LOCK_DRAW_IMAGE); + BKE_image_signal(G.main, + BKE_image_verify_viewer(G.main, IMA_TYPE_R_RESULT, "Render Result"), + NULL, + IMA_SIGNAL_FREE); + BLI_thread_unlock(LOCK_DRAW_IMAGE); + } + else { + if (this->m_outputBuffer) { + MEM_freeN(this->m_outputBuffer); + } + if (this->m_depthBuffer) { + MEM_freeN(this->m_depthBuffer); + } + } + + this->m_outputBuffer = NULL; + this->m_depthBuffer = NULL; + this->m_imageInput = NULL; + this->m_alphaInput = NULL; + this->m_depthInput = NULL; } - void CompositorOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/) { - float color[8]; // 7 is enough - float *buffer = this->m_outputBuffer; - float *zbuffer = this->m_depthBuffer; - - if (!buffer) return; - int x1 = rect->xmin; - int y1 = rect->ymin; - int x2 = rect->xmax; - int y2 = rect->ymax; - int offset = (y1 * this->getWidth() + x1); - int add = (this->getWidth() - (x2 - x1)); - int offset4 = offset * COM_NUM_CHANNELS_COLOR; - int x; - int y; - bool breaked = false; - int dx = 0, dy = 0; + float color[8]; // 7 is enough + float *buffer = this->m_outputBuffer; + float *zbuffer = this->m_depthBuffer; + + if (!buffer) + return; + int x1 = rect->xmin; + int y1 = rect->ymin; + int x2 = rect->xmax; + int y2 = rect->ymax; + int offset = (y1 * this->getWidth() + x1); + int add = (this->getWidth() - (x2 - x1)); + int offset4 = offset * COM_NUM_CHANNELS_COLOR; + int x; + int y; + bool breaked = false; + int dx = 0, dy = 0; #if 0 - const RenderData *rd = this->m_rd; - - if (rd->mode & R_BORDER && rd->mode & R_CROP) { - /** - * When using cropped render result, need to re-position area of interest, - * so it'll natch bounds of render border within frame. By default, canvas - * will be centered between full frame and cropped frame, so we use such - * scheme to map cropped coordinates to full-frame coordinates - * - * ^ Y - * | Width - * +------------------------------------------------+ - * | | - * | | - * | Centered canvas, we map coordinate from it | - * | +------------------+ | - * | | | | H - * | | | | e - * | +------------------+ . Center | | i - * | | | | | | g - * | | | | | | h - * | |....dx.... +------|-----------+ | t - * | | . dy | | - * | +------------------+ | - * | Render border, we map coordinates to it | - * | | X - * +------------------------------------------------+----> - * Full frame - */ - - int full_width = rd->xsch * rd->size / 100; - int full_height = rd->ysch * rd->size / 100; - - dx = rd->border.xmin * full_width - (full_width - this->getWidth()) / 2.0f; - dy = rd->border.ymin * full_height - (full_height - this->getHeight()) / 2.0f; - } + const RenderData *rd = this->m_rd; + + if (rd->mode & R_BORDER && rd->mode & R_CROP) { + /** + * When using cropped render result, need to re-position area of interest, + * so it'll natch bounds of render border within frame. By default, canvas + * will be centered between full frame and cropped frame, so we use such + * scheme to map cropped coordinates to full-frame coordinates + * + * ^ Y + * | Width + * +------------------------------------------------+ + * | | + * | | + * | Centered canvas, we map coordinate from it | + * | +------------------+ | + * | | | | H + * | | | | e + * | +------------------+ . Center | | i + * | | | | | | g + * | | | | | | h + * | |....dx.... +------|-----------+ | t + * | | . dy | | + * | +------------------+ | + * | Render border, we map coordinates to it | + * | | X + * +------------------------------------------------+----> + * Full frame + */ + + int full_width = rd->xsch * rd->size / 100; + int full_height = rd->ysch * rd->size / 100; + + dx = rd->border.xmin * full_width - (full_width - this->getWidth()) / 2.0f; + dy = rd->border.ymin * full_height - (full_height - this->getHeight()) / 2.0f; + } #endif - for (y = y1; y < y2 && (!breaked); y++) { - for (x = x1; x < x2 && (!breaked); x++) { - int input_x = x + dx, input_y = y + dy; - - this->m_imageInput->readSampled(color, input_x, input_y, COM_PS_NEAREST); - if (this->m_useAlphaInput) { - this->m_alphaInput->readSampled(&(color[3]), input_x, input_y, COM_PS_NEAREST); - } - - copy_v4_v4(buffer + offset4, color); - - this->m_depthInput->readSampled(color, input_x, input_y, COM_PS_NEAREST); - zbuffer[offset] = color[0]; - offset4 += COM_NUM_CHANNELS_COLOR; - offset++; - if (isBreaked()) { - breaked = true; - } - } - offset += add; - offset4 += add * COM_NUM_CHANNELS_COLOR; - } + for (y = y1; y < y2 && (!breaked); y++) { + for (x = x1; x < x2 && (!breaked); x++) { + int input_x = x + dx, input_y = y + dy; + + this->m_imageInput->readSampled(color, input_x, input_y, COM_PS_NEAREST); + if (this->m_useAlphaInput) { + this->m_alphaInput->readSampled(&(color[3]), input_x, input_y, COM_PS_NEAREST); + } + + copy_v4_v4(buffer + offset4, color); + + this->m_depthInput->readSampled(color, input_x, input_y, COM_PS_NEAREST); + zbuffer[offset] = color[0]; + offset4 += COM_NUM_CHANNELS_COLOR; + offset++; + if (isBreaked()) { + breaked = true; + } + } + offset += add; + offset4 += add * COM_NUM_CHANNELS_COLOR; + } } -void CompositorOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +void CompositorOperation::determineResolution(unsigned int resolution[2], + unsigned int preferredResolution[2]) { - int width = this->m_rd->xsch * this->m_rd->size / 100; - int height = this->m_rd->ysch * this->m_rd->size / 100; - - // check actual render resolution with cropping it may differ with cropped border.rendering - // FIX for: [31777] Border Crop gives black (easy) - Render *re = RE_GetSceneRender(this->m_scene); - if (re) { - RenderResult *rr = RE_AcquireResultRead(re); - if (rr) { - width = rr->rectx; - height = rr->recty; - } - RE_ReleaseResult(re); - } - - preferredResolution[0] = width; - preferredResolution[1] = height; - - NodeOperation::determineResolution(resolution, preferredResolution); - - resolution[0] = width; - resolution[1] = height; + int width = this->m_rd->xsch * this->m_rd->size / 100; + int height = this->m_rd->ysch * this->m_rd->size / 100; + + // check actual render resolution with cropping it may differ with cropped border.rendering + // FIX for: [31777] Border Crop gives black (easy) + Render *re = RE_GetSceneRender(this->m_scene); + if (re) { + RenderResult *rr = RE_AcquireResultRead(re); + if (rr) { + width = rr->rectx; + height = rr->recty; + } + RE_ReleaseResult(re); + } + + preferredResolution[0] = width; + preferredResolution[1] = height; + + NodeOperation::determineResolution(resolution, preferredResolution); + + resolution[0] = width; + resolution[1] = height; } diff --git a/source/blender/compositor/operations/COM_CompositorOperation.h b/source/blender/compositor/operations/COM_CompositorOperation.h index 3d195bd3c6c..d24fc49059c 100644 --- a/source/blender/compositor/operations/COM_CompositorOperation.h +++ b/source/blender/compositor/operations/COM_CompositorOperation.h @@ -28,71 +28,99 @@ struct Scene; * \brief Compositor output operation */ class CompositorOperation : public NodeOperation { -private: - const struct Scene *m_scene; - /** - * \brief Scene name, used for getting the render output, includes 'SC' prefix. - */ - char m_sceneName[MAX_ID_NAME]; + private: + const struct Scene *m_scene; + /** + * \brief Scene name, used for getting the render output, includes 'SC' prefix. + */ + char m_sceneName[MAX_ID_NAME]; - /** - * \brief local reference to the scene - */ - const RenderData *m_rd; + /** + * \brief local reference to the scene + */ + const RenderData *m_rd; - /** - * \brief reference to the output float buffer - */ - float *m_outputBuffer; + /** + * \brief reference to the output float buffer + */ + float *m_outputBuffer; - /** - * \brief reference to the output depth float buffer - */ - float *m_depthBuffer; + /** + * \brief reference to the output depth float buffer + */ + float *m_depthBuffer; - /** - * \brief local reference to the input image operation - */ - SocketReader *m_imageInput; + /** + * \brief local reference to the input image operation + */ + SocketReader *m_imageInput; - /** - * \brief local reference to the input alpha operation - */ - SocketReader *m_alphaInput; + /** + * \brief local reference to the input alpha operation + */ + SocketReader *m_alphaInput; - /** - * \brief local reference to the depth operation - */ - SocketReader *m_depthInput; + /** + * \brief local reference to the depth operation + */ + SocketReader *m_depthInput; - /** - * \brief Ignore any alpha input - */ - bool m_useAlphaInput; + /** + * \brief Ignore any alpha input + */ + bool m_useAlphaInput; - /** - * \brief operation is active for calculating final compo result - */ - bool m_active; + /** + * \brief operation is active for calculating final compo result + */ + bool m_active; - /** - * \brief View name, used for multiview - */ - const char *m_viewName; -public: - CompositorOperation(); - bool isActiveCompositorOutput() const { return this->m_active; } - void executeRegion(rcti *rect, unsigned int tileNumber); - void setScene(const struct Scene *scene) { m_scene = scene; } - void setSceneName(const char *sceneName) { BLI_strncpy(this->m_sceneName, sceneName, sizeof(this->m_sceneName)); } - void setViewName(const char *viewName) { this->m_viewName = viewName; } - void setRenderData(const RenderData *rd) { this->m_rd = rd; } - bool isOutputOperation(bool /*rendering*/) const { return this->isActiveCompositorOutput(); } - void initExecution(); - void deinitExecution(); - CompositorPriority getRenderPriority() const { return COM_PRIORITY_MEDIUM; } - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); - void setUseAlphaInput(bool value) { this->m_useAlphaInput = value; } - void setActive(bool active) { this->m_active = active; } + /** + * \brief View name, used for multiview + */ + const char *m_viewName; + + public: + CompositorOperation(); + bool isActiveCompositorOutput() const + { + return this->m_active; + } + void executeRegion(rcti *rect, unsigned int tileNumber); + void setScene(const struct Scene *scene) + { + m_scene = scene; + } + void setSceneName(const char *sceneName) + { + BLI_strncpy(this->m_sceneName, sceneName, sizeof(this->m_sceneName)); + } + void setViewName(const char *viewName) + { + this->m_viewName = viewName; + } + void setRenderData(const RenderData *rd) + { + this->m_rd = rd; + } + bool isOutputOperation(bool /*rendering*/) const + { + return this->isActiveCompositorOutput(); + } + void initExecution(); + void deinitExecution(); + CompositorPriority getRenderPriority() const + { + return COM_PRIORITY_MEDIUM; + } + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); + void setUseAlphaInput(bool value) + { + this->m_useAlphaInput = value; + } + void setActive(bool active) + { + this->m_active = active; + } }; #endif diff --git a/source/blender/compositor/operations/COM_ConvertColorProfileOperation.cpp b/source/blender/compositor/operations/COM_ConvertColorProfileOperation.cpp index 3b04bc41367..59a605a77c9 100644 --- a/source/blender/compositor/operations/COM_ConvertColorProfileOperation.cpp +++ b/source/blender/compositor/operations/COM_ConvertColorProfileOperation.cpp @@ -19,29 +19,33 @@ #include "COM_ConvertColorProfileOperation.h" extern "C" { -# include "IMB_imbuf.h" +#include "IMB_imbuf.h" } ConvertColorProfileOperation::ConvertColorProfileOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - this->m_inputOperation = NULL; - this->m_predivided = false; + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); + this->m_inputOperation = NULL; + this->m_predivided = false; } void ConvertColorProfileOperation::initExecution() { - this->m_inputOperation = this->getInputSocketReader(0); + this->m_inputOperation = this->getInputSocketReader(0); } -void ConvertColorProfileOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ConvertColorProfileOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float color[4]; - this->m_inputOperation->readSampled(color, x, y, sampler); - IMB_buffer_float_from_float(output, color, 4, this->m_toProfile, this->m_fromProfile, this->m_predivided, 1, 1, 0, 0); + float color[4]; + this->m_inputOperation->readSampled(color, x, y, sampler); + IMB_buffer_float_from_float( + output, color, 4, this->m_toProfile, this->m_fromProfile, this->m_predivided, 1, 1, 0, 0); } void ConvertColorProfileOperation::deinitExecution() { - this->m_inputOperation = NULL; + this->m_inputOperation = NULL; } diff --git a/source/blender/compositor/operations/COM_ConvertColorProfileOperation.h b/source/blender/compositor/operations/COM_ConvertColorProfileOperation.h index 86e6971c528..7cc39a47dd0 100644 --- a/source/blender/compositor/operations/COM_ConvertColorProfileOperation.h +++ b/source/blender/compositor/operations/COM_ConvertColorProfileOperation.h @@ -20,55 +20,64 @@ #define __COM_CONVERTCOLORPROFILEOPERATION_H__ #include "COM_NodeOperation.h" - /** * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ class ConvertColorProfileOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputOperation; + private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputOperation; + + /** + * \brief color profile where to convert from + */ + int m_fromProfile; - /** - * \brief color profile where to convert from - */ - int m_fromProfile; + /** + * \brief color profile where to convert to + */ + int m_toProfile; - /** - * \brief color profile where to convert to - */ - int m_toProfile; + /** + * \brief is color predivided + */ + bool m_predivided; - /** - * \brief is color predivided - */ - bool m_predivided; -public: - /** - * Default constructor - */ - ConvertColorProfileOperation(); + public: + /** + * Default constructor + */ + ConvertColorProfileOperation(); - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - /** - * Initialize the execution - */ - void initExecution(); + /** + * Initialize the execution + */ + void initExecution(); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Deinitialize the execution + */ + void deinitExecution(); - void setFromColorProfile(int colorProfile) { this->m_fromProfile = colorProfile; } - void setToColorProfile(int colorProfile) { this->m_toProfile = colorProfile; } - void setPredivided(bool predivided) { this->m_predivided = predivided; } + void setFromColorProfile(int colorProfile) + { + this->m_fromProfile = colorProfile; + } + void setToColorProfile(int colorProfile) + { + this->m_toProfile = colorProfile; + } + void setPredivided(bool predivided) + { + this->m_predivided = predivided; + } }; #endif diff --git a/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cpp b/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cpp index c0c9c413c8b..7b63d3ef3cb 100644 --- a/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cpp +++ b/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cpp @@ -23,81 +23,91 @@ ConvertDepthToRadiusOperation::ConvertDepthToRadiusOperation() : NodeOperation() { - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_VALUE); - this->m_inputOperation = NULL; - this->m_fStop = 128.0f; - this->m_cameraObject = NULL; - this->m_maxRadius = 32.0f; - this->m_blurPostOperation = NULL; + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_VALUE); + this->m_inputOperation = NULL; + this->m_fStop = 128.0f; + this->m_cameraObject = NULL; + this->m_maxRadius = 32.0f; + this->m_blurPostOperation = NULL; } float ConvertDepthToRadiusOperation::determineFocalDistance() { - if (this->m_cameraObject && this->m_cameraObject->type == OB_CAMERA) { - Camera *camera = (Camera *)this->m_cameraObject->data; - this->m_cam_lens = camera->lens; - return BKE_camera_object_dof_distance(this->m_cameraObject); - } - else { - return 10.0f; - } + if (this->m_cameraObject && this->m_cameraObject->type == OB_CAMERA) { + Camera *camera = (Camera *)this->m_cameraObject->data; + this->m_cam_lens = camera->lens; + return BKE_camera_object_dof_distance(this->m_cameraObject); + } + else { + return 10.0f; + } } void ConvertDepthToRadiusOperation::initExecution() { - float cam_sensor = DEFAULT_SENSOR_WIDTH; - Camera *camera = NULL; + float cam_sensor = DEFAULT_SENSOR_WIDTH; + Camera *camera = NULL; - if (this->m_cameraObject && this->m_cameraObject->type == OB_CAMERA) { - camera = (Camera *)this->m_cameraObject->data; - cam_sensor = BKE_camera_sensor_size(camera->sensor_fit, camera->sensor_x, camera->sensor_y); - } + if (this->m_cameraObject && this->m_cameraObject->type == OB_CAMERA) { + camera = (Camera *)this->m_cameraObject->data; + cam_sensor = BKE_camera_sensor_size(camera->sensor_fit, camera->sensor_x, camera->sensor_y); + } - this->m_inputOperation = this->getInputSocketReader(0); - float focalDistance = determineFocalDistance(); - if (focalDistance == 0.0f) focalDistance = 1e10f; /* if the dof is 0.0 then set it to be far away */ - this->m_inverseFocalDistance = 1.0f / focalDistance; - this->m_aspect = (this->getWidth() > this->getHeight()) ? (this->getHeight() / (float)this->getWidth()) : (this->getWidth() / (float)this->getHeight()); - this->m_aperture = 0.5f * (this->m_cam_lens / (this->m_aspect * cam_sensor)) / this->m_fStop; - const float minsz = min(getWidth(), getHeight()); - this->m_dof_sp = minsz / ((cam_sensor / 2.0f) / this->m_cam_lens); // <- == aspect * min(img->x, img->y) / tan(0.5f * fov); + this->m_inputOperation = this->getInputSocketReader(0); + float focalDistance = determineFocalDistance(); + if (focalDistance == 0.0f) + focalDistance = 1e10f; /* if the dof is 0.0 then set it to be far away */ + this->m_inverseFocalDistance = 1.0f / focalDistance; + this->m_aspect = (this->getWidth() > this->getHeight()) ? + (this->getHeight() / (float)this->getWidth()) : + (this->getWidth() / (float)this->getHeight()); + this->m_aperture = 0.5f * (this->m_cam_lens / (this->m_aspect * cam_sensor)) / this->m_fStop; + const float minsz = min(getWidth(), getHeight()); + this->m_dof_sp = minsz / + ((cam_sensor / 2.0f) / + this->m_cam_lens); // <- == aspect * min(img->x, img->y) / tan(0.5f * fov); - if (this->m_blurPostOperation) { - m_blurPostOperation->setSigma(min(m_aperture * 128.0f, this->m_maxRadius)); - } + if (this->m_blurPostOperation) { + m_blurPostOperation->setSigma(min(m_aperture * 128.0f, this->m_maxRadius)); + } } -void ConvertDepthToRadiusOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ConvertDepthToRadiusOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue[4]; - float z; - float radius; - this->m_inputOperation->readSampled(inputValue, x, y, sampler); - z = inputValue[0]; - if (z != 0.0f) { - float iZ = (1.0f / z); + float inputValue[4]; + float z; + float radius; + this->m_inputOperation->readSampled(inputValue, x, y, sampler); + z = inputValue[0]; + if (z != 0.0f) { + float iZ = (1.0f / z); - // bug #6656 part 2b, do not rescale + // bug #6656 part 2b, do not rescale #if 0 - bcrad = 0.5f * fabs(aperture * (dof_sp * (cam_invfdist - iZ) - 1.0f)); - // scale crad back to original maximum and blend - crad->rect[px] = bcrad + wts->rect[px] * (scf * crad->rect[px] - bcrad); + bcrad = 0.5f * fabs(aperture * (dof_sp * (cam_invfdist - iZ) - 1.0f)); + // scale crad back to original maximum and blend + crad->rect[px] = bcrad + wts->rect[px] * (scf * crad->rect[px] - bcrad); #endif - radius = 0.5f * fabsf(this->m_aperture * (this->m_dof_sp * (this->m_inverseFocalDistance - iZ) - 1.0f)); - // 'bug' #6615, limit minimum radius to 1 pixel, not really a solution, but somewhat mitigates the problem - if (radius < 0.0f) radius = 0.0f; - if (radius > this->m_maxRadius) { - radius = this->m_maxRadius; - } - output[0] = radius; - } - else { - output[0] = 0.0f; - } + radius = 0.5f * fabsf(this->m_aperture * + (this->m_dof_sp * (this->m_inverseFocalDistance - iZ) - 1.0f)); + // 'bug' #6615, limit minimum radius to 1 pixel, not really a solution, but somewhat mitigates the problem + if (radius < 0.0f) + radius = 0.0f; + if (radius > this->m_maxRadius) { + radius = this->m_maxRadius; + } + output[0] = radius; + } + else { + output[0] = 0.0f; + } } void ConvertDepthToRadiusOperation::deinitExecution() { - this->m_inputOperation = NULL; + this->m_inputOperation = NULL; } diff --git a/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.h b/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.h index 2611c082a05..f375d6efb8f 100644 --- a/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.h +++ b/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.h @@ -26,47 +26,59 @@ * it assumes we are in sRGB color space. */ class ConvertDepthToRadiusOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputOperation; - float m_fStop; - float m_aspect; - float m_maxRadius; - float m_inverseFocalDistance; - float m_aperture; - float m_cam_lens; - float m_dof_sp; - Object *m_cameraObject; + private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputOperation; + float m_fStop; + float m_aspect; + float m_maxRadius; + float m_inverseFocalDistance; + float m_aperture; + float m_cam_lens; + float m_dof_sp; + Object *m_cameraObject; - FastGaussianBlurValueOperation *m_blurPostOperation; -public: - /** - * Default constructor - */ - ConvertDepthToRadiusOperation(); + FastGaussianBlurValueOperation *m_blurPostOperation; - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + /** + * Default constructor + */ + ConvertDepthToRadiusOperation(); - /** - * Initialize the execution - */ - void initExecution(); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Initialize the execution + */ + void initExecution(); - void setfStop(float fStop) { this->m_fStop = fStop; } - void setMaxRadius(float maxRadius) { this->m_maxRadius = maxRadius; } - void setCameraObject(Object *camera) { this->m_cameraObject = camera; } - float determineFocalDistance(); - void setPostBlur(FastGaussianBlurValueOperation *operation) { this->m_blurPostOperation = operation; } + /** + * Deinitialize the execution + */ + void deinitExecution(); + void setfStop(float fStop) + { + this->m_fStop = fStop; + } + void setMaxRadius(float maxRadius) + { + this->m_maxRadius = maxRadius; + } + void setCameraObject(Object *camera) + { + this->m_cameraObject = camera; + } + float determineFocalDistance(); + void setPostBlur(FastGaussianBlurValueOperation *operation) + { + this->m_blurPostOperation = operation; + } }; #endif diff --git a/source/blender/compositor/operations/COM_ConvertOperation.cpp b/source/blender/compositor/operations/COM_ConvertOperation.cpp index 5c32ac7e48e..6caccb89046 100644 --- a/source/blender/compositor/operations/COM_ConvertOperation.cpp +++ b/source/blender/compositor/operations/COM_ConvertOperation.cpp @@ -24,406 +24,459 @@ extern "C" { ConvertBaseOperation::ConvertBaseOperation() { - this->m_inputOperation = NULL; + this->m_inputOperation = NULL; } void ConvertBaseOperation::initExecution() { - this->m_inputOperation = this->getInputSocketReader(0); + this->m_inputOperation = this->getInputSocketReader(0); } void ConvertBaseOperation::deinitExecution() { - this->m_inputOperation = NULL; + this->m_inputOperation = NULL; } - /* ******** Value to Color ******** */ ConvertValueToColorOperation::ConvertValueToColorOperation() : ConvertBaseOperation() { - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_COLOR); } -void ConvertValueToColorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ConvertValueToColorOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float value; - this->m_inputOperation->readSampled(&value, x, y, sampler); - output[0] = output[1] = output[2] = value; - output[3] = 1.0f; + float value; + this->m_inputOperation->readSampled(&value, x, y, sampler); + output[0] = output[1] = output[2] = value; + output[3] = 1.0f; } - /* ******** Color to Value ******** */ ConvertColorToValueOperation::ConvertColorToValueOperation() : ConvertBaseOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_VALUE); } -void ConvertColorToValueOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ConvertColorToValueOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor[4]; - this->m_inputOperation->readSampled(inputColor, x, y, sampler); - output[0] = (inputColor[0] + inputColor[1] + inputColor[2]) / 3.0f; + float inputColor[4]; + this->m_inputOperation->readSampled(inputColor, x, y, sampler); + output[0] = (inputColor[0] + inputColor[1] + inputColor[2]) / 3.0f; } - /* ******** Color to BW ******** */ ConvertColorToBWOperation::ConvertColorToBWOperation() : ConvertBaseOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_VALUE); } -void ConvertColorToBWOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ConvertColorToBWOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor[4]; - this->m_inputOperation->readSampled(inputColor, x, y, sampler); - output[0] = IMB_colormanagement_get_luminance(inputColor); + float inputColor[4]; + this->m_inputOperation->readSampled(inputColor, x, y, sampler); + output[0] = IMB_colormanagement_get_luminance(inputColor); } - /* ******** Color to Vector ******** */ ConvertColorToVectorOperation::ConvertColorToVectorOperation() : ConvertBaseOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_VECTOR); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_VECTOR); } -void ConvertColorToVectorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ConvertColorToVectorOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float color[4]; - this->m_inputOperation->readSampled(color, x, y, sampler); - copy_v3_v3(output, color);} - + float color[4]; + this->m_inputOperation->readSampled(color, x, y, sampler); + copy_v3_v3(output, color); +} /* ******** Value to Vector ******** */ ConvertValueToVectorOperation::ConvertValueToVectorOperation() : ConvertBaseOperation() { - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_VECTOR); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_VECTOR); } -void ConvertValueToVectorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ConvertValueToVectorOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float value; - this->m_inputOperation->readSampled(&value, x, y, sampler); - output[0] = output[1] = output[2] = value; + float value; + this->m_inputOperation->readSampled(&value, x, y, sampler); + output[0] = output[1] = output[2] = value; } - /* ******** Vector to Color ******** */ ConvertVectorToColorOperation::ConvertVectorToColorOperation() : ConvertBaseOperation() { - this->addInputSocket(COM_DT_VECTOR); - this->addOutputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VECTOR); + this->addOutputSocket(COM_DT_COLOR); } -void ConvertVectorToColorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ConvertVectorToColorOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - this->m_inputOperation->readSampled(output, x, y, sampler); - output[3] = 1.0f; + this->m_inputOperation->readSampled(output, x, y, sampler); + output[3] = 1.0f; } - /* ******** Vector to Value ******** */ ConvertVectorToValueOperation::ConvertVectorToValueOperation() : ConvertBaseOperation() { - this->addInputSocket(COM_DT_VECTOR); - this->addOutputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VECTOR); + this->addOutputSocket(COM_DT_VALUE); } -void ConvertVectorToValueOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ConvertVectorToValueOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float input[4]; - this->m_inputOperation->readSampled(input, x, y, sampler); - output[0] = (input[0] + input[1] + input[2]) / 3.0f; + float input[4]; + this->m_inputOperation->readSampled(input, x, y, sampler); + output[0] = (input[0] + input[1] + input[2]) / 3.0f; } - /* ******** RGB to YCC ******** */ ConvertRGBToYCCOperation::ConvertRGBToYCCOperation() : ConvertBaseOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); } void ConvertRGBToYCCOperation::setMode(int mode) { - switch (mode) { - case 0: - this->m_mode = BLI_YCC_ITU_BT601; - break; - case 2: - this->m_mode = BLI_YCC_JFIF_0_255; - break; - case 1: - default: - this->m_mode = BLI_YCC_ITU_BT709; - break; - } + switch (mode) { + case 0: + this->m_mode = BLI_YCC_ITU_BT601; + break; + case 2: + this->m_mode = BLI_YCC_JFIF_0_255; + break; + case 1: + default: + this->m_mode = BLI_YCC_ITU_BT709; + break; + } } -void ConvertRGBToYCCOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ConvertRGBToYCCOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor[4]; - float color[3]; + float inputColor[4]; + float color[3]; - this->m_inputOperation->readSampled(inputColor, x, y, sampler); - rgb_to_ycc(inputColor[0], inputColor[1], inputColor[2], &color[0], &color[1], &color[2], this->m_mode); + this->m_inputOperation->readSampled(inputColor, x, y, sampler); + rgb_to_ycc( + inputColor[0], inputColor[1], inputColor[2], &color[0], &color[1], &color[2], this->m_mode); - /* divided by 255 to normalize for viewing in */ - /* R,G,B --> Y,Cb,Cr */ - mul_v3_v3fl(output, color, 1.0f / 255.0f); - output[3] = inputColor[3]; + /* divided by 255 to normalize for viewing in */ + /* R,G,B --> Y,Cb,Cr */ + mul_v3_v3fl(output, color, 1.0f / 255.0f); + output[3] = inputColor[3]; } /* ******** YCC to RGB ******** */ ConvertYCCToRGBOperation::ConvertYCCToRGBOperation() : ConvertBaseOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); } void ConvertYCCToRGBOperation::setMode(int mode) { - switch (mode) { - case 0: - this->m_mode = BLI_YCC_ITU_BT601; - break; - case 2: - this->m_mode = BLI_YCC_JFIF_0_255; - break; - case 1: - default: - this->m_mode = BLI_YCC_ITU_BT709; - break; - } + switch (mode) { + case 0: + this->m_mode = BLI_YCC_ITU_BT601; + break; + case 2: + this->m_mode = BLI_YCC_JFIF_0_255; + break; + case 1: + default: + this->m_mode = BLI_YCC_ITU_BT709; + break; + } +} + +void ConvertYCCToRGBOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) +{ + float inputColor[4]; + this->m_inputOperation->readSampled(inputColor, x, y, sampler); + + /* need to un-normalize the data */ + /* R,G,B --> Y,Cb,Cr */ + mul_v3_fl(inputColor, 255.0f); + + ycc_to_rgb(inputColor[0], + inputColor[1], + inputColor[2], + &output[0], + &output[1], + &output[2], + this->m_mode); + output[3] = inputColor[3]; } -void ConvertYCCToRGBOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor[4]; - this->m_inputOperation->readSampled(inputColor, x, y, sampler); - - /* need to un-normalize the data */ - /* R,G,B --> Y,Cb,Cr */ - mul_v3_fl(inputColor, 255.0f); - - ycc_to_rgb(inputColor[0], inputColor[1], inputColor[2], &output[0], &output[1], &output[2], this->m_mode); - output[3] = inputColor[3]; -} - - /* ******** RGB to YUV ******** */ ConvertRGBToYUVOperation::ConvertRGBToYUVOperation() : ConvertBaseOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); } -void ConvertRGBToYUVOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ConvertRGBToYUVOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor[4]; - this->m_inputOperation->readSampled(inputColor, x, y, sampler); - rgb_to_yuv(inputColor[0], inputColor[1], inputColor[2], &output[0], &output[1], &output[2], BLI_YUV_ITU_BT709); - output[3] = inputColor[3]; + float inputColor[4]; + this->m_inputOperation->readSampled(inputColor, x, y, sampler); + rgb_to_yuv(inputColor[0], + inputColor[1], + inputColor[2], + &output[0], + &output[1], + &output[2], + BLI_YUV_ITU_BT709); + output[3] = inputColor[3]; } - /* ******** YUV to RGB ******** */ ConvertYUVToRGBOperation::ConvertYUVToRGBOperation() : ConvertBaseOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); } -void ConvertYUVToRGBOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ConvertYUVToRGBOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor[4]; - this->m_inputOperation->readSampled(inputColor, x, y, sampler); - yuv_to_rgb(inputColor[0], inputColor[1], inputColor[2], &output[0], &output[1], &output[2], BLI_YUV_ITU_BT709); - output[3] = inputColor[3]; + float inputColor[4]; + this->m_inputOperation->readSampled(inputColor, x, y, sampler); + yuv_to_rgb(inputColor[0], + inputColor[1], + inputColor[2], + &output[0], + &output[1], + &output[2], + BLI_YUV_ITU_BT709); + output[3] = inputColor[3]; } - /* ******** RGB to HSV ******** */ ConvertRGBToHSVOperation::ConvertRGBToHSVOperation() : ConvertBaseOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); } -void ConvertRGBToHSVOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ConvertRGBToHSVOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor[4]; - this->m_inputOperation->readSampled(inputColor, x, y, sampler); - rgb_to_hsv_v(inputColor, output); - output[3] = inputColor[3]; + float inputColor[4]; + this->m_inputOperation->readSampled(inputColor, x, y, sampler); + rgb_to_hsv_v(inputColor, output); + output[3] = inputColor[3]; } - /* ******** HSV to RGB ******** */ ConvertHSVToRGBOperation::ConvertHSVToRGBOperation() : ConvertBaseOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); } -void ConvertHSVToRGBOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ConvertHSVToRGBOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor[4]; - this->m_inputOperation->readSampled(inputColor, x, y, sampler); - hsv_to_rgb_v(inputColor, output); - output[0] = max_ff(output[0], 0.0f); - output[1] = max_ff(output[1], 0.0f); - output[2] = max_ff(output[2], 0.0f); - output[3] = inputColor[3]; + float inputColor[4]; + this->m_inputOperation->readSampled(inputColor, x, y, sampler); + hsv_to_rgb_v(inputColor, output); + output[0] = max_ff(output[0], 0.0f); + output[1] = max_ff(output[1], 0.0f); + output[2] = max_ff(output[2], 0.0f); + output[3] = inputColor[3]; } - /* ******** Premul to Straight ******** */ ConvertPremulToStraightOperation::ConvertPremulToStraightOperation() : ConvertBaseOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); } -void ConvertPremulToStraightOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ConvertPremulToStraightOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue[4]; - float alpha; + float inputValue[4]; + float alpha; - this->m_inputOperation->readSampled(inputValue, x, y, sampler); - alpha = inputValue[3]; + this->m_inputOperation->readSampled(inputValue, x, y, sampler); + alpha = inputValue[3]; - if (fabsf(alpha) < 1e-5f) { - zero_v3(output); - } - else { - mul_v3_v3fl(output, inputValue, 1.0f / alpha); - } + if (fabsf(alpha) < 1e-5f) { + zero_v3(output); + } + else { + mul_v3_v3fl(output, inputValue, 1.0f / alpha); + } - /* never touches the alpha */ - output[3] = alpha; + /* never touches the alpha */ + output[3] = alpha; } - /* ******** Straight to Premul ******** */ ConvertStraightToPremulOperation::ConvertStraightToPremulOperation() : ConvertBaseOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); } -void ConvertStraightToPremulOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ConvertStraightToPremulOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue[4]; - float alpha; + float inputValue[4]; + float alpha; - this->m_inputOperation->readSampled(inputValue, x, y, sampler); - alpha = inputValue[3]; + this->m_inputOperation->readSampled(inputValue, x, y, sampler); + alpha = inputValue[3]; - mul_v3_v3fl(output, inputValue, alpha); + mul_v3_v3fl(output, inputValue, alpha); - /* never touches the alpha */ - output[3] = alpha; + /* never touches the alpha */ + output[3] = alpha; } - /* ******** Separate Channels ******** */ SeparateChannelOperation::SeparateChannelOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_VALUE); - this->m_inputOperation = NULL; + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_VALUE); + this->m_inputOperation = NULL; } void SeparateChannelOperation::initExecution() { - this->m_inputOperation = this->getInputSocketReader(0); + this->m_inputOperation = this->getInputSocketReader(0); } void SeparateChannelOperation::deinitExecution() { - this->m_inputOperation = NULL; + this->m_inputOperation = NULL; } - -void SeparateChannelOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void SeparateChannelOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float input[4]; - this->m_inputOperation->readSampled(input, x, y, sampler); - output[0] = input[this->m_channel]; + float input[4]; + this->m_inputOperation->readSampled(input, x, y, sampler); + output[0] = input[this->m_channel]; } - /* ******** Combine Channels ******** */ CombineChannelsOperation::CombineChannelsOperation() : NodeOperation() { - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_COLOR); - this->setResolutionInputSocketIndex(0); - this->m_inputChannel1Operation = NULL; - this->m_inputChannel2Operation = NULL; - this->m_inputChannel3Operation = NULL; - this->m_inputChannel4Operation = NULL; + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_COLOR); + this->setResolutionInputSocketIndex(0); + this->m_inputChannel1Operation = NULL; + this->m_inputChannel2Operation = NULL; + this->m_inputChannel3Operation = NULL; + this->m_inputChannel4Operation = NULL; } void CombineChannelsOperation::initExecution() { - this->m_inputChannel1Operation = this->getInputSocketReader(0); - this->m_inputChannel2Operation = this->getInputSocketReader(1); - this->m_inputChannel3Operation = this->getInputSocketReader(2); - this->m_inputChannel4Operation = this->getInputSocketReader(3); + this->m_inputChannel1Operation = this->getInputSocketReader(0); + this->m_inputChannel2Operation = this->getInputSocketReader(1); + this->m_inputChannel3Operation = this->getInputSocketReader(2); + this->m_inputChannel4Operation = this->getInputSocketReader(3); } void CombineChannelsOperation::deinitExecution() { - this->m_inputChannel1Operation = NULL; - this->m_inputChannel2Operation = NULL; - this->m_inputChannel3Operation = NULL; - this->m_inputChannel4Operation = NULL; -} - - -void CombineChannelsOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) -{ - float input[4]; - if (this->m_inputChannel1Operation) { - this->m_inputChannel1Operation->readSampled(input, x, y, sampler); - output[0] = input[0]; - } - if (this->m_inputChannel2Operation) { - this->m_inputChannel2Operation->readSampled(input, x, y, sampler); - output[1] = input[0]; - } - if (this->m_inputChannel3Operation) { - this->m_inputChannel3Operation->readSampled(input, x, y, sampler); - output[2] = input[0]; - } - if (this->m_inputChannel4Operation) { - this->m_inputChannel4Operation->readSampled(input, x, y, sampler); - output[3] = input[0]; - } + this->m_inputChannel1Operation = NULL; + this->m_inputChannel2Operation = NULL; + this->m_inputChannel3Operation = NULL; + this->m_inputChannel4Operation = NULL; +} + +void CombineChannelsOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) +{ + float input[4]; + if (this->m_inputChannel1Operation) { + this->m_inputChannel1Operation->readSampled(input, x, y, sampler); + output[0] = input[0]; + } + if (this->m_inputChannel2Operation) { + this->m_inputChannel2Operation->readSampled(input, x, y, sampler); + output[1] = input[0]; + } + if (this->m_inputChannel3Operation) { + this->m_inputChannel3Operation->readSampled(input, x, y, sampler); + output[2] = input[0]; + } + if (this->m_inputChannel4Operation) { + this->m_inputChannel4Operation->readSampled(input, x, y, sampler); + output[3] = input[0]; + } } diff --git a/source/blender/compositor/operations/COM_ConvertOperation.h b/source/blender/compositor/operations/COM_ConvertOperation.h index f738879b572..a4cf05372a5 100644 --- a/source/blender/compositor/operations/COM_ConvertOperation.h +++ b/source/blender/compositor/operations/COM_ConvertOperation.h @@ -21,178 +21,167 @@ #include "COM_NodeOperation.h" - class ConvertBaseOperation : public NodeOperation { -protected: - SocketReader *m_inputOperation; + protected: + SocketReader *m_inputOperation; -public: - ConvertBaseOperation(); + public: + ConvertBaseOperation(); - void initExecution(); - void deinitExecution(); + void initExecution(); + void deinitExecution(); }; - class ConvertValueToColorOperation : public ConvertBaseOperation { -public: - ConvertValueToColorOperation(); + public: + ConvertValueToColorOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; - class ConvertColorToValueOperation : public ConvertBaseOperation { -public: - ConvertColorToValueOperation(); + public: + ConvertColorToValueOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; - class ConvertColorToBWOperation : public ConvertBaseOperation { -public: - ConvertColorToBWOperation(); + public: + ConvertColorToBWOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; - class ConvertColorToVectorOperation : public ConvertBaseOperation { -public: - ConvertColorToVectorOperation(); + public: + ConvertColorToVectorOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; - class ConvertValueToVectorOperation : public ConvertBaseOperation { -public: - ConvertValueToVectorOperation(); + public: + ConvertValueToVectorOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; - class ConvertVectorToColorOperation : public ConvertBaseOperation { -public: - ConvertVectorToColorOperation(); + public: + ConvertVectorToColorOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; - class ConvertVectorToValueOperation : public ConvertBaseOperation { -public: - ConvertVectorToValueOperation(); + public: + ConvertVectorToValueOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; - class ConvertRGBToYCCOperation : public ConvertBaseOperation { -private: - /** YCbCr mode (Jpeg, ITU601, ITU709) */ - int m_mode; -public: - ConvertRGBToYCCOperation(); + private: + /** YCbCr mode (Jpeg, ITU601, ITU709) */ + int m_mode; - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + ConvertRGBToYCCOperation(); - /** Set the YCC mode */ - void setMode(int mode); -}; + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + /** Set the YCC mode */ + void setMode(int mode); +}; class ConvertYCCToRGBOperation : public ConvertBaseOperation { -private: - /** YCbCr mode (Jpeg, ITU601, ITU709) */ - int m_mode; -public: - ConvertYCCToRGBOperation(); + private: + /** YCbCr mode (Jpeg, ITU601, ITU709) */ + int m_mode; - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + ConvertYCCToRGBOperation(); - /** Set the YCC mode */ - void setMode(int mode); -}; + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + /** Set the YCC mode */ + void setMode(int mode); +}; class ConvertRGBToYUVOperation : public ConvertBaseOperation { -public: - ConvertRGBToYUVOperation(); + public: + ConvertRGBToYUVOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; - class ConvertYUVToRGBOperation : public ConvertBaseOperation { -public: - ConvertYUVToRGBOperation(); + public: + ConvertYUVToRGBOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; - class ConvertRGBToHSVOperation : public ConvertBaseOperation { -public: - ConvertRGBToHSVOperation(); + public: + ConvertRGBToHSVOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; - class ConvertHSVToRGBOperation : public ConvertBaseOperation { -public: - ConvertHSVToRGBOperation(); + public: + ConvertHSVToRGBOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; - class ConvertPremulToStraightOperation : public ConvertBaseOperation { -public: - ConvertPremulToStraightOperation(); + public: + ConvertPremulToStraightOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; - class ConvertStraightToPremulOperation : public ConvertBaseOperation { -public: - ConvertStraightToPremulOperation(); + public: + ConvertStraightToPremulOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; - class SeparateChannelOperation : public NodeOperation { -private: - SocketReader *m_inputOperation; - int m_channel; -public: - SeparateChannelOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + private: + SocketReader *m_inputOperation; + int m_channel; - void initExecution(); - void deinitExecution(); + public: + SeparateChannelOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - void setChannel(int channel) { this->m_channel = channel; } -}; + void initExecution(); + void deinitExecution(); + void setChannel(int channel) + { + this->m_channel = channel; + } +}; class CombineChannelsOperation : public NodeOperation { -private: - SocketReader *m_inputChannel1Operation; - SocketReader *m_inputChannel2Operation; - SocketReader *m_inputChannel3Operation; - SocketReader *m_inputChannel4Operation; -public: - CombineChannelsOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - - void initExecution(); - void deinitExecution(); + private: + SocketReader *m_inputChannel1Operation; + SocketReader *m_inputChannel2Operation; + SocketReader *m_inputChannel3Operation; + SocketReader *m_inputChannel4Operation; + + public: + CombineChannelsOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + + void initExecution(); + void deinitExecution(); }; #endif diff --git a/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cpp b/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cpp index b79fea5bfd9..1439c7abb45 100644 --- a/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cpp +++ b/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cpp @@ -21,79 +21,79 @@ ConvolutionEdgeFilterOperation::ConvolutionEdgeFilterOperation() : ConvolutionFilterOperation() { - /* pass */ + /* pass */ } void ConvolutionEdgeFilterOperation::executePixel(float output[4], int x, int y, void * /*data*/) { - float in1[4], in2[4], res1[4] = {0.0}, res2[4] = {0.0}; - - int x1 = x - 1; - int x2 = x; - int x3 = x + 1; - int y1 = y - 1; - int y2 = y; - int y3 = y + 1; - CLAMP(x1, 0, getWidth() - 1); - CLAMP(x2, 0, getWidth() - 1); - CLAMP(x3, 0, getWidth() - 1); - CLAMP(y1, 0, getHeight() - 1); - CLAMP(y2, 0, getHeight() - 1); - CLAMP(y3, 0, getHeight() - 1); - - float value[4]; - this->m_inputValueOperation->read(value, x2, y2, NULL); - float mval = 1.0f - value[0]; - - this->m_inputOperation->read(in1, x1, y1, NULL); - madd_v3_v3fl(res1, in1, this->m_filter[0]); - madd_v3_v3fl(res2, in1, this->m_filter[0]); - - this->m_inputOperation->read(in1, x2, y1, NULL); - madd_v3_v3fl(res1, in1, this->m_filter[1]); - madd_v3_v3fl(res2, in1, this->m_filter[3]); - - this->m_inputOperation->read(in1, x3, y1, NULL); - madd_v3_v3fl(res1, in1, this->m_filter[2]); - madd_v3_v3fl(res2, in1, this->m_filter[6]); - - this->m_inputOperation->read(in1, x1, y2, NULL); - madd_v3_v3fl(res1, in1, this->m_filter[3]); - madd_v3_v3fl(res2, in1, this->m_filter[1]); - - this->m_inputOperation->read(in2, x2, y2, NULL); - madd_v3_v3fl(res1, in2, this->m_filter[4]); - madd_v3_v3fl(res2, in2, this->m_filter[4]); - - this->m_inputOperation->read(in1, x3, y2, NULL); - madd_v3_v3fl(res1, in1, this->m_filter[5]); - madd_v3_v3fl(res2, in1, this->m_filter[7]); - - this->m_inputOperation->read(in1, x1, y3, NULL); - madd_v3_v3fl(res1, in1, this->m_filter[6]); - madd_v3_v3fl(res2, in1, this->m_filter[2]); - - this->m_inputOperation->read(in1, x2, y3, NULL); - madd_v3_v3fl(res1, in1, this->m_filter[7]); - madd_v3_v3fl(res2, in1, this->m_filter[5]); - - this->m_inputOperation->read(in1, x3, y3, NULL); - madd_v3_v3fl(res1, in1, this->m_filter[8]); - madd_v3_v3fl(res2, in1, this->m_filter[8]); - - output[0] = sqrt(res1[0] * res1[0] + res2[0] * res2[0]); - output[1] = sqrt(res1[1] * res1[1] + res2[1] * res2[1]); - output[2] = sqrt(res1[2] * res1[2] + res2[2] * res2[2]); - - output[0] = output[0] * value[0] + in2[0] * mval; - output[1] = output[1] * value[0] + in2[1] * mval; - output[2] = output[2] * value[0] + in2[2] * mval; - - output[3] = in2[3]; - - /* Make sure we don't return negative color. */ - output[0] = max(output[0], 0.0f); - output[1] = max(output[1], 0.0f); - output[2] = max(output[2], 0.0f); - output[3] = max(output[3], 0.0f); + float in1[4], in2[4], res1[4] = {0.0}, res2[4] = {0.0}; + + int x1 = x - 1; + int x2 = x; + int x3 = x + 1; + int y1 = y - 1; + int y2 = y; + int y3 = y + 1; + CLAMP(x1, 0, getWidth() - 1); + CLAMP(x2, 0, getWidth() - 1); + CLAMP(x3, 0, getWidth() - 1); + CLAMP(y1, 0, getHeight() - 1); + CLAMP(y2, 0, getHeight() - 1); + CLAMP(y3, 0, getHeight() - 1); + + float value[4]; + this->m_inputValueOperation->read(value, x2, y2, NULL); + float mval = 1.0f - value[0]; + + this->m_inputOperation->read(in1, x1, y1, NULL); + madd_v3_v3fl(res1, in1, this->m_filter[0]); + madd_v3_v3fl(res2, in1, this->m_filter[0]); + + this->m_inputOperation->read(in1, x2, y1, NULL); + madd_v3_v3fl(res1, in1, this->m_filter[1]); + madd_v3_v3fl(res2, in1, this->m_filter[3]); + + this->m_inputOperation->read(in1, x3, y1, NULL); + madd_v3_v3fl(res1, in1, this->m_filter[2]); + madd_v3_v3fl(res2, in1, this->m_filter[6]); + + this->m_inputOperation->read(in1, x1, y2, NULL); + madd_v3_v3fl(res1, in1, this->m_filter[3]); + madd_v3_v3fl(res2, in1, this->m_filter[1]); + + this->m_inputOperation->read(in2, x2, y2, NULL); + madd_v3_v3fl(res1, in2, this->m_filter[4]); + madd_v3_v3fl(res2, in2, this->m_filter[4]); + + this->m_inputOperation->read(in1, x3, y2, NULL); + madd_v3_v3fl(res1, in1, this->m_filter[5]); + madd_v3_v3fl(res2, in1, this->m_filter[7]); + + this->m_inputOperation->read(in1, x1, y3, NULL); + madd_v3_v3fl(res1, in1, this->m_filter[6]); + madd_v3_v3fl(res2, in1, this->m_filter[2]); + + this->m_inputOperation->read(in1, x2, y3, NULL); + madd_v3_v3fl(res1, in1, this->m_filter[7]); + madd_v3_v3fl(res2, in1, this->m_filter[5]); + + this->m_inputOperation->read(in1, x3, y3, NULL); + madd_v3_v3fl(res1, in1, this->m_filter[8]); + madd_v3_v3fl(res2, in1, this->m_filter[8]); + + output[0] = sqrt(res1[0] * res1[0] + res2[0] * res2[0]); + output[1] = sqrt(res1[1] * res1[1] + res2[1] * res2[1]); + output[2] = sqrt(res1[2] * res1[2] + res2[2] * res2[2]); + + output[0] = output[0] * value[0] + in2[0] * mval; + output[1] = output[1] * value[0] + in2[1] * mval; + output[2] = output[2] * value[0] + in2[2] * mval; + + output[3] = in2[3]; + + /* Make sure we don't return negative color. */ + output[0] = max(output[0], 0.0f); + output[1] = max(output[1], 0.0f); + output[2] = max(output[2], 0.0f); + output[3] = max(output[3], 0.0f); } diff --git a/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.h b/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.h index 58073e08acf..17509b018bf 100644 --- a/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.h +++ b/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.h @@ -22,9 +22,9 @@ #include "COM_ConvolutionFilterOperation.h" class ConvolutionEdgeFilterOperation : public ConvolutionFilterOperation { -public: - ConvolutionEdgeFilterOperation(); - void executePixel(float output[4], int x, int y, void *data); + public: + ConvolutionEdgeFilterOperation(); + void executePixel(float output[4], int x, int y, void *data); }; #endif diff --git a/source/blender/compositor/operations/COM_ConvolutionFilterOperation.cpp b/source/blender/compositor/operations/COM_ConvolutionFilterOperation.cpp index bc1ecf2bd80..3f47bfda618 100644 --- a/source/blender/compositor/operations/COM_ConvolutionFilterOperation.cpp +++ b/source/blender/compositor/operations/COM_ConvolutionFilterOperation.cpp @@ -24,102 +24,103 @@ ConvolutionFilterOperation::ConvolutionFilterOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_COLOR); - this->setResolutionInputSocketIndex(0); - this->m_inputOperation = NULL; - this->setComplex(true); + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_COLOR); + this->setResolutionInputSocketIndex(0); + this->m_inputOperation = NULL; + this->setComplex(true); } void ConvolutionFilterOperation::initExecution() { - this->m_inputOperation = this->getInputSocketReader(0); - this->m_inputValueOperation = this->getInputSocketReader(1); + this->m_inputOperation = this->getInputSocketReader(0); + this->m_inputValueOperation = this->getInputSocketReader(1); } -void ConvolutionFilterOperation::set3x3Filter(float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9) +void ConvolutionFilterOperation::set3x3Filter( + float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9) { - this->m_filter[0] = f1; - this->m_filter[1] = f2; - this->m_filter[2] = f3; - this->m_filter[3] = f4; - this->m_filter[4] = f5; - this->m_filter[5] = f6; - this->m_filter[6] = f7; - this->m_filter[7] = f8; - this->m_filter[8] = f9; - this->m_filterHeight = 3; - this->m_filterWidth = 3; + this->m_filter[0] = f1; + this->m_filter[1] = f2; + this->m_filter[2] = f3; + this->m_filter[3] = f4; + this->m_filter[4] = f5; + this->m_filter[5] = f6; + this->m_filter[6] = f7; + this->m_filter[7] = f8; + this->m_filter[8] = f9; + this->m_filterHeight = 3; + this->m_filterWidth = 3; } void ConvolutionFilterOperation::deinitExecution() { - this->m_inputOperation = NULL; - this->m_inputValueOperation = NULL; + this->m_inputOperation = NULL; + this->m_inputValueOperation = NULL; } - void ConvolutionFilterOperation::executePixel(float output[4], int x, int y, void * /*data*/) { - float in1[4]; - float in2[4]; - int x1 = x - 1; - int x2 = x; - int x3 = x + 1; - int y1 = y - 1; - int y2 = y; - int y3 = y + 1; - CLAMP(x1, 0, getWidth() - 1); - CLAMP(x2, 0, getWidth() - 1); - CLAMP(x3, 0, getWidth() - 1); - CLAMP(y1, 0, getHeight() - 1); - CLAMP(y2, 0, getHeight() - 1); - CLAMP(y3, 0, getHeight() - 1); - float value[4]; - this->m_inputValueOperation->read(value, x2, y2, NULL); - const float mval = 1.0f - value[0]; + float in1[4]; + float in2[4]; + int x1 = x - 1; + int x2 = x; + int x3 = x + 1; + int y1 = y - 1; + int y2 = y; + int y3 = y + 1; + CLAMP(x1, 0, getWidth() - 1); + CLAMP(x2, 0, getWidth() - 1); + CLAMP(x3, 0, getWidth() - 1); + CLAMP(y1, 0, getHeight() - 1); + CLAMP(y2, 0, getHeight() - 1); + CLAMP(y3, 0, getHeight() - 1); + float value[4]; + this->m_inputValueOperation->read(value, x2, y2, NULL); + const float mval = 1.0f - value[0]; - zero_v4(output); - this->m_inputOperation->read(in1, x1, y1, NULL); - madd_v4_v4fl(output, in1, this->m_filter[0]); - this->m_inputOperation->read(in1, x2, y1, NULL); - madd_v4_v4fl(output, in1, this->m_filter[1]); - this->m_inputOperation->read(in1, x3, y1, NULL); - madd_v4_v4fl(output, in1, this->m_filter[2]); - this->m_inputOperation->read(in1, x1, y2, NULL); - madd_v4_v4fl(output, in1, this->m_filter[3]); - this->m_inputOperation->read(in2, x2, y2, NULL); - madd_v4_v4fl(output, in2, this->m_filter[4]); - this->m_inputOperation->read(in1, x3, y2, NULL); - madd_v4_v4fl(output, in1, this->m_filter[5]); - this->m_inputOperation->read(in1, x1, y3, NULL); - madd_v4_v4fl(output, in1, this->m_filter[6]); - this->m_inputOperation->read(in1, x2, y3, NULL); - madd_v4_v4fl(output, in1, this->m_filter[7]); - this->m_inputOperation->read(in1, x3, y3, NULL); - madd_v4_v4fl(output, in1, this->m_filter[8]); + zero_v4(output); + this->m_inputOperation->read(in1, x1, y1, NULL); + madd_v4_v4fl(output, in1, this->m_filter[0]); + this->m_inputOperation->read(in1, x2, y1, NULL); + madd_v4_v4fl(output, in1, this->m_filter[1]); + this->m_inputOperation->read(in1, x3, y1, NULL); + madd_v4_v4fl(output, in1, this->m_filter[2]); + this->m_inputOperation->read(in1, x1, y2, NULL); + madd_v4_v4fl(output, in1, this->m_filter[3]); + this->m_inputOperation->read(in2, x2, y2, NULL); + madd_v4_v4fl(output, in2, this->m_filter[4]); + this->m_inputOperation->read(in1, x3, y2, NULL); + madd_v4_v4fl(output, in1, this->m_filter[5]); + this->m_inputOperation->read(in1, x1, y3, NULL); + madd_v4_v4fl(output, in1, this->m_filter[6]); + this->m_inputOperation->read(in1, x2, y3, NULL); + madd_v4_v4fl(output, in1, this->m_filter[7]); + this->m_inputOperation->read(in1, x3, y3, NULL); + madd_v4_v4fl(output, in1, this->m_filter[8]); - output[0] = output[0] * value[0] + in2[0] * mval; - output[1] = output[1] * value[0] + in2[1] * mval; - output[2] = output[2] * value[0] + in2[2] * mval; - output[3] = output[3] * value[0] + in2[3] * mval; + output[0] = output[0] * value[0] + in2[0] * mval; + output[1] = output[1] * value[0] + in2[1] * mval; + output[2] = output[2] * value[0] + in2[2] * mval; + output[3] = output[3] * value[0] + in2[3] * mval; - /* Make sure we don't return negative color. */ - output[0] = max(output[0], 0.0f); - output[1] = max(output[1], 0.0f); - output[2] = max(output[2], 0.0f); - output[3] = max(output[3], 0.0f); + /* Make sure we don't return negative color. */ + output[0] = max(output[0], 0.0f); + output[1] = max(output[1], 0.0f); + output[2] = max(output[2], 0.0f); + output[3] = max(output[3], 0.0f); } -bool ConvolutionFilterOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool ConvolutionFilterOperation::determineDependingAreaOfInterest( + rcti *input, ReadBufferOperation *readOperation, rcti *output) { - rcti newInput; - int addx = (this->m_filterWidth - 1) / 2 + 1; - int addy = (this->m_filterHeight - 1) / 2 + 1; - newInput.xmax = input->xmax + addx; - newInput.xmin = input->xmin - addx; - newInput.ymax = input->ymax + addy; - newInput.ymin = input->ymin - addy; + rcti newInput; + int addx = (this->m_filterWidth - 1) / 2 + 1; + int addy = (this->m_filterHeight - 1) / 2 + 1; + 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); + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } diff --git a/source/blender/compositor/operations/COM_ConvolutionFilterOperation.h b/source/blender/compositor/operations/COM_ConvolutionFilterOperation.h index 5342e2a7fa8..78db5a5ae9d 100644 --- a/source/blender/compositor/operations/COM_ConvolutionFilterOperation.h +++ b/source/blender/compositor/operations/COM_ConvolutionFilterOperation.h @@ -22,23 +22,26 @@ #include "COM_NodeOperation.h" class ConvolutionFilterOperation : public NodeOperation { -private: - int m_filterWidth; - int m_filterHeight; + private: + int m_filterWidth; + int m_filterHeight; -protected: - SocketReader *m_inputOperation; - SocketReader *m_inputValueOperation; - float m_filter[9]; + protected: + SocketReader *m_inputOperation; + SocketReader *m_inputValueOperation; + float m_filter[9]; -public: - ConvolutionFilterOperation(); - void set3x3Filter(float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - void executePixel(float output[4], int x, int y, void *data); + public: + ConvolutionFilterOperation(); + void set3x3Filter( + float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + void executePixel(float output[4], int x, int y, void *data); - void initExecution(); - void deinitExecution(); + void initExecution(); + void deinitExecution(); }; #endif diff --git a/source/blender/compositor/operations/COM_CropOperation.cpp b/source/blender/compositor/operations/COM_CropOperation.cpp index 2a78dc3a1f9..fbbe8706e11 100644 --- a/source/blender/compositor/operations/COM_CropOperation.cpp +++ b/source/blender/compositor/operations/COM_CropOperation.cpp @@ -21,105 +21,111 @@ CropBaseOperation::CropBaseOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); - this->addOutputSocket(COM_DT_COLOR); - this->m_inputOperation = NULL; - this->m_settings = NULL; + this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); + this->addOutputSocket(COM_DT_COLOR); + this->m_inputOperation = NULL; + this->m_settings = NULL; } void CropBaseOperation::updateArea() { - SocketReader *inputReference = this->getInputSocketReader(0); - float width = inputReference->getWidth(); - float height = inputReference->getHeight(); - NodeTwoXYs local_settings = *this->m_settings; + SocketReader *inputReference = this->getInputSocketReader(0); + float width = inputReference->getWidth(); + float height = inputReference->getHeight(); + NodeTwoXYs local_settings = *this->m_settings; - if (width > 0.0f && height > 0.0f) { - if (this->m_relative) { - local_settings.x1 = width * local_settings.fac_x1; - local_settings.x2 = width * local_settings.fac_x2; - local_settings.y1 = height * local_settings.fac_y1; - local_settings.y2 = height * local_settings.fac_y2; - } - if (width <= local_settings.x1 + 1) - local_settings.x1 = width - 1; - if (height <= local_settings.y1 + 1) - local_settings.y1 = height - 1; - if (width <= local_settings.x2 + 1) - local_settings.x2 = width - 1; - if (height <= local_settings.y2 + 1) - local_settings.y2 = height - 1; + if (width > 0.0f && height > 0.0f) { + if (this->m_relative) { + local_settings.x1 = width * local_settings.fac_x1; + local_settings.x2 = width * local_settings.fac_x2; + local_settings.y1 = height * local_settings.fac_y1; + local_settings.y2 = height * local_settings.fac_y2; + } + if (width <= local_settings.x1 + 1) + local_settings.x1 = width - 1; + if (height <= local_settings.y1 + 1) + local_settings.y1 = height - 1; + if (width <= local_settings.x2 + 1) + local_settings.x2 = width - 1; + if (height <= local_settings.y2 + 1) + local_settings.y2 = height - 1; - this->m_xmax = max(local_settings.x1, local_settings.x2) + 1; - this->m_xmin = min(local_settings.x1, local_settings.x2); - this->m_ymax = max(local_settings.y1, local_settings.y2) + 1; - this->m_ymin = min(local_settings.y1, local_settings.y2); - } - else { - this->m_xmax = 0; - this->m_xmin = 0; - this->m_ymax = 0; - this->m_ymin = 0; - } + this->m_xmax = max(local_settings.x1, local_settings.x2) + 1; + this->m_xmin = min(local_settings.x1, local_settings.x2); + this->m_ymax = max(local_settings.y1, local_settings.y2) + 1; + this->m_ymin = min(local_settings.y1, local_settings.y2); + } + else { + this->m_xmax = 0; + this->m_xmin = 0; + this->m_ymax = 0; + this->m_ymin = 0; + } } void CropBaseOperation::initExecution() { - this->m_inputOperation = this->getInputSocketReader(0); - updateArea(); + this->m_inputOperation = this->getInputSocketReader(0); + updateArea(); } void CropBaseOperation::deinitExecution() { - this->m_inputOperation = NULL; + this->m_inputOperation = NULL; } CropOperation::CropOperation() : CropBaseOperation() { - /* pass */ + /* pass */ } void CropOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { - if ((x < this->m_xmax && x >= this->m_xmin) && (y < this->m_ymax && y >= this->m_ymin)) { - this->m_inputOperation->readSampled(output, x, y, sampler); - } - else { - zero_v4(output); - } + if ((x < this->m_xmax && x >= this->m_xmin) && (y < this->m_ymax && y >= this->m_ymin)) { + this->m_inputOperation->readSampled(output, x, y, sampler); + } + else { + zero_v4(output); + } } CropImageOperation::CropImageOperation() : CropBaseOperation() { - /* pass */ + /* pass */ } -bool CropImageOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool CropImageOperation::determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output) { - rcti newInput; + rcti newInput; - newInput.xmax = input->xmax + this->m_xmin; - newInput.xmin = input->xmin + this->m_xmin; - newInput.ymax = input->ymax + this->m_ymin; - newInput.ymin = input->ymin + this->m_ymin; + newInput.xmax = input->xmax + this->m_xmin; + newInput.xmin = input->xmin + this->m_xmin; + newInput.ymax = input->ymax + this->m_ymin; + newInput.ymin = input->ymin + this->m_ymin; - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } -void CropImageOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +void CropImageOperation::determineResolution(unsigned int resolution[2], + unsigned int preferredResolution[2]) { - NodeOperation::determineResolution(resolution, preferredResolution); - updateArea(); - resolution[0] = this->m_xmax - this->m_xmin; - resolution[1] = this->m_ymax - this->m_ymin; + NodeOperation::determineResolution(resolution, preferredResolution); + updateArea(); + resolution[0] = this->m_xmax - this->m_xmin; + resolution[1] = this->m_ymax - this->m_ymin; } -void CropImageOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void CropImageOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) { - this->m_inputOperation->readSampled(output, (x + this->m_xmin), (y + this->m_ymin), sampler); - } - else { - zero_v4(output); - } + if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) { + this->m_inputOperation->readSampled(output, (x + this->m_xmin), (y + this->m_ymin), sampler); + } + else { + zero_v4(output); + } } diff --git a/source/blender/compositor/operations/COM_CropOperation.h b/source/blender/compositor/operations/COM_CropOperation.h index 06863f6fd0c..36c18d29e92 100644 --- a/source/blender/compositor/operations/COM_CropOperation.h +++ b/source/blender/compositor/operations/COM_CropOperation.h @@ -22,38 +22,46 @@ #include "COM_NodeOperation.h" class CropBaseOperation : public NodeOperation { -protected: - SocketReader *m_inputOperation; - NodeTwoXYs *m_settings; - bool m_relative; - int m_xmax; - int m_xmin; - int m_ymax; - int m_ymin; + protected: + SocketReader *m_inputOperation; + NodeTwoXYs *m_settings; + bool m_relative; + int m_xmax; + int m_xmin; + int m_ymax; + int m_ymin; - void updateArea(); -public: - CropBaseOperation(); - void initExecution(); - void deinitExecution(); - void setCropSettings(NodeTwoXYs *settings) { this->m_settings = settings; } - void setRelative(bool rel) { this->m_relative = rel; } + void updateArea(); + + public: + CropBaseOperation(); + void initExecution(); + void deinitExecution(); + void setCropSettings(NodeTwoXYs *settings) + { + this->m_settings = settings; + } + void setRelative(bool rel) + { + this->m_relative = rel; + } }; class CropOperation : public CropBaseOperation { -private: -public: - CropOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + private: + public: + CropOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class CropImageOperation : public CropBaseOperation { -private: -public: - CropImageOperation(); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - + private: + public: + CropImageOperation(); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; #endif diff --git a/source/blender/compositor/operations/COM_CryptomatteOperation.cpp b/source/blender/compositor/operations/COM_CryptomatteOperation.cpp index bd1c9b31d75..085db6a9dea 100644 --- a/source/blender/compositor/operations/COM_CryptomatteOperation.cpp +++ b/source/blender/compositor/operations/COM_CryptomatteOperation.cpp @@ -20,54 +20,51 @@ CryptomatteOperation::CryptomatteOperation(size_t num_inputs) : NodeOperation() { - for (size_t i = 0; i < num_inputs; i++) { - this->addInputSocket(COM_DT_COLOR); - } - inputs.resize(num_inputs); - this->addOutputSocket(COM_DT_COLOR); - this->setComplex(true); + for (size_t i = 0; i < num_inputs; i++) { + this->addInputSocket(COM_DT_COLOR); + } + inputs.resize(num_inputs); + this->addOutputSocket(COM_DT_COLOR); + this->setComplex(true); } void CryptomatteOperation::initExecution() { - for (size_t i = 0; i < inputs.size(); i++) { - inputs[i] = this->getInputSocketReader(i); - } + for (size_t i = 0; i < inputs.size(); i++) { + inputs[i] = this->getInputSocketReader(i); + } } void CryptomatteOperation::addObjectIndex(float objectIndex) { - if (objectIndex != 0.0f) { - m_objectIndex.push_back(objectIndex); - } + if (objectIndex != 0.0f) { + m_objectIndex.push_back(objectIndex); + } } -void CryptomatteOperation::executePixel(float output[4], - int x, - int y, - void *data) +void CryptomatteOperation::executePixel(float output[4], int x, int y, void *data) { - float input[4]; - output[0] = output[1] = output[2] = output[3] = 0.0f; - for (size_t i = 0; i < inputs.size(); i++) { - inputs[i]->read(input, x, y, data); - if (i == 0) { - /* Write the frontmost object as false color for picking. */ - output[0] = input[0]; - uint32_t m3hash; - ::memcpy(&m3hash, &input[0], sizeof(uint32_t)); - /* Since the red channel is likely to be out of display range, - * setting green and blue gives more meaningful images. */ - output[1] = ((float) ((m3hash << 8)) / (float) UINT32_MAX); - output[2] = ((float) ((m3hash << 16)) / (float) UINT32_MAX); - } - for (size_t i = 0; i < m_objectIndex.size(); i++) { - if (m_objectIndex[i] == input[0]) { - output[3] += input[1]; - } - if (m_objectIndex[i] == input[2]) { - output[3] += input[3]; - } - } - } + float input[4]; + output[0] = output[1] = output[2] = output[3] = 0.0f; + for (size_t i = 0; i < inputs.size(); i++) { + inputs[i]->read(input, x, y, data); + if (i == 0) { + /* Write the frontmost object as false color for picking. */ + output[0] = input[0]; + uint32_t m3hash; + ::memcpy(&m3hash, &input[0], sizeof(uint32_t)); + /* Since the red channel is likely to be out of display range, + * setting green and blue gives more meaningful images. */ + output[1] = ((float)((m3hash << 8)) / (float)UINT32_MAX); + output[2] = ((float)((m3hash << 16)) / (float)UINT32_MAX); + } + for (size_t i = 0; i < m_objectIndex.size(); i++) { + if (m_objectIndex[i] == input[0]) { + output[3] += input[1]; + } + if (m_objectIndex[i] == input[2]) { + output[3] += input[3]; + } + } + } } diff --git a/source/blender/compositor/operations/COM_CryptomatteOperation.h b/source/blender/compositor/operations/COM_CryptomatteOperation.h index 63d566c553f..459d8b65f12 100644 --- a/source/blender/compositor/operations/COM_CryptomatteOperation.h +++ b/source/blender/compositor/operations/COM_CryptomatteOperation.h @@ -20,19 +20,18 @@ #define __COM_CRYPTOMATTEOPERATION_H__ #include "COM_NodeOperation.h" - class CryptomatteOperation : public NodeOperation { -private: - std::vector<float> m_objectIndex; -public: - std::vector<SocketReader *> inputs; + private: + std::vector<float> m_objectIndex; - CryptomatteOperation(size_t num_inputs = 6); + public: + std::vector<SocketReader *> inputs; - void initExecution(); - void executePixel(float output[4], int x, int y, void *data); + CryptomatteOperation(size_t num_inputs = 6); - void addObjectIndex(float objectIndex); + void initExecution(); + void executePixel(float output[4], int x, int y, void *data); + void addObjectIndex(float objectIndex); }; #endif diff --git a/source/blender/compositor/operations/COM_CurveBaseOperation.cpp b/source/blender/compositor/operations/COM_CurveBaseOperation.cpp index fe83e75442f..d84af71d8d8 100644 --- a/source/blender/compositor/operations/COM_CurveBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_CurveBaseOperation.cpp @@ -21,41 +21,41 @@ #ifdef __cplusplus extern "C" { #endif -# include "BKE_colortools.h" +#include "BKE_colortools.h" #ifdef __cplusplus } #endif CurveBaseOperation::CurveBaseOperation() : NodeOperation() { - this->m_curveMapping = NULL; + this->m_curveMapping = NULL; } CurveBaseOperation::~CurveBaseOperation() { - if (this->m_curveMapping) { - curvemapping_free(this->m_curveMapping); - this->m_curveMapping = NULL; - } + if (this->m_curveMapping) { + curvemapping_free(this->m_curveMapping); + this->m_curveMapping = NULL; + } } void CurveBaseOperation::initExecution() { - curvemapping_initialize(this->m_curveMapping); + curvemapping_initialize(this->m_curveMapping); } void CurveBaseOperation::deinitExecution() { - if (this->m_curveMapping) { - curvemapping_free(this->m_curveMapping); - this->m_curveMapping = NULL; - } + if (this->m_curveMapping) { + curvemapping_free(this->m_curveMapping); + this->m_curveMapping = NULL; + } } void CurveBaseOperation::setCurveMapping(CurveMapping *mapping) { - /* duplicate the curve to avoid glitches while drawing, see bug [#32374] */ - if (this->m_curveMapping) { - curvemapping_free(this->m_curveMapping); - } - this->m_curveMapping = curvemapping_copy(mapping); + /* duplicate the curve to avoid glitches while drawing, see bug [#32374] */ + if (this->m_curveMapping) { + curvemapping_free(this->m_curveMapping); + } + this->m_curveMapping = curvemapping_copy(mapping); } diff --git a/source/blender/compositor/operations/COM_CurveBaseOperation.h b/source/blender/compositor/operations/COM_CurveBaseOperation.h index 71d5e4a67da..f42ce3c366f 100644 --- a/source/blender/compositor/operations/COM_CurveBaseOperation.h +++ b/source/blender/compositor/operations/COM_CurveBaseOperation.h @@ -22,21 +22,22 @@ #include "DNA_color_types.h" class CurveBaseOperation : public NodeOperation { -protected: - /** - * Cached reference to the inputProgram - */ - CurveMapping *m_curveMapping; -public: - CurveBaseOperation(); - ~CurveBaseOperation(); + protected: + /** + * Cached reference to the inputProgram + */ + CurveMapping *m_curveMapping; - /** - * Initialize the execution - */ - void initExecution(); - void deinitExecution(); + public: + CurveBaseOperation(); + ~CurveBaseOperation(); - void setCurveMapping(CurveMapping *mapping); + /** + * Initialize the execution + */ + void initExecution(); + void deinitExecution(); + + void setCurveMapping(CurveMapping *mapping); }; #endif diff --git a/source/blender/compositor/operations/COM_DespeckleOperation.cpp b/source/blender/compositor/operations/COM_DespeckleOperation.cpp index 0ac96ac89e9..807450040de 100644 --- a/source/blender/compositor/operations/COM_DespeckleOperation.cpp +++ b/source/blender/compositor/operations/COM_DespeckleOperation.cpp @@ -24,114 +24,120 @@ DespeckleOperation::DespeckleOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_COLOR); - this->setResolutionInputSocketIndex(0); - this->m_inputOperation = NULL; - this->setComplex(true); + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_COLOR); + this->setResolutionInputSocketIndex(0); + this->m_inputOperation = NULL; + this->setComplex(true); } void DespeckleOperation::initExecution() { - this->m_inputOperation = this->getInputSocketReader(0); - this->m_inputValueOperation = this->getInputSocketReader(1); + this->m_inputOperation = this->getInputSocketReader(0); + this->m_inputValueOperation = this->getInputSocketReader(1); } void DespeckleOperation::deinitExecution() { - this->m_inputOperation = NULL; - this->m_inputValueOperation = NULL; + this->m_inputOperation = NULL; + this->m_inputValueOperation = NULL; } BLI_INLINE int color_diff(const float a[3], const float b[3], const float threshold) { - return ((fabsf(a[0] - b[0]) > threshold) || - (fabsf(a[1] - b[1]) > threshold) || - (fabsf(a[2] - b[2]) > threshold)); + return ((fabsf(a[0] - b[0]) > threshold) || (fabsf(a[1] - b[1]) > threshold) || + (fabsf(a[2] - b[2]) > threshold)); } void DespeckleOperation::executePixel(float output[4], int x, int y, void * /*data*/) { - float w = 0.0f; - float color_org[4]; - float color_mid[4]; - float color_mid_ok[4]; - float in1[4]; - int x1 = x - 1; - int x2 = x; - int x3 = x + 1; - int y1 = y - 1; - int y2 = y; - int y3 = y + 1; - CLAMP(x1, 0, getWidth() - 1); - CLAMP(x2, 0, getWidth() - 1); - CLAMP(x3, 0, getWidth() - 1); - CLAMP(y1, 0, getHeight() - 1); - CLAMP(y2, 0, getHeight() - 1); - CLAMP(y3, 0, getHeight() - 1); - float value[4]; - this->m_inputValueOperation->read(value, x2, y2, NULL); - //const float mval = 1.0f - value[0]; - - - this->m_inputOperation->read(color_org, x2, y2, NULL); + float w = 0.0f; + float color_org[4]; + float color_mid[4]; + float color_mid_ok[4]; + float in1[4]; + int x1 = x - 1; + int x2 = x; + int x3 = x + 1; + int y1 = y - 1; + int y2 = y; + int y3 = y + 1; + CLAMP(x1, 0, getWidth() - 1); + CLAMP(x2, 0, getWidth() - 1); + CLAMP(x3, 0, getWidth() - 1); + CLAMP(y1, 0, getHeight() - 1); + CLAMP(y2, 0, getHeight() - 1); + CLAMP(y3, 0, getHeight() - 1); + float value[4]; + this->m_inputValueOperation->read(value, x2, y2, NULL); + //const float mval = 1.0f - value[0]; + + this->m_inputOperation->read(color_org, x2, y2, NULL); #define TOT_DIV_ONE 1.0f #define TOT_DIV_CNR (float)M_SQRT1_2 -#define WTOT (TOT_DIV_ONE * 4 + TOT_DIV_CNR * 4) - -#define COLOR_ADD(fac) \ -{ \ - madd_v4_v4fl(color_mid, in1, fac); \ - if (color_diff(in1, color_org, this->m_threshold)) { \ - w += fac; \ - madd_v4_v4fl(color_mid_ok, in1, fac); \ - } \ -} - - zero_v4(color_mid); - zero_v4(color_mid_ok); - - this->m_inputOperation->read(in1, x1, y1, NULL); COLOR_ADD(TOT_DIV_CNR) - this->m_inputOperation->read(in1, x2, y1, NULL); COLOR_ADD(TOT_DIV_ONE) - this->m_inputOperation->read(in1, x3, y1, NULL); COLOR_ADD(TOT_DIV_CNR) - this->m_inputOperation->read(in1, x1, y2, NULL); COLOR_ADD(TOT_DIV_ONE) +#define WTOT (TOT_DIV_ONE * 4 + TOT_DIV_CNR * 4) + +#define COLOR_ADD(fac) \ + { \ + madd_v4_v4fl(color_mid, in1, fac); \ + if (color_diff(in1, color_org, this->m_threshold)) { \ + w += fac; \ + madd_v4_v4fl(color_mid_ok, in1, fac); \ + } \ + } + + zero_v4(color_mid); + zero_v4(color_mid_ok); + + this->m_inputOperation->read(in1, x1, y1, NULL); + COLOR_ADD(TOT_DIV_CNR) + this->m_inputOperation->read(in1, x2, y1, NULL); + COLOR_ADD(TOT_DIV_ONE) + this->m_inputOperation->read(in1, x3, y1, NULL); + COLOR_ADD(TOT_DIV_CNR) + this->m_inputOperation->read(in1, x1, y2, NULL); + COLOR_ADD(TOT_DIV_ONE) #if 0 - this->m_inputOperation->read(in2, x2, y2, NULL); - madd_v4_v4fl(color_mid, in2, this->m_filter[4]); + this->m_inputOperation->read(in2, x2, y2, NULL); + madd_v4_v4fl(color_mid, in2, this->m_filter[4]); #endif - this->m_inputOperation->read(in1, x3, y2, NULL); COLOR_ADD(TOT_DIV_ONE) - this->m_inputOperation->read(in1, x1, y3, NULL); COLOR_ADD(TOT_DIV_CNR) - this->m_inputOperation->read(in1, x2, y3, NULL); COLOR_ADD(TOT_DIV_ONE) - this->m_inputOperation->read(in1, x3, y3, NULL); COLOR_ADD(TOT_DIV_CNR) - - mul_v4_fl(color_mid, 1.0f / (4.0f + (4.0f * (float)M_SQRT1_2))); - //mul_v4_fl(color_mid, 1.0f / w); - - if ((w != 0.0f) && - ((w / WTOT) > (this->m_threshold_neighbor)) && - color_diff(color_mid, color_org, this->m_threshold)) - { - mul_v4_fl(color_mid_ok, 1.0f / w); - interp_v4_v4v4(output, color_org, color_mid_ok, value[0]); - } - else { - copy_v4_v4(output, color_org); - } + this->m_inputOperation->read(in1, x3, y2, NULL); + COLOR_ADD(TOT_DIV_ONE) + this->m_inputOperation->read(in1, x1, y3, NULL); + COLOR_ADD(TOT_DIV_CNR) + this->m_inputOperation->read(in1, x2, y3, NULL); + COLOR_ADD(TOT_DIV_ONE) + this->m_inputOperation->read(in1, x3, y3, NULL); + COLOR_ADD(TOT_DIV_CNR) + + mul_v4_fl(color_mid, 1.0f / (4.0f + (4.0f * (float)M_SQRT1_2))); + //mul_v4_fl(color_mid, 1.0f / w); + + if ((w != 0.0f) && ((w / WTOT) > (this->m_threshold_neighbor)) && + color_diff(color_mid, color_org, this->m_threshold)) { + mul_v4_fl(color_mid_ok, 1.0f / w); + interp_v4_v4v4(output, color_org, color_mid_ok, value[0]); + } + else { + copy_v4_v4(output, color_org); + } } -bool DespeckleOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool DespeckleOperation::determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output) { - rcti newInput; - int addx = 2; //(this->m_filterWidth - 1) / 2 + 1; - int addy = 2; //(this->m_filterHeight - 1) / 2 + 1; - 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); + rcti newInput; + int addx = 2; //(this->m_filterWidth - 1) / 2 + 1; + int addy = 2; //(this->m_filterHeight - 1) / 2 + 1; + 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); } diff --git a/source/blender/compositor/operations/COM_DespeckleOperation.h b/source/blender/compositor/operations/COM_DespeckleOperation.h index 4a4aac41c32..280948b7fbe 100644 --- a/source/blender/compositor/operations/COM_DespeckleOperation.h +++ b/source/blender/compositor/operations/COM_DespeckleOperation.h @@ -21,27 +21,35 @@ #include "COM_NodeOperation.h" class DespeckleOperation : public NodeOperation { -private: - float m_threshold; - float m_threshold_neighbor; - - // int m_filterWidth; - // int m_filterHeight; - -protected: - SocketReader *m_inputOperation; - SocketReader *m_inputValueOperation; - -public: - DespeckleOperation(); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - void executePixel(float output[4], int x, int y, void *data); - - void setThreshold(float threshold) { this->m_threshold = threshold; } - void setThresholdNeighbor(float threshold) { this->m_threshold_neighbor = threshold; } - - void initExecution(); - void deinitExecution(); + private: + float m_threshold; + float m_threshold_neighbor; + + // int m_filterWidth; + // int m_filterHeight; + + protected: + SocketReader *m_inputOperation; + SocketReader *m_inputValueOperation; + + public: + DespeckleOperation(); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + void executePixel(float output[4], int x, int y, void *data); + + void setThreshold(float threshold) + { + this->m_threshold = threshold; + } + void setThresholdNeighbor(float threshold) + { + this->m_threshold_neighbor = threshold; + } + + void initExecution(); + void deinitExecution(); }; #endif diff --git a/source/blender/compositor/operations/COM_DifferenceMatteOperation.cpp b/source/blender/compositor/operations/COM_DifferenceMatteOperation.cpp index cb4feaf4918..ea3526eb7e0 100644 --- a/source/blender/compositor/operations/COM_DifferenceMatteOperation.cpp +++ b/source/blender/compositor/operations/COM_DifferenceMatteOperation.cpp @@ -21,63 +21,65 @@ DifferenceMatteOperation::DifferenceMatteOperation() : NodeOperation() { - addInputSocket(COM_DT_COLOR); - addInputSocket(COM_DT_COLOR); - addOutputSocket(COM_DT_VALUE); + addInputSocket(COM_DT_COLOR); + addInputSocket(COM_DT_COLOR); + addOutputSocket(COM_DT_VALUE); - this->m_inputImage1Program = NULL; - this->m_inputImage2Program = NULL; + this->m_inputImage1Program = NULL; + this->m_inputImage2Program = NULL; } void DifferenceMatteOperation::initExecution() { - this->m_inputImage1Program = this->getInputSocketReader(0); - this->m_inputImage2Program = this->getInputSocketReader(1); + this->m_inputImage1Program = this->getInputSocketReader(0); + this->m_inputImage2Program = this->getInputSocketReader(1); } void DifferenceMatteOperation::deinitExecution() { - this->m_inputImage1Program = NULL; - this->m_inputImage2Program = NULL; + this->m_inputImage1Program = NULL; + this->m_inputImage2Program = NULL; } -void DifferenceMatteOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void DifferenceMatteOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inColor1[4]; - float inColor2[4]; + float inColor1[4]; + float inColor2[4]; - const float tolerance = this->m_settings->t1; - const float falloff = this->m_settings->t2; - float difference; - float alpha; + const float tolerance = this->m_settings->t1; + const float falloff = this->m_settings->t2; + float difference; + float alpha; - this->m_inputImage1Program->readSampled(inColor1, x, y, sampler); - this->m_inputImage2Program->readSampled(inColor2, x, y, sampler); + this->m_inputImage1Program->readSampled(inColor1, x, y, sampler); + this->m_inputImage2Program->readSampled(inColor2, x, y, sampler); - difference = (fabsf(inColor2[0] - inColor1[0]) + - fabsf(inColor2[1] - inColor1[1]) + - fabsf(inColor2[2] - inColor1[2])); + difference = (fabsf(inColor2[0] - inColor1[0]) + fabsf(inColor2[1] - inColor1[1]) + + fabsf(inColor2[2] - inColor1[2])); - /* average together the distances */ - difference = difference / 3.0f; + /* average together the distances */ + difference = difference / 3.0f; - /* make 100% transparent */ - if (difference <= tolerance) { - output[0] = 0.0f; - } - /*in the falloff region, make partially transparent */ - else if (difference <= falloff + tolerance) { - difference = difference - tolerance; - alpha = difference / falloff; - /*only change if more transparent than before */ - if (alpha < inColor1[3]) { - output[0] = alpha; - } - else { /* leave as before */ - output[0] = inColor1[3]; - } - } - else { - /* foreground object */ - output[0] = inColor1[3]; - } + /* make 100% transparent */ + if (difference <= tolerance) { + output[0] = 0.0f; + } + /*in the falloff region, make partially transparent */ + else if (difference <= falloff + tolerance) { + difference = difference - tolerance; + alpha = difference / falloff; + /*only change if more transparent than before */ + if (alpha < inColor1[3]) { + output[0] = alpha; + } + else { /* leave as before */ + output[0] = inColor1[3]; + } + } + else { + /* foreground object */ + output[0] = inColor1[3]; + } } diff --git a/source/blender/compositor/operations/COM_DifferenceMatteOperation.h b/source/blender/compositor/operations/COM_DifferenceMatteOperation.h index 09f77a3d793..e96e212e511 100644 --- a/source/blender/compositor/operations/COM_DifferenceMatteOperation.h +++ b/source/blender/compositor/operations/COM_DifferenceMatteOperation.h @@ -20,30 +20,33 @@ #define __COM_DIFFERENCEMATTEOPERATION_H__ #include "COM_MixOperation.h" - /** * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ class DifferenceMatteOperation : public NodeOperation { -private: - NodeChroma *m_settings; - SocketReader *m_inputImage1Program; - SocketReader *m_inputImage2Program; -public: - /** - * Default constructor - */ - DifferenceMatteOperation(); + private: + NodeChroma *m_settings; + SocketReader *m_inputImage1Program; + SocketReader *m_inputImage2Program; + + public: + /** + * Default constructor + */ + DifferenceMatteOperation(); - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - void initExecution(); - void deinitExecution(); + void initExecution(); + void deinitExecution(); - void setSettings(NodeChroma *nodeChroma) { this->m_settings = nodeChroma; } + void setSettings(NodeChroma *nodeChroma) + { + this->m_settings = nodeChroma; + } }; #endif diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.cpp b/source/blender/compositor/operations/COM_DilateErodeOperation.cpp index 2e2888052b2..7cf1086dca1 100644 --- a/source/blender/compositor/operations/COM_DilateErodeOperation.cpp +++ b/source/blender/compositor/operations/COM_DilateErodeOperation.cpp @@ -25,532 +25,544 @@ // DilateErode Distance Threshold DilateErodeThresholdOperation::DilateErodeThresholdOperation() : NodeOperation() { - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_VALUE); - this->setComplex(true); - this->m_inputProgram = NULL; - this->m_inset = 0.0f; - this->m__switch = 0.5f; - this->m_distance = 0.0f; + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_VALUE); + this->setComplex(true); + this->m_inputProgram = NULL; + this->m_inset = 0.0f; + this->m__switch = 0.5f; + this->m_distance = 0.0f; } void DilateErodeThresholdOperation::initExecution() { - this->m_inputProgram = this->getInputSocketReader(0); - if (this->m_distance < 0.0f) { - this->m_scope = -this->m_distance + this->m_inset; - } - else { - if (this->m_inset * 2 > this->m_distance) { - this->m_scope = max(this->m_inset * 2 - this->m_distance, this->m_distance); - } - else { - this->m_scope = this->m_distance; - } - } - if (this->m_scope < 3) { - this->m_scope = 3; - } + this->m_inputProgram = this->getInputSocketReader(0); + if (this->m_distance < 0.0f) { + this->m_scope = -this->m_distance + this->m_inset; + } + else { + if (this->m_inset * 2 > this->m_distance) { + this->m_scope = max(this->m_inset * 2 - this->m_distance, this->m_distance); + } + else { + this->m_scope = this->m_distance; + } + } + if (this->m_scope < 3) { + this->m_scope = 3; + } } void *DilateErodeThresholdOperation::initializeTileData(rcti * /*rect*/) { - void *buffer = this->m_inputProgram->initializeTileData(NULL); - return buffer; + void *buffer = this->m_inputProgram->initializeTileData(NULL); + return buffer; } void DilateErodeThresholdOperation::executePixel(float output[4], int x, int y, void *data) { - float inputValue[4]; - const float sw = this->m__switch; - const float distance = this->m_distance; - float pixelvalue; - const float rd = this->m_scope * this->m_scope; - const float inset = this->m_inset; - float mindist = rd * 2; - - MemoryBuffer *inputBuffer = (MemoryBuffer *)data; - float *buffer = inputBuffer->getBuffer(); - rcti *rect = inputBuffer->getRect(); - const int minx = max(x - this->m_scope, rect->xmin); - const int miny = max(y - this->m_scope, rect->ymin); - const int maxx = min(x + this->m_scope, rect->xmax); - const int maxy = min(y + this->m_scope, rect->ymax); - const int bufferWidth = BLI_rcti_size_x(rect); - int offset; - - inputBuffer->read(inputValue, x, y); - if (inputValue[0] > sw) { - for (int yi = miny; yi < maxy; yi++) { - const float dy = yi - y; - offset = ((yi - rect->ymin) * bufferWidth + (minx - rect->xmin)); - for (int xi = minx; xi < maxx; xi++) { - if (buffer[offset] < sw) { - const float dx = xi - x; - const float dis = dx * dx + dy * dy; - mindist = min(mindist, dis); - } - offset ++; - } - } - pixelvalue = -sqrtf(mindist); - } - else { - for (int yi = miny; yi < maxy; yi++) { - const float dy = yi - y; - offset = ((yi - rect->ymin) * bufferWidth + (minx - rect->xmin)); - for (int xi = minx; xi < maxx; xi++) { - if (buffer[offset] > sw) { - const float dx = xi - x; - const float dis = dx * dx + dy * dy; - mindist = min(mindist, dis); - } - offset ++; - } - } - pixelvalue = sqrtf(mindist); - } - - if (distance > 0.0f) { - const float delta = distance - pixelvalue; - if (delta >= 0.0f) { - if (delta >= inset) { - output[0] = 1.0f; - } - else { - output[0] = delta / inset; - } - } - else { - output[0] = 0.0f; - } - } - else { - const float delta = -distance + pixelvalue; - if (delta < 0.0f) { - if (delta < -inset) { - output[0] = 1.0f; - } - else { - output[0] = (-delta) / inset; - } - } - else { - output[0] = 0.0f; - } - } + float inputValue[4]; + const float sw = this->m__switch; + const float distance = this->m_distance; + float pixelvalue; + const float rd = this->m_scope * this->m_scope; + const float inset = this->m_inset; + float mindist = rd * 2; + + MemoryBuffer *inputBuffer = (MemoryBuffer *)data; + float *buffer = inputBuffer->getBuffer(); + rcti *rect = inputBuffer->getRect(); + const int minx = max(x - this->m_scope, rect->xmin); + const int miny = max(y - this->m_scope, rect->ymin); + const int maxx = min(x + this->m_scope, rect->xmax); + const int maxy = min(y + this->m_scope, rect->ymax); + const int bufferWidth = BLI_rcti_size_x(rect); + int offset; + + inputBuffer->read(inputValue, x, y); + if (inputValue[0] > sw) { + for (int yi = miny; yi < maxy; yi++) { + const float dy = yi - y; + offset = ((yi - rect->ymin) * bufferWidth + (minx - rect->xmin)); + for (int xi = minx; xi < maxx; xi++) { + if (buffer[offset] < sw) { + const float dx = xi - x; + const float dis = dx * dx + dy * dy; + mindist = min(mindist, dis); + } + offset++; + } + } + pixelvalue = -sqrtf(mindist); + } + else { + for (int yi = miny; yi < maxy; yi++) { + const float dy = yi - y; + offset = ((yi - rect->ymin) * bufferWidth + (minx - rect->xmin)); + for (int xi = minx; xi < maxx; xi++) { + if (buffer[offset] > sw) { + const float dx = xi - x; + const float dis = dx * dx + dy * dy; + mindist = min(mindist, dis); + } + offset++; + } + } + pixelvalue = sqrtf(mindist); + } + + if (distance > 0.0f) { + const float delta = distance - pixelvalue; + if (delta >= 0.0f) { + if (delta >= inset) { + output[0] = 1.0f; + } + else { + output[0] = delta / inset; + } + } + else { + output[0] = 0.0f; + } + } + else { + const float delta = -distance + pixelvalue; + if (delta < 0.0f) { + if (delta < -inset) { + output[0] = 1.0f; + } + else { + output[0] = (-delta) / inset; + } + } + else { + output[0] = 0.0f; + } + } } void DilateErodeThresholdOperation::deinitExecution() { - this->m_inputProgram = NULL; + this->m_inputProgram = NULL; } -bool DilateErodeThresholdOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool DilateErodeThresholdOperation::determineDependingAreaOfInterest( + rcti *input, ReadBufferOperation *readOperation, rcti *output) { - rcti newInput; + rcti newInput; - newInput.xmax = input->xmax + this->m_scope; - newInput.xmin = input->xmin - this->m_scope; - newInput.ymax = input->ymax + this->m_scope; - newInput.ymin = input->ymin - this->m_scope; + newInput.xmax = input->xmax + this->m_scope; + newInput.xmin = input->xmin - this->m_scope; + newInput.ymax = input->ymax + this->m_scope; + newInput.ymin = input->ymin - this->m_scope; - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } // Dilate Distance DilateDistanceOperation::DilateDistanceOperation() : NodeOperation() { - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_VALUE); - this->setComplex(true); - this->m_inputProgram = NULL; - this->m_distance = 0.0f; - this->setOpenCL(true); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_VALUE); + this->setComplex(true); + this->m_inputProgram = NULL; + this->m_distance = 0.0f; + this->setOpenCL(true); } void DilateDistanceOperation::initExecution() { - this->m_inputProgram = this->getInputSocketReader(0); - this->m_scope = this->m_distance; - if (this->m_scope < 3) { - this->m_scope = 3; - } + this->m_inputProgram = this->getInputSocketReader(0); + this->m_scope = this->m_distance; + if (this->m_scope < 3) { + this->m_scope = 3; + } } void *DilateDistanceOperation::initializeTileData(rcti * /*rect*/) { - void *buffer = this->m_inputProgram->initializeTileData(NULL); - return buffer; + void *buffer = this->m_inputProgram->initializeTileData(NULL); + return buffer; } void DilateDistanceOperation::executePixel(float output[4], int x, int y, void *data) { - const float distance = this->m_distance; - const float mindist = distance * distance; - - MemoryBuffer *inputBuffer = (MemoryBuffer *)data; - float *buffer = inputBuffer->getBuffer(); - rcti *rect = inputBuffer->getRect(); - const int minx = max(x - this->m_scope, rect->xmin); - const int miny = max(y - this->m_scope, rect->ymin); - const int maxx = min(x + this->m_scope, rect->xmax); - const int maxy = min(y + this->m_scope, rect->ymax); - const int bufferWidth = BLI_rcti_size_x(rect); - int offset; - - float value = 0.0f; - - for (int yi = miny; yi < maxy; yi++) { - const float dy = yi - y; - offset = ((yi - rect->ymin) * bufferWidth + (minx - rect->xmin)); - for (int xi = minx; xi < maxx; xi++) { - const float dx = xi - x; - const float dis = dx * dx + dy * dy; - if (dis <= mindist) { - value = max(buffer[offset], value); - } - offset ++; - } - } - output[0] = value; + const float distance = this->m_distance; + const float mindist = distance * distance; + + MemoryBuffer *inputBuffer = (MemoryBuffer *)data; + float *buffer = inputBuffer->getBuffer(); + rcti *rect = inputBuffer->getRect(); + const int minx = max(x - this->m_scope, rect->xmin); + const int miny = max(y - this->m_scope, rect->ymin); + const int maxx = min(x + this->m_scope, rect->xmax); + const int maxy = min(y + this->m_scope, rect->ymax); + const int bufferWidth = BLI_rcti_size_x(rect); + int offset; + + float value = 0.0f; + + for (int yi = miny; yi < maxy; yi++) { + const float dy = yi - y; + offset = ((yi - rect->ymin) * bufferWidth + (minx - rect->xmin)); + for (int xi = minx; xi < maxx; xi++) { + const float dx = xi - x; + const float dis = dx * dx + dy * dy; + if (dis <= mindist) { + value = max(buffer[offset], value); + } + offset++; + } + } + output[0] = value; } void DilateDistanceOperation::deinitExecution() { - this->m_inputProgram = NULL; + this->m_inputProgram = NULL; } -bool DilateDistanceOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool DilateDistanceOperation::determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output) { - rcti newInput; + rcti newInput; - newInput.xmax = input->xmax + this->m_scope; - newInput.xmin = input->xmin - this->m_scope; - newInput.ymax = input->ymax + this->m_scope; - newInput.ymin = input->ymin - this->m_scope; + newInput.xmax = input->xmax + this->m_scope; + newInput.xmin = input->xmin - this->m_scope; + newInput.ymax = input->ymax + this->m_scope; + newInput.ymin = input->ymin - this->m_scope; - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } void DilateDistanceOperation::executeOpenCL(OpenCLDevice *device, - MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, - MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, + MemoryBuffer *outputMemoryBuffer, + cl_mem clOutputBuffer, + MemoryBuffer **inputMemoryBuffers, + list<cl_mem> *clMemToCleanUp, list<cl_kernel> * /*clKernelsToCleanUp*/) { - cl_kernel dilateKernel = device->COM_clCreateKernel("dilateKernel", NULL); - - cl_int distanceSquared = this->m_distance * this->m_distance; - cl_int scope = this->m_scope; - - device->COM_clAttachMemoryBufferToKernelParameter(dilateKernel, 0, 2, clMemToCleanUp, inputMemoryBuffers, this->m_inputProgram); - device->COM_clAttachOutputMemoryBufferToKernelParameter(dilateKernel, 1, clOutputBuffer); - device->COM_clAttachMemoryBufferOffsetToKernelParameter(dilateKernel, 3, outputMemoryBuffer); - clSetKernelArg(dilateKernel, 4, sizeof(cl_int), &scope); - clSetKernelArg(dilateKernel, 5, sizeof(cl_int), &distanceSquared); - device->COM_clAttachSizeToKernelParameter(dilateKernel, 6, this); - device->COM_clEnqueueRange(dilateKernel, outputMemoryBuffer, 7, this); + cl_kernel dilateKernel = device->COM_clCreateKernel("dilateKernel", NULL); + + cl_int distanceSquared = this->m_distance * this->m_distance; + cl_int scope = this->m_scope; + + device->COM_clAttachMemoryBufferToKernelParameter( + dilateKernel, 0, 2, clMemToCleanUp, inputMemoryBuffers, this->m_inputProgram); + device->COM_clAttachOutputMemoryBufferToKernelParameter(dilateKernel, 1, clOutputBuffer); + device->COM_clAttachMemoryBufferOffsetToKernelParameter(dilateKernel, 3, outputMemoryBuffer); + clSetKernelArg(dilateKernel, 4, sizeof(cl_int), &scope); + clSetKernelArg(dilateKernel, 5, sizeof(cl_int), &distanceSquared); + device->COM_clAttachSizeToKernelParameter(dilateKernel, 6, this); + device->COM_clEnqueueRange(dilateKernel, outputMemoryBuffer, 7, this); } // Erode Distance ErodeDistanceOperation::ErodeDistanceOperation() : DilateDistanceOperation() { - /* pass */ + /* pass */ } void ErodeDistanceOperation::executePixel(float output[4], int x, int y, void *data) { - const float distance = this->m_distance; - const float mindist = distance * distance; - - MemoryBuffer *inputBuffer = (MemoryBuffer *)data; - float *buffer = inputBuffer->getBuffer(); - rcti *rect = inputBuffer->getRect(); - const int minx = max(x - this->m_scope, rect->xmin); - const int miny = max(y - this->m_scope, rect->ymin); - const int maxx = min(x + this->m_scope, rect->xmax); - const int maxy = min(y + this->m_scope, rect->ymax); - const int bufferWidth = BLI_rcti_size_x(rect); - int offset; - - float value = 1.0f; - - for (int yi = miny; yi < maxy; yi++) { - const float dy = yi - y; - offset = ((yi - rect->ymin) * bufferWidth + (minx - rect->xmin)); - for (int xi = minx; xi < maxx; xi++) { - const float dx = xi - x; - const float dis = dx * dx + dy * dy; - if (dis <= mindist) { - value = min(buffer[offset], value); - } - offset ++; - } - } - output[0] = value; + const float distance = this->m_distance; + const float mindist = distance * distance; + + MemoryBuffer *inputBuffer = (MemoryBuffer *)data; + float *buffer = inputBuffer->getBuffer(); + rcti *rect = inputBuffer->getRect(); + const int minx = max(x - this->m_scope, rect->xmin); + const int miny = max(y - this->m_scope, rect->ymin); + const int maxx = min(x + this->m_scope, rect->xmax); + const int maxy = min(y + this->m_scope, rect->ymax); + const int bufferWidth = BLI_rcti_size_x(rect); + int offset; + + float value = 1.0f; + + for (int yi = miny; yi < maxy; yi++) { + const float dy = yi - y; + offset = ((yi - rect->ymin) * bufferWidth + (minx - rect->xmin)); + for (int xi = minx; xi < maxx; xi++) { + const float dx = xi - x; + const float dis = dx * dx + dy * dy; + if (dis <= mindist) { + value = min(buffer[offset], value); + } + offset++; + } + } + output[0] = value; } void ErodeDistanceOperation::executeOpenCL(OpenCLDevice *device, - MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, - MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, + MemoryBuffer *outputMemoryBuffer, + cl_mem clOutputBuffer, + MemoryBuffer **inputMemoryBuffers, + list<cl_mem> *clMemToCleanUp, list<cl_kernel> * /*clKernelsToCleanUp*/) { - cl_kernel erodeKernel = device->COM_clCreateKernel("erodeKernel", NULL); - - cl_int distanceSquared = this->m_distance * this->m_distance; - cl_int scope = this->m_scope; - - device->COM_clAttachMemoryBufferToKernelParameter(erodeKernel, 0, 2, clMemToCleanUp, inputMemoryBuffers, this->m_inputProgram); - device->COM_clAttachOutputMemoryBufferToKernelParameter(erodeKernel, 1, clOutputBuffer); - device->COM_clAttachMemoryBufferOffsetToKernelParameter(erodeKernel, 3, outputMemoryBuffer); - clSetKernelArg(erodeKernel, 4, sizeof(cl_int), &scope); - clSetKernelArg(erodeKernel, 5, sizeof(cl_int), &distanceSquared); - device->COM_clAttachSizeToKernelParameter(erodeKernel, 6, this); - device->COM_clEnqueueRange(erodeKernel, outputMemoryBuffer, 7, this); + cl_kernel erodeKernel = device->COM_clCreateKernel("erodeKernel", NULL); + + cl_int distanceSquared = this->m_distance * this->m_distance; + cl_int scope = this->m_scope; + + device->COM_clAttachMemoryBufferToKernelParameter( + erodeKernel, 0, 2, clMemToCleanUp, inputMemoryBuffers, this->m_inputProgram); + device->COM_clAttachOutputMemoryBufferToKernelParameter(erodeKernel, 1, clOutputBuffer); + device->COM_clAttachMemoryBufferOffsetToKernelParameter(erodeKernel, 3, outputMemoryBuffer); + clSetKernelArg(erodeKernel, 4, sizeof(cl_int), &scope); + clSetKernelArg(erodeKernel, 5, sizeof(cl_int), &distanceSquared); + device->COM_clAttachSizeToKernelParameter(erodeKernel, 6, this); + device->COM_clEnqueueRange(erodeKernel, outputMemoryBuffer, 7, this); } // Dilate step DilateStepOperation::DilateStepOperation() : NodeOperation() { - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_VALUE); - this->setComplex(true); - this->m_inputProgram = NULL; + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_VALUE); + this->setComplex(true); + this->m_inputProgram = NULL; } void DilateStepOperation::initExecution() { - this->m_inputProgram = this->getInputSocketReader(0); + this->m_inputProgram = this->getInputSocketReader(0); } - // small helper to pass data from initializeTileData to executePixel typedef struct tile_info { - rcti rect; - int width; - float *buffer; + rcti rect; + int width; + float *buffer; } tile_info; static tile_info *create_cache(int xmin, int xmax, int ymin, int ymax) { - tile_info *result = (tile_info *)MEM_mallocN(sizeof(tile_info), "dilate erode tile"); - result->rect.xmin = xmin; - result->rect.xmax = xmax; - result->rect.ymin = ymin; - result->rect.ymax = ymax; - result->width = xmax - xmin; - result->buffer = (float *)MEM_callocN(sizeof(float) * (ymax - ymin) * result->width, "dilate erode cache"); - return result; + tile_info *result = (tile_info *)MEM_mallocN(sizeof(tile_info), "dilate erode tile"); + result->rect.xmin = xmin; + result->rect.xmax = xmax; + result->rect.ymin = ymin; + result->rect.ymax = ymax; + result->width = xmax - xmin; + result->buffer = (float *)MEM_callocN(sizeof(float) * (ymax - ymin) * result->width, + "dilate erode cache"); + return result; } void *DilateStepOperation::initializeTileData(rcti *rect) { - MemoryBuffer *tile = (MemoryBuffer *)this->m_inputProgram->initializeTileData(NULL); - int x, y, i; - int width = tile->getWidth(); - int height = tile->getHeight(); - float *buffer = tile->getBuffer(); - - int half_window = this->m_iterations; - int window = half_window * 2 + 1; - - int xmin = max(0, rect->xmin - half_window); - int ymin = max(0, rect->ymin - half_window); - int xmax = min(width, rect->xmax + half_window); - int ymax = min(height, rect->ymax + half_window); - - int bwidth = rect->xmax - rect->xmin; - int bheight = rect->ymax - rect->ymin; - - // Note: Cache buffer has original tilesize width, but new height. - // We have to calculate the additional rows in the first pass, - // to have valid data available for the second pass. - tile_info *result = create_cache(rect->xmin, rect->xmax, ymin, ymax); - float *rectf = result->buffer; - - // temp holds maxima for every step in the algorithm, buf holds a - // single row or column of input values, padded with FLT_MAX's to - // simplify the logic. - float *temp = (float *)MEM_mallocN(sizeof(float) * (2 * window - 1), "dilate erode temp"); - float *buf = (float *)MEM_mallocN(sizeof(float) * (max(bwidth, bheight) + 5 * half_window), "dilate erode buf"); - - // The following is based on the van Herk/Gil-Werman algorithm for morphology operations. - // first pass, horizontal dilate/erode - for (y = ymin; y < ymax; y++) { - for (x = 0; x < bwidth + 5 * half_window; x++) { - buf[x] = -FLT_MAX; - } - for (x = xmin; x < xmax; ++x) { - buf[x - rect->xmin + window - 1] = buffer[(y * width + x)]; - } - - for (i = 0; i < (bwidth + 3 * half_window) / window; i++) { - int start = (i + 1) * window - 1; - - temp[window - 1] = buf[start]; - for (x = 1; x < window; x++) { - temp[window - 1 - x] = max(temp[window - x], buf[start - x]); - temp[window - 1 + x] = max(temp[window + x - 2], buf[start + x]); - } - - start = half_window + (i - 1) * window + 1; - for (x = -min(0, start); x < window - max(0, start + window - bwidth); x++) { - rectf[bwidth * (y - ymin) + (start + x)] = max(temp[x], temp[x + window - 1]); - } - } - } - - // second pass, vertical dilate/erode - for (x = 0; x < bwidth; x++) { - for (y = 0; y < bheight + 5 * half_window; y++) { - buf[y] = -FLT_MAX; - } - for (y = ymin; y < ymax; y++) { - buf[y - rect->ymin + window - 1] = rectf[(y - ymin) * bwidth + x]; - } - - for (i = 0; i < (bheight + 3 * half_window) / window; i++) { - int start = (i + 1) * window - 1; - - temp[window - 1] = buf[start]; - for (y = 1; y < window; y++) { - temp[window - 1 - y] = max(temp[window - y], buf[start - y]); - temp[window - 1 + y] = max(temp[window + y - 2], buf[start + y]); - } - - start = half_window + (i - 1) * window + 1; - for (y = -min(0, start); y < window - max(0, start + window - bheight); y++) { - rectf[bwidth * (y + start + (rect->ymin - ymin)) + x] = max(temp[y], temp[y + window - 1]); - } - } - } - - MEM_freeN(temp); - MEM_freeN(buf); - - return result; + MemoryBuffer *tile = (MemoryBuffer *)this->m_inputProgram->initializeTileData(NULL); + int x, y, i; + int width = tile->getWidth(); + int height = tile->getHeight(); + float *buffer = tile->getBuffer(); + + int half_window = this->m_iterations; + int window = half_window * 2 + 1; + + int xmin = max(0, rect->xmin - half_window); + int ymin = max(0, rect->ymin - half_window); + int xmax = min(width, rect->xmax + half_window); + int ymax = min(height, rect->ymax + half_window); + + int bwidth = rect->xmax - rect->xmin; + int bheight = rect->ymax - rect->ymin; + + // Note: Cache buffer has original tilesize width, but new height. + // We have to calculate the additional rows in the first pass, + // to have valid data available for the second pass. + tile_info *result = create_cache(rect->xmin, rect->xmax, ymin, ymax); + float *rectf = result->buffer; + + // temp holds maxima for every step in the algorithm, buf holds a + // single row or column of input values, padded with FLT_MAX's to + // simplify the logic. + float *temp = (float *)MEM_mallocN(sizeof(float) * (2 * window - 1), "dilate erode temp"); + float *buf = (float *)MEM_mallocN(sizeof(float) * (max(bwidth, bheight) + 5 * half_window), + "dilate erode buf"); + + // The following is based on the van Herk/Gil-Werman algorithm for morphology operations. + // first pass, horizontal dilate/erode + for (y = ymin; y < ymax; y++) { + for (x = 0; x < bwidth + 5 * half_window; x++) { + buf[x] = -FLT_MAX; + } + for (x = xmin; x < xmax; ++x) { + buf[x - rect->xmin + window - 1] = buffer[(y * width + x)]; + } + + for (i = 0; i < (bwidth + 3 * half_window) / window; i++) { + int start = (i + 1) * window - 1; + + temp[window - 1] = buf[start]; + for (x = 1; x < window; x++) { + temp[window - 1 - x] = max(temp[window - x], buf[start - x]); + temp[window - 1 + x] = max(temp[window + x - 2], buf[start + x]); + } + + start = half_window + (i - 1) * window + 1; + for (x = -min(0, start); x < window - max(0, start + window - bwidth); x++) { + rectf[bwidth * (y - ymin) + (start + x)] = max(temp[x], temp[x + window - 1]); + } + } + } + + // second pass, vertical dilate/erode + for (x = 0; x < bwidth; x++) { + for (y = 0; y < bheight + 5 * half_window; y++) { + buf[y] = -FLT_MAX; + } + for (y = ymin; y < ymax; y++) { + buf[y - rect->ymin + window - 1] = rectf[(y - ymin) * bwidth + x]; + } + + for (i = 0; i < (bheight + 3 * half_window) / window; i++) { + int start = (i + 1) * window - 1; + + temp[window - 1] = buf[start]; + for (y = 1; y < window; y++) { + temp[window - 1 - y] = max(temp[window - y], buf[start - y]); + temp[window - 1 + y] = max(temp[window + y - 2], buf[start + y]); + } + + start = half_window + (i - 1) * window + 1; + for (y = -min(0, start); y < window - max(0, start + window - bheight); y++) { + rectf[bwidth * (y + start + (rect->ymin - ymin)) + x] = max(temp[y], temp[y + window - 1]); + } + } + } + + MEM_freeN(temp); + MEM_freeN(buf); + + return result; } - void DilateStepOperation::executePixel(float output[4], int x, int y, void *data) { - tile_info *tile = (tile_info *)data; - int nx = x - tile->rect.xmin; - int ny = y - tile->rect.ymin; - output[0] = tile->buffer[tile->width * ny + nx]; + tile_info *tile = (tile_info *)data; + int nx = x - tile->rect.xmin; + int ny = y - tile->rect.ymin; + output[0] = tile->buffer[tile->width * ny + nx]; } void DilateStepOperation::deinitExecution() { - this->m_inputProgram = NULL; + this->m_inputProgram = NULL; } void DilateStepOperation::deinitializeTileData(rcti * /*rect*/, void *data) { - tile_info *tile = (tile_info *)data; - MEM_freeN(tile->buffer); - MEM_freeN(tile); + tile_info *tile = (tile_info *)data; + MEM_freeN(tile->buffer); + MEM_freeN(tile); } -bool DilateStepOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool DilateStepOperation::determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output) { - rcti newInput; - int it = this->m_iterations; - newInput.xmax = input->xmax + it; - newInput.xmin = input->xmin - it; - newInput.ymax = input->ymax + it; - newInput.ymin = input->ymin - it; - - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + rcti newInput; + int it = this->m_iterations; + newInput.xmax = input->xmax + it; + newInput.xmin = input->xmin - it; + newInput.ymax = input->ymax + it; + newInput.ymin = input->ymin - it; + + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } // Erode step ErodeStepOperation::ErodeStepOperation() : DilateStepOperation() { - /* pass */ + /* pass */ } void *ErodeStepOperation::initializeTileData(rcti *rect) { - MemoryBuffer *tile = (MemoryBuffer *)this->m_inputProgram->initializeTileData(NULL); - int x, y, i; - int width = tile->getWidth(); - int height = tile->getHeight(); - float *buffer = tile->getBuffer(); - - int half_window = this->m_iterations; - int window = half_window * 2 + 1; - - int xmin = max(0, rect->xmin - half_window); - int ymin = max(0, rect->ymin - half_window); - int xmax = min(width, rect->xmax + half_window); - int ymax = min(height, rect->ymax + half_window); - - int bwidth = rect->xmax - rect->xmin; - int bheight = rect->ymax - rect->ymin; - - // Note: Cache buffer has original tilesize width, but new height. - // We have to calculate the additional rows in the first pass, - // to have valid data available for the second pass. - tile_info *result = create_cache(rect->xmin, rect->xmax, ymin, ymax); - float *rectf = result->buffer; - - // temp holds maxima for every step in the algorithm, buf holds a - // single row or column of input values, padded with FLT_MAX's to - // simplify the logic. - float *temp = (float *)MEM_mallocN(sizeof(float) * (2 * window - 1), "dilate erode temp"); - float *buf = (float *)MEM_mallocN(sizeof(float) * (max(bwidth, bheight) + 5 * half_window), "dilate erode buf"); - - // The following is based on the van Herk/Gil-Werman algorithm for morphology operations. - // first pass, horizontal dilate/erode - for (y = ymin; y < ymax; y++) { - for (x = 0; x < bwidth + 5 * half_window; x++) { - buf[x] = FLT_MAX; - } - for (x = xmin; x < xmax; ++x) { - buf[x - rect->xmin + window - 1] = buffer[(y * width + x)]; - } - - for (i = 0; i < (bwidth + 3 * half_window) / window; i++) { - int start = (i + 1) * window - 1; - - temp[window - 1] = buf[start]; - for (x = 1; x < window; x++) { - temp[window - 1 - x] = min(temp[window - x], buf[start - x]); - temp[window - 1 + x] = min(temp[window + x - 2], buf[start + x]); - } - - start = half_window + (i - 1) * window + 1; - for (x = -min(0, start); x < window - max(0, start + window - bwidth); x++) { - rectf[bwidth * (y - ymin) + (start + x)] = min(temp[x], temp[x + window - 1]); - } - } - } - - // second pass, vertical dilate/erode - for (x = 0; x < bwidth; x++) { - for (y = 0; y < bheight + 5 * half_window; y++) { - buf[y] = FLT_MAX; - } - for (y = ymin; y < ymax; y++) { - buf[y - rect->ymin + window - 1] = rectf[(y - ymin) * bwidth + x]; - } - - for (i = 0; i < (bheight + 3 * half_window) / window; i++) { - int start = (i + 1) * window - 1; - - temp[window - 1] = buf[start]; - for (y = 1; y < window; y++) { - temp[window - 1 - y] = min(temp[window - y], buf[start - y]); - temp[window - 1 + y] = min(temp[window + y - 2], buf[start + y]); - } - - start = half_window + (i - 1) * window + 1; - for (y = -min(0, start); y < window - max(0, start + window - bheight); y++) { - rectf[bwidth * (y + start + (rect->ymin - ymin)) + x] = min(temp[y], temp[y + window - 1]); - } - } - } - - MEM_freeN(temp); - MEM_freeN(buf); - - return result; + MemoryBuffer *tile = (MemoryBuffer *)this->m_inputProgram->initializeTileData(NULL); + int x, y, i; + int width = tile->getWidth(); + int height = tile->getHeight(); + float *buffer = tile->getBuffer(); + + int half_window = this->m_iterations; + int window = half_window * 2 + 1; + + int xmin = max(0, rect->xmin - half_window); + int ymin = max(0, rect->ymin - half_window); + int xmax = min(width, rect->xmax + half_window); + int ymax = min(height, rect->ymax + half_window); + + int bwidth = rect->xmax - rect->xmin; + int bheight = rect->ymax - rect->ymin; + + // Note: Cache buffer has original tilesize width, but new height. + // We have to calculate the additional rows in the first pass, + // to have valid data available for the second pass. + tile_info *result = create_cache(rect->xmin, rect->xmax, ymin, ymax); + float *rectf = result->buffer; + + // temp holds maxima for every step in the algorithm, buf holds a + // single row or column of input values, padded with FLT_MAX's to + // simplify the logic. + float *temp = (float *)MEM_mallocN(sizeof(float) * (2 * window - 1), "dilate erode temp"); + float *buf = (float *)MEM_mallocN(sizeof(float) * (max(bwidth, bheight) + 5 * half_window), + "dilate erode buf"); + + // The following is based on the van Herk/Gil-Werman algorithm for morphology operations. + // first pass, horizontal dilate/erode + for (y = ymin; y < ymax; y++) { + for (x = 0; x < bwidth + 5 * half_window; x++) { + buf[x] = FLT_MAX; + } + for (x = xmin; x < xmax; ++x) { + buf[x - rect->xmin + window - 1] = buffer[(y * width + x)]; + } + + for (i = 0; i < (bwidth + 3 * half_window) / window; i++) { + int start = (i + 1) * window - 1; + + temp[window - 1] = buf[start]; + for (x = 1; x < window; x++) { + temp[window - 1 - x] = min(temp[window - x], buf[start - x]); + temp[window - 1 + x] = min(temp[window + x - 2], buf[start + x]); + } + + start = half_window + (i - 1) * window + 1; + for (x = -min(0, start); x < window - max(0, start + window - bwidth); x++) { + rectf[bwidth * (y - ymin) + (start + x)] = min(temp[x], temp[x + window - 1]); + } + } + } + + // second pass, vertical dilate/erode + for (x = 0; x < bwidth; x++) { + for (y = 0; y < bheight + 5 * half_window; y++) { + buf[y] = FLT_MAX; + } + for (y = ymin; y < ymax; y++) { + buf[y - rect->ymin + window - 1] = rectf[(y - ymin) * bwidth + x]; + } + + for (i = 0; i < (bheight + 3 * half_window) / window; i++) { + int start = (i + 1) * window - 1; + + temp[window - 1] = buf[start]; + for (y = 1; y < window; y++) { + temp[window - 1 - y] = min(temp[window - y], buf[start - y]); + temp[window - 1 + y] = min(temp[window + y - 2], buf[start + y]); + } + + start = half_window + (i - 1) * window + 1; + for (y = -min(0, start); y < window - max(0, start + window - bheight); y++) { + rectf[bwidth * (y + start + (rect->ymin - ymin)) + x] = min(temp[y], temp[y + window - 1]); + } + } + } + + MEM_freeN(temp); + MEM_freeN(buf); + + return result; } diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.h b/source/blender/compositor/operations/COM_DilateErodeOperation.h index 7aa71c80999..bd7e0938c58 100644 --- a/source/blender/compositor/operations/COM_DilateErodeOperation.h +++ b/source/blender/compositor/operations/COM_DilateErodeOperation.h @@ -20,140 +20,165 @@ #define __COM_DILATEERODEOPERATION_H__ #include "COM_NodeOperation.h" - class DilateErodeThresholdOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputProgram; - - float m_distance; - float m__switch; - float m_inset; - - /** - * determines the area of interest to track pixels - * keep this one as small as possible for speed gain. - */ - int m_scope; -public: - DilateErodeThresholdOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], int x, int y, void *data); - - /** - * Initialize the execution - */ - void initExecution(); - - void *initializeTileData(rcti *rect); - /** - * Deinitialize the execution - */ - void deinitExecution(); - - void setDistance(float distance) { this->m_distance = distance; } - void setSwitch(float sw) { this->m__switch = sw; } - void setInset(float inset) { this->m_inset = inset; } - - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - + private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputProgram; + + float m_distance; + float m__switch; + float m_inset; + + /** + * determines the area of interest to track pixels + * keep this one as small as possible for speed gain. + */ + int m_scope; + + public: + DilateErodeThresholdOperation(); + + /** + * the inner loop of this program + */ + void executePixel(float output[4], int x, int y, void *data); + + /** + * Initialize the execution + */ + void initExecution(); + + void *initializeTileData(rcti *rect); + /** + * Deinitialize the execution + */ + void deinitExecution(); + + void setDistance(float distance) + { + this->m_distance = distance; + } + void setSwitch(float sw) + { + this->m__switch = sw; + } + void setInset(float inset) + { + this->m_inset = inset; + } + + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); }; class DilateDistanceOperation : public NodeOperation { -private: -protected: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputProgram; - float m_distance; - int m_scope; -public: - DilateDistanceOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], int x, int y, void *data); - - /** - * Initialize the execution - */ - void initExecution(); - - void *initializeTileData(rcti *rect); - /** - * Deinitialize the execution - */ - void deinitExecution(); - - void setDistance(float distance) { this->m_distance = distance; } - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - - void executeOpenCL(OpenCLDevice *device, - MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, - MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, - list<cl_kernel> *clKernelsToCleanUp); + private: + protected: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputProgram; + float m_distance; + int m_scope; + + public: + DilateDistanceOperation(); + + /** + * the inner loop of this program + */ + void executePixel(float output[4], int x, int y, void *data); + + /** + * Initialize the execution + */ + void initExecution(); + + void *initializeTileData(rcti *rect); + /** + * Deinitialize the execution + */ + void deinitExecution(); + + void setDistance(float distance) + { + this->m_distance = distance; + } + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + + void executeOpenCL(OpenCLDevice *device, + MemoryBuffer *outputMemoryBuffer, + cl_mem clOutputBuffer, + MemoryBuffer **inputMemoryBuffers, + list<cl_mem> *clMemToCleanUp, + list<cl_kernel> *clKernelsToCleanUp); }; class ErodeDistanceOperation : public DilateDistanceOperation { -public: - ErodeDistanceOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], int x, int y, void *data); - - void executeOpenCL(OpenCLDevice *device, - MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, - MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, - list<cl_kernel> *clKernelsToCleanUp); + public: + ErodeDistanceOperation(); + + /** + * the inner loop of this program + */ + void executePixel(float output[4], int x, int y, void *data); + + void executeOpenCL(OpenCLDevice *device, + MemoryBuffer *outputMemoryBuffer, + cl_mem clOutputBuffer, + MemoryBuffer **inputMemoryBuffers, + list<cl_mem> *clMemToCleanUp, + list<cl_kernel> *clKernelsToCleanUp); }; class DilateStepOperation : public NodeOperation { -protected: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputProgram; - - int m_iterations; - -public: - DilateStepOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], int x, int y, void *data); - - /** - * Initialize the execution - */ - void initExecution(); - - void *initializeTileData(rcti *rect); - /** - * Deinitialize the execution - */ - void deinitExecution(); - void deinitializeTileData(rcti *rect, void *data); - - void setIterations(int iterations) { this->m_iterations = iterations; } - - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + protected: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputProgram; + + int m_iterations; + + public: + DilateStepOperation(); + + /** + * the inner loop of this program + */ + void executePixel(float output[4], int x, int y, void *data); + + /** + * Initialize the execution + */ + void initExecution(); + + void *initializeTileData(rcti *rect); + /** + * Deinitialize the execution + */ + void deinitExecution(); + void deinitializeTileData(rcti *rect, void *data); + + void setIterations(int iterations) + { + this->m_iterations = iterations; + } + + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); }; class ErodeStepOperation : public DilateStepOperation { -public: - ErodeStepOperation(); + public: + ErodeStepOperation(); - void *initializeTileData(rcti *rect); + void *initializeTileData(rcti *rect); }; #endif diff --git a/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp b/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp index a9f9ec9f091..59a397ab32d 100644 --- a/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp @@ -20,122 +20,127 @@ #include "BLI_math.h" #include "COM_OpenCLDevice.h" extern "C" { -# include "RE_pipeline.h" +#include "RE_pipeline.h" } DirectionalBlurOperation::DirectionalBlurOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - this->setComplex(true); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); + this->setComplex(true); - this->setOpenCL(true); - this->m_inputProgram = NULL; + this->setOpenCL(true); + this->m_inputProgram = NULL; } void DirectionalBlurOperation::initExecution() { - this->m_inputProgram = getInputSocketReader(0); - QualityStepHelper::initExecution(COM_QH_INCREASE); - const float angle = this->m_data->angle; - const float zoom = this->m_data->zoom; - const float spin = this->m_data->spin; - const float iterations = this->m_data->iter; - const float distance = this->m_data->distance; - const float center_x = this->m_data->center_x; - const float center_y = this->m_data->center_y; - const float width = getWidth(); - const float height = getHeight(); - - const float a = angle; - const float itsc = 1.0f / powf(2.0f, (float)iterations); - float D; - - D = distance * sqrtf(width * width + height * height); - this->m_center_x_pix = center_x * width; - this->m_center_y_pix = center_y * height; - - this->m_tx = itsc * D * cosf(a); - this->m_ty = -itsc * D * sinf(a); - this->m_sc = itsc * zoom; - this->m_rot = itsc * spin; - + this->m_inputProgram = getInputSocketReader(0); + QualityStepHelper::initExecution(COM_QH_INCREASE); + const float angle = this->m_data->angle; + const float zoom = this->m_data->zoom; + const float spin = this->m_data->spin; + const float iterations = this->m_data->iter; + const float distance = this->m_data->distance; + const float center_x = this->m_data->center_x; + const float center_y = this->m_data->center_y; + const float width = getWidth(); + const float height = getHeight(); + + const float a = angle; + const float itsc = 1.0f / powf(2.0f, (float)iterations); + float D; + + D = distance * sqrtf(width * width + height * height); + this->m_center_x_pix = center_x * width; + this->m_center_y_pix = center_y * height; + + this->m_tx = itsc * D * cosf(a); + this->m_ty = -itsc * D * sinf(a); + this->m_sc = itsc * zoom; + this->m_rot = itsc * spin; } void DirectionalBlurOperation::executePixel(float output[4], int x, int y, void * /*data*/) { - const int iterations = pow(2.0f, this->m_data->iter); - float col[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - float col2[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - this->m_inputProgram->readSampled(col2, x, y, COM_PS_BILINEAR); - float ltx = this->m_tx; - float lty = this->m_ty; - float lsc = this->m_sc; - float lrot = this->m_rot; - /* blur the image */ - for (int i = 0; i < iterations; ++i) { - const float cs = cosf(lrot), ss = sinf(lrot); - const float isc = 1.0f / (1.0f + lsc); - - const float v = isc * (y - this->m_center_y_pix) + lty; - const float u = isc * (x - this->m_center_x_pix) + ltx; - - this->m_inputProgram->readSampled(col, - cs * u + ss * v + this->m_center_x_pix, - cs * v - ss * u + this->m_center_y_pix, - COM_PS_BILINEAR); - - add_v4_v4(col2, col); - - /* double transformations */ - ltx += this->m_tx; - lty += this->m_ty; - lrot += this->m_rot; - lsc += this->m_sc; - } - - mul_v4_v4fl(output, col2, 1.0f / (iterations + 1)); + const int iterations = pow(2.0f, this->m_data->iter); + float col[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + float col2[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + this->m_inputProgram->readSampled(col2, x, y, COM_PS_BILINEAR); + float ltx = this->m_tx; + float lty = this->m_ty; + float lsc = this->m_sc; + float lrot = this->m_rot; + /* blur the image */ + for (int i = 0; i < iterations; ++i) { + const float cs = cosf(lrot), ss = sinf(lrot); + const float isc = 1.0f / (1.0f + lsc); + + const float v = isc * (y - this->m_center_y_pix) + lty; + const float u = isc * (x - this->m_center_x_pix) + ltx; + + this->m_inputProgram->readSampled(col, + cs * u + ss * v + this->m_center_x_pix, + cs * v - ss * u + this->m_center_y_pix, + COM_PS_BILINEAR); + + add_v4_v4(col2, col); + + /* double transformations */ + ltx += this->m_tx; + lty += this->m_ty; + lrot += this->m_rot; + lsc += this->m_sc; + } + + mul_v4_v4fl(output, col2, 1.0f / (iterations + 1)); } void DirectionalBlurOperation::executeOpenCL(OpenCLDevice *device, - MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, - MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, - list<cl_kernel> * /*clKernelsToCleanUp*/) + MemoryBuffer *outputMemoryBuffer, + cl_mem clOutputBuffer, + MemoryBuffer **inputMemoryBuffers, + list<cl_mem> *clMemToCleanUp, + list<cl_kernel> * /*clKernelsToCleanUp*/) { - cl_kernel directionalBlurKernel = device->COM_clCreateKernel("directionalBlurKernel", NULL); - - cl_int iterations = pow(2.0f, this->m_data->iter); - cl_float2 ltxy = {{this->m_tx, this->m_ty}}; - cl_float2 centerpix = {{this->m_center_x_pix, this->m_center_y_pix}}; - cl_float lsc = this->m_sc; - cl_float lrot = this->m_rot; - - device->COM_clAttachMemoryBufferToKernelParameter(directionalBlurKernel, 0, -1, clMemToCleanUp, inputMemoryBuffers, this->m_inputProgram); - device->COM_clAttachOutputMemoryBufferToKernelParameter(directionalBlurKernel, 1, clOutputBuffer); - device->COM_clAttachMemoryBufferOffsetToKernelParameter(directionalBlurKernel, 2, outputMemoryBuffer); - clSetKernelArg(directionalBlurKernel, 3, sizeof(cl_int), &iterations); - clSetKernelArg(directionalBlurKernel, 4, sizeof(cl_float), &lsc); - clSetKernelArg(directionalBlurKernel, 5, sizeof(cl_float), &lrot); - clSetKernelArg(directionalBlurKernel, 6, sizeof(cl_float2), <xy); - clSetKernelArg(directionalBlurKernel, 7, sizeof(cl_float2), ¢erpix); - - device->COM_clEnqueueRange(directionalBlurKernel, outputMemoryBuffer, 8, this); + cl_kernel directionalBlurKernel = device->COM_clCreateKernel("directionalBlurKernel", NULL); + + cl_int iterations = pow(2.0f, this->m_data->iter); + cl_float2 ltxy = {{this->m_tx, this->m_ty}}; + cl_float2 centerpix = {{this->m_center_x_pix, this->m_center_y_pix}}; + cl_float lsc = this->m_sc; + cl_float lrot = this->m_rot; + + device->COM_clAttachMemoryBufferToKernelParameter( + directionalBlurKernel, 0, -1, clMemToCleanUp, inputMemoryBuffers, this->m_inputProgram); + device->COM_clAttachOutputMemoryBufferToKernelParameter( + directionalBlurKernel, 1, clOutputBuffer); + device->COM_clAttachMemoryBufferOffsetToKernelParameter( + directionalBlurKernel, 2, outputMemoryBuffer); + clSetKernelArg(directionalBlurKernel, 3, sizeof(cl_int), &iterations); + clSetKernelArg(directionalBlurKernel, 4, sizeof(cl_float), &lsc); + clSetKernelArg(directionalBlurKernel, 5, sizeof(cl_float), &lrot); + clSetKernelArg(directionalBlurKernel, 6, sizeof(cl_float2), <xy); + clSetKernelArg(directionalBlurKernel, 7, sizeof(cl_float2), ¢erpix); + + device->COM_clEnqueueRange(directionalBlurKernel, outputMemoryBuffer, 8, this); } - void DirectionalBlurOperation::deinitExecution() { - this->m_inputProgram = NULL; + this->m_inputProgram = NULL; } -bool DirectionalBlurOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output) +bool DirectionalBlurOperation::determineDependingAreaOfInterest(rcti * /*input*/, + ReadBufferOperation *readOperation, + rcti *output) { - rcti newInput; + rcti newInput; - newInput.xmax = this->getWidth(); - newInput.xmin = 0; - newInput.ymax = this->getHeight(); - newInput.ymin = 0; + newInput.xmax = this->getWidth(); + newInput.xmin = 0; + newInput.ymax = this->getHeight(); + newInput.ymin = 0; - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } diff --git a/source/blender/compositor/operations/COM_DirectionalBlurOperation.h b/source/blender/compositor/operations/COM_DirectionalBlurOperation.h index fa224407d08..f8b7bab010b 100644 --- a/source/blender/compositor/operations/COM_DirectionalBlurOperation.h +++ b/source/blender/compositor/operations/COM_DirectionalBlurOperation.h @@ -22,40 +22,46 @@ #include "COM_QualityStepHelper.h" class DirectionalBlurOperation : public NodeOperation, public QualityStepHelper { -private: - SocketReader *m_inputProgram; - NodeDBlurData *m_data; + private: + SocketReader *m_inputProgram; + NodeDBlurData *m_data; - float m_center_x_pix, m_center_y_pix; - float m_tx, m_ty; - float m_sc, m_rot; + float m_center_x_pix, m_center_y_pix; + float m_tx, m_ty; + float m_sc, m_rot; -public: - DirectionalBlurOperation(); + public: + DirectionalBlurOperation(); - /** - * the inner loop of this program - */ - void executePixel(float output[4], int x, int y, void *data); + /** + * the inner loop of this program + */ + void executePixel(float output[4], int x, int y, void *data); - /** - * Initialize the execution - */ - void initExecution(); + /** + * Initialize the execution + */ + void initExecution(); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Deinitialize the execution + */ + void deinitExecution(); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); - void setData(NodeDBlurData *data) { this->m_data = data; } - - void executeOpenCL(OpenCLDevice *device, - MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, - MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, - list<cl_kernel> *clKernelsToCleanUp); + void setData(NodeDBlurData *data) + { + this->m_data = data; + } + void executeOpenCL(OpenCLDevice *device, + MemoryBuffer *outputMemoryBuffer, + cl_mem clOutputBuffer, + MemoryBuffer **inputMemoryBuffers, + list<cl_mem> *clMemToCleanUp, + list<cl_kernel> *clKernelsToCleanUp); }; #endif diff --git a/source/blender/compositor/operations/COM_DisplaceOperation.cpp b/source/blender/compositor/operations/COM_DisplaceOperation.cpp index b44123196f8..3efc566cb4e 100644 --- a/source/blender/compositor/operations/COM_DisplaceOperation.cpp +++ b/source/blender/compositor/operations/COM_DisplaceOperation.cpp @@ -22,168 +22,174 @@ DisplaceOperation::DisplaceOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_VECTOR); - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_COLOR); - this->setComplex(true); - - this->m_inputColorProgram = NULL; - this->m_inputVectorProgram = NULL; - this->m_inputScaleXProgram = NULL; - this->m_inputScaleYProgram = NULL; + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VECTOR); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_COLOR); + this->setComplex(true); + + this->m_inputColorProgram = NULL; + this->m_inputVectorProgram = NULL; + this->m_inputScaleXProgram = NULL; + this->m_inputScaleYProgram = NULL; } void DisplaceOperation::initExecution() { - this->m_inputColorProgram = this->getInputSocketReader(0); - this->m_inputVectorProgram = this->getInputSocketReader(1); - this->m_inputScaleXProgram = this->getInputSocketReader(2); - this->m_inputScaleYProgram = this->getInputSocketReader(3); + this->m_inputColorProgram = this->getInputSocketReader(0); + this->m_inputVectorProgram = this->getInputSocketReader(1); + this->m_inputScaleXProgram = this->getInputSocketReader(2); + this->m_inputScaleYProgram = this->getInputSocketReader(3); - this->m_width_x4 = this->getWidth() * 4; - this->m_height_x4 = this->getHeight() * 4; + this->m_width_x4 = this->getWidth() * 4; + this->m_height_x4 = this->getHeight() * 4; } -void DisplaceOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) +void DisplaceOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler /*sampler*/) { - float xy[2] = { x, y }; - float uv[2], deriv[2][2]; - - pixelTransform(xy, uv, deriv); - if (is_zero_v2(deriv[0]) && is_zero_v2(deriv[1])) { - this->m_inputColorProgram->readSampled(output, uv[0], uv[1], COM_PS_BILINEAR); - } - else { - /* EWA filtering (without nearest it gets blurry with NO distortion) */ - this->m_inputColorProgram->readFiltered(output, uv[0], uv[1], deriv[0], deriv[1]); - } + float xy[2] = {x, y}; + float uv[2], deriv[2][2]; + + pixelTransform(xy, uv, deriv); + if (is_zero_v2(deriv[0]) && is_zero_v2(deriv[1])) { + this->m_inputColorProgram->readSampled(output, uv[0], uv[1], COM_PS_BILINEAR); + } + else { + /* EWA filtering (without nearest it gets blurry with NO distortion) */ + this->m_inputColorProgram->readFiltered(output, uv[0], uv[1], deriv[0], deriv[1]); + } } -bool DisplaceOperation::read_displacement(float x, float y, float xscale, float yscale, const float origin[2], float &r_u, float &r_v) +bool DisplaceOperation::read_displacement( + float x, float y, float xscale, float yscale, const float origin[2], float &r_u, float &r_v) { - float width = m_inputVectorProgram->getWidth(); - float height = m_inputVectorProgram->getHeight(); - if (x < 0.0f || x >= width || y < 0.0f || y >= height) { - r_u = 0.0f; - r_v = 0.0f; - return false; - } - else { - float col[4]; - m_inputVectorProgram->readSampled(col, x, y, COM_PS_BILINEAR); - r_u = origin[0] - col[0] * xscale; - r_v = origin[1] - col[1] * yscale; - return true; - } + float width = m_inputVectorProgram->getWidth(); + float height = m_inputVectorProgram->getHeight(); + if (x < 0.0f || x >= width || y < 0.0f || y >= height) { + r_u = 0.0f; + r_v = 0.0f; + return false; + } + else { + float col[4]; + m_inputVectorProgram->readSampled(col, x, y, COM_PS_BILINEAR); + r_u = origin[0] - col[0] * xscale; + r_v = origin[1] - col[1] * yscale; + return true; + } } void DisplaceOperation::pixelTransform(const float xy[2], float r_uv[2], float r_deriv[2][2]) { - float col[4]; - float uv[2]; /* temporary variables for derivative estimation */ - int num; - - m_inputScaleXProgram->readSampled(col, xy[0], xy[1], COM_PS_NEAREST); - float xs = col[0]; - m_inputScaleYProgram->readSampled(col, xy[0], xy[1], COM_PS_NEAREST); - float ys = col[0]; - /* clamp x and y displacement to triple image resolution - - * to prevent hangs from huge values mistakenly plugged in eg. z buffers */ - CLAMP(xs, -m_width_x4, m_width_x4); - CLAMP(ys, -m_height_x4, m_height_x4); - - /* displaced pixel in uv coords, for image sampling */ - read_displacement(xy[0], xy[1], xs, ys, xy, r_uv[0], r_uv[1]); - - /* Estimate partial derivatives using 1-pixel offsets */ - const float epsilon[2] = { 1.0f, 1.0f }; - - zero_v2(r_deriv[0]); - zero_v2(r_deriv[1]); - - num = 0; - if (read_displacement(xy[0] + epsilon[0], xy[1], xs, ys, xy, uv[0], uv[1])) { - r_deriv[0][0] += uv[0] - r_uv[0]; - r_deriv[1][0] += uv[1] - r_uv[1]; - ++num; - } - if (read_displacement(xy[0] - epsilon[0], xy[1], xs, ys, xy, uv[0], uv[1])) { - r_deriv[0][0] += r_uv[0] - uv[0]; - r_deriv[1][0] += r_uv[1] - uv[1]; - ++num; - } - if (num > 0) { - float numinv = 1.0f / (float)num; - r_deriv[0][0] *= numinv; - r_deriv[1][0] *= numinv; - } - - num = 0; - if (read_displacement(xy[0], xy[1] + epsilon[1], xs, ys, xy, uv[0], uv[1])) { - r_deriv[0][1] += uv[0] - r_uv[0]; - r_deriv[1][1] += uv[1] - r_uv[1]; - ++num; - } - if (read_displacement(xy[0], xy[1] - epsilon[1], xs, ys, xy, uv[0], uv[1])) { - r_deriv[0][1] += r_uv[0] - uv[0]; - r_deriv[1][1] += r_uv[1] - uv[1]; - ++num; - } - if (num > 0) { - float numinv = 1.0f / (float)num; - r_deriv[0][1] *= numinv; - r_deriv[1][1] *= numinv; - } + float col[4]; + float uv[2]; /* temporary variables for derivative estimation */ + int num; + + m_inputScaleXProgram->readSampled(col, xy[0], xy[1], COM_PS_NEAREST); + float xs = col[0]; + m_inputScaleYProgram->readSampled(col, xy[0], xy[1], COM_PS_NEAREST); + float ys = col[0]; + /* clamp x and y displacement to triple image resolution - + * to prevent hangs from huge values mistakenly plugged in eg. z buffers */ + CLAMP(xs, -m_width_x4, m_width_x4); + CLAMP(ys, -m_height_x4, m_height_x4); + + /* displaced pixel in uv coords, for image sampling */ + read_displacement(xy[0], xy[1], xs, ys, xy, r_uv[0], r_uv[1]); + + /* Estimate partial derivatives using 1-pixel offsets */ + const float epsilon[2] = {1.0f, 1.0f}; + + zero_v2(r_deriv[0]); + zero_v2(r_deriv[1]); + + num = 0; + if (read_displacement(xy[0] + epsilon[0], xy[1], xs, ys, xy, uv[0], uv[1])) { + r_deriv[0][0] += uv[0] - r_uv[0]; + r_deriv[1][0] += uv[1] - r_uv[1]; + ++num; + } + if (read_displacement(xy[0] - epsilon[0], xy[1], xs, ys, xy, uv[0], uv[1])) { + r_deriv[0][0] += r_uv[0] - uv[0]; + r_deriv[1][0] += r_uv[1] - uv[1]; + ++num; + } + if (num > 0) { + float numinv = 1.0f / (float)num; + r_deriv[0][0] *= numinv; + r_deriv[1][0] *= numinv; + } + + num = 0; + if (read_displacement(xy[0], xy[1] + epsilon[1], xs, ys, xy, uv[0], uv[1])) { + r_deriv[0][1] += uv[0] - r_uv[0]; + r_deriv[1][1] += uv[1] - r_uv[1]; + ++num; + } + if (read_displacement(xy[0], xy[1] - epsilon[1], xs, ys, xy, uv[0], uv[1])) { + r_deriv[0][1] += r_uv[0] - uv[0]; + r_deriv[1][1] += r_uv[1] - uv[1]; + ++num; + } + if (num > 0) { + float numinv = 1.0f / (float)num; + r_deriv[0][1] *= numinv; + r_deriv[1][1] *= numinv; + } } void DisplaceOperation::deinitExecution() { - this->m_inputColorProgram = NULL; - this->m_inputVectorProgram = NULL; - this->m_inputScaleXProgram = NULL; - this->m_inputScaleYProgram = NULL; + this->m_inputColorProgram = NULL; + this->m_inputVectorProgram = NULL; + this->m_inputScaleXProgram = NULL; + this->m_inputScaleYProgram = NULL; } -bool DisplaceOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool DisplaceOperation::determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output) { - rcti colorInput; - rcti vectorInput; - NodeOperation *operation = NULL; - - /* the vector buffer only needs a 2x2 buffer. The image needs whole buffer */ - /* image */ - operation = getInputOperation(0); - colorInput.xmax = operation->getWidth(); - colorInput.xmin = 0; - colorInput.ymax = operation->getHeight(); - colorInput.ymin = 0; - if (operation->determineDependingAreaOfInterest(&colorInput, readOperation, output)) { - return true; - } - - /* vector */ - operation = getInputOperation(1); - vectorInput.xmax = input->xmax + 1; - vectorInput.xmin = input->xmin - 1; - vectorInput.ymax = input->ymax + 1; - vectorInput.ymin = input->ymin - 1; - if (operation->determineDependingAreaOfInterest(&vectorInput, readOperation, output)) { - return true; - } - - /* scale x */ - operation = getInputOperation(2); - if (operation->determineDependingAreaOfInterest(input, readOperation, output) ) { - return true; - } - - /* scale y */ - operation = getInputOperation(3); - if (operation->determineDependingAreaOfInterest(input, readOperation, output) ) { - return true; - } - - return false; + rcti colorInput; + rcti vectorInput; + NodeOperation *operation = NULL; + + /* the vector buffer only needs a 2x2 buffer. The image needs whole buffer */ + /* image */ + operation = getInputOperation(0); + colorInput.xmax = operation->getWidth(); + colorInput.xmin = 0; + colorInput.ymax = operation->getHeight(); + colorInput.ymin = 0; + if (operation->determineDependingAreaOfInterest(&colorInput, readOperation, output)) { + return true; + } + + /* vector */ + operation = getInputOperation(1); + vectorInput.xmax = input->xmax + 1; + vectorInput.xmin = input->xmin - 1; + vectorInput.ymax = input->ymax + 1; + vectorInput.ymin = input->ymin - 1; + if (operation->determineDependingAreaOfInterest(&vectorInput, readOperation, output)) { + return true; + } + + /* scale x */ + operation = getInputOperation(2); + if (operation->determineDependingAreaOfInterest(input, readOperation, output)) { + return true; + } + + /* scale y */ + operation = getInputOperation(3); + if (operation->determineDependingAreaOfInterest(input, readOperation, output)) { + return true; + } + + return false; } diff --git a/source/blender/compositor/operations/COM_DisplaceOperation.h b/source/blender/compositor/operations/COM_DisplaceOperation.h index da652975a1d..4e44572fcf2 100644 --- a/source/blender/compositor/operations/COM_DisplaceOperation.h +++ b/source/blender/compositor/operations/COM_DisplaceOperation.h @@ -20,46 +20,48 @@ #define __COM_DISPLACEOPERATION_H__ #include "COM_NodeOperation.h" - class DisplaceOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputColorProgram; - SocketReader *m_inputVectorProgram; - SocketReader *m_inputScaleXProgram; - SocketReader *m_inputScaleYProgram; + private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputColorProgram; + SocketReader *m_inputVectorProgram; + SocketReader *m_inputScaleXProgram; + SocketReader *m_inputScaleYProgram; - float m_width_x4; - float m_height_x4; + float m_width_x4; + float m_height_x4; -public: - DisplaceOperation(); + public: + DisplaceOperation(); - /** - * we need a 2x2 differential filter for Vector Input and full buffer for the image - */ - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + /** + * we need a 2x2 differential filter for Vector Input and full buffer for the image + */ + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - void pixelTransform(const float xy[2], float r_uv[2], float r_deriv[2][2]); + void pixelTransform(const float xy[2], float r_uv[2], float r_deriv[2][2]); - /** - * Initialize the execution - */ - void initExecution(); + /** + * Initialize the execution + */ + void initExecution(); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Deinitialize the execution + */ + void deinitExecution(); -private: - bool read_displacement(float x, float y, float xscale, float yscale, const float origin[2], float &r_u, float &r_v); + private: + bool read_displacement( + float x, float y, float xscale, float yscale, const float origin[2], float &r_u, float &r_v); }; #endif diff --git a/source/blender/compositor/operations/COM_DisplaceSimpleOperation.cpp b/source/blender/compositor/operations/COM_DisplaceSimpleOperation.cpp index e6edbfcf6e0..32eb5679d9d 100644 --- a/source/blender/compositor/operations/COM_DisplaceSimpleOperation.cpp +++ b/source/blender/compositor/operations/COM_DisplaceSimpleOperation.cpp @@ -22,106 +22,110 @@ DisplaceSimpleOperation::DisplaceSimpleOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_VECTOR); - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_COLOR); - - this->m_inputColorProgram = NULL; - this->m_inputVectorProgram = NULL; - this->m_inputScaleXProgram = NULL; - this->m_inputScaleYProgram = NULL; + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VECTOR); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_COLOR); + + this->m_inputColorProgram = NULL; + this->m_inputVectorProgram = NULL; + this->m_inputScaleXProgram = NULL; + this->m_inputScaleYProgram = NULL; } void DisplaceSimpleOperation::initExecution() { - this->m_inputColorProgram = this->getInputSocketReader(0); - this->m_inputVectorProgram = this->getInputSocketReader(1); - this->m_inputScaleXProgram = this->getInputSocketReader(2); - this->m_inputScaleYProgram = this->getInputSocketReader(3); + this->m_inputColorProgram = this->getInputSocketReader(0); + this->m_inputVectorProgram = this->getInputSocketReader(1); + this->m_inputScaleXProgram = this->getInputSocketReader(2); + this->m_inputScaleYProgram = this->getInputSocketReader(3); - this->m_width_x4 = this->getWidth() * 4; - this->m_height_x4 = this->getHeight() * 4; + this->m_width_x4 = this->getWidth() * 4; + this->m_height_x4 = this->getHeight() * 4; } - /* minimum distance (in pixels) a pixel has to be displaced * in order to take effect */ // #define DISPLACE_EPSILON 0.01f -void DisplaceSimpleOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void DisplaceSimpleOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inVector[4]; - float inScale[4]; - - float p_dx, p_dy; /* main displacement in pixel space */ - float u, v; - - this->m_inputScaleXProgram->readSampled(inScale, x, y, sampler); - float xs = inScale[0]; - this->m_inputScaleYProgram->readSampled(inScale, x, y, sampler); - float ys = inScale[0]; - - /* clamp x and y displacement to triple image resolution - - * to prevent hangs from huge values mistakenly plugged in eg. z buffers */ - CLAMP(xs, -this->m_width_x4, this->m_width_x4); - CLAMP(ys, -this->m_height_x4, this->m_height_x4); - - this->m_inputVectorProgram->readSampled(inVector, x, y, sampler); - p_dx = inVector[0] * xs; - p_dy = inVector[1] * ys; - - /* displaced pixel in uv coords, for image sampling */ - /* clamp nodes to avoid glitches */ - u = x - p_dx + 0.5f; - v = y - p_dy + 0.5f; - CLAMP(u, 0.0f, this->getWidth() - 1.0f); - CLAMP(v, 0.0f, this->getHeight() - 1.0f); - - this->m_inputColorProgram->readSampled(output, u, v, sampler); + float inVector[4]; + float inScale[4]; + + float p_dx, p_dy; /* main displacement in pixel space */ + float u, v; + + this->m_inputScaleXProgram->readSampled(inScale, x, y, sampler); + float xs = inScale[0]; + this->m_inputScaleYProgram->readSampled(inScale, x, y, sampler); + float ys = inScale[0]; + + /* clamp x and y displacement to triple image resolution - + * to prevent hangs from huge values mistakenly plugged in eg. z buffers */ + CLAMP(xs, -this->m_width_x4, this->m_width_x4); + CLAMP(ys, -this->m_height_x4, this->m_height_x4); + + this->m_inputVectorProgram->readSampled(inVector, x, y, sampler); + p_dx = inVector[0] * xs; + p_dy = inVector[1] * ys; + + /* displaced pixel in uv coords, for image sampling */ + /* clamp nodes to avoid glitches */ + u = x - p_dx + 0.5f; + v = y - p_dy + 0.5f; + CLAMP(u, 0.0f, this->getWidth() - 1.0f); + CLAMP(v, 0.0f, this->getHeight() - 1.0f); + + this->m_inputColorProgram->readSampled(output, u, v, sampler); } void DisplaceSimpleOperation::deinitExecution() { - this->m_inputColorProgram = NULL; - this->m_inputVectorProgram = NULL; - this->m_inputScaleXProgram = NULL; - this->m_inputScaleYProgram = NULL; + this->m_inputColorProgram = NULL; + this->m_inputVectorProgram = NULL; + this->m_inputScaleXProgram = NULL; + this->m_inputScaleYProgram = NULL; } -bool DisplaceSimpleOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool DisplaceSimpleOperation::determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output) { - rcti colorInput; - NodeOperation *operation = NULL; - - /* the vector buffer only needs a 2x2 buffer. The image needs whole buffer */ - /* image */ - operation = getInputOperation(0); - colorInput.xmax = operation->getWidth(); - colorInput.xmin = 0; - colorInput.ymax = operation->getHeight(); - colorInput.ymin = 0; - if (operation->determineDependingAreaOfInterest(&colorInput, readOperation, output)) { - return true; - } - - /* vector */ - if (operation->determineDependingAreaOfInterest(input, readOperation, output)) { - return true; - } - - /* scale x */ - operation = getInputOperation(2); - if (operation->determineDependingAreaOfInterest(input, readOperation, output) ) { - return true; - } - - /* scale y */ - operation = getInputOperation(3); - if (operation->determineDependingAreaOfInterest(input, readOperation, output) ) { - return true; - } - - return false; + rcti colorInput; + NodeOperation *operation = NULL; + + /* the vector buffer only needs a 2x2 buffer. The image needs whole buffer */ + /* image */ + operation = getInputOperation(0); + colorInput.xmax = operation->getWidth(); + colorInput.xmin = 0; + colorInput.ymax = operation->getHeight(); + colorInput.ymin = 0; + if (operation->determineDependingAreaOfInterest(&colorInput, readOperation, output)) { + return true; + } + + /* vector */ + if (operation->determineDependingAreaOfInterest(input, readOperation, output)) { + return true; + } + + /* scale x */ + operation = getInputOperation(2); + if (operation->determineDependingAreaOfInterest(input, readOperation, output)) { + return true; + } + + /* scale y */ + operation = getInputOperation(3); + if (operation->determineDependingAreaOfInterest(input, readOperation, output)) { + return true; + } + + return false; } diff --git a/source/blender/compositor/operations/COM_DisplaceSimpleOperation.h b/source/blender/compositor/operations/COM_DisplaceSimpleOperation.h index c3e20b4b816..6d4d6047137 100644 --- a/source/blender/compositor/operations/COM_DisplaceSimpleOperation.h +++ b/source/blender/compositor/operations/COM_DisplaceSimpleOperation.h @@ -20,41 +20,42 @@ #define __COM_DISPLACESIMPLEOPERATION_H__ #include "COM_NodeOperation.h" - class DisplaceSimpleOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputColorProgram; - SocketReader *m_inputVectorProgram; - SocketReader *m_inputScaleXProgram; - SocketReader *m_inputScaleYProgram; - - float m_width_x4; - float m_height_x4; - -public: - DisplaceSimpleOperation(); - - /** - * we need a full buffer for the image - */ - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - - /** - * Initialize the execution - */ - void initExecution(); - - /** - * Deinitialize the execution - */ - void deinitExecution(); + private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputColorProgram; + SocketReader *m_inputVectorProgram; + SocketReader *m_inputScaleXProgram; + SocketReader *m_inputScaleYProgram; + + float m_width_x4; + float m_height_x4; + + public: + DisplaceSimpleOperation(); + + /** + * we need a full buffer for the image + */ + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + + /** + * Initialize the execution + */ + void initExecution(); + + /** + * Deinitialize the execution + */ + void deinitExecution(); }; #endif diff --git a/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.cpp b/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.cpp index 98b49022639..ff337455658 100644 --- a/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.cpp +++ b/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.cpp @@ -21,69 +21,72 @@ DistanceRGBMatteOperation::DistanceRGBMatteOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_VALUE); - this->m_inputImageProgram = NULL; - this->m_inputKeyProgram = NULL; + this->m_inputImageProgram = NULL; + this->m_inputKeyProgram = NULL; } void DistanceRGBMatteOperation::initExecution() { - this->m_inputImageProgram = this->getInputSocketReader(0); - this->m_inputKeyProgram = this->getInputSocketReader(1); + this->m_inputImageProgram = this->getInputSocketReader(0); + this->m_inputKeyProgram = this->getInputSocketReader(1); } void DistanceRGBMatteOperation::deinitExecution() { - this->m_inputImageProgram = NULL; - this->m_inputKeyProgram = NULL; + this->m_inputImageProgram = NULL; + this->m_inputKeyProgram = NULL; } float DistanceRGBMatteOperation::calculateDistance(float key[4], float image[4]) { - return len_v3v3(key, image); + return len_v3v3(key, image); } -void DistanceRGBMatteOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void DistanceRGBMatteOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inKey[4]; - float inImage[4]; + float inKey[4]; + float inImage[4]; - const float tolerance = this->m_settings->t1; - const float falloff = this->m_settings->t2; + const float tolerance = this->m_settings->t1; + const float falloff = this->m_settings->t2; - float distance; - float alpha; + float distance; + float alpha; - this->m_inputKeyProgram->readSampled(inKey, x, y, sampler); - this->m_inputImageProgram->readSampled(inImage, x, y, sampler); + this->m_inputKeyProgram->readSampled(inKey, x, y, sampler); + this->m_inputImageProgram->readSampled(inImage, x, y, sampler); - distance = this->calculateDistance(inKey, inImage); + distance = this->calculateDistance(inKey, inImage); - /* store matte(alpha) value in [0] to go with - * COM_SetAlphaOperation and the Value output - */ + /* store matte(alpha) value in [0] to go with + * COM_SetAlphaOperation and the Value output + */ - /*make 100% transparent */ - if (distance < tolerance) { - output[0] = 0.0f; - } - /*in the falloff region, make partially transparent */ - else if (distance < falloff + tolerance) { - distance = distance - tolerance; - alpha = distance / falloff; - /*only change if more transparent than before */ - if (alpha < inImage[3]) { - output[0] = alpha; - } - else { /* leave as before */ - output[0] = inImage[3]; - } - } - else { - /* leave as before */ - output[0] = inImage[3]; - } + /*make 100% transparent */ + if (distance < tolerance) { + output[0] = 0.0f; + } + /*in the falloff region, make partially transparent */ + else if (distance < falloff + tolerance) { + distance = distance - tolerance; + alpha = distance / falloff; + /*only change if more transparent than before */ + if (alpha < inImage[3]) { + output[0] = alpha; + } + else { /* leave as before */ + output[0] = inImage[3]; + } + } + else { + /* leave as before */ + output[0] = inImage[3]; + } } diff --git a/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h b/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h index 418e7fd47d6..c64c6da8d24 100644 --- a/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h +++ b/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h @@ -20,33 +20,35 @@ #define __COM_DISTANCERGBMATTEOPERATION_H__ #include "COM_MixOperation.h" - /** * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ class DistanceRGBMatteOperation : public NodeOperation { -protected: - NodeChroma *m_settings; - SocketReader *m_inputImageProgram; - SocketReader *m_inputKeyProgram; - - virtual float calculateDistance(float key[4], float image[4]); - -public: - /** - * Default constructor - */ - DistanceRGBMatteOperation(); - - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - - void initExecution(); - void deinitExecution(); - - void setSettings(NodeChroma *nodeChroma) { this->m_settings = nodeChroma; } + protected: + NodeChroma *m_settings; + SocketReader *m_inputImageProgram; + SocketReader *m_inputKeyProgram; + + virtual float calculateDistance(float key[4], float image[4]); + + public: + /** + * Default constructor + */ + DistanceRGBMatteOperation(); + + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + + void initExecution(); + void deinitExecution(); + + void setSettings(NodeChroma *nodeChroma) + { + this->m_settings = nodeChroma; + } }; #endif diff --git a/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.cpp b/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.cpp index cc063d27fb5..6ad1a7e440a 100644 --- a/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.cpp +++ b/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.cpp @@ -21,11 +21,11 @@ DistanceYCCMatteOperation::DistanceYCCMatteOperation() : DistanceRGBMatteOperation() { - /* pass */ + /* pass */ } float DistanceYCCMatteOperation::calculateDistance(float key[4], float image[4]) { - /* only measure the second 2 values */ - return len_v2v2(key + 1, image + 1); + /* only measure the second 2 values */ + return len_v2v2(key + 1, image + 1); } diff --git a/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h b/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h index 9c3d9680a1f..48880fb2b59 100644 --- a/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h +++ b/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h @@ -21,20 +21,18 @@ #include "COM_MixOperation.h" #include "COM_DistanceRGBMatteOperation.h" - /** * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ class DistanceYCCMatteOperation : public DistanceRGBMatteOperation { -protected: - virtual float calculateDistance(float key[4], float image[4]); - -public: - /** - * Default constructor - */ - DistanceYCCMatteOperation(); + protected: + virtual float calculateDistance(float key[4], float image[4]); + public: + /** + * Default constructor + */ + DistanceYCCMatteOperation(); }; #endif diff --git a/source/blender/compositor/operations/COM_DotproductOperation.cpp b/source/blender/compositor/operations/COM_DotproductOperation.cpp index 67e1276121f..da6ce510a25 100644 --- a/source/blender/compositor/operations/COM_DotproductOperation.cpp +++ b/source/blender/compositor/operations/COM_DotproductOperation.cpp @@ -20,32 +20,35 @@ DotproductOperation::DotproductOperation() : NodeOperation() { - this->addInputSocket(COM_DT_VECTOR); - this->addInputSocket(COM_DT_VECTOR); - this->addOutputSocket(COM_DT_VALUE); - this->setResolutionInputSocketIndex(0); - this->m_input1Operation = NULL; - this->m_input2Operation = NULL; + this->addInputSocket(COM_DT_VECTOR); + this->addInputSocket(COM_DT_VECTOR); + this->addOutputSocket(COM_DT_VALUE); + this->setResolutionInputSocketIndex(0); + this->m_input1Operation = NULL; + this->m_input2Operation = NULL; } void DotproductOperation::initExecution() { - this->m_input1Operation = this->getInputSocketReader(0); - this->m_input2Operation = this->getInputSocketReader(1); + this->m_input1Operation = this->getInputSocketReader(0); + this->m_input2Operation = this->getInputSocketReader(1); } void DotproductOperation::deinitExecution() { - this->m_input1Operation = NULL; - this->m_input2Operation = NULL; + this->m_input1Operation = NULL; + this->m_input2Operation = NULL; } /** \todo: current implementation is the inverse of a dotproduct. not 'logically' correct */ -void DotproductOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void DotproductOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float input1[4]; - float input2[4]; - this->m_input1Operation->readSampled(input1, x, y, sampler); - this->m_input2Operation->readSampled(input2, x, y, sampler); - output[0] = -(input1[0] * input2[0] + input1[1] * input2[1] + input1[2] * input2[2]); + float input1[4]; + float input2[4]; + this->m_input1Operation->readSampled(input1, x, y, sampler); + this->m_input2Operation->readSampled(input2, x, y, sampler); + output[0] = -(input1[0] * input2[0] + input1[1] * input2[1] + input1[2] * input2[2]); } diff --git a/source/blender/compositor/operations/COM_DotproductOperation.h b/source/blender/compositor/operations/COM_DotproductOperation.h index a568e909f17..9ef9753f4c9 100644 --- a/source/blender/compositor/operations/COM_DotproductOperation.h +++ b/source/blender/compositor/operations/COM_DotproductOperation.h @@ -22,16 +22,16 @@ #include "COM_NodeOperation.h" class DotproductOperation : public NodeOperation { -private: - SocketReader *m_input1Operation; - SocketReader *m_input2Operation; -public: - DotproductOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + private: + SocketReader *m_input1Operation; + SocketReader *m_input2Operation; - void initExecution(); - void deinitExecution(); + public: + DotproductOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void initExecution(); + void deinitExecution(); }; #endif diff --git a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp index 5e514796edb..34f0d2cb760 100644 --- a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp +++ b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp @@ -24,1280 +24,1353 @@ #include "MEM_guardedalloc.h" // this part has been copied from the double edge mask -static void do_adjacentKeepBorders(unsigned int t, unsigned int rw, unsigned int *limask, unsigned int *lomask, unsigned int *lres, float *res, unsigned int *rsize) +static void do_adjacentKeepBorders(unsigned int t, + unsigned int rw, + unsigned int *limask, + unsigned int *lomask, + unsigned int *lres, + float *res, + unsigned int *rsize) { - int x; - unsigned int isz = 0; // inner edge size - unsigned int osz = 0; // outer edge size - unsigned int gsz = 0; // gradient fill area size - /* Test the four corners */ - /* upper left corner */ - x = t - rw + 1; - // test if inner mask is filled - if (limask[x]) { - // test if pixel underneath, or to the right, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x + 1] && lomask[x + 1])) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - /* upper right corner */ - x = t; - // test if inner mask is filled - if (limask[x]) { - // test if pixel underneath, or to the left, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x - 1] && lomask[x - 1])) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - /* lower left corner */ - x = 0; - // test if inner mask is filled - if (limask[x]) { - // test if pixel above, or to the right, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x + rw] && lomask[x + rw]) || (!limask[x + 1] && lomask[x + 1])) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - /* lower right corner */ - x = rw - 1; - // test if inner mask is filled - if (limask[x]) { - // test if pixel above, or to the left, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x + rw] && lomask[x + rw]) || (!limask[x - 1] && lomask[x - 1])) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } + int x; + unsigned int isz = 0; // inner edge size + unsigned int osz = 0; // outer edge size + unsigned int gsz = 0; // gradient fill area size + /* Test the four corners */ + /* upper left corner */ + x = t - rw + 1; + // test if inner mask is filled + if (limask[x]) { + // test if pixel underneath, or to the right, are empty in the inner mask, + // but filled in the outer mask + if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x + 1] && lomask[x + 1])) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + /* upper right corner */ + x = t; + // test if inner mask is filled + if (limask[x]) { + // test if pixel underneath, or to the left, are empty in the inner mask, + // but filled in the outer mask + if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x - 1] && lomask[x - 1])) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + /* lower left corner */ + x = 0; + // test if inner mask is filled + if (limask[x]) { + // test if pixel above, or to the right, are empty in the inner mask, + // but filled in the outer mask + if ((!limask[x + rw] && lomask[x + rw]) || (!limask[x + 1] && lomask[x + 1])) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + /* lower right corner */ + x = rw - 1; + // test if inner mask is filled + if (limask[x]) { + // test if pixel above, or to the left, are empty in the inner mask, + // but filled in the outer mask + if ((!limask[x + rw] && lomask[x + rw]) || (!limask[x - 1] && lomask[x - 1])) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } - /* Test the TOP row of pixels in buffer, except corners */ - for (x = t - 1; x >= (t - rw) + 2; x--) { - // test if inner mask is filled - if (limask[x]) { - // test if pixel to the right, or to the left, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x - 1] && lomask[x - 1]) || (!limask[x + 1] && lomask[x + 1])) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - } + /* Test the TOP row of pixels in buffer, except corners */ + for (x = t - 1; x >= (t - rw) + 2; x--) { + // test if inner mask is filled + if (limask[x]) { + // test if pixel to the right, or to the left, are empty in the inner mask, + // but filled in the outer mask + if ((!limask[x - 1] && lomask[x - 1]) || (!limask[x + 1] && lomask[x + 1])) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + } - /* Test the BOTTOM row of pixels in buffer, except corners */ - for (x = rw - 2; x; x--) { - // test if inner mask is filled - if (limask[x]) { - // test if pixel to the right, or to the left, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x - 1] && lomask[x - 1]) || (!limask[x + 1] && lomask[x + 1])) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - } - /* Test the LEFT edge of pixels in buffer, except corners */ - for (x = t - (rw << 1) + 1; x >= rw; x -= rw) { - // test if inner mask is filled - if (limask[x]) { - // test if pixel underneath, or above, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x + rw] && lomask[x + rw])) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - } + /* Test the BOTTOM row of pixels in buffer, except corners */ + for (x = rw - 2; x; x--) { + // test if inner mask is filled + if (limask[x]) { + // test if pixel to the right, or to the left, are empty in the inner mask, + // but filled in the outer mask + if ((!limask[x - 1] && lomask[x - 1]) || (!limask[x + 1] && lomask[x + 1])) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + } + /* Test the LEFT edge of pixels in buffer, except corners */ + for (x = t - (rw << 1) + 1; x >= rw; x -= rw) { + // test if inner mask is filled + if (limask[x]) { + // test if pixel underneath, or above, are empty in the inner mask, + // but filled in the outer mask + if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x + rw] && lomask[x + rw])) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + } - /* Test the RIGHT edge of pixels in buffer, except corners */ - for (x = t - rw; x > rw; x -= rw) { - // test if inner mask is filled - if (limask[x]) { - // test if pixel underneath, or above, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x + rw] && lomask[x + rw])) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - } + /* Test the RIGHT edge of pixels in buffer, except corners */ + for (x = t - rw; x > rw; x -= rw) { + // test if inner mask is filled + if (limask[x]) { + // test if pixel underneath, or above, are empty in the inner mask, + // but filled in the outer mask + if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x + rw] && lomask[x + rw])) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + } - rsize[0] = isz; // fill in our return sizes for edges + fill - rsize[1] = osz; - rsize[2] = gsz; + rsize[0] = isz; // fill in our return sizes for edges + fill + rsize[1] = osz; + rsize[2] = gsz; } -static void do_adjacentBleedBorders(unsigned int t, unsigned int rw, unsigned int *limask, unsigned int *lomask, unsigned int *lres, float *res, unsigned int *rsize) +static void do_adjacentBleedBorders(unsigned int t, + unsigned int rw, + unsigned int *limask, + unsigned int *lomask, + unsigned int *lres, + float *res, + unsigned int *rsize) { - int x; - unsigned int isz = 0; // inner edge size - unsigned int osz = 0; // outer edge size - unsigned int gsz = 0; // gradient fill area size - /* Test the four corners */ - /* upper left corner */ - x = t - rw + 1; - // test if inner mask is filled - if (limask[x]) { - // test if pixel underneath, or to the right, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x + 1] && lomask[x + 1])) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x - rw] || !lomask[x + 1]) { // test if outer mask is empty underneath or to the right - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x] = 2; // flag pixel as gradient - } - } - /* upper right corner */ - x = t; - // test if inner mask is filled - if (limask[x]) { - // test if pixel underneath, or to the left, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x - 1] && lomask[x - 1])) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x - rw] || !lomask[x - 1]) { // test if outer mask is empty underneath or to the left - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x] = 2; // flag pixel as gradient - } - } - /* lower left corner */ - x = 0; - // test if inner mask is filled - if (limask[x]) { - // test if pixel above, or to the right, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x + rw] && lomask[x + rw]) || (!limask[x + 1] && lomask[x + 1])) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x + rw] || !lomask[x + 1]) { // test if outer mask is empty above or to the right - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x] = 2; // flag pixel as gradient - } - } - /* lower right corner */ - x = rw - 1; - // test if inner mask is filled - if (limask[x]) { - // test if pixel above, or to the left, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x + rw] && lomask[x + rw]) || (!limask[x - 1] && lomask[x - 1])) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x + rw] || !lomask[x - 1]) { // test if outer mask is empty above or to the left - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x] = 2; // flag pixel as gradient - } - } - /* Test the TOP row of pixels in buffer, except corners */ - for (x = t - 1; x >= (t - rw) + 2; x--) { - // test if inner mask is filled - if (limask[x]) { - // test if pixel to the left, or to the right, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x - 1] && lomask[x - 1]) || (!limask[x + 1] && lomask[x + 1])) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x - 1] || !lomask[x + 1]) { // test if outer mask is empty to the left or to the right - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x] = 2; // flag pixel as gradient - } - } - } + int x; + unsigned int isz = 0; // inner edge size + unsigned int osz = 0; // outer edge size + unsigned int gsz = 0; // gradient fill area size + /* Test the four corners */ + /* upper left corner */ + x = t - rw + 1; + // test if inner mask is filled + if (limask[x]) { + // test if pixel underneath, or to the right, are empty in the inner mask, + // but filled in the outer mask + if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x + 1] && lomask[x + 1])) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + if (!lomask[x - rw] || + !lomask[x + 1]) { // test if outer mask is empty underneath or to the right + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + else { + gsz++; // increment the gradient pixel count + lres[x] = 2; // flag pixel as gradient + } + } + /* upper right corner */ + x = t; + // test if inner mask is filled + if (limask[x]) { + // test if pixel underneath, or to the left, are empty in the inner mask, + // but filled in the outer mask + if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x - 1] && lomask[x - 1])) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + if (!lomask[x - rw] || + !lomask[x - 1]) { // test if outer mask is empty underneath or to the left + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + else { + gsz++; // increment the gradient pixel count + lres[x] = 2; // flag pixel as gradient + } + } + /* lower left corner */ + x = 0; + // test if inner mask is filled + if (limask[x]) { + // test if pixel above, or to the right, are empty in the inner mask, + // but filled in the outer mask + if ((!limask[x + rw] && lomask[x + rw]) || (!limask[x + 1] && lomask[x + 1])) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + if (!lomask[x + rw] || !lomask[x + 1]) { // test if outer mask is empty above or to the right + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + else { + gsz++; // increment the gradient pixel count + lres[x] = 2; // flag pixel as gradient + } + } + /* lower right corner */ + x = rw - 1; + // test if inner mask is filled + if (limask[x]) { + // test if pixel above, or to the left, are empty in the inner mask, + // but filled in the outer mask + if ((!limask[x + rw] && lomask[x + rw]) || (!limask[x - 1] && lomask[x - 1])) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + if (!lomask[x + rw] || !lomask[x - 1]) { // test if outer mask is empty above or to the left + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + else { + gsz++; // increment the gradient pixel count + lres[x] = 2; // flag pixel as gradient + } + } + /* Test the TOP row of pixels in buffer, except corners */ + for (x = t - 1; x >= (t - rw) + 2; x--) { + // test if inner mask is filled + if (limask[x]) { + // test if pixel to the left, or to the right, are empty in the inner mask, + // but filled in the outer mask + if ((!limask[x - 1] && lomask[x - 1]) || (!limask[x + 1] && lomask[x + 1])) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + if (!lomask[x - 1] || + !lomask[x + 1]) { // test if outer mask is empty to the left or to the right + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + else { + gsz++; // increment the gradient pixel count + lres[x] = 2; // flag pixel as gradient + } + } + } - /* Test the BOTTOM row of pixels in buffer, except corners */ - for (x = rw - 2; x; x--) { - // test if inner mask is filled - if (limask[x]) { - // test if pixel to the left, or to the right, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x - 1] && lomask[x - 1]) || (!limask[x + 1] && lomask[x + 1])) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x - 1] || !lomask[x + 1]) { // test if outer mask is empty to the left or to the right - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x] = 2; // flag pixel as gradient - } - } - } - /* Test the LEFT edge of pixels in buffer, except corners */ - for (x = t - (rw << 1) + 1; x >= rw; x -= rw) { - // test if inner mask is filled - if (limask[x]) { - // test if pixel underneath, or above, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x + rw] && lomask[x + rw])) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x - rw] || !lomask[x + rw]) { // test if outer mask is empty underneath or above - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x] = 2; // flag pixel as gradient - } - } - } + /* Test the BOTTOM row of pixels in buffer, except corners */ + for (x = rw - 2; x; x--) { + // test if inner mask is filled + if (limask[x]) { + // test if pixel to the left, or to the right, are empty in the inner mask, + // but filled in the outer mask + if ((!limask[x - 1] && lomask[x - 1]) || (!limask[x + 1] && lomask[x + 1])) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + if (!lomask[x - 1] || + !lomask[x + 1]) { // test if outer mask is empty to the left or to the right + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + else { + gsz++; // increment the gradient pixel count + lres[x] = 2; // flag pixel as gradient + } + } + } + /* Test the LEFT edge of pixels in buffer, except corners */ + for (x = t - (rw << 1) + 1; x >= rw; x -= rw) { + // test if inner mask is filled + if (limask[x]) { + // test if pixel underneath, or above, are empty in the inner mask, + // but filled in the outer mask + if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x + rw] && lomask[x + rw])) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + if (!lomask[x - rw] || !lomask[x + rw]) { // test if outer mask is empty underneath or above + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + else { + gsz++; // increment the gradient pixel count + lres[x] = 2; // flag pixel as gradient + } + } + } - /* Test the RIGHT edge of pixels in buffer, except corners */ - for (x = t - rw; x > rw; x -= rw) { - // test if inner mask is filled - if (limask[x]) { - // test if pixel underneath, or above, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x + rw] && lomask[x + rw])) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x - rw] || !lomask[x + rw]) { // test if outer mask is empty underneath or above - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x] = 2; // flag pixel as gradient - } - } - } + /* Test the RIGHT edge of pixels in buffer, except corners */ + for (x = t - rw; x > rw; x -= rw) { + // test if inner mask is filled + if (limask[x]) { + // test if pixel underneath, or above, are empty in the inner mask, + // but filled in the outer mask + if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x + rw] && lomask[x + rw])) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + if (!lomask[x - rw] || !lomask[x + rw]) { // test if outer mask is empty underneath or above + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + else { + gsz++; // increment the gradient pixel count + lres[x] = 2; // flag pixel as gradient + } + } + } - rsize[0] = isz; // fill in our return sizes for edges + fill - rsize[1] = osz; - rsize[2] = gsz; + rsize[0] = isz; // fill in our return sizes for edges + fill + rsize[1] = osz; + rsize[2] = gsz; } -static void do_allKeepBorders(unsigned int t, unsigned int rw, unsigned int *limask, unsigned int *lomask, unsigned int *lres, float *res, unsigned int *rsize) +static void do_allKeepBorders(unsigned int t, + unsigned int rw, + unsigned int *limask, + unsigned int *lomask, + unsigned int *lres, + float *res, + unsigned int *rsize) { - int x; - unsigned int isz = 0; // inner edge size - unsigned int osz = 0; // outer edge size - unsigned int gsz = 0; // gradient fill area size - /* Test the four corners */ - /* upper left corner */ - x = t - rw + 1; - // test if inner mask is filled - if (limask[x]) { - // test if the inner mask is empty underneath or to the right - if (!limask[x - rw] || !limask[x + 1]) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - /* upper right corner */ - x = t; - // test if inner mask is filled - if (limask[x]) { - // test if the inner mask is empty underneath or to the left - if (!limask[x - rw] || !limask[x - 1]) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - /* lower left corner */ - x = 0; - // test if inner mask is filled - if (limask[x]) { - // test if inner mask is empty above or to the right - if (!limask[x + rw] || !limask[x + 1]) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - /* lower right corner */ - x = rw - 1; - // test if inner mask is filled - if (limask[x]) { - // test if inner mask is empty above or to the left - if (!limask[x + rw] || !limask[x - 1]) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } + int x; + unsigned int isz = 0; // inner edge size + unsigned int osz = 0; // outer edge size + unsigned int gsz = 0; // gradient fill area size + /* Test the four corners */ + /* upper left corner */ + x = t - rw + 1; + // test if inner mask is filled + if (limask[x]) { + // test if the inner mask is empty underneath or to the right + if (!limask[x - rw] || !limask[x + 1]) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + /* upper right corner */ + x = t; + // test if inner mask is filled + if (limask[x]) { + // test if the inner mask is empty underneath or to the left + if (!limask[x - rw] || !limask[x - 1]) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + /* lower left corner */ + x = 0; + // test if inner mask is filled + if (limask[x]) { + // test if inner mask is empty above or to the right + if (!limask[x + rw] || !limask[x + 1]) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + /* lower right corner */ + x = rw - 1; + // test if inner mask is filled + if (limask[x]) { + // test if inner mask is empty above or to the left + if (!limask[x + rw] || !limask[x - 1]) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } - /* Test the TOP row of pixels in buffer, except corners */ - for (x = t - 1; x >= (t - rw) + 2; x--) { - // test if inner mask is filled - if (limask[x]) { - // test if inner mask is empty to the left or to the right - if (!limask[x - 1] || !limask[x + 1]) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - } + /* Test the TOP row of pixels in buffer, except corners */ + for (x = t - 1; x >= (t - rw) + 2; x--) { + // test if inner mask is filled + if (limask[x]) { + // test if inner mask is empty to the left or to the right + if (!limask[x - 1] || !limask[x + 1]) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + } - /* Test the BOTTOM row of pixels in buffer, except corners */ - for (x = rw - 2; x; x--) { - // test if inner mask is filled - if (limask[x]) { - // test if inner mask is empty to the left or to the right - if (!limask[x - 1] || !limask[x + 1]) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - } - /* Test the LEFT edge of pixels in buffer, except corners */ - for (x = t - (rw << 1) + 1; x >= rw; x -= rw) { - // test if inner mask is filled - if (limask[x]) { - // test if inner mask is empty underneath or above - if (!limask[x - rw] || !limask[x + rw]) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - } + /* Test the BOTTOM row of pixels in buffer, except corners */ + for (x = rw - 2; x; x--) { + // test if inner mask is filled + if (limask[x]) { + // test if inner mask is empty to the left or to the right + if (!limask[x - 1] || !limask[x + 1]) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + } + /* Test the LEFT edge of pixels in buffer, except corners */ + for (x = t - (rw << 1) + 1; x >= rw; x -= rw) { + // test if inner mask is filled + if (limask[x]) { + // test if inner mask is empty underneath or above + if (!limask[x - rw] || !limask[x + rw]) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + } - /* Test the RIGHT edge of pixels in buffer, except corners */ - for (x = t - rw; x > rw; x -= rw) { - // test if inner mask is filled - if (limask[x]) { - // test if inner mask is empty underneath or above - if (!limask[x - rw] || !limask[x + rw]) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - } + /* Test the RIGHT edge of pixels in buffer, except corners */ + for (x = t - rw; x > rw; x -= rw) { + // test if inner mask is filled + if (limask[x]) { + // test if inner mask is empty underneath or above + if (!limask[x - rw] || !limask[x + rw]) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + } - rsize[0] = isz; // fill in our return sizes for edges + fill - rsize[1] = osz; - rsize[2] = gsz; + rsize[0] = isz; // fill in our return sizes for edges + fill + rsize[1] = osz; + rsize[2] = gsz; } -static void do_allBleedBorders(unsigned int t, unsigned int rw, unsigned int *limask, unsigned int *lomask, unsigned int *lres, float *res, unsigned int *rsize) +static void do_allBleedBorders(unsigned int t, + unsigned int rw, + unsigned int *limask, + unsigned int *lomask, + unsigned int *lres, + float *res, + unsigned int *rsize) { - int x; - unsigned int isz = 0; // inner edge size - unsigned int osz = 0; // outer edge size - unsigned int gsz = 0; // gradient fill area size - /* Test the four corners */ - /* upper left corner */ - x = t - rw + 1; - // test if inner mask is filled - if (limask[x]) { - // test if the inner mask is empty underneath or to the right - if (!limask[x - rw] || !limask[x + 1]) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x - rw] || !lomask[x + 1]) { // test if outer mask is empty underneath or to the right - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x] = 2; // flag pixel as gradient - } - } - /* upper right corner */ - x = t; - // test if inner mask is filled - if (limask[x]) { - // test if the inner mask is empty underneath or to the left - if (!limask[x - rw] || !limask[x - 1]) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x - rw] || !lomask[x - 1]) { // test if outer mask is empty above or to the left - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x] = 2; // flag pixel as gradient - } - } - /* lower left corner */ - x = 0; - // test if inner mask is filled - if (limask[x]) { - // test if inner mask is empty above or to the right - if (!limask[x + rw] || !limask[x + 1]) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x + rw] || !lomask[x + 1]) { // test if outer mask is empty underneath or to the right - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x] = 2; // flag pixel as gradient - } - } - /* lower right corner */ - x = rw - 1; - // test if inner mask is filled - if (limask[x]) { - // test if inner mask is empty above or to the left - if (!limask[x + rw] || !limask[x - 1]) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x + rw] || !lomask[x - 1]) { // test if outer mask is empty underneath or to the left - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x] = 2; // flag pixel as gradient - } - } - /* Test the TOP row of pixels in buffer, except corners */ - for (x = t - 1; x >= (t - rw) + 2; x--) { - // test if inner mask is filled - if (limask[x]) { - // test if inner mask is empty to the left or to the right - if (!limask[x - 1] || !limask[x + 1]) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x - 1] || !lomask[x + 1]) { // test if outer mask is empty to the left or to the right - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x] = 2; // flag pixel as gradient - } - } - } + int x; + unsigned int isz = 0; // inner edge size + unsigned int osz = 0; // outer edge size + unsigned int gsz = 0; // gradient fill area size + /* Test the four corners */ + /* upper left corner */ + x = t - rw + 1; + // test if inner mask is filled + if (limask[x]) { + // test if the inner mask is empty underneath or to the right + if (!limask[x - rw] || !limask[x + 1]) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + if (!lomask[x - rw] || + !lomask[x + 1]) { // test if outer mask is empty underneath or to the right + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + else { + gsz++; // increment the gradient pixel count + lres[x] = 2; // flag pixel as gradient + } + } + /* upper right corner */ + x = t; + // test if inner mask is filled + if (limask[x]) { + // test if the inner mask is empty underneath or to the left + if (!limask[x - rw] || !limask[x - 1]) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + if (!lomask[x - rw] || !lomask[x - 1]) { // test if outer mask is empty above or to the left + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + else { + gsz++; // increment the gradient pixel count + lres[x] = 2; // flag pixel as gradient + } + } + /* lower left corner */ + x = 0; + // test if inner mask is filled + if (limask[x]) { + // test if inner mask is empty above or to the right + if (!limask[x + rw] || !limask[x + 1]) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + if (!lomask[x + rw] || + !lomask[x + 1]) { // test if outer mask is empty underneath or to the right + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + else { + gsz++; // increment the gradient pixel count + lres[x] = 2; // flag pixel as gradient + } + } + /* lower right corner */ + x = rw - 1; + // test if inner mask is filled + if (limask[x]) { + // test if inner mask is empty above or to the left + if (!limask[x + rw] || !limask[x - 1]) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + if (!lomask[x + rw] || + !lomask[x - 1]) { // test if outer mask is empty underneath or to the left + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + else { + gsz++; // increment the gradient pixel count + lres[x] = 2; // flag pixel as gradient + } + } + /* Test the TOP row of pixels in buffer, except corners */ + for (x = t - 1; x >= (t - rw) + 2; x--) { + // test if inner mask is filled + if (limask[x]) { + // test if inner mask is empty to the left or to the right + if (!limask[x - 1] || !limask[x + 1]) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + if (!lomask[x - 1] || + !lomask[x + 1]) { // test if outer mask is empty to the left or to the right + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + else { + gsz++; // increment the gradient pixel count + lres[x] = 2; // flag pixel as gradient + } + } + } - /* Test the BOTTOM row of pixels in buffer, except corners */ - for (x = rw - 2; x; x--) { - // test if inner mask is filled - if (limask[x]) { - // test if inner mask is empty to the left or to the right - if (!limask[x - 1] || !limask[x + 1]) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x - 1] || !lomask[x + 1]) { // test if outer mask is empty to the left or to the right - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x] = 2; // flag pixel as gradient - } - } - } - /* Test the LEFT edge of pixels in buffer, except corners */ - for (x = t - (rw << 1) + 1; x >= rw; x -= rw) { - // test if inner mask is filled - if (limask[x]) { - // test if inner mask is empty underneath or above - if (!limask[x - rw] || !limask[x + rw]) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x - rw] || !lomask[x + rw]) { // test if outer mask is empty underneath or above - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x] = 2; // flag pixel as gradient - } - } - } + /* Test the BOTTOM row of pixels in buffer, except corners */ + for (x = rw - 2; x; x--) { + // test if inner mask is filled + if (limask[x]) { + // test if inner mask is empty to the left or to the right + if (!limask[x - 1] || !limask[x + 1]) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + if (!lomask[x - 1] || + !lomask[x + 1]) { // test if outer mask is empty to the left or to the right + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + else { + gsz++; // increment the gradient pixel count + lres[x] = 2; // flag pixel as gradient + } + } + } + /* Test the LEFT edge of pixels in buffer, except corners */ + for (x = t - (rw << 1) + 1; x >= rw; x -= rw) { + // test if inner mask is filled + if (limask[x]) { + // test if inner mask is empty underneath or above + if (!limask[x - rw] || !limask[x + rw]) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + if (!lomask[x - rw] || !lomask[x + rw]) { // test if outer mask is empty underneath or above + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + else { + gsz++; // increment the gradient pixel count + lres[x] = 2; // flag pixel as gradient + } + } + } - /* Test the RIGHT edge of pixels in buffer, except corners */ - for (x = t - rw; x > rw; x -= rw) { - // test if inner mask is filled - if (limask[x]) { - // test if inner mask is empty underneath or above - if (!limask[x - rw] || !limask[x + rw]) { - isz++; // increment inner edge size - lres[x] = 4; // flag pixel as inner edge - } - else { - res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x - rw] || !lomask[x + rw]) { // test if outer mask is empty underneath or above - osz++; // increment outer edge size - lres[x] = 3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x] = 2; // flag pixel as gradient - } - } - } + /* Test the RIGHT edge of pixels in buffer, except corners */ + for (x = t - rw; x > rw; x -= rw) { + // test if inner mask is filled + if (limask[x]) { + // test if inner mask is empty underneath or above + if (!limask[x - rw] || !limask[x + rw]) { + isz++; // increment inner edge size + lres[x] = 4; // flag pixel as inner edge + } + else { + res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge + } + } + else if (lomask[x]) { // inner mask was empty, test if outer mask is filled + if (!lomask[x - rw] || !lomask[x + rw]) { // test if outer mask is empty underneath or above + osz++; // increment outer edge size + lres[x] = 3; // flag pixel as outer edge + } + else { + gsz++; // increment the gradient pixel count + lres[x] = 2; // flag pixel as gradient + } + } + } - rsize[0] = isz; // fill in our return sizes for edges + fill - rsize[1] = osz; - rsize[2] = gsz; + rsize[0] = isz; // fill in our return sizes for edges + fill + rsize[1] = osz; + rsize[2] = gsz; } -static void do_allEdgeDetection(unsigned int t, unsigned int rw, unsigned int *limask, unsigned int *lomask, unsigned int *lres, float *res, unsigned int *rsize, unsigned int in_isz, unsigned int in_osz, unsigned int in_gsz) +static void do_allEdgeDetection(unsigned int t, + unsigned int rw, + unsigned int *limask, + unsigned int *lomask, + unsigned int *lres, + float *res, + unsigned int *rsize, + unsigned int in_isz, + unsigned int in_osz, + unsigned int in_gsz) { - int x; // x = pixel loop counter - int a; // a = pixel loop counter - int dx; // dx = delta x - int pix_prevRow; // pix_prevRow = pixel one row behind the one we are testing in a loop - int pix_nextRow; // pix_nextRow = pixel one row in front of the one we are testing in a loop - int pix_prevCol; // pix_prevCol = pixel one column behind the one we are testing in a loop - int pix_nextCol; // pix_nextCol = pixel one column in front of the one we are testing in a loop - /* Test all rows between the FIRST and LAST rows, excluding left and right edges */ - for (x = (t - rw) + 1, dx = x - (rw - 2); dx > rw; x -= rw, dx -= rw) { - a = x - 2; - pix_prevRow = a + rw; - pix_nextRow = a - rw; - pix_prevCol = a + 1; - pix_nextCol = a - 1; - while (a > dx - 2) { - if (!limask[a]) { // if the inner mask is empty - if (lomask[a]) { // if the outer mask is full - /* - * Next we test all 4 directions around the current pixel: next/prev/up/down - * The test ensures that the outer mask is empty and that the inner mask - * is also empty. If both conditions are true for any one of the 4 adjacent pixels - * then the current pixel is counted as being a true outer edge pixel. - */ - if ((!lomask[pix_nextCol] && !limask[pix_nextCol]) || - (!lomask[pix_prevCol] && !limask[pix_prevCol]) || - (!lomask[pix_nextRow] && !limask[pix_nextRow]) || - (!lomask[pix_prevRow] && !limask[pix_prevRow])) - { - in_osz++; // increment the outer boundary pixel count - lres[a] = 3; // flag pixel as part of outer edge - } - else { // it's not a boundary pixel, but it is a gradient pixel - in_gsz++; // increment the gradient pixel count - lres[a] = 2; // flag pixel as gradient - } - } + int x; // x = pixel loop counter + int a; // a = pixel loop counter + int dx; // dx = delta x + int pix_prevRow; // pix_prevRow = pixel one row behind the one we are testing in a loop + int pix_nextRow; // pix_nextRow = pixel one row in front of the one we are testing in a loop + int pix_prevCol; // pix_prevCol = pixel one column behind the one we are testing in a loop + int pix_nextCol; // pix_nextCol = pixel one column in front of the one we are testing in a loop + /* Test all rows between the FIRST and LAST rows, excluding left and right edges */ + for (x = (t - rw) + 1, dx = x - (rw - 2); dx > rw; x -= rw, dx -= rw) { + a = x - 2; + pix_prevRow = a + rw; + pix_nextRow = a - rw; + pix_prevCol = a + 1; + pix_nextCol = a - 1; + while (a > dx - 2) { + if (!limask[a]) { // if the inner mask is empty + if (lomask[a]) { // if the outer mask is full + /* + * Next we test all 4 directions around the current pixel: next/prev/up/down + * The test ensures that the outer mask is empty and that the inner mask + * is also empty. If both conditions are true for any one of the 4 adjacent pixels + * then the current pixel is counted as being a true outer edge pixel. + */ + if ((!lomask[pix_nextCol] && !limask[pix_nextCol]) || + (!lomask[pix_prevCol] && !limask[pix_prevCol]) || + (!lomask[pix_nextRow] && !limask[pix_nextRow]) || + (!lomask[pix_prevRow] && !limask[pix_prevRow])) { + in_osz++; // increment the outer boundary pixel count + lres[a] = 3; // flag pixel as part of outer edge + } + else { // it's not a boundary pixel, but it is a gradient pixel + in_gsz++; // increment the gradient pixel count + lres[a] = 2; // flag pixel as gradient + } + } + } + else { + if (!limask[pix_nextCol] || !limask[pix_prevCol] || !limask[pix_nextRow] || + !limask[pix_prevRow]) { + in_isz++; // increment the inner boundary pixel count + lres[a] = 4; // flag pixel as part of inner edge + } + else { + res[a] = 1.0f; // pixel is part of inner mask, but not at an edge + } + } + a--; + pix_prevRow--; + pix_nextRow--; + pix_prevCol--; + pix_nextCol--; + } + } - } - else { - if (!limask[pix_nextCol] || !limask[pix_prevCol] || !limask[pix_nextRow] || !limask[pix_prevRow]) { - in_isz++; // increment the inner boundary pixel count - lres[a] = 4; // flag pixel as part of inner edge - } - else { - res[a] = 1.0f; // pixel is part of inner mask, but not at an edge - } - } - a--; - pix_prevRow--; - pix_nextRow--; - pix_prevCol--; - pix_nextCol--; - } - } - - rsize[0] = in_isz; // fill in our return sizes for edges + fill - rsize[1] = in_osz; - rsize[2] = in_gsz; + rsize[0] = in_isz; // fill in our return sizes for edges + fill + rsize[1] = in_osz; + rsize[2] = in_gsz; } -static void do_adjacentEdgeDetection(unsigned int t, unsigned int rw, unsigned int *limask, unsigned int *lomask, unsigned int *lres, float *res, unsigned int *rsize, unsigned int in_isz, unsigned int in_osz, unsigned int in_gsz) +static void do_adjacentEdgeDetection(unsigned int t, + unsigned int rw, + unsigned int *limask, + unsigned int *lomask, + unsigned int *lres, + float *res, + unsigned int *rsize, + unsigned int in_isz, + unsigned int in_osz, + unsigned int in_gsz) { - int x; // x = pixel loop counter - int a; // a = pixel loop counter - int dx; // dx = delta x - int pix_prevRow; // pix_prevRow = pixel one row behind the one we are testing in a loop - int pix_nextRow; // pix_nextRow = pixel one row in front of the one we are testing in a loop - int pix_prevCol; // pix_prevCol = pixel one column behind the one we are testing in a loop - int pix_nextCol; // pix_nextCol = pixel one column in front of the one we are testing in a loop - /* Test all rows between the FIRST and LAST rows, excluding left and right edges */ - for (x = (t - rw) + 1, dx = x - (rw - 2); dx > rw; x -= rw, dx -= rw) { - a = x - 2; - pix_prevRow = a + rw; - pix_nextRow = a - rw; - pix_prevCol = a + 1; - pix_nextCol = a - 1; - while (a > dx - 2) { - if (!limask[a]) { // if the inner mask is empty - if (lomask[a]) { // if the outer mask is full - /* - * Next we test all 4 directions around the current pixel: next/prev/up/down - * The test ensures that the outer mask is empty and that the inner mask - * is also empty. If both conditions are true for any one of the 4 adjacent pixels - * then the current pixel is counted as being a true outer edge pixel. - */ - if ((!lomask[pix_nextCol] && !limask[pix_nextCol]) || - (!lomask[pix_prevCol] && !limask[pix_prevCol]) || - (!lomask[pix_nextRow] && !limask[pix_nextRow]) || - (!lomask[pix_prevRow] && !limask[pix_prevRow])) - { - in_osz++; // increment the outer boundary pixel count - lres[a] = 3; // flag pixel as part of outer edge - } - else { // it's not a boundary pixel, but it is a gradient pixel - in_gsz++; // increment the gradient pixel count - lres[a] = 2; // flag pixel as gradient - } - } - - } - else { - if ((!limask[pix_nextCol] && lomask[pix_nextCol]) || - (!limask[pix_prevCol] && lomask[pix_prevCol]) || - (!limask[pix_nextRow] && lomask[pix_nextRow]) || - (!limask[pix_prevRow] && lomask[pix_prevRow])) - { - in_isz++; // increment the inner boundary pixel count - lres[a] = 4; // flag pixel as part of inner edge - } - else { - res[a] = 1.0f; // pixel is part of inner mask, but not at an edge - } - } - a--; - pix_prevRow--; // advance all four "surrounding" pixel pointers - pix_nextRow--; - pix_prevCol--; - pix_nextCol--; - } - } + int x; // x = pixel loop counter + int a; // a = pixel loop counter + int dx; // dx = delta x + int pix_prevRow; // pix_prevRow = pixel one row behind the one we are testing in a loop + int pix_nextRow; // pix_nextRow = pixel one row in front of the one we are testing in a loop + int pix_prevCol; // pix_prevCol = pixel one column behind the one we are testing in a loop + int pix_nextCol; // pix_nextCol = pixel one column in front of the one we are testing in a loop + /* Test all rows between the FIRST and LAST rows, excluding left and right edges */ + for (x = (t - rw) + 1, dx = x - (rw - 2); dx > rw; x -= rw, dx -= rw) { + a = x - 2; + pix_prevRow = a + rw; + pix_nextRow = a - rw; + pix_prevCol = a + 1; + pix_nextCol = a - 1; + while (a > dx - 2) { + if (!limask[a]) { // if the inner mask is empty + if (lomask[a]) { // if the outer mask is full + /* + * Next we test all 4 directions around the current pixel: next/prev/up/down + * The test ensures that the outer mask is empty and that the inner mask + * is also empty. If both conditions are true for any one of the 4 adjacent pixels + * then the current pixel is counted as being a true outer edge pixel. + */ + if ((!lomask[pix_nextCol] && !limask[pix_nextCol]) || + (!lomask[pix_prevCol] && !limask[pix_prevCol]) || + (!lomask[pix_nextRow] && !limask[pix_nextRow]) || + (!lomask[pix_prevRow] && !limask[pix_prevRow])) { + in_osz++; // increment the outer boundary pixel count + lres[a] = 3; // flag pixel as part of outer edge + } + else { // it's not a boundary pixel, but it is a gradient pixel + in_gsz++; // increment the gradient pixel count + lres[a] = 2; // flag pixel as gradient + } + } + } + else { + if ((!limask[pix_nextCol] && lomask[pix_nextCol]) || + (!limask[pix_prevCol] && lomask[pix_prevCol]) || + (!limask[pix_nextRow] && lomask[pix_nextRow]) || + (!limask[pix_prevRow] && lomask[pix_prevRow])) { + in_isz++; // increment the inner boundary pixel count + lres[a] = 4; // flag pixel as part of inner edge + } + else { + res[a] = 1.0f; // pixel is part of inner mask, but not at an edge + } + } + a--; + pix_prevRow--; // advance all four "surrounding" pixel pointers + pix_nextRow--; + pix_prevCol--; + pix_nextCol--; + } + } - rsize[0] = in_isz; // fill in our return sizes for edges + fill - rsize[1] = in_osz; - rsize[2] = in_gsz; + rsize[0] = in_isz; // fill in our return sizes for edges + fill + rsize[1] = in_osz; + rsize[2] = in_gsz; } -static void do_createEdgeLocationBuffer(unsigned int t, unsigned int rw, unsigned int *lres, float *res, unsigned short *gbuf, unsigned int *innerEdgeOffset, unsigned int *outerEdgeOffset, unsigned int isz, unsigned int gsz) +static void do_createEdgeLocationBuffer(unsigned int t, + unsigned int rw, + unsigned int *lres, + float *res, + unsigned short *gbuf, + unsigned int *innerEdgeOffset, + unsigned int *outerEdgeOffset, + unsigned int isz, + unsigned int gsz) { - int x; // x = pixel loop counter - int a; // a = temporary pixel index buffer loop counter - unsigned int ud; // ud = unscaled edge distance - unsigned int dmin; // dmin = minimum edge distance - - unsigned int rsl; // long used for finding fast 1.0/sqrt - unsigned int gradientFillOffset; - unsigned int innerAccum = 0; // for looping inner edge pixel indexes, represents current position from offset - unsigned int outerAccum = 0; // for looping outer edge pixel indexes, represents current position from offset - unsigned int gradientAccum = 0; // for looping gradient pixel indexes, represents current position from offset - /* - * Here we compute the size of buffer needed to hold (row,col) coordinates - * for each pixel previously determined to be either gradient, inner edge, - * or outer edge. - * - * Allocation is done by requesting 4 bytes "sizeof(int)" per pixel, even - * though gbuf[] is declared as (unsigned short *) (2 bytes) because we don't - * store the pixel indexes, we only store x,y location of pixel in buffer. - * - * This does make the assumption that x and y can fit in 16 unsigned bits - * so if Blender starts doing renders greater than 65536 in either direction - * this will need to allocate gbuf[] as unsigned int *and allocate 8 bytes - * per flagged pixel. - * - * In general, the buffer on-screen: - * - * Example: 9 by 9 pixel block - * - * . = pixel non-white in both outer and inner mask - * o = pixel white in outer, but not inner mask, adjacent to "." pixel - * g = pixel white in outer, but not inner mask, not adjacent to "." pixel - * i = pixel white in inner mask, adjacent to "g" or "." pixel - * F = pixel white in inner mask, only adjacent to other pixels white in the inner mask - * - * - * ......... <----- pixel #80 - * ..oooo... - * .oggggo.. - * .oggiggo. - * .ogiFigo. - * .oggiggo. - * .oggggo.. - * ..oooo... - * pixel #00 -----> ......... - * - * gsz = 18 (18 "g" pixels above) - * isz = 4 (4 "i" pixels above) - * osz = 18 (18 "o" pixels above) - * - * - * The memory in gbuf[] after filling will look like this: - * - * gradientFillOffset (0 pixels) innerEdgeOffset (18 pixels) outerEdgeOffset (22 pixels) - * / / / - * / / / - * |X Y X Y X Y X Y > <X Y X Y > <X Y X Y X Y > <X Y X Y | <- (x,y) - * +--------------------------------> <----------------> <------------------------> <----------------+ - * |0 2 4 6 8 10 12 14 > ... <68 70 72 74 > ... <80 82 84 86 88 90 > ... <152 154 156 158 | <- bytes - * +--------------------------------> <----------------> <------------------------> <----------------+ - * |g0 g0 g1 g1 g2 g2 g3 g3 > <g17 g17 i0 i0 > <i2 i2 i3 i3 o0 o0 > <o16 o16 o17 o17 | <- pixel - * / / / - * / / / - * / / / - * +---------- gradientAccum (18) ---------+ +--- innerAccum (22) ---+ +--- outerAccum (40) ---+ - * - * - * Ultimately we do need the pixel's memory buffer index to set the output - * pixel color, but it's faster to reconstruct the memory buffer location - * each iteration of the final gradient calculation than it is to deconstruct - * a memory location into x,y pairs each round. - */ + int x; // x = pixel loop counter + int a; // a = temporary pixel index buffer loop counter + unsigned int ud; // ud = unscaled edge distance + unsigned int dmin; // dmin = minimum edge distance + unsigned int rsl; // long used for finding fast 1.0/sqrt + unsigned int gradientFillOffset; + unsigned int innerAccum = + 0; // for looping inner edge pixel indexes, represents current position from offset + unsigned int outerAccum = + 0; // for looping outer edge pixel indexes, represents current position from offset + unsigned int gradientAccum = + 0; // for looping gradient pixel indexes, represents current position from offset + /* + * Here we compute the size of buffer needed to hold (row,col) coordinates + * for each pixel previously determined to be either gradient, inner edge, + * or outer edge. + * + * Allocation is done by requesting 4 bytes "sizeof(int)" per pixel, even + * though gbuf[] is declared as (unsigned short *) (2 bytes) because we don't + * store the pixel indexes, we only store x,y location of pixel in buffer. + * + * This does make the assumption that x and y can fit in 16 unsigned bits + * so if Blender starts doing renders greater than 65536 in either direction + * this will need to allocate gbuf[] as unsigned int *and allocate 8 bytes + * per flagged pixel. + * + * In general, the buffer on-screen: + * + * Example: 9 by 9 pixel block + * + * . = pixel non-white in both outer and inner mask + * o = pixel white in outer, but not inner mask, adjacent to "." pixel + * g = pixel white in outer, but not inner mask, not adjacent to "." pixel + * i = pixel white in inner mask, adjacent to "g" or "." pixel + * F = pixel white in inner mask, only adjacent to other pixels white in the inner mask + * + * + * ......... <----- pixel #80 + * ..oooo... + * .oggggo.. + * .oggiggo. + * .ogiFigo. + * .oggiggo. + * .oggggo.. + * ..oooo... + * pixel #00 -----> ......... + * + * gsz = 18 (18 "g" pixels above) + * isz = 4 (4 "i" pixels above) + * osz = 18 (18 "o" pixels above) + * + * + * The memory in gbuf[] after filling will look like this: + * + * gradientFillOffset (0 pixels) innerEdgeOffset (18 pixels) outerEdgeOffset (22 pixels) + * / / / + * / / / + * |X Y X Y X Y X Y > <X Y X Y > <X Y X Y X Y > <X Y X Y | <- (x,y) + * +--------------------------------> <----------------> <------------------------> <----------------+ + * |0 2 4 6 8 10 12 14 > ... <68 70 72 74 > ... <80 82 84 86 88 90 > ... <152 154 156 158 | <- bytes + * +--------------------------------> <----------------> <------------------------> <----------------+ + * |g0 g0 g1 g1 g2 g2 g3 g3 > <g17 g17 i0 i0 > <i2 i2 i3 i3 o0 o0 > <o16 o16 o17 o17 | <- pixel + * / / / + * / / / + * / / / + * +---------- gradientAccum (18) ---------+ +--- innerAccum (22) ---+ +--- outerAccum (40) ---+ + * + * + * Ultimately we do need the pixel's memory buffer index to set the output + * pixel color, but it's faster to reconstruct the memory buffer location + * each iteration of the final gradient calculation than it is to deconstruct + * a memory location into x,y pairs each round. + */ - gradientFillOffset = 0; // since there are likely "more" of these, put it first. :) - *innerEdgeOffset = gradientFillOffset + gsz; // set start of inner edge indexes - *outerEdgeOffset = (*innerEdgeOffset) + isz; // set start of outer edge indexes - /* set the accumulators to correct positions */ // set up some accumulator variables for loops - gradientAccum = gradientFillOffset; // each accumulator variable starts at its respective - innerAccum = *innerEdgeOffset; // section's offset so when we start filling, each - outerAccum = *outerEdgeOffset; // section fills up it's allocated space in gbuf - //uses dmin=row, rsl=col - for (x = 0, dmin = 0; x < t; x += rw, dmin++) { - for (rsl = 0; rsl < rw; rsl++) { - a = x + rsl; - if (lres[a] == 2) { // it is a gradient pixel flagged by 2 - ud = gradientAccum << 1; // double the index to reach correct unsigned short location - gbuf[ud] = dmin; // insert pixel's row into gradient pixel location buffer - gbuf[ud + 1] = rsl; // insert pixel's column into gradient pixel location buffer - gradientAccum++; // increment gradient index buffer pointer - } - else if (lres[a] == 3) { // it is an outer edge pixel flagged by 3 - ud = outerAccum << 1; // double the index to reach correct unsigned short location - gbuf[ud] = dmin; // insert pixel's row into outer edge pixel location buffer - gbuf[ud + 1] = rsl; // insert pixel's column into outer edge pixel location buffer - outerAccum++; // increment outer edge index buffer pointer - res[a] = 0.0f; // set output pixel intensity now since it won't change later - } - else if (lres[a] == 4) { // it is an inner edge pixel flagged by 4 - ud = innerAccum << 1; // double int index to reach correct unsigned short location - gbuf[ud] = dmin; // insert pixel's row into inner edge pixel location buffer - gbuf[ud + 1] = rsl; // insert pixel's column into inner edge pixel location buffer - innerAccum++; // increment inner edge index buffer pointer - res[a] = 1.0f; // set output pixel intensity now since it won't change later - } - } - } - + gradientFillOffset = 0; // since there are likely "more" of these, put it first. :) + *innerEdgeOffset = gradientFillOffset + gsz; // set start of inner edge indexes + *outerEdgeOffset = (*innerEdgeOffset) + isz; // set start of outer edge indexes + /* set the accumulators to correct positions */ // set up some accumulator variables for loops + gradientAccum = gradientFillOffset; // each accumulator variable starts at its respective + innerAccum = *innerEdgeOffset; // section's offset so when we start filling, each + outerAccum = *outerEdgeOffset; // section fills up it's allocated space in gbuf + //uses dmin=row, rsl=col + for (x = 0, dmin = 0; x < t; x += rw, dmin++) { + for (rsl = 0; rsl < rw; rsl++) { + a = x + rsl; + if (lres[a] == 2) { // it is a gradient pixel flagged by 2 + ud = gradientAccum << 1; // double the index to reach correct unsigned short location + gbuf[ud] = dmin; // insert pixel's row into gradient pixel location buffer + gbuf[ud + 1] = rsl; // insert pixel's column into gradient pixel location buffer + gradientAccum++; // increment gradient index buffer pointer + } + else if (lres[a] == 3) { // it is an outer edge pixel flagged by 3 + ud = outerAccum << 1; // double the index to reach correct unsigned short location + gbuf[ud] = dmin; // insert pixel's row into outer edge pixel location buffer + gbuf[ud + 1] = rsl; // insert pixel's column into outer edge pixel location buffer + outerAccum++; // increment outer edge index buffer pointer + res[a] = 0.0f; // set output pixel intensity now since it won't change later + } + else if (lres[a] == 4) { // it is an inner edge pixel flagged by 4 + ud = innerAccum << 1; // double int index to reach correct unsigned short location + gbuf[ud] = dmin; // insert pixel's row into inner edge pixel location buffer + gbuf[ud + 1] = rsl; // insert pixel's column into inner edge pixel location buffer + innerAccum++; // increment inner edge index buffer pointer + res[a] = 1.0f; // set output pixel intensity now since it won't change later + } + } + } } -static void do_fillGradientBuffer(unsigned int rw, float *res, unsigned short *gbuf, unsigned int isz, unsigned int osz, unsigned int gsz, unsigned int innerEdgeOffset, unsigned int outerEdgeOffset) +static void do_fillGradientBuffer(unsigned int rw, + float *res, + unsigned short *gbuf, + unsigned int isz, + unsigned int osz, + unsigned int gsz, + unsigned int innerEdgeOffset, + unsigned int outerEdgeOffset) { - int x; // x = pixel loop counter - int a; // a = temporary pixel index buffer loop counter - int fsz; // size of the frame - unsigned int rsl; // long used for finding fast 1.0/sqrt - float rsf; // float used for finding fast 1.0/sqrt - const float rsopf = 1.5f; // constant float used for finding fast 1.0/sqrt - - unsigned int gradientFillOffset; - unsigned int t; - unsigned int ud; // ud = unscaled edge distance - unsigned int dmin; // dmin = minimum edge distance - float odist; // odist = current outer edge distance - float idist; // idist = current inner edge distance - int dx; // dx = X-delta (used for distance proportion calculation) - int dy; // dy = Y-delta (used for distance proportion calculation) + int x; // x = pixel loop counter + int a; // a = temporary pixel index buffer loop counter + int fsz; // size of the frame + unsigned int rsl; // long used for finding fast 1.0/sqrt + float rsf; // float used for finding fast 1.0/sqrt + const float rsopf = 1.5f; // constant float used for finding fast 1.0/sqrt - /* - * The general algorithm used to color each gradient pixel is: - * - * 1.) Loop through all gradient pixels. - * A.) For each gradient pixel: - * a.) Loop though all outside edge pixels, looking for closest one - * to the gradient pixel we are in. - * b.) Loop through all inside edge pixels, looking for closest one - * to the gradient pixel we are in. - * c.) Find proportion of distance from gradient pixel to inside edge - * pixel compared to sum of distance to inside edge and distance to - * outside edge. - * - * In an image where: - * . = blank (black) pixels, not covered by inner mask or outer mask - * + = desired gradient pixels, covered only by outer mask - * * = white full mask pixels, covered by at least inner mask - * - * ............................... - * ...............+++++++++++..... - * ...+O++++++..++++++++++++++.... - * ..+++\++++++++++++++++++++..... - * .+++++G+++++++++*******+++..... - * .+++++|+++++++*********+++..... - * .++***I****************+++..... - * .++*******************+++...... - * .+++*****************+++....... - * ..+++***************+++........ - * ....+++**********+++........... - * ......++++++++++++............. - * ............................... - * - * O = outside edge pixel - * \ - * G = gradient pixel - * | - * I = inside edge pixel - * - * __ - * *note that IO does not need to be a straight line, in fact - * many cases can arise where straight lines do not work - * correctly. - * - * __ __ __ - * d.) Pixel color is assigned as |GO| / ( |GI| + |GO| ) - * - * The implementation does not compute distance, but the reciprocal of the - * distance. This is done to avoid having to compute a square root, as a - * reciprocal square root can be computed faster. Therefore, the code computes - * pixel color as |GI| / (|GI| + |GO|). Since these are reciprocals, GI serves the - * purpose of GO for the proportion calculation. - * - * For the purposes of the minimum distance comparisons, we only check - * the sums-of-squares against eachother, since they are in the same - * mathematical sort-order as if we did go ahead and take square roots - * - * Loop through all gradient pixels. - */ + unsigned int gradientFillOffset; + unsigned int t; + unsigned int ud; // ud = unscaled edge distance + unsigned int dmin; // dmin = minimum edge distance + float odist; // odist = current outer edge distance + float idist; // idist = current inner edge distance + int dx; // dx = X-delta (used for distance proportion calculation) + int dy; // dy = Y-delta (used for distance proportion calculation) - for (x = gsz - 1; x >= 0; x--) { - gradientFillOffset = x << 1; - t = gbuf[gradientFillOffset]; // calculate column of pixel indexed by gbuf[x] - fsz = gbuf[gradientFillOffset + 1]; // calculate row of pixel indexed by gbuf[x] - dmin = 0xffffffff; // reset min distance to edge pixel - for (a = outerEdgeOffset + osz - 1; a >= outerEdgeOffset; a--) { // loop through all outer edge buffer pixels - ud = a << 1; - dy = t - gbuf[ud]; // set dx to gradient pixel column - outer edge pixel row - dx = fsz - gbuf[ud + 1]; // set dy to gradient pixel row - outer edge pixel column - ud = dx * dx + dy * dy; // compute sum of squares - if (ud < dmin) { // if our new sum of squares is less than the current minimum - dmin = ud; // set a new minimum equal to the new lower value - } - } - odist = (float)(dmin); // cast outer min to a float - rsf = odist * 0.5f; // - rsl = *(unsigned int *)&odist; // use some peculiar properties of the way bits are stored - rsl = 0x5f3759df - (rsl >> 1); // in floats vs. unsigned ints to compute an approximate - odist = *(float *)&rsl; // reciprocal square root - odist = odist * (rsopf - (rsf * odist * odist)); // -- ** this line can be iterated for more accuracy ** -- - dmin = 0xffffffff; // reset min distance to edge pixel - for (a = innerEdgeOffset + isz - 1; a >= innerEdgeOffset; a--) { // loop through all inside edge pixels - ud = a << 1; - dy = t - gbuf[ud]; // compute delta in Y from gradient pixel to inside edge pixel - dx = fsz - gbuf[ud + 1]; // compute delta in X from gradient pixel to inside edge pixel - ud = dx * dx + dy * dy; // compute sum of squares - if (ud < dmin) { // if our new sum of squares is less than the current minimum we've found - dmin = ud; // set a new minimum equal to the new lower value - } - } - idist = (float)(dmin); // cast inner min to a float - rsf = idist * 0.5f; // - rsl = *(unsigned int *)&idist; // - rsl = 0x5f3759df - (rsl >> 1); // see notes above - idist = *(float *)&rsl; // - idist = idist * (rsopf - (rsf * idist * idist)); // - /* - * Note once again that since we are using reciprocals of distance values our - * proportion is already the correct intensity, and does not need to be - * subtracted from 1.0 like it would have if we used real distances. - */ + /* + * The general algorithm used to color each gradient pixel is: + * + * 1.) Loop through all gradient pixels. + * A.) For each gradient pixel: + * a.) Loop though all outside edge pixels, looking for closest one + * to the gradient pixel we are in. + * b.) Loop through all inside edge pixels, looking for closest one + * to the gradient pixel we are in. + * c.) Find proportion of distance from gradient pixel to inside edge + * pixel compared to sum of distance to inside edge and distance to + * outside edge. + * + * In an image where: + * . = blank (black) pixels, not covered by inner mask or outer mask + * + = desired gradient pixels, covered only by outer mask + * * = white full mask pixels, covered by at least inner mask + * + * ............................... + * ...............+++++++++++..... + * ...+O++++++..++++++++++++++.... + * ..+++\++++++++++++++++++++..... + * .+++++G+++++++++*******+++..... + * .+++++|+++++++*********+++..... + * .++***I****************+++..... + * .++*******************+++...... + * .+++*****************+++....... + * ..+++***************+++........ + * ....+++**********+++........... + * ......++++++++++++............. + * ............................... + * + * O = outside edge pixel + * \ + * G = gradient pixel + * | + * I = inside edge pixel + * + * __ + * *note that IO does not need to be a straight line, in fact + * many cases can arise where straight lines do not work + * correctly. + * + * __ __ __ + * d.) Pixel color is assigned as |GO| / ( |GI| + |GO| ) + * + * The implementation does not compute distance, but the reciprocal of the + * distance. This is done to avoid having to compute a square root, as a + * reciprocal square root can be computed faster. Therefore, the code computes + * pixel color as |GI| / (|GI| + |GO|). Since these are reciprocals, GI serves the + * purpose of GO for the proportion calculation. + * + * For the purposes of the minimum distance comparisons, we only check + * the sums-of-squares against eachother, since they are in the same + * mathematical sort-order as if we did go ahead and take square roots + * + * Loop through all gradient pixels. + */ - /* - * Here we reconstruct the pixel's memory location in the CompBuf by - * Pixel Index = Pixel Column + ( Pixel Row * Row Width ) - */ - res[gbuf[gradientFillOffset + 1] + (gbuf[gradientFillOffset] * rw)] = (idist / (idist + odist)); //set intensity - } + for (x = gsz - 1; x >= 0; x--) { + gradientFillOffset = x << 1; + t = gbuf[gradientFillOffset]; // calculate column of pixel indexed by gbuf[x] + fsz = gbuf[gradientFillOffset + 1]; // calculate row of pixel indexed by gbuf[x] + dmin = 0xffffffff; // reset min distance to edge pixel + for (a = outerEdgeOffset + osz - 1; a >= outerEdgeOffset; + a--) { // loop through all outer edge buffer pixels + ud = a << 1; + dy = t - gbuf[ud]; // set dx to gradient pixel column - outer edge pixel row + dx = fsz - gbuf[ud + 1]; // set dy to gradient pixel row - outer edge pixel column + ud = dx * dx + dy * dy; // compute sum of squares + if (ud < dmin) { // if our new sum of squares is less than the current minimum + dmin = ud; // set a new minimum equal to the new lower value + } + } + odist = (float)(dmin); // cast outer min to a float + rsf = odist * 0.5f; // + rsl = *(unsigned int *)&odist; // use some peculiar properties of the way bits are stored + rsl = 0x5f3759df - (rsl >> 1); // in floats vs. unsigned ints to compute an approximate + odist = *(float *)&rsl; // reciprocal square root + odist = odist * (rsopf - (rsf * odist * + odist)); // -- ** this line can be iterated for more accuracy ** -- + dmin = 0xffffffff; // reset min distance to edge pixel + for (a = innerEdgeOffset + isz - 1; a >= innerEdgeOffset; + a--) { // loop through all inside edge pixels + ud = a << 1; + dy = t - gbuf[ud]; // compute delta in Y from gradient pixel to inside edge pixel + dx = fsz - gbuf[ud + 1]; // compute delta in X from gradient pixel to inside edge pixel + ud = dx * dx + dy * dy; // compute sum of squares + if (ud < dmin) { // if our new sum of squares is less than the current minimum we've found + dmin = ud; // set a new minimum equal to the new lower value + } + } + idist = (float)(dmin); // cast inner min to a float + rsf = idist * 0.5f; // + rsl = *(unsigned int *)&idist; // + rsl = 0x5f3759df - (rsl >> 1); // see notes above + idist = *(float *)&rsl; // + idist = idist * (rsopf - (rsf * idist * idist)); // + /* + * Note once again that since we are using reciprocals of distance values our + * proportion is already the correct intensity, and does not need to be + * subtracted from 1.0 like it would have if we used real distances. + */ + /* + * Here we reconstruct the pixel's memory location in the CompBuf by + * Pixel Index = Pixel Column + ( Pixel Row * Row Width ) + */ + res[gbuf[gradientFillOffset + 1] + (gbuf[gradientFillOffset] * rw)] = + (idist / (idist + odist)); //set intensity + } } // end of copy void DoubleEdgeMaskOperation::doDoubleEdgeMask(float *imask, float *omask, float *res) { - unsigned int *lres; // lres = unsigned int pointer to output pixel buffer (for bit operations) - unsigned int *limask; // limask = unsigned int pointer to inner mask (for bit operations) - unsigned int *lomask; // lomask = unsigned int pointer to outer mask (for bit operations) - - int rw; // rw = pixel row width - int t; // t = total number of pixels in buffer - 1 (used for loop starts) - int fsz; // size of the frame + unsigned int *lres; // lres = unsigned int pointer to output pixel buffer (for bit operations) + unsigned int *limask; // limask = unsigned int pointer to inner mask (for bit operations) + unsigned int *lomask; // lomask = unsigned int pointer to outer mask (for bit operations) - unsigned int isz = 0; // size (in pixels) of inside edge pixel index buffer - unsigned int osz = 0; // size (in pixels) of outside edge pixel index buffer - unsigned int gsz = 0; // size (in pixels) of gradient pixel index buffer - unsigned int rsize[3]; // size storage to pass to helper functions - unsigned int innerEdgeOffset = 0; // offset into final buffer where inner edge pixel indexes start - unsigned int outerEdgeOffset = 0; // offset into final buffer where outer edge pixel indexes start + int rw; // rw = pixel row width + int t; // t = total number of pixels in buffer - 1 (used for loop starts) + int fsz; // size of the frame - unsigned short *gbuf; // gradient/inner/outer pixel location index buffer + unsigned int isz = 0; // size (in pixels) of inside edge pixel index buffer + unsigned int osz = 0; // size (in pixels) of outside edge pixel index buffer + unsigned int gsz = 0; // size (in pixels) of gradient pixel index buffer + unsigned int rsize[3]; // size storage to pass to helper functions + unsigned int innerEdgeOffset = + 0; // offset into final buffer where inner edge pixel indexes start + unsigned int outerEdgeOffset = + 0; // offset into final buffer where outer edge pixel indexes start - if (true) { // if both input sockets have some data coming in... + unsigned short *gbuf; // gradient/inner/outer pixel location index buffer - rw = this->getWidth(); // width of a row of pixels - t = (rw * this->getHeight()) - 1; // determine size of the frame - memset(res, 0, sizeof(float) * (t + 1)); // clear output buffer (not all pixels will be written later) + if (true) { // if both input sockets have some data coming in... - lres = (unsigned int *)res; // unsigned int pointer to output buffer (for bit level ops) - limask = (unsigned int *)imask; // unsigned int pointer to input mask (for bit level ops) - lomask = (unsigned int *)omask; // unsigned int pointer to output mask (for bit level ops) + rw = this->getWidth(); // width of a row of pixels + t = (rw * this->getHeight()) - 1; // determine size of the frame + memset(res, + 0, + sizeof(float) * (t + 1)); // clear output buffer (not all pixels will be written later) + lres = (unsigned int *)res; // unsigned int pointer to output buffer (for bit level ops) + limask = (unsigned int *)imask; // unsigned int pointer to input mask (for bit level ops) + lomask = (unsigned int *)omask; // unsigned int pointer to output mask (for bit level ops) - /* - * The whole buffer is broken up into 4 parts. The four CORNERS, the FIRST and LAST rows, the - * LEFT and RIGHT edges (excluding the corner pixels), and all OTHER rows. - * This allows for quick computation of outer edge pixels where - * a screen edge pixel is marked to be gradient. - * - * The pixel type (gradient vs inner-edge vs outer-edge) tests change - * depending on the user selected "Inner Edge Mode" and the user selected - * "Buffer Edge Mode" on the node's GUI. There are 4 sets of basically the - * same algorithm: - * - * 1.) Inner Edge -> Adjacent Only - * Buffer Edge -> Keep Inside - * - * 2.) Inner Edge -> Adjacent Only - * Buffer Edge -> Bleed Out - * - * 3.) Inner Edge -> All - * Buffer Edge -> Keep Inside - * - * 4.) Inner Edge -> All - * Buffer Edge -> Bleed Out - * - * Each version has slightly different criteria for detecting an edge pixel. - */ - if (this->m_adjecentOnly) { // if "adjacent only" inner edge mode is turned on - if (this->m_keepInside) { // if "keep inside" buffer edge mode is turned on - do_adjacentKeepBorders(t, rw, limask, lomask, lres, res, rsize); - } - else { // "bleed out" buffer edge mode is turned on - do_adjacentBleedBorders(t, rw, limask, lomask, lres, res, rsize); - } - // set up inner edge, outer edge, and gradient buffer sizes after border pass - isz = rsize[0]; - osz = rsize[1]; - gsz = rsize[2]; - // detect edges in all non-border pixels in the buffer - do_adjacentEdgeDetection(t, rw, limask, lomask, lres, res, rsize, isz, osz, gsz); - } - else { // "all" inner edge mode is turned on - if (this->m_keepInside) { // if "keep inside" buffer edge mode is turned on - do_allKeepBorders(t, rw, limask, lomask, lres, res, rsize); - } - else { // "bleed out" buffer edge mode is turned on - do_allBleedBorders(t, rw, limask, lomask, lres, res, rsize); - } - // set up inner edge, outer edge, and gradient buffer sizes after border pass - isz = rsize[0]; - osz = rsize[1]; - gsz = rsize[2]; - // detect edges in all non-border pixels in the buffer - do_allEdgeDetection(t, rw, limask, lomask, lres, res, rsize, isz, osz, gsz); - } + /* + * The whole buffer is broken up into 4 parts. The four CORNERS, the FIRST and LAST rows, the + * LEFT and RIGHT edges (excluding the corner pixels), and all OTHER rows. + * This allows for quick computation of outer edge pixels where + * a screen edge pixel is marked to be gradient. + * + * The pixel type (gradient vs inner-edge vs outer-edge) tests change + * depending on the user selected "Inner Edge Mode" and the user selected + * "Buffer Edge Mode" on the node's GUI. There are 4 sets of basically the + * same algorithm: + * + * 1.) Inner Edge -> Adjacent Only + * Buffer Edge -> Keep Inside + * + * 2.) Inner Edge -> Adjacent Only + * Buffer Edge -> Bleed Out + * + * 3.) Inner Edge -> All + * Buffer Edge -> Keep Inside + * + * 4.) Inner Edge -> All + * Buffer Edge -> Bleed Out + * + * Each version has slightly different criteria for detecting an edge pixel. + */ + if (this->m_adjecentOnly) { // if "adjacent only" inner edge mode is turned on + if (this->m_keepInside) { // if "keep inside" buffer edge mode is turned on + do_adjacentKeepBorders(t, rw, limask, lomask, lres, res, rsize); + } + else { // "bleed out" buffer edge mode is turned on + do_adjacentBleedBorders(t, rw, limask, lomask, lres, res, rsize); + } + // set up inner edge, outer edge, and gradient buffer sizes after border pass + isz = rsize[0]; + osz = rsize[1]; + gsz = rsize[2]; + // detect edges in all non-border pixels in the buffer + do_adjacentEdgeDetection(t, rw, limask, lomask, lres, res, rsize, isz, osz, gsz); + } + else { // "all" inner edge mode is turned on + if (this->m_keepInside) { // if "keep inside" buffer edge mode is turned on + do_allKeepBorders(t, rw, limask, lomask, lres, res, rsize); + } + else { // "bleed out" buffer edge mode is turned on + do_allBleedBorders(t, rw, limask, lomask, lres, res, rsize); + } + // set up inner edge, outer edge, and gradient buffer sizes after border pass + isz = rsize[0]; + osz = rsize[1]; + gsz = rsize[2]; + // detect edges in all non-border pixels in the buffer + do_allEdgeDetection(t, rw, limask, lomask, lres, res, rsize, isz, osz, gsz); + } - // set edge and gradient buffer sizes once again... - // the sizes in rsize[] may have been modified - // by the do_*EdgeDetection() function. - isz = rsize[0]; - osz = rsize[1]; - gsz = rsize[2]; + // set edge and gradient buffer sizes once again... + // the sizes in rsize[] may have been modified + // by the do_*EdgeDetection() function. + isz = rsize[0]; + osz = rsize[1]; + gsz = rsize[2]; - // calculate size of pixel index buffer needed - fsz = gsz + isz + osz; - // allocate edge/gradient pixel index buffer - gbuf = (unsigned short *)MEM_callocN(sizeof(unsigned short) * fsz * 2, "DEM"); + // calculate size of pixel index buffer needed + fsz = gsz + isz + osz; + // allocate edge/gradient pixel index buffer + gbuf = (unsigned short *)MEM_callocN(sizeof(unsigned short) * fsz * 2, "DEM"); - do_createEdgeLocationBuffer(t, rw, lres, res, gbuf, &innerEdgeOffset, &outerEdgeOffset, isz, gsz); - do_fillGradientBuffer(rw, res, gbuf, isz, osz, gsz, innerEdgeOffset, outerEdgeOffset); + do_createEdgeLocationBuffer( + t, rw, lres, res, gbuf, &innerEdgeOffset, &outerEdgeOffset, isz, gsz); + do_fillGradientBuffer(rw, res, gbuf, isz, osz, gsz, innerEdgeOffset, outerEdgeOffset); - // free the gradient index buffer - MEM_freeN(gbuf); - } + // free the gradient index buffer + MEM_freeN(gbuf); + } } DoubleEdgeMaskOperation::DoubleEdgeMaskOperation() : NodeOperation() { - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_VALUE); - this->m_inputInnerMask = NULL; - this->m_inputOuterMask = NULL; - this->m_adjecentOnly = false; - this->m_keepInside = false; - this->setComplex(true); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_VALUE); + this->m_inputInnerMask = NULL; + this->m_inputOuterMask = NULL; + this->m_adjecentOnly = false; + this->m_keepInside = false; + this->setComplex(true); } -bool DoubleEdgeMaskOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output) +bool DoubleEdgeMaskOperation::determineDependingAreaOfInterest(rcti * /*input*/, + ReadBufferOperation *readOperation, + rcti *output) { - if (this->m_cachedInstance == NULL) { - rcti newInput; - newInput.xmax = this->getWidth(); - newInput.xmin = 0; - newInput.ymax = this->getHeight(); - newInput.ymin = 0; - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); - } - else { - return false; - } + if (this->m_cachedInstance == NULL) { + rcti newInput; + newInput.xmax = this->getWidth(); + newInput.xmin = 0; + newInput.ymax = this->getHeight(); + newInput.ymin = 0; + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + } + else { + return false; + } } void DoubleEdgeMaskOperation::initExecution() { - this->m_inputInnerMask = this->getInputSocketReader(0); - this->m_inputOuterMask = this->getInputSocketReader(1); - initMutex(); - this->m_cachedInstance = NULL; + this->m_inputInnerMask = this->getInputSocketReader(0); + this->m_inputOuterMask = this->getInputSocketReader(1); + initMutex(); + this->m_cachedInstance = NULL; } void *DoubleEdgeMaskOperation::initializeTileData(rcti *rect) { - if (this->m_cachedInstance) - return this->m_cachedInstance; + if (this->m_cachedInstance) + return this->m_cachedInstance; - lockMutex(); - if (this->m_cachedInstance == NULL) { - MemoryBuffer *innerMask = (MemoryBuffer *)this->m_inputInnerMask->initializeTileData(rect); - MemoryBuffer *outerMask = (MemoryBuffer *)this->m_inputOuterMask->initializeTileData(rect); - float *data = (float *)MEM_mallocN(sizeof(float) * this->getWidth() * this->getHeight(), __func__); - float *imask = innerMask->getBuffer(); - float *omask = outerMask->getBuffer(); - doDoubleEdgeMask(imask, omask, data); - this->m_cachedInstance = data; - } - unlockMutex(); - return this->m_cachedInstance; + lockMutex(); + if (this->m_cachedInstance == NULL) { + MemoryBuffer *innerMask = (MemoryBuffer *)this->m_inputInnerMask->initializeTileData(rect); + MemoryBuffer *outerMask = (MemoryBuffer *)this->m_inputOuterMask->initializeTileData(rect); + float *data = (float *)MEM_mallocN(sizeof(float) * this->getWidth() * this->getHeight(), + __func__); + float *imask = innerMask->getBuffer(); + float *omask = outerMask->getBuffer(); + doDoubleEdgeMask(imask, omask, data); + this->m_cachedInstance = data; + } + unlockMutex(); + return this->m_cachedInstance; } void DoubleEdgeMaskOperation::executePixel(float output[4], int x, int y, void *data) { - float *buffer = (float *)data; - int index = (y * this->getWidth() + x); - output[0] = buffer[index]; + float *buffer = (float *)data; + int index = (y * this->getWidth() + x); + output[0] = buffer[index]; } void DoubleEdgeMaskOperation::deinitExecution() { - this->m_inputInnerMask = NULL; - this->m_inputOuterMask = NULL; - deinitMutex(); - if (this->m_cachedInstance) { - MEM_freeN(this->m_cachedInstance); - this->m_cachedInstance = NULL; - } + this->m_inputInnerMask = NULL; + this->m_inputOuterMask = NULL; + deinitMutex(); + if (this->m_cachedInstance) { + MEM_freeN(this->m_cachedInstance); + this->m_cachedInstance = NULL; + } } diff --git a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.h b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.h index 2bb3761805b..40cfa370cb7 100644 --- a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.h +++ b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.h @@ -20,41 +20,49 @@ #define __COM_DOUBLEEDGEMASKOPERATION_H__ #include "COM_NodeOperation.h" - class DoubleEdgeMaskOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputOuterMask; - SocketReader *m_inputInnerMask; - bool m_adjecentOnly; - bool m_keepInside; - float *m_cachedInstance; -public: - DoubleEdgeMaskOperation(); - - void doDoubleEdgeMask(float *inner, float *outer, float *res); - /** - * the inner loop of this program - */ - void executePixel(float output[4], int x, int y, void *data); - - /** - * Initialize the execution - */ - void initExecution(); - - /** - * Deinitialize the execution - */ - void deinitExecution(); - - void *initializeTileData(rcti *rect); - - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - - void setAdjecentOnly(bool adjecentOnly) { this->m_adjecentOnly = adjecentOnly; } - void setKeepInside(bool keepInside) { this->m_keepInside = keepInside; } + private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputOuterMask; + SocketReader *m_inputInnerMask; + bool m_adjecentOnly; + bool m_keepInside; + float *m_cachedInstance; + + public: + DoubleEdgeMaskOperation(); + + void doDoubleEdgeMask(float *inner, float *outer, float *res); + /** + * the inner loop of this program + */ + void executePixel(float output[4], int x, int y, void *data); + + /** + * Initialize the execution + */ + void initExecution(); + + /** + * Deinitialize the execution + */ + void deinitExecution(); + + void *initializeTileData(rcti *rect); + + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + + void setAdjecentOnly(bool adjecentOnly) + { + this->m_adjecentOnly = adjecentOnly; + } + void setKeepInside(bool keepInside) + { + this->m_keepInside = keepInside; + } }; #endif diff --git a/source/blender/compositor/operations/COM_EllipseMaskOperation.cpp b/source/blender/compositor/operations/COM_EllipseMaskOperation.cpp index d7c0339c0d1..0dc42b3457f 100644 --- a/source/blender/compositor/operations/COM_EllipseMaskOperation.cpp +++ b/source/blender/compositor/operations/COM_EllipseMaskOperation.cpp @@ -22,95 +22,98 @@ EllipseMaskOperation::EllipseMaskOperation() : NodeOperation() { - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_VALUE); - this->m_inputMask = NULL; - this->m_inputValue = NULL; - this->m_cosine = 0.0f; - this->m_sine = 0.0f; + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_VALUE); + this->m_inputMask = NULL; + this->m_inputValue = NULL; + this->m_cosine = 0.0f; + this->m_sine = 0.0f; } void EllipseMaskOperation::initExecution() { - this->m_inputMask = this->getInputSocketReader(0); - this->m_inputValue = this->getInputSocketReader(1); - const double rad = (double)this->m_data->rotation; - this->m_cosine = cos(rad); - this->m_sine = sin(rad); - this->m_aspectRatio = ((float)this->getWidth()) / this->getHeight(); + this->m_inputMask = this->getInputSocketReader(0); + this->m_inputValue = this->getInputSocketReader(1); + const double rad = (double)this->m_data->rotation; + this->m_cosine = cos(rad); + this->m_sine = sin(rad); + this->m_aspectRatio = ((float)this->getWidth()) / this->getHeight(); } -void EllipseMaskOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void EllipseMaskOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputMask[4]; - float inputValue[4]; + float inputMask[4]; + float inputValue[4]; - float rx = x / this->getWidth(); - float ry = y / this->getHeight(); + float rx = x / this->getWidth(); + float ry = y / this->getHeight(); - const float dy = (ry - this->m_data->y) / this->m_aspectRatio; - const float dx = rx - this->m_data->x; - rx = this->m_data->x + (this->m_cosine * dx + this->m_sine * dy); - ry = this->m_data->y + (-this->m_sine * dx + this->m_cosine * dy); + const float dy = (ry - this->m_data->y) / this->m_aspectRatio; + const float dx = rx - this->m_data->x; + rx = this->m_data->x + (this->m_cosine * dx + this->m_sine * dy); + ry = this->m_data->y + (-this->m_sine * dx + this->m_cosine * dy); - this->m_inputMask->readSampled(inputMask, x, y, sampler); - this->m_inputValue->readSampled(inputValue, x, y, sampler); + this->m_inputMask->readSampled(inputMask, x, y, sampler); + this->m_inputValue->readSampled(inputValue, x, y, sampler); - const float halfHeight = (this->m_data->height) / 2.0f; - const float halfWidth = this->m_data->width / 2.0f; - float sx = rx - this->m_data->x; - sx *= sx; - const float tx = halfWidth * halfWidth; - float sy = ry - this->m_data->y; - sy *= sy; - const float ty = halfHeight * halfHeight; + const float halfHeight = (this->m_data->height) / 2.0f; + const float halfWidth = this->m_data->width / 2.0f; + float sx = rx - this->m_data->x; + sx *= sx; + const float tx = halfWidth * halfWidth; + float sy = ry - this->m_data->y; + sy *= sy; + const float ty = halfHeight * halfHeight; - bool inside = ((sx / tx) + (sy / ty)) < 1.0f; + bool inside = ((sx / tx) + (sy / ty)) < 1.0f; - switch (this->m_maskType) { - case CMP_NODE_MASKTYPE_ADD: - if (inside) { - output[0] = max(inputMask[0], inputValue[0]); - } - else { - output[0] = inputMask[0]; - } - break; - case CMP_NODE_MASKTYPE_SUBTRACT: - if (inside) { - output[0] = inputMask[0] - inputValue[0]; - CLAMP(output[0], 0, 1); - } - else { - output[0] = inputMask[0]; - } - break; - case CMP_NODE_MASKTYPE_MULTIPLY: - if (inside) { - output[0] = inputMask[0] * inputValue[0]; - } - else { - output[0] = 0; - } - break; - case CMP_NODE_MASKTYPE_NOT: - if (inside) { - if (inputMask[0] > 0.0f) { - output[0] = 0; - } - else { - output[0] = inputValue[0]; - } - } - else { - output[0] = inputMask[0]; - } - break; - } + switch (this->m_maskType) { + case CMP_NODE_MASKTYPE_ADD: + if (inside) { + output[0] = max(inputMask[0], inputValue[0]); + } + else { + output[0] = inputMask[0]; + } + break; + case CMP_NODE_MASKTYPE_SUBTRACT: + if (inside) { + output[0] = inputMask[0] - inputValue[0]; + CLAMP(output[0], 0, 1); + } + else { + output[0] = inputMask[0]; + } + break; + case CMP_NODE_MASKTYPE_MULTIPLY: + if (inside) { + output[0] = inputMask[0] * inputValue[0]; + } + else { + output[0] = 0; + } + break; + case CMP_NODE_MASKTYPE_NOT: + if (inside) { + if (inputMask[0] > 0.0f) { + output[0] = 0; + } + else { + output[0] = inputValue[0]; + } + } + else { + output[0] = inputMask[0]; + } + break; + } } void EllipseMaskOperation::deinitExecution() { - this->m_inputMask = NULL; - this->m_inputValue = NULL; + this->m_inputMask = NULL; + this->m_inputValue = NULL; } diff --git a/source/blender/compositor/operations/COM_EllipseMaskOperation.h b/source/blender/compositor/operations/COM_EllipseMaskOperation.h index 6f5b6e3e25d..b73a35a5452 100644 --- a/source/blender/compositor/operations/COM_EllipseMaskOperation.h +++ b/source/blender/compositor/operations/COM_EllipseMaskOperation.h @@ -20,42 +20,47 @@ #define __COM_ELLIPSEMASKOPERATION_H__ #include "COM_NodeOperation.h" - class EllipseMaskOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputMask; - SocketReader *m_inputValue; + private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputMask; + SocketReader *m_inputValue; - float m_sine; - float m_cosine; - float m_aspectRatio; - int m_maskType; + float m_sine; + float m_cosine; + float m_aspectRatio; + int m_maskType; - NodeEllipseMask *m_data; -public: - EllipseMaskOperation(); + NodeEllipseMask *m_data; - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + EllipseMaskOperation(); - /** - * Initialize the execution - */ - void initExecution(); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Initialize the execution + */ + void initExecution(); - void setData(NodeEllipseMask *data) { this->m_data = data; } + /** + * Deinitialize the execution + */ + void deinitExecution(); - void setMaskType(int maskType) { this->m_maskType = maskType; } + void setData(NodeEllipseMask *data) + { + this->m_data = data; + } + void setMaskType(int maskType) + { + this->m_maskType = maskType; + } }; #endif 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; } diff --git a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.h b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.h index b31e88a545d..22f9a6f9cf2 100644 --- a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.h +++ b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.h @@ -23,50 +23,62 @@ #include "DNA_node_types.h" class FastGaussianBlurOperation : public BlurBaseOperation { -private: - float m_sx; - float m_sy; - MemoryBuffer *m_iirgaus; -public: - FastGaussianBlurOperation(); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - void executePixel(float output[4], int x, int y, void *data); + private: + float m_sx; + float m_sy; + MemoryBuffer *m_iirgaus; - static void IIR_gauss(MemoryBuffer *src, float sigma, unsigned int channel, unsigned int xy); - void *initializeTileData(rcti *rect); - void deinitExecution(); - void initExecution(); + public: + FastGaussianBlurOperation(); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + void executePixel(float output[4], int x, int y, void *data); + + static void IIR_gauss(MemoryBuffer *src, float sigma, unsigned int channel, unsigned int xy); + void *initializeTileData(rcti *rect); + void deinitExecution(); + void initExecution(); }; enum { - FAST_GAUSS_OVERLAY_MIN = -1, - FAST_GAUSS_OVERLAY_NONE = 0, - FAST_GAUSS_OVERLAY_MAX = 1, + FAST_GAUSS_OVERLAY_MIN = -1, + FAST_GAUSS_OVERLAY_NONE = 0, + FAST_GAUSS_OVERLAY_MAX = 1, }; class FastGaussianBlurValueOperation : public NodeOperation { -private: - float m_sigma; - MemoryBuffer *m_iirgaus; - SocketReader *m_inputprogram; + private: + float m_sigma; + MemoryBuffer *m_iirgaus; + SocketReader *m_inputprogram; + + /** + * -1: re-mix with darker + * 0: do nothing + * 1 re-mix with lighter */ + int m_overlay; - /** - * -1: re-mix with darker - * 0: do nothing - * 1 re-mix with lighter */ - int m_overlay; -public: - FastGaussianBlurValueOperation(); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - void executePixel(float output[4], int x, int y, void *data); + public: + FastGaussianBlurValueOperation(); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + void executePixel(float output[4], int x, int y, void *data); - void *initializeTileData(rcti *rect); - void deinitExecution(); - void initExecution(); - void setSigma(float sigma) { this->m_sigma = sigma; } + void *initializeTileData(rcti *rect); + void deinitExecution(); + void initExecution(); + void setSigma(float sigma) + { + this->m_sigma = sigma; + } - /* used for DOF blurring ZBuffer */ - void setOverlay(int overlay) { this->m_overlay = overlay; } + /* used for DOF blurring ZBuffer */ + void setOverlay(int overlay) + { + this->m_overlay = overlay; + } }; #endif diff --git a/source/blender/compositor/operations/COM_FlipOperation.cpp b/source/blender/compositor/operations/COM_FlipOperation.cpp index 913704bdfc0..57b686986b7 100644 --- a/source/blender/compositor/operations/COM_FlipOperation.cpp +++ b/source/blender/compositor/operations/COM_FlipOperation.cpp @@ -20,54 +20,55 @@ FlipOperation::FlipOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - this->setResolutionInputSocketIndex(0); - this->m_inputOperation = NULL; - this->m_flipX = true; - this->m_flipY = false; + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); + this->setResolutionInputSocketIndex(0); + this->m_inputOperation = NULL; + this->m_flipX = true; + this->m_flipY = false; } void FlipOperation::initExecution() { - this->m_inputOperation = this->getInputSocketReader(0); + this->m_inputOperation = this->getInputSocketReader(0); } void FlipOperation::deinitExecution() { - this->m_inputOperation = NULL; + this->m_inputOperation = NULL; } - void FlipOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { - float nx = this->m_flipX ? ((int)this->getWidth() - 1) - x : x; - float ny = this->m_flipY ? ((int)this->getHeight() - 1) - y : y; + float nx = this->m_flipX ? ((int)this->getWidth() - 1) - x : x; + float ny = this->m_flipY ? ((int)this->getHeight() - 1) - y : y; - this->m_inputOperation->readSampled(output, nx, ny, sampler); + this->m_inputOperation->readSampled(output, nx, ny, sampler); } -bool FlipOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool FlipOperation::determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output) { - rcti newInput; + rcti newInput; - if (this->m_flipX) { - const int w = (int)this->getWidth() - 1; - newInput.xmax = (w - input->xmin) + 1; - newInput.xmin = (w - input->xmax) - 1; - } - else { - newInput.xmin = input->xmin; - newInput.xmax = input->xmax; - } - if (this->m_flipY) { - const int h = (int)this->getHeight() - 1; - newInput.ymax = (h - input->ymin) + 1; - newInput.ymin = (h - input->ymax) - 1; - } - else { - newInput.ymin = input->ymin; - newInput.ymax = input->ymax; - } + if (this->m_flipX) { + const int w = (int)this->getWidth() - 1; + newInput.xmax = (w - input->xmin) + 1; + newInput.xmin = (w - input->xmax) - 1; + } + else { + newInput.xmin = input->xmin; + newInput.xmax = input->xmax; + } + if (this->m_flipY) { + const int h = (int)this->getHeight() - 1; + newInput.ymax = (h - input->ymin) + 1; + newInput.ymin = (h - input->ymax) - 1; + } + else { + newInput.ymin = input->ymin; + newInput.ymax = input->ymax; + } - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } diff --git a/source/blender/compositor/operations/COM_FlipOperation.h b/source/blender/compositor/operations/COM_FlipOperation.h index 1564daf5469..2d00c50dc8a 100644 --- a/source/blender/compositor/operations/COM_FlipOperation.h +++ b/source/blender/compositor/operations/COM_FlipOperation.h @@ -22,19 +22,28 @@ #include "COM_NodeOperation.h" class FlipOperation : public NodeOperation { -private: - SocketReader *m_inputOperation; - bool m_flipX; - bool m_flipY; -public: - FlipOperation(); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + private: + SocketReader *m_inputOperation; + bool m_flipX; + bool m_flipY; - void initExecution(); - void deinitExecution(); - void setFlipX(bool flipX) { this->m_flipX = flipX; } - void setFlipY(bool flipY) { this->m_flipY = flipY; } + public: + FlipOperation(); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + + void initExecution(); + void deinitExecution(); + void setFlipX(bool flipX) + { + this->m_flipX = flipX; + } + void setFlipY(bool flipY) + { + this->m_flipY = flipY; + } }; #endif diff --git a/source/blender/compositor/operations/COM_GammaCorrectOperation.cpp b/source/blender/compositor/operations/COM_GammaCorrectOperation.cpp index 8828553b4fd..36272c05774 100644 --- a/source/blender/compositor/operations/COM_GammaCorrectOperation.cpp +++ b/source/blender/compositor/operations/COM_GammaCorrectOperation.cpp @@ -21,78 +21,84 @@ GammaCorrectOperation::GammaCorrectOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - this->m_inputProgram = NULL; + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); + this->m_inputProgram = NULL; } void GammaCorrectOperation::initExecution() { - this->m_inputProgram = this->getInputSocketReader(0); + this->m_inputProgram = this->getInputSocketReader(0); } -void GammaCorrectOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void GammaCorrectOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor[4]; - this->m_inputProgram->readSampled(inputColor, x, y, sampler); - if (inputColor[3] > 0.0f) { - inputColor[0] /= inputColor[3]; - inputColor[1] /= inputColor[3]; - inputColor[2] /= inputColor[3]; - } + float inputColor[4]; + this->m_inputProgram->readSampled(inputColor, x, y, sampler); + if (inputColor[3] > 0.0f) { + inputColor[0] /= inputColor[3]; + inputColor[1] /= inputColor[3]; + inputColor[2] /= inputColor[3]; + } - /* check for negative to avoid nan's */ - output[0] = inputColor[0] > 0.0f ? inputColor[0] * inputColor[0] : 0.0f; - output[1] = inputColor[1] > 0.0f ? inputColor[1] * inputColor[1] : 0.0f; - output[2] = inputColor[2] > 0.0f ? inputColor[2] * inputColor[2] : 0.0f; - output[3] = inputColor[3]; + /* check for negative to avoid nan's */ + output[0] = inputColor[0] > 0.0f ? inputColor[0] * inputColor[0] : 0.0f; + output[1] = inputColor[1] > 0.0f ? inputColor[1] * inputColor[1] : 0.0f; + output[2] = inputColor[2] > 0.0f ? inputColor[2] * inputColor[2] : 0.0f; + output[3] = inputColor[3]; - if (inputColor[3] > 0.0f) { - output[0] *= inputColor[3]; - output[1] *= inputColor[3]; - output[2] *= inputColor[3]; - } + if (inputColor[3] > 0.0f) { + output[0] *= inputColor[3]; + output[1] *= inputColor[3]; + output[2] *= inputColor[3]; + } } void GammaCorrectOperation::deinitExecution() { - this->m_inputProgram = NULL; + this->m_inputProgram = NULL; } GammaUncorrectOperation::GammaUncorrectOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - this->m_inputProgram = NULL; + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); + this->m_inputProgram = NULL; } void GammaUncorrectOperation::initExecution() { - this->m_inputProgram = this->getInputSocketReader(0); + this->m_inputProgram = this->getInputSocketReader(0); } -void GammaUncorrectOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void GammaUncorrectOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor[4]; - this->m_inputProgram->readSampled(inputColor, x, y, sampler); + float inputColor[4]; + this->m_inputProgram->readSampled(inputColor, x, y, sampler); - if (inputColor[3] > 0.0f) { - inputColor[0] /= inputColor[3]; - inputColor[1] /= inputColor[3]; - inputColor[2] /= inputColor[3]; - } + if (inputColor[3] > 0.0f) { + inputColor[0] /= inputColor[3]; + inputColor[1] /= inputColor[3]; + inputColor[2] /= inputColor[3]; + } - output[0] = inputColor[0] > 0.0f ? sqrtf(inputColor[0]) : 0.0f; - output[1] = inputColor[1] > 0.0f ? sqrtf(inputColor[1]) : 0.0f; - output[2] = inputColor[2] > 0.0f ? sqrtf(inputColor[2]) : 0.0f; - output[3] = inputColor[3]; + output[0] = inputColor[0] > 0.0f ? sqrtf(inputColor[0]) : 0.0f; + output[1] = inputColor[1] > 0.0f ? sqrtf(inputColor[1]) : 0.0f; + output[2] = inputColor[2] > 0.0f ? sqrtf(inputColor[2]) : 0.0f; + output[3] = inputColor[3]; - if (inputColor[3] > 0.0f) { - output[0] *= inputColor[3]; - output[1] *= inputColor[3]; - output[2] *= inputColor[3]; - } + if (inputColor[3] > 0.0f) { + output[0] *= inputColor[3]; + output[1] *= inputColor[3]; + output[2] *= inputColor[3]; + } } void GammaUncorrectOperation::deinitExecution() { - this->m_inputProgram = NULL; + this->m_inputProgram = NULL; } diff --git a/source/blender/compositor/operations/COM_GammaCorrectOperation.h b/source/blender/compositor/operations/COM_GammaCorrectOperation.h index f982a3f7b18..26e31df880f 100644 --- a/source/blender/compositor/operations/COM_GammaCorrectOperation.h +++ b/source/blender/compositor/operations/COM_GammaCorrectOperation.h @@ -20,57 +20,56 @@ #define __COM_GAMMACORRECTOPERATION_H__ #include "COM_NodeOperation.h" - class GammaCorrectOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputProgram; + private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputProgram; -public: - GammaCorrectOperation(); + public: + GammaCorrectOperation(); - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - /** - * Initialize the execution - */ - void initExecution(); + /** + * Initialize the execution + */ + void initExecution(); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Deinitialize the execution + */ + void deinitExecution(); }; class GammaUncorrectOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputProgram; + private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputProgram; -public: - GammaUncorrectOperation(); + public: + GammaUncorrectOperation(); - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - /** - * Initialize the execution - */ - void initExecution(); + /** + * Initialize the execution + */ + void initExecution(); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Deinitialize the execution + */ + void deinitExecution(); }; #endif diff --git a/source/blender/compositor/operations/COM_GammaOperation.cpp b/source/blender/compositor/operations/COM_GammaOperation.cpp index 614daebfed6..ee6b42c349f 100644 --- a/source/blender/compositor/operations/COM_GammaOperation.cpp +++ b/source/blender/compositor/operations/COM_GammaOperation.cpp @@ -21,36 +21,36 @@ GammaOperation::GammaOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_COLOR); - this->m_inputProgram = NULL; - this->m_inputGammaProgram = NULL; + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_COLOR); + this->m_inputProgram = NULL; + this->m_inputGammaProgram = NULL; } void GammaOperation::initExecution() { - this->m_inputProgram = this->getInputSocketReader(0); - this->m_inputGammaProgram = this->getInputSocketReader(1); + this->m_inputProgram = this->getInputSocketReader(0); + this->m_inputGammaProgram = this->getInputSocketReader(1); } void GammaOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { - float inputValue[4]; - float inputGamma[4]; + float inputValue[4]; + float inputGamma[4]; - this->m_inputProgram->readSampled(inputValue, x, y, sampler); - this->m_inputGammaProgram->readSampled(inputGamma, x, y, sampler); - const float gamma = inputGamma[0]; - /* check for negative to avoid nan's */ - output[0] = inputValue[0] > 0.0f ? powf(inputValue[0], gamma) : inputValue[0]; - output[1] = inputValue[1] > 0.0f ? powf(inputValue[1], gamma) : inputValue[1]; - output[2] = inputValue[2] > 0.0f ? powf(inputValue[2], gamma) : inputValue[2]; + this->m_inputProgram->readSampled(inputValue, x, y, sampler); + this->m_inputGammaProgram->readSampled(inputGamma, x, y, sampler); + const float gamma = inputGamma[0]; + /* check for negative to avoid nan's */ + output[0] = inputValue[0] > 0.0f ? powf(inputValue[0], gamma) : inputValue[0]; + output[1] = inputValue[1] > 0.0f ? powf(inputValue[1], gamma) : inputValue[1]; + output[2] = inputValue[2] > 0.0f ? powf(inputValue[2], gamma) : inputValue[2]; - output[3] = inputValue[3]; + output[3] = inputValue[3]; } void GammaOperation::deinitExecution() { - this->m_inputProgram = NULL; - this->m_inputGammaProgram = NULL; + this->m_inputProgram = NULL; + this->m_inputGammaProgram = NULL; } diff --git a/source/blender/compositor/operations/COM_GammaOperation.h b/source/blender/compositor/operations/COM_GammaOperation.h index 0ec96cfccee..ba0b84db931 100644 --- a/source/blender/compositor/operations/COM_GammaOperation.h +++ b/source/blender/compositor/operations/COM_GammaOperation.h @@ -20,31 +20,30 @@ #define __COM_GAMMAOPERATION_H__ #include "COM_NodeOperation.h" - class GammaOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputProgram; - SocketReader *m_inputGammaProgram; + private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputProgram; + SocketReader *m_inputGammaProgram; -public: - GammaOperation(); + public: + GammaOperation(); - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - /** - * Initialize the execution - */ - void initExecution(); + /** + * Initialize the execution + */ + void initExecution(); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Deinitialize the execution + */ + void deinitExecution(); }; #endif diff --git a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp index f9a548e1498..c6239dba604 100644 --- a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp @@ -21,168 +21,171 @@ #include "MEM_guardedalloc.h" extern "C" { -# include "RE_pipeline.h" +#include "RE_pipeline.h" } GaussianAlphaXBlurOperation::GaussianAlphaXBlurOperation() : BlurBaseOperation(COM_DT_VALUE) { - this->m_gausstab = NULL; - this->m_filtersize = 0; - this->m_falloff = -1; /* intentionally invalid, so we can detect uninitialized values */ + this->m_gausstab = NULL; + this->m_filtersize = 0; + this->m_falloff = -1; /* intentionally invalid, so we can detect uninitialized values */ } void *GaussianAlphaXBlurOperation::initializeTileData(rcti * /*rect*/) { - lockMutex(); - if (!this->m_sizeavailable) { - updateGauss(); - } - void *buffer = getInputOperation(0)->initializeTileData(NULL); - unlockMutex(); - return buffer; + lockMutex(); + if (!this->m_sizeavailable) { + updateGauss(); + } + void *buffer = getInputOperation(0)->initializeTileData(NULL); + unlockMutex(); + return buffer; } void GaussianAlphaXBlurOperation::initExecution() { - /* BlurBaseOperation::initExecution(); */ /* until we suppoer size input - comment this */ + /* BlurBaseOperation::initExecution(); */ /* until we suppoer size input - comment this */ - initMutex(); + initMutex(); - if (this->m_sizeavailable) { - float rad = max_ff(m_size * m_data.sizex, 0.0f); - m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS); + if (this->m_sizeavailable) { + float rad = max_ff(m_size * m_data.sizex, 0.0f); + m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS); - m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize); - m_distbuf_inv = BlurBaseOperation::make_dist_fac_inverse(rad, m_filtersize, m_falloff); - } + m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize); + m_distbuf_inv = BlurBaseOperation::make_dist_fac_inverse(rad, m_filtersize, m_falloff); + } } void GaussianAlphaXBlurOperation::updateGauss() { - if (this->m_gausstab == NULL) { - updateSize(); - float rad = max_ff(m_size * m_data.sizex, 0.0f); - m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS); + if (this->m_gausstab == NULL) { + updateSize(); + float rad = max_ff(m_size * m_data.sizex, 0.0f); + m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS); - m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize); - } + m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize); + } - if (this->m_distbuf_inv == NULL) { - updateSize(); - float rad = max_ff(m_size * m_data.sizex, 0.0f); - m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS); + if (this->m_distbuf_inv == NULL) { + updateSize(); + float rad = max_ff(m_size * m_data.sizex, 0.0f); + m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS); - m_distbuf_inv = BlurBaseOperation::make_dist_fac_inverse(rad, m_filtersize, m_falloff); - } + m_distbuf_inv = BlurBaseOperation::make_dist_fac_inverse(rad, m_filtersize, m_falloff); + } } BLI_INLINE float finv_test(const float f, const bool test) { - return (LIKELY(test == false)) ? f : 1.0f - f; + return (LIKELY(test == false)) ? f : 1.0f - f; } void GaussianAlphaXBlurOperation::executePixel(float output[4], int x, int y, void *data) { - const bool do_invert = this->m_do_subtract; - MemoryBuffer *inputBuffer = (MemoryBuffer *)data; - float *buffer = inputBuffer->getBuffer(); - int bufferwidth = inputBuffer->getWidth(); - int bufferstartx = inputBuffer->getRect()->xmin; - int bufferstarty = inputBuffer->getRect()->ymin; - - rcti &rect = *inputBuffer->getRect(); - int xmin = max_ii(x - m_filtersize, rect.xmin); - int xmax = min_ii(x + m_filtersize + 1, rect.xmax); - int ymin = max_ii(y, rect.ymin); - - /* *** this is the main part which is different to 'GaussianXBlurOperation' *** */ - int step = getStep(); - int bufferindex = ((xmin - bufferstartx)) + ((ymin - bufferstarty) * bufferwidth); - - /* gauss */ - float alpha_accum = 0.0f; - float multiplier_accum = 0.0f; - - /* dilate */ - float value_max = finv_test(buffer[(x) + (y * bufferwidth)], do_invert); /* init with the current color to avoid unneeded lookups */ - float distfacinv_max = 1.0f; /* 0 to 1 */ - - for (int nx = xmin; nx < xmax; nx += step) { - const int index = (nx - x) + this->m_filtersize; - float value = finv_test(buffer[bufferindex], do_invert); - float multiplier; - - /* gauss */ - { - multiplier = this->m_gausstab[index]; - alpha_accum += value * multiplier; - multiplier_accum += multiplier; - } - - /* dilate - find most extreme color */ - if (value > value_max) { - multiplier = this->m_distbuf_inv[index]; - value *= multiplier; - if (value > value_max) { - value_max = value; - distfacinv_max = multiplier; - } - } - bufferindex += step; - } - - /* blend between the max value and gauss blue - gives nice feather */ - const float value_blur = alpha_accum / multiplier_accum; - const float value_final = (value_max * distfacinv_max) + (value_blur * (1.0f - distfacinv_max)); - output[0] = finv_test(value_final, do_invert); + const bool do_invert = this->m_do_subtract; + MemoryBuffer *inputBuffer = (MemoryBuffer *)data; + float *buffer = inputBuffer->getBuffer(); + int bufferwidth = inputBuffer->getWidth(); + int bufferstartx = inputBuffer->getRect()->xmin; + int bufferstarty = inputBuffer->getRect()->ymin; + + rcti &rect = *inputBuffer->getRect(); + int xmin = max_ii(x - m_filtersize, rect.xmin); + int xmax = min_ii(x + m_filtersize + 1, rect.xmax); + int ymin = max_ii(y, rect.ymin); + + /* *** this is the main part which is different to 'GaussianXBlurOperation' *** */ + int step = getStep(); + int bufferindex = ((xmin - bufferstartx)) + ((ymin - bufferstarty) * bufferwidth); + + /* gauss */ + float alpha_accum = 0.0f; + float multiplier_accum = 0.0f; + + /* dilate */ + float value_max = finv_test( + buffer[(x) + (y * bufferwidth)], + do_invert); /* init with the current color to avoid unneeded lookups */ + float distfacinv_max = 1.0f; /* 0 to 1 */ + + for (int nx = xmin; nx < xmax; nx += step) { + const int index = (nx - x) + this->m_filtersize; + float value = finv_test(buffer[bufferindex], do_invert); + float multiplier; + + /* gauss */ + { + multiplier = this->m_gausstab[index]; + alpha_accum += value * multiplier; + multiplier_accum += multiplier; + } + + /* dilate - find most extreme color */ + if (value > value_max) { + multiplier = this->m_distbuf_inv[index]; + value *= multiplier; + if (value > value_max) { + value_max = value; + distfacinv_max = multiplier; + } + } + bufferindex += step; + } + + /* blend between the max value and gauss blue - gives nice feather */ + const float value_blur = alpha_accum / multiplier_accum; + const float value_final = (value_max * distfacinv_max) + (value_blur * (1.0f - distfacinv_max)); + output[0] = finv_test(value_final, do_invert); } void GaussianAlphaXBlurOperation::deinitExecution() { - BlurBaseOperation::deinitExecution(); + BlurBaseOperation::deinitExecution(); - if (this->m_gausstab) { - MEM_freeN(this->m_gausstab); - this->m_gausstab = NULL; - } + if (this->m_gausstab) { + MEM_freeN(this->m_gausstab); + this->m_gausstab = NULL; + } - if (this->m_distbuf_inv) { - MEM_freeN(this->m_distbuf_inv); - this->m_distbuf_inv = NULL; - } + if (this->m_distbuf_inv) { + MEM_freeN(this->m_distbuf_inv); + this->m_distbuf_inv = NULL; + } - deinitMutex(); + deinitMutex(); } -bool GaussianAlphaXBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool GaussianAlphaXBlurOperation::determineDependingAreaOfInterest( + rcti *input, ReadBufferOperation *readOperation, rcti *output) { - rcti newInput; + rcti newInput; #if 0 /* until we add size input */ - 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 + 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 #endif - { - if (this->m_sizeavailable && this->m_gausstab != NULL) { - newInput.xmax = input->xmax + this->m_filtersize + 1; - newInput.xmin = input->xmin - this->m_filtersize - 1; - newInput.ymax = input->ymax; - newInput.ymin = input->ymin; - } - else { - newInput.xmax = this->getWidth(); - newInput.xmin = 0; - newInput.ymax = this->getHeight(); - newInput.ymin = 0; - } - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); - } + { + if (this->m_sizeavailable && this->m_gausstab != NULL) { + newInput.xmax = input->xmax + this->m_filtersize + 1; + newInput.xmin = input->xmin - this->m_filtersize - 1; + newInput.ymax = input->ymax; + newInput.ymin = input->ymin; + } + else { + newInput.xmax = this->getWidth(); + newInput.xmin = 0; + newInput.ymax = this->getHeight(); + newInput.ymin = 0; + } + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + } } diff --git a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.h b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.h index 530fccad60c..4d249778f53 100644 --- a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.h +++ b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.h @@ -22,38 +22,47 @@ #include "COM_BlurBaseOperation.h" class GaussianAlphaXBlurOperation : public BlurBaseOperation { -private: - float *m_gausstab; - float *m_distbuf_inv; - int m_falloff; /* falloff for distbuf_inv */ - bool m_do_subtract; - int m_filtersize; - void updateGauss(); -public: - GaussianAlphaXBlurOperation(); - - /** - * \brief the inner loop of this program - */ - void executePixel(float output[4], int x, int y, void *data); - - /** - * \brief initialize the execution - */ - void initExecution(); - - /** - * \brief Deinitialize the execution - */ - void deinitExecution(); - - void *initializeTileData(rcti *rect); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - - /** - * Set subtract for Dilate/Erode functionality - */ - void setSubtract(bool subtract) { this->m_do_subtract = subtract; } - void setFalloff(int falloff) { this->m_falloff = falloff; } + private: + float *m_gausstab; + float *m_distbuf_inv; + int m_falloff; /* falloff for distbuf_inv */ + bool m_do_subtract; + int m_filtersize; + void updateGauss(); + + public: + GaussianAlphaXBlurOperation(); + + /** + * \brief the inner loop of this program + */ + void executePixel(float output[4], int x, int y, void *data); + + /** + * \brief initialize the execution + */ + void initExecution(); + + /** + * \brief Deinitialize the execution + */ + void deinitExecution(); + + void *initializeTileData(rcti *rect); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + + /** + * Set subtract for Dilate/Erode functionality + */ + void setSubtract(bool subtract) + { + this->m_do_subtract = subtract; + } + void setFalloff(int falloff) + { + this->m_falloff = falloff; + } }; #endif diff --git a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp index 058718c6a97..37109b4a03e 100644 --- a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp @@ -21,169 +21,171 @@ #include "MEM_guardedalloc.h" extern "C" { -# include "RE_pipeline.h" +#include "RE_pipeline.h" } GaussianAlphaYBlurOperation::GaussianAlphaYBlurOperation() : BlurBaseOperation(COM_DT_VALUE) { - this->m_gausstab = NULL; - this->m_filtersize = 0; - this->m_falloff = -1; /* intentionally invalid, so we can detect uninitialized values */ + this->m_gausstab = NULL; + this->m_filtersize = 0; + this->m_falloff = -1; /* intentionally invalid, so we can detect uninitialized values */ } void *GaussianAlphaYBlurOperation::initializeTileData(rcti * /*rect*/) { - lockMutex(); - if (!this->m_sizeavailable) { - updateGauss(); - } - void *buffer = getInputOperation(0)->initializeTileData(NULL); - unlockMutex(); - return buffer; + lockMutex(); + if (!this->m_sizeavailable) { + updateGauss(); + } + void *buffer = getInputOperation(0)->initializeTileData(NULL); + unlockMutex(); + return buffer; } void GaussianAlphaYBlurOperation::initExecution() { - /* BlurBaseOperation::initExecution(); */ /* until we suppoer size input - comment this */ + /* BlurBaseOperation::initExecution(); */ /* until we suppoer size input - comment this */ - initMutex(); + initMutex(); - if (this->m_sizeavailable) { - float rad = max_ff(m_size * m_data.sizey, 0.0f); - m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS); + if (this->m_sizeavailable) { + float rad = max_ff(m_size * m_data.sizey, 0.0f); + m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS); - m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize); - m_distbuf_inv = BlurBaseOperation::make_dist_fac_inverse(rad, m_filtersize, m_falloff); - } + m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize); + m_distbuf_inv = BlurBaseOperation::make_dist_fac_inverse(rad, m_filtersize, m_falloff); + } } void GaussianAlphaYBlurOperation::updateGauss() { - if (this->m_gausstab == NULL) { - updateSize(); - float rad = max_ff(m_size * m_data.sizey, 0.0f); - m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS); + if (this->m_gausstab == NULL) { + updateSize(); + float rad = max_ff(m_size * m_data.sizey, 0.0f); + m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS); - m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize); - } + m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize); + } - if (this->m_distbuf_inv == NULL) { - updateSize(); - float rad = max_ff(m_size * m_data.sizey, 0.0f); - m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS); + if (this->m_distbuf_inv == NULL) { + updateSize(); + float rad = max_ff(m_size * m_data.sizey, 0.0f); + m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS); - m_distbuf_inv = BlurBaseOperation::make_dist_fac_inverse(rad, m_filtersize, m_falloff); - } + m_distbuf_inv = BlurBaseOperation::make_dist_fac_inverse(rad, m_filtersize, m_falloff); + } } BLI_INLINE float finv_test(const float f, const bool test) { - return (LIKELY(test == false)) ? f : 1.0f - f; + return (LIKELY(test == false)) ? f : 1.0f - f; } void GaussianAlphaYBlurOperation::executePixel(float output[4], int x, int y, void *data) { - const bool do_invert = this->m_do_subtract; - MemoryBuffer *inputBuffer = (MemoryBuffer *)data; - float *buffer = inputBuffer->getBuffer(); - int bufferwidth = inputBuffer->getWidth(); - int bufferstartx = inputBuffer->getRect()->xmin; - int bufferstarty = inputBuffer->getRect()->ymin; - - rcti &rect = *inputBuffer->getRect(); - int xmin = max_ii(x, rect.xmin); - int ymin = max_ii(y - m_filtersize, rect.ymin); - int ymax = min_ii(y + m_filtersize + 1, rect.ymax); - - /* *** this is the main part which is different to 'GaussianYBlurOperation' *** */ - int step = getStep(); - - /* gauss */ - float alpha_accum = 0.0f; - float multiplier_accum = 0.0f; - - /* dilate */ - float value_max = finv_test(buffer[(x) + (y * bufferwidth)], do_invert); /* init with the current color to avoid unneeded lookups */ - float distfacinv_max = 1.0f; /* 0 to 1 */ - - for (int ny = ymin; ny < ymax; ny += step) { - int bufferindex = ((xmin - bufferstartx)) + ((ny - bufferstarty) * bufferwidth); - - const int index = (ny - y) + this->m_filtersize; - float value = finv_test(buffer[bufferindex], do_invert); - float multiplier; - - /* gauss */ - { - multiplier = this->m_gausstab[index]; - alpha_accum += value * multiplier; - multiplier_accum += multiplier; - } - - /* dilate - find most extreme color */ - if (value > value_max) { - multiplier = this->m_distbuf_inv[index]; - value *= multiplier; - if (value > value_max) { - value_max = value; - distfacinv_max = multiplier; - } - } - - } - - /* blend between the max value and gauss blue - gives nice feather */ - const float value_blur = alpha_accum / multiplier_accum; - const float value_final = (value_max * distfacinv_max) + (value_blur * (1.0f - distfacinv_max)); - output[0] = finv_test(value_final, do_invert); + const bool do_invert = this->m_do_subtract; + MemoryBuffer *inputBuffer = (MemoryBuffer *)data; + float *buffer = inputBuffer->getBuffer(); + int bufferwidth = inputBuffer->getWidth(); + int bufferstartx = inputBuffer->getRect()->xmin; + int bufferstarty = inputBuffer->getRect()->ymin; + + rcti &rect = *inputBuffer->getRect(); + int xmin = max_ii(x, rect.xmin); + int ymin = max_ii(y - m_filtersize, rect.ymin); + int ymax = min_ii(y + m_filtersize + 1, rect.ymax); + + /* *** this is the main part which is different to 'GaussianYBlurOperation' *** */ + int step = getStep(); + + /* gauss */ + float alpha_accum = 0.0f; + float multiplier_accum = 0.0f; + + /* dilate */ + float value_max = finv_test( + buffer[(x) + (y * bufferwidth)], + do_invert); /* init with the current color to avoid unneeded lookups */ + float distfacinv_max = 1.0f; /* 0 to 1 */ + + for (int ny = ymin; ny < ymax; ny += step) { + int bufferindex = ((xmin - bufferstartx)) + ((ny - bufferstarty) * bufferwidth); + + const int index = (ny - y) + this->m_filtersize; + float value = finv_test(buffer[bufferindex], do_invert); + float multiplier; + + /* gauss */ + { + multiplier = this->m_gausstab[index]; + alpha_accum += value * multiplier; + multiplier_accum += multiplier; + } + + /* dilate - find most extreme color */ + if (value > value_max) { + multiplier = this->m_distbuf_inv[index]; + value *= multiplier; + if (value > value_max) { + value_max = value; + distfacinv_max = multiplier; + } + } + } + + /* blend between the max value and gauss blue - gives nice feather */ + const float value_blur = alpha_accum / multiplier_accum; + const float value_final = (value_max * distfacinv_max) + (value_blur * (1.0f - distfacinv_max)); + output[0] = finv_test(value_final, do_invert); } void GaussianAlphaYBlurOperation::deinitExecution() { - BlurBaseOperation::deinitExecution(); + BlurBaseOperation::deinitExecution(); - if (this->m_gausstab) { - MEM_freeN(this->m_gausstab); - this->m_gausstab = NULL; - } + if (this->m_gausstab) { + MEM_freeN(this->m_gausstab); + this->m_gausstab = NULL; + } - if (this->m_distbuf_inv) { - MEM_freeN(this->m_distbuf_inv); - this->m_distbuf_inv = NULL; - } + if (this->m_distbuf_inv) { + MEM_freeN(this->m_distbuf_inv); + this->m_distbuf_inv = NULL; + } - deinitMutex(); + deinitMutex(); } -bool GaussianAlphaYBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool GaussianAlphaYBlurOperation::determineDependingAreaOfInterest( + rcti *input, ReadBufferOperation *readOperation, rcti *output) { - rcti newInput; + rcti newInput; #if 0 /* until we add size input */ - 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 + 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 #endif - { - if (this->m_sizeavailable && this->m_gausstab != NULL) { - newInput.xmax = input->xmax; - newInput.xmin = input->xmin; - newInput.ymax = input->ymax + this->m_filtersize + 1; - newInput.ymin = input->ymin - this->m_filtersize - 1; - } - else { - newInput.xmax = this->getWidth(); - newInput.xmin = 0; - newInput.ymax = this->getHeight(); - newInput.ymin = 0; - } - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); - } + { + if (this->m_sizeavailable && this->m_gausstab != NULL) { + newInput.xmax = input->xmax; + newInput.xmin = input->xmin; + newInput.ymax = input->ymax + this->m_filtersize + 1; + newInput.ymin = input->ymin - this->m_filtersize - 1; + } + else { + newInput.xmax = this->getWidth(); + newInput.xmin = 0; + newInput.ymax = this->getHeight(); + newInput.ymin = 0; + } + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + } } diff --git a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.h b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.h index cf3670f90ad..d31534455bc 100644 --- a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.h +++ b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.h @@ -22,38 +22,47 @@ #include "COM_BlurBaseOperation.h" class GaussianAlphaYBlurOperation : public BlurBaseOperation { -private: - float *m_gausstab; - float *m_distbuf_inv; - bool m_do_subtract; - int m_falloff; - int m_filtersize; - void updateGauss(); -public: - GaussianAlphaYBlurOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], int x, int y, void *data); - - /** - * \brief initialize the execution - */ - void initExecution(); - - /** - * Deinitialize the execution - */ - void deinitExecution(); - - void *initializeTileData(rcti *rect); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - - /** - * Set subtract for Dilate/Erode functionality - */ - void setSubtract(bool subtract) { this->m_do_subtract = subtract; } - void setFalloff(int falloff) { this->m_falloff = falloff; } + private: + float *m_gausstab; + float *m_distbuf_inv; + bool m_do_subtract; + int m_falloff; + int m_filtersize; + void updateGauss(); + + public: + GaussianAlphaYBlurOperation(); + + /** + * the inner loop of this program + */ + void executePixel(float output[4], int x, int y, void *data); + + /** + * \brief initialize the execution + */ + void initExecution(); + + /** + * Deinitialize the execution + */ + void deinitExecution(); + + void *initializeTileData(rcti *rect); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + + /** + * Set subtract for Dilate/Erode functionality + */ + void setSubtract(bool subtract) + { + this->m_do_subtract = subtract; + } + void setFalloff(int falloff) + { + this->m_falloff = falloff; + } }; #endif diff --git a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp index 40a6f52c7a6..88c4ff7d935 100644 --- a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp @@ -20,333 +20,336 @@ #include "BLI_math.h" #include "MEM_guardedalloc.h" extern "C" { -# include "RE_pipeline.h" +#include "RE_pipeline.h" } GaussianBokehBlurOperation::GaussianBokehBlurOperation() : BlurBaseOperation(COM_DT_COLOR) { - this->m_gausstab = NULL; + this->m_gausstab = NULL; } void *GaussianBokehBlurOperation::initializeTileData(rcti * /*rect*/) { - lockMutex(); - if (!this->m_sizeavailable) { - updateGauss(); - } - void *buffer = getInputOperation(0)->initializeTileData(NULL); - unlockMutex(); - return buffer; + lockMutex(); + if (!this->m_sizeavailable) { + updateGauss(); + } + void *buffer = getInputOperation(0)->initializeTileData(NULL); + unlockMutex(); + return buffer; } void GaussianBokehBlurOperation::initExecution() { - BlurBaseOperation::initExecution(); + BlurBaseOperation::initExecution(); - initMutex(); + initMutex(); - if (this->m_sizeavailable) { - updateGauss(); - } + if (this->m_sizeavailable) { + updateGauss(); + } } void GaussianBokehBlurOperation::updateGauss() { - if (this->m_gausstab == NULL) { - float radxf; - float radyf; - int n; - float *dgauss; - float *ddgauss; - int j, i; - const float width = this->getWidth(); - const float height = this->getHeight(); - if (!this->m_sizeavailable) { - updateSize(); - } - radxf = this->m_size * (float)this->m_data.sizex; - CLAMP(radxf, 0.0f, width / 2.0f); - - /* vertical */ - radyf = this->m_size * (float)this->m_data.sizey; - CLAMP(radyf, 0.0f, height / 2.0f); - - 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 = (float *)MEM_mallocN(sizeof(float) * n, __func__); - dgauss = ddgauss; - 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->m_data.filtertype, dist); - - sum += *dgauss; - } - } - - if (sum > 0.0f) { - /* normalize */ - float norm = 1.0f / sum; - for (j = n - 1; j >= 0; j--) - ddgauss[j] *= norm; - } - else { - int center = m_rady * ddwidth + m_radx; - ddgauss[center] = 1.0f; - } - - this->m_gausstab = ddgauss; - } + if (this->m_gausstab == NULL) { + float radxf; + float radyf; + int n; + float *dgauss; + float *ddgauss; + int j, i; + const float width = this->getWidth(); + const float height = this->getHeight(); + if (!this->m_sizeavailable) { + updateSize(); + } + radxf = this->m_size * (float)this->m_data.sizex; + CLAMP(radxf, 0.0f, width / 2.0f); + + /* vertical */ + radyf = this->m_size * (float)this->m_data.sizey; + CLAMP(radyf, 0.0f, height / 2.0f); + + 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 = (float *)MEM_mallocN(sizeof(float) * n, __func__); + dgauss = ddgauss; + 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->m_data.filtertype, dist); + + sum += *dgauss; + } + } + + if (sum > 0.0f) { + /* normalize */ + float norm = 1.0f / sum; + for (j = n - 1; j >= 0; j--) + ddgauss[j] *= norm; + } + else { + int center = m_rady * ddwidth + m_radx; + ddgauss[center] = 1.0f; + } + + this->m_gausstab = ddgauss; + } } 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 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; - - 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(); - 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(output, tempColor, 1.0f / multiplier_accum); + float tempColor[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; + + 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(); + 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(output, tempColor, 1.0f / multiplier_accum); } void GaussianBokehBlurOperation::deinitExecution() { - BlurBaseOperation::deinitExecution(); + BlurBaseOperation::deinitExecution(); - if (this->m_gausstab) { - MEM_freeN(this->m_gausstab); - this->m_gausstab = NULL; - } + if (this->m_gausstab) { + MEM_freeN(this->m_gausstab); + this->m_gausstab = NULL; + } - deinitMutex(); + deinitMutex(); } -bool GaussianBokehBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool GaussianBokehBlurOperation::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_sizeavailable && this->m_gausstab != NULL) { - newInput.xmin = 0; - newInput.ymin = 0; - newInput.xmax = this->getWidth(); - newInput.ymax = this->getHeight(); - } - else { - 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; - newInput.ymin = input->ymin - addy; - - } - return BlurBaseOperation::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_sizeavailable && this->m_gausstab != NULL) { + newInput.xmin = 0; + newInput.ymin = 0; + newInput.xmax = this->getWidth(); + newInput.ymax = this->getHeight(); + } + else { + 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; + newInput.ymin = input->ymin - addy; + } + return BlurBaseOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + } } // reference image GaussianBlurReferenceOperation::GaussianBlurReferenceOperation() : BlurBaseOperation(COM_DT_COLOR) { - this->m_maintabs = NULL; + this->m_maintabs = NULL; } void *GaussianBlurReferenceOperation::initializeTileData(rcti * /*rect*/) { - void *buffer = getInputOperation(0)->initializeTileData(NULL); - return buffer; + 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(); + 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); - } + 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; - } - + 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(); + 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) +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); - } + 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); + } } diff --git a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.h b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.h index c3d6d30b694..99e22cf91c3 100644 --- a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.h +++ b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.h @@ -23,53 +23,57 @@ #include "COM_QualityStepHelper.h" class GaussianBokehBlurOperation : public BlurBaseOperation { -private: - float *m_gausstab; - int m_radx, m_rady; - void updateGauss(); + private: + float *m_gausstab; + int m_radx, m_rady; + void updateGauss(); -public: - GaussianBokehBlurOperation(); - void initExecution(); - void *initializeTileData(rcti *rect); - /** - * the inner loop of this program - */ - void executePixel(float output[4], int x, int y, void *data); + public: + GaussianBokehBlurOperation(); + void initExecution(); + void *initializeTileData(rcti *rect); + /** + * the inner loop of this program + */ + void executePixel(float output[4], int x, int y, void *data); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Deinitialize the execution + */ + void deinitExecution(); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); }; class GaussianBlurReferenceOperation : public BlurBaseOperation { -private: - float **m_maintabs; + private: + float **m_maintabs; - void updateGauss(); - int m_filtersizex; - int m_filtersizey; - float m_radx; - float m_rady; + void updateGauss(); + int m_filtersizex; + int m_filtersizey; + float m_radx; + float m_rady; -public: - GaussianBlurReferenceOperation(); - void initExecution(); - void *initializeTileData(rcti *rect); - /** - * the inner loop of this program - */ - void executePixel(float output[4], int x, int y, void *data); + public: + GaussianBlurReferenceOperation(); + void initExecution(); + void *initializeTileData(rcti *rect); + /** + * the inner loop of this program + */ + void executePixel(float output[4], int x, int y, void *data); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Deinitialize the execution + */ + void deinitExecution(); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); }; #endif diff --git a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp index c8c1db24b08..29a50f5350a 100644 --- a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp @@ -22,175 +22,187 @@ #include "MEM_guardedalloc.h" extern "C" { -# include "RE_pipeline.h" +#include "RE_pipeline.h" } GaussianXBlurOperation::GaussianXBlurOperation() : BlurBaseOperation(COM_DT_COLOR) { - this->m_gausstab = NULL; + this->m_gausstab = NULL; #ifdef __SSE2__ - this->m_gausstab_sse = NULL; + this->m_gausstab_sse = NULL; #endif - this->m_filtersize = 0; + this->m_filtersize = 0; } void *GaussianXBlurOperation::initializeTileData(rcti * /*rect*/) { - lockMutex(); - if (!this->m_sizeavailable) { - updateGauss(); - } - void *buffer = getInputOperation(0)->initializeTileData(NULL); - unlockMutex(); - return buffer; + lockMutex(); + if (!this->m_sizeavailable) { + updateGauss(); + } + void *buffer = getInputOperation(0)->initializeTileData(NULL); + unlockMutex(); + return buffer; } void GaussianXBlurOperation::initExecution() { - BlurBaseOperation::initExecution(); + BlurBaseOperation::initExecution(); - initMutex(); + initMutex(); - if (this->m_sizeavailable) { - float rad = max_ff(m_size * m_data.sizex, 0.0f); - m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS); + if (this->m_sizeavailable) { + float rad = max_ff(m_size * m_data.sizex, 0.0f); + m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS); - /* TODO(sergey): De-duplicate with the case below and Y blur. */ - this->m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize); + /* TODO(sergey): De-duplicate with the case below and Y blur. */ + this->m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize); #ifdef __SSE2__ - this->m_gausstab_sse = BlurBaseOperation::convert_gausstab_sse(this->m_gausstab, - m_filtersize); + this->m_gausstab_sse = BlurBaseOperation::convert_gausstab_sse(this->m_gausstab, m_filtersize); #endif - } + } } void GaussianXBlurOperation::updateGauss() { - if (this->m_gausstab == NULL) { - updateSize(); - float rad = max_ff(m_size * m_data.sizex, 0.0f); - m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS); + if (this->m_gausstab == NULL) { + updateSize(); + float rad = max_ff(m_size * m_data.sizex, 0.0f); + m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS); - this->m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize); + this->m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize); #ifdef __SSE2__ - this->m_gausstab_sse = BlurBaseOperation::convert_gausstab_sse(this->m_gausstab, - m_filtersize); + this->m_gausstab_sse = BlurBaseOperation::convert_gausstab_sse(this->m_gausstab, m_filtersize); #endif - } + } } void GaussianXBlurOperation::executePixel(float output[4], int x, int y, void *data) { - float ATTR_ALIGN(16) color_accum[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - float multiplier_accum = 0.0f; - MemoryBuffer *inputBuffer = (MemoryBuffer *)data; - float *buffer = inputBuffer->getBuffer(); - int bufferwidth = inputBuffer->getWidth(); - int bufferstartx = inputBuffer->getRect()->xmin; - int bufferstarty = inputBuffer->getRect()->ymin; - - rcti &rect = *inputBuffer->getRect(); - int xmin = max_ii(x - m_filtersize, rect.xmin); - int xmax = min_ii(x + m_filtersize + 1, rect.xmax); - int ymin = max_ii(y, rect.ymin); - - int step = getStep(); - int offsetadd = getOffsetAdd(); - int bufferindex = ((xmin - bufferstartx) * 4) + ((ymin - bufferstarty) * 4 * bufferwidth); + float ATTR_ALIGN(16) color_accum[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + float multiplier_accum = 0.0f; + MemoryBuffer *inputBuffer = (MemoryBuffer *)data; + float *buffer = inputBuffer->getBuffer(); + int bufferwidth = inputBuffer->getWidth(); + int bufferstartx = inputBuffer->getRect()->xmin; + int bufferstarty = inputBuffer->getRect()->ymin; + + rcti &rect = *inputBuffer->getRect(); + int xmin = max_ii(x - m_filtersize, rect.xmin); + int xmax = min_ii(x + m_filtersize + 1, rect.xmax); + int ymin = max_ii(y, rect.ymin); + + int step = getStep(); + int offsetadd = getOffsetAdd(); + int bufferindex = ((xmin - bufferstartx) * 4) + ((ymin - bufferstarty) * 4 * bufferwidth); #ifdef __SSE2__ - __m128 accum_r = _mm_load_ps(color_accum); - for (int nx = xmin, index = (xmin - x) + this->m_filtersize; nx < xmax; nx += step, index += step) { - __m128 reg_a = _mm_load_ps(&buffer[bufferindex]); - reg_a = _mm_mul_ps(reg_a, this->m_gausstab_sse[index]); - accum_r = _mm_add_ps(accum_r, reg_a); - multiplier_accum += this->m_gausstab[index]; - bufferindex += offsetadd; - } - _mm_store_ps(color_accum, accum_r); + __m128 accum_r = _mm_load_ps(color_accum); + for (int nx = xmin, index = (xmin - x) + this->m_filtersize; nx < xmax; + nx += step, index += step) { + __m128 reg_a = _mm_load_ps(&buffer[bufferindex]); + reg_a = _mm_mul_ps(reg_a, this->m_gausstab_sse[index]); + accum_r = _mm_add_ps(accum_r, reg_a); + multiplier_accum += this->m_gausstab[index]; + bufferindex += offsetadd; + } + _mm_store_ps(color_accum, accum_r); #else - for (int nx = xmin, index = (xmin - x) + this->m_filtersize; nx < xmax; nx += step, index += step) { - const float multiplier = this->m_gausstab[index]; - madd_v4_v4fl(color_accum, &buffer[bufferindex], multiplier); - multiplier_accum += multiplier; - bufferindex += offsetadd; - } + for (int nx = xmin, index = (xmin - x) + this->m_filtersize; nx < xmax; + nx += step, index += step) { + const float multiplier = this->m_gausstab[index]; + madd_v4_v4fl(color_accum, &buffer[bufferindex], multiplier); + multiplier_accum += multiplier; + bufferindex += offsetadd; + } #endif - mul_v4_v4fl(output, color_accum, 1.0f / multiplier_accum); + mul_v4_v4fl(output, color_accum, 1.0f / multiplier_accum); } void GaussianXBlurOperation::executeOpenCL(OpenCLDevice *device, - MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, - MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, + MemoryBuffer *outputMemoryBuffer, + cl_mem clOutputBuffer, + MemoryBuffer **inputMemoryBuffers, + list<cl_mem> *clMemToCleanUp, list<cl_kernel> * /*clKernelsToCleanUp*/) { - cl_kernel gaussianXBlurOperationKernel = device->COM_clCreateKernel("gaussianXBlurOperationKernel", NULL); - cl_int filter_size = this->m_filtersize; - - cl_mem gausstab = clCreateBuffer(device->getContext(), - CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, - sizeof(float) * (this->m_filtersize * 2 + 1), - this->m_gausstab, - NULL); - - device->COM_clAttachMemoryBufferToKernelParameter(gaussianXBlurOperationKernel, 0, 1, clMemToCleanUp, inputMemoryBuffers, this->m_inputProgram); - device->COM_clAttachOutputMemoryBufferToKernelParameter(gaussianXBlurOperationKernel, 2, clOutputBuffer); - device->COM_clAttachMemoryBufferOffsetToKernelParameter(gaussianXBlurOperationKernel, 3, outputMemoryBuffer); - clSetKernelArg(gaussianXBlurOperationKernel, 4, sizeof(cl_int), &filter_size); - device->COM_clAttachSizeToKernelParameter(gaussianXBlurOperationKernel, 5, this); - clSetKernelArg(gaussianXBlurOperationKernel, 6, sizeof(cl_mem), &gausstab); - - device->COM_clEnqueueRange(gaussianXBlurOperationKernel, outputMemoryBuffer, 7, this); - - clReleaseMemObject(gausstab); + cl_kernel gaussianXBlurOperationKernel = device->COM_clCreateKernel( + "gaussianXBlurOperationKernel", NULL); + cl_int filter_size = this->m_filtersize; + + cl_mem gausstab = clCreateBuffer(device->getContext(), + CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, + sizeof(float) * (this->m_filtersize * 2 + 1), + this->m_gausstab, + NULL); + + device->COM_clAttachMemoryBufferToKernelParameter(gaussianXBlurOperationKernel, + 0, + 1, + clMemToCleanUp, + inputMemoryBuffers, + this->m_inputProgram); + device->COM_clAttachOutputMemoryBufferToKernelParameter( + gaussianXBlurOperationKernel, 2, clOutputBuffer); + device->COM_clAttachMemoryBufferOffsetToKernelParameter( + gaussianXBlurOperationKernel, 3, outputMemoryBuffer); + clSetKernelArg(gaussianXBlurOperationKernel, 4, sizeof(cl_int), &filter_size); + device->COM_clAttachSizeToKernelParameter(gaussianXBlurOperationKernel, 5, this); + clSetKernelArg(gaussianXBlurOperationKernel, 6, sizeof(cl_mem), &gausstab); + + device->COM_clEnqueueRange(gaussianXBlurOperationKernel, outputMemoryBuffer, 7, this); + + clReleaseMemObject(gausstab); } void GaussianXBlurOperation::deinitExecution() { - BlurBaseOperation::deinitExecution(); + BlurBaseOperation::deinitExecution(); - if (this->m_gausstab) { - MEM_freeN(this->m_gausstab); - this->m_gausstab = NULL; - } + if (this->m_gausstab) { + MEM_freeN(this->m_gausstab); + this->m_gausstab = NULL; + } #ifdef __SSE2__ - if (this->m_gausstab_sse) { - MEM_freeN(this->m_gausstab_sse); - this->m_gausstab_sse = NULL; - } + if (this->m_gausstab_sse) { + MEM_freeN(this->m_gausstab_sse); + this->m_gausstab_sse = NULL; + } #endif - deinitMutex(); + deinitMutex(); } -bool GaussianXBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool GaussianXBlurOperation::determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output) { - rcti newInput; - - if (!this->m_sizeavailable) { - 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; - } - } - { - if (this->m_sizeavailable && this->m_gausstab != NULL) { - newInput.xmax = input->xmax + this->m_filtersize + 1; - newInput.xmin = input->xmin - this->m_filtersize - 1; - newInput.ymax = input->ymax; - newInput.ymin = input->ymin; - } - else { - newInput.xmax = this->getWidth(); - newInput.xmin = 0; - newInput.ymax = this->getHeight(); - newInput.ymin = 0; - } - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); - } + rcti newInput; + + if (!this->m_sizeavailable) { + 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; + } + } + { + if (this->m_sizeavailable && this->m_gausstab != NULL) { + newInput.xmax = input->xmax + this->m_filtersize + 1; + newInput.xmin = input->xmin - this->m_filtersize - 1; + newInput.ymax = input->ymax; + newInput.ymin = input->ymin; + } + else { + newInput.xmax = this->getWidth(); + newInput.xmin = 0; + newInput.ymax = this->getHeight(); + newInput.ymin = 0; + } + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + } } diff --git a/source/blender/compositor/operations/COM_GaussianXBlurOperation.h b/source/blender/compositor/operations/COM_GaussianXBlurOperation.h index ad9d718b86a..3ebe52cfcce 100644 --- a/source/blender/compositor/operations/COM_GaussianXBlurOperation.h +++ b/source/blender/compositor/operations/COM_GaussianXBlurOperation.h @@ -22,41 +22,47 @@ #include "COM_BlurBaseOperation.h" class GaussianXBlurOperation : public BlurBaseOperation { -private: - float *m_gausstab; + private: + float *m_gausstab; #ifdef __SSE2__ - __m128 *m_gausstab_sse; + __m128 *m_gausstab_sse; #endif - int m_filtersize; - void updateGauss(); -public: - GaussianXBlurOperation(); - - /** - * \brief the inner loop of this program - */ - void executePixel(float output[4], int x, int y, void *data); - - void executeOpenCL(OpenCLDevice *device, - MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, - MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, - list<cl_kernel> *clKernelsToCleanUp); - - /** - * \brief initialize the execution - */ - void initExecution(); - - /** - * \brief Deinitialize the execution - */ - void deinitExecution(); - - void *initializeTileData(rcti *rect); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - - void checkOpenCL() { - this->setOpenCL(m_data.sizex >= 128); - } + int m_filtersize; + void updateGauss(); + + public: + GaussianXBlurOperation(); + + /** + * \brief the inner loop of this program + */ + void executePixel(float output[4], int x, int y, void *data); + + void executeOpenCL(OpenCLDevice *device, + MemoryBuffer *outputMemoryBuffer, + cl_mem clOutputBuffer, + MemoryBuffer **inputMemoryBuffers, + list<cl_mem> *clMemToCleanUp, + list<cl_kernel> *clKernelsToCleanUp); + + /** + * \brief initialize the execution + */ + void initExecution(); + + /** + * \brief Deinitialize the execution + */ + void deinitExecution(); + + void *initializeTileData(rcti *rect); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + + void checkOpenCL() + { + this->setOpenCL(m_data.sizex >= 128); + } }; #endif diff --git a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp index 168dbddf400..500e0fbedc3 100644 --- a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp @@ -22,177 +22,187 @@ #include "MEM_guardedalloc.h" extern "C" { -# include "RE_pipeline.h" +#include "RE_pipeline.h" } GaussianYBlurOperation::GaussianYBlurOperation() : BlurBaseOperation(COM_DT_COLOR) { - this->m_gausstab = NULL; + this->m_gausstab = NULL; #ifdef __SSE2__ - this->m_gausstab_sse = NULL; + this->m_gausstab_sse = NULL; #endif - this->m_filtersize = 0; + this->m_filtersize = 0; } void *GaussianYBlurOperation::initializeTileData(rcti * /*rect*/) { - lockMutex(); - if (!this->m_sizeavailable) { - updateGauss(); - } - void *buffer = getInputOperation(0)->initializeTileData(NULL); - unlockMutex(); - return buffer; + lockMutex(); + if (!this->m_sizeavailable) { + updateGauss(); + } + void *buffer = getInputOperation(0)->initializeTileData(NULL); + unlockMutex(); + return buffer; } void GaussianYBlurOperation::initExecution() { - BlurBaseOperation::initExecution(); + BlurBaseOperation::initExecution(); - initMutex(); + initMutex(); - if (this->m_sizeavailable) { - float rad = max_ff(m_size * m_data.sizey, 0.0f); - m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS); + if (this->m_sizeavailable) { + float rad = max_ff(m_size * m_data.sizey, 0.0f); + m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS); - this->m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize); + this->m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize); #ifdef __SSE2__ - this->m_gausstab_sse = BlurBaseOperation::convert_gausstab_sse(this->m_gausstab, - m_filtersize); + this->m_gausstab_sse = BlurBaseOperation::convert_gausstab_sse(this->m_gausstab, m_filtersize); #endif - } + } } void GaussianYBlurOperation::updateGauss() { - if (this->m_gausstab == NULL) { - updateSize(); - float rad = max_ff(m_size * m_data.sizey, 0.0f); - m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS); + if (this->m_gausstab == NULL) { + updateSize(); + float rad = max_ff(m_size * m_data.sizey, 0.0f); + m_filtersize = min_ii(ceil(rad), MAX_GAUSSTAB_RADIUS); - this->m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize); + this->m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize); #ifdef __SSE2__ - this->m_gausstab_sse = BlurBaseOperation::convert_gausstab_sse(this->m_gausstab, - m_filtersize); + this->m_gausstab_sse = BlurBaseOperation::convert_gausstab_sse(this->m_gausstab, m_filtersize); #endif - } + } } void GaussianYBlurOperation::executePixel(float output[4], int x, int y, void *data) { - float ATTR_ALIGN(16) color_accum[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - float multiplier_accum = 0.0f; - MemoryBuffer *inputBuffer = (MemoryBuffer *)data; - float *buffer = inputBuffer->getBuffer(); - int bufferwidth = inputBuffer->getWidth(); - int bufferstartx = inputBuffer->getRect()->xmin; - int bufferstarty = inputBuffer->getRect()->ymin; - - rcti &rect = *inputBuffer->getRect(); - int xmin = max_ii(x, rect.xmin); - int ymin = max_ii(y - m_filtersize, rect.ymin); - int ymax = min_ii(y + m_filtersize + 1, rect.ymax); - - int index; - int step = getStep(); - const int bufferIndexx = ((xmin - bufferstartx) * 4); + float ATTR_ALIGN(16) color_accum[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + float multiplier_accum = 0.0f; + MemoryBuffer *inputBuffer = (MemoryBuffer *)data; + float *buffer = inputBuffer->getBuffer(); + int bufferwidth = inputBuffer->getWidth(); + int bufferstartx = inputBuffer->getRect()->xmin; + int bufferstarty = inputBuffer->getRect()->ymin; + + rcti &rect = *inputBuffer->getRect(); + int xmin = max_ii(x, rect.xmin); + int ymin = max_ii(y - m_filtersize, rect.ymin); + int ymax = min_ii(y + m_filtersize + 1, rect.ymax); + + int index; + int step = getStep(); + const int bufferIndexx = ((xmin - bufferstartx) * 4); #ifdef __SSE2__ - __m128 accum_r = _mm_load_ps(color_accum); - for (int ny = ymin; ny < ymax; ny += step) { - index = (ny - y) + this->m_filtersize; - int bufferindex = bufferIndexx + ((ny - bufferstarty) * 4 * bufferwidth); - const float multiplier = this->m_gausstab[index]; - __m128 reg_a = _mm_load_ps(&buffer[bufferindex]); - reg_a = _mm_mul_ps(reg_a, this->m_gausstab_sse[index]); - accum_r = _mm_add_ps(accum_r, reg_a); - multiplier_accum += multiplier; - } - _mm_store_ps(color_accum, accum_r); + __m128 accum_r = _mm_load_ps(color_accum); + for (int ny = ymin; ny < ymax; ny += step) { + index = (ny - y) + this->m_filtersize; + int bufferindex = bufferIndexx + ((ny - bufferstarty) * 4 * bufferwidth); + const float multiplier = this->m_gausstab[index]; + __m128 reg_a = _mm_load_ps(&buffer[bufferindex]); + reg_a = _mm_mul_ps(reg_a, this->m_gausstab_sse[index]); + accum_r = _mm_add_ps(accum_r, reg_a); + multiplier_accum += multiplier; + } + _mm_store_ps(color_accum, accum_r); #else - for (int ny = ymin; ny < ymax; ny += step) { - index = (ny - y) + this->m_filtersize; - int bufferindex = bufferIndexx + ((ny - bufferstarty) * 4 * bufferwidth); - const float multiplier = this->m_gausstab[index]; - madd_v4_v4fl(color_accum, &buffer[bufferindex], multiplier); - multiplier_accum += multiplier; - } + for (int ny = ymin; ny < ymax; ny += step) { + index = (ny - y) + this->m_filtersize; + int bufferindex = bufferIndexx + ((ny - bufferstarty) * 4 * bufferwidth); + const float multiplier = this->m_gausstab[index]; + madd_v4_v4fl(color_accum, &buffer[bufferindex], multiplier); + multiplier_accum += multiplier; + } #endif - mul_v4_v4fl(output, color_accum, 1.0f / multiplier_accum); + mul_v4_v4fl(output, color_accum, 1.0f / multiplier_accum); } void GaussianYBlurOperation::executeOpenCL(OpenCLDevice *device, - MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, - MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, + MemoryBuffer *outputMemoryBuffer, + cl_mem clOutputBuffer, + MemoryBuffer **inputMemoryBuffers, + list<cl_mem> *clMemToCleanUp, list<cl_kernel> * /*clKernelsToCleanUp*/) { - cl_kernel gaussianYBlurOperationKernel = device->COM_clCreateKernel("gaussianYBlurOperationKernel", NULL); - cl_int filter_size = this->m_filtersize; - - cl_mem gausstab = clCreateBuffer(device->getContext(), - CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, - sizeof(float) * (this->m_filtersize * 2 + 1), - this->m_gausstab, - NULL); - - device->COM_clAttachMemoryBufferToKernelParameter(gaussianYBlurOperationKernel, 0, 1, clMemToCleanUp, inputMemoryBuffers, this->m_inputProgram); - device->COM_clAttachOutputMemoryBufferToKernelParameter(gaussianYBlurOperationKernel, 2, clOutputBuffer); - device->COM_clAttachMemoryBufferOffsetToKernelParameter(gaussianYBlurOperationKernel, 3, outputMemoryBuffer); - clSetKernelArg(gaussianYBlurOperationKernel, 4, sizeof(cl_int), &filter_size); - device->COM_clAttachSizeToKernelParameter(gaussianYBlurOperationKernel, 5, this); - clSetKernelArg(gaussianYBlurOperationKernel, 6, sizeof(cl_mem), &gausstab); - - device->COM_clEnqueueRange(gaussianYBlurOperationKernel, outputMemoryBuffer, 7, this); - - clReleaseMemObject(gausstab); + cl_kernel gaussianYBlurOperationKernel = device->COM_clCreateKernel( + "gaussianYBlurOperationKernel", NULL); + cl_int filter_size = this->m_filtersize; + + cl_mem gausstab = clCreateBuffer(device->getContext(), + CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, + sizeof(float) * (this->m_filtersize * 2 + 1), + this->m_gausstab, + NULL); + + device->COM_clAttachMemoryBufferToKernelParameter(gaussianYBlurOperationKernel, + 0, + 1, + clMemToCleanUp, + inputMemoryBuffers, + this->m_inputProgram); + device->COM_clAttachOutputMemoryBufferToKernelParameter( + gaussianYBlurOperationKernel, 2, clOutputBuffer); + device->COM_clAttachMemoryBufferOffsetToKernelParameter( + gaussianYBlurOperationKernel, 3, outputMemoryBuffer); + clSetKernelArg(gaussianYBlurOperationKernel, 4, sizeof(cl_int), &filter_size); + device->COM_clAttachSizeToKernelParameter(gaussianYBlurOperationKernel, 5, this); + clSetKernelArg(gaussianYBlurOperationKernel, 6, sizeof(cl_mem), &gausstab); + + device->COM_clEnqueueRange(gaussianYBlurOperationKernel, outputMemoryBuffer, 7, this); + + clReleaseMemObject(gausstab); } void GaussianYBlurOperation::deinitExecution() { - BlurBaseOperation::deinitExecution(); + BlurBaseOperation::deinitExecution(); - if (this->m_gausstab) { - MEM_freeN(this->m_gausstab); - this->m_gausstab = NULL; - } + if (this->m_gausstab) { + MEM_freeN(this->m_gausstab); + this->m_gausstab = NULL; + } #ifdef __SSE2__ - if (this->m_gausstab_sse) { - MEM_freeN(this->m_gausstab_sse); - this->m_gausstab_sse = NULL; - } + if (this->m_gausstab_sse) { + MEM_freeN(this->m_gausstab_sse); + this->m_gausstab_sse = NULL; + } #endif - deinitMutex(); + deinitMutex(); } -bool GaussianYBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool GaussianYBlurOperation::determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output) { - rcti newInput; - - if (!m_sizeavailable) { - 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; - } - } - { - if (this->m_sizeavailable && this->m_gausstab != NULL) { - newInput.xmax = input->xmax; - newInput.xmin = input->xmin; - newInput.ymax = input->ymax + this->m_filtersize + 1; - newInput.ymin = input->ymin - this->m_filtersize - 1; - } - else { - newInput.xmax = this->getWidth(); - newInput.xmin = 0; - newInput.ymax = this->getHeight(); - newInput.ymin = 0; - } - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); - } + rcti newInput; + + if (!m_sizeavailable) { + 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; + } + } + { + if (this->m_sizeavailable && this->m_gausstab != NULL) { + newInput.xmax = input->xmax; + newInput.xmin = input->xmin; + newInput.ymax = input->ymax + this->m_filtersize + 1; + newInput.ymin = input->ymin - this->m_filtersize - 1; + } + else { + newInput.xmax = this->getWidth(); + newInput.xmin = 0; + newInput.ymax = this->getHeight(); + newInput.ymin = 0; + } + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + } } diff --git a/source/blender/compositor/operations/COM_GaussianYBlurOperation.h b/source/blender/compositor/operations/COM_GaussianYBlurOperation.h index 9d4e3d62055..ce8e0a7b781 100644 --- a/source/blender/compositor/operations/COM_GaussianYBlurOperation.h +++ b/source/blender/compositor/operations/COM_GaussianYBlurOperation.h @@ -22,41 +22,47 @@ #include "COM_BlurBaseOperation.h" class GaussianYBlurOperation : public BlurBaseOperation { -private: - float *m_gausstab; + private: + float *m_gausstab; #ifdef __SSE2__ - __m128 *m_gausstab_sse; + __m128 *m_gausstab_sse; #endif - int m_filtersize; - void updateGauss(); -public: - GaussianYBlurOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], int x, int y, void *data); - - void executeOpenCL(OpenCLDevice *device, - MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, - MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, - list<cl_kernel> *clKernelsToCleanUp); - - /** - * \brief initialize the execution - */ - void initExecution(); - - /** - * Deinitialize the execution - */ - void deinitExecution(); - - void *initializeTileData(rcti *rect); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - - void checkOpenCL() { - this->setOpenCL(m_data.sizex >= 128); - } + int m_filtersize; + void updateGauss(); + + public: + GaussianYBlurOperation(); + + /** + * the inner loop of this program + */ + void executePixel(float output[4], int x, int y, void *data); + + void executeOpenCL(OpenCLDevice *device, + MemoryBuffer *outputMemoryBuffer, + cl_mem clOutputBuffer, + MemoryBuffer **inputMemoryBuffers, + list<cl_mem> *clMemToCleanUp, + list<cl_kernel> *clKernelsToCleanUp); + + /** + * \brief initialize the execution + */ + void initExecution(); + + /** + * Deinitialize the execution + */ + void deinitExecution(); + + void *initializeTileData(rcti *rect); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + + void checkOpenCL() + { + this->setOpenCL(m_data.sizex >= 128); + } }; #endif diff --git a/source/blender/compositor/operations/COM_GlareBaseOperation.cpp b/source/blender/compositor/operations/COM_GlareBaseOperation.cpp index 1d98ef65671..593f1eaeefa 100644 --- a/source/blender/compositor/operations/COM_GlareBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_GlareBaseOperation.cpp @@ -21,47 +21,49 @@ GlareBaseOperation::GlareBaseOperation() : SingleThreadedOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - this->m_settings = NULL; + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); + this->m_settings = NULL; } void GlareBaseOperation::initExecution() { - SingleThreadedOperation::initExecution(); - this->m_inputProgram = getInputSocketReader(0); + SingleThreadedOperation::initExecution(); + this->m_inputProgram = getInputSocketReader(0); } void GlareBaseOperation::deinitExecution() { - this->m_inputProgram = NULL; - SingleThreadedOperation::deinitExecution(); + this->m_inputProgram = NULL; + SingleThreadedOperation::deinitExecution(); } MemoryBuffer *GlareBaseOperation::createMemoryBuffer(rcti *rect2) { - MemoryBuffer *tile = (MemoryBuffer *)this->m_inputProgram->initializeTileData(rect2); - rcti rect; - rect.xmin = 0; - rect.ymin = 0; - rect.xmax = getWidth(); - rect.ymax = getHeight(); - MemoryBuffer *result = new MemoryBuffer(COM_DT_COLOR, &rect); - float *data = result->getBuffer(); - this->generateGlare(data, tile, this->m_settings); - return result; + MemoryBuffer *tile = (MemoryBuffer *)this->m_inputProgram->initializeTileData(rect2); + rcti rect; + rect.xmin = 0; + rect.ymin = 0; + rect.xmax = getWidth(); + rect.ymax = getHeight(); + MemoryBuffer *result = new MemoryBuffer(COM_DT_COLOR, &rect); + float *data = result->getBuffer(); + this->generateGlare(data, tile, this->m_settings); + return result; } -bool GlareBaseOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output) +bool GlareBaseOperation::determineDependingAreaOfInterest(rcti * /*input*/, + ReadBufferOperation *readOperation, + rcti *output) { - if (isCached()) { - return false; - } - else { - rcti newInput; - newInput.xmax = this->getWidth(); - newInput.xmin = 0; - newInput.ymax = this->getHeight(); - newInput.ymin = 0; - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); - } + if (isCached()) { + return false; + } + else { + rcti newInput; + newInput.xmax = this->getWidth(); + newInput.xmin = 0; + newInput.ymax = this->getHeight(); + newInput.ymin = 0; + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + } } diff --git a/source/blender/compositor/operations/COM_GlareBaseOperation.h b/source/blender/compositor/operations/COM_GlareBaseOperation.h index 3353b087b3b..ba2b9a8f4b8 100644 --- a/source/blender/compositor/operations/COM_GlareBaseOperation.h +++ b/source/blender/compositor/operations/COM_GlareBaseOperation.h @@ -22,49 +22,56 @@ #include "COM_SingleThreadedOperation.h" #include "DNA_node_types.h" - /* utility functions used by glare, tonemap and lens distortion */ /* soms macros for color handling */ typedef float fRGB[4]; /* TODO - replace with BLI_math_vector */ /* multiply c2 by color rgb, rgb as separate arguments */ -#define fRGB_rgbmult(c, r, g, b) { c[0] *= (r); c[1] *= (g); c[2] *= (b); } (void)0 - +#define fRGB_rgbmult(c, r, g, b) \ + { \ + c[0] *= (r); \ + c[1] *= (g); \ + c[2] *= (b); \ + } \ + (void)0 class GlareBaseOperation : public SingleThreadedOperation { -private: - /** - * \brief Cached reference to the inputProgram - */ - SocketReader *m_inputProgram; + private: + /** + * \brief Cached reference to the inputProgram + */ + SocketReader *m_inputProgram; - /** - * \brief settings of the glare node. - */ - NodeGlare *m_settings; -public: - /** - * Initialize the execution - */ - void initExecution(); + /** + * \brief settings of the glare node. + */ + NodeGlare *m_settings; - /** - * Deinitialize the execution - */ - void deinitExecution(); + public: + /** + * Initialize the execution + */ + void initExecution(); - void setGlareSettings(NodeGlare *settings) { - this->m_settings = settings; - } - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + /** + * Deinitialize the execution + */ + void deinitExecution(); -protected: - GlareBaseOperation(); + void setGlareSettings(NodeGlare *settings) + { + this->m_settings = settings; + } + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); - virtual void generateGlare(float *data, MemoryBuffer *inputTile, NodeGlare *settings) = 0; + protected: + GlareBaseOperation(); - MemoryBuffer *createMemoryBuffer(rcti *rect); + virtual void generateGlare(float *data, MemoryBuffer *inputTile, NodeGlare *settings) = 0; + MemoryBuffer *createMemoryBuffer(rcti *rect); }; #endif diff --git a/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp b/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp index c74c1899daa..e0a2790b318 100644 --- a/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp +++ b/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp @@ -28,12 +28,16 @@ typedef float fREAL; // returns next highest power of 2 of x, as well it's log2 in L2 static unsigned int nextPow2(unsigned int x, unsigned int *L2) { - unsigned int pw, x_notpow2 = x & (x - 1); - *L2 = 0; - while (x >>= 1) ++(*L2); - pw = 1 << (*L2); - if (x_notpow2) { (*L2)++; pw <<= 1; } - return pw; + unsigned int pw, x_notpow2 = x & (x - 1); + *L2 = 0; + while (x >>= 1) + ++(*L2); + pw = 1 << (*L2); + if (x_notpow2) { + (*L2)++; + pw <<= 1; + } + return pw; } //------------------------------------------------------------------------------ @@ -42,143 +46,145 @@ static unsigned int nextPow2(unsigned int x, unsigned int *L2) // use: r = revbin_upd(r, h) where h = N>>1 static unsigned int revbin_upd(unsigned int r, unsigned int h) { - while (!((r ^= h) & h)) h >>= 1; - return r; + while (!((r ^= h) & h)) + h >>= 1; + return r; } //------------------------------------------------------------------------------ static void FHT(fREAL *data, unsigned int M, unsigned int inverse) { - double tt, fc, dc, fs, ds, a = M_PI; - fREAL t1, t2; - int n2, bd, bl, istep, k, len = 1 << M, n = 1; - - int i, j = 0; - unsigned int Nh = len >> 1; - for (i = 1; i < (len - 1); ++i) { - j = revbin_upd(j, Nh); - if (j > i) { - t1 = data[i]; - data[i] = data[j]; - data[j] = t1; - } - } - - do { - fREAL *data_n = &data[n]; - - istep = n << 1; - for (k = 0; k < len; k += istep) { - t1 = data_n[k]; - data_n[k] = data[k] - t1; - data[k] += t1; - } - - n2 = n >> 1; - if (n > 2) { - fc = dc = cos(a); - fs = ds = sqrt(1.0 - fc * fc); //sin(a); - bd = n - 2; - for (bl = 1; bl < n2; bl++) { - fREAL *data_nbd = &data_n[bd]; - fREAL *data_bd = &data[bd]; - for (k = bl; k < len; k += istep) { - t1 = fc * (double)data_n[k] + fs * (double)data_nbd[k]; - t2 = fs * (double)data_n[k] - fc * (double)data_nbd[k]; - data_n[k] = data[k] - t1; - data_nbd[k] = data_bd[k] - t2; - data[k] += t1; - data_bd[k] += t2; - } - tt = fc * dc - fs * ds; - fs = fs * dc + fc * ds; - fc = tt; - bd -= 2; - } - } - - if (n > 1) { - for (k = n2; k < len; k += istep) { - t1 = data_n[k]; - data_n[k] = data[k] - t1; - data[k] += t1; - } - } - - n = istep; - a *= 0.5; - } while (n < len); - - if (inverse) { - fREAL sc = (fREAL)1 / (fREAL)len; - for (k = 0; k < len; ++k) - data[k] *= sc; - } + double tt, fc, dc, fs, ds, a = M_PI; + fREAL t1, t2; + int n2, bd, bl, istep, k, len = 1 << M, n = 1; + + int i, j = 0; + unsigned int Nh = len >> 1; + for (i = 1; i < (len - 1); ++i) { + j = revbin_upd(j, Nh); + if (j > i) { + t1 = data[i]; + data[i] = data[j]; + data[j] = t1; + } + } + + do { + fREAL *data_n = &data[n]; + + istep = n << 1; + for (k = 0; k < len; k += istep) { + t1 = data_n[k]; + data_n[k] = data[k] - t1; + data[k] += t1; + } + + n2 = n >> 1; + if (n > 2) { + fc = dc = cos(a); + fs = ds = sqrt(1.0 - fc * fc); //sin(a); + bd = n - 2; + for (bl = 1; bl < n2; bl++) { + fREAL *data_nbd = &data_n[bd]; + fREAL *data_bd = &data[bd]; + for (k = bl; k < len; k += istep) { + t1 = fc * (double)data_n[k] + fs * (double)data_nbd[k]; + t2 = fs * (double)data_n[k] - fc * (double)data_nbd[k]; + data_n[k] = data[k] - t1; + data_nbd[k] = data_bd[k] - t2; + data[k] += t1; + data_bd[k] += t2; + } + tt = fc * dc - fs * ds; + fs = fs * dc + fc * ds; + fc = tt; + bd -= 2; + } + } + + if (n > 1) { + for (k = n2; k < len; k += istep) { + t1 = data_n[k]; + data_n[k] = data[k] - t1; + data[k] += t1; + } + } + + n = istep; + a *= 0.5; + } while (n < len); + + if (inverse) { + fREAL sc = (fREAL)1 / (fREAL)len; + for (k = 0; k < len; ++k) + data[k] *= sc; + } } //------------------------------------------------------------------------------ /* 2D Fast Hartley Transform, Mx/My -> log2 of width/height, * nzp -> the row where zero pad data starts, * inverse -> see above */ -static void FHT2D(fREAL *data, unsigned int Mx, unsigned int My, - unsigned int nzp, unsigned int inverse) +static void FHT2D( + fREAL *data, unsigned int Mx, unsigned int My, unsigned int nzp, unsigned int inverse) { - unsigned int i, j, Nx, Ny, maxy; - - Nx = 1 << Mx; - Ny = 1 << My; - - // rows (forward transform skips 0 pad data) - maxy = inverse ? Ny : nzp; - for (j = 0; j < maxy; ++j) - FHT(&data[Nx * j], Mx, inverse); - - // transpose data - if (Nx == Ny) { // square - for (j = 0; j < Ny; ++j) - for (i = j + 1; i < Nx; ++i) { - unsigned int op = i + (j << Mx), np = j + (i << My); - SWAP(fREAL, data[op], data[np]); - } - } - else { // rectangular - unsigned int k, Nym = Ny - 1, stm = 1 << (Mx + My); - for (i = 0; stm > 0; i++) { + unsigned int i, j, Nx, Ny, maxy; + + Nx = 1 << Mx; + Ny = 1 << My; + + // rows (forward transform skips 0 pad data) + maxy = inverse ? Ny : nzp; + for (j = 0; j < maxy; ++j) + FHT(&data[Nx * j], Mx, inverse); + + // transpose data + if (Nx == Ny) { // square + for (j = 0; j < Ny; ++j) + for (i = j + 1; i < Nx; ++i) { + unsigned int op = i + (j << Mx), np = j + (i << My); + SWAP(fREAL, data[op], data[np]); + } + } + else { // rectangular + unsigned int k, Nym = Ny - 1, stm = 1 << (Mx + My); + for (i = 0; stm > 0; i++) { #define PRED(k) (((k & Nym) << Mx) + (k >> My)) - for (j = PRED(i); j > i; j = PRED(j)) ; - if (j < i) continue; - for (k = i, j = PRED(i); j != i; k = j, j = PRED(j), stm--) { - SWAP(fREAL, data[j], data[k]); - } + for (j = PRED(i); j > i; j = PRED(j)) + ; + if (j < i) + continue; + for (k = i, j = PRED(i); j != i; k = j, j = PRED(j), stm--) { + SWAP(fREAL, data[j], data[k]); + } #undef PRED - stm--; - } - } - - SWAP(unsigned int, Nx, Ny); - SWAP(unsigned int, Mx, My); - - // now columns == transposed rows - for (j = 0; j < Ny; ++j) - FHT(&data[Nx * j], Mx, inverse); - - // finalize - for (j = 0; j <= (Ny >> 1); j++) { - unsigned int jm = (Ny - j) & (Ny - 1); - unsigned int ji = j << Mx; - unsigned int jmi = jm << Mx; - for (i = 0; i <= (Nx >> 1); i++) { - unsigned int im = (Nx - i) & (Nx - 1); - fREAL A = data[ji + i]; - fREAL B = data[jmi + i]; - fREAL C = data[ji + im]; - fREAL D = data[jmi + im]; - fREAL E = (fREAL)0.5 * ((A + D) - (B + C)); - data[ji + i] = A - E; - data[jmi + i] = B + E; - data[ji + im] = C + E; - data[jmi + im] = D - E; - } - } - + stm--; + } + } + + SWAP(unsigned int, Nx, Ny); + SWAP(unsigned int, Mx, My); + + // now columns == transposed rows + for (j = 0; j < Ny; ++j) + FHT(&data[Nx * j], Mx, inverse); + + // finalize + for (j = 0; j <= (Ny >> 1); j++) { + unsigned int jm = (Ny - j) & (Ny - 1); + unsigned int ji = j << Mx; + unsigned int jmi = jm << Mx; + for (i = 0; i <= (Nx >> 1); i++) { + unsigned int im = (Nx - i) & (Nx - 1); + fREAL A = data[ji + i]; + fREAL B = data[jmi + i]; + fREAL C = data[ji + im]; + fREAL D = data[jmi + im]; + fREAL E = (fREAL)0.5 * ((A + D) - (B + C)); + data[ji + i] = A - E; + data[jmi + i] = B + E; + data[ji + im] = C + E; + data[jmi + im] = D - E; + } + } } //------------------------------------------------------------------------------ @@ -186,218 +192,232 @@ static void FHT2D(fREAL *data, unsigned int Mx, unsigned int My, /* 2D convolution calc, d1 *= d2, M/N - > log2 of width/height */ static void fht_convolve(fREAL *d1, fREAL *d2, unsigned int M, unsigned int N) { - fREAL a, b; - unsigned int i, j, k, L, mj, mL; - unsigned int m = 1 << M, n = 1 << N; - unsigned int m2 = 1 << (M - 1), n2 = 1 << (N - 1); - unsigned int mn2 = m << (N - 1); - - d1[0] *= d2[0]; - d1[mn2] *= d2[mn2]; - d1[m2] *= d2[m2]; - d1[m2 + mn2] *= d2[m2 + mn2]; - for (i = 1; i < m2; i++) { - k = m - i; - a = d1[i] * d2[i] - d1[k] * d2[k]; - b = d1[k] * d2[i] + d1[i] * d2[k]; - d1[i] = (b + a) * (fREAL)0.5; - d1[k] = (b - a) * (fREAL)0.5; - a = d1[i + mn2] * d2[i + mn2] - d1[k + mn2] * d2[k + mn2]; - b = d1[k + mn2] * d2[i + mn2] + d1[i + mn2] * d2[k + mn2]; - d1[i + mn2] = (b + a) * (fREAL)0.5; - d1[k + mn2] = (b - a) * (fREAL)0.5; - } - for (j = 1; j < n2; j++) { - L = n - j; - mj = j << M; - mL = L << M; - a = d1[mj] * d2[mj] - d1[mL] * d2[mL]; - b = d1[mL] * d2[mj] + d1[mj] * d2[mL]; - d1[mj] = (b + a) * (fREAL)0.5; - d1[mL] = (b - a) * (fREAL)0.5; - a = d1[m2 + mj] * d2[m2 + mj] - d1[m2 + mL] * d2[m2 + mL]; - b = d1[m2 + mL] * d2[m2 + mj] + d1[m2 + mj] * d2[m2 + mL]; - d1[m2 + mj] = (b + a) * (fREAL)0.5; - d1[m2 + mL] = (b - a) * (fREAL)0.5; - } - for (i = 1; i < m2; i++) { - k = m - i; - for (j = 1; j < n2; j++) { - L = n - j; - mj = j << M; - mL = L << M; - a = d1[i + mj] * d2[i + mj] - d1[k + mL] * d2[k + mL]; - b = d1[k + mL] * d2[i + mj] + d1[i + mj] * d2[k + mL]; - d1[i + mj] = (b + a) * (fREAL)0.5; - d1[k + mL] = (b - a) * (fREAL)0.5; - a = d1[i + mL] * d2[i + mL] - d1[k + mj] * d2[k + mj]; - b = d1[k + mj] * d2[i + mL] + d1[i + mL] * d2[k + mj]; - d1[i + mL] = (b + a) * (fREAL)0.5; - d1[k + mj] = (b - a) * (fREAL)0.5; - } - } + fREAL a, b; + unsigned int i, j, k, L, mj, mL; + unsigned int m = 1 << M, n = 1 << N; + unsigned int m2 = 1 << (M - 1), n2 = 1 << (N - 1); + unsigned int mn2 = m << (N - 1); + + d1[0] *= d2[0]; + d1[mn2] *= d2[mn2]; + d1[m2] *= d2[m2]; + d1[m2 + mn2] *= d2[m2 + mn2]; + for (i = 1; i < m2; i++) { + k = m - i; + a = d1[i] * d2[i] - d1[k] * d2[k]; + b = d1[k] * d2[i] + d1[i] * d2[k]; + d1[i] = (b + a) * (fREAL)0.5; + d1[k] = (b - a) * (fREAL)0.5; + a = d1[i + mn2] * d2[i + mn2] - d1[k + mn2] * d2[k + mn2]; + b = d1[k + mn2] * d2[i + mn2] + d1[i + mn2] * d2[k + mn2]; + d1[i + mn2] = (b + a) * (fREAL)0.5; + d1[k + mn2] = (b - a) * (fREAL)0.5; + } + for (j = 1; j < n2; j++) { + L = n - j; + mj = j << M; + mL = L << M; + a = d1[mj] * d2[mj] - d1[mL] * d2[mL]; + b = d1[mL] * d2[mj] + d1[mj] * d2[mL]; + d1[mj] = (b + a) * (fREAL)0.5; + d1[mL] = (b - a) * (fREAL)0.5; + a = d1[m2 + mj] * d2[m2 + mj] - d1[m2 + mL] * d2[m2 + mL]; + b = d1[m2 + mL] * d2[m2 + mj] + d1[m2 + mj] * d2[m2 + mL]; + d1[m2 + mj] = (b + a) * (fREAL)0.5; + d1[m2 + mL] = (b - a) * (fREAL)0.5; + } + for (i = 1; i < m2; i++) { + k = m - i; + for (j = 1; j < n2; j++) { + L = n - j; + mj = j << M; + mL = L << M; + a = d1[i + mj] * d2[i + mj] - d1[k + mL] * d2[k + mL]; + b = d1[k + mL] * d2[i + mj] + d1[i + mj] * d2[k + mL]; + d1[i + mj] = (b + a) * (fREAL)0.5; + d1[k + mL] = (b - a) * (fREAL)0.5; + a = d1[i + mL] * d2[i + mL] - d1[k + mj] * d2[k + mj]; + b = d1[k + mj] * d2[i + mL] + d1[i + mL] * d2[k + mj]; + d1[i + mL] = (b + a) * (fREAL)0.5; + d1[k + mj] = (b - a) * (fREAL)0.5; + } + } } //------------------------------------------------------------------------------ static void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2) { - fREAL *data1, *data2, *fp; - unsigned int w2, h2, hw, hh, log2_w, log2_h; - fRGB wt, *colp; - int x, y, ch; - int xbl, ybl, nxb, nyb, xbsz, ybsz; - bool in2done = false; - const unsigned int kernelWidth = in2->getWidth(); - const unsigned int kernelHeight = in2->getHeight(); - const unsigned int imageWidth = in1->getWidth(); - const unsigned int imageHeight = in1->getHeight(); - float *kernelBuffer = in2->getBuffer(); - float *imageBuffer = in1->getBuffer(); - - MemoryBuffer *rdst = new MemoryBuffer(COM_DT_COLOR, in1->getRect()); - memset(rdst->getBuffer(), 0, rdst->getWidth() * rdst->getHeight() * COM_NUM_CHANNELS_COLOR * sizeof(float)); - - // convolution result width & height - w2 = 2 * kernelWidth - 1; - h2 = 2 * kernelHeight - 1; - // FFT pow2 required size & log2 - w2 = nextPow2(w2, &log2_w); - h2 = nextPow2(h2, &log2_h); - - // alloc space - data1 = (fREAL *)MEM_callocN(3 * w2 * h2 * sizeof(fREAL), "convolve_fast FHT data1"); - data2 = (fREAL *)MEM_callocN(w2 * h2 * sizeof(fREAL), "convolve_fast FHT data2"); - - // normalize convolutor - wt[0] = wt[1] = wt[2] = 0.0f; - for (y = 0; y < kernelHeight; y++) { - colp = (fRGB *)&kernelBuffer[y * kernelWidth * COM_NUM_CHANNELS_COLOR]; - for (x = 0; x < kernelWidth; x++) - add_v3_v3(wt, colp[x]); - } - if (wt[0] != 0.0f) wt[0] = 1.0f / wt[0]; - if (wt[1] != 0.0f) wt[1] = 1.0f / wt[1]; - if (wt[2] != 0.0f) wt[2] = 1.0f / wt[2]; - for (y = 0; y < kernelHeight; y++) { - colp = (fRGB *)&kernelBuffer[y * kernelWidth * COM_NUM_CHANNELS_COLOR]; - for (x = 0; x < kernelWidth; x++) - mul_v3_v3(colp[x], wt); - } - - // copy image data, unpacking interleaved RGBA into separate channels - // only need to calc data1 once - - // block add-overlap - hw = kernelWidth >> 1; - hh = kernelHeight >> 1; - xbsz = (w2 + 1) - kernelWidth; - ybsz = (h2 + 1) - kernelHeight; - nxb = imageWidth / xbsz; - if (imageWidth % xbsz) nxb++; - nyb = imageHeight / ybsz; - if (imageHeight % ybsz) nyb++; - for (ybl = 0; ybl < nyb; ybl++) { - for (xbl = 0; xbl < nxb; xbl++) { - - // each channel one by one - for (ch = 0; ch < 3; ch++) { - fREAL *data1ch = &data1[ch * w2 * h2]; - - // only need to calc fht data from in2 once, can re-use for every block - if (!in2done) { - // in2, channel ch -> data1 - for (y = 0; y < kernelHeight; y++) { - fp = &data1ch[y * w2]; - colp = (fRGB *)&kernelBuffer[y * kernelWidth * COM_NUM_CHANNELS_COLOR]; - for (x = 0; x < kernelWidth; x++) - fp[x] = colp[x][ch]; - } - } - - // in1, channel ch -> data2 - memset(data2, 0, w2 * h2 * sizeof(fREAL)); - for (y = 0; y < ybsz; y++) { - int yy = ybl * ybsz + y; - if (yy >= imageHeight) continue; - fp = &data2[y * w2]; - colp = (fRGB *)&imageBuffer[yy * imageWidth * COM_NUM_CHANNELS_COLOR]; - for (x = 0; x < xbsz; x++) { - int xx = xbl * xbsz + x; - if (xx >= imageWidth) continue; - fp[x] = colp[xx][ch]; - } - } - - // forward FHT - // zero pad data start is different for each == height+1 - if (!in2done) FHT2D(data1ch, log2_w, log2_h, kernelHeight + 1, 0); - FHT2D(data2, log2_w, log2_h, kernelHeight + 1, 0); - - // FHT2D transposed data, row/col now swapped - // convolve & inverse FHT - fht_convolve(data2, data1ch, log2_h, log2_w); - FHT2D(data2, log2_h, log2_w, 0, 1); - // data again transposed, so in order again - - // overlap-add result - for (y = 0; y < (int)h2; y++) { - const int yy = ybl * ybsz + y - hh; - if ((yy < 0) || (yy >= imageHeight)) continue; - fp = &data2[y * w2]; - colp = (fRGB *)&rdst->getBuffer()[yy * imageWidth * COM_NUM_CHANNELS_COLOR]; - for (x = 0; x < (int)w2; x++) { - const int xx = xbl * xbsz + x - hw; - if ((xx < 0) || (xx >= imageWidth)) continue; - colp[xx][ch] += fp[x]; - } - } - - } - in2done = true; - } - } - - MEM_freeN(data2); - MEM_freeN(data1); - memcpy(dst, rdst->getBuffer(), sizeof(float) * imageWidth * imageHeight * COM_NUM_CHANNELS_COLOR); - delete(rdst); + fREAL *data1, *data2, *fp; + unsigned int w2, h2, hw, hh, log2_w, log2_h; + fRGB wt, *colp; + int x, y, ch; + int xbl, ybl, nxb, nyb, xbsz, ybsz; + bool in2done = false; + const unsigned int kernelWidth = in2->getWidth(); + const unsigned int kernelHeight = in2->getHeight(); + const unsigned int imageWidth = in1->getWidth(); + const unsigned int imageHeight = in1->getHeight(); + float *kernelBuffer = in2->getBuffer(); + float *imageBuffer = in1->getBuffer(); + + MemoryBuffer *rdst = new MemoryBuffer(COM_DT_COLOR, in1->getRect()); + memset(rdst->getBuffer(), + 0, + rdst->getWidth() * rdst->getHeight() * COM_NUM_CHANNELS_COLOR * sizeof(float)); + + // convolution result width & height + w2 = 2 * kernelWidth - 1; + h2 = 2 * kernelHeight - 1; + // FFT pow2 required size & log2 + w2 = nextPow2(w2, &log2_w); + h2 = nextPow2(h2, &log2_h); + + // alloc space + data1 = (fREAL *)MEM_callocN(3 * w2 * h2 * sizeof(fREAL), "convolve_fast FHT data1"); + data2 = (fREAL *)MEM_callocN(w2 * h2 * sizeof(fREAL), "convolve_fast FHT data2"); + + // normalize convolutor + wt[0] = wt[1] = wt[2] = 0.0f; + for (y = 0; y < kernelHeight; y++) { + colp = (fRGB *)&kernelBuffer[y * kernelWidth * COM_NUM_CHANNELS_COLOR]; + for (x = 0; x < kernelWidth; x++) + add_v3_v3(wt, colp[x]); + } + if (wt[0] != 0.0f) + wt[0] = 1.0f / wt[0]; + if (wt[1] != 0.0f) + wt[1] = 1.0f / wt[1]; + if (wt[2] != 0.0f) + wt[2] = 1.0f / wt[2]; + for (y = 0; y < kernelHeight; y++) { + colp = (fRGB *)&kernelBuffer[y * kernelWidth * COM_NUM_CHANNELS_COLOR]; + for (x = 0; x < kernelWidth; x++) + mul_v3_v3(colp[x], wt); + } + + // copy image data, unpacking interleaved RGBA into separate channels + // only need to calc data1 once + + // block add-overlap + hw = kernelWidth >> 1; + hh = kernelHeight >> 1; + xbsz = (w2 + 1) - kernelWidth; + ybsz = (h2 + 1) - kernelHeight; + nxb = imageWidth / xbsz; + if (imageWidth % xbsz) + nxb++; + nyb = imageHeight / ybsz; + if (imageHeight % ybsz) + nyb++; + for (ybl = 0; ybl < nyb; ybl++) { + for (xbl = 0; xbl < nxb; xbl++) { + + // each channel one by one + for (ch = 0; ch < 3; ch++) { + fREAL *data1ch = &data1[ch * w2 * h2]; + + // only need to calc fht data from in2 once, can re-use for every block + if (!in2done) { + // in2, channel ch -> data1 + for (y = 0; y < kernelHeight; y++) { + fp = &data1ch[y * w2]; + colp = (fRGB *)&kernelBuffer[y * kernelWidth * COM_NUM_CHANNELS_COLOR]; + for (x = 0; x < kernelWidth; x++) + fp[x] = colp[x][ch]; + } + } + + // in1, channel ch -> data2 + memset(data2, 0, w2 * h2 * sizeof(fREAL)); + for (y = 0; y < ybsz; y++) { + int yy = ybl * ybsz + y; + if (yy >= imageHeight) + continue; + fp = &data2[y * w2]; + colp = (fRGB *)&imageBuffer[yy * imageWidth * COM_NUM_CHANNELS_COLOR]; + for (x = 0; x < xbsz; x++) { + int xx = xbl * xbsz + x; + if (xx >= imageWidth) + continue; + fp[x] = colp[xx][ch]; + } + } + + // forward FHT + // zero pad data start is different for each == height+1 + if (!in2done) + FHT2D(data1ch, log2_w, log2_h, kernelHeight + 1, 0); + FHT2D(data2, log2_w, log2_h, kernelHeight + 1, 0); + + // FHT2D transposed data, row/col now swapped + // convolve & inverse FHT + fht_convolve(data2, data1ch, log2_h, log2_w); + FHT2D(data2, log2_h, log2_w, 0, 1); + // data again transposed, so in order again + + // overlap-add result + for (y = 0; y < (int)h2; y++) { + const int yy = ybl * ybsz + y - hh; + if ((yy < 0) || (yy >= imageHeight)) + continue; + fp = &data2[y * w2]; + colp = (fRGB *)&rdst->getBuffer()[yy * imageWidth * COM_NUM_CHANNELS_COLOR]; + for (x = 0; x < (int)w2; x++) { + const int xx = xbl * xbsz + x - hw; + if ((xx < 0) || (xx >= imageWidth)) + continue; + colp[xx][ch] += fp[x]; + } + } + } + in2done = true; + } + } + + MEM_freeN(data2); + MEM_freeN(data1); + memcpy( + dst, rdst->getBuffer(), sizeof(float) * imageWidth * imageHeight * COM_NUM_CHANNELS_COLOR); + delete (rdst); } -void GlareFogGlowOperation::generateGlare(float *data, MemoryBuffer *inputTile, NodeGlare *settings) +void GlareFogGlowOperation::generateGlare(float *data, + MemoryBuffer *inputTile, + NodeGlare *settings) { - int x, y; - float scale, u, v, r, w, d; - fRGB fcol; - MemoryBuffer *ckrn; - unsigned int sz = 1 << settings->size; - const float cs_r = 1.0f, cs_g = 1.0f, cs_b = 1.0f; - - // temp. src image - // make the convolution kernel - rcti kernelRect; - BLI_rcti_init(&kernelRect, 0, sz, 0, sz); - ckrn = new MemoryBuffer(COM_DT_COLOR, &kernelRect); - - scale = 0.25f * sqrtf((float)(sz * sz)); - - for (y = 0; y < sz; ++y) { - v = 2.0f * (y / (float)sz) - 1.0f; - for (x = 0; x < sz; ++x) { - u = 2.0f * (x / (float)sz) - 1.0f; - r = (u * u + v * v) * scale; - d = -sqrtf(sqrtf(sqrtf(r))) * 9.0f; - fcol[0] = expf(d * cs_r); - fcol[1] = expf(d * cs_g); - fcol[2] = expf(d * cs_b); - // linear window good enough here, visual result counts, not scientific analysis - //w = (1.0f-fabs(u))*(1.0f-fabs(v)); - // actually, Hanning window is ok, cos^2 for some reason is slower - w = (0.5f + 0.5f * cosf(u * (float)M_PI)) * (0.5f + 0.5f * cosf(v * (float)M_PI)); - mul_v3_fl(fcol, w); - ckrn->writePixel(x, y, fcol); - } - } - - convolve(data, inputTile, ckrn); - delete ckrn; + int x, y; + float scale, u, v, r, w, d; + fRGB fcol; + MemoryBuffer *ckrn; + unsigned int sz = 1 << settings->size; + const float cs_r = 1.0f, cs_g = 1.0f, cs_b = 1.0f; + + // temp. src image + // make the convolution kernel + rcti kernelRect; + BLI_rcti_init(&kernelRect, 0, sz, 0, sz); + ckrn = new MemoryBuffer(COM_DT_COLOR, &kernelRect); + + scale = 0.25f * sqrtf((float)(sz * sz)); + + for (y = 0; y < sz; ++y) { + v = 2.0f * (y / (float)sz) - 1.0f; + for (x = 0; x < sz; ++x) { + u = 2.0f * (x / (float)sz) - 1.0f; + r = (u * u + v * v) * scale; + d = -sqrtf(sqrtf(sqrtf(r))) * 9.0f; + fcol[0] = expf(d * cs_r); + fcol[1] = expf(d * cs_g); + fcol[2] = expf(d * cs_b); + // linear window good enough here, visual result counts, not scientific analysis + //w = (1.0f-fabs(u))*(1.0f-fabs(v)); + // actually, Hanning window is ok, cos^2 for some reason is slower + w = (0.5f + 0.5f * cosf(u * (float)M_PI)) * (0.5f + 0.5f * cosf(v * (float)M_PI)); + mul_v3_fl(fcol, w); + ckrn->writePixel(x, y, fcol); + } + } + + convolve(data, inputTile, ckrn); + delete ckrn; } diff --git a/source/blender/compositor/operations/COM_GlareFogGlowOperation.h b/source/blender/compositor/operations/COM_GlareFogGlowOperation.h index b209e3d4fc6..45067457778 100644 --- a/source/blender/compositor/operations/COM_GlareFogGlowOperation.h +++ b/source/blender/compositor/operations/COM_GlareFogGlowOperation.h @@ -23,9 +23,12 @@ #include "COM_GlareBaseOperation.h" class GlareFogGlowOperation : public GlareBaseOperation { -public: - GlareFogGlowOperation() : GlareBaseOperation() {} -protected: - void generateGlare(float *data, MemoryBuffer *inputTile, NodeGlare *settings); + public: + GlareFogGlowOperation() : GlareBaseOperation() + { + } + + protected: + void generateGlare(float *data, MemoryBuffer *inputTile, NodeGlare *settings); }; #endif diff --git a/source/blender/compositor/operations/COM_GlareGhostOperation.cpp b/source/blender/compositor/operations/COM_GlareGhostOperation.cpp index 852fc6fc6f9..f2bf25327af 100644 --- a/source/blender/compositor/operations/COM_GlareGhostOperation.cpp +++ b/source/blender/compositor/operations/COM_GlareGhostOperation.cpp @@ -22,104 +22,124 @@ static float smoothMask(float x, float y) { - float t; - x = 2.0f * x - 1.0f; - y = 2.0f * y - 1.0f; - if ((t = 1.0f - sqrtf(x * x + y * y)) > 0.0f) { - return t; - } - else { - return 0.0f; - } + float t; + x = 2.0f * x - 1.0f; + y = 2.0f * y - 1.0f; + if ((t = 1.0f - sqrtf(x * x + y * y)) > 0.0f) { + return t; + } + else { + return 0.0f; + } } void GlareGhostOperation::generateGlare(float *data, MemoryBuffer *inputTile, NodeGlare *settings) { - const int qt = 1 << settings->quality; - const float s1 = 4.0f / (float)qt, s2 = 2.0f * s1; - int x, y, n, p, np; - fRGB c, tc, cm[64]; - float sc, isc, u, v, sm, s, t, ofs, scalef[64]; - const float cmo = 1.0f - settings->colmod; + const int qt = 1 << settings->quality; + const float s1 = 4.0f / (float)qt, s2 = 2.0f * s1; + int x, y, n, p, np; + fRGB c, tc, cm[64]; + float sc, isc, u, v, sm, s, t, ofs, scalef[64]; + const float cmo = 1.0f - settings->colmod; - MemoryBuffer *gbuf = inputTile->duplicate(); - MemoryBuffer *tbuf1 = inputTile->duplicate(); + MemoryBuffer *gbuf = inputTile->duplicate(); + MemoryBuffer *tbuf1 = inputTile->duplicate(); - bool breaked = false; + bool breaked = false; - FastGaussianBlurOperation::IIR_gauss(tbuf1, s1, 0, 3); - if (!breaked) FastGaussianBlurOperation::IIR_gauss(tbuf1, s1, 1, 3); - if (isBreaked()) breaked = true; - if (!breaked) FastGaussianBlurOperation::IIR_gauss(tbuf1, s1, 2, 3); + FastGaussianBlurOperation::IIR_gauss(tbuf1, s1, 0, 3); + if (!breaked) + FastGaussianBlurOperation::IIR_gauss(tbuf1, s1, 1, 3); + if (isBreaked()) + breaked = true; + if (!breaked) + FastGaussianBlurOperation::IIR_gauss(tbuf1, s1, 2, 3); - MemoryBuffer *tbuf2 = tbuf1->duplicate(); + MemoryBuffer *tbuf2 = tbuf1->duplicate(); - if (isBreaked()) breaked = true; - if (!breaked) FastGaussianBlurOperation::IIR_gauss(tbuf2, s2, 0, 3); - if (isBreaked()) breaked = true; - if (!breaked) FastGaussianBlurOperation::IIR_gauss(tbuf2, s2, 1, 3); - if (isBreaked()) breaked = true; - if (!breaked) FastGaussianBlurOperation::IIR_gauss(tbuf2, s2, 2, 3); + if (isBreaked()) + breaked = true; + if (!breaked) + FastGaussianBlurOperation::IIR_gauss(tbuf2, s2, 0, 3); + if (isBreaked()) + breaked = true; + if (!breaked) + FastGaussianBlurOperation::IIR_gauss(tbuf2, s2, 1, 3); + if (isBreaked()) + breaked = true; + if (!breaked) + FastGaussianBlurOperation::IIR_gauss(tbuf2, s2, 2, 3); - ofs = (settings->iter & 1) ? 0.5f : 0.0f; - for (x = 0; x < (settings->iter * 4); x++) { - y = x & 3; - cm[x][0] = cm[x][1] = cm[x][2] = 1; - if (y == 1) fRGB_rgbmult(cm[x], 1.0f, cmo, cmo); - if (y == 2) fRGB_rgbmult(cm[x], cmo, cmo, 1.0f); - if (y == 3) fRGB_rgbmult(cm[x], cmo, 1.0f, cmo); - scalef[x] = 2.1f * (1.0f - (x + ofs) / (float)(settings->iter * 4)); - if (x & 1) scalef[x] = -0.99f / scalef[x]; - } + ofs = (settings->iter & 1) ? 0.5f : 0.0f; + for (x = 0; x < (settings->iter * 4); x++) { + y = x & 3; + cm[x][0] = cm[x][1] = cm[x][2] = 1; + if (y == 1) + fRGB_rgbmult(cm[x], 1.0f, cmo, cmo); + if (y == 2) + fRGB_rgbmult(cm[x], cmo, cmo, 1.0f); + if (y == 3) + fRGB_rgbmult(cm[x], cmo, 1.0f, cmo); + scalef[x] = 2.1f * (1.0f - (x + ofs) / (float)(settings->iter * 4)); + if (x & 1) + scalef[x] = -0.99f / scalef[x]; + } - sc = 2.13; - isc = -0.97; - for (y = 0; y < gbuf->getHeight() && (!breaked); y++) { - v = ((float)y + 0.5f) / (float)gbuf->getHeight(); - for (x = 0; x < gbuf->getWidth(); x++) { - u = ((float)x + 0.5f) / (float)gbuf->getWidth(); - s = (u - 0.5f) * sc + 0.5f; - t = (v - 0.5f) * sc + 0.5f; - tbuf1->readBilinear(c, s * gbuf->getWidth(), t * gbuf->getHeight()); - sm = smoothMask(s, t); - mul_v3_fl(c, sm); - s = (u - 0.5f) * isc + 0.5f; - t = (v - 0.5f) * isc + 0.5f; - tbuf2->readBilinear(tc, s * gbuf->getWidth() - 0.5f, t * gbuf->getHeight() - 0.5f); - sm = smoothMask(s, t); - madd_v3_v3fl(c, tc, sm); + sc = 2.13; + isc = -0.97; + for (y = 0; y < gbuf->getHeight() && (!breaked); y++) { + v = ((float)y + 0.5f) / (float)gbuf->getHeight(); + for (x = 0; x < gbuf->getWidth(); x++) { + u = ((float)x + 0.5f) / (float)gbuf->getWidth(); + s = (u - 0.5f) * sc + 0.5f; + t = (v - 0.5f) * sc + 0.5f; + tbuf1->readBilinear(c, s * gbuf->getWidth(), t * gbuf->getHeight()); + sm = smoothMask(s, t); + mul_v3_fl(c, sm); + s = (u - 0.5f) * isc + 0.5f; + t = (v - 0.5f) * isc + 0.5f; + tbuf2->readBilinear(tc, s * gbuf->getWidth() - 0.5f, t * gbuf->getHeight() - 0.5f); + sm = smoothMask(s, t); + madd_v3_v3fl(c, tc, sm); - gbuf->writePixel(x, y, c); - } - if (isBreaked()) breaked = true; + gbuf->writePixel(x, y, c); + } + if (isBreaked()) + breaked = true; + } - } + memset(tbuf1->getBuffer(), + 0, + tbuf1->getWidth() * tbuf1->getHeight() * COM_NUM_CHANNELS_COLOR * sizeof(float)); + for (n = 1; n < settings->iter && (!breaked); n++) { + for (y = 0; y < gbuf->getHeight() && (!breaked); y++) { + v = ((float)y + 0.5f) / (float)gbuf->getHeight(); + for (x = 0; x < gbuf->getWidth(); x++) { + u = ((float)x + 0.5f) / (float)gbuf->getWidth(); + tc[0] = tc[1] = tc[2] = 0.0f; + for (p = 0; p < 4; p++) { + np = (n << 2) + p; + s = (u - 0.5f) * scalef[np] + 0.5f; + t = (v - 0.5f) * scalef[np] + 0.5f; + gbuf->readBilinear(c, s * gbuf->getWidth() - 0.5f, t * gbuf->getHeight() - 0.5f); + mul_v3_v3(c, cm[np]); + sm = smoothMask(s, t) * 0.25f; + madd_v3_v3fl(tc, c, sm); + } + tbuf1->addPixel(x, y, tc); + } + if (isBreaked()) + breaked = true; + } + memcpy(gbuf->getBuffer(), + tbuf1->getBuffer(), + tbuf1->getWidth() * tbuf1->getHeight() * COM_NUM_CHANNELS_COLOR * sizeof(float)); + } + memcpy(data, + gbuf->getBuffer(), + gbuf->getWidth() * gbuf->getHeight() * COM_NUM_CHANNELS_COLOR * sizeof(float)); - memset(tbuf1->getBuffer(), 0, tbuf1->getWidth() * tbuf1->getHeight() * COM_NUM_CHANNELS_COLOR * sizeof(float)); - for (n = 1; n < settings->iter && (!breaked); n++) { - for (y = 0; y < gbuf->getHeight() && (!breaked); y++) { - v = ((float)y + 0.5f) / (float)gbuf->getHeight(); - for (x = 0; x < gbuf->getWidth(); x++) { - u = ((float)x + 0.5f) / (float)gbuf->getWidth(); - tc[0] = tc[1] = tc[2] = 0.0f; - for (p = 0; p < 4; p++) { - np = (n << 2) + p; - s = (u - 0.5f) * scalef[np] + 0.5f; - t = (v - 0.5f) * scalef[np] + 0.5f; - gbuf->readBilinear(c, s * gbuf->getWidth() - 0.5f, t * gbuf->getHeight() - 0.5f); - mul_v3_v3(c, cm[np]); - sm = smoothMask(s, t) * 0.25f; - madd_v3_v3fl(tc, c, sm); - } - tbuf1->addPixel(x, y, tc); - } - if (isBreaked()) breaked = true; - } - memcpy(gbuf->getBuffer(), tbuf1->getBuffer(), tbuf1->getWidth() * tbuf1->getHeight() * COM_NUM_CHANNELS_COLOR * sizeof(float)); - } - memcpy(data, gbuf->getBuffer(), gbuf->getWidth() * gbuf->getHeight() * COM_NUM_CHANNELS_COLOR * sizeof(float)); - - delete gbuf; - delete tbuf1; - delete tbuf2; + delete gbuf; + delete tbuf1; + delete tbuf2; } diff --git a/source/blender/compositor/operations/COM_GlareGhostOperation.h b/source/blender/compositor/operations/COM_GlareGhostOperation.h index 2844ed5f894..c89c239e4d1 100644 --- a/source/blender/compositor/operations/COM_GlareGhostOperation.h +++ b/source/blender/compositor/operations/COM_GlareGhostOperation.h @@ -23,9 +23,12 @@ #include "COM_GlareBaseOperation.h" class GlareGhostOperation : public GlareBaseOperation { -public: - GlareGhostOperation() : GlareBaseOperation() {} -protected: - void generateGlare(float *data, MemoryBuffer *inputTile, NodeGlare *settings); + public: + GlareGhostOperation() : GlareBaseOperation() + { + } + + protected: + void generateGlare(float *data, MemoryBuffer *inputTile, NodeGlare *settings); }; #endif diff --git a/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp b/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp index f984bdade4d..1ceeba18960 100644 --- a/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp +++ b/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp @@ -18,83 +18,85 @@ #include "COM_GlareSimpleStarOperation.h" -void GlareSimpleStarOperation::generateGlare(float *data, MemoryBuffer *inputTile, NodeGlare *settings) +void GlareSimpleStarOperation::generateGlare(float *data, + MemoryBuffer *inputTile, + NodeGlare *settings) { - int i, x, y, ym, yp, xm, xp; - float c[4] = {0, 0, 0, 0}, tc[4] = {0, 0, 0, 0}; - const float f1 = 1.0f - settings->fade; - const float f2 = (1.0f - f1) * 0.5f; + int i, x, y, ym, yp, xm, xp; + float c[4] = {0, 0, 0, 0}, tc[4] = {0, 0, 0, 0}; + const float f1 = 1.0f - settings->fade; + const float f2 = (1.0f - f1) * 0.5f; - MemoryBuffer *tbuf1 = inputTile->duplicate(); - MemoryBuffer *tbuf2 = inputTile->duplicate(); + MemoryBuffer *tbuf1 = inputTile->duplicate(); + MemoryBuffer *tbuf2 = inputTile->duplicate(); - bool breaked = false; - for (i = 0; i < settings->iter && (!breaked); i++) { -// // (x || x-1, y-1) to (x || x+1, y+1) -// // F - for (y = 0; y < this->getHeight() && (!breaked); y++) { - ym = y - i; - yp = y + i; - for (x = 0; x < this->getWidth(); x++) { - xm = x - i; - xp = x + i; - tbuf1->read(c, x, y); - mul_v3_fl(c, f1); - tbuf1->read(tc, (settings->star_45 ? xm : x), ym); - madd_v3_v3fl(c, tc, f2); - tbuf1->read(tc, (settings->star_45 ? xp : x), yp); - madd_v3_v3fl(c, tc, f2); - c[3] = 1.0f; - tbuf1->writePixel(x, y, c); + bool breaked = false; + for (i = 0; i < settings->iter && (!breaked); i++) { + // // (x || x-1, y-1) to (x || x+1, y+1) + // // F + for (y = 0; y < this->getHeight() && (!breaked); y++) { + ym = y - i; + yp = y + i; + for (x = 0; x < this->getWidth(); x++) { + xm = x - i; + xp = x + i; + tbuf1->read(c, x, y); + mul_v3_fl(c, f1); + tbuf1->read(tc, (settings->star_45 ? xm : x), ym); + madd_v3_v3fl(c, tc, f2); + tbuf1->read(tc, (settings->star_45 ? xp : x), yp); + madd_v3_v3fl(c, tc, f2); + c[3] = 1.0f; + tbuf1->writePixel(x, y, c); - tbuf2->read(c, x, y); - mul_v3_fl(c, f1); - tbuf2->read(tc, xm, (settings->star_45 ? yp : y)); - madd_v3_v3fl(c, tc, f2); - tbuf2->read(tc, xp, (settings->star_45 ? ym : y)); - madd_v3_v3fl(c, tc, f2); - c[3] = 1.0f; - tbuf2->writePixel(x, y, c); - } - if (isBreaked()) { - breaked = true; - } - } -// // B - for (y = this->getHeight() - 1; y >= 0 && (!breaked); y--) { - ym = y - i; - yp = y + i; - for (x = this->getWidth() - 1; x >= 0; x--) { - xm = x - i; - xp = x + i; - tbuf1->read(c, x, y); - mul_v3_fl(c, f1); - tbuf1->read(tc, (settings->star_45 ? xm : x), ym); - madd_v3_v3fl(c, tc, f2); - tbuf1->read(tc, (settings->star_45 ? xp : x), yp); - madd_v3_v3fl(c, tc, f2); - c[3] = 1.0f; - tbuf1->writePixel(x, y, c); + tbuf2->read(c, x, y); + mul_v3_fl(c, f1); + tbuf2->read(tc, xm, (settings->star_45 ? yp : y)); + madd_v3_v3fl(c, tc, f2); + tbuf2->read(tc, xp, (settings->star_45 ? ym : y)); + madd_v3_v3fl(c, tc, f2); + c[3] = 1.0f; + tbuf2->writePixel(x, y, c); + } + if (isBreaked()) { + breaked = true; + } + } + // // B + for (y = this->getHeight() - 1; y >= 0 && (!breaked); y--) { + ym = y - i; + yp = y + i; + for (x = this->getWidth() - 1; x >= 0; x--) { + xm = x - i; + xp = x + i; + tbuf1->read(c, x, y); + mul_v3_fl(c, f1); + tbuf1->read(tc, (settings->star_45 ? xm : x), ym); + madd_v3_v3fl(c, tc, f2); + tbuf1->read(tc, (settings->star_45 ? xp : x), yp); + madd_v3_v3fl(c, tc, f2); + c[3] = 1.0f; + tbuf1->writePixel(x, y, c); - tbuf2->read(c, x, y); - mul_v3_fl(c, f1); - tbuf2->read(tc, xm, (settings->star_45 ? yp : y)); - madd_v3_v3fl(c, tc, f2); - tbuf2->read(tc, xp, (settings->star_45 ? ym : y)); - madd_v3_v3fl(c, tc, f2); - c[3] = 1.0f; - tbuf2->writePixel(x, y, c); - } - if (isBreaked()) { - breaked = true; - } - } - } + tbuf2->read(c, x, y); + mul_v3_fl(c, f1); + tbuf2->read(tc, xm, (settings->star_45 ? yp : y)); + madd_v3_v3fl(c, tc, f2); + tbuf2->read(tc, xp, (settings->star_45 ? ym : y)); + madd_v3_v3fl(c, tc, f2); + c[3] = 1.0f; + tbuf2->writePixel(x, y, c); + } + if (isBreaked()) { + breaked = true; + } + } + } - for (i = 0; i < this->getWidth() * this->getHeight() * 4; i++) { - data[i] = tbuf1->getBuffer()[i] + tbuf2->getBuffer()[i]; - } + for (i = 0; i < this->getWidth() * this->getHeight() * 4; i++) { + data[i] = tbuf1->getBuffer()[i] + tbuf2->getBuffer()[i]; + } - delete tbuf1; - delete tbuf2; + delete tbuf1; + delete tbuf2; } diff --git a/source/blender/compositor/operations/COM_GlareSimpleStarOperation.h b/source/blender/compositor/operations/COM_GlareSimpleStarOperation.h index 3cb66c1212c..a40dfac86ff 100644 --- a/source/blender/compositor/operations/COM_GlareSimpleStarOperation.h +++ b/source/blender/compositor/operations/COM_GlareSimpleStarOperation.h @@ -23,9 +23,12 @@ #include "COM_GlareBaseOperation.h" class GlareSimpleStarOperation : public GlareBaseOperation { -public: - GlareSimpleStarOperation() : GlareBaseOperation() {} -protected: - void generateGlare(float *data, MemoryBuffer *inputTile, NodeGlare *settings); + public: + GlareSimpleStarOperation() : GlareBaseOperation() + { + } + + protected: + void generateGlare(float *data, MemoryBuffer *inputTile, NodeGlare *settings); }; #endif diff --git a/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp b/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp index 18be89af75b..cf60a1378b4 100644 --- a/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp +++ b/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp @@ -19,74 +19,82 @@ #include "COM_GlareStreaksOperation.h" #include "BLI_math.h" -void GlareStreaksOperation::generateGlare(float *data, MemoryBuffer *inputTile, NodeGlare *settings) +void GlareStreaksOperation::generateGlare(float *data, + MemoryBuffer *inputTile, + NodeGlare *settings) { - int x, y, n; - unsigned int nump = 0; - float c1[4], c2[4], c3[4], c4[4]; - float a, ang = DEG2RADF(360.0f) / (float)settings->streaks; + int x, y, n; + unsigned int nump = 0; + float c1[4], c2[4], c3[4], c4[4]; + float a, ang = DEG2RADF(360.0f) / (float)settings->streaks; - int size = inputTile->getWidth() * inputTile->getHeight(); - int size4 = size * 4; + int size = inputTile->getWidth() * inputTile->getHeight(); + int size4 = size * 4; - bool breaked = false; + bool breaked = false; - MemoryBuffer *tsrc = inputTile->duplicate(); - MemoryBuffer *tdst = new MemoryBuffer(COM_DT_COLOR, inputTile->getRect()); - tdst->clear(); - memset(data, 0, size4 * sizeof(float)); + MemoryBuffer *tsrc = inputTile->duplicate(); + MemoryBuffer *tdst = new MemoryBuffer(COM_DT_COLOR, inputTile->getRect()); + tdst->clear(); + memset(data, 0, size4 * sizeof(float)); - for (a = 0.0f; a < DEG2RADF(360.0f) && (!breaked); a += ang) { - const float an = a + settings->angle_ofs; - const float vx = cos((double)an), vy = sin((double)an); - for (n = 0; n < settings->iter && (!breaked); ++n) { - const float p4 = pow(4.0, (double)n); - const float vxp = vx * p4, vyp = vy * p4; - const float wt = pow((double)settings->fade, (double)p4); - const float cmo = 1.0f - (float)pow((double)settings->colmod, (double)n + 1); // colormodulation amount relative to current pass - float *tdstcol = tdst->getBuffer(); - for (y = 0; y < tsrc->getHeight() && (!breaked); ++y) { - for (x = 0; x < tsrc->getWidth(); ++x, tdstcol += 4) { - // first pass no offset, always same for every pass, exact copy, - // otherwise results in uneven brightness, only need once - if (n == 0) tsrc->read(c1, x, y); else c1[0] = c1[1] = c1[2] = 0; - tsrc->readBilinear(c2, x + vxp, y + vyp); - tsrc->readBilinear(c3, x + vxp * 2.0f, y + vyp * 2.0f); - tsrc->readBilinear(c4, x + vxp * 3.0f, y + vyp * 3.0f); - // modulate color to look vaguely similar to a color spectrum - c2[1] *= cmo; - c2[2] *= cmo; + for (a = 0.0f; a < DEG2RADF(360.0f) && (!breaked); a += ang) { + const float an = a + settings->angle_ofs; + const float vx = cos((double)an), vy = sin((double)an); + for (n = 0; n < settings->iter && (!breaked); ++n) { + const float p4 = pow(4.0, (double)n); + const float vxp = vx * p4, vyp = vy * p4; + const float wt = pow((double)settings->fade, (double)p4); + const float cmo = 1.0f - + (float)pow((double)settings->colmod, + (double)n + + 1); // colormodulation amount relative to current pass + float *tdstcol = tdst->getBuffer(); + for (y = 0; y < tsrc->getHeight() && (!breaked); ++y) { + for (x = 0; x < tsrc->getWidth(); ++x, tdstcol += 4) { + // first pass no offset, always same for every pass, exact copy, + // otherwise results in uneven brightness, only need once + if (n == 0) + tsrc->read(c1, x, y); + else + c1[0] = c1[1] = c1[2] = 0; + tsrc->readBilinear(c2, x + vxp, y + vyp); + tsrc->readBilinear(c3, x + vxp * 2.0f, y + vyp * 2.0f); + tsrc->readBilinear(c4, x + vxp * 3.0f, y + vyp * 3.0f); + // modulate color to look vaguely similar to a color spectrum + c2[1] *= cmo; + c2[2] *= cmo; - c3[0] *= cmo; - c3[1] *= cmo; + c3[0] *= cmo; + c3[1] *= cmo; - c4[0] *= cmo; - c4[2] *= cmo; + c4[0] *= cmo; + c4[2] *= cmo; - tdstcol[0] = 0.5f * (tdstcol[0] + c1[0] + wt * (c2[0] + wt * (c3[0] + wt * c4[0]))); - tdstcol[1] = 0.5f * (tdstcol[1] + c1[1] + wt * (c2[1] + wt * (c3[1] + wt * c4[1]))); - tdstcol[2] = 0.5f * (tdstcol[2] + c1[2] + wt * (c2[2] + wt * (c3[2] + wt * c4[2]))); - tdstcol[3] = 1.0f; - } - if (isBreaked()) { - breaked = true; - } - } - memcpy(tsrc->getBuffer(), tdst->getBuffer(), sizeof(float) * size4); - } + tdstcol[0] = 0.5f * (tdstcol[0] + c1[0] + wt * (c2[0] + wt * (c3[0] + wt * c4[0]))); + tdstcol[1] = 0.5f * (tdstcol[1] + c1[1] + wt * (c2[1] + wt * (c3[1] + wt * c4[1]))); + tdstcol[2] = 0.5f * (tdstcol[2] + c1[2] + wt * (c2[2] + wt * (c3[2] + wt * c4[2]))); + tdstcol[3] = 1.0f; + } + if (isBreaked()) { + breaked = true; + } + } + memcpy(tsrc->getBuffer(), tdst->getBuffer(), sizeof(float) * size4); + } - float *sourcebuffer = tsrc->getBuffer(); - float factor = 1.0f / (float)(6 - settings->iter); - for (int i = 0; i < size4; i += 4) { - madd_v3_v3fl(&data[i], &sourcebuffer[i], factor); - data[i + 3] = 1.0f; - } + float *sourcebuffer = tsrc->getBuffer(); + float factor = 1.0f / (float)(6 - settings->iter); + for (int i = 0; i < size4; i += 4) { + madd_v3_v3fl(&data[i], &sourcebuffer[i], factor); + data[i + 3] = 1.0f; + } - tdst->clear(); - memcpy(tsrc->getBuffer(), inputTile->getBuffer(), sizeof(float) * size4); - nump++; - } + tdst->clear(); + memcpy(tsrc->getBuffer(), inputTile->getBuffer(), sizeof(float) * size4); + nump++; + } - delete tsrc; - delete tdst; + delete tsrc; + delete tdst; } diff --git a/source/blender/compositor/operations/COM_GlareStreaksOperation.h b/source/blender/compositor/operations/COM_GlareStreaksOperation.h index cb2356123a5..9150b5e4641 100644 --- a/source/blender/compositor/operations/COM_GlareStreaksOperation.h +++ b/source/blender/compositor/operations/COM_GlareStreaksOperation.h @@ -23,9 +23,12 @@ #include "COM_GlareBaseOperation.h" class GlareStreaksOperation : public GlareBaseOperation { -public: - GlareStreaksOperation() : GlareBaseOperation() {} -protected: - void generateGlare(float *data, MemoryBuffer *inputTile, NodeGlare *settings); + public: + GlareStreaksOperation() : GlareBaseOperation() + { + } + + protected: + void generateGlare(float *data, MemoryBuffer *inputTile, NodeGlare *settings); }; #endif diff --git a/source/blender/compositor/operations/COM_GlareThresholdOperation.cpp b/source/blender/compositor/operations/COM_GlareThresholdOperation.cpp index 75e0ce57980..142c51122a1 100644 --- a/source/blender/compositor/operations/COM_GlareThresholdOperation.cpp +++ b/source/blender/compositor/operations/COM_GlareThresholdOperation.cpp @@ -25,43 +25,47 @@ extern "C" { GlareThresholdOperation::GlareThresholdOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR, COM_SC_FIT); - this->addOutputSocket(COM_DT_COLOR); - this->m_inputProgram = NULL; + this->addInputSocket(COM_DT_COLOR, COM_SC_FIT); + this->addOutputSocket(COM_DT_COLOR); + this->m_inputProgram = NULL; } -void GlareThresholdOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +void GlareThresholdOperation::determineResolution(unsigned int resolution[2], + unsigned int preferredResolution[2]) { - NodeOperation::determineResolution(resolution, preferredResolution); - resolution[0] = resolution[0] / (1 << this->m_settings->quality); - resolution[1] = resolution[1] / (1 << this->m_settings->quality); + NodeOperation::determineResolution(resolution, preferredResolution); + resolution[0] = resolution[0] / (1 << this->m_settings->quality); + resolution[1] = resolution[1] / (1 << this->m_settings->quality); } void GlareThresholdOperation::initExecution() { - this->m_inputProgram = this->getInputSocketReader(0); + this->m_inputProgram = this->getInputSocketReader(0); } -void GlareThresholdOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void GlareThresholdOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - const float threshold = this->m_settings->threshold; + const float threshold = this->m_settings->threshold; - this->m_inputProgram->readSampled(output, x, y, sampler); - if (IMB_colormanagement_get_luminance(output) >= threshold) { - output[0] -= threshold; - output[1] -= threshold; - output[2] -= threshold; + this->m_inputProgram->readSampled(output, x, y, sampler); + if (IMB_colormanagement_get_luminance(output) >= threshold) { + output[0] -= threshold; + output[1] -= threshold; + output[2] -= threshold; - output[0] = max(output[0], 0.0f); - output[1] = max(output[1], 0.0f); - output[2] = max(output[2], 0.0f); - } - else { - zero_v3(output); - } + output[0] = max(output[0], 0.0f); + output[1] = max(output[1], 0.0f); + output[2] = max(output[2], 0.0f); + } + else { + zero_v3(output); + } } void GlareThresholdOperation::deinitExecution() { - this->m_inputProgram = NULL; + this->m_inputProgram = NULL; } diff --git a/source/blender/compositor/operations/COM_GlareThresholdOperation.h b/source/blender/compositor/operations/COM_GlareThresholdOperation.h index 2a38783511f..385111cdf0b 100644 --- a/source/blender/compositor/operations/COM_GlareThresholdOperation.h +++ b/source/blender/compositor/operations/COM_GlareThresholdOperation.h @@ -22,38 +22,40 @@ #include "DNA_light_types.h" class GlareThresholdOperation : public NodeOperation { -private: - /** - * \brief Cached reference to the inputProgram - */ - SocketReader *m_inputProgram; - - /** - * \brief settings of the glare node. - */ - NodeGlare *m_settings; -public: - GlareThresholdOperation(); - - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - - /** - * Initialize the execution - */ - void initExecution(); - - /** - * Deinitialize the execution - */ - void deinitExecution(); - - void setGlareSettings(NodeGlare *settings) { - this->m_settings = settings; - } - - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); + private: + /** + * \brief Cached reference to the inputProgram + */ + SocketReader *m_inputProgram; + + /** + * \brief settings of the glare node. + */ + NodeGlare *m_settings; + + public: + GlareThresholdOperation(); + + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + + /** + * Initialize the execution + */ + void initExecution(); + + /** + * Deinitialize the execution + */ + void deinitExecution(); + + void setGlareSettings(NodeGlare *settings) + { + this->m_settings = settings; + } + + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); }; #endif diff --git a/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.cpp b/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.cpp index 02497725d46..61ad4248fb0 100644 --- a/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.cpp +++ b/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.cpp @@ -23,53 +23,56 @@ #ifdef __cplusplus extern "C" { #endif -# include "BKE_colortools.h" +#include "BKE_colortools.h" #ifdef __cplusplus } #endif HueSaturationValueCorrectOperation::HueSaturationValueCorrectOperation() : CurveBaseOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); - this->m_inputProgram = NULL; + this->m_inputProgram = NULL; } void HueSaturationValueCorrectOperation::initExecution() { - CurveBaseOperation::initExecution(); - this->m_inputProgram = this->getInputSocketReader(0); + CurveBaseOperation::initExecution(); + this->m_inputProgram = this->getInputSocketReader(0); } -void HueSaturationValueCorrectOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void HueSaturationValueCorrectOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float hsv[4], f; + float hsv[4], f; - this->m_inputProgram->readSampled(hsv, x, y, sampler); + this->m_inputProgram->readSampled(hsv, x, y, sampler); - /* adjust hue, scaling returned default 0.5 up to 1 */ - f = curvemapping_evaluateF(this->m_curveMapping, 0, hsv[0]); - hsv[0] += f - 0.5f; + /* adjust hue, scaling returned default 0.5 up to 1 */ + f = curvemapping_evaluateF(this->m_curveMapping, 0, hsv[0]); + hsv[0] += f - 0.5f; - /* adjust saturation, scaling returned default 0.5 up to 1 */ - f = curvemapping_evaluateF(this->m_curveMapping, 1, hsv[0]); - hsv[1] *= (f * 2.0f); + /* adjust saturation, scaling returned default 0.5 up to 1 */ + f = curvemapping_evaluateF(this->m_curveMapping, 1, hsv[0]); + hsv[1] *= (f * 2.0f); - /* adjust value, scaling returned default 0.5 up to 1 */ - f = curvemapping_evaluateF(this->m_curveMapping, 2, hsv[0]); - hsv[2] *= (f * 2.0f); + /* adjust value, scaling returned default 0.5 up to 1 */ + f = curvemapping_evaluateF(this->m_curveMapping, 2, hsv[0]); + hsv[2] *= (f * 2.0f); - hsv[0] = hsv[0] - floorf(hsv[0]); /* mod 1.0 */ - CLAMP(hsv[1], 0.0f, 1.0f); + hsv[0] = hsv[0] - floorf(hsv[0]); /* mod 1.0 */ + CLAMP(hsv[1], 0.0f, 1.0f); - output[0] = hsv[0]; - output[1] = hsv[1]; - output[2] = hsv[2]; - output[3] = hsv[3]; + output[0] = hsv[0]; + output[1] = hsv[1]; + output[2] = hsv[2]; + output[3] = hsv[3]; } void HueSaturationValueCorrectOperation::deinitExecution() { - CurveBaseOperation::deinitExecution(); - this->m_inputProgram = NULL; + CurveBaseOperation::deinitExecution(); + this->m_inputProgram = NULL; } diff --git a/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.h b/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.h index 9d8b6e0aa7b..3e212b96521 100644 --- a/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.h +++ b/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.h @@ -22,28 +22,28 @@ #include "COM_CurveBaseOperation.h" class HueSaturationValueCorrectOperation : public CurveBaseOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputProgram; -public: - HueSaturationValueCorrectOperation(); + private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputProgram; - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + HueSaturationValueCorrectOperation(); - /** - * Initialize the execution - */ - void initExecution(); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Initialize the execution + */ + void initExecution(); + /** + * Deinitialize the execution + */ + void deinitExecution(); }; #endif diff --git a/source/blender/compositor/operations/COM_IDMaskOperation.cpp b/source/blender/compositor/operations/COM_IDMaskOperation.cpp index ce24cfcca79..ef321157320 100644 --- a/source/blender/compositor/operations/COM_IDMaskOperation.cpp +++ b/source/blender/compositor/operations/COM_IDMaskOperation.cpp @@ -20,25 +20,22 @@ IDMaskOperation::IDMaskOperation() : NodeOperation() { - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_VALUE); - this->setComplex(true); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_VALUE); + this->setComplex(true); } void *IDMaskOperation::initializeTileData(rcti *rect) { - void *buffer = getInputOperation(0)->initializeTileData(rect); - return buffer; + void *buffer = getInputOperation(0)->initializeTileData(rect); + return buffer; } -void IDMaskOperation::executePixel(float output[4], - int x, - int y, - void *data) +void IDMaskOperation::executePixel(float output[4], int x, int y, void *data) { - MemoryBuffer *input_buffer = (MemoryBuffer *)data; - const int buffer_width = input_buffer->getWidth(); - float *buffer = input_buffer->getBuffer(); - int buffer_index = (y * buffer_width + x); - output[0] = (roundf(buffer[buffer_index]) == this->m_objectIndex) ? 1.0f : 0.0f; + MemoryBuffer *input_buffer = (MemoryBuffer *)data; + const int buffer_width = input_buffer->getWidth(); + float *buffer = input_buffer->getBuffer(); + int buffer_index = (y * buffer_width + x); + output[0] = (roundf(buffer[buffer_index]) == this->m_objectIndex) ? 1.0f : 0.0f; } diff --git a/source/blender/compositor/operations/COM_IDMaskOperation.h b/source/blender/compositor/operations/COM_IDMaskOperation.h index f2ca267e80a..b3a40106b9d 100644 --- a/source/blender/compositor/operations/COM_IDMaskOperation.h +++ b/source/blender/compositor/operations/COM_IDMaskOperation.h @@ -20,17 +20,19 @@ #define __COM_IDMASKOPERATION_H__ #include "COM_NodeOperation.h" - class IDMaskOperation : public NodeOperation { -private: - float m_objectIndex; -public: - IDMaskOperation(); + private: + float m_objectIndex; - void *initializeTileData(rcti *rect); - void executePixel(float output[4], int x, int y, void *data); + public: + IDMaskOperation(); - void setObjectIndex(float objectIndex) { this->m_objectIndex = objectIndex; } + void *initializeTileData(rcti *rect); + void executePixel(float output[4], int x, int y, void *data); + void setObjectIndex(float objectIndex) + { + this->m_objectIndex = objectIndex; + } }; #endif diff --git a/source/blender/compositor/operations/COM_ImageOperation.cpp b/source/blender/compositor/operations/COM_ImageOperation.cpp index efdd71f7f26..bf9ad441803 100644 --- a/source/blender/compositor/operations/COM_ImageOperation.cpp +++ b/source/blender/compositor/operations/COM_ImageOperation.cpp @@ -25,173 +25,180 @@ #include "BLI_math.h" extern "C" { -# include "RE_pipeline.h" -# include "RE_shader_ext.h" -# include "RE_render_ext.h" -# include "IMB_imbuf.h" -# include "IMB_imbuf_types.h" -# include "IMB_colormanagement.h" +#include "RE_pipeline.h" +#include "RE_shader_ext.h" +#include "RE_render_ext.h" +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" +#include "IMB_colormanagement.h" } BaseImageOperation::BaseImageOperation() : NodeOperation() { - this->m_image = NULL; - this->m_buffer = NULL; - this->m_imageFloatBuffer = NULL; - this->m_imageByteBuffer = NULL; - this->m_imageUser = NULL; - this->m_imagewidth = 0; - this->m_imageheight = 0; - this->m_framenumber = 0; - this->m_depthBuffer = NULL; - this->m_numberOfChannels = 0; - this->m_rd = NULL; - this->m_viewName = NULL; + this->m_image = NULL; + this->m_buffer = NULL; + this->m_imageFloatBuffer = NULL; + this->m_imageByteBuffer = NULL; + this->m_imageUser = NULL; + this->m_imagewidth = 0; + this->m_imageheight = 0; + this->m_framenumber = 0; + this->m_depthBuffer = NULL; + this->m_numberOfChannels = 0; + this->m_rd = NULL; + this->m_viewName = NULL; } ImageOperation::ImageOperation() : BaseImageOperation() { - this->addOutputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); } ImageAlphaOperation::ImageAlphaOperation() : BaseImageOperation() { - this->addOutputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_VALUE); } ImageDepthOperation::ImageDepthOperation() : BaseImageOperation() { - this->addOutputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_VALUE); } ImBuf *BaseImageOperation::getImBuf() { - ImBuf *ibuf; - ImageUser iuser = *this->m_imageUser; - - if (this->m_image == NULL) - return NULL; - - /* local changes to the original ImageUser */ - if (BKE_image_is_multilayer(this->m_image) == false) - iuser.multi_index = BKE_scene_multiview_view_id_get(this->m_rd, this->m_viewName); - - ibuf = BKE_image_acquire_ibuf(this->m_image, &iuser, NULL); - if (ibuf == NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL)) { - BKE_image_release_ibuf(this->m_image, ibuf, NULL); - return NULL; - } - return ibuf; + ImBuf *ibuf; + ImageUser iuser = *this->m_imageUser; + + if (this->m_image == NULL) + return NULL; + + /* local changes to the original ImageUser */ + if (BKE_image_is_multilayer(this->m_image) == false) + iuser.multi_index = BKE_scene_multiview_view_id_get(this->m_rd, this->m_viewName); + + ibuf = BKE_image_acquire_ibuf(this->m_image, &iuser, NULL); + if (ibuf == NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL)) { + BKE_image_release_ibuf(this->m_image, ibuf, NULL); + return NULL; + } + return ibuf; } - void BaseImageOperation::initExecution() { - ImBuf *stackbuf = getImBuf(); - this->m_buffer = stackbuf; - if (stackbuf) { - this->m_imageFloatBuffer = stackbuf->rect_float; - this->m_imageByteBuffer = stackbuf->rect; - this->m_depthBuffer = stackbuf->zbuf_float; - this->m_imagewidth = stackbuf->x; - this->m_imageheight = stackbuf->y; - this->m_numberOfChannels = stackbuf->channels; - } + ImBuf *stackbuf = getImBuf(); + this->m_buffer = stackbuf; + if (stackbuf) { + this->m_imageFloatBuffer = stackbuf->rect_float; + this->m_imageByteBuffer = stackbuf->rect; + this->m_depthBuffer = stackbuf->zbuf_float; + this->m_imagewidth = stackbuf->x; + this->m_imageheight = stackbuf->y; + this->m_numberOfChannels = stackbuf->channels; + } } void BaseImageOperation::deinitExecution() { - this->m_imageFloatBuffer = NULL; - this->m_imageByteBuffer = NULL; - BKE_image_release_ibuf(this->m_image, this->m_buffer, NULL); + this->m_imageFloatBuffer = NULL; + this->m_imageByteBuffer = NULL; + BKE_image_release_ibuf(this->m_image, this->m_buffer, NULL); } -void BaseImageOperation::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2]) +void BaseImageOperation::determineResolution(unsigned int resolution[2], + unsigned int /*preferredResolution*/[2]) { - ImBuf *stackbuf = getImBuf(); + ImBuf *stackbuf = getImBuf(); - resolution[0] = 0; - resolution[1] = 0; + resolution[0] = 0; + resolution[1] = 0; - if (stackbuf) { - resolution[0] = stackbuf->x; - resolution[1] = stackbuf->y; - } + if (stackbuf) { + resolution[0] = stackbuf->x; + resolution[1] = stackbuf->y; + } - BKE_image_release_ibuf(this->m_image, stackbuf, NULL); + BKE_image_release_ibuf(this->m_image, stackbuf, NULL); } -static void sampleImageAtLocation(ImBuf *ibuf, float x, float y, PixelSampler sampler, bool make_linear_rgb, float color[4]) +static void sampleImageAtLocation( + ImBuf *ibuf, float x, float y, PixelSampler sampler, bool make_linear_rgb, float color[4]) { - if (ibuf->rect_float) { - switch (sampler) { - case COM_PS_NEAREST: - nearest_interpolation_color(ibuf, NULL, color, x, y); - break; - case COM_PS_BILINEAR: - bilinear_interpolation_color(ibuf, NULL, color, x, y); - break; - case COM_PS_BICUBIC: - bicubic_interpolation_color(ibuf, NULL, color, x, y); - break; - } - } - else { - unsigned char byte_color[4]; - switch (sampler) { - case COM_PS_NEAREST: - nearest_interpolation_color(ibuf, byte_color, NULL, x, y); - break; - case COM_PS_BILINEAR: - bilinear_interpolation_color(ibuf, byte_color, NULL, x, y); - break; - case COM_PS_BICUBIC: - bicubic_interpolation_color(ibuf, byte_color, NULL, x, y); - break; - } - rgba_uchar_to_float(color, byte_color); - if (make_linear_rgb) { - IMB_colormanagement_colorspace_to_scene_linear_v4(color, false, ibuf->rect_colorspace); - } - } + if (ibuf->rect_float) { + switch (sampler) { + case COM_PS_NEAREST: + nearest_interpolation_color(ibuf, NULL, color, x, y); + break; + case COM_PS_BILINEAR: + bilinear_interpolation_color(ibuf, NULL, color, x, y); + break; + case COM_PS_BICUBIC: + bicubic_interpolation_color(ibuf, NULL, color, x, y); + break; + } + } + else { + unsigned char byte_color[4]; + switch (sampler) { + case COM_PS_NEAREST: + nearest_interpolation_color(ibuf, byte_color, NULL, x, y); + break; + case COM_PS_BILINEAR: + bilinear_interpolation_color(ibuf, byte_color, NULL, x, y); + break; + case COM_PS_BICUBIC: + bicubic_interpolation_color(ibuf, byte_color, NULL, x, y); + break; + } + rgba_uchar_to_float(color, byte_color); + if (make_linear_rgb) { + IMB_colormanagement_colorspace_to_scene_linear_v4(color, false, ibuf->rect_colorspace); + } + } } void ImageOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { - int ix = x, iy = y; - if (this->m_imageFloatBuffer == NULL && this->m_imageByteBuffer == NULL) { - zero_v4(output); - } - else if (ix < 0 || iy < 0 || ix >= this->m_buffer->x || iy >= this->m_buffer->y) { - zero_v4(output); - } - else { - sampleImageAtLocation(this->m_buffer, x, y, sampler, true, output); - } + int ix = x, iy = y; + if (this->m_imageFloatBuffer == NULL && this->m_imageByteBuffer == NULL) { + zero_v4(output); + } + else if (ix < 0 || iy < 0 || ix >= this->m_buffer->x || iy >= this->m_buffer->y) { + zero_v4(output); + } + else { + sampleImageAtLocation(this->m_buffer, x, y, sampler, true, output); + } } -void ImageAlphaOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ImageAlphaOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float tempcolor[4]; - - if (this->m_imageFloatBuffer == NULL && this->m_imageByteBuffer == NULL) { - output[0] = 0.0f; - } - else { - tempcolor[3] = 1.0f; - sampleImageAtLocation(this->m_buffer, x, y, sampler, false, tempcolor); - output[0] = tempcolor[3]; - } + float tempcolor[4]; + + if (this->m_imageFloatBuffer == NULL && this->m_imageByteBuffer == NULL) { + output[0] = 0.0f; + } + else { + tempcolor[3] = 1.0f; + sampleImageAtLocation(this->m_buffer, x, y, sampler, false, tempcolor); + output[0] = tempcolor[3]; + } } -void ImageDepthOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) +void ImageDepthOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler /*sampler*/) { - if (this->m_depthBuffer == NULL) { - output[0] = 0.0f; - } - else { - if (x < 0 || y < 0 || x >= this->getWidth() || y >= this->getHeight()) - output[0] = 0.0f; - else { - int offset = y * this->m_width + x; - output[0] = this->m_depthBuffer[offset]; - } - } + if (this->m_depthBuffer == NULL) { + output[0] = 0.0f; + } + else { + if (x < 0 || y < 0 || x >= this->getWidth() || y >= this->getHeight()) + output[0] = 0.0f; + else { + int offset = y * this->m_width + x; + output[0] = this->m_depthBuffer[offset]; + } + } } diff --git a/source/blender/compositor/operations/COM_ImageOperation.h b/source/blender/compositor/operations/COM_ImageOperation.h index 350c24bfafb..e03173dca8d 100644 --- a/source/blender/compositor/operations/COM_ImageOperation.h +++ b/source/blender/compositor/operations/COM_ImageOperation.h @@ -16,7 +16,6 @@ * Copyright 2011, Blender Foundation. */ - #ifndef __COM_IMAGEOPERATION_H__ #define __COM_IMAGEOPERATION_H__ @@ -24,70 +23,84 @@ #include "BLI_listbase.h" #include "BKE_image.h" extern "C" { -# include "RE_pipeline.h" -# include "RE_shader_ext.h" -# include "RE_render_ext.h" -# include "MEM_guardedalloc.h" +#include "RE_pipeline.h" +#include "RE_shader_ext.h" +#include "RE_render_ext.h" +#include "MEM_guardedalloc.h" } /** * \brief Base class for all image operations */ class BaseImageOperation : public NodeOperation { -protected: - ImBuf *m_buffer; - Image *m_image; - ImageUser *m_imageUser; - float *m_imageFloatBuffer; - unsigned int *m_imageByteBuffer; - float *m_depthBuffer; - int m_imageheight; - int m_imagewidth; - int m_framenumber; - int m_numberOfChannels; - const RenderData *m_rd; - const char *m_viewName; - - BaseImageOperation(); - /** - * Determine the output resolution. The resolution is retrieved from the Renderer - */ - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); + protected: + ImBuf *m_buffer; + Image *m_image; + ImageUser *m_imageUser; + float *m_imageFloatBuffer; + unsigned int *m_imageByteBuffer; + float *m_depthBuffer; + int m_imageheight; + int m_imagewidth; + int m_framenumber; + int m_numberOfChannels; + const RenderData *m_rd; + const char *m_viewName; - virtual ImBuf *getImBuf(); + BaseImageOperation(); + /** + * Determine the output resolution. The resolution is retrieved from the Renderer + */ + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); -public: + virtual ImBuf *getImBuf(); - void initExecution(); - void deinitExecution(); - void setImage(Image *image) { this->m_image = image; } - void setImageUser(ImageUser *imageuser) { this->m_imageUser = imageuser; } - void setRenderData(const RenderData *rd) { this->m_rd = rd; } - void setViewName(const char *viewName) { this->m_viewName = viewName; } - void setFramenumber(int framenumber) { this->m_framenumber = framenumber; } + public: + void initExecution(); + void deinitExecution(); + void setImage(Image *image) + { + this->m_image = image; + } + void setImageUser(ImageUser *imageuser) + { + this->m_imageUser = imageuser; + } + void setRenderData(const RenderData *rd) + { + this->m_rd = rd; + } + void setViewName(const char *viewName) + { + this->m_viewName = viewName; + } + void setFramenumber(int framenumber) + { + this->m_framenumber = framenumber; + } }; class ImageOperation : public BaseImageOperation { -public: - /** - * Constructor - */ - ImageOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + /** + * Constructor + */ + ImageOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class ImageAlphaOperation : public BaseImageOperation { -public: - /** - * Constructor - */ - ImageAlphaOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + /** + * Constructor + */ + ImageAlphaOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class ImageDepthOperation : public BaseImageOperation { -public: - /** - * Constructor - */ - ImageDepthOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + /** + * Constructor + */ + ImageDepthOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; #endif diff --git a/source/blender/compositor/operations/COM_InpaintOperation.cpp b/source/blender/compositor/operations/COM_InpaintOperation.cpp index e0f99d1916d..86d566834e6 100644 --- a/source/blender/compositor/operations/COM_InpaintOperation.cpp +++ b/source/blender/compositor/operations/COM_InpaintOperation.cpp @@ -23,260 +23,259 @@ #include "BLI_math.h" -#define ASSERT_XY_RANGE(x, y) \ - BLI_assert(x >= 0 && x < this->getWidth() && \ - y >= 0 && y < this->getHeight()) - +#define ASSERT_XY_RANGE(x, y) \ + BLI_assert(x >= 0 && x < this->getWidth() && y >= 0 && y < this->getHeight()) // Inpaint (simple convolve using average of known pixels) InpaintSimpleOperation::InpaintSimpleOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - this->setComplex(true); - this->m_inputImageProgram = NULL; - this->m_pixelorder = NULL; - this->m_manhatten_distance = NULL; - this->m_cached_buffer = NULL; - this->m_cached_buffer_ready = false; + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); + this->setComplex(true); + this->m_inputImageProgram = NULL; + this->m_pixelorder = NULL; + this->m_manhatten_distance = NULL; + this->m_cached_buffer = NULL; + this->m_cached_buffer_ready = false; } void InpaintSimpleOperation::initExecution() { - this->m_inputImageProgram = this->getInputSocketReader(0); + this->m_inputImageProgram = this->getInputSocketReader(0); - this->m_pixelorder = NULL; - this->m_manhatten_distance = NULL; - this->m_cached_buffer = NULL; - this->m_cached_buffer_ready = false; + this->m_pixelorder = NULL; + this->m_manhatten_distance = NULL; + this->m_cached_buffer = NULL; + this->m_cached_buffer_ready = false; - this->initMutex(); + this->initMutex(); } void InpaintSimpleOperation::clamp_xy(int &x, int &y) { - int width = this->getWidth(); - int height = this->getHeight(); - - if (x < 0) { - x = 0; - } - else if (x >= width) { - x = width - 1; - } - - if (y < 0) { - y = 0; - } - else if (y >= height) { - y = height - 1; - } + int width = this->getWidth(); + int height = this->getHeight(); + + if (x < 0) { + x = 0; + } + else if (x >= width) { + x = width - 1; + } + + if (y < 0) { + y = 0; + } + else if (y >= height) { + y = height - 1; + } } float *InpaintSimpleOperation::get_pixel(int x, int y) { - int width = this->getWidth(); + int width = this->getWidth(); - ASSERT_XY_RANGE(x, y); + ASSERT_XY_RANGE(x, y); - return &this->m_cached_buffer[ - y * width * COM_NUM_CHANNELS_COLOR + - x * COM_NUM_CHANNELS_COLOR]; + return &this->m_cached_buffer[y * width * COM_NUM_CHANNELS_COLOR + x * COM_NUM_CHANNELS_COLOR]; } int InpaintSimpleOperation::mdist(int x, int y) { - int width = this->getWidth(); + int width = this->getWidth(); - ASSERT_XY_RANGE(x, y); + ASSERT_XY_RANGE(x, y); - return this->m_manhatten_distance[y * width + x]; + return this->m_manhatten_distance[y * width + x]; } -bool InpaintSimpleOperation::next_pixel(int &x, int &y, int & curr, int iters) +bool InpaintSimpleOperation::next_pixel(int &x, int &y, int &curr, int iters) { - int width = this->getWidth(); + int width = this->getWidth(); - if (curr >= this->m_area_size) { - return false; - } + if (curr >= this->m_area_size) { + return false; + } - int r = this->m_pixelorder[curr++]; + int r = this->m_pixelorder[curr++]; - x = r % width; - y = r / width; + x = r % width; + y = r / width; - if (this->mdist(x, y) > iters) { - return false; - } + if (this->mdist(x, y) > iters) { + return false; + } - return true; + return true; } void InpaintSimpleOperation::calc_manhatten_distance() { - int width = this->getWidth(); - int height = this->getHeight(); - short *m = this->m_manhatten_distance = (short *)MEM_mallocN(sizeof(short) * width * height, __func__); - int *offsets; - - offsets = (int *)MEM_callocN(sizeof(int) * (width + height + 1), "InpaintSimpleOperation offsets"); - - for (int j = 0; j < height; j++) { - for (int i = 0; i < width; i++) { - int r = 0; - /* no need to clamp here */ - if (this->get_pixel(i, j)[3] < 1.0f) { - r = width + height; - if (i > 0) - r = min_ii(r, m[j * width + i - 1] + 1); - if (j > 0) - r = min_ii(r, m[(j - 1) * width + i] + 1); - } - m[j * width + i] = r; - } - } - - for (int j = height - 1; j >= 0; j--) { - for (int i = width - 1; i >= 0; i--) { - int r = m[j * width + i]; - - if (i + 1 < width) - r = min_ii(r, m[j * width + i + 1] + 1); - if (j + 1 < height) - r = min_ii(r, m[(j + 1) * width + i] + 1); - - m[j * width + i] = r; - - offsets[r]++; - } - } - - offsets[0] = 0; - - for (int i = 1; i < width + height + 1; i++) { - offsets[i] += offsets[i - 1]; - } - - this->m_area_size = offsets[width + height]; - this->m_pixelorder = (int *)MEM_mallocN(sizeof(int) * this->m_area_size, __func__); - - for (int i = 0; i < width * height; i++) { - if (m[i] > 0) { - this->m_pixelorder[offsets[m[i] - 1]++] = i; - } - } - - MEM_freeN(offsets); + int width = this->getWidth(); + int height = this->getHeight(); + short *m = this->m_manhatten_distance = (short *)MEM_mallocN(sizeof(short) * width * height, + __func__); + int *offsets; + + offsets = (int *)MEM_callocN(sizeof(int) * (width + height + 1), + "InpaintSimpleOperation offsets"); + + for (int j = 0; j < height; j++) { + for (int i = 0; i < width; i++) { + int r = 0; + /* no need to clamp here */ + if (this->get_pixel(i, j)[3] < 1.0f) { + r = width + height; + if (i > 0) + r = min_ii(r, m[j * width + i - 1] + 1); + if (j > 0) + r = min_ii(r, m[(j - 1) * width + i] + 1); + } + m[j * width + i] = r; + } + } + + for (int j = height - 1; j >= 0; j--) { + for (int i = width - 1; i >= 0; i--) { + int r = m[j * width + i]; + + if (i + 1 < width) + r = min_ii(r, m[j * width + i + 1] + 1); + if (j + 1 < height) + r = min_ii(r, m[(j + 1) * width + i] + 1); + + m[j * width + i] = r; + + offsets[r]++; + } + } + + offsets[0] = 0; + + for (int i = 1; i < width + height + 1; i++) { + offsets[i] += offsets[i - 1]; + } + + this->m_area_size = offsets[width + height]; + this->m_pixelorder = (int *)MEM_mallocN(sizeof(int) * this->m_area_size, __func__); + + for (int i = 0; i < width * height; i++) { + if (m[i] > 0) { + this->m_pixelorder[offsets[m[i] - 1]++] = i; + } + } + + MEM_freeN(offsets); } void InpaintSimpleOperation::pix_step(int x, int y) { - const int d = this->mdist(x, y); - float pix[3] = {0.0f, 0.0f, 0.0f}; - float pix_divider = 0.0f; - - for (int dx = -1; dx <= 1; dx++) { - for (int dy = -1; dy <= 1; dy++) { - /* changing to both != 0 gives dithering artifacts */ - if (dx != 0 || dy != 0) { - int x_ofs = x + dx; - int y_ofs = y + dy; - - this->clamp_xy(x_ofs, y_ofs); - - if (this->mdist(x_ofs, y_ofs) < d) { - - float weight; - - if (dx == 0 || dy == 0) { - weight = 1.0f; - } - else { - weight = M_SQRT1_2; /* 1.0f / sqrt(2) */ - } - - madd_v3_v3fl(pix, this->get_pixel(x_ofs, y_ofs), weight); - pix_divider += weight; - } - } - } - } - - float *output = this->get_pixel(x, y); - if (pix_divider != 0.0f) { - mul_v3_fl(pix, 1.0f / pix_divider); - /* use existing pixels alpha to blend into */ - interp_v3_v3v3(output, pix, output, output[3]); - output[3] = 1.0f; - } + const int d = this->mdist(x, y); + float pix[3] = {0.0f, 0.0f, 0.0f}; + float pix_divider = 0.0f; + + for (int dx = -1; dx <= 1; dx++) { + for (int dy = -1; dy <= 1; dy++) { + /* changing to both != 0 gives dithering artifacts */ + if (dx != 0 || dy != 0) { + int x_ofs = x + dx; + int y_ofs = y + dy; + + this->clamp_xy(x_ofs, y_ofs); + + if (this->mdist(x_ofs, y_ofs) < d) { + + float weight; + + if (dx == 0 || dy == 0) { + weight = 1.0f; + } + else { + weight = M_SQRT1_2; /* 1.0f / sqrt(2) */ + } + + madd_v3_v3fl(pix, this->get_pixel(x_ofs, y_ofs), weight); + pix_divider += weight; + } + } + } + } + + float *output = this->get_pixel(x, y); + if (pix_divider != 0.0f) { + mul_v3_fl(pix, 1.0f / pix_divider); + /* use existing pixels alpha to blend into */ + interp_v3_v3v3(output, pix, output, output[3]); + output[3] = 1.0f; + } } void *InpaintSimpleOperation::initializeTileData(rcti *rect) { - if (this->m_cached_buffer_ready) { - return this->m_cached_buffer; - } - lockMutex(); - if (!this->m_cached_buffer_ready) { - MemoryBuffer *buf = (MemoryBuffer *)this->m_inputImageProgram->initializeTileData(rect); - this->m_cached_buffer = (float *)MEM_dupallocN(buf->getBuffer()); - - this->calc_manhatten_distance(); - - int curr = 0; - int x, y; - - - while (this->next_pixel(x, y, curr, this->m_iterations)) { - this->pix_step(x, y); - } - this->m_cached_buffer_ready = true; - } - - unlockMutex(); - return this->m_cached_buffer; + if (this->m_cached_buffer_ready) { + return this->m_cached_buffer; + } + lockMutex(); + if (!this->m_cached_buffer_ready) { + MemoryBuffer *buf = (MemoryBuffer *)this->m_inputImageProgram->initializeTileData(rect); + this->m_cached_buffer = (float *)MEM_dupallocN(buf->getBuffer()); + + this->calc_manhatten_distance(); + + int curr = 0; + int x, y; + + while (this->next_pixel(x, y, curr, this->m_iterations)) { + this->pix_step(x, y); + } + this->m_cached_buffer_ready = true; + } + + unlockMutex(); + return this->m_cached_buffer; } void InpaintSimpleOperation::executePixel(float output[4], int x, int y, void * /*data*/) { - this->clamp_xy(x, y); - copy_v4_v4(output, this->get_pixel(x, y)); + this->clamp_xy(x, y); + copy_v4_v4(output, this->get_pixel(x, y)); } void InpaintSimpleOperation::deinitExecution() { - this->m_inputImageProgram = NULL; - this->deinitMutex(); - if (this->m_cached_buffer) { - MEM_freeN(this->m_cached_buffer); - this->m_cached_buffer = NULL; - } - - if (this->m_pixelorder) { - MEM_freeN(this->m_pixelorder); - this->m_pixelorder = NULL; - } - - if (this->m_manhatten_distance) { - MEM_freeN(this->m_manhatten_distance); - this->m_manhatten_distance = NULL; - } - this->m_cached_buffer_ready = false; + this->m_inputImageProgram = NULL; + this->deinitMutex(); + if (this->m_cached_buffer) { + MEM_freeN(this->m_cached_buffer); + this->m_cached_buffer = NULL; + } + + if (this->m_pixelorder) { + MEM_freeN(this->m_pixelorder); + this->m_pixelorder = NULL; + } + + if (this->m_manhatten_distance) { + MEM_freeN(this->m_manhatten_distance); + this->m_manhatten_distance = NULL; + } + this->m_cached_buffer_ready = false; } -bool InpaintSimpleOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output) +bool InpaintSimpleOperation::determineDependingAreaOfInterest(rcti * /*input*/, + ReadBufferOperation *readOperation, + rcti *output) { - if (this->m_cached_buffer_ready) { - return false; - } - else { - rcti newInput; - - newInput.xmax = getWidth(); - newInput.xmin = 0; - newInput.ymax = getHeight(); - newInput.ymin = 0; - - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); - } + if (this->m_cached_buffer_ready) { + return false; + } + else { + rcti newInput; + + newInput.xmax = getWidth(); + newInput.xmin = 0; + newInput.ymax = getHeight(); + newInput.ymin = 0; + + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + } } diff --git a/source/blender/compositor/operations/COM_InpaintOperation.h b/source/blender/compositor/operations/COM_InpaintOperation.h index 3bad383f51e..2fef7c590ea 100644 --- a/source/blender/compositor/operations/COM_InpaintOperation.h +++ b/source/blender/compositor/operations/COM_InpaintOperation.h @@ -21,51 +21,56 @@ #include "COM_NodeOperation.h" class InpaintSimpleOperation : public NodeOperation { -protected: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputImageProgram; + protected: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputImageProgram; - int m_iterations; + int m_iterations; - float *m_cached_buffer; - bool m_cached_buffer_ready; + float *m_cached_buffer; + bool m_cached_buffer_ready; - int *m_pixelorder; - int m_area_size; - short *m_manhatten_distance; -public: - InpaintSimpleOperation(); + int *m_pixelorder; + int m_area_size; + short *m_manhatten_distance; - /** - * the inner loop of this program - */ - void executePixel(float output[4], int x, int y, void *data); + public: + InpaintSimpleOperation(); - /** - * Initialize the execution - */ - void initExecution(); + /** + * the inner loop of this program + */ + void executePixel(float output[4], int x, int y, void *data); - void *initializeTileData(rcti *rect); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Initialize the execution + */ + void initExecution(); - void setIterations(int iterations) { this->m_iterations = iterations; } + void *initializeTileData(rcti *rect); + /** + * Deinitialize the execution + */ + void deinitExecution(); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + void setIterations(int iterations) + { + this->m_iterations = iterations; + } -private: - void calc_manhatten_distance(); - void clamp_xy(int &x, int &y); - float *get_pixel(int x, int y); - int mdist(int x, int y); - bool next_pixel(int &x, int &y, int &curr, int iters); - void pix_step(int x, int y); -}; + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + private: + void calc_manhatten_distance(); + void clamp_xy(int &x, int &y); + float *get_pixel(int x, int y); + int mdist(int x, int y); + bool next_pixel(int &x, int &y, int &curr, int iters); + void pix_step(int x, int y); +}; #endif diff --git a/source/blender/compositor/operations/COM_InvertOperation.cpp b/source/blender/compositor/operations/COM_InvertOperation.cpp index 17b86fba076..632dbdbfa4e 100644 --- a/source/blender/compositor/operations/COM_InvertOperation.cpp +++ b/source/blender/compositor/operations/COM_InvertOperation.cpp @@ -20,49 +20,48 @@ InvertOperation::InvertOperation() : NodeOperation() { - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - this->m_inputValueProgram = NULL; - this->m_inputColorProgram = NULL; - this->m_color = true; - this->m_alpha = false; - setResolutionInputSocketIndex(1); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); + this->m_inputValueProgram = NULL; + this->m_inputColorProgram = NULL; + this->m_color = true; + this->m_alpha = false; + setResolutionInputSocketIndex(1); } void InvertOperation::initExecution() { - this->m_inputValueProgram = this->getInputSocketReader(0); - this->m_inputColorProgram = this->getInputSocketReader(1); + this->m_inputValueProgram = this->getInputSocketReader(0); + this->m_inputColorProgram = this->getInputSocketReader(1); } void InvertOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { - float inputValue[4]; - float inputColor[4]; - this->m_inputValueProgram->readSampled(inputValue, x, y, sampler); - this->m_inputColorProgram->readSampled(inputColor, x, y, sampler); + float inputValue[4]; + float inputColor[4]; + this->m_inputValueProgram->readSampled(inputValue, x, y, sampler); + this->m_inputColorProgram->readSampled(inputColor, x, y, sampler); - const float value = inputValue[0]; - const float invertedValue = 1.0f - value; + const float value = inputValue[0]; + const float invertedValue = 1.0f - value; - if (this->m_color) { - output[0] = (1.0f - inputColor[0]) * value + inputColor[0] * invertedValue; - output[1] = (1.0f - inputColor[1]) * value + inputColor[1] * invertedValue; - output[2] = (1.0f - inputColor[2]) * value + inputColor[2] * invertedValue; - } - else { - copy_v3_v3(output, inputColor); - } - - if (this->m_alpha) - output[3] = (1.0f - inputColor[3]) * value + inputColor[3] * invertedValue; - else - output[3] = inputColor[3]; + if (this->m_color) { + output[0] = (1.0f - inputColor[0]) * value + inputColor[0] * invertedValue; + output[1] = (1.0f - inputColor[1]) * value + inputColor[1] * invertedValue; + output[2] = (1.0f - inputColor[2]) * value + inputColor[2] * invertedValue; + } + else { + copy_v3_v3(output, inputColor); + } + if (this->m_alpha) + output[3] = (1.0f - inputColor[3]) * value + inputColor[3] * invertedValue; + else + output[3] = inputColor[3]; } void InvertOperation::deinitExecution() { - this->m_inputValueProgram = NULL; - this->m_inputColorProgram = NULL; + this->m_inputValueProgram = NULL; + this->m_inputColorProgram = NULL; } diff --git a/source/blender/compositor/operations/COM_InvertOperation.h b/source/blender/compositor/operations/COM_InvertOperation.h index a5d2d498641..39161455a76 100644 --- a/source/blender/compositor/operations/COM_InvertOperation.h +++ b/source/blender/compositor/operations/COM_InvertOperation.h @@ -20,37 +20,42 @@ #define __COM_INVERTOPERATION_H__ #include "COM_NodeOperation.h" - class InvertOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputValueProgram; - SocketReader *m_inputColorProgram; - - bool m_alpha; - bool m_color; - -public: - InvertOperation(); - - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - - /** - * Initialize the execution - */ - void initExecution(); - - /** - * Deinitialize the execution - */ - void deinitExecution(); - - void setColor(bool color) { this->m_color = color; } - void setAlpha(bool alpha) { this->m_alpha = alpha; } + private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputValueProgram; + SocketReader *m_inputColorProgram; + + bool m_alpha; + bool m_color; + + public: + InvertOperation(); + + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + + /** + * Initialize the execution + */ + void initExecution(); + + /** + * Deinitialize the execution + */ + void deinitExecution(); + + void setColor(bool color) + { + this->m_color = color; + } + void setAlpha(bool alpha) + { + this->m_alpha = alpha; + } }; #endif diff --git a/source/blender/compositor/operations/COM_KeyingBlurOperation.cpp b/source/blender/compositor/operations/COM_KeyingBlurOperation.cpp index 71386c20886..300d122589f 100644 --- a/source/blender/compositor/operations/COM_KeyingBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingBlurOperation.cpp @@ -25,70 +25,71 @@ KeyingBlurOperation::KeyingBlurOperation() : NodeOperation() { - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_VALUE); - this->m_size = 0; - this->m_axis = BLUR_AXIS_X; + this->m_size = 0; + this->m_axis = BLUR_AXIS_X; - this->setComplex(true); + this->setComplex(true); } void *KeyingBlurOperation::initializeTileData(rcti *rect) { - void *buffer = getInputOperation(0)->initializeTileData(rect); + void *buffer = getInputOperation(0)->initializeTileData(rect); - return buffer; + return buffer; } void KeyingBlurOperation::executePixel(float output[4], int x, int y, void *data) { - MemoryBuffer *inputBuffer = (MemoryBuffer *)data; - const int bufferWidth = inputBuffer->getWidth(); - float *buffer = inputBuffer->getBuffer(); - int count = 0; - float average = 0.0f; + MemoryBuffer *inputBuffer = (MemoryBuffer *)data; + const int bufferWidth = inputBuffer->getWidth(); + float *buffer = inputBuffer->getBuffer(); + int count = 0; + float average = 0.0f; - if (this->m_axis == 0) { - const int start = max(0, x - this->m_size + 1), - end = min(bufferWidth, x + this->m_size); - for (int cx = start; cx < end; ++cx) { - int bufferIndex = (y * bufferWidth + cx); - average += buffer[bufferIndex]; - count++; - } - } - else { - const int start = max(0, y - this->m_size + 1), - end = min(inputBuffer->getHeight(), y + this->m_size); - for (int cy = start; cy < end; ++cy) { - int bufferIndex = (cy * bufferWidth + x); - average += buffer[bufferIndex]; - count++; - } - } + if (this->m_axis == 0) { + const int start = max(0, x - this->m_size + 1), end = min(bufferWidth, x + this->m_size); + for (int cx = start; cx < end; ++cx) { + int bufferIndex = (y * bufferWidth + cx); + average += buffer[bufferIndex]; + count++; + } + } + else { + const int start = max(0, y - this->m_size + 1), + end = min(inputBuffer->getHeight(), y + this->m_size); + for (int cy = start; cy < end; ++cy) { + int bufferIndex = (cy * bufferWidth + x); + average += buffer[bufferIndex]; + count++; + } + } - average /= (float) count; + average /= (float)count; - output[0] = average; + output[0] = average; } -bool KeyingBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool KeyingBlurOperation::determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output) { - rcti newInput; + rcti newInput; - if (this->m_axis == BLUR_AXIS_X) { - newInput.xmin = input->xmin - this->m_size; - newInput.ymin = input->ymin; - newInput.xmax = input->xmax + this->m_size; - newInput.ymax = input->ymax; - } - else { - newInput.xmin = input->xmin; - newInput.ymin = input->ymin - this->m_size; - newInput.xmax = input->xmax; - newInput.ymax = input->ymax + this->m_size; - } + if (this->m_axis == BLUR_AXIS_X) { + newInput.xmin = input->xmin - this->m_size; + newInput.ymin = input->ymin; + newInput.xmax = input->xmax + this->m_size; + newInput.ymax = input->ymax; + } + else { + newInput.xmin = input->xmin; + newInput.ymin = input->ymin - this->m_size; + newInput.xmax = input->xmax; + newInput.ymax = input->ymax + this->m_size; + } - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } diff --git a/source/blender/compositor/operations/COM_KeyingBlurOperation.h b/source/blender/compositor/operations/COM_KeyingBlurOperation.h index 76360d7fd6b..0e45f1c32b8 100644 --- a/source/blender/compositor/operations/COM_KeyingBlurOperation.h +++ b/source/blender/compositor/operations/COM_KeyingBlurOperation.h @@ -25,26 +25,34 @@ * Class with implementation of blurring for keying node */ class KeyingBlurOperation : public NodeOperation { -protected: - int m_size; - int m_axis; - -public: - enum BlurAxis { - BLUR_AXIS_X = 0, - BLUR_AXIS_Y = 1, - }; - - KeyingBlurOperation(); - - void setSize(int value) {this->m_size = value;} - void setAxis(int value) {this->m_axis = value;} - - void *initializeTileData(rcti *rect); - - void executePixel(float output[4], int x, int y, void *data); - - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + protected: + int m_size; + int m_axis; + + public: + enum BlurAxis { + BLUR_AXIS_X = 0, + BLUR_AXIS_Y = 1, + }; + + KeyingBlurOperation(); + + void setSize(int value) + { + this->m_size = value; + } + void setAxis(int value) + { + this->m_axis = value; + } + + void *initializeTileData(rcti *rect); + + void executePixel(float output[4], int x, int y, void *data); + + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); }; #endif diff --git a/source/blender/compositor/operations/COM_KeyingClipOperation.cpp b/source/blender/compositor/operations/COM_KeyingClipOperation.cpp index f4600c753ba..89fa8a8d303 100644 --- a/source/blender/compositor/operations/COM_KeyingClipOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingClipOperation.cpp @@ -25,99 +25,100 @@ KeyingClipOperation::KeyingClipOperation() : NodeOperation() { - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_VALUE); - this->m_kernelRadius = 3; - this->m_kernelTolerance = 0.1f; + this->m_kernelRadius = 3; + this->m_kernelTolerance = 0.1f; - this->m_clipBlack = 0.0f; - this->m_clipWhite = 1.0f; + this->m_clipBlack = 0.0f; + this->m_clipWhite = 1.0f; - this->m_isEdgeMatte = false; + this->m_isEdgeMatte = false; - this->setComplex(true); + this->setComplex(true); } void *KeyingClipOperation::initializeTileData(rcti *rect) { - void *buffer = getInputOperation(0)->initializeTileData(rect); + void *buffer = getInputOperation(0)->initializeTileData(rect); - return buffer; + return buffer; } void KeyingClipOperation::executePixel(float output[4], int x, int y, void *data) { - const int delta = this->m_kernelRadius; - const float tolerance = this->m_kernelTolerance; - - MemoryBuffer *inputBuffer = (MemoryBuffer *)data; - float *buffer = inputBuffer->getBuffer(); - - int bufferWidth = inputBuffer->getWidth(); - int bufferHeight = inputBuffer->getHeight(); - - float value = buffer[(y * bufferWidth + x)]; - - bool ok = false; - int start_x = max_ff(0, x - delta + 1), - start_y = max_ff(0, y - delta + 1), - end_x = min_ff(x + delta - 1, bufferWidth - 1), - end_y = min_ff(y + delta - 1, bufferHeight - 1); - - int count = 0, totalCount = (end_x - start_x + 1) * (end_y - start_y + 1) - 1; - int thresholdCount = ceil((float) totalCount * 0.9f); - - if (delta == 0) { - ok = true; - } - - for (int cx = start_x; ok == false && cx <= end_x; ++cx) { - for (int cy = start_y; ok == false && cy <= end_y; ++cy) { - if (UNLIKELY(cx == x && cy == y)) { - continue; - } - - int bufferIndex = (cy * bufferWidth + cx); - float currentValue = buffer[bufferIndex]; - - if (fabsf(currentValue - value) < tolerance) { - count++; - if (count >= thresholdCount) { - ok = true; - } - } - } - } - - if (this->m_isEdgeMatte) { - if (ok) - output[0] = 0.0f; - else - output[0] = 1.0f; - } - else { - output[0] = value; - - if (ok) { - if (output[0] < this->m_clipBlack) - output[0] = 0.0f; - else if (output[0] >= this->m_clipWhite) - output[0] = 1.0f; - else - output[0] = (output[0] - this->m_clipBlack) / (this->m_clipWhite - this->m_clipBlack); - } - } + const int delta = this->m_kernelRadius; + const float tolerance = this->m_kernelTolerance; + + MemoryBuffer *inputBuffer = (MemoryBuffer *)data; + float *buffer = inputBuffer->getBuffer(); + + int bufferWidth = inputBuffer->getWidth(); + int bufferHeight = inputBuffer->getHeight(); + + float value = buffer[(y * bufferWidth + x)]; + + bool ok = false; + int start_x = max_ff(0, x - delta + 1), start_y = max_ff(0, y - delta + 1), + end_x = min_ff(x + delta - 1, bufferWidth - 1), + end_y = min_ff(y + delta - 1, bufferHeight - 1); + + int count = 0, totalCount = (end_x - start_x + 1) * (end_y - start_y + 1) - 1; + int thresholdCount = ceil((float)totalCount * 0.9f); + + if (delta == 0) { + ok = true; + } + + for (int cx = start_x; ok == false && cx <= end_x; ++cx) { + for (int cy = start_y; ok == false && cy <= end_y; ++cy) { + if (UNLIKELY(cx == x && cy == y)) { + continue; + } + + int bufferIndex = (cy * bufferWidth + cx); + float currentValue = buffer[bufferIndex]; + + if (fabsf(currentValue - value) < tolerance) { + count++; + if (count >= thresholdCount) { + ok = true; + } + } + } + } + + if (this->m_isEdgeMatte) { + if (ok) + output[0] = 0.0f; + else + output[0] = 1.0f; + } + else { + output[0] = value; + + if (ok) { + if (output[0] < this->m_clipBlack) + output[0] = 0.0f; + else if (output[0] >= this->m_clipWhite) + output[0] = 1.0f; + else + output[0] = (output[0] - this->m_clipBlack) / (this->m_clipWhite - this->m_clipBlack); + } + } } -bool KeyingClipOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool KeyingClipOperation::determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output) { - rcti newInput; + rcti newInput; - newInput.xmin = input->xmin - this->m_kernelRadius; - newInput.ymin = input->ymin - this->m_kernelRadius; - newInput.xmax = input->xmax + this->m_kernelRadius; - newInput.ymax = input->ymax + this->m_kernelRadius; + newInput.xmin = input->xmin - this->m_kernelRadius; + newInput.ymin = input->ymin - this->m_kernelRadius; + newInput.xmax = input->xmax + this->m_kernelRadius; + newInput.ymax = input->ymax + this->m_kernelRadius; - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } diff --git a/source/blender/compositor/operations/COM_KeyingClipOperation.h b/source/blender/compositor/operations/COM_KeyingClipOperation.h index 6f8922c0124..8237c443cf2 100644 --- a/source/blender/compositor/operations/COM_KeyingClipOperation.h +++ b/source/blender/compositor/operations/COM_KeyingClipOperation.h @@ -25,30 +25,48 @@ * Class with implementation of black/white clipping for keying node */ class KeyingClipOperation : public NodeOperation { -protected: - float m_clipBlack; - float m_clipWhite; + protected: + float m_clipBlack; + float m_clipWhite; - int m_kernelRadius; - float m_kernelTolerance; + int m_kernelRadius; + float m_kernelTolerance; - bool m_isEdgeMatte; -public: - KeyingClipOperation(); + bool m_isEdgeMatte; - void setClipBlack(float value) {this->m_clipBlack = value;} - void setClipWhite(float value) {this->m_clipWhite = value;} + public: + KeyingClipOperation(); - void setKernelRadius(int value) {this->m_kernelRadius = value;} - void setKernelTolerance(float value) {this->m_kernelTolerance = value;} + void setClipBlack(float value) + { + this->m_clipBlack = value; + } + void setClipWhite(float value) + { + this->m_clipWhite = value; + } - void setIsEdgeMatte(bool value) {this->m_isEdgeMatte = value;} + void setKernelRadius(int value) + { + this->m_kernelRadius = value; + } + void setKernelTolerance(float value) + { + this->m_kernelTolerance = value; + } - void *initializeTileData(rcti *rect); + void setIsEdgeMatte(bool value) + { + this->m_isEdgeMatte = value; + } - void executePixel(float output[4], int x, int y, void *data); + void *initializeTileData(rcti *rect); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + void executePixel(float output[4], int x, int y, void *data); + + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); }; #endif diff --git a/source/blender/compositor/operations/COM_KeyingDespillOperation.cpp b/source/blender/compositor/operations/COM_KeyingDespillOperation.cpp index 9b3e89dc1f7..a1ba49a69b2 100644 --- a/source/blender/compositor/operations/COM_KeyingDespillOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingDespillOperation.cpp @@ -25,53 +25,57 @@ KeyingDespillOperation::KeyingDespillOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); - this->m_despillFactor = 0.5f; - this->m_colorBalance = 0.5f; + this->m_despillFactor = 0.5f; + this->m_colorBalance = 0.5f; - this->m_pixelReader = NULL; - this->m_screenReader = NULL; + this->m_pixelReader = NULL; + this->m_screenReader = NULL; } void KeyingDespillOperation::initExecution() { - this->m_pixelReader = this->getInputSocketReader(0); - this->m_screenReader = this->getInputSocketReader(1); + this->m_pixelReader = this->getInputSocketReader(0); + this->m_screenReader = this->getInputSocketReader(1); } void KeyingDespillOperation::deinitExecution() { - this->m_pixelReader = NULL; - this->m_screenReader = NULL; + this->m_pixelReader = NULL; + this->m_screenReader = NULL; } -void KeyingDespillOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void KeyingDespillOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float pixelColor[4]; - float screenColor[4]; + float pixelColor[4]; + float screenColor[4]; - this->m_pixelReader->readSampled(pixelColor, x, y, sampler); - this->m_screenReader->readSampled(screenColor, x, y, sampler); + this->m_pixelReader->readSampled(pixelColor, x, y, sampler); + this->m_screenReader->readSampled(screenColor, x, y, sampler); - const int screen_primary_channel = max_axis_v3(screenColor); - const int other_1 = (screen_primary_channel + 1) % 3; - const int other_2 = (screen_primary_channel + 2) % 3; + const int screen_primary_channel = max_axis_v3(screenColor); + const int other_1 = (screen_primary_channel + 1) % 3; + const int other_2 = (screen_primary_channel + 2) % 3; - const int min_channel = min(other_1, other_2); - const int max_channel = max(other_1, other_2); + const int min_channel = min(other_1, other_2); + const int max_channel = max(other_1, other_2); - float average_value, amount; + float average_value, amount; - average_value = this->m_colorBalance * pixelColor[min_channel] + (1.0f - this->m_colorBalance) * pixelColor[max_channel]; - amount = (pixelColor[screen_primary_channel] - average_value); + average_value = this->m_colorBalance * pixelColor[min_channel] + + (1.0f - this->m_colorBalance) * pixelColor[max_channel]; + amount = (pixelColor[screen_primary_channel] - average_value); - copy_v4_v4(output, pixelColor); + copy_v4_v4(output, pixelColor); - const float amount_despill = this->m_despillFactor * amount; - if (amount_despill > 0.0f) { - output[screen_primary_channel] = pixelColor[screen_primary_channel] - amount_despill; - } + const float amount_despill = this->m_despillFactor * amount; + if (amount_despill > 0.0f) { + output[screen_primary_channel] = pixelColor[screen_primary_channel] - amount_despill; + } } diff --git a/source/blender/compositor/operations/COM_KeyingDespillOperation.h b/source/blender/compositor/operations/COM_KeyingDespillOperation.h index 13f15c12d0c..eb43a478e50 100644 --- a/source/blender/compositor/operations/COM_KeyingDespillOperation.h +++ b/source/blender/compositor/operations/COM_KeyingDespillOperation.h @@ -25,22 +25,28 @@ * Class with implementation of keying despill node */ class KeyingDespillOperation : public NodeOperation { -protected: - SocketReader *m_pixelReader; - SocketReader *m_screenReader; - float m_despillFactor; - float m_colorBalance; - -public: - KeyingDespillOperation(); - - void initExecution(); - void deinitExecution(); - - void setDespillFactor(float value) {this->m_despillFactor = value;} - void setColorBalance(float value) {this->m_colorBalance = value;} - - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + protected: + SocketReader *m_pixelReader; + SocketReader *m_screenReader; + float m_despillFactor; + float m_colorBalance; + + public: + KeyingDespillOperation(); + + void initExecution(); + void deinitExecution(); + + void setDespillFactor(float value) + { + this->m_despillFactor = value; + } + void setColorBalance(float value) + { + this->m_colorBalance = value; + } + + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; #endif diff --git a/source/blender/compositor/operations/COM_KeyingOperation.cpp b/source/blender/compositor/operations/COM_KeyingOperation.cpp index 53bb696866a..50562143ce6 100644 --- a/source/blender/compositor/operations/COM_KeyingOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingOperation.cpp @@ -23,83 +23,87 @@ #include "BLI_listbase.h" #include "BLI_math.h" -static float get_pixel_saturation(const float pixelColor[4], float screen_balance, int primary_channel) +static float get_pixel_saturation(const float pixelColor[4], + float screen_balance, + int primary_channel) { - const int other_1 = (primary_channel + 1) % 3; - const int other_2 = (primary_channel + 2) % 3; + const int other_1 = (primary_channel + 1) % 3; + const int other_2 = (primary_channel + 2) % 3; - const int min_channel = min(other_1, other_2); - const int max_channel = max(other_1, other_2); + const int min_channel = min(other_1, other_2); + const int max_channel = max(other_1, other_2); - const float val = screen_balance * pixelColor[min_channel] + (1.0f - screen_balance) * pixelColor[max_channel]; + const float val = screen_balance * pixelColor[min_channel] + + (1.0f - screen_balance) * pixelColor[max_channel]; - return (pixelColor[primary_channel] - val) * fabsf(1.0f - val); + return (pixelColor[primary_channel] - val) * fabsf(1.0f - val); } KeyingOperation::KeyingOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_VALUE); - this->m_screenBalance = 0.5f; + this->m_screenBalance = 0.5f; - this->m_pixelReader = NULL; - this->m_screenReader = NULL; + this->m_pixelReader = NULL; + this->m_screenReader = NULL; } void KeyingOperation::initExecution() { - this->m_pixelReader = this->getInputSocketReader(0); - this->m_screenReader = this->getInputSocketReader(1); + this->m_pixelReader = this->getInputSocketReader(0); + this->m_screenReader = this->getInputSocketReader(1); } void KeyingOperation::deinitExecution() { - this->m_pixelReader = NULL; - this->m_screenReader = NULL; + this->m_pixelReader = NULL; + this->m_screenReader = NULL; } void KeyingOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { - float pixel_color[4]; - float screen_color[4]; - - this->m_pixelReader->readSampled(pixel_color, x, y, sampler); - this->m_screenReader->readSampled(screen_color, x, y, sampler); - - const int primary_channel = max_axis_v3(screen_color); - const float min_pixel_color = min_fff(pixel_color[0], pixel_color[1], pixel_color[2]); - - if (min_pixel_color > 1.0f) { - /* overexposure doesn't happen on screen itself and usually happens - * on light sources in the shot, this need to be checked separately - * because saturation and falloff calculation is based on the fact - * that pixels are not overexposed - */ - output[0] = 1.0f; - } - else { - float saturation = get_pixel_saturation(pixel_color, this->m_screenBalance, primary_channel); - float screen_saturation = get_pixel_saturation(screen_color, this->m_screenBalance, primary_channel); - - if (saturation < 0) { - /* means main channel of pixel is different from screen, - * assume this is completely a foreground - */ - output[0] = 1.0f; - } - else if (saturation >= screen_saturation) { - /* matched main channels and higher saturation on pixel - * is treated as completely background - */ - output[0] = 0.0f; - } - else { - /* nice alpha falloff on edges */ - float distance = 1.0f - saturation / screen_saturation; - - output[0] = distance; - } - } + float pixel_color[4]; + float screen_color[4]; + + this->m_pixelReader->readSampled(pixel_color, x, y, sampler); + this->m_screenReader->readSampled(screen_color, x, y, sampler); + + const int primary_channel = max_axis_v3(screen_color); + const float min_pixel_color = min_fff(pixel_color[0], pixel_color[1], pixel_color[2]); + + if (min_pixel_color > 1.0f) { + /* overexposure doesn't happen on screen itself and usually happens + * on light sources in the shot, this need to be checked separately + * because saturation and falloff calculation is based on the fact + * that pixels are not overexposed + */ + output[0] = 1.0f; + } + else { + float saturation = get_pixel_saturation(pixel_color, this->m_screenBalance, primary_channel); + float screen_saturation = get_pixel_saturation( + screen_color, this->m_screenBalance, primary_channel); + + if (saturation < 0) { + /* means main channel of pixel is different from screen, + * assume this is completely a foreground + */ + output[0] = 1.0f; + } + else if (saturation >= screen_saturation) { + /* matched main channels and higher saturation on pixel + * is treated as completely background + */ + output[0] = 0.0f; + } + else { + /* nice alpha falloff on edges */ + float distance = 1.0f - saturation / screen_saturation; + + output[0] = distance; + } + } } diff --git a/source/blender/compositor/operations/COM_KeyingOperation.h b/source/blender/compositor/operations/COM_KeyingOperation.h index 194d6eb0027..81d23e76b2a 100644 --- a/source/blender/compositor/operations/COM_KeyingOperation.h +++ b/source/blender/compositor/operations/COM_KeyingOperation.h @@ -16,7 +16,6 @@ * Copyright 2012, Blender Foundation. */ - #ifndef __COM_KEYINGOPERATION_H__ #define __COM_KEYINGOPERATION_H__ @@ -30,21 +29,24 @@ * Class with implementation of keying node */ class KeyingOperation : public NodeOperation { -protected: - SocketReader *m_pixelReader; - SocketReader *m_screenReader; + protected: + SocketReader *m_pixelReader; + SocketReader *m_screenReader; - float m_screenBalance; + float m_screenBalance; -public: - KeyingOperation(); + public: + KeyingOperation(); - void initExecution(); - void deinitExecution(); + void initExecution(); + void deinitExecution(); - void setScreenBalance(float value) {this->m_screenBalance = value;} + void setScreenBalance(float value) + { + this->m_screenBalance = value; + } - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; #endif diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp index 6e5d40c6621..03a6bf6a7dd 100644 --- a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp @@ -25,306 +25,313 @@ #include "BLI_math_color.h" extern "C" { -# include "BKE_movieclip.h" -# include "BKE_tracking.h" +#include "BKE_movieclip.h" +#include "BKE_tracking.h" -# include "IMB_imbuf.h" -# include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" } KeyingScreenOperation::KeyingScreenOperation() : NodeOperation() { - this->addOutputSocket(COM_DT_COLOR); - this->m_movieClip = NULL; - this->m_framenumber = 0; - this->m_trackingObject[0] = 0; - setComplex(true); + this->addOutputSocket(COM_DT_COLOR); + this->m_movieClip = NULL; + this->m_framenumber = 0; + this->m_trackingObject[0] = 0; + setComplex(true); } void KeyingScreenOperation::initExecution() { - initMutex(); - this->m_cachedTriangulation = NULL; + initMutex(); + this->m_cachedTriangulation = NULL; } void KeyingScreenOperation::deinitExecution() { - if (this->m_cachedTriangulation) { - TriangulationData *triangulation = this->m_cachedTriangulation; + if (this->m_cachedTriangulation) { + TriangulationData *triangulation = this->m_cachedTriangulation; - if (triangulation->triangulated_points) - MEM_freeN(triangulation->triangulated_points); + if (triangulation->triangulated_points) + MEM_freeN(triangulation->triangulated_points); - if (triangulation->triangles) - MEM_freeN(triangulation->triangles); + if (triangulation->triangles) + MEM_freeN(triangulation->triangles); - if (triangulation->triangles_AABB) - MEM_freeN(triangulation->triangles_AABB); + if (triangulation->triangles_AABB) + MEM_freeN(triangulation->triangles_AABB); - MEM_freeN(this->m_cachedTriangulation); + MEM_freeN(this->m_cachedTriangulation); - this->m_cachedTriangulation = NULL; - } + this->m_cachedTriangulation = NULL; + } } KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTriangulation() { - MovieClipUser user = {0}; - TriangulationData *triangulation; - MovieTracking *tracking = &this->m_movieClip->tracking; - MovieTrackingTrack *track; - VoronoiSite *sites, *site; - ImBuf *ibuf; - ListBase *tracksbase; - ListBase edges = {NULL, NULL}; - int sites_total; - int i; - int width = this->getWidth(); - int height = this->getHeight(); - int clip_frame = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, this->m_framenumber); + MovieClipUser user = {0}; + TriangulationData *triangulation; + MovieTracking *tracking = &this->m_movieClip->tracking; + MovieTrackingTrack *track; + VoronoiSite *sites, *site; + ImBuf *ibuf; + ListBase *tracksbase; + ListBase edges = {NULL, NULL}; + int sites_total; + int i; + int width = this->getWidth(); + int height = this->getHeight(); + int clip_frame = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, this->m_framenumber); + + if (this->m_trackingObject[0]) { + MovieTrackingObject *object = BKE_tracking_object_get_named(tracking, this->m_trackingObject); + + if (!object) + return NULL; + + tracksbase = BKE_tracking_object_get_tracks(tracking, object); + } + else + tracksbase = BKE_tracking_get_active_tracks(tracking); + + /* count sites */ + for (track = (MovieTrackingTrack *)tracksbase->first, sites_total = 0; track; + track = track->next) { + MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_frame); + float pos[2]; + + if (marker->flag & MARKER_DISABLED) + continue; + + add_v2_v2v2(pos, marker->pos, track->offset); + + if (!IN_RANGE_INCL(pos[0], 0.0f, 1.0f) || !IN_RANGE_INCL(pos[1], 0.0f, 1.0f)) { + continue; + } + + sites_total++; + } + + if (!sites_total) + return NULL; + + BKE_movieclip_user_set_frame(&user, clip_frame); + ibuf = BKE_movieclip_get_ibuf(this->m_movieClip, &user); + + if (!ibuf) + return NULL; + + triangulation = (TriangulationData *)MEM_callocN(sizeof(TriangulationData), + "keying screen triangulation data"); + + sites = (VoronoiSite *)MEM_callocN(sizeof(VoronoiSite) * sites_total, + "keyingscreen voronoi sites"); + track = (MovieTrackingTrack *)tracksbase->first; + for (track = (MovieTrackingTrack *)tracksbase->first, site = sites; track; track = track->next) { + MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_frame); + ImBuf *pattern_ibuf; + int j; + float pos[2]; + + if (marker->flag & MARKER_DISABLED) + continue; + + add_v2_v2v2(pos, marker->pos, track->offset); + + if (!IN_RANGE_INCL(pos[0], 0.0f, 1.0f) || !IN_RANGE_INCL(pos[1], 0.0f, 1.0f)) { + continue; + } + + pattern_ibuf = BKE_tracking_get_pattern_imbuf(ibuf, track, marker, true, false); + + zero_v3(site->color); + + if (pattern_ibuf) { + for (j = 0; j < pattern_ibuf->x * pattern_ibuf->y; j++) { + if (pattern_ibuf->rect_float) { + add_v3_v3(site->color, &pattern_ibuf->rect_float[4 * j]); + } + else { + unsigned char *rrgb = (unsigned char *)pattern_ibuf->rect; + + site->color[0] += srgb_to_linearrgb((float)rrgb[4 * j + 0] / 255.0f); + site->color[1] += srgb_to_linearrgb((float)rrgb[4 * j + 1] / 255.0f); + site->color[2] += srgb_to_linearrgb((float)rrgb[4 * j + 2] / 255.0f); + } + } + + mul_v3_fl(site->color, 1.0f / (pattern_ibuf->x * pattern_ibuf->y)); + IMB_freeImBuf(pattern_ibuf); + } + + site->co[0] = pos[0] * width; + site->co[1] = pos[1] * height; + + site++; + } + + IMB_freeImBuf(ibuf); + + BLI_voronoi_compute(sites, sites_total, width, height, &edges); - if (this->m_trackingObject[0]) { - MovieTrackingObject *object = BKE_tracking_object_get_named(tracking, this->m_trackingObject); - - if (!object) - return NULL; - - tracksbase = BKE_tracking_object_get_tracks(tracking, object); - } - else - tracksbase = BKE_tracking_get_active_tracks(tracking); - - /* count sites */ - for (track = (MovieTrackingTrack *) tracksbase->first, sites_total = 0; track; track = track->next) { - MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_frame); - float pos[2]; + BLI_voronoi_triangulate(sites, + sites_total, + &edges, + width, + height, + &triangulation->triangulated_points, + &triangulation->triangulated_points_total, + &triangulation->triangles, + &triangulation->triangles_total); - if (marker->flag & MARKER_DISABLED) - continue; + MEM_freeN(sites); + BLI_freelistN(&edges); - add_v2_v2v2(pos, marker->pos, track->offset); + if (triangulation->triangles_total) { + rcti *rect; + rect = triangulation->triangles_AABB = (rcti *)MEM_callocN( + sizeof(rcti) * triangulation->triangles_total, "voronoi triangulation AABB"); - if (!IN_RANGE_INCL(pos[0], 0.0f, 1.0f) || - !IN_RANGE_INCL(pos[1], 0.0f, 1.0f)) - { - continue; - } + for (i = 0; i < triangulation->triangles_total; i++, rect++) { + int *triangle = triangulation->triangles[i]; + VoronoiTriangulationPoint *a = &triangulation->triangulated_points[triangle[0]], + *b = &triangulation->triangulated_points[triangle[1]], + *c = &triangulation->triangulated_points[triangle[2]]; - sites_total++; - } + float min[2], max[2]; - if (!sites_total) - return NULL; + INIT_MINMAX2(min, max); - BKE_movieclip_user_set_frame(&user, clip_frame); - ibuf = BKE_movieclip_get_ibuf(this->m_movieClip, &user); + minmax_v2v2_v2(min, max, a->co); + minmax_v2v2_v2(min, max, b->co); + minmax_v2v2_v2(min, max, c->co); - if (!ibuf) - return NULL; + rect->xmin = (int)min[0]; + rect->ymin = (int)min[1]; - triangulation = (TriangulationData *) MEM_callocN(sizeof(TriangulationData), "keying screen triangulation data"); + rect->xmax = (int)max[0] + 1; + rect->ymax = (int)max[1] + 1; + } + } - sites = (VoronoiSite *) MEM_callocN(sizeof(VoronoiSite) * sites_total, "keyingscreen voronoi sites"); - track = (MovieTrackingTrack *) tracksbase->first; - for (track = (MovieTrackingTrack *) tracksbase->first, site = sites; track; track = track->next) { - MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_frame); - ImBuf *pattern_ibuf; - int j; - float pos[2]; - - if (marker->flag & MARKER_DISABLED) - continue; - - add_v2_v2v2(pos, marker->pos, track->offset); - - if (!IN_RANGE_INCL(pos[0], 0.0f, 1.0f) || - !IN_RANGE_INCL(pos[1], 0.0f, 1.0f)) - { - continue; - } - - pattern_ibuf = BKE_tracking_get_pattern_imbuf(ibuf, track, marker, true, false); - - zero_v3(site->color); - - if (pattern_ibuf) { - for (j = 0; j < pattern_ibuf->x * pattern_ibuf->y; j++) { - if (pattern_ibuf->rect_float) { - add_v3_v3(site->color, &pattern_ibuf->rect_float[4 * j]); - } - else { - unsigned char *rrgb = (unsigned char *)pattern_ibuf->rect; - - site->color[0] += srgb_to_linearrgb((float)rrgb[4 * j + 0] / 255.0f); - site->color[1] += srgb_to_linearrgb((float)rrgb[4 * j + 1] / 255.0f); - site->color[2] += srgb_to_linearrgb((float)rrgb[4 * j + 2] / 255.0f); - } - } - - mul_v3_fl(site->color, 1.0f / (pattern_ibuf->x * pattern_ibuf->y)); - IMB_freeImBuf(pattern_ibuf); - } - - site->co[0] = pos[0] * width; - site->co[1] = pos[1] * height; - - site++; - } - - IMB_freeImBuf(ibuf); - - BLI_voronoi_compute(sites, sites_total, width, height, &edges); - - BLI_voronoi_triangulate(sites, sites_total, &edges, width, height, - &triangulation->triangulated_points, &triangulation->triangulated_points_total, - &triangulation->triangles, &triangulation->triangles_total); - - MEM_freeN(sites); - BLI_freelistN(&edges); - - if (triangulation->triangles_total) { - rcti *rect; - rect = triangulation->triangles_AABB = - (rcti *) MEM_callocN(sizeof(rcti) * triangulation->triangles_total, "voronoi triangulation AABB"); - - for (i = 0; i < triangulation->triangles_total; i++, rect++) { - int *triangle = triangulation->triangles[i]; - VoronoiTriangulationPoint *a = &triangulation->triangulated_points[triangle[0]], - *b = &triangulation->triangulated_points[triangle[1]], - *c = &triangulation->triangulated_points[triangle[2]]; - - float min[2], max[2]; - - INIT_MINMAX2(min, max); - - minmax_v2v2_v2(min, max, a->co); - minmax_v2v2_v2(min, max, b->co); - minmax_v2v2_v2(min, max, c->co); - - rect->xmin = (int)min[0]; - rect->ymin = (int)min[1]; - - rect->xmax = (int)max[0] + 1; - rect->ymax = (int)max[1] + 1; - } - } - - return triangulation; + return triangulation; } void *KeyingScreenOperation::initializeTileData(rcti *rect) { - TileData *tile_data; - TriangulationData *triangulation; - int triangles_allocated = 0; - int chunk_size = 20; - int i; - - if (this->m_movieClip == NULL) - return NULL; - - if (!this->m_cachedTriangulation) { - lockMutex(); - if (this->m_cachedTriangulation == NULL) { - this->m_cachedTriangulation = buildVoronoiTriangulation(); - } - unlockMutex(); - } - - triangulation = this->m_cachedTriangulation; - - if (!triangulation) - return NULL; - - tile_data = (TileData *) MEM_callocN(sizeof(TileData), "keying screen tile data"); - - for (i = 0; i < triangulation->triangles_total; i++) { - if (BLI_rcti_isect(rect, &triangulation->triangles_AABB[i], NULL)) { - tile_data->triangles_total++; - - if (tile_data->triangles_total > triangles_allocated) { - if (!tile_data->triangles) { - tile_data->triangles = (int *) MEM_mallocN(sizeof(int) * chunk_size, - "keying screen tile triangles chunk"); - } - else { - tile_data->triangles = (int *) MEM_reallocN(tile_data->triangles, - sizeof(int) * (triangles_allocated + chunk_size)); - } - - triangles_allocated += chunk_size; - } - - tile_data->triangles[tile_data->triangles_total - 1] = i; - } - } - - return tile_data; + TileData *tile_data; + TriangulationData *triangulation; + int triangles_allocated = 0; + int chunk_size = 20; + int i; + + if (this->m_movieClip == NULL) + return NULL; + + if (!this->m_cachedTriangulation) { + lockMutex(); + if (this->m_cachedTriangulation == NULL) { + this->m_cachedTriangulation = buildVoronoiTriangulation(); + } + unlockMutex(); + } + + triangulation = this->m_cachedTriangulation; + + if (!triangulation) + return NULL; + + tile_data = (TileData *)MEM_callocN(sizeof(TileData), "keying screen tile data"); + + for (i = 0; i < triangulation->triangles_total; i++) { + if (BLI_rcti_isect(rect, &triangulation->triangles_AABB[i], NULL)) { + tile_data->triangles_total++; + + if (tile_data->triangles_total > triangles_allocated) { + if (!tile_data->triangles) { + tile_data->triangles = (int *)MEM_mallocN(sizeof(int) * chunk_size, + "keying screen tile triangles chunk"); + } + else { + tile_data->triangles = (int *)MEM_reallocN( + tile_data->triangles, sizeof(int) * (triangles_allocated + chunk_size)); + } + + triangles_allocated += chunk_size; + } + + tile_data->triangles[tile_data->triangles_total - 1] = i; + } + } + + return tile_data; } void KeyingScreenOperation::deinitializeTileData(rcti * /*rect*/, void *data) { - TileData *tile_data = (TileData *) data; + TileData *tile_data = (TileData *)data; - if (tile_data->triangles) { - MEM_freeN(tile_data->triangles); - } + if (tile_data->triangles) { + MEM_freeN(tile_data->triangles); + } - MEM_freeN(tile_data); + MEM_freeN(tile_data); } -void KeyingScreenOperation::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2]) +void KeyingScreenOperation::determineResolution(unsigned int resolution[2], + unsigned int /*preferredResolution*/[2]) { - resolution[0] = 0; - resolution[1] = 0; + resolution[0] = 0; + resolution[1] = 0; - if (this->m_movieClip) { - MovieClipUser user = {0}; - int width, height; - int clip_frame = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, this->m_framenumber); + if (this->m_movieClip) { + MovieClipUser user = {0}; + int width, height; + int clip_frame = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, + this->m_framenumber); - BKE_movieclip_user_set_frame(&user, clip_frame); - BKE_movieclip_get_size(this->m_movieClip, &user, &width, &height); + BKE_movieclip_user_set_frame(&user, clip_frame); + BKE_movieclip_get_size(this->m_movieClip, &user, &width, &height); - resolution[0] = width; - resolution[1] = height; - } + resolution[0] = width; + resolution[1] = height; + } } void KeyingScreenOperation::executePixel(float output[4], int x, int y, void *data) { - output[0] = 0.0f; - output[1] = 0.0f; - output[2] = 0.0f; - output[3] = 1.0f; - - if (this->m_movieClip && data) { - TriangulationData *triangulation = this->m_cachedTriangulation; - TileData *tile_data = (TileData *) data; - int i; - float co[2] = {(float) x, (float) y}; - - for (i = 0; i < tile_data->triangles_total; i++) { - int triangle_idx = tile_data->triangles[i]; - rcti *rect = &triangulation->triangles_AABB[triangle_idx]; - - if (IN_RANGE_INCL(x, rect->xmin, rect->xmax) && IN_RANGE_INCL(y, rect->ymin, rect->ymax)) { - int *triangle = triangulation->triangles[triangle_idx]; - VoronoiTriangulationPoint *a = &triangulation->triangulated_points[triangle[0]], - *b = &triangulation->triangulated_points[triangle[1]], - *c = &triangulation->triangulated_points[triangle[2]]; - float w[3]; - - if (barycentric_coords_v2(a->co, b->co, c->co, co, w)) { - if (barycentric_inside_triangle_v2(w)) { - output[0] = a->color[0] * w[0] + b->color[0] * w[1] + c->color[0] * w[2]; - output[1] = a->color[1] * w[0] + b->color[1] * w[1] + c->color[1] * w[2]; - output[2] = a->color[2] * w[0] + b->color[2] * w[1] + c->color[2] * w[2]; - - break; - } - } - } - } - } + output[0] = 0.0f; + output[1] = 0.0f; + output[2] = 0.0f; + output[3] = 1.0f; + + if (this->m_movieClip && data) { + TriangulationData *triangulation = this->m_cachedTriangulation; + TileData *tile_data = (TileData *)data; + int i; + float co[2] = {(float)x, (float)y}; + + for (i = 0; i < tile_data->triangles_total; i++) { + int triangle_idx = tile_data->triangles[i]; + rcti *rect = &triangulation->triangles_AABB[triangle_idx]; + + if (IN_RANGE_INCL(x, rect->xmin, rect->xmax) && IN_RANGE_INCL(y, rect->ymin, rect->ymax)) { + int *triangle = triangulation->triangles[triangle_idx]; + VoronoiTriangulationPoint *a = &triangulation->triangulated_points[triangle[0]], + *b = &triangulation->triangulated_points[triangle[1]], + *c = &triangulation->triangulated_points[triangle[2]]; + float w[3]; + + if (barycentric_coords_v2(a->co, b->co, c->co, co, w)) { + if (barycentric_inside_triangle_v2(w)) { + output[0] = a->color[0] * w[0] + b->color[0] * w[1] + c->color[0] * w[2]; + output[1] = a->color[1] * w[0] + b->color[1] * w[1] + c->color[1] * w[2]; + output[2] = a->color[2] * w[0] + b->color[2] * w[1] + c->color[2] * w[2]; + + break; + } + } + } + } + } } diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.h b/source/blender/compositor/operations/COM_KeyingScreenOperation.h index e11905fbfac..860a358e79d 100644 --- a/source/blender/compositor/operations/COM_KeyingScreenOperation.h +++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.h @@ -16,7 +16,6 @@ * Copyright 2012, Blender Foundation. */ - #ifndef __COM_KEYINGSCREENOPERATION_H__ #define __COM_KEYINGSCREENOPERATION_H__ @@ -30,52 +29,61 @@ #include "BLI_string.h" extern "C" { -# include "BLI_voronoi_2d.h" +#include "BLI_voronoi_2d.h" } /** * Class with implementation of green screen gradient rasterization */ class KeyingScreenOperation : public NodeOperation { -protected: - typedef struct TriangulationData { - VoronoiTriangulationPoint *triangulated_points; - int (*triangles)[3]; - int triangulated_points_total, triangles_total; - rcti *triangles_AABB; - } TriangulationData; - - typedef struct TileData { - int *triangles; - int triangles_total; - } TileData; - - MovieClip *m_movieClip; - int m_framenumber; - TriangulationData *m_cachedTriangulation; - char m_trackingObject[64]; - - /** - * Determine the output resolution. The resolution is retrieved from the Renderer - */ - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); - - TriangulationData *buildVoronoiTriangulation(); - -public: - KeyingScreenOperation(); - - void initExecution(); - void deinitExecution(); - - void *initializeTileData(rcti *rect); - void deinitializeTileData(rcti *rect, void *data); - - void setMovieClip(MovieClip *clip) {this->m_movieClip = clip;} - void setTrackingObject(const char *object) { BLI_strncpy(this->m_trackingObject, object, sizeof(this->m_trackingObject)); } - void setFramenumber(int framenumber) {this->m_framenumber = framenumber;} - - void executePixel(float output[4], int x, int y, void *data); + protected: + typedef struct TriangulationData { + VoronoiTriangulationPoint *triangulated_points; + int (*triangles)[3]; + int triangulated_points_total, triangles_total; + rcti *triangles_AABB; + } TriangulationData; + + typedef struct TileData { + int *triangles; + int triangles_total; + } TileData; + + MovieClip *m_movieClip; + int m_framenumber; + TriangulationData *m_cachedTriangulation; + char m_trackingObject[64]; + + /** + * Determine the output resolution. The resolution is retrieved from the Renderer + */ + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); + + TriangulationData *buildVoronoiTriangulation(); + + public: + KeyingScreenOperation(); + + void initExecution(); + void deinitExecution(); + + void *initializeTileData(rcti *rect); + void deinitializeTileData(rcti *rect, void *data); + + void setMovieClip(MovieClip *clip) + { + this->m_movieClip = clip; + } + void setTrackingObject(const char *object) + { + BLI_strncpy(this->m_trackingObject, object, sizeof(this->m_trackingObject)); + } + void setFramenumber(int framenumber) + { + this->m_framenumber = framenumber; + } + + void executePixel(float output[4], int x, int y, void *data); }; #endif diff --git a/source/blender/compositor/operations/COM_LuminanceMatteOperation.cpp b/source/blender/compositor/operations/COM_LuminanceMatteOperation.cpp index 4b98da47f43..30ad954e0bc 100644 --- a/source/blender/compositor/operations/COM_LuminanceMatteOperation.cpp +++ b/source/blender/compositor/operations/COM_LuminanceMatteOperation.cpp @@ -25,52 +25,55 @@ extern "C" { LuminanceMatteOperation::LuminanceMatteOperation() : NodeOperation() { - addInputSocket(COM_DT_COLOR); - addOutputSocket(COM_DT_VALUE); + addInputSocket(COM_DT_COLOR); + addOutputSocket(COM_DT_VALUE); - this->m_inputImageProgram = NULL; + this->m_inputImageProgram = NULL; } void LuminanceMatteOperation::initExecution() { - this->m_inputImageProgram = this->getInputSocketReader(0); + this->m_inputImageProgram = this->getInputSocketReader(0); } void LuminanceMatteOperation::deinitExecution() { - this->m_inputImageProgram = NULL; + this->m_inputImageProgram = NULL; } -void LuminanceMatteOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void LuminanceMatteOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inColor[4]; - this->m_inputImageProgram->readSampled(inColor, x, y, sampler); + float inColor[4]; + this->m_inputImageProgram->readSampled(inColor, x, y, sampler); - const float high = this->m_settings->t1; - const float low = this->m_settings->t2; - const float luminance = IMB_colormanagement_get_luminance(inColor); + const float high = this->m_settings->t1; + const float low = this->m_settings->t2; + const float luminance = IMB_colormanagement_get_luminance(inColor); - float alpha; + float alpha; - /* one line thread-friend algorithm: - * output[0] = min(inputValue[3], min(1.0f, max(0.0f, ((luminance - low) / (high - low)))); - */ + /* one line thread-friend algorithm: + * output[0] = min(inputValue[3], min(1.0f, max(0.0f, ((luminance - low) / (high - low)))); + */ - /* test range */ - if (luminance > high) { - alpha = 1.0f; - } - else if (luminance < low) { - alpha = 0.0f; - } - else { /*blend */ - alpha = (luminance - low) / (high - low); - } + /* test range */ + if (luminance > high) { + alpha = 1.0f; + } + else if (luminance < low) { + alpha = 0.0f; + } + else { /*blend */ + alpha = (luminance - low) / (high - low); + } - /* store matte(alpha) value in [0] to go with - * COM_SetAlphaOperation and the Value output - */ + /* store matte(alpha) value in [0] to go with + * COM_SetAlphaOperation and the Value output + */ - /* don't make something that was more transparent less transparent */ - output[0] = min_ff(alpha, inColor[3]); + /* don't make something that was more transparent less transparent */ + output[0] = min_ff(alpha, inColor[3]); } diff --git a/source/blender/compositor/operations/COM_LuminanceMatteOperation.h b/source/blender/compositor/operations/COM_LuminanceMatteOperation.h index 890fa6ee3b3..2df7847f7ff 100644 --- a/source/blender/compositor/operations/COM_LuminanceMatteOperation.h +++ b/source/blender/compositor/operations/COM_LuminanceMatteOperation.h @@ -20,29 +20,32 @@ #define __COM_LUMINANCEMATTEOPERATION_H__ #include "COM_MixOperation.h" - /** * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ class LuminanceMatteOperation : public NodeOperation { -private: - NodeChroma *m_settings; - SocketReader *m_inputImageProgram; -public: - /** - * Default constructor - */ - LuminanceMatteOperation(); + private: + NodeChroma *m_settings; + SocketReader *m_inputImageProgram; + + public: + /** + * Default constructor + */ + LuminanceMatteOperation(); - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - void initExecution(); - void deinitExecution(); + void initExecution(); + void deinitExecution(); - void setSettings(NodeChroma *nodeChroma) { this->m_settings = nodeChroma; } + void setSettings(NodeChroma *nodeChroma) + { + this->m_settings = nodeChroma; + } }; #endif diff --git a/source/blender/compositor/operations/COM_MapRangeOperation.cpp b/source/blender/compositor/operations/COM_MapRangeOperation.cpp index e32158132d7..489f0dabdaf 100644 --- a/source/blender/compositor/operations/COM_MapRangeOperation.cpp +++ b/source/blender/compositor/operations/COM_MapRangeOperation.cpp @@ -20,78 +20,81 @@ MapRangeOperation::MapRangeOperation() : NodeOperation() { - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_VALUE); - this->m_inputOperation = NULL; - this->m_useClamp = false; + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_VALUE); + this->m_inputOperation = NULL; + this->m_useClamp = false; } void MapRangeOperation::initExecution() { - this->m_inputOperation = this->getInputSocketReader(0); - this->m_sourceMinOperation = this->getInputSocketReader(1); - this->m_sourceMaxOperation = this->getInputSocketReader(2); - this->m_destMinOperation = this->getInputSocketReader(3); - this->m_destMaxOperation = this->getInputSocketReader(4); + this->m_inputOperation = this->getInputSocketReader(0); + this->m_sourceMinOperation = this->getInputSocketReader(1); + this->m_sourceMaxOperation = this->getInputSocketReader(2); + this->m_destMinOperation = this->getInputSocketReader(3); + this->m_destMaxOperation = this->getInputSocketReader(4); } /* The code below assumes all data is inside range +- this, and that input buffer is single channel */ #define BLENDER_ZMAX 10000.0f -void MapRangeOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MapRangeOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputs[8]; /* includes the 5 inputs + 3 pads */ - float value; - float source_min, source_max; - float dest_min, dest_max; + float inputs[8]; /* includes the 5 inputs + 3 pads */ + float value; + float source_min, source_max; + float dest_min, dest_max; - this->m_inputOperation->readSampled(inputs, x, y, sampler); - this->m_sourceMinOperation->readSampled(inputs + 1, x, y, sampler); - this->m_sourceMaxOperation->readSampled(inputs + 2, x, y, sampler); - this->m_destMinOperation->readSampled(inputs + 3, x, y, sampler); - this->m_destMaxOperation->readSampled(inputs + 4, x, y, sampler); + this->m_inputOperation->readSampled(inputs, x, y, sampler); + this->m_sourceMinOperation->readSampled(inputs + 1, x, y, sampler); + this->m_sourceMaxOperation->readSampled(inputs + 2, x, y, sampler); + this->m_destMinOperation->readSampled(inputs + 3, x, y, sampler); + this->m_destMaxOperation->readSampled(inputs + 4, x, y, sampler); - value = inputs[0]; - source_min = inputs[1]; - source_max = inputs[2]; - dest_min = inputs[3]; - dest_max = inputs[4]; + value = inputs[0]; + source_min = inputs[1]; + source_max = inputs[2]; + dest_min = inputs[3]; + dest_max = inputs[4]; - if (fabsf(source_max - source_min) < 1e-6f) { - output[0] = 0.0f; - return; - } + if (fabsf(source_max - source_min) < 1e-6f) { + output[0] = 0.0f; + return; + } - if (value >= -BLENDER_ZMAX && value <= BLENDER_ZMAX) { - value = (value - source_min) / (source_max - source_min); - value = dest_min + value * (dest_max - dest_min); - } - else if (value > BLENDER_ZMAX) - value = dest_max; - else - value = dest_min; + if (value >= -BLENDER_ZMAX && value <= BLENDER_ZMAX) { + value = (value - source_min) / (source_max - source_min); + value = dest_min + value * (dest_max - dest_min); + } + else if (value > BLENDER_ZMAX) + value = dest_max; + else + value = dest_min; - if (this->m_useClamp) { - if (dest_max > dest_min) { - CLAMP(value, dest_min, dest_max); - } - else { - CLAMP(value, dest_max, dest_min); - } - } + if (this->m_useClamp) { + if (dest_max > dest_min) { + CLAMP(value, dest_min, dest_max); + } + else { + CLAMP(value, dest_max, dest_min); + } + } - output[0] = value; + output[0] = value; } void MapRangeOperation::deinitExecution() { - this->m_inputOperation = NULL; - this->m_sourceMinOperation = NULL; - this->m_sourceMaxOperation = NULL; - this->m_destMinOperation = NULL; - this->m_destMaxOperation = NULL; + this->m_inputOperation = NULL; + this->m_sourceMinOperation = NULL; + this->m_sourceMaxOperation = NULL; + this->m_destMinOperation = NULL; + this->m_destMaxOperation = NULL; } diff --git a/source/blender/compositor/operations/COM_MapRangeOperation.h b/source/blender/compositor/operations/COM_MapRangeOperation.h index 7b3d51a1896..55b5cc7453c 100644 --- a/source/blender/compositor/operations/COM_MapRangeOperation.h +++ b/source/blender/compositor/operations/COM_MapRangeOperation.h @@ -26,42 +26,45 @@ * it assumes we are in sRGB color space. */ class MapRangeOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputOperation; - SocketReader *m_sourceMinOperation; - SocketReader *m_sourceMaxOperation; - SocketReader *m_destMinOperation; - SocketReader *m_destMaxOperation; + private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputOperation; + SocketReader *m_sourceMinOperation; + SocketReader *m_sourceMaxOperation; + SocketReader *m_destMinOperation; + SocketReader *m_destMaxOperation; - bool m_useClamp; -public: - /** - * Default constructor - */ - MapRangeOperation(); + bool m_useClamp; - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + /** + * Default constructor + */ + MapRangeOperation(); - /** - * Initialize the execution - */ - void initExecution(); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Initialize the execution + */ + void initExecution(); - /** - * Clamp the output - */ - void setUseClamp(bool value) { this->m_useClamp = value; } + /** + * Deinitialize the execution + */ + void deinitExecution(); + /** + * Clamp the output + */ + void setUseClamp(bool value) + { + this->m_useClamp = value; + } }; #endif diff --git a/source/blender/compositor/operations/COM_MapUVOperation.cpp b/source/blender/compositor/operations/COM_MapUVOperation.cpp index 3dbf4db5280..98b5b650cb9 100644 --- a/source/blender/compositor/operations/COM_MapUVOperation.cpp +++ b/source/blender/compositor/operations/COM_MapUVOperation.cpp @@ -21,153 +21,164 @@ MapUVOperation::MapUVOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); - this->addInputSocket(COM_DT_VECTOR); - this->addOutputSocket(COM_DT_COLOR); - this->m_alpha = 0.0f; - this->setComplex(true); - setResolutionInputSocketIndex(1); - - this->m_inputUVProgram = NULL; - this->m_inputColorProgram = NULL; + this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); + this->addInputSocket(COM_DT_VECTOR); + this->addOutputSocket(COM_DT_COLOR); + this->m_alpha = 0.0f; + this->setComplex(true); + setResolutionInputSocketIndex(1); + + this->m_inputUVProgram = NULL; + this->m_inputColorProgram = NULL; } void MapUVOperation::initExecution() { - this->m_inputColorProgram = this->getInputSocketReader(0); - this->m_inputUVProgram = this->getInputSocketReader(1); + this->m_inputColorProgram = this->getInputSocketReader(0); + this->m_inputUVProgram = this->getInputSocketReader(1); } -void MapUVOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) +void MapUVOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler /*sampler*/) { - float xy[2] = { x, y }; - float uv[2], deriv[2][2], alpha; - - pixelTransform(xy, uv, deriv, alpha); - if (alpha == 0.0f) { - zero_v4(output); - return; - } - - /* EWA filtering */ - this->m_inputColorProgram->readFiltered(output, uv[0], uv[1], deriv[0], deriv[1]); - - /* UV to alpha threshold */ - const float threshold = this->m_alpha * 0.05f; - /* XXX alpha threshold is used to fade out pixels on boundaries with invalid derivatives. - * this calculation is not very well defined, should be looked into if it becomes a problem ... - */ - float du = len_v2(deriv[0]); - float dv = len_v2(deriv[1]); - float factor = 1.0f - threshold * (du / m_inputColorProgram->getWidth() + dv / m_inputColorProgram->getHeight()); - if (factor < 0.0f) alpha = 0.0f; - else alpha *= factor; - - /* "premul" */ - if (alpha < 1.0f) { - mul_v4_fl(output, alpha); - } + float xy[2] = {x, y}; + float uv[2], deriv[2][2], alpha; + + pixelTransform(xy, uv, deriv, alpha); + if (alpha == 0.0f) { + zero_v4(output); + return; + } + + /* EWA filtering */ + this->m_inputColorProgram->readFiltered(output, uv[0], uv[1], deriv[0], deriv[1]); + + /* UV to alpha threshold */ + const float threshold = this->m_alpha * 0.05f; + /* XXX alpha threshold is used to fade out pixels on boundaries with invalid derivatives. + * this calculation is not very well defined, should be looked into if it becomes a problem ... + */ + float du = len_v2(deriv[0]); + float dv = len_v2(deriv[1]); + float factor = 1.0f - threshold * (du / m_inputColorProgram->getWidth() + + dv / m_inputColorProgram->getHeight()); + if (factor < 0.0f) + alpha = 0.0f; + else + alpha *= factor; + + /* "premul" */ + if (alpha < 1.0f) { + mul_v4_fl(output, alpha); + } } bool MapUVOperation::read_uv(float x, float y, float &r_u, float &r_v, float &r_alpha) { - float width = m_inputUVProgram->getWidth(); - float height = m_inputUVProgram->getHeight(); - if (x < 0.0f || x >= width || y < 0.0f || y >= height) { - r_u = 0.0f; - r_v = 0.0f; - r_alpha = 0.0f; - return false; - } - else { - float vector[3]; - m_inputUVProgram->readSampled(vector, x, y, COM_PS_BILINEAR); - r_u = vector[0] * m_inputColorProgram->getWidth(); - r_v = vector[1] * m_inputColorProgram->getHeight(); - r_alpha = vector[2]; - return true; - } + float width = m_inputUVProgram->getWidth(); + float height = m_inputUVProgram->getHeight(); + if (x < 0.0f || x >= width || y < 0.0f || y >= height) { + r_u = 0.0f; + r_v = 0.0f; + r_alpha = 0.0f; + return false; + } + else { + float vector[3]; + m_inputUVProgram->readSampled(vector, x, y, COM_PS_BILINEAR); + r_u = vector[0] * m_inputColorProgram->getWidth(); + r_v = vector[1] * m_inputColorProgram->getHeight(); + r_alpha = vector[2]; + return true; + } } -void MapUVOperation::pixelTransform(const float xy[2], float r_uv[2], float r_deriv[2][2], float &r_alpha) +void MapUVOperation::pixelTransform(const float xy[2], + float r_uv[2], + float r_deriv[2][2], + float &r_alpha) { - float uv[2], alpha; /* temporary variables for derivative estimation */ - int num; - - read_uv(xy[0], xy[1], r_uv[0], r_uv[1], r_alpha); - - /* Estimate partial derivatives using 1-pixel offsets */ - const float epsilon[2] = { 1.0f, 1.0f }; - - zero_v2(r_deriv[0]); - zero_v2(r_deriv[1]); - - num = 0; - if (read_uv(xy[0] + epsilon[0], xy[1], uv[0], uv[1], alpha)) { - r_deriv[0][0] += uv[0] - r_uv[0]; - r_deriv[1][0] += uv[1] - r_uv[1]; - ++num; - } - if (read_uv(xy[0] - epsilon[0], xy[1], uv[0], uv[1], alpha)) { - r_deriv[0][0] += r_uv[0] - uv[0]; - r_deriv[1][0] += r_uv[1] - uv[1]; - ++num; - } - if (num > 0) { - float numinv = 1.0f / (float)num; - r_deriv[0][0] *= numinv; - r_deriv[1][0] *= numinv; - } - - num = 0; - if (read_uv(xy[0], xy[1] + epsilon[1], uv[0], uv[1], alpha)) { - r_deriv[0][1] += uv[0] - r_uv[0]; - r_deriv[1][1] += uv[1] - r_uv[1]; - ++num; - } - if (read_uv(xy[0], xy[1] - epsilon[1], uv[0], uv[1], alpha)) { - r_deriv[0][1] += r_uv[0] - uv[0]; - r_deriv[1][1] += r_uv[1] - uv[1]; - ++num; - } - if (num > 0) { - float numinv = 1.0f / (float)num; - r_deriv[0][1] *= numinv; - r_deriv[1][1] *= numinv; - } + float uv[2], alpha; /* temporary variables for derivative estimation */ + int num; + + read_uv(xy[0], xy[1], r_uv[0], r_uv[1], r_alpha); + + /* Estimate partial derivatives using 1-pixel offsets */ + const float epsilon[2] = {1.0f, 1.0f}; + + zero_v2(r_deriv[0]); + zero_v2(r_deriv[1]); + + num = 0; + if (read_uv(xy[0] + epsilon[0], xy[1], uv[0], uv[1], alpha)) { + r_deriv[0][0] += uv[0] - r_uv[0]; + r_deriv[1][0] += uv[1] - r_uv[1]; + ++num; + } + if (read_uv(xy[0] - epsilon[0], xy[1], uv[0], uv[1], alpha)) { + r_deriv[0][0] += r_uv[0] - uv[0]; + r_deriv[1][0] += r_uv[1] - uv[1]; + ++num; + } + if (num > 0) { + float numinv = 1.0f / (float)num; + r_deriv[0][0] *= numinv; + r_deriv[1][0] *= numinv; + } + + num = 0; + if (read_uv(xy[0], xy[1] + epsilon[1], uv[0], uv[1], alpha)) { + r_deriv[0][1] += uv[0] - r_uv[0]; + r_deriv[1][1] += uv[1] - r_uv[1]; + ++num; + } + if (read_uv(xy[0], xy[1] - epsilon[1], uv[0], uv[1], alpha)) { + r_deriv[0][1] += r_uv[0] - uv[0]; + r_deriv[1][1] += r_uv[1] - uv[1]; + ++num; + } + if (num > 0) { + float numinv = 1.0f / (float)num; + r_deriv[0][1] *= numinv; + r_deriv[1][1] *= numinv; + } } void MapUVOperation::deinitExecution() { - this->m_inputUVProgram = NULL; - this->m_inputColorProgram = NULL; + this->m_inputUVProgram = NULL; + this->m_inputColorProgram = NULL; } -bool MapUVOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool MapUVOperation::determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output) { - rcti colorInput; - rcti uvInput; - NodeOperation *operation = NULL; - - /* the uv buffer only needs a 3x3 buffer. The image needs whole buffer */ - - operation = getInputOperation(0); - colorInput.xmax = operation->getWidth(); - colorInput.xmin = 0; - colorInput.ymax = operation->getHeight(); - colorInput.ymin = 0; - if (operation->determineDependingAreaOfInterest(&colorInput, readOperation, output)) { - return true; - } - - operation = getInputOperation(1); - uvInput.xmax = input->xmax + 1; - uvInput.xmin = input->xmin - 1; - uvInput.ymax = input->ymax + 1; - uvInput.ymin = input->ymin - 1; - if (operation->determineDependingAreaOfInterest(&uvInput, readOperation, output)) { - return true; - } - - return false; + rcti colorInput; + rcti uvInput; + NodeOperation *operation = NULL; + + /* the uv buffer only needs a 3x3 buffer. The image needs whole buffer */ + + operation = getInputOperation(0); + colorInput.xmax = operation->getWidth(); + colorInput.xmin = 0; + colorInput.ymax = operation->getHeight(); + colorInput.ymin = 0; + if (operation->determineDependingAreaOfInterest(&colorInput, readOperation, output)) { + return true; + } + + operation = getInputOperation(1); + uvInput.xmax = input->xmax + 1; + uvInput.xmin = input->xmin - 1; + uvInput.ymax = input->ymax + 1; + uvInput.ymin = input->ymin - 1; + if (operation->determineDependingAreaOfInterest(&uvInput, readOperation, output)) { + return true; + } + + return false; } diff --git a/source/blender/compositor/operations/COM_MapUVOperation.h b/source/blender/compositor/operations/COM_MapUVOperation.h index b2235d4de25..64e17b180b4 100644 --- a/source/blender/compositor/operations/COM_MapUVOperation.h +++ b/source/blender/compositor/operations/COM_MapUVOperation.h @@ -20,46 +20,50 @@ #define __COM_MAPUVOPERATION_H__ #include "COM_NodeOperation.h" - class MapUVOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputUVProgram; - SocketReader *m_inputColorProgram; + private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputUVProgram; + SocketReader *m_inputColorProgram; - float m_alpha; + float m_alpha; -public: - MapUVOperation(); + public: + MapUVOperation(); - /** - * we need a 3x3 differential filter for UV Input and full buffer for the image - */ - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + /** + * we need a 3x3 differential filter for UV Input and full buffer for the image + */ + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - void pixelTransform(const float xy[2], float r_uv[2], float r_deriv[2][2], float &r_alpha); + void pixelTransform(const float xy[2], float r_uv[2], float r_deriv[2][2], float &r_alpha); - /** - * Initialize the execution - */ - void initExecution(); + /** + * Initialize the execution + */ + void initExecution(); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Deinitialize the execution + */ + void deinitExecution(); - void setAlpha(float alpha) { this->m_alpha = alpha; } + void setAlpha(float alpha) + { + this->m_alpha = alpha; + } -private: - bool read_uv(float x, float y, float &r_u, float &r_v, float &r_alpha); + private: + bool read_uv(float x, float y, float &r_u, float &r_v, float &r_alpha); }; #endif diff --git a/source/blender/compositor/operations/COM_MapValueOperation.cpp b/source/blender/compositor/operations/COM_MapValueOperation.cpp index e8731c0f146..d99a68a5e00 100644 --- a/source/blender/compositor/operations/COM_MapValueOperation.cpp +++ b/source/blender/compositor/operations/COM_MapValueOperation.cpp @@ -20,33 +20,36 @@ MapValueOperation::MapValueOperation() : NodeOperation() { - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_VALUE); - this->m_inputOperation = NULL; + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_VALUE); + this->m_inputOperation = NULL; } void MapValueOperation::initExecution() { - this->m_inputOperation = this->getInputSocketReader(0); + this->m_inputOperation = this->getInputSocketReader(0); } -void MapValueOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MapValueOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float src[4]; - this->m_inputOperation->readSampled(src, x, y, sampler); - TexMapping *texmap = this->m_settings; - float value = (src[0] + texmap->loc[0]) * texmap->size[0]; - if (texmap->flag & TEXMAP_CLIP_MIN) - if (value < texmap->min[0]) - value = texmap->min[0]; - if (texmap->flag & TEXMAP_CLIP_MAX) - if (value > texmap->max[0]) - value = texmap->max[0]; + float src[4]; + this->m_inputOperation->readSampled(src, x, y, sampler); + TexMapping *texmap = this->m_settings; + float value = (src[0] + texmap->loc[0]) * texmap->size[0]; + if (texmap->flag & TEXMAP_CLIP_MIN) + if (value < texmap->min[0]) + value = texmap->min[0]; + if (texmap->flag & TEXMAP_CLIP_MAX) + if (value > texmap->max[0]) + value = texmap->max[0]; - output[0] = value; + output[0] = value; } void MapValueOperation::deinitExecution() { - this->m_inputOperation = NULL; + this->m_inputOperation = NULL; } diff --git a/source/blender/compositor/operations/COM_MapValueOperation.h b/source/blender/compositor/operations/COM_MapValueOperation.h index dfea3703d24..81071d78cd7 100644 --- a/source/blender/compositor/operations/COM_MapValueOperation.h +++ b/source/blender/compositor/operations/COM_MapValueOperation.h @@ -26,37 +26,40 @@ * it assumes we are in sRGB color space. */ class MapValueOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputOperation; - TexMapping *m_settings; -public: - /** - * Default constructor - */ - MapValueOperation(); + private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputOperation; + TexMapping *m_settings; - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + /** + * Default constructor + */ + MapValueOperation(); - /** - * Initialize the execution - */ - void initExecution(); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Initialize the execution + */ + void initExecution(); - /** - * \brief set the TexMapping settings - */ - void setSettings(TexMapping *settings) { this->m_settings = settings; } + /** + * Deinitialize the execution + */ + void deinitExecution(); + /** + * \brief set the TexMapping settings + */ + void setSettings(TexMapping *settings) + { + this->m_settings = settings; + } }; #endif diff --git a/source/blender/compositor/operations/COM_MaskOperation.cpp b/source/blender/compositor/operations/COM_MaskOperation.cpp index d2603978ac8..6f146d9e1e6 100644 --- a/source/blender/compositor/operations/COM_MaskOperation.cpp +++ b/source/blender/compositor/operations/COM_MaskOperation.cpp @@ -24,129 +24,138 @@ #include "BLI_math.h" extern "C" { -# include "BKE_mask.h" +#include "BKE_mask.h" } MaskOperation::MaskOperation() : NodeOperation() { - this->addOutputSocket(COM_DT_VALUE); - this->m_mask = NULL; - this->m_maskWidth = 0; - this->m_maskHeight = 0; - this->m_maskWidthInv = 0.0f; - this->m_maskHeightInv = 0.0f; - this->m_frame_shutter = 0.0f; - this->m_frame_number = 0; - this->m_rasterMaskHandleTot = 1; - memset(this->m_rasterMaskHandles, 0, sizeof(this->m_rasterMaskHandles)); + this->addOutputSocket(COM_DT_VALUE); + this->m_mask = NULL; + this->m_maskWidth = 0; + this->m_maskHeight = 0; + this->m_maskWidthInv = 0.0f; + this->m_maskHeightInv = 0.0f; + this->m_frame_shutter = 0.0f; + this->m_frame_number = 0; + this->m_rasterMaskHandleTot = 1; + memset(this->m_rasterMaskHandles, 0, sizeof(this->m_rasterMaskHandles)); } void MaskOperation::initExecution() { - if (this->m_mask && this->m_rasterMaskHandles[0] == NULL) { - if (this->m_rasterMaskHandleTot == 1) { - this->m_rasterMaskHandles[0] = BKE_maskrasterize_handle_new(); - - BKE_maskrasterize_handle_init(this->m_rasterMaskHandles[0], this->m_mask, - this->m_maskWidth, this->m_maskHeight, - true, true, this->m_do_feather); - } - else { - /* make a throw away copy of the mask */ - const float frame = (float)this->m_frame_number - this->m_frame_shutter; - const float frame_step = (this->m_frame_shutter * 2.0f) / this->m_rasterMaskHandleTot; - float frame_iter = frame; - - Mask *mask_temp; - - mask_temp = BKE_mask_copy_nolib(this->m_mask); - - /* trick so we can get unkeyed edits to display */ - { - MaskLayer *masklay; - MaskLayerShape *masklay_shape; - - for (masklay = (MaskLayer *)mask_temp->masklayers.first; - masklay; - masklay = masklay->next) - { - masklay_shape = BKE_mask_layer_shape_verify_frame(masklay, this->m_frame_number); - BKE_mask_layer_shape_from_mask(masklay, masklay_shape); - } - } - - for (unsigned int i = 0; i < this->m_rasterMaskHandleTot; i++) { - this->m_rasterMaskHandles[i] = BKE_maskrasterize_handle_new(); - - /* re-eval frame info */ - BKE_mask_evaluate(mask_temp, frame_iter, true); - - BKE_maskrasterize_handle_init(this->m_rasterMaskHandles[i], mask_temp, - this->m_maskWidth, this->m_maskHeight, - true, true, this->m_do_feather); - - frame_iter += frame_step; - } - - BKE_mask_free(mask_temp); - MEM_freeN(mask_temp); - } - } + if (this->m_mask && this->m_rasterMaskHandles[0] == NULL) { + if (this->m_rasterMaskHandleTot == 1) { + this->m_rasterMaskHandles[0] = BKE_maskrasterize_handle_new(); + + BKE_maskrasterize_handle_init(this->m_rasterMaskHandles[0], + this->m_mask, + this->m_maskWidth, + this->m_maskHeight, + true, + true, + this->m_do_feather); + } + else { + /* make a throw away copy of the mask */ + const float frame = (float)this->m_frame_number - this->m_frame_shutter; + const float frame_step = (this->m_frame_shutter * 2.0f) / this->m_rasterMaskHandleTot; + float frame_iter = frame; + + Mask *mask_temp; + + mask_temp = BKE_mask_copy_nolib(this->m_mask); + + /* trick so we can get unkeyed edits to display */ + { + MaskLayer *masklay; + MaskLayerShape *masklay_shape; + + for (masklay = (MaskLayer *)mask_temp->masklayers.first; masklay; + masklay = masklay->next) { + masklay_shape = BKE_mask_layer_shape_verify_frame(masklay, this->m_frame_number); + BKE_mask_layer_shape_from_mask(masklay, masklay_shape); + } + } + + for (unsigned int i = 0; i < this->m_rasterMaskHandleTot; i++) { + this->m_rasterMaskHandles[i] = BKE_maskrasterize_handle_new(); + + /* re-eval frame info */ + BKE_mask_evaluate(mask_temp, frame_iter, true); + + BKE_maskrasterize_handle_init(this->m_rasterMaskHandles[i], + mask_temp, + this->m_maskWidth, + this->m_maskHeight, + true, + true, + this->m_do_feather); + + frame_iter += frame_step; + } + + BKE_mask_free(mask_temp); + MEM_freeN(mask_temp); + } + } } void MaskOperation::deinitExecution() { - for (unsigned int i = 0; i < this->m_rasterMaskHandleTot; i++) { - if (this->m_rasterMaskHandles[i]) { - BKE_maskrasterize_handle_free(this->m_rasterMaskHandles[i]); - this->m_rasterMaskHandles[i] = NULL; - } - } + for (unsigned int i = 0; i < this->m_rasterMaskHandleTot; i++) { + if (this->m_rasterMaskHandles[i]) { + BKE_maskrasterize_handle_free(this->m_rasterMaskHandles[i]); + this->m_rasterMaskHandles[i] = NULL; + } + } } -void MaskOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +void MaskOperation::determineResolution(unsigned int resolution[2], + unsigned int preferredResolution[2]) { - if (this->m_maskWidth == 0 || this->m_maskHeight == 0) { - NodeOperation::determineResolution(resolution, preferredResolution); - } - else { - unsigned int nr[2]; + if (this->m_maskWidth == 0 || this->m_maskHeight == 0) { + NodeOperation::determineResolution(resolution, preferredResolution); + } + else { + unsigned int nr[2]; - nr[0] = this->m_maskWidth; - nr[1] = this->m_maskHeight; + nr[0] = this->m_maskWidth; + nr[1] = this->m_maskHeight; - NodeOperation::determineResolution(resolution, nr); + NodeOperation::determineResolution(resolution, nr); - resolution[0] = this->m_maskWidth; - resolution[1] = this->m_maskHeight; - } + resolution[0] = this->m_maskWidth; + resolution[1] = this->m_maskHeight; + } } -void MaskOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) +void MaskOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler /*sampler*/) { - const float xy[2] = { - (x * this->m_maskWidthInv) + this->m_mask_px_ofs[0], - (y * this->m_maskHeightInv) + this->m_mask_px_ofs[1]}; - - if (this->m_rasterMaskHandleTot == 1) { - if (this->m_rasterMaskHandles[0]) { - output[0] = BKE_maskrasterize_handle_sample(this->m_rasterMaskHandles[0], xy); - } - else { - output[0] = 0.0f; - } - } - else { - /* incase loop below fails */ - output[0] = 0.0f; - - for (unsigned int i = 0; i < this->m_rasterMaskHandleTot; i++) { - if (this->m_rasterMaskHandles[i]) { - output[0] += BKE_maskrasterize_handle_sample(this->m_rasterMaskHandles[i], xy); - } - } - - /* until we get better falloff */ - output[0] /= this->m_rasterMaskHandleTot; - } + const float xy[2] = {(x * this->m_maskWidthInv) + this->m_mask_px_ofs[0], + (y * this->m_maskHeightInv) + this->m_mask_px_ofs[1]}; + + if (this->m_rasterMaskHandleTot == 1) { + if (this->m_rasterMaskHandles[0]) { + output[0] = BKE_maskrasterize_handle_sample(this->m_rasterMaskHandles[0], xy); + } + else { + output[0] = 0.0f; + } + } + else { + /* incase loop below fails */ + output[0] = 0.0f; + + for (unsigned int i = 0; i < this->m_rasterMaskHandleTot; i++) { + if (this->m_rasterMaskHandles[i]) { + output[0] += BKE_maskrasterize_handle_sample(this->m_rasterMaskHandles[i], xy); + } + } + + /* until we get better falloff */ + output[0] /= this->m_rasterMaskHandleTot; + } } diff --git a/source/blender/compositor/operations/COM_MaskOperation.h b/source/blender/compositor/operations/COM_MaskOperation.h index 643705e0535..531d6ef1b08 100644 --- a/source/blender/compositor/operations/COM_MaskOperation.h +++ b/source/blender/compositor/operations/COM_MaskOperation.h @@ -19,7 +19,6 @@ #ifndef __COM_MASKOPERATION_H__ #define __COM_MASKOPERATION_H__ - #include "COM_NodeOperation.h" #include "DNA_mask_types.h" #include "BLI_listbase.h" @@ -29,57 +28,71 @@ * Class with implementation of mask rasterization */ class MaskOperation : public NodeOperation { -protected: - Mask *m_mask; - - /* note, these are used more like aspect, - * but they _do_ impact on mask detail */ - int m_maskWidth; - int m_maskHeight; - float m_maskWidthInv; /* 1 / m_maskWidth */ - float m_maskHeightInv; /* 1 / m_maskHeight */ - float m_mask_px_ofs[2]; - - float m_frame_shutter; - int m_frame_number; - - bool m_do_feather; - - struct MaskRasterHandle *m_rasterMaskHandles[CMP_NODE_MASK_MBLUR_SAMPLES_MAX]; - unsigned int m_rasterMaskHandleTot; - - /** - * Determine the output resolution. The resolution is retrieved from the Renderer - */ - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); - -public: - MaskOperation(); - - void initExecution(); - void deinitExecution(); - - - void setMask(Mask *mask) { this->m_mask = mask; } - void setMaskWidth(int width) - { - this->m_maskWidth = width; - this->m_maskWidthInv = 1.0f / (float)width; - this->m_mask_px_ofs[0] = this->m_maskWidthInv * 0.5f; - } - void setMaskHeight(int height) - { - this->m_maskHeight = height; - this->m_maskHeightInv = 1.0f / (float)height; - this->m_mask_px_ofs[1] = this->m_maskHeightInv * 0.5f; - } - void setFramenumber(int frame_number) { this->m_frame_number = frame_number; } - void setFeather(bool feather) { this->m_do_feather = feather; } - - void setMotionBlurSamples(int samples) { this->m_rasterMaskHandleTot = min(max(1, samples), CMP_NODE_MASK_MBLUR_SAMPLES_MAX); } - void setMotionBlurShutter(float shutter) { this->m_frame_shutter = shutter; } - - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + protected: + Mask *m_mask; + + /* note, these are used more like aspect, + * but they _do_ impact on mask detail */ + int m_maskWidth; + int m_maskHeight; + float m_maskWidthInv; /* 1 / m_maskWidth */ + float m_maskHeightInv; /* 1 / m_maskHeight */ + float m_mask_px_ofs[2]; + + float m_frame_shutter; + int m_frame_number; + + bool m_do_feather; + + struct MaskRasterHandle *m_rasterMaskHandles[CMP_NODE_MASK_MBLUR_SAMPLES_MAX]; + unsigned int m_rasterMaskHandleTot; + + /** + * Determine the output resolution. The resolution is retrieved from the Renderer + */ + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); + + public: + MaskOperation(); + + void initExecution(); + void deinitExecution(); + + void setMask(Mask *mask) + { + this->m_mask = mask; + } + void setMaskWidth(int width) + { + this->m_maskWidth = width; + this->m_maskWidthInv = 1.0f / (float)width; + this->m_mask_px_ofs[0] = this->m_maskWidthInv * 0.5f; + } + void setMaskHeight(int height) + { + this->m_maskHeight = height; + this->m_maskHeightInv = 1.0f / (float)height; + this->m_mask_px_ofs[1] = this->m_maskHeightInv * 0.5f; + } + void setFramenumber(int frame_number) + { + this->m_frame_number = frame_number; + } + void setFeather(bool feather) + { + this->m_do_feather = feather; + } + + void setMotionBlurSamples(int samples) + { + this->m_rasterMaskHandleTot = min(max(1, samples), CMP_NODE_MASK_MBLUR_SAMPLES_MAX); + } + void setMotionBlurShutter(float shutter) + { + this->m_frame_shutter = shutter; + } + + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; #endif diff --git a/source/blender/compositor/operations/COM_MathBaseOperation.cpp b/source/blender/compositor/operations/COM_MathBaseOperation.cpp index 5bcb71a8dfc..b3251d32005 100644 --- a/source/blender/compositor/operations/COM_MathBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_MathBaseOperation.cpp @@ -23,379 +23,448 @@ extern "C" { MathBaseOperation::MathBaseOperation() : NodeOperation() { - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_VALUE); - this->m_inputValue1Operation = NULL; - this->m_inputValue2Operation = NULL; - this->m_useClamp = false; + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_VALUE); + this->m_inputValue1Operation = NULL; + this->m_inputValue2Operation = NULL; + this->m_useClamp = false; } void MathBaseOperation::initExecution() { - this->m_inputValue1Operation = this->getInputSocketReader(0); - this->m_inputValue2Operation = this->getInputSocketReader(1); + this->m_inputValue1Operation = this->getInputSocketReader(0); + this->m_inputValue2Operation = this->getInputSocketReader(1); } - void MathBaseOperation::deinitExecution() { - this->m_inputValue1Operation = NULL; - this->m_inputValue2Operation = NULL; + this->m_inputValue1Operation = NULL; + this->m_inputValue2Operation = NULL; } -void MathBaseOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +void MathBaseOperation::determineResolution(unsigned int resolution[2], + unsigned int preferredResolution[2]) { - NodeOperationInput *socket; - unsigned int tempPreferredResolution[2] = {0, 0}; - unsigned int tempResolution[2]; - - socket = this->getInputSocket(0); - socket->determineResolution(tempResolution, tempPreferredResolution); - if ((tempResolution[0] != 0) && (tempResolution[1] != 0)) { - this->setResolutionInputSocketIndex(0); - } - else { - this->setResolutionInputSocketIndex(1); - } - NodeOperation::determineResolution(resolution, preferredResolution); + NodeOperationInput *socket; + unsigned int tempPreferredResolution[2] = {0, 0}; + unsigned int tempResolution[2]; + + socket = this->getInputSocket(0); + socket->determineResolution(tempResolution, tempPreferredResolution); + if ((tempResolution[0] != 0) && (tempResolution[1] != 0)) { + this->setResolutionInputSocketIndex(0); + } + else { + this->setResolutionInputSocketIndex(1); + } + NodeOperation::determineResolution(resolution, preferredResolution); } void MathBaseOperation::clampIfNeeded(float *color) { - if (this->m_useClamp) { - CLAMP(color[0], 0.0f, 1.0f); - } + if (this->m_useClamp) { + CLAMP(color[0], 0.0f, 1.0f); + } } void MathAddOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { - float inputValue1[4]; - float inputValue2[4]; + float inputValue1[4]; + float inputValue2[4]; - this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); - this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); + this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); + this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); - output[0] = inputValue1[0] + inputValue2[0]; + output[0] = inputValue1[0] + inputValue2[0]; - clampIfNeeded(output); + clampIfNeeded(output); } -void MathSubtractOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MathSubtractOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue1[4]; - float inputValue2[4]; + float inputValue1[4]; + float inputValue2[4]; - this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); - this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); + this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); + this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); - output[0] = inputValue1[0] - inputValue2[0]; + output[0] = inputValue1[0] - inputValue2[0]; - clampIfNeeded(output); + clampIfNeeded(output); } -void MathMultiplyOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MathMultiplyOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue1[4]; - float inputValue2[4]; + float inputValue1[4]; + float inputValue2[4]; - this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); - this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); + this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); + this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); - output[0] = inputValue1[0] * inputValue2[0]; + output[0] = inputValue1[0] * inputValue2[0]; - clampIfNeeded(output); + clampIfNeeded(output); } -void MathDivideOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MathDivideOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue1[4]; - float inputValue2[4]; + float inputValue1[4]; + float inputValue2[4]; - this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); - this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); + this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); + this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); - if (inputValue2[0] == 0) /* We don't want to divide by zero. */ - output[0] = 0.0; - else - output[0] = inputValue1[0] / inputValue2[0]; + if (inputValue2[0] == 0) /* We don't want to divide by zero. */ + output[0] = 0.0; + else + output[0] = inputValue1[0] / inputValue2[0]; - clampIfNeeded(output); + clampIfNeeded(output); } -void MathSineOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MathSineOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue1[4]; - float inputValue2[4]; + float inputValue1[4]; + float inputValue2[4]; - this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); - this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); + this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); + this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); - output[0] = sin(inputValue1[0]); + output[0] = sin(inputValue1[0]); - clampIfNeeded(output); + clampIfNeeded(output); } -void MathCosineOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MathCosineOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue1[4]; - float inputValue2[4]; + float inputValue1[4]; + float inputValue2[4]; - this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); - this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); + this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); + this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); - output[0] = cos(inputValue1[0]); + output[0] = cos(inputValue1[0]); - clampIfNeeded(output); + clampIfNeeded(output); } -void MathTangentOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MathTangentOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue1[4]; - float inputValue2[4]; + float inputValue1[4]; + float inputValue2[4]; - this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); - this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); + this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); + this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); - output[0] = tan(inputValue1[0]); + output[0] = tan(inputValue1[0]); - clampIfNeeded(output); + clampIfNeeded(output); } -void MathArcSineOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MathArcSineOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue1[4]; - float inputValue2[4]; + float inputValue1[4]; + float inputValue2[4]; - this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); - this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); + this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); + this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); - if (inputValue1[0] <= 1 && inputValue1[0] >= -1) - output[0] = asin(inputValue1[0]); - else - output[0] = 0.0; + if (inputValue1[0] <= 1 && inputValue1[0] >= -1) + output[0] = asin(inputValue1[0]); + else + output[0] = 0.0; - clampIfNeeded(output); + clampIfNeeded(output); } -void MathArcCosineOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MathArcCosineOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue1[4]; - float inputValue2[4]; + float inputValue1[4]; + float inputValue2[4]; - this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); - this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); + this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); + this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); - if (inputValue1[0] <= 1 && inputValue1[0] >= -1) - output[0] = acos(inputValue1[0]); - else - output[0] = 0.0; + if (inputValue1[0] <= 1 && inputValue1[0] >= -1) + output[0] = acos(inputValue1[0]); + else + output[0] = 0.0; - clampIfNeeded(output); + clampIfNeeded(output); } -void MathArcTangentOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MathArcTangentOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue1[4]; - float inputValue2[4]; + float inputValue1[4]; + float inputValue2[4]; - this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); - this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); + this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); + this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); - output[0] = atan(inputValue1[0]); + output[0] = atan(inputValue1[0]); - clampIfNeeded(output); + clampIfNeeded(output); } -void MathPowerOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MathPowerOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue1[4]; - float inputValue2[4]; - - this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); - this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); - - if (inputValue1[0] >= 0) { - output[0] = pow(inputValue1[0], inputValue2[0]); - } - else { - float y_mod_1 = fmod(inputValue2[0], 1); - /* if input value is not nearly an integer, fall back to zero, nicer than straight rounding */ - if (y_mod_1 > 0.999f || y_mod_1 < 0.001f) { - output[0] = pow(inputValue1[0], floorf(inputValue2[0] + 0.5f)); - } - else { - output[0] = 0.0; - } - } - - clampIfNeeded(output); + float inputValue1[4]; + float inputValue2[4]; + + this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); + this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); + + if (inputValue1[0] >= 0) { + output[0] = pow(inputValue1[0], inputValue2[0]); + } + else { + float y_mod_1 = fmod(inputValue2[0], 1); + /* if input value is not nearly an integer, fall back to zero, nicer than straight rounding */ + if (y_mod_1 > 0.999f || y_mod_1 < 0.001f) { + output[0] = pow(inputValue1[0], floorf(inputValue2[0] + 0.5f)); + } + else { + output[0] = 0.0; + } + } + + clampIfNeeded(output); } -void MathLogarithmOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MathLogarithmOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue1[4]; - float inputValue2[4]; + float inputValue1[4]; + float inputValue2[4]; - this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); - this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); + this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); + this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); - if (inputValue1[0] > 0 && inputValue2[0] > 0) - output[0] = log(inputValue1[0]) / log(inputValue2[0]); - else - output[0] = 0.0; + if (inputValue1[0] > 0 && inputValue2[0] > 0) + output[0] = log(inputValue1[0]) / log(inputValue2[0]); + else + output[0] = 0.0; - clampIfNeeded(output); + clampIfNeeded(output); } -void MathMinimumOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MathMinimumOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue1[4]; - float inputValue2[4]; + float inputValue1[4]; + float inputValue2[4]; - this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); - this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); + this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); + this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); - output[0] = min(inputValue1[0], inputValue2[0]); + output[0] = min(inputValue1[0], inputValue2[0]); - clampIfNeeded(output); + clampIfNeeded(output); } -void MathMaximumOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MathMaximumOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue1[4]; - float inputValue2[4]; + float inputValue1[4]; + float inputValue2[4]; - this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); - this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); + this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); + this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); - output[0] = max(inputValue1[0], inputValue2[0]); + output[0] = max(inputValue1[0], inputValue2[0]); - clampIfNeeded(output); + clampIfNeeded(output); } -void MathRoundOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MathRoundOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue1[4]; - float inputValue2[4]; + float inputValue1[4]; + float inputValue2[4]; - this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); - this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); + this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); + this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); - output[0] = round(inputValue1[0]); + output[0] = round(inputValue1[0]); - clampIfNeeded(output); + clampIfNeeded(output); } -void MathLessThanOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MathLessThanOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue1[4]; - float inputValue2[4]; + float inputValue1[4]; + float inputValue2[4]; - this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); - this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); + this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); + this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); - output[0] = inputValue1[0] < inputValue2[0] ? 1.0f : 0.0f; + output[0] = inputValue1[0] < inputValue2[0] ? 1.0f : 0.0f; - clampIfNeeded(output); + clampIfNeeded(output); } -void MathGreaterThanOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MathGreaterThanOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue1[4]; - float inputValue2[4]; + float inputValue1[4]; + float inputValue2[4]; - this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); - this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); + this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); + this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); - output[0] = inputValue1[0] > inputValue2[0] ? 1.0f : 0.0f; + output[0] = inputValue1[0] > inputValue2[0] ? 1.0f : 0.0f; - clampIfNeeded(output); + clampIfNeeded(output); } -void MathModuloOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MathModuloOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue1[4]; - float inputValue2[4]; + float inputValue1[4]; + float inputValue2[4]; - this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); - this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); + this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); + this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); - if (inputValue2[0] == 0) - output[0] = 0.0; - else - output[0] = fmod(inputValue1[0], inputValue2[0]); + if (inputValue2[0] == 0) + output[0] = 0.0; + else + output[0] = fmod(inputValue1[0], inputValue2[0]); - clampIfNeeded(output); + clampIfNeeded(output); } -void MathAbsoluteOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MathAbsoluteOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue1[4]; + float inputValue1[4]; - this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); + this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); - output[0] = fabs(inputValue1[0]); + output[0] = fabs(inputValue1[0]); - clampIfNeeded(output); + clampIfNeeded(output); } -void MathArcTan2Operation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MathArcTan2Operation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue1[4]; - float inputValue2[4]; + float inputValue1[4]; + float inputValue2[4]; - this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); - this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); + this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); + this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); - output[0] = atan2(inputValue1[0], inputValue2[0]); + output[0] = atan2(inputValue1[0], inputValue2[0]); - clampIfNeeded(output); + clampIfNeeded(output); } -void MathFloorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MathFloorOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue1[4]; + float inputValue1[4]; - this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); + this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); - output[0] = floor(inputValue1[0]); + output[0] = floor(inputValue1[0]); - clampIfNeeded(output); + clampIfNeeded(output); } -void MathCeilOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MathCeilOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue1[4]; + float inputValue1[4]; - this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); + this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); - output[0] = ceil(inputValue1[0]); + output[0] = ceil(inputValue1[0]); - clampIfNeeded(output); + clampIfNeeded(output); } -void MathFractOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MathFractOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue1[4]; + float inputValue1[4]; - this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); + this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); - output[0] = inputValue1[0] - floor(inputValue1[0]); + output[0] = inputValue1[0] - floor(inputValue1[0]); - clampIfNeeded(output); + clampIfNeeded(output); } -void MathSqrtOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MathSqrtOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputValue1[4]; + float inputValue1[4]; - this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); + this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); - if (inputValue1[0] > 0) - output[0] = sqrt(inputValue1[0]); - else - output[0] = 0.0f; + if (inputValue1[0] > 0) + output[0] = sqrt(inputValue1[0]); + else + output[0] = 0.0f; - clampIfNeeded(output); + clampIfNeeded(output); } diff --git a/source/blender/compositor/operations/COM_MathBaseOperation.h b/source/blender/compositor/operations/COM_MathBaseOperation.h index 7306a166e87..7c11ea8f45b 100644 --- a/source/blender/compositor/operations/COM_MathBaseOperation.h +++ b/source/blender/compositor/operations/COM_MathBaseOperation.h @@ -20,179 +20,230 @@ #define __COM_MATHBASEOPERATION_H__ #include "COM_NodeOperation.h" - /** * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ class MathBaseOperation : public NodeOperation { -protected: - /** - * Prefetched reference to the inputProgram - */ - SocketReader *m_inputValue1Operation; - SocketReader *m_inputValue2Operation; - - bool m_useClamp; - -protected: - /** - * Default constructor - */ - MathBaseOperation(); - - void clampIfNeeded(float color[4]); -public: - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) = 0; - - /** - * Initialize the execution - */ - void initExecution(); - - /** - * Deinitialize the execution - */ - void deinitExecution(); - - /** - * Determine resolution - */ - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); - - void setUseClamp(bool value) { this->m_useClamp = value; } + protected: + /** + * Prefetched reference to the inputProgram + */ + SocketReader *m_inputValue1Operation; + SocketReader *m_inputValue2Operation; + + bool m_useClamp; + + protected: + /** + * Default constructor + */ + MathBaseOperation(); + + void clampIfNeeded(float color[4]); + + public: + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) = 0; + + /** + * Initialize the execution + */ + void initExecution(); + + /** + * Deinitialize the execution + */ + void deinitExecution(); + + /** + * Determine resolution + */ + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); + + void setUseClamp(bool value) + { + this->m_useClamp = value; + } }; class MathAddOperation : public MathBaseOperation { -public: - MathAddOperation() : MathBaseOperation() {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MathAddOperation() : MathBaseOperation() + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MathSubtractOperation : public MathBaseOperation { -public: - MathSubtractOperation() : MathBaseOperation() {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MathSubtractOperation() : MathBaseOperation() + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MathMultiplyOperation : public MathBaseOperation { -public: - MathMultiplyOperation() : MathBaseOperation() {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MathMultiplyOperation() : MathBaseOperation() + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MathDivideOperation : public MathBaseOperation { -public: - MathDivideOperation() : MathBaseOperation() {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MathDivideOperation() : MathBaseOperation() + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MathSineOperation : public MathBaseOperation { -public: - MathSineOperation() : MathBaseOperation() {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MathSineOperation() : MathBaseOperation() + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MathCosineOperation : public MathBaseOperation { -public: - MathCosineOperation() : MathBaseOperation() {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MathCosineOperation() : MathBaseOperation() + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MathTangentOperation : public MathBaseOperation { -public: - MathTangentOperation() : MathBaseOperation() {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MathTangentOperation() : MathBaseOperation() + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MathArcSineOperation : public MathBaseOperation { -public: - MathArcSineOperation() : MathBaseOperation() {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MathArcSineOperation() : MathBaseOperation() + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MathArcCosineOperation : public MathBaseOperation { -public: - MathArcCosineOperation() : MathBaseOperation() {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MathArcCosineOperation() : MathBaseOperation() + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MathArcTangentOperation : public MathBaseOperation { -public: - MathArcTangentOperation() : MathBaseOperation() {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MathArcTangentOperation() : MathBaseOperation() + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MathPowerOperation : public MathBaseOperation { -public: - MathPowerOperation() : MathBaseOperation() {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MathPowerOperation() : MathBaseOperation() + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MathLogarithmOperation : public MathBaseOperation { -public: - MathLogarithmOperation() : MathBaseOperation() {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MathLogarithmOperation() : MathBaseOperation() + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MathMinimumOperation : public MathBaseOperation { -public: - MathMinimumOperation() : MathBaseOperation() {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MathMinimumOperation() : MathBaseOperation() + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MathMaximumOperation : public MathBaseOperation { -public: - MathMaximumOperation() : MathBaseOperation() {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MathMaximumOperation() : MathBaseOperation() + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MathRoundOperation : public MathBaseOperation { -public: - MathRoundOperation() : MathBaseOperation() {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MathRoundOperation() : MathBaseOperation() + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MathLessThanOperation : public MathBaseOperation { -public: - MathLessThanOperation() : MathBaseOperation() {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MathLessThanOperation() : MathBaseOperation() + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MathGreaterThanOperation : public MathBaseOperation { -public: - MathGreaterThanOperation() : MathBaseOperation() {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MathGreaterThanOperation() : MathBaseOperation() + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MathModuloOperation : public MathBaseOperation { -public: - MathModuloOperation() : MathBaseOperation() {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MathModuloOperation() : MathBaseOperation() + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MathAbsoluteOperation : public MathBaseOperation { -public: - MathAbsoluteOperation() : MathBaseOperation() {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MathAbsoluteOperation() : MathBaseOperation() + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MathArcTan2Operation : public MathBaseOperation { -public: - MathArcTan2Operation() : MathBaseOperation() {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MathArcTan2Operation() : MathBaseOperation() + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MathFloorOperation : public MathBaseOperation { -public: - MathFloorOperation() : MathBaseOperation() {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MathFloorOperation() : MathBaseOperation() + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MathCeilOperation : public MathBaseOperation { -public: - MathCeilOperation() : MathBaseOperation() {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MathCeilOperation() : MathBaseOperation() + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MathFractOperation : public MathBaseOperation { -public: - MathFractOperation() : MathBaseOperation() {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MathFractOperation() : MathBaseOperation() + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MathSqrtOperation : public MathBaseOperation { -public: - MathSqrtOperation() : MathBaseOperation() {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MathSqrtOperation() : MathBaseOperation() + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; #endif diff --git a/source/blender/compositor/operations/COM_MixOperation.cpp b/source/blender/compositor/operations/COM_MixOperation.cpp index abde0fa5547..8e09586aaa8 100644 --- a/source/blender/compositor/operations/COM_MixOperation.cpp +++ b/source/blender/compositor/operations/COM_MixOperation.cpp @@ -19,818 +19,882 @@ #include "COM_MixOperation.h" extern "C" { -# include "BLI_math.h" +#include "BLI_math.h" } /* ******** Mix Base Operation ******** */ MixBaseOperation::MixBaseOperation() : NodeOperation() { - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - this->m_inputValueOperation = NULL; - this->m_inputColor1Operation = NULL; - this->m_inputColor2Operation = NULL; - this->setUseValueAlphaMultiply(false); - this->setUseClamp(false); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); + this->m_inputValueOperation = NULL; + this->m_inputColor1Operation = NULL; + this->m_inputColor2Operation = NULL; + this->setUseValueAlphaMultiply(false); + this->setUseClamp(false); } void MixBaseOperation::initExecution() { - this->m_inputValueOperation = this->getInputSocketReader(0); - this->m_inputColor1Operation = this->getInputSocketReader(1); - this->m_inputColor2Operation = this->getInputSocketReader(2); + this->m_inputValueOperation = this->getInputSocketReader(0); + this->m_inputColor1Operation = this->getInputSocketReader(1); + this->m_inputColor2Operation = this->getInputSocketReader(2); } void MixBaseOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - - this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); - this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); - this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); - - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float valuem = 1.0f - value; - output[0] = valuem * (inputColor1[0]) + value * (inputColor2[0]); - output[1] = valuem * (inputColor1[1]) + value * (inputColor2[1]); - output[2] = valuem * (inputColor1[2]) + value * (inputColor2[2]); - output[3] = inputColor1[3]; -} - -void MixBaseOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) -{ - NodeOperationInput *socket; - unsigned int tempPreferredResolution[2] = {0, 0}; - unsigned int tempResolution[2]; - - socket = this->getInputSocket(1); - socket->determineResolution(tempResolution, tempPreferredResolution); - if ((tempResolution[0] != 0) && (tempResolution[1] != 0)) { - this->setResolutionInputSocketIndex(1); - } - else { - socket = this->getInputSocket(2); - socket->determineResolution(tempResolution, tempPreferredResolution); - if ((tempResolution[0] != 0) && (tempResolution[1] != 0)) { - this->setResolutionInputSocketIndex(2); - } - else { - this->setResolutionInputSocketIndex(0); - } - } - NodeOperation::determineResolution(resolution, preferredResolution); + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + + this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); + this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); + this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); + + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float valuem = 1.0f - value; + output[0] = valuem * (inputColor1[0]) + value * (inputColor2[0]); + output[1] = valuem * (inputColor1[1]) + value * (inputColor2[1]); + output[2] = valuem * (inputColor1[2]) + value * (inputColor2[2]); + output[3] = inputColor1[3]; +} + +void MixBaseOperation::determineResolution(unsigned int resolution[2], + unsigned int preferredResolution[2]) +{ + NodeOperationInput *socket; + unsigned int tempPreferredResolution[2] = {0, 0}; + unsigned int tempResolution[2]; + + socket = this->getInputSocket(1); + socket->determineResolution(tempResolution, tempPreferredResolution); + if ((tempResolution[0] != 0) && (tempResolution[1] != 0)) { + this->setResolutionInputSocketIndex(1); + } + else { + socket = this->getInputSocket(2); + socket->determineResolution(tempResolution, tempPreferredResolution); + if ((tempResolution[0] != 0) && (tempResolution[1] != 0)) { + this->setResolutionInputSocketIndex(2); + } + else { + this->setResolutionInputSocketIndex(0); + } + } + NodeOperation::determineResolution(resolution, preferredResolution); } void MixBaseOperation::deinitExecution() { - this->m_inputValueOperation = NULL; - this->m_inputColor1Operation = NULL; - this->m_inputColor2Operation = NULL; + this->m_inputValueOperation = NULL; + this->m_inputColor1Operation = NULL; + this->m_inputColor2Operation = NULL; } /* ******** Mix Add Operation ******** */ MixAddOperation::MixAddOperation() : MixBaseOperation() { - /* pass */ + /* pass */ } void MixAddOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; - this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); - this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); - this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); + this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); + this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); + this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - output[0] = inputColor1[0] + value * inputColor2[0]; - output[1] = inputColor1[1] + value * inputColor2[1]; - output[2] = inputColor1[2] + value * inputColor2[2]; - output[3] = inputColor1[3]; + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + output[0] = inputColor1[0] + value * inputColor2[0]; + output[1] = inputColor1[1] + value * inputColor2[1]; + output[2] = inputColor1[2] + value * inputColor2[2]; + output[3] = inputColor1[3]; - clampIfNeeded(output); + clampIfNeeded(output); } /* ******** Mix Blend Operation ******** */ MixBlendOperation::MixBlendOperation() : MixBaseOperation() { - /* pass */ + /* pass */ } -void MixBlendOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MixBlendOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - float value; + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + float value; - this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); - this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); - this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); - value = inputValue[0]; + this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); + this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); + this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); + value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float valuem = 1.0f - value; - output[0] = valuem * (inputColor1[0]) + value * (inputColor2[0]); - output[1] = valuem * (inputColor1[1]) + value * (inputColor2[1]); - output[2] = valuem * (inputColor1[2]) + value * (inputColor2[2]); - output[3] = inputColor1[3]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float valuem = 1.0f - value; + output[0] = valuem * (inputColor1[0]) + value * (inputColor2[0]); + output[1] = valuem * (inputColor1[1]) + value * (inputColor2[1]); + output[2] = valuem * (inputColor1[2]) + value * (inputColor2[2]); + output[3] = inputColor1[3]; - clampIfNeeded(output); + clampIfNeeded(output); } /* ******** Mix Burn Operation ******** */ MixBurnOperation::MixBurnOperation() : MixBaseOperation() { - /* pass */ + /* pass */ } void MixBurnOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - float tmp; - - this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); - this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); - this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); - - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float valuem = 1.0f - value; - - tmp = valuem + value * inputColor2[0]; - if (tmp <= 0.0f) - output[0] = 0.0f; - else { - tmp = 1.0f - (1.0f - inputColor1[0]) / tmp; - if (tmp < 0.0f) - output[0] = 0.0f; - else if (tmp > 1.0f) - output[0] = 1.0f; - else - output[0] = tmp; - } - - tmp = valuem + value * inputColor2[1]; - if (tmp <= 0.0f) - output[1] = 0.0f; - else { - tmp = 1.0f - (1.0f - inputColor1[1]) / tmp; - if (tmp < 0.0f) - output[1] = 0.0f; - else if (tmp > 1.0f) - output[1] = 1.0f; - else - output[1] = tmp; - } - - tmp = valuem + value * inputColor2[2]; - if (tmp <= 0.0f) - output[2] = 0.0f; - else { - tmp = 1.0f - (1.0f - inputColor1[2]) / tmp; - if (tmp < 0.0f) - output[2] = 0.0f; - else if (tmp > 1.0f) - output[2] = 1.0f; - else - output[2] = tmp; - } - - output[3] = inputColor1[3]; - - clampIfNeeded(output); + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + float tmp; + + this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); + this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); + this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); + + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float valuem = 1.0f - value; + + tmp = valuem + value * inputColor2[0]; + if (tmp <= 0.0f) + output[0] = 0.0f; + else { + tmp = 1.0f - (1.0f - inputColor1[0]) / tmp; + if (tmp < 0.0f) + output[0] = 0.0f; + else if (tmp > 1.0f) + output[0] = 1.0f; + else + output[0] = tmp; + } + + tmp = valuem + value * inputColor2[1]; + if (tmp <= 0.0f) + output[1] = 0.0f; + else { + tmp = 1.0f - (1.0f - inputColor1[1]) / tmp; + if (tmp < 0.0f) + output[1] = 0.0f; + else if (tmp > 1.0f) + output[1] = 1.0f; + else + output[1] = tmp; + } + + tmp = valuem + value * inputColor2[2]; + if (tmp <= 0.0f) + output[2] = 0.0f; + else { + tmp = 1.0f - (1.0f - inputColor1[2]) / tmp; + if (tmp < 0.0f) + output[2] = 0.0f; + else if (tmp > 1.0f) + output[2] = 1.0f; + else + output[2] = tmp; + } + + output[3] = inputColor1[3]; + + clampIfNeeded(output); } /* ******** Mix Color Operation ******** */ MixColorOperation::MixColorOperation() : MixBaseOperation() { - /* pass */ + /* pass */ } -void MixColorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MixColorOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; - this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); - this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); - this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); + this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); + this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); + this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float valuem = 1.0f - value; + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float valuem = 1.0f - value; - float colH, colS, colV; - rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV); - if (colS != 0.0f) { - float rH, rS, rV; - float tmpr, tmpg, tmpb; - rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV); - hsv_to_rgb(colH, colS, rV, &tmpr, &tmpg, &tmpb); - output[0] = (valuem * inputColor1[0]) + (value * tmpr); - output[1] = (valuem * inputColor1[1]) + (value * tmpg); - output[2] = (valuem * inputColor1[2]) + (value * tmpb); - } - else { - copy_v3_v3(output, inputColor1); - } - output[3] = inputColor1[3]; + float colH, colS, colV; + rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV); + if (colS != 0.0f) { + float rH, rS, rV; + float tmpr, tmpg, tmpb; + rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV); + hsv_to_rgb(colH, colS, rV, &tmpr, &tmpg, &tmpb); + output[0] = (valuem * inputColor1[0]) + (value * tmpr); + output[1] = (valuem * inputColor1[1]) + (value * tmpg); + output[2] = (valuem * inputColor1[2]) + (value * tmpb); + } + else { + copy_v3_v3(output, inputColor1); + } + output[3] = inputColor1[3]; - clampIfNeeded(output); + clampIfNeeded(output); } /* ******** Mix Darken Operation ******** */ MixDarkenOperation::MixDarkenOperation() : MixBaseOperation() { - /* pass */ + /* pass */ } -void MixDarkenOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MixDarkenOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; - this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); - this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); - this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); + this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); + this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); + this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float valuem = 1.0f - value; - output[0] = min_ff(inputColor1[0], inputColor2[0]) * value + inputColor1[0] * valuem; - output[1] = min_ff(inputColor1[1], inputColor2[1]) * value + inputColor1[1] * valuem; - output[2] = min_ff(inputColor1[2], inputColor2[2]) * value + inputColor1[2] * valuem; - output[3] = inputColor1[3]; + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float valuem = 1.0f - value; + output[0] = min_ff(inputColor1[0], inputColor2[0]) * value + inputColor1[0] * valuem; + output[1] = min_ff(inputColor1[1], inputColor2[1]) * value + inputColor1[1] * valuem; + output[2] = min_ff(inputColor1[2], inputColor2[2]) * value + inputColor1[2] * valuem; + output[3] = inputColor1[3]; - clampIfNeeded(output); + clampIfNeeded(output); } /* ******** Mix Difference Operation ******** */ MixDifferenceOperation::MixDifferenceOperation() : MixBaseOperation() { - /* pass */ + /* pass */ } -void MixDifferenceOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MixDifferenceOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; - this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); - this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); - this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); + this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); + this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); + this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float valuem = 1.0f - value; - output[0] = valuem * inputColor1[0] + value * fabsf(inputColor1[0] - inputColor2[0]); - output[1] = valuem * inputColor1[1] + value * fabsf(inputColor1[1] - inputColor2[1]); - output[2] = valuem * inputColor1[2] + value * fabsf(inputColor1[2] - inputColor2[2]); - output[3] = inputColor1[3]; + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float valuem = 1.0f - value; + output[0] = valuem * inputColor1[0] + value * fabsf(inputColor1[0] - inputColor2[0]); + output[1] = valuem * inputColor1[1] + value * fabsf(inputColor1[1] - inputColor2[1]); + output[2] = valuem * inputColor1[2] + value * fabsf(inputColor1[2] - inputColor2[2]); + output[3] = inputColor1[3]; - clampIfNeeded(output); + clampIfNeeded(output); } /* ******** Mix Difference Operation ******** */ MixDivideOperation::MixDivideOperation() : MixBaseOperation() { - /* pass */ + /* pass */ } -void MixDivideOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MixDivideOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; - this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); - this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); - this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); + this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); + this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); + this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float valuem = 1.0f - value; + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float valuem = 1.0f - value; - if (inputColor2[0] != 0.0f) - output[0] = valuem * (inputColor1[0]) + value * (inputColor1[0]) / inputColor2[0]; - else - output[0] = 0.0f; - if (inputColor2[1] != 0.0f) - output[1] = valuem * (inputColor1[1]) + value * (inputColor1[1]) / inputColor2[1]; - else - output[1] = 0.0f; - if (inputColor2[2] != 0.0f) - output[2] = valuem * (inputColor1[2]) + value * (inputColor1[2]) / inputColor2[2]; - else - output[2] = 0.0f; + if (inputColor2[0] != 0.0f) + output[0] = valuem * (inputColor1[0]) + value * (inputColor1[0]) / inputColor2[0]; + else + output[0] = 0.0f; + if (inputColor2[1] != 0.0f) + output[1] = valuem * (inputColor1[1]) + value * (inputColor1[1]) / inputColor2[1]; + else + output[1] = 0.0f; + if (inputColor2[2] != 0.0f) + output[2] = valuem * (inputColor1[2]) + value * (inputColor1[2]) / inputColor2[2]; + else + output[2] = 0.0f; - output[3] = inputColor1[3]; + output[3] = inputColor1[3]; - clampIfNeeded(output); + clampIfNeeded(output); } /* ******** Mix Dodge Operation ******** */ MixDodgeOperation::MixDodgeOperation() : MixBaseOperation() { - /* pass */ -} - -void MixDodgeOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - float tmp; - - this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); - this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); - this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); - - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - - if (inputColor1[0] != 0.0f) { - tmp = 1.0f - value * inputColor2[0]; - if (tmp <= 0.0f) - output[0] = 1.0f; - else { - tmp = inputColor1[0] / tmp; - if (tmp > 1.0f) - output[0] = 1.0f; - else - output[0] = tmp; - } - } - else - output[0] = 0.0f; - - if (inputColor1[1] != 0.0f) { - tmp = 1.0f - value * inputColor2[1]; - if (tmp <= 0.0f) - output[1] = 1.0f; - else { - tmp = inputColor1[1] / tmp; - if (tmp > 1.0f) - output[1] = 1.0f; - else - output[1] = tmp; - } - } - else - output[1] = 0.0f; - - if (inputColor1[2] != 0.0f) { - tmp = 1.0f - value * inputColor2[2]; - if (tmp <= 0.0f) - output[2] = 1.0f; - else { - tmp = inputColor1[2] / tmp; - if (tmp > 1.0f) - output[2] = 1.0f; - else - output[2] = tmp; - } - } - else - output[2] = 0.0f; - - output[3] = inputColor1[3]; - - clampIfNeeded(output); + /* pass */ +} + +void MixDodgeOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) +{ + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + float tmp; + + this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); + this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); + this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); + + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + + if (inputColor1[0] != 0.0f) { + tmp = 1.0f - value * inputColor2[0]; + if (tmp <= 0.0f) + output[0] = 1.0f; + else { + tmp = inputColor1[0] / tmp; + if (tmp > 1.0f) + output[0] = 1.0f; + else + output[0] = tmp; + } + } + else + output[0] = 0.0f; + + if (inputColor1[1] != 0.0f) { + tmp = 1.0f - value * inputColor2[1]; + if (tmp <= 0.0f) + output[1] = 1.0f; + else { + tmp = inputColor1[1] / tmp; + if (tmp > 1.0f) + output[1] = 1.0f; + else + output[1] = tmp; + } + } + else + output[1] = 0.0f; + + if (inputColor1[2] != 0.0f) { + tmp = 1.0f - value * inputColor2[2]; + if (tmp <= 0.0f) + output[2] = 1.0f; + else { + tmp = inputColor1[2] / tmp; + if (tmp > 1.0f) + output[2] = 1.0f; + else + output[2] = tmp; + } + } + else + output[2] = 0.0f; + + output[3] = inputColor1[3]; + + clampIfNeeded(output); } /* ******** Mix Glare Operation ******** */ MixGlareOperation::MixGlareOperation() : MixBaseOperation() { - /* pass */ + /* pass */ } -void MixGlareOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MixGlareOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - float value; + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + float value; - this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); - this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); - this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); - value = inputValue[0]; - float mf = 2.0f - 2.0f * fabsf(value - 0.5f); + this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); + this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); + this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); + value = inputValue[0]; + float mf = 2.0f - 2.0f * fabsf(value - 0.5f); - if (inputColor1[0] < 0.0f) inputColor1[0] = 0.0f; - if (inputColor1[1] < 0.0f) inputColor1[1] = 0.0f; - if (inputColor1[2] < 0.0f) inputColor1[2] = 0.0f; + if (inputColor1[0] < 0.0f) + inputColor1[0] = 0.0f; + if (inputColor1[1] < 0.0f) + inputColor1[1] = 0.0f; + if (inputColor1[2] < 0.0f) + inputColor1[2] = 0.0f; - output[0] = mf * max(inputColor1[0] + value * (inputColor2[0] - inputColor1[0]), 0.0f); - output[1] = mf * max(inputColor1[1] + value * (inputColor2[1] - inputColor1[1]), 0.0f); - output[2] = mf * max(inputColor1[2] + value * (inputColor2[2] - inputColor1[2]), 0.0f); - output[3] = inputColor1[3]; + output[0] = mf * max(inputColor1[0] + value * (inputColor2[0] - inputColor1[0]), 0.0f); + output[1] = mf * max(inputColor1[1] + value * (inputColor2[1] - inputColor1[1]), 0.0f); + output[2] = mf * max(inputColor1[2] + value * (inputColor2[2] - inputColor1[2]), 0.0f); + output[3] = inputColor1[3]; - clampIfNeeded(output); + clampIfNeeded(output); } /* ******** Mix Hue Operation ******** */ MixHueOperation::MixHueOperation() : MixBaseOperation() { - /* pass */ + /* pass */ } void MixHueOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - - this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); - this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); - this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); - - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float valuem = 1.0f - value; - - float colH, colS, colV; - rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV); - if (colS != 0.0f) { - float rH, rS, rV; - float tmpr, tmpg, tmpb; - rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV); - hsv_to_rgb(colH, rS, rV, &tmpr, &tmpg, &tmpb); - output[0] = valuem * (inputColor1[0]) + value * tmpr; - output[1] = valuem * (inputColor1[1]) + value * tmpg; - output[2] = valuem * (inputColor1[2]) + value * tmpb; - } - else { - copy_v3_v3(output, inputColor1); - } - output[3] = inputColor1[3]; - - clampIfNeeded(output); + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + + this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); + this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); + this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); + + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float valuem = 1.0f - value; + + float colH, colS, colV; + rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV); + if (colS != 0.0f) { + float rH, rS, rV; + float tmpr, tmpg, tmpb; + rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV); + hsv_to_rgb(colH, rS, rV, &tmpr, &tmpg, &tmpb); + output[0] = valuem * (inputColor1[0]) + value * tmpr; + output[1] = valuem * (inputColor1[1]) + value * tmpg; + output[2] = valuem * (inputColor1[2]) + value * tmpb; + } + else { + copy_v3_v3(output, inputColor1); + } + output[3] = inputColor1[3]; + + clampIfNeeded(output); } /* ******** Mix Lighten Operation ******** */ MixLightenOperation::MixLightenOperation() : MixBaseOperation() { - /* pass */ -} - -void MixLightenOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - - this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); - this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); - this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); - - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float tmp; - tmp = value * inputColor2[0]; - if (tmp > inputColor1[0]) output[0] = tmp; - else output[0] = inputColor1[0]; - tmp = value * inputColor2[1]; - if (tmp > inputColor1[1]) output[1] = tmp; - else output[1] = inputColor1[1]; - tmp = value * inputColor2[2]; - if (tmp > inputColor1[2]) output[2] = tmp; - else output[2] = inputColor1[2]; - output[3] = inputColor1[3]; - - clampIfNeeded(output); + /* pass */ +} + +void MixLightenOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) +{ + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + + this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); + this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); + this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); + + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float tmp; + tmp = value * inputColor2[0]; + if (tmp > inputColor1[0]) + output[0] = tmp; + else + output[0] = inputColor1[0]; + tmp = value * inputColor2[1]; + if (tmp > inputColor1[1]) + output[1] = tmp; + else + output[1] = inputColor1[1]; + tmp = value * inputColor2[2]; + if (tmp > inputColor1[2]) + output[2] = tmp; + else + output[2] = inputColor1[2]; + output[3] = inputColor1[3]; + + clampIfNeeded(output); } /* ******** Mix Linear Light Operation ******** */ MixLinearLightOperation::MixLinearLightOperation() : MixBaseOperation() { - /* pass */ + /* pass */ } -void MixLinearLightOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MixLinearLightOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; - this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); - this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); - this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); + this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); + this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); + this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - if (inputColor2[0] > 0.5f) - output[0] = inputColor1[0] + value * (2.0f * (inputColor2[0] - 0.5f)); - else - output[0] = inputColor1[0] + value * (2.0f * (inputColor2[0]) - 1.0f); - if (inputColor2[1] > 0.5f) - output[1] = inputColor1[1] + value * (2.0f * (inputColor2[1] - 0.5f)); - else - output[1] = inputColor1[1] + value * (2.0f * (inputColor2[1]) - 1.0f); - if (inputColor2[2] > 0.5f) - output[2] = inputColor1[2] + value * (2.0f * (inputColor2[2] - 0.5f)); - else - output[2] = inputColor1[2] + value * (2.0f * (inputColor2[2]) - 1.0f); + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + if (inputColor2[0] > 0.5f) + output[0] = inputColor1[0] + value * (2.0f * (inputColor2[0] - 0.5f)); + else + output[0] = inputColor1[0] + value * (2.0f * (inputColor2[0]) - 1.0f); + if (inputColor2[1] > 0.5f) + output[1] = inputColor1[1] + value * (2.0f * (inputColor2[1] - 0.5f)); + else + output[1] = inputColor1[1] + value * (2.0f * (inputColor2[1]) - 1.0f); + if (inputColor2[2] > 0.5f) + output[2] = inputColor1[2] + value * (2.0f * (inputColor2[2] - 0.5f)); + else + output[2] = inputColor1[2] + value * (2.0f * (inputColor2[2]) - 1.0f); - output[3] = inputColor1[3]; + output[3] = inputColor1[3]; - clampIfNeeded(output); + clampIfNeeded(output); } /* ******** Mix Multiply Operation ******** */ MixMultiplyOperation::MixMultiplyOperation() : MixBaseOperation() { - /* pass */ + /* pass */ } -void MixMultiplyOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MixMultiplyOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; - this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); - this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); - this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); + this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); + this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); + this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float valuem = 1.0f - value; - output[0] = inputColor1[0] * (valuem + value * inputColor2[0]); - output[1] = inputColor1[1] * (valuem + value * inputColor2[1]); - output[2] = inputColor1[2] * (valuem + value * inputColor2[2]); - output[3] = inputColor1[3]; + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float valuem = 1.0f - value; + output[0] = inputColor1[0] * (valuem + value * inputColor2[0]); + output[1] = inputColor1[1] * (valuem + value * inputColor2[1]); + output[2] = inputColor1[2] * (valuem + value * inputColor2[2]); + output[3] = inputColor1[3]; - clampIfNeeded(output); + clampIfNeeded(output); } /* ******** Mix Ovelray Operation ******** */ MixOverlayOperation::MixOverlayOperation() : MixBaseOperation() { - /* pass */ + /* pass */ } -void MixOverlayOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MixOverlayOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; - this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); - this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); - this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); + this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); + this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); + this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } - float valuem = 1.0f - value; + float valuem = 1.0f - value; - if (inputColor1[0] < 0.5f) { - output[0] = inputColor1[0] * (valuem + 2.0f * value * inputColor2[0]); - } - else { - output[0] = 1.0f - (valuem + 2.0f * value * (1.0f - inputColor2[0])) * (1.0f - inputColor1[0]); - } - if (inputColor1[1] < 0.5f) { - output[1] = inputColor1[1] * (valuem + 2.0f * value * inputColor2[1]); - } - else { - output[1] = 1.0f - (valuem + 2.0f * value * (1.0f - inputColor2[1])) * (1.0f - inputColor1[1]); - } - if (inputColor1[2] < 0.5f) { - output[2] = inputColor1[2] * (valuem + 2.0f * value * inputColor2[2]); - } - else { - output[2] = 1.0f - (valuem + 2.0f * value * (1.0f - inputColor2[2])) * (1.0f - inputColor1[2]); - } - output[3] = inputColor1[3]; + if (inputColor1[0] < 0.5f) { + output[0] = inputColor1[0] * (valuem + 2.0f * value * inputColor2[0]); + } + else { + output[0] = 1.0f - (valuem + 2.0f * value * (1.0f - inputColor2[0])) * (1.0f - inputColor1[0]); + } + if (inputColor1[1] < 0.5f) { + output[1] = inputColor1[1] * (valuem + 2.0f * value * inputColor2[1]); + } + else { + output[1] = 1.0f - (valuem + 2.0f * value * (1.0f - inputColor2[1])) * (1.0f - inputColor1[1]); + } + if (inputColor1[2] < 0.5f) { + output[2] = inputColor1[2] * (valuem + 2.0f * value * inputColor2[2]); + } + else { + output[2] = 1.0f - (valuem + 2.0f * value * (1.0f - inputColor2[2])) * (1.0f - inputColor1[2]); + } + output[3] = inputColor1[3]; - clampIfNeeded(output); + clampIfNeeded(output); } /* ******** Mix Saturation Operation ******** */ MixSaturationOperation::MixSaturationOperation() : MixBaseOperation() { - /* pass */ + /* pass */ } -void MixSaturationOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MixSaturationOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; - this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); - this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); - this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); + this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); + this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); + this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float valuem = 1.0f - value; + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float valuem = 1.0f - value; - float rH, rS, rV; - rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV); - if (rS != 0.0f) { - float colH, colS, colV; - rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV); - hsv_to_rgb(rH, (valuem * rS + value * colS), rV, &output[0], &output[1], &output[2]); - } - else { - copy_v3_v3(output, inputColor1); - } + float rH, rS, rV; + rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV); + if (rS != 0.0f) { + float colH, colS, colV; + rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV); + hsv_to_rgb(rH, (valuem * rS + value * colS), rV, &output[0], &output[1], &output[2]); + } + else { + copy_v3_v3(output, inputColor1); + } - output[3] = inputColor1[3]; + output[3] = inputColor1[3]; - clampIfNeeded(output); + clampIfNeeded(output); } /* ******** Mix Screen Operation ******** */ MixScreenOperation::MixScreenOperation() : MixBaseOperation() { - /* pass */ + /* pass */ } -void MixScreenOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MixScreenOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; - this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); - this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); - this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); + this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); + this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); + this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float valuem = 1.0f - value; + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float valuem = 1.0f - value; - output[0] = 1.0f - (valuem + value * (1.0f - inputColor2[0])) * (1.0f - inputColor1[0]); - output[1] = 1.0f - (valuem + value * (1.0f - inputColor2[1])) * (1.0f - inputColor1[1]); - output[2] = 1.0f - (valuem + value * (1.0f - inputColor2[2])) * (1.0f - inputColor1[2]); - output[3] = inputColor1[3]; + output[0] = 1.0f - (valuem + value * (1.0f - inputColor2[0])) * (1.0f - inputColor1[0]); + output[1] = 1.0f - (valuem + value * (1.0f - inputColor2[1])) * (1.0f - inputColor1[1]); + output[2] = 1.0f - (valuem + value * (1.0f - inputColor2[2])) * (1.0f - inputColor1[2]); + output[3] = inputColor1[3]; - clampIfNeeded(output); + clampIfNeeded(output); } /* ******** Mix Soft Light Operation ******** */ MixSoftLightOperation::MixSoftLightOperation() : MixBaseOperation() { - /* pass */ + /* pass */ } -void MixSoftLightOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) \ +void MixSoftLightOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; - this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); - this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); - this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); + this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); + this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); + this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float valuem = 1.0f - value; - float scr, scg, scb; + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float valuem = 1.0f - value; + float scr, scg, scb; - /* first calculate non-fac based Screen mix */ - scr = 1.0f - (1.0f - inputColor2[0]) * (1.0f - inputColor1[0]); - scg = 1.0f - (1.0f - inputColor2[1]) * (1.0f - inputColor1[1]); - scb = 1.0f - (1.0f - inputColor2[2]) * (1.0f - inputColor1[2]); + /* first calculate non-fac based Screen mix */ + scr = 1.0f - (1.0f - inputColor2[0]) * (1.0f - inputColor1[0]); + scg = 1.0f - (1.0f - inputColor2[1]) * (1.0f - inputColor1[1]); + scb = 1.0f - (1.0f - inputColor2[2]) * (1.0f - inputColor1[2]); - output[0] = valuem * (inputColor1[0]) + value * (((1.0f - inputColor1[0]) * inputColor2[0] * (inputColor1[0])) + (inputColor1[0] * scr)); - output[1] = valuem * (inputColor1[1]) + value * (((1.0f - inputColor1[1]) * inputColor2[1] * (inputColor1[1])) + (inputColor1[1] * scg)); - output[2] = valuem * (inputColor1[2]) + value * (((1.0f - inputColor1[2]) * inputColor2[2] * (inputColor1[2])) + (inputColor1[2] * scb)); - output[3] = inputColor1[3]; + output[0] = valuem * (inputColor1[0]) + + value * (((1.0f - inputColor1[0]) * inputColor2[0] * (inputColor1[0])) + + (inputColor1[0] * scr)); + output[1] = valuem * (inputColor1[1]) + + value * (((1.0f - inputColor1[1]) * inputColor2[1] * (inputColor1[1])) + + (inputColor1[1] * scg)); + output[2] = valuem * (inputColor1[2]) + + value * (((1.0f - inputColor1[2]) * inputColor2[2] * (inputColor1[2])) + + (inputColor1[2] * scb)); + output[3] = inputColor1[3]; - clampIfNeeded(output); + clampIfNeeded(output); } /* ******** Mix Subtract Operation ******** */ MixSubtractOperation::MixSubtractOperation() : MixBaseOperation() { - /* pass */ + /* pass */ } -void MixSubtractOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MixSubtractOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; - this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); - this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); - this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); + this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); + this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); + this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - output[0] = inputColor1[0] - value * (inputColor2[0]); - output[1] = inputColor1[1] - value * (inputColor2[1]); - output[2] = inputColor1[2] - value * (inputColor2[2]); - output[3] = inputColor1[3]; + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + output[0] = inputColor1[0] - value * (inputColor2[0]); + output[1] = inputColor1[1] - value * (inputColor2[1]); + output[2] = inputColor1[2] - value * (inputColor2[2]); + output[3] = inputColor1[3]; - clampIfNeeded(output); + clampIfNeeded(output); } /* ******** Mix Value Operation ******** */ MixValueOperation::MixValueOperation() : MixBaseOperation() { - /* pass */ + /* pass */ } -void MixValueOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MixValueOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; - this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); - this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); - this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); + this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); + this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); + this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float valuem = 1.0f - value; + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float valuem = 1.0f - value; - float rH, rS, rV; - float colH, colS, colV; - rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV); - rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV); - hsv_to_rgb(rH, rS, (valuem * rV + value * colV), &output[0], &output[1], &output[2]); - output[3] = inputColor1[3]; + float rH, rS, rV; + float colH, colS, colV; + rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV); + rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV); + hsv_to_rgb(rH, rS, (valuem * rV + value * colV), &output[0], &output[1], &output[2]); + output[3] = inputColor1[3]; - clampIfNeeded(output); + clampIfNeeded(output); } diff --git a/source/blender/compositor/operations/COM_MixOperation.h b/source/blender/compositor/operations/COM_MixOperation.h index c724a54c9a4..6ea55a3edfd 100644 --- a/source/blender/compositor/operations/COM_MixOperation.h +++ b/source/blender/compositor/operations/COM_MixOperation.h @@ -20,174 +20,181 @@ #define __COM_MIXOPERATION_H__ #include "COM_NodeOperation.h" - /** * All this programs converts an input color to an output value. * it assumes we are in sRGB color space. */ class MixBaseOperation : public NodeOperation { -protected: - /** - * Prefetched reference to the inputProgram - */ - SocketReader *m_inputValueOperation; - SocketReader *m_inputColor1Operation; - SocketReader *m_inputColor2Operation; - bool m_valueAlphaMultiply; - bool m_useClamp; - - inline void clampIfNeeded(float color[4]) - { - if (m_useClamp) { - CLAMP(color[0], 0.0f, 1.0f); - CLAMP(color[1], 0.0f, 1.0f); - CLAMP(color[2], 0.0f, 1.0f); - CLAMP(color[3], 0.0f, 1.0f); - } - } - -public: - /** - * Default constructor - */ - MixBaseOperation(); - - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - - /** - * Initialize the execution - */ - void initExecution(); - - /** - * Deinitialize the execution - */ - void deinitExecution(); - - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); - - - void setUseValueAlphaMultiply(const bool value) { this->m_valueAlphaMultiply = value; } - inline bool useValueAlphaMultiply() { return this->m_valueAlphaMultiply; } - void setUseClamp(bool value) { this->m_useClamp = value; } + protected: + /** + * Prefetched reference to the inputProgram + */ + SocketReader *m_inputValueOperation; + SocketReader *m_inputColor1Operation; + SocketReader *m_inputColor2Operation; + bool m_valueAlphaMultiply; + bool m_useClamp; + + inline void clampIfNeeded(float color[4]) + { + if (m_useClamp) { + CLAMP(color[0], 0.0f, 1.0f); + CLAMP(color[1], 0.0f, 1.0f); + CLAMP(color[2], 0.0f, 1.0f); + CLAMP(color[3], 0.0f, 1.0f); + } + } + + public: + /** + * Default constructor + */ + MixBaseOperation(); + + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + + /** + * Initialize the execution + */ + void initExecution(); + + /** + * Deinitialize the execution + */ + void deinitExecution(); + + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); + + void setUseValueAlphaMultiply(const bool value) + { + this->m_valueAlphaMultiply = value; + } + inline bool useValueAlphaMultiply() + { + return this->m_valueAlphaMultiply; + } + void setUseClamp(bool value) + { + this->m_useClamp = value; + } }; class MixAddOperation : public MixBaseOperation { -public: - MixAddOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MixAddOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MixBlendOperation : public MixBaseOperation { -public: - MixBlendOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MixBlendOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MixBurnOperation : public MixBaseOperation { -public: - MixBurnOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MixBurnOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MixColorOperation : public MixBaseOperation { -public: - MixColorOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MixColorOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MixDarkenOperation : public MixBaseOperation { -public: - MixDarkenOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MixDarkenOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MixDifferenceOperation : public MixBaseOperation { -public: - MixDifferenceOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MixDifferenceOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MixDivideOperation : public MixBaseOperation { -public: - MixDivideOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MixDivideOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MixDodgeOperation : public MixBaseOperation { -public: - MixDodgeOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MixDodgeOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MixGlareOperation : public MixBaseOperation { -public: - MixGlareOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MixGlareOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MixHueOperation : public MixBaseOperation { -public: - MixHueOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MixHueOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MixLightenOperation : public MixBaseOperation { -public: - MixLightenOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MixLightenOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MixLinearLightOperation : public MixBaseOperation { -public: - MixLinearLightOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MixLinearLightOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MixMultiplyOperation : public MixBaseOperation { -public: - MixMultiplyOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MixMultiplyOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MixOverlayOperation : public MixBaseOperation { -public: - MixOverlayOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MixOverlayOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MixSaturationOperation : public MixBaseOperation { -public: - MixSaturationOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MixSaturationOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MixScreenOperation : public MixBaseOperation { -public: - MixScreenOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MixScreenOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MixSoftLightOperation : public MixBaseOperation { -public: - MixSoftLightOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MixSoftLightOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MixSubtractOperation : public MixBaseOperation { -public: - MixSubtractOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MixSubtractOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MixValueOperation : public MixBaseOperation { -public: - MixValueOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MixValueOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; #endif diff --git a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp index db91a8beb1a..967fa7ad653 100644 --- a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp +++ b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp @@ -18,68 +18,65 @@ #include "COM_MovieClipAttributeOperation.h" extern "C" { -# include "BKE_tracking.h" -# include "BKE_movieclip.h" +#include "BKE_tracking.h" +#include "BKE_movieclip.h" } MovieClipAttributeOperation::MovieClipAttributeOperation() : NodeOperation() { - this->addOutputSocket(COM_DT_VALUE); - this->m_framenumber = 0; - this->m_attribute = MCA_X; - this->m_invert = false; + this->addOutputSocket(COM_DT_VALUE); + this->m_framenumber = 0; + this->m_attribute = MCA_X; + this->m_invert = false; } void MovieClipAttributeOperation::initExecution() { - if (this->m_clip == NULL) { - return; - } - float loc[2], scale, angle; - loc[0] = 0.0f; - loc[1] = 0.0f; - scale = 1.0f; - angle = 0.0f; - int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame( - this->m_clip, this->m_framenumber); - BKE_tracking_stabilization_data_get(this->m_clip, - clip_framenr, - getWidth(), getHeight(), - loc, &scale, &angle); - switch (this->m_attribute) { - case MCA_SCALE: - this->m_value = scale; - break; - case MCA_ANGLE: - this->m_value = angle; - break; - case MCA_X: - this->m_value = loc[0]; - break; - case MCA_Y: - this->m_value = loc[1]; - break; - } - if (this->m_invert) { - if (this->m_attribute != MCA_SCALE) { - this->m_value = -this->m_value; - } - else { - this->m_value = 1.0f / this->m_value; - } - } + if (this->m_clip == NULL) { + return; + } + float loc[2], scale, angle; + loc[0] = 0.0f; + loc[1] = 0.0f; + scale = 1.0f; + angle = 0.0f; + int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(this->m_clip, this->m_framenumber); + BKE_tracking_stabilization_data_get( + this->m_clip, clip_framenr, getWidth(), getHeight(), loc, &scale, &angle); + switch (this->m_attribute) { + case MCA_SCALE: + this->m_value = scale; + break; + case MCA_ANGLE: + this->m_value = angle; + break; + case MCA_X: + this->m_value = loc[0]; + break; + case MCA_Y: + this->m_value = loc[1]; + break; + } + if (this->m_invert) { + if (this->m_attribute != MCA_SCALE) { + this->m_value = -this->m_value; + } + else { + this->m_value = 1.0f / this->m_value; + } + } } void MovieClipAttributeOperation::executePixelSampled(float output[4], - float /*x*/, float /*y*/, + float /*x*/, + float /*y*/, PixelSampler /*sampler*/) { - output[0] = this->m_value; + output[0] = this->m_value; } -void MovieClipAttributeOperation::determineResolution( - unsigned int resolution[2], - unsigned int preferredResolution[2]) +void MovieClipAttributeOperation::determineResolution(unsigned int resolution[2], + unsigned int preferredResolution[2]) { - resolution[0] = preferredResolution[0]; - resolution[1] = preferredResolution[1]; + resolution[0] = preferredResolution[0]; + resolution[1] = preferredResolution[1]; } diff --git a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.h b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.h index a73167352d3..8a95293b470 100644 --- a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.h +++ b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.h @@ -22,40 +22,52 @@ #include "DNA_movieclip_types.h" typedef enum MovieClipAttribute { - MCA_SCALE, - MCA_X, - MCA_Y, - MCA_ANGLE, + MCA_SCALE, + MCA_X, + MCA_Y, + MCA_ANGLE, } MovieClipAttribute; /** * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ class MovieClipAttributeOperation : public NodeOperation { -private: - MovieClip *m_clip; - float m_value; - int m_framenumber; - bool m_invert; - MovieClipAttribute m_attribute; + private: + MovieClip *m_clip; + float m_value; + int m_framenumber; + bool m_invert; + MovieClipAttribute m_attribute; -public: - /** - * Default constructor - */ - MovieClipAttributeOperation(); + public: + /** + * Default constructor + */ + MovieClipAttributeOperation(); - void initExecution(); + void initExecution(); - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); - void setMovieClip(MovieClip *clip) { this->m_clip = clip; } - void setFramenumber(int framenumber) { this->m_framenumber = framenumber; } - void setAttribute(MovieClipAttribute attribute) { this->m_attribute = attribute; } - void setInvert(bool invert) { this->m_invert = invert; } + void setMovieClip(MovieClip *clip) + { + this->m_clip = clip; + } + void setFramenumber(int framenumber) + { + this->m_framenumber = framenumber; + } + void setAttribute(MovieClipAttribute attribute) + { + this->m_attribute = attribute; + } + void setInvert(bool invert) + { + this->m_invert = invert; + } }; #endif diff --git a/source/blender/compositor/operations/COM_MovieClipOperation.cpp b/source/blender/compositor/operations/COM_MovieClipOperation.cpp index 1f4b947daa5..ce7973fdc99 100644 --- a/source/blender/compositor/operations/COM_MovieClipOperation.cpp +++ b/source/blender/compositor/operations/COM_MovieClipOperation.cpp @@ -21,106 +21,113 @@ #include "BLI_listbase.h" #include "BLI_math.h" extern "C" { -# include "BKE_movieclip.h" -# include "IMB_imbuf.h" +#include "BKE_movieclip.h" +#include "IMB_imbuf.h" } #include "BKE_image.h" MovieClipBaseOperation::MovieClipBaseOperation() : NodeOperation() { - this->m_movieClip = NULL; - this->m_movieClipBuffer = NULL; - this->m_movieClipUser = NULL; - this->m_movieClipwidth = 0; - this->m_movieClipheight = 0; - this->m_framenumber = 0; + this->m_movieClip = NULL; + this->m_movieClipBuffer = NULL; + this->m_movieClipUser = NULL; + this->m_movieClipwidth = 0; + this->m_movieClipheight = 0; + this->m_framenumber = 0; } - void MovieClipBaseOperation::initExecution() { - if (this->m_movieClip) { - BKE_movieclip_user_set_frame(this->m_movieClipUser, this->m_framenumber); - ImBuf *ibuf; - - if (this->m_cacheFrame) - ibuf = BKE_movieclip_get_ibuf(this->m_movieClip, this->m_movieClipUser); - else - ibuf = BKE_movieclip_get_ibuf_flag(this->m_movieClip, this->m_movieClipUser, this->m_movieClip->flag, MOVIECLIP_CACHE_SKIP); - - if (ibuf) { - this->m_movieClipBuffer = ibuf; - if (ibuf->rect_float == NULL || ibuf->userflags & IB_RECT_INVALID) { - IMB_float_from_rect(ibuf); - ibuf->userflags &= ~IB_RECT_INVALID; - } - } - } + if (this->m_movieClip) { + BKE_movieclip_user_set_frame(this->m_movieClipUser, this->m_framenumber); + ImBuf *ibuf; + + if (this->m_cacheFrame) + ibuf = BKE_movieclip_get_ibuf(this->m_movieClip, this->m_movieClipUser); + else + ibuf = BKE_movieclip_get_ibuf_flag( + this->m_movieClip, this->m_movieClipUser, this->m_movieClip->flag, MOVIECLIP_CACHE_SKIP); + + if (ibuf) { + this->m_movieClipBuffer = ibuf; + if (ibuf->rect_float == NULL || ibuf->userflags & IB_RECT_INVALID) { + IMB_float_from_rect(ibuf); + ibuf->userflags &= ~IB_RECT_INVALID; + } + } + } } void MovieClipBaseOperation::deinitExecution() { - if (this->m_movieClipBuffer) { - IMB_freeImBuf(this->m_movieClipBuffer); + if (this->m_movieClipBuffer) { + IMB_freeImBuf(this->m_movieClipBuffer); - this->m_movieClipBuffer = NULL; - } + this->m_movieClipBuffer = NULL; + } } -void MovieClipBaseOperation::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2]) +void MovieClipBaseOperation::determineResolution(unsigned int resolution[2], + unsigned int /*preferredResolution*/[2]) { - resolution[0] = 0; - resolution[1] = 0; + resolution[0] = 0; + resolution[1] = 0; - if (this->m_movieClip) { - int width, height; + if (this->m_movieClip) { + int width, height; - BKE_movieclip_get_size(this->m_movieClip, this->m_movieClipUser, &width, &height); + BKE_movieclip_get_size(this->m_movieClip, this->m_movieClipUser, &width, &height); - resolution[0] = width; - resolution[1] = height; - } + resolution[0] = width; + resolution[1] = height; + } } -void MovieClipBaseOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MovieClipBaseOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - ImBuf *ibuf = this->m_movieClipBuffer; - - if (ibuf == NULL) { - zero_v4(output); - } - else if (ibuf->rect == NULL && ibuf->rect_float == NULL) { - /* Happens for multilayer exr, i.e. */ - zero_v4(output); - } - else { - switch (sampler) { - case COM_PS_NEAREST: - nearest_interpolation_color(ibuf, NULL, output, x, y); - break; - case COM_PS_BILINEAR: - bilinear_interpolation_color(ibuf, NULL, output, x, y); - break; - case COM_PS_BICUBIC: - bicubic_interpolation_color(ibuf, NULL, output, x, y); - break; - } - } + ImBuf *ibuf = this->m_movieClipBuffer; + + if (ibuf == NULL) { + zero_v4(output); + } + else if (ibuf->rect == NULL && ibuf->rect_float == NULL) { + /* Happens for multilayer exr, i.e. */ + zero_v4(output); + } + else { + switch (sampler) { + case COM_PS_NEAREST: + nearest_interpolation_color(ibuf, NULL, output, x, y); + break; + case COM_PS_BILINEAR: + bilinear_interpolation_color(ibuf, NULL, output, x, y); + break; + case COM_PS_BICUBIC: + bicubic_interpolation_color(ibuf, NULL, output, x, y); + break; + } + } } MovieClipOperation::MovieClipOperation() : MovieClipBaseOperation() { - this->addOutputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); } MovieClipAlphaOperation::MovieClipAlphaOperation() : MovieClipBaseOperation() { - this->addOutputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_VALUE); } -void MovieClipAlphaOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MovieClipAlphaOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float result[4]; - MovieClipBaseOperation::executePixelSampled(result, x, y, sampler); - output[0] = result[3]; + float result[4]; + MovieClipBaseOperation::executePixelSampled(result, x, y, sampler); + output[0] = result[3]; } diff --git a/source/blender/compositor/operations/COM_MovieClipOperation.h b/source/blender/compositor/operations/COM_MovieClipOperation.h index caadb1e0a40..8d2dd99afc0 100644 --- a/source/blender/compositor/operations/COM_MovieClipOperation.h +++ b/source/blender/compositor/operations/COM_MovieClipOperation.h @@ -16,7 +16,6 @@ * Copyright 2011, Blender Foundation. */ - #ifndef __COM_MOVIECLIPOPERATION_H__ #define __COM_MOVIECLIPOPERATION_H__ @@ -29,42 +28,54 @@ * Base class for movie clip */ class MovieClipBaseOperation : public NodeOperation { -protected: - MovieClip *m_movieClip; - MovieClipUser *m_movieClipUser; - ImBuf *m_movieClipBuffer; - int m_movieClipheight; - int m_movieClipwidth; - int m_framenumber; - bool m_cacheFrame; + protected: + MovieClip *m_movieClip; + MovieClipUser *m_movieClipUser; + ImBuf *m_movieClipBuffer; + int m_movieClipheight; + int m_movieClipwidth; + int m_framenumber; + bool m_cacheFrame; - /** - * Determine the output resolution. The resolution is retrieved from the Renderer - */ - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); + /** + * Determine the output resolution. The resolution is retrieved from the Renderer + */ + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); -public: - MovieClipBaseOperation(); + public: + MovieClipBaseOperation(); - void initExecution(); - void deinitExecution(); - void setMovieClip(MovieClip *image) { this->m_movieClip = image; } - void setMovieClipUser(MovieClipUser *imageuser) { this->m_movieClipUser = imageuser; } - void setCacheFrame(bool value) { this->m_cacheFrame = value; } + void initExecution(); + void deinitExecution(); + void setMovieClip(MovieClip *image) + { + this->m_movieClip = image; + } + void setMovieClipUser(MovieClipUser *imageuser) + { + this->m_movieClipUser = imageuser; + } + void setCacheFrame(bool value) + { + this->m_cacheFrame = value; + } - void setFramenumber(int framenumber) { this->m_framenumber = framenumber; } - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void setFramenumber(int framenumber) + { + this->m_framenumber = framenumber; + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MovieClipOperation : public MovieClipBaseOperation { -public: - MovieClipOperation(); + public: + MovieClipOperation(); }; class MovieClipAlphaOperation : public MovieClipBaseOperation { -public: - MovieClipAlphaOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MovieClipAlphaOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; #endif diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp index e8dc6f41110..be354ba5a12 100644 --- a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp @@ -19,72 +19,64 @@ #include "COM_MovieDistortionOperation.h" extern "C" { -# include "BKE_tracking.h" -# include "BKE_movieclip.h" -# include "BLI_linklist.h" +#include "BKE_tracking.h" +#include "BKE_movieclip.h" +#include "BLI_linklist.h" } - MovieDistortionOperation::MovieDistortionOperation(bool distortion) : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - this->setResolutionInputSocketIndex(0); - this->m_inputOperation = NULL; - this->m_movieClip = NULL; - this->m_apply = distortion; + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); + this->setResolutionInputSocketIndex(0); + this->m_inputOperation = NULL; + this->m_movieClip = NULL; + this->m_apply = distortion; } void MovieDistortionOperation::initExecution() { - this->m_inputOperation = this->getInputSocketReader(0); - if (this->m_movieClip) { - MovieTracking *tracking = &this->m_movieClip->tracking; - MovieClipUser clipUser = {0}; - int calibration_width, calibration_height; - - BKE_movieclip_user_set_frame(&clipUser, this->m_framenumber); - BKE_movieclip_get_size(this->m_movieClip, - &clipUser, - &calibration_width, - &calibration_height); - - float delta[2]; - rcti full_frame; - full_frame.xmin = full_frame.ymin = 0; - full_frame.xmax = this->m_width; - full_frame.ymax = this->m_height; - BKE_tracking_max_distortion_delta_across_bound(tracking, - &full_frame, - !this->m_apply, - delta); - - /* 5 is just in case we didn't hit real max of distortion in - * BKE_tracking_max_undistortion_delta_across_bound - */ - m_margin[0] = delta[0] + 5; - m_margin[1] = delta[1] + 5; - - this->m_distortion = BKE_tracking_distortion_new(tracking, - calibration_width, - calibration_height); - this->m_calibration_width = calibration_width; - this->m_calibration_height = calibration_height; - this->m_pixel_aspect = tracking->camera.pixel_aspect; - } - else { - m_margin[0] = m_margin[1] = 0; - this->m_distortion = NULL; - } + this->m_inputOperation = this->getInputSocketReader(0); + if (this->m_movieClip) { + MovieTracking *tracking = &this->m_movieClip->tracking; + MovieClipUser clipUser = {0}; + int calibration_width, calibration_height; + + BKE_movieclip_user_set_frame(&clipUser, this->m_framenumber); + BKE_movieclip_get_size(this->m_movieClip, &clipUser, &calibration_width, &calibration_height); + + float delta[2]; + rcti full_frame; + full_frame.xmin = full_frame.ymin = 0; + full_frame.xmax = this->m_width; + full_frame.ymax = this->m_height; + BKE_tracking_max_distortion_delta_across_bound(tracking, &full_frame, !this->m_apply, delta); + + /* 5 is just in case we didn't hit real max of distortion in + * BKE_tracking_max_undistortion_delta_across_bound + */ + m_margin[0] = delta[0] + 5; + m_margin[1] = delta[1] + 5; + + this->m_distortion = BKE_tracking_distortion_new( + tracking, calibration_width, calibration_height); + this->m_calibration_width = calibration_width; + this->m_calibration_height = calibration_height; + this->m_pixel_aspect = tracking->camera.pixel_aspect; + } + else { + m_margin[0] = m_margin[1] = 0; + this->m_distortion = NULL; + } } void MovieDistortionOperation::deinitExecution() { - this->m_inputOperation = NULL; - this->m_movieClip = NULL; - if (this->m_distortion != NULL) { - BKE_tracking_distortion_free(this->m_distortion); - } + this->m_inputOperation = NULL; + this->m_movieClip = NULL; + if (this->m_distortion != NULL) { + BKE_tracking_distortion_free(this->m_distortion); + } } void MovieDistortionOperation::executePixelSampled(float output[4], @@ -92,47 +84,44 @@ void MovieDistortionOperation::executePixelSampled(float output[4], float y, PixelSampler /*sampler*/) { - if (this->m_distortion != NULL) { - /* float overscan = 0.0f; */ - const float pixel_aspect = this->m_pixel_aspect; - const float w = (float)this->m_width /* / (1 + overscan) */; - const float h = (float)this->m_height /* / (1 + overscan) */; - const float aspx = w / (float)this->m_calibration_width; - const float aspy = h / (float)this->m_calibration_height; - float in[2]; - float out[2]; - - in[0] = (x /* - 0.5 * overscan * w */) / aspx; - in[1] = (y /* - 0.5 * overscan * h */) / aspy / pixel_aspect; - - if (this->m_apply) { - BKE_tracking_distortion_undistort_v2(this->m_distortion, in, out); - } - else { - BKE_tracking_distortion_distort_v2(this->m_distortion, in, out); - } - - float u = out[0] * aspx /* + 0.5 * overscan * w */, - v = (out[1] * aspy /* + 0.5 * overscan * h */) * pixel_aspect; - - this->m_inputOperation->readSampled(output, u, v, COM_PS_BILINEAR); - } - else { - this->m_inputOperation->readSampled(output, x, y, COM_PS_BILINEAR); - } + if (this->m_distortion != NULL) { + /* float overscan = 0.0f; */ + const float pixel_aspect = this->m_pixel_aspect; + const float w = (float)this->m_width /* / (1 + overscan) */; + const float h = (float)this->m_height /* / (1 + overscan) */; + const float aspx = w / (float)this->m_calibration_width; + const float aspy = h / (float)this->m_calibration_height; + float in[2]; + float out[2]; + + in[0] = (x /* - 0.5 * overscan * w */) / aspx; + in[1] = (y /* - 0.5 * overscan * h */) / aspy / pixel_aspect; + + if (this->m_apply) { + BKE_tracking_distortion_undistort_v2(this->m_distortion, in, out); + } + else { + BKE_tracking_distortion_distort_v2(this->m_distortion, in, out); + } + + float u = out[0] * aspx /* + 0.5 * overscan * w */, + v = (out[1] * aspy /* + 0.5 * overscan * h */) * pixel_aspect; + + this->m_inputOperation->readSampled(output, u, v, COM_PS_BILINEAR); + } + else { + this->m_inputOperation->readSampled(output, x, y, COM_PS_BILINEAR); + } } -bool MovieDistortionOperation::determineDependingAreaOfInterest( - rcti *input, - ReadBufferOperation *readOperation, - rcti *output) +bool MovieDistortionOperation::determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output) { - rcti newInput; - newInput.xmin = input->xmin - m_margin[0]; - newInput.ymin = input->ymin - m_margin[1]; - newInput.xmax = input->xmax + m_margin[0]; - newInput.ymax = input->ymax + m_margin[1]; - return NodeOperation::determineDependingAreaOfInterest(&newInput, - readOperation, - output); + rcti newInput; + newInput.xmin = input->xmin - m_margin[0]; + newInput.ymin = input->ymin - m_margin[1]; + newInput.xmax = input->xmax + m_margin[0]; + newInput.ymax = input->ymax + m_margin[1]; + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.h b/source/blender/compositor/operations/COM_MovieDistortionOperation.h index 89c242bf505..3ca9fe16b1e 100644 --- a/source/blender/compositor/operations/COM_MovieDistortionOperation.h +++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.h @@ -24,38 +24,41 @@ #include "MEM_guardedalloc.h" extern "C" { -# include "BKE_tracking.h" +#include "BKE_tracking.h" } class MovieDistortionOperation : public NodeOperation { -private: - SocketReader *m_inputOperation; - MovieClip *m_movieClip; - int m_margin[2]; - -protected: - bool m_apply; - int m_framenumber; - - struct MovieDistortion *m_distortion; - int m_calibration_width, m_calibration_height; - float m_pixel_aspect; - -public: - MovieDistortionOperation(bool distortion); - void executePixelSampled(float output[4], - float x, float y, - PixelSampler sampler); - - void initExecution(); - void deinitExecution(); - - void setMovieClip(MovieClip *clip) { this->m_movieClip = clip; } - void setFramenumber(int framenumber) { this->m_framenumber = framenumber; } - bool determineDependingAreaOfInterest(rcti *input, - ReadBufferOperation *readOperation, - rcti *output); + private: + SocketReader *m_inputOperation; + MovieClip *m_movieClip; + int m_margin[2]; + protected: + bool m_apply; + int m_framenumber; + + struct MovieDistortion *m_distortion; + int m_calibration_width, m_calibration_height; + float m_pixel_aspect; + + public: + MovieDistortionOperation(bool distortion); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + + void initExecution(); + void deinitExecution(); + + void setMovieClip(MovieClip *clip) + { + this->m_movieClip = clip; + } + void setFramenumber(int framenumber) + { + this->m_framenumber = framenumber; + } + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); }; #endif diff --git a/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp b/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp index 34c6478d149..14542f1e65a 100644 --- a/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp +++ b/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp @@ -18,96 +18,108 @@ #include "COM_MultilayerImageOperation.h" extern "C" { -# include "IMB_imbuf.h" -# include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" } MultilayerBaseOperation::MultilayerBaseOperation(int passindex, int view) : BaseImageOperation() { - this->m_passId = passindex; - this->m_view = view; + this->m_passId = passindex; + this->m_view = view; } ImBuf *MultilayerBaseOperation::getImBuf() { - /* temporarily changes the view to get the right ImBuf */ - int view = this->m_imageUser->view; + /* temporarily changes the view to get the right ImBuf */ + int view = this->m_imageUser->view; - this->m_imageUser->view = this->m_view; - this->m_imageUser->pass = this->m_passId; + this->m_imageUser->view = this->m_view; + this->m_imageUser->pass = this->m_passId; - if (BKE_image_multilayer_index(this->m_image->rr, this->m_imageUser)) { - ImBuf *ibuf = BaseImageOperation::getImBuf(); - this->m_imageUser->view = view; - return ibuf; - } + if (BKE_image_multilayer_index(this->m_image->rr, this->m_imageUser)) { + ImBuf *ibuf = BaseImageOperation::getImBuf(); + this->m_imageUser->view = view; + return ibuf; + } - this->m_imageUser->view = view; - return NULL; + this->m_imageUser->view = view; + return NULL; } -void MultilayerColorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MultilayerColorOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - if (this->m_imageFloatBuffer == NULL) { - zero_v4(output); - } - else { - if (this->m_numberOfChannels == 4) { - switch (sampler) { - case COM_PS_NEAREST: - nearest_interpolation_color(this->m_buffer, NULL, output, x, y); - break; - case COM_PS_BILINEAR: - bilinear_interpolation_color(this->m_buffer, NULL, output, x, y); - break; - case COM_PS_BICUBIC: - bicubic_interpolation_color(this->m_buffer, NULL, output, x, y); - break; - } - } - else { - int yi = y; - int xi = x; - if (xi < 0 || yi < 0 || (unsigned int)xi >= this->getWidth() || (unsigned int)yi >= this->getHeight()) - zero_v4(output); - else { - int offset = (yi * this->getWidth() + xi) * 3; - copy_v3_v3(output, &this->m_imageFloatBuffer[offset]); - } - } - } + if (this->m_imageFloatBuffer == NULL) { + zero_v4(output); + } + else { + if (this->m_numberOfChannels == 4) { + switch (sampler) { + case COM_PS_NEAREST: + nearest_interpolation_color(this->m_buffer, NULL, output, x, y); + break; + case COM_PS_BILINEAR: + bilinear_interpolation_color(this->m_buffer, NULL, output, x, y); + break; + case COM_PS_BICUBIC: + bicubic_interpolation_color(this->m_buffer, NULL, output, x, y); + break; + } + } + else { + int yi = y; + int xi = x; + if (xi < 0 || yi < 0 || (unsigned int)xi >= this->getWidth() || + (unsigned int)yi >= this->getHeight()) + zero_v4(output); + else { + int offset = (yi * this->getWidth() + xi) * 3; + copy_v3_v3(output, &this->m_imageFloatBuffer[offset]); + } + } + } } -void MultilayerValueOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) +void MultilayerValueOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler /*sampler*/) { - if (this->m_imageFloatBuffer == NULL) { - output[0] = 0.0f; - } - else { - int yi = y; - int xi = x; - if (xi < 0 || yi < 0 || (unsigned int)xi >= this->getWidth() || (unsigned int)yi >= this->getHeight()) - output[0] = 0.0f; - else { - float result = this->m_imageFloatBuffer[yi * this->getWidth() + xi]; - output[0] = result; - } - } + if (this->m_imageFloatBuffer == NULL) { + output[0] = 0.0f; + } + else { + int yi = y; + int xi = x; + if (xi < 0 || yi < 0 || (unsigned int)xi >= this->getWidth() || + (unsigned int)yi >= this->getHeight()) + output[0] = 0.0f; + else { + float result = this->m_imageFloatBuffer[yi * this->getWidth() + xi]; + output[0] = result; + } + } } -void MultilayerVectorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) +void MultilayerVectorOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler /*sampler*/) { - if (this->m_imageFloatBuffer == NULL) { - output[0] = 0.0f; - } - else { - int yi = y; - int xi = x; - if (xi < 0 || yi < 0 || (unsigned int)xi >= this->getWidth() || (unsigned int)yi >= this->getHeight()) - output[0] = 0.0f; - else { - int offset = (yi * this->getWidth() + xi) * 3; - copy_v3_v3(output, &this->m_imageFloatBuffer[offset]); - } - } + if (this->m_imageFloatBuffer == NULL) { + output[0] = 0.0f; + } + else { + int yi = y; + int xi = x; + if (xi < 0 || yi < 0 || (unsigned int)xi >= this->getWidth() || + (unsigned int)yi >= this->getHeight()) + output[0] = 0.0f; + else { + int offset = (yi * this->getWidth() + xi) * 3; + copy_v3_v3(output, &this->m_imageFloatBuffer[offset]); + } + } } diff --git a/source/blender/compositor/operations/COM_MultilayerImageOperation.h b/source/blender/compositor/operations/COM_MultilayerImageOperation.h index 948301e2be4..10c475ced4d 100644 --- a/source/blender/compositor/operations/COM_MultilayerImageOperation.h +++ b/source/blender/compositor/operations/COM_MultilayerImageOperation.h @@ -16,49 +16,56 @@ * Copyright 2011, Blender Foundation. */ - #ifndef __COM_MULTILAYERIMAGEOPERATION_H__ #define __COM_MULTILAYERIMAGEOPERATION_H__ #include "COM_ImageOperation.h" class MultilayerBaseOperation : public BaseImageOperation { -private: - int m_passId; - int m_view; - RenderLayer *m_renderlayer; -protected: - ImBuf *getImBuf(); -public: - /** - * Constructor - */ - MultilayerBaseOperation(int passindex, int view); - void setRenderLayer(RenderLayer *renderlayer) { this->m_renderlayer = renderlayer; } + private: + int m_passId; + int m_view; + RenderLayer *m_renderlayer; + + protected: + ImBuf *getImBuf(); + + public: + /** + * Constructor + */ + MultilayerBaseOperation(int passindex, int view); + void setRenderLayer(RenderLayer *renderlayer) + { + this->m_renderlayer = renderlayer; + } }; class MultilayerColorOperation : public MultilayerBaseOperation { -public: - MultilayerColorOperation(int passindex, int view) : MultilayerBaseOperation(passindex, view) { - this->addOutputSocket(COM_DT_COLOR); - } - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MultilayerColorOperation(int passindex, int view) : MultilayerBaseOperation(passindex, view) + { + this->addOutputSocket(COM_DT_COLOR); + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MultilayerValueOperation : public MultilayerBaseOperation { -public: - MultilayerValueOperation(int passindex, int view) : MultilayerBaseOperation(passindex, view) { - this->addOutputSocket(COM_DT_VALUE); - } - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MultilayerValueOperation(int passindex, int view) : MultilayerBaseOperation(passindex, view) + { + this->addOutputSocket(COM_DT_VALUE); + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class MultilayerVectorOperation : public MultilayerBaseOperation { -public: - MultilayerVectorOperation(int passindex, int view) : MultilayerBaseOperation(passindex, view) { - this->addOutputSocket(COM_DT_VECTOR); - } - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + MultilayerVectorOperation(int passindex, int view) : MultilayerBaseOperation(passindex, view) + { + this->addOutputSocket(COM_DT_VECTOR); + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; #endif diff --git a/source/blender/compositor/operations/COM_NormalizeOperation.cpp b/source/blender/compositor/operations/COM_NormalizeOperation.cpp index b32bb42ca62..703ffbe3999 100644 --- a/source/blender/compositor/operations/COM_NormalizeOperation.cpp +++ b/source/blender/compositor/operations/COM_NormalizeOperation.cpp @@ -20,58 +20,61 @@ NormalizeOperation::NormalizeOperation() : NodeOperation() { - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_VALUE); - this->m_imageReader = NULL; - this->m_cachedInstance = NULL; - this->setComplex(true); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_VALUE); + this->m_imageReader = NULL; + this->m_cachedInstance = NULL; + this->setComplex(true); } void NormalizeOperation::initExecution() { - this->m_imageReader = this->getInputSocketReader(0); - NodeOperation::initMutex(); + this->m_imageReader = this->getInputSocketReader(0); + NodeOperation::initMutex(); } void NormalizeOperation::executePixel(float output[4], int x, int y, void *data) { - /* using generic two floats struct to store x: min y: mult */ - NodeTwoFloats *minmult = (NodeTwoFloats *)data; + /* using generic two floats struct to store x: min y: mult */ + NodeTwoFloats *minmult = (NodeTwoFloats *)data; - this->m_imageReader->read(output, x, y, NULL); + this->m_imageReader->read(output, x, y, NULL); - output[0] = (output[0] - minmult->x) * minmult->y; + output[0] = (output[0] - minmult->x) * minmult->y; - /* clamp infinities */ - if (output[0] > 1.0f) - output[0] = 1.0f; - else if (output[0] < 0.0f) - output[0] = 0.0f; + /* clamp infinities */ + if (output[0] > 1.0f) + output[0] = 1.0f; + else if (output[0] < 0.0f) + output[0] = 0.0f; } void NormalizeOperation::deinitExecution() { - this->m_imageReader = NULL; - if (this->m_cachedInstance) { - delete this->m_cachedInstance; - } - NodeOperation::deinitMutex(); + this->m_imageReader = NULL; + if (this->m_cachedInstance) { + delete this->m_cachedInstance; + } + NodeOperation::deinitMutex(); } -bool NormalizeOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output) +bool NormalizeOperation::determineDependingAreaOfInterest(rcti * /*input*/, + ReadBufferOperation *readOperation, + rcti *output) { - rcti imageInput; - if (this->m_cachedInstance) return false; - - NodeOperation *operation = getInputOperation(0); - imageInput.xmax = operation->getWidth(); - imageInput.xmin = 0; - imageInput.ymax = operation->getHeight(); - imageInput.ymin = 0; - - if (operation->determineDependingAreaOfInterest(&imageInput, readOperation, output) ) { - return true; - } - return false; + rcti imageInput; + if (this->m_cachedInstance) + return false; + + NodeOperation *operation = getInputOperation(0); + imageInput.xmax = operation->getWidth(); + imageInput.xmin = 0; + imageInput.ymax = operation->getHeight(); + imageInput.ymin = 0; + + if (operation->determineDependingAreaOfInterest(&imageInput, readOperation, output)) { + return true; + } + return false; } /* The code below assumes all data is inside range +- this, and that input buffer is single channel */ @@ -79,43 +82,43 @@ bool NormalizeOperation::determineDependingAreaOfInterest(rcti * /*input*/, Read void *NormalizeOperation::initializeTileData(rcti *rect) { - lockMutex(); - if (this->m_cachedInstance == NULL) { - MemoryBuffer *tile = (MemoryBuffer *)this->m_imageReader->initializeTileData(rect); - /* using generic two floats struct to store x: min y: mult */ - NodeTwoFloats *minmult = new NodeTwoFloats(); - - float *buffer = tile->getBuffer(); - int p = tile->getWidth() * tile->getHeight(); - float *bc = buffer; - - float minv = 1.0f + BLENDER_ZMAX; - float maxv = -1.0f - BLENDER_ZMAX; - - float value; - while (p--) { - value = bc[0]; - if ((value > maxv) && (value <= BLENDER_ZMAX)) { - maxv = value; - } - if ((value < minv) && (value >= -BLENDER_ZMAX)) { - minv = value; - } - bc ++; - } - - minmult->x = minv; - /* The rare case of flat buffer would cause a divide by 0 */ - minmult->y = ((maxv != minv) ? 1.0f / (maxv - minv) : 0.0f); - - this->m_cachedInstance = minmult; - } - - unlockMutex(); - return this->m_cachedInstance; + lockMutex(); + if (this->m_cachedInstance == NULL) { + MemoryBuffer *tile = (MemoryBuffer *)this->m_imageReader->initializeTileData(rect); + /* using generic two floats struct to store x: min y: mult */ + NodeTwoFloats *minmult = new NodeTwoFloats(); + + float *buffer = tile->getBuffer(); + int p = tile->getWidth() * tile->getHeight(); + float *bc = buffer; + + float minv = 1.0f + BLENDER_ZMAX; + float maxv = -1.0f - BLENDER_ZMAX; + + float value; + while (p--) { + value = bc[0]; + if ((value > maxv) && (value <= BLENDER_ZMAX)) { + maxv = value; + } + if ((value < minv) && (value >= -BLENDER_ZMAX)) { + minv = value; + } + bc++; + } + + minmult->x = minv; + /* The rare case of flat buffer would cause a divide by 0 */ + minmult->y = ((maxv != minv) ? 1.0f / (maxv - minv) : 0.0f); + + this->m_cachedInstance = minmult; + } + + unlockMutex(); + return this->m_cachedInstance; } void NormalizeOperation::deinitializeTileData(rcti * /*rect*/, void * /*data*/) { - /* pass */ + /* pass */ } diff --git a/source/blender/compositor/operations/COM_NormalizeOperation.h b/source/blender/compositor/operations/COM_NormalizeOperation.h index e7803fe3dee..a38e79bb0ab 100644 --- a/source/blender/compositor/operations/COM_NormalizeOperation.h +++ b/source/blender/compositor/operations/COM_NormalizeOperation.h @@ -26,41 +26,42 @@ * \ingroup operation */ class NormalizeOperation : public NodeOperation { -protected: - /** - * \brief Cached reference to the reader - */ - SocketReader *m_imageReader; + protected: + /** + * \brief Cached reference to the reader + */ + SocketReader *m_imageReader; - /** - * \brief temporarily cache of the execution storage - * it stores x->min and y->mult - */ - NodeTwoFloats *m_cachedInstance; + /** + * \brief temporarily cache of the execution storage + * it stores x->min and y->mult + */ + NodeTwoFloats *m_cachedInstance; -public: - NormalizeOperation(); + public: + NormalizeOperation(); - /** - * the inner loop of this program - */ - void executePixel(float output[4], int x, int y, void *data); + /** + * the inner loop of this program + */ + void executePixel(float output[4], int x, int y, void *data); - /** - * Initialize the execution - */ - void initExecution(); + /** + * Initialize the execution + */ + void initExecution(); - void *initializeTileData(rcti *rect); - void deinitializeTileData(rcti *rect, void *data); + void *initializeTileData(rcti *rect); + void deinitializeTileData(rcti *rect, void *data); - /** - * Deinitialize the execution - */ - void deinitExecution(); - - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + /** + * Deinitialize the execution + */ + void deinitExecution(); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); }; #endif diff --git a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp index 1a2d5a052cd..62ba896f38e 100644 --- a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp +++ b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp @@ -42,274 +42,327 @@ extern "C" { /************************************ OpenEXR Singlelayer Multiview *****************************************/ OutputOpenExrSingleLayerMultiViewOperation::OutputOpenExrSingleLayerMultiViewOperation( - const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path, - const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings, - const char *viewName) - : OutputSingleLayerOperation(rd, tree, datatype, format, path, viewSettings, displaySettings, viewName) + const RenderData *rd, + const bNodeTree *tree, + DataType datatype, + ImageFormatData *format, + const char *path, + const ColorManagedViewSettings *viewSettings, + const ColorManagedDisplaySettings *displaySettings, + const char *viewName) + : OutputSingleLayerOperation( + rd, tree, datatype, format, path, viewSettings, displaySettings, viewName) { } void *OutputOpenExrSingleLayerMultiViewOperation::get_handle(const char *filename) { - size_t width = this->getWidth(); - size_t height = this->getHeight(); - SceneRenderView *srv; + size_t width = this->getWidth(); + size_t height = this->getHeight(); + SceneRenderView *srv; - if (width != 0 && height != 0) { - void *exrhandle; + if (width != 0 && height != 0) { + void *exrhandle; - exrhandle = IMB_exr_get_handle_name(filename); + exrhandle = IMB_exr_get_handle_name(filename); - if (!BKE_scene_multiview_is_render_view_first(this->m_rd, this->m_viewName)) - return exrhandle; + if (!BKE_scene_multiview_is_render_view_first(this->m_rd, this->m_viewName)) + return exrhandle; - IMB_exr_clear_channels(exrhandle); + IMB_exr_clear_channels(exrhandle); - for (srv = (SceneRenderView *)this->m_rd->views.first; srv; srv = srv->next) { - if (BKE_scene_multiview_is_render_view_active(this->m_rd, srv) == false) - continue; + for (srv = (SceneRenderView *)this->m_rd->views.first; srv; srv = srv->next) { + if (BKE_scene_multiview_is_render_view_active(this->m_rd, srv) == false) + continue; - IMB_exr_add_view(exrhandle, srv->name); - add_exr_channels(exrhandle, NULL, this->m_datatype, srv->name, width, false, NULL); - } + IMB_exr_add_view(exrhandle, srv->name); + add_exr_channels(exrhandle, NULL, this->m_datatype, srv->name, width, false, NULL); + } - BLI_make_existing_file(filename); + BLI_make_existing_file(filename); - /* prepare the file with all the channels */ + /* prepare the file with all the channels */ - if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_format->exr_codec, NULL) == 0) { - printf("Error Writing Singlelayer Multiview Openexr\n"); - IMB_exr_close(exrhandle); - } - else { - IMB_exr_clear_channels(exrhandle); - return exrhandle; - } - } - return NULL; + if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_format->exr_codec, NULL) == + 0) { + printf("Error Writing Singlelayer Multiview Openexr\n"); + IMB_exr_close(exrhandle); + } + else { + IMB_exr_clear_channels(exrhandle); + return exrhandle; + } + } + return NULL; } void OutputOpenExrSingleLayerMultiViewOperation::deinitExecution() { - unsigned int width = this->getWidth(); - unsigned int height = this->getHeight(); - - if (width != 0 && height != 0) { - void *exrhandle; - char filename[FILE_MAX]; - - BKE_image_path_from_imtype( - filename, this->m_path, BKE_main_blendfile_path_from_global(), this->m_rd->cfra, R_IMF_IMTYPE_OPENEXR, - (this->m_rd->scemode & R_EXTENSION) != 0, true, NULL); - - exrhandle = this->get_handle(filename); - add_exr_channels(exrhandle, NULL, this->m_datatype, this->m_viewName, width, - this->m_format->depth == R_IMF_CHAN_DEPTH_16, this->m_outputBuffer); - - /* memory can only be freed after we write all views to the file */ - this->m_outputBuffer = NULL; - this->m_imageInput = NULL; - - /* ready to close the file */ - if (BKE_scene_multiview_is_render_view_last(this->m_rd, this->m_viewName)) { - IMB_exr_write_channels(exrhandle); - - /* free buffer memory for all the views */ - free_exr_channels(exrhandle, this->m_rd, NULL, this->m_datatype); - - /* remove exr handle and data */ - IMB_exr_close(exrhandle); - } - } + unsigned int width = this->getWidth(); + unsigned int height = this->getHeight(); + + if (width != 0 && height != 0) { + void *exrhandle; + char filename[FILE_MAX]; + + BKE_image_path_from_imtype(filename, + this->m_path, + BKE_main_blendfile_path_from_global(), + this->m_rd->cfra, + R_IMF_IMTYPE_OPENEXR, + (this->m_rd->scemode & R_EXTENSION) != 0, + true, + NULL); + + exrhandle = this->get_handle(filename); + add_exr_channels(exrhandle, + NULL, + this->m_datatype, + this->m_viewName, + width, + this->m_format->depth == R_IMF_CHAN_DEPTH_16, + this->m_outputBuffer); + + /* memory can only be freed after we write all views to the file */ + this->m_outputBuffer = NULL; + this->m_imageInput = NULL; + + /* ready to close the file */ + if (BKE_scene_multiview_is_render_view_last(this->m_rd, this->m_viewName)) { + IMB_exr_write_channels(exrhandle); + + /* free buffer memory for all the views */ + free_exr_channels(exrhandle, this->m_rd, NULL, this->m_datatype); + + /* remove exr handle and data */ + IMB_exr_close(exrhandle); + } + } } /************************************ OpenEXR Multilayer Multiview *****************************************/ OutputOpenExrMultiLayerMultiViewOperation::OutputOpenExrMultiLayerMultiViewOperation( - const RenderData *rd, const bNodeTree *tree, const char *path, - char exr_codec, bool exr_half_float, const char *viewName) + const RenderData *rd, + const bNodeTree *tree, + const char *path, + char exr_codec, + bool exr_half_float, + const char *viewName) : OutputOpenExrMultiLayerOperation(rd, tree, path, exr_codec, exr_half_float, viewName) { } void *OutputOpenExrMultiLayerMultiViewOperation::get_handle(const char *filename) { - unsigned int width = this->getWidth(); - unsigned int height = this->getHeight(); + unsigned int width = this->getWidth(); + unsigned int height = this->getHeight(); - if (width != 0 && height != 0) { + if (width != 0 && height != 0) { - void *exrhandle; - SceneRenderView *srv; + void *exrhandle; + SceneRenderView *srv; - /* get a new global handle */ - exrhandle = IMB_exr_get_handle_name(filename); + /* get a new global handle */ + exrhandle = IMB_exr_get_handle_name(filename); - if (!BKE_scene_multiview_is_render_view_first(this->m_rd, this->m_viewName)) - return exrhandle; + if (!BKE_scene_multiview_is_render_view_first(this->m_rd, this->m_viewName)) + return exrhandle; - IMB_exr_clear_channels(exrhandle); + IMB_exr_clear_channels(exrhandle); - /* check renderdata for amount of views */ - for (srv = (SceneRenderView *) this->m_rd->views.first; srv; srv = srv->next) { + /* check renderdata for amount of views */ + for (srv = (SceneRenderView *)this->m_rd->views.first; srv; srv = srv->next) { - if (BKE_scene_multiview_is_render_view_active(this->m_rd, srv) == false) - continue; + if (BKE_scene_multiview_is_render_view_active(this->m_rd, srv) == false) + continue; - IMB_exr_add_view(exrhandle, srv->name); + IMB_exr_add_view(exrhandle, srv->name); - for (unsigned int i = 0; i < this->m_layers.size(); ++i) - add_exr_channels(exrhandle, this->m_layers[i].name, this->m_layers[i].datatype, - srv->name, width, this->m_exr_half_float, NULL); - } + for (unsigned int i = 0; i < this->m_layers.size(); ++i) + add_exr_channels(exrhandle, + this->m_layers[i].name, + this->m_layers[i].datatype, + srv->name, + width, + this->m_exr_half_float, + NULL); + } - BLI_make_existing_file(filename); + BLI_make_existing_file(filename); - /* prepare the file with all the channels for the header */ - if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_exr_codec, NULL) == 0) { - printf("Error Writing Multilayer Multiview Openexr\n"); - IMB_exr_close(exrhandle); - } - else { - IMB_exr_clear_channels(exrhandle); - return exrhandle; - } - } - return NULL; + /* prepare the file with all the channels for the header */ + if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_exr_codec, NULL) == 0) { + printf("Error Writing Multilayer Multiview Openexr\n"); + IMB_exr_close(exrhandle); + } + else { + IMB_exr_clear_channels(exrhandle); + return exrhandle; + } + } + return NULL; } void OutputOpenExrMultiLayerMultiViewOperation::deinitExecution() { - unsigned int width = this->getWidth(); - unsigned int height = this->getHeight(); - - if (width != 0 && height != 0) { - void *exrhandle; - char filename[FILE_MAX]; - - BKE_image_path_from_imtype( - filename, this->m_path, BKE_main_blendfile_path_from_global(), this->m_rd->cfra, R_IMF_IMTYPE_MULTILAYER, - (this->m_rd->scemode & R_EXTENSION) != 0, true, NULL); - - exrhandle = this->get_handle(filename); - - for (unsigned int i = 0; i < this->m_layers.size(); ++i) - add_exr_channels(exrhandle, this->m_layers[i].name, this->m_layers[i].datatype, this->m_viewName, - width, this->m_exr_half_float, this->m_layers[i].outputBuffer); - - for (unsigned int i = 0; i < this->m_layers.size(); ++i) { - /* memory can only be freed after we write all views to the file */ - this->m_layers[i].outputBuffer = NULL; - this->m_layers[i].imageInput = NULL; - } - - /* ready to close the file */ - if (BKE_scene_multiview_is_render_view_last(this->m_rd, this->m_viewName)) { - IMB_exr_write_channels(exrhandle); - - /* free buffer memory for all the views */ - for (unsigned int i = 0; i < this->m_layers.size(); ++i) { - free_exr_channels(exrhandle, this->m_rd, this->m_layers[i].name, this->m_layers[i].datatype); - } - - IMB_exr_close(exrhandle); - } - } + unsigned int width = this->getWidth(); + unsigned int height = this->getHeight(); + + if (width != 0 && height != 0) { + void *exrhandle; + char filename[FILE_MAX]; + + BKE_image_path_from_imtype(filename, + this->m_path, + BKE_main_blendfile_path_from_global(), + this->m_rd->cfra, + R_IMF_IMTYPE_MULTILAYER, + (this->m_rd->scemode & R_EXTENSION) != 0, + true, + NULL); + + exrhandle = this->get_handle(filename); + + for (unsigned int i = 0; i < this->m_layers.size(); ++i) + add_exr_channels(exrhandle, + this->m_layers[i].name, + this->m_layers[i].datatype, + this->m_viewName, + width, + this->m_exr_half_float, + this->m_layers[i].outputBuffer); + + for (unsigned int i = 0; i < this->m_layers.size(); ++i) { + /* memory can only be freed after we write all views to the file */ + this->m_layers[i].outputBuffer = NULL; + this->m_layers[i].imageInput = NULL; + } + + /* ready to close the file */ + if (BKE_scene_multiview_is_render_view_last(this->m_rd, this->m_viewName)) { + IMB_exr_write_channels(exrhandle); + + /* free buffer memory for all the views */ + for (unsigned int i = 0; i < this->m_layers.size(); ++i) { + free_exr_channels( + exrhandle, this->m_rd, this->m_layers[i].name, this->m_layers[i].datatype); + } + + IMB_exr_close(exrhandle); + } + } } - /******************************** Stereo3D ******************************/ -OutputStereoOperation::OutputStereoOperation( - const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path, - const char *name, const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings, - const char *viewName) - : OutputSingleLayerOperation(rd, tree, datatype, format, path, viewSettings, displaySettings, viewName) +OutputStereoOperation::OutputStereoOperation(const RenderData *rd, + const bNodeTree *tree, + DataType datatype, + ImageFormatData *format, + const char *path, + const char *name, + const ColorManagedViewSettings *viewSettings, + const ColorManagedDisplaySettings *displaySettings, + const char *viewName) + : OutputSingleLayerOperation( + rd, tree, datatype, format, path, viewSettings, displaySettings, viewName) { - BLI_strncpy(this->m_name, name, sizeof(this->m_name)); - this->m_channels = get_datatype_size(datatype); + BLI_strncpy(this->m_name, name, sizeof(this->m_name)); + this->m_channels = get_datatype_size(datatype); } void *OutputStereoOperation::get_handle(const char *filename) { - size_t width = this->getWidth(); - size_t height = this->getHeight(); - const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; - size_t i; + size_t width = this->getWidth(); + size_t height = this->getHeight(); + const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; + size_t i; - if (width != 0 && height != 0) { - void *exrhandle; + if (width != 0 && height != 0) { + void *exrhandle; - exrhandle = IMB_exr_get_handle_name(filename); + exrhandle = IMB_exr_get_handle_name(filename); - if (!BKE_scene_multiview_is_render_view_first(this->m_rd, this->m_viewName)) - return exrhandle; + if (!BKE_scene_multiview_is_render_view_first(this->m_rd, this->m_viewName)) + return exrhandle; - IMB_exr_clear_channels(exrhandle); + IMB_exr_clear_channels(exrhandle); - for (i = 0; i < 2; i++) - IMB_exr_add_view(exrhandle, names[i]); + for (i = 0; i < 2; i++) + IMB_exr_add_view(exrhandle, names[i]); - return exrhandle; - } - return NULL; + return exrhandle; + } + return NULL; } void OutputStereoOperation::deinitExecution() { - unsigned int width = this->getWidth(); - unsigned int height = this->getHeight(); - - if (width != 0 && height != 0) { - void *exrhandle; - - exrhandle = this->get_handle(this->m_path); - float *buf = this->m_outputBuffer; - - /* populate single EXR channel with view data */ - IMB_exr_add_channel(exrhandle, NULL, this->m_name, this->m_viewName, 1, this->m_channels * width * height, buf, - this->m_format->depth == R_IMF_CHAN_DEPTH_16); - - this->m_imageInput = NULL; - this->m_outputBuffer = NULL; - - /* create stereo ibuf */ - if (BKE_scene_multiview_is_render_view_last(this->m_rd, this->m_viewName)) { - ImBuf *ibuf[3] = {NULL}; - const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; - char filename[FILE_MAX]; - int i; - - /* get rectf from EXR */ - for (i = 0; i < 2; i++) { - float *rectf = IMB_exr_channel_rect(exrhandle, NULL, this->m_name, names[i]); - ibuf[i] = IMB_allocImBuf(width, height, this->m_format->planes, 0); - - ibuf[i]->channels = this->m_channels; - ibuf[i]->rect_float = rectf; - ibuf[i]->mall |= IB_rectfloat; - ibuf[i]->dither = this->m_rd->dither_intensity; - - /* do colormanagement in the individual views, so it doesn't need to do in the stereo */ - IMB_colormanagement_imbuf_for_write(ibuf[i], true, false, this->m_viewSettings, - this->m_displaySettings, this->m_format); - IMB_prepare_write_ImBuf(IMB_isfloat(ibuf[i]), ibuf[i]); - } - - /* create stereo buffer */ - ibuf[2] = IMB_stereo3d_ImBuf(this->m_format, ibuf[0], ibuf[1]); - - BKE_image_path_from_imformat( - filename, this->m_path, BKE_main_blendfile_path_from_global(), this->m_rd->cfra, this->m_format, - (this->m_rd->scemode & R_EXTENSION) != 0, true, NULL); - - BKE_imbuf_write(ibuf[2], filename, this->m_format); - - /* imbuf knows which rects are not part of ibuf */ - for (i = 0; i < 3; i++) - IMB_freeImBuf(ibuf[i]); - - IMB_exr_close(exrhandle); - } - } + unsigned int width = this->getWidth(); + unsigned int height = this->getHeight(); + + if (width != 0 && height != 0) { + void *exrhandle; + + exrhandle = this->get_handle(this->m_path); + float *buf = this->m_outputBuffer; + + /* populate single EXR channel with view data */ + IMB_exr_add_channel(exrhandle, + NULL, + this->m_name, + this->m_viewName, + 1, + this->m_channels * width * height, + buf, + this->m_format->depth == R_IMF_CHAN_DEPTH_16); + + this->m_imageInput = NULL; + this->m_outputBuffer = NULL; + + /* create stereo ibuf */ + if (BKE_scene_multiview_is_render_view_last(this->m_rd, this->m_viewName)) { + ImBuf *ibuf[3] = {NULL}; + const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; + char filename[FILE_MAX]; + int i; + + /* get rectf from EXR */ + for (i = 0; i < 2; i++) { + float *rectf = IMB_exr_channel_rect(exrhandle, NULL, this->m_name, names[i]); + ibuf[i] = IMB_allocImBuf(width, height, this->m_format->planes, 0); + + ibuf[i]->channels = this->m_channels; + ibuf[i]->rect_float = rectf; + ibuf[i]->mall |= IB_rectfloat; + ibuf[i]->dither = this->m_rd->dither_intensity; + + /* do colormanagement in the individual views, so it doesn't need to do in the stereo */ + IMB_colormanagement_imbuf_for_write( + ibuf[i], true, false, this->m_viewSettings, this->m_displaySettings, this->m_format); + IMB_prepare_write_ImBuf(IMB_isfloat(ibuf[i]), ibuf[i]); + } + + /* create stereo buffer */ + ibuf[2] = IMB_stereo3d_ImBuf(this->m_format, ibuf[0], ibuf[1]); + + BKE_image_path_from_imformat(filename, + this->m_path, + BKE_main_blendfile_path_from_global(), + this->m_rd->cfra, + this->m_format, + (this->m_rd->scemode & R_EXTENSION) != 0, + true, + NULL); + + BKE_imbuf_write(ibuf[2], filename, this->m_format); + + /* imbuf knows which rects are not part of ibuf */ + for (i = 0; i < 3; i++) + IMB_freeImBuf(ibuf[i]); + + IMB_exr_close(exrhandle); + } + } } diff --git a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h index a3bcaac2835..036468f9472 100644 --- a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h +++ b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h @@ -28,40 +28,53 @@ #include "intern/openexr/openexr_multi.h" class OutputOpenExrSingleLayerMultiViewOperation : public OutputSingleLayerOperation { -private: -public: - OutputOpenExrSingleLayerMultiViewOperation(const RenderData *rd, const bNodeTree *tree, DataType datatype, - ImageFormatData *format, const char *path, - const ColorManagedViewSettings *viewSettings, - const ColorManagedDisplaySettings *displaySettings, - const char *viewName); + private: + public: + OutputOpenExrSingleLayerMultiViewOperation(const RenderData *rd, + const bNodeTree *tree, + DataType datatype, + ImageFormatData *format, + const char *path, + const ColorManagedViewSettings *viewSettings, + const ColorManagedDisplaySettings *displaySettings, + const char *viewName); - void *get_handle(const char *filename); - void deinitExecution(); + void *get_handle(const char *filename); + void deinitExecution(); }; /* Writes inputs into OpenEXR multilayer channels. */ class OutputOpenExrMultiLayerMultiViewOperation : public OutputOpenExrMultiLayerOperation { -private: -public: - OutputOpenExrMultiLayerMultiViewOperation(const RenderData *rd, const bNodeTree *tree, const char *path, - char exr_codec, bool exr_half_float, const char *viewName); + private: + public: + OutputOpenExrMultiLayerMultiViewOperation(const RenderData *rd, + const bNodeTree *tree, + const char *path, + char exr_codec, + bool exr_half_float, + const char *viewName); - void *get_handle(const char *filename); - void deinitExecution(); + void *get_handle(const char *filename); + void deinitExecution(); }; class OutputStereoOperation : public OutputSingleLayerOperation { -private: - char m_name[FILE_MAX]; - size_t m_channels; -public: - OutputStereoOperation(const RenderData *rd, const bNodeTree *tree, DataType datatype, - struct ImageFormatData *format, const char *path, const char *name, - const ColorManagedViewSettings *viewSettings, - const ColorManagedDisplaySettings *displaySettings, const char *viewName); - void *get_handle(const char *filename); - void deinitExecution(); + private: + char m_name[FILE_MAX]; + size_t m_channels; + + public: + OutputStereoOperation(const RenderData *rd, + const bNodeTree *tree, + DataType datatype, + struct ImageFormatData *format, + const char *path, + const char *name, + const ColorManagedViewSettings *viewSettings, + const ColorManagedDisplaySettings *displaySettings, + const char *viewName); + void *get_handle(const char *filename); + void deinitExecution(); }; #endif diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cpp b/source/blender/compositor/operations/COM_OutputFileOperation.cpp index 9da3d15883c..f83ce478bd5 100644 --- a/source/blender/compositor/operations/COM_OutputFileOperation.cpp +++ b/source/blender/compositor/operations/COM_OutputFileOperation.cpp @@ -32,279 +32,340 @@ #include "DNA_color_types.h" extern "C" { -# include "MEM_guardedalloc.h" -# include "IMB_imbuf.h" -# include "IMB_colormanagement.h" -# include "IMB_imbuf_types.h" +#include "MEM_guardedalloc.h" +#include "IMB_imbuf.h" +#include "IMB_colormanagement.h" +#include "IMB_imbuf_types.h" } -void add_exr_channels(void *exrhandle, const char *layerName, const DataType datatype, - const char *viewName, const size_t width, bool use_half_float, float *buf) +void add_exr_channels(void *exrhandle, + const char *layerName, + const DataType datatype, + const char *viewName, + const size_t width, + bool use_half_float, + float *buf) { - /* create channels */ - switch (datatype) { - case COM_DT_VALUE: - IMB_exr_add_channel(exrhandle, layerName, "V", viewName, 1, width, buf ? buf : NULL, use_half_float); - break; - case COM_DT_VECTOR: - IMB_exr_add_channel(exrhandle, layerName, "X", viewName, 3, 3 * width, buf ? buf : NULL, use_half_float); - IMB_exr_add_channel(exrhandle, layerName, "Y", viewName, 3, 3 * width, buf ? buf + 1 : NULL, use_half_float); - IMB_exr_add_channel(exrhandle, layerName, "Z", viewName, 3, 3 * width, buf ? buf + 2 : NULL, use_half_float); - break; - case COM_DT_COLOR: - IMB_exr_add_channel(exrhandle, layerName, "R", viewName, 4, 4 * width, buf ? buf : NULL, use_half_float); - IMB_exr_add_channel(exrhandle, layerName, "G", viewName, 4, 4 * width, buf ? buf + 1 : NULL, use_half_float); - IMB_exr_add_channel(exrhandle, layerName, "B", viewName, 4, 4 * width, buf ? buf + 2 : NULL, use_half_float); - IMB_exr_add_channel(exrhandle, layerName, "A", viewName, 4, 4 * width, buf ? buf + 3 : NULL, use_half_float); - break; - default: - break; - } + /* create channels */ + switch (datatype) { + case COM_DT_VALUE: + IMB_exr_add_channel( + exrhandle, layerName, "V", viewName, 1, width, buf ? buf : NULL, use_half_float); + break; + case COM_DT_VECTOR: + IMB_exr_add_channel( + exrhandle, layerName, "X", viewName, 3, 3 * width, buf ? buf : NULL, use_half_float); + IMB_exr_add_channel( + exrhandle, layerName, "Y", viewName, 3, 3 * width, buf ? buf + 1 : NULL, use_half_float); + IMB_exr_add_channel( + exrhandle, layerName, "Z", viewName, 3, 3 * width, buf ? buf + 2 : NULL, use_half_float); + break; + case COM_DT_COLOR: + IMB_exr_add_channel( + exrhandle, layerName, "R", viewName, 4, 4 * width, buf ? buf : NULL, use_half_float); + IMB_exr_add_channel( + exrhandle, layerName, "G", viewName, 4, 4 * width, buf ? buf + 1 : NULL, use_half_float); + IMB_exr_add_channel( + exrhandle, layerName, "B", viewName, 4, 4 * width, buf ? buf + 2 : NULL, use_half_float); + IMB_exr_add_channel( + exrhandle, layerName, "A", viewName, 4, 4 * width, buf ? buf + 3 : NULL, use_half_float); + break; + default: + break; + } } -void free_exr_channels(void *exrhandle, const RenderData *rd, const char *layerName, const DataType datatype) +void free_exr_channels(void *exrhandle, + const RenderData *rd, + const char *layerName, + const DataType datatype) { - SceneRenderView *srv; - - /* check renderdata for amount of views */ - for (srv = (SceneRenderView *) rd->views.first; srv; srv = srv->next) { - float *rect = NULL; - - if (BKE_scene_multiview_is_render_view_active(rd, srv) == false) - continue; - - /* the pointer is stored in the first channel of each datatype */ - switch (datatype) { - case COM_DT_VALUE: - rect = IMB_exr_channel_rect(exrhandle, layerName, "V", srv->name); - break; - case COM_DT_VECTOR: - rect = IMB_exr_channel_rect(exrhandle, layerName, "X", srv->name); - break; - case COM_DT_COLOR: - rect = IMB_exr_channel_rect(exrhandle, layerName, "R", srv->name); - break; - default: - break; - } - if (rect) - MEM_freeN(rect); - } + SceneRenderView *srv; + + /* check renderdata for amount of views */ + for (srv = (SceneRenderView *)rd->views.first; srv; srv = srv->next) { + float *rect = NULL; + + if (BKE_scene_multiview_is_render_view_active(rd, srv) == false) + continue; + + /* the pointer is stored in the first channel of each datatype */ + switch (datatype) { + case COM_DT_VALUE: + rect = IMB_exr_channel_rect(exrhandle, layerName, "V", srv->name); + break; + case COM_DT_VECTOR: + rect = IMB_exr_channel_rect(exrhandle, layerName, "X", srv->name); + break; + case COM_DT_COLOR: + rect = IMB_exr_channel_rect(exrhandle, layerName, "R", srv->name); + break; + default: + break; + } + if (rect) + MEM_freeN(rect); + } } int get_datatype_size(DataType datatype) { - switch (datatype) { - case COM_DT_VALUE: return 1; - case COM_DT_VECTOR: return 3; - case COM_DT_COLOR: return 4; - default: return 0; - } + switch (datatype) { + case COM_DT_VALUE: + return 1; + case COM_DT_VECTOR: + return 3; + case COM_DT_COLOR: + return 4; + default: + return 0; + } } static float *init_buffer(unsigned int width, unsigned int height, DataType datatype) { - // When initializing the tree during initial load the width and height can be zero. - if (width != 0 && height != 0) { - int size = get_datatype_size(datatype); - return (float *)MEM_callocN(width * height * size * sizeof(float), "OutputFile buffer"); - } - else - return NULL; + // When initializing the tree during initial load the width and height can be zero. + if (width != 0 && height != 0) { + int size = get_datatype_size(datatype); + return (float *)MEM_callocN(width * height * size * sizeof(float), "OutputFile buffer"); + } + else + return NULL; } -static void write_buffer_rect(rcti *rect, const bNodeTree *tree, - SocketReader *reader, float *buffer, unsigned int width, DataType datatype) +static void write_buffer_rect(rcti *rect, + const bNodeTree *tree, + SocketReader *reader, + float *buffer, + unsigned int width, + DataType datatype) { - float color[4]; - int i, size = get_datatype_size(datatype); - - if (!buffer) return; - int x1 = rect->xmin; - int y1 = rect->ymin; - int x2 = rect->xmax; - int y2 = rect->ymax; - int offset = (y1 * width + x1) * size; - int x; - int y; - bool breaked = false; - - for (y = y1; y < y2 && (!breaked); y++) { - for (x = x1; x < x2 && (!breaked); x++) { - reader->readSampled(color, x, y, COM_PS_NEAREST); - - for (i = 0; i < size; ++i) - buffer[offset + i] = color[i]; - offset += size; - - if (tree->test_break && tree->test_break(tree->tbh)) - breaked = true; - } - offset += (width - (x2 - x1)) * size; - } + float color[4]; + int i, size = get_datatype_size(datatype); + + if (!buffer) + return; + int x1 = rect->xmin; + int y1 = rect->ymin; + int x2 = rect->xmax; + int y2 = rect->ymax; + int offset = (y1 * width + x1) * size; + int x; + int y; + bool breaked = false; + + for (y = y1; y < y2 && (!breaked); y++) { + for (x = x1; x < x2 && (!breaked); x++) { + reader->readSampled(color, x, y, COM_PS_NEAREST); + + for (i = 0; i < size; ++i) + buffer[offset + i] = color[i]; + offset += size; + + if (tree->test_break && tree->test_break(tree->tbh)) + breaked = true; + } + offset += (width - (x2 - x1)) * size; + } } - OutputSingleLayerOperation::OutputSingleLayerOperation( - const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path, - const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings, const char *viewName) + const RenderData *rd, + const bNodeTree *tree, + DataType datatype, + ImageFormatData *format, + const char *path, + const ColorManagedViewSettings *viewSettings, + const ColorManagedDisplaySettings *displaySettings, + const char *viewName) { - this->m_rd = rd; - this->m_tree = tree; + this->m_rd = rd; + this->m_tree = tree; - this->addInputSocket(datatype); + this->addInputSocket(datatype); - this->m_outputBuffer = NULL; - this->m_datatype = datatype; - this->m_imageInput = NULL; + this->m_outputBuffer = NULL; + this->m_datatype = datatype; + this->m_imageInput = NULL; - this->m_format = format; - BLI_strncpy(this->m_path, path, sizeof(this->m_path)); + this->m_format = format; + BLI_strncpy(this->m_path, path, sizeof(this->m_path)); - this->m_viewSettings = viewSettings; - this->m_displaySettings = displaySettings; - this->m_viewName = viewName; + this->m_viewSettings = viewSettings; + this->m_displaySettings = displaySettings; + this->m_viewName = viewName; } void OutputSingleLayerOperation::initExecution() { - this->m_imageInput = getInputSocketReader(0); - this->m_outputBuffer = init_buffer(this->getWidth(), this->getHeight(), this->m_datatype); + this->m_imageInput = getInputSocketReader(0); + this->m_outputBuffer = init_buffer(this->getWidth(), this->getHeight(), this->m_datatype); } void OutputSingleLayerOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/) { - write_buffer_rect(rect, this->m_tree, this->m_imageInput, this->m_outputBuffer, this->getWidth(), this->m_datatype); + write_buffer_rect(rect, + this->m_tree, + this->m_imageInput, + this->m_outputBuffer, + this->getWidth(), + this->m_datatype); } void OutputSingleLayerOperation::deinitExecution() { - if (this->getWidth() * this->getHeight() != 0) { - - int size = get_datatype_size(this->m_datatype); - ImBuf *ibuf = IMB_allocImBuf(this->getWidth(), this->getHeight(), this->m_format->planes, 0); - char filename[FILE_MAX]; - const char *suffix; - - ibuf->channels = size; - ibuf->rect_float = this->m_outputBuffer; - ibuf->mall |= IB_rectfloat; - ibuf->dither = this->m_rd->dither_intensity; - - IMB_colormanagement_imbuf_for_write(ibuf, true, false, m_viewSettings, m_displaySettings, - this->m_format); - - suffix = BKE_scene_multiview_view_suffix_get(this->m_rd, this->m_viewName); - - BKE_image_path_from_imformat( - filename, this->m_path, BKE_main_blendfile_path_from_global(), this->m_rd->cfra, this->m_format, - (this->m_rd->scemode & R_EXTENSION) != 0, true, suffix); - - if (0 == BKE_imbuf_write(ibuf, filename, this->m_format)) - printf("Cannot save Node File Output to %s\n", filename); - else - printf("Saved: %s\n", filename); - - IMB_freeImBuf(ibuf); - } - this->m_outputBuffer = NULL; - this->m_imageInput = NULL; + if (this->getWidth() * this->getHeight() != 0) { + + int size = get_datatype_size(this->m_datatype); + ImBuf *ibuf = IMB_allocImBuf(this->getWidth(), this->getHeight(), this->m_format->planes, 0); + char filename[FILE_MAX]; + const char *suffix; + + ibuf->channels = size; + ibuf->rect_float = this->m_outputBuffer; + ibuf->mall |= IB_rectfloat; + ibuf->dither = this->m_rd->dither_intensity; + + IMB_colormanagement_imbuf_for_write( + ibuf, true, false, m_viewSettings, m_displaySettings, this->m_format); + + suffix = BKE_scene_multiview_view_suffix_get(this->m_rd, this->m_viewName); + + BKE_image_path_from_imformat(filename, + this->m_path, + BKE_main_blendfile_path_from_global(), + this->m_rd->cfra, + this->m_format, + (this->m_rd->scemode & R_EXTENSION) != 0, + true, + suffix); + + if (0 == BKE_imbuf_write(ibuf, filename, this->m_format)) + printf("Cannot save Node File Output to %s\n", filename); + else + printf("Saved: %s\n", filename); + + IMB_freeImBuf(ibuf); + } + this->m_outputBuffer = NULL; + this->m_imageInput = NULL; } /******************************* MultiLayer *******************************/ OutputOpenExrLayer::OutputOpenExrLayer(const char *name_, DataType datatype_, bool use_layer_) { - BLI_strncpy(this->name, name_, sizeof(this->name)); - this->datatype = datatype_; - this->use_layer = use_layer_; + BLI_strncpy(this->name, name_, sizeof(this->name)); + this->datatype = datatype_; + this->use_layer = use_layer_; - /* these are created in initExecution */ - this->outputBuffer = 0; - this->imageInput = 0; + /* these are created in initExecution */ + this->outputBuffer = 0; + this->imageInput = 0; } -OutputOpenExrMultiLayerOperation::OutputOpenExrMultiLayerOperation( - const RenderData *rd, const bNodeTree *tree, const char *path, - char exr_codec, bool exr_half_float, const char *viewName) +OutputOpenExrMultiLayerOperation::OutputOpenExrMultiLayerOperation(const RenderData *rd, + const bNodeTree *tree, + const char *path, + char exr_codec, + bool exr_half_float, + const char *viewName) { - this->m_rd = rd; - this->m_tree = tree; + this->m_rd = rd; + this->m_tree = tree; - BLI_strncpy(this->m_path, path, sizeof(this->m_path)); - this->m_exr_codec = exr_codec; - this->m_exr_half_float = exr_half_float; - this->m_viewName = viewName; + BLI_strncpy(this->m_path, path, sizeof(this->m_path)); + this->m_exr_codec = exr_codec; + this->m_exr_half_float = exr_half_float; + this->m_viewName = viewName; } -void OutputOpenExrMultiLayerOperation::add_layer(const char *name, DataType datatype, bool use_layer) +void OutputOpenExrMultiLayerOperation::add_layer(const char *name, + DataType datatype, + bool use_layer) { - this->addInputSocket(datatype); - this->m_layers.push_back(OutputOpenExrLayer(name, datatype, use_layer)); + this->addInputSocket(datatype); + this->m_layers.push_back(OutputOpenExrLayer(name, datatype, use_layer)); } void OutputOpenExrMultiLayerOperation::initExecution() { - for (unsigned int i = 0; i < this->m_layers.size(); ++i) { - if (this->m_layers[i].use_layer) { - SocketReader *reader = getInputSocketReader(i); - this->m_layers[i].imageInput = reader; - this->m_layers[i].outputBuffer = init_buffer(this->getWidth(), this->getHeight(), this->m_layers[i].datatype); - } - } + for (unsigned int i = 0; i < this->m_layers.size(); ++i) { + if (this->m_layers[i].use_layer) { + SocketReader *reader = getInputSocketReader(i); + this->m_layers[i].imageInput = reader; + this->m_layers[i].outputBuffer = init_buffer( + this->getWidth(), this->getHeight(), this->m_layers[i].datatype); + } + } } void OutputOpenExrMultiLayerOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/) { - for (unsigned int i = 0; i < this->m_layers.size(); ++i) { - OutputOpenExrLayer &layer = this->m_layers[i]; - if (layer.imageInput) - write_buffer_rect(rect, this->m_tree, layer.imageInput, layer.outputBuffer, this->getWidth(), layer.datatype); - } + for (unsigned int i = 0; i < this->m_layers.size(); ++i) { + OutputOpenExrLayer &layer = this->m_layers[i]; + if (layer.imageInput) + write_buffer_rect(rect, + this->m_tree, + layer.imageInput, + layer.outputBuffer, + this->getWidth(), + layer.datatype); + } } void OutputOpenExrMultiLayerOperation::deinitExecution() { - unsigned int width = this->getWidth(); - unsigned int height = this->getHeight(); - if (width != 0 && height != 0) { - char filename[FILE_MAX]; - const char *suffix; - void *exrhandle = IMB_exr_get_handle(); - - suffix = BKE_scene_multiview_view_suffix_get(this->m_rd, this->m_viewName); - BKE_image_path_from_imtype( - filename, this->m_path, BKE_main_blendfile_path_from_global(), this->m_rd->cfra, R_IMF_IMTYPE_MULTILAYER, - (this->m_rd->scemode & R_EXTENSION) != 0, true, suffix); - BLI_make_existing_file(filename); - - for (unsigned int i = 0; i < this->m_layers.size(); ++i) { - OutputOpenExrLayer &layer = this->m_layers[i]; - if (!layer.imageInput) - continue; /* skip unconnected sockets */ - - add_exr_channels(exrhandle, this->m_layers[i].name, this->m_layers[i].datatype, "", width, - this->m_exr_half_float, this->m_layers[i].outputBuffer); - } - - /* when the filename has no permissions, this can fail */ - if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_exr_codec, NULL)) { - IMB_exr_write_channels(exrhandle); - } - else { - /* TODO, get the error from openexr's exception */ - /* XXX nice way to do report? */ - printf("Error Writing Render Result, see console\n"); - } - - IMB_exr_close(exrhandle); - for (unsigned int i = 0; i < this->m_layers.size(); ++i) { - if (this->m_layers[i].outputBuffer) { - MEM_freeN(this->m_layers[i].outputBuffer); - this->m_layers[i].outputBuffer = NULL; - } - - this->m_layers[i].imageInput = NULL; - } - } + unsigned int width = this->getWidth(); + unsigned int height = this->getHeight(); + if (width != 0 && height != 0) { + char filename[FILE_MAX]; + const char *suffix; + void *exrhandle = IMB_exr_get_handle(); + + suffix = BKE_scene_multiview_view_suffix_get(this->m_rd, this->m_viewName); + BKE_image_path_from_imtype(filename, + this->m_path, + BKE_main_blendfile_path_from_global(), + this->m_rd->cfra, + R_IMF_IMTYPE_MULTILAYER, + (this->m_rd->scemode & R_EXTENSION) != 0, + true, + suffix); + BLI_make_existing_file(filename); + + for (unsigned int i = 0; i < this->m_layers.size(); ++i) { + OutputOpenExrLayer &layer = this->m_layers[i]; + if (!layer.imageInput) + continue; /* skip unconnected sockets */ + + add_exr_channels(exrhandle, + this->m_layers[i].name, + this->m_layers[i].datatype, + "", + width, + this->m_exr_half_float, + this->m_layers[i].outputBuffer); + } + + /* when the filename has no permissions, this can fail */ + if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_exr_codec, NULL)) { + IMB_exr_write_channels(exrhandle); + } + else { + /* TODO, get the error from openexr's exception */ + /* XXX nice way to do report? */ + printf("Error Writing Render Result, see console\n"); + } + + IMB_exr_close(exrhandle); + for (unsigned int i = 0; i < this->m_layers.size(); ++i) { + if (this->m_layers[i].outputBuffer) { + MEM_freeN(this->m_layers[i].outputBuffer); + this->m_layers[i].outputBuffer = NULL; + } + + this->m_layers[i].imageInput = NULL; + } + } } diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.h b/source/blender/compositor/operations/COM_OutputFileOperation.h index de256e25ce0..3ffba6b374e 100644 --- a/source/blender/compositor/operations/COM_OutputFileOperation.h +++ b/source/blender/compositor/operations/COM_OutputFileOperation.h @@ -29,79 +29,116 @@ /* Writes the image to a single-layer file. */ class OutputSingleLayerOperation : public NodeOperation { -protected: - const RenderData *m_rd; - const bNodeTree *m_tree; - - ImageFormatData *m_format; - char m_path[FILE_MAX]; - - float *m_outputBuffer; - DataType m_datatype; - SocketReader *m_imageInput; - - const ColorManagedViewSettings *m_viewSettings; - const ColorManagedDisplaySettings *m_displaySettings; - - const char *m_viewName; -public: - OutputSingleLayerOperation(const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path, - const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings, const char *viewName); - - void executeRegion(rcti *rect, unsigned int tileNumber); - bool isOutputOperation(bool /*rendering*/) const { return true; } - void initExecution(); - void deinitExecution(); - CompositorPriority getRenderPriority() const { return COM_PRIORITY_LOW; } - - bool isFileOutputOperation() const { return true; } + protected: + const RenderData *m_rd; + const bNodeTree *m_tree; + + ImageFormatData *m_format; + char m_path[FILE_MAX]; + + float *m_outputBuffer; + DataType m_datatype; + SocketReader *m_imageInput; + + const ColorManagedViewSettings *m_viewSettings; + const ColorManagedDisplaySettings *m_displaySettings; + + const char *m_viewName; + + public: + OutputSingleLayerOperation(const RenderData *rd, + const bNodeTree *tree, + DataType datatype, + ImageFormatData *format, + const char *path, + const ColorManagedViewSettings *viewSettings, + const ColorManagedDisplaySettings *displaySettings, + const char *viewName); + + void executeRegion(rcti *rect, unsigned int tileNumber); + bool isOutputOperation(bool /*rendering*/) const + { + return true; + } + void initExecution(); + void deinitExecution(); + CompositorPriority getRenderPriority() const + { + return COM_PRIORITY_LOW; + } + + bool isFileOutputOperation() const + { + return true; + } }; /* extra info for OpenEXR layers */ struct OutputOpenExrLayer { - OutputOpenExrLayer(const char *name, DataType datatype, bool use_layer); + OutputOpenExrLayer(const char *name, DataType datatype, bool use_layer); - char name[EXR_TOT_MAXNAME - 2]; - DataType datatype; - bool use_layer; + char name[EXR_TOT_MAXNAME - 2]; + DataType datatype; + bool use_layer; - /* internals */ - float *outputBuffer; - SocketReader *imageInput; + /* internals */ + float *outputBuffer; + SocketReader *imageInput; }; /* Writes inputs into OpenEXR multilayer channels. */ class OutputOpenExrMultiLayerOperation : public NodeOperation { -protected: - typedef std::vector<OutputOpenExrLayer> LayerList; - - const RenderData *m_rd; - const bNodeTree *m_tree; - - char m_path[FILE_MAX]; - char m_exr_codec; - bool m_exr_half_float; - LayerList m_layers; - const char *m_viewName; - -public: - OutputOpenExrMultiLayerOperation(const RenderData *rd, const bNodeTree *tree, const char *path, - char exr_codec, bool exr_half_float, const char *viewName); - - void add_layer(const char *name, DataType datatype, bool use_layer); - - void executeRegion(rcti *rect, unsigned int tileNumber); - bool isOutputOperation(bool /*rendering*/) const { return true; } - void initExecution(); - void deinitExecution(); - CompositorPriority getRenderPriority() const { return COM_PRIORITY_LOW; } - - bool isFileOutputOperation() const { return true; } + protected: + typedef std::vector<OutputOpenExrLayer> LayerList; + + const RenderData *m_rd; + const bNodeTree *m_tree; + + char m_path[FILE_MAX]; + char m_exr_codec; + bool m_exr_half_float; + LayerList m_layers; + const char *m_viewName; + + public: + OutputOpenExrMultiLayerOperation(const RenderData *rd, + const bNodeTree *tree, + const char *path, + char exr_codec, + bool exr_half_float, + const char *viewName); + + void add_layer(const char *name, DataType datatype, bool use_layer); + + void executeRegion(rcti *rect, unsigned int tileNumber); + bool isOutputOperation(bool /*rendering*/) const + { + return true; + } + void initExecution(); + void deinitExecution(); + CompositorPriority getRenderPriority() const + { + return COM_PRIORITY_LOW; + } + + bool isFileOutputOperation() const + { + return true; + } }; -void add_exr_channels(void *exrhandle, const char *layerName, const DataType datatype, const char *viewName, - const size_t width, bool use_half_float, float *buf); -void free_exr_channels(void *exrhandle, const RenderData *rd, const char *layerName, const DataType datatype); +void add_exr_channels(void *exrhandle, + const char *layerName, + const DataType datatype, + const char *viewName, + const size_t width, + bool use_half_float, + float *buf); +void free_exr_channels(void *exrhandle, + const RenderData *rd, + const char *layerName, + const DataType datatype); int get_datatype_size(DataType datatype); #endif diff --git a/source/blender/compositor/operations/COM_PixelateOperation.cpp b/source/blender/compositor/operations/COM_PixelateOperation.cpp index e047f8a38de..18e691d3c34 100644 --- a/source/blender/compositor/operations/COM_PixelateOperation.cpp +++ b/source/blender/compositor/operations/COM_PixelateOperation.cpp @@ -20,25 +20,28 @@ PixelateOperation::PixelateOperation(DataType datatype) : NodeOperation() { - this->addInputSocket(datatype); - this->addOutputSocket(datatype); - this->setResolutionInputSocketIndex(0); - this->m_inputOperation = NULL; + this->addInputSocket(datatype); + this->addOutputSocket(datatype); + this->setResolutionInputSocketIndex(0); + this->m_inputOperation = NULL; } void PixelateOperation::initExecution() { - this->m_inputOperation = this->getInputSocketReader(0); + this->m_inputOperation = this->getInputSocketReader(0); } void PixelateOperation::deinitExecution() { - this->m_inputOperation = NULL; + this->m_inputOperation = NULL; } -void PixelateOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void PixelateOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float nx = round(x); - float ny = round(y); - this->m_inputOperation->readSampled(output, nx, ny, sampler); + float nx = round(x); + float ny = round(y); + this->m_inputOperation->readSampled(output, nx, ny, sampler); } diff --git a/source/blender/compositor/operations/COM_PixelateOperation.h b/source/blender/compositor/operations/COM_PixelateOperation.h index f9846cec2f6..86aab26ee00 100644 --- a/source/blender/compositor/operations/COM_PixelateOperation.h +++ b/source/blender/compositor/operations/COM_PixelateOperation.h @@ -29,36 +29,37 @@ * This operation will remove the sub-pixel accuracy */ class PixelateOperation : public NodeOperation { -private: - /** - * \brief cached reference to the input operation - */ - SocketReader *m_inputOperation; -public: - /** - * \brief PixelateOperation - * \param dataType: the datatype to create this operator for (saves datatype conversions) - */ - PixelateOperation(DataType dataType); + private: + /** + * \brief cached reference to the input operation + */ + SocketReader *m_inputOperation; - /** - * \brief initialization of the execution - */ - void initExecution(); + public: + /** + * \brief PixelateOperation + * \param dataType: the datatype to create this operator for (saves datatype conversions) + */ + PixelateOperation(DataType dataType); - /** - * \brief de-initialization of the execution - */ - void deinitExecution(); + /** + * \brief initialization of the execution + */ + void initExecution(); - /** - * \brief executePixel - * \param output: result - * \param x: x-coordinate - * \param y: y-coordinate - * \param sampler: sampler - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + /** + * \brief de-initialization of the execution + */ + void deinitExecution(); + + /** + * \brief executePixel + * \param output: result + * \param x: x-coordinate + * \param y: y-coordinate + * \param sampler: sampler + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; #endif diff --git a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp index c1dae48d1c6..54d5d6e97a5 100644 --- a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp +++ b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp @@ -25,192 +25,194 @@ #include "BLI_math_color.h" extern "C" { -# include "BKE_node.h" +#include "BKE_node.h" } static bool check_corners(float corners[4][2]) { - int i, next, prev; - float cross = 0.0f; + int i, next, prev; + float cross = 0.0f; - for (i = 0; i < 4; i++) { - float v1[2], v2[2], cur_cross; + for (i = 0; i < 4; i++) { + float v1[2], v2[2], cur_cross; - next = (i + 1) % 4; - prev = (4 + i - 1) % 4; + next = (i + 1) % 4; + prev = (4 + i - 1) % 4; - sub_v2_v2v2(v1, corners[i], corners[prev]); - sub_v2_v2v2(v2, corners[next], corners[i]); + sub_v2_v2v2(v1, corners[i], corners[prev]); + sub_v2_v2v2(v2, corners[next], corners[i]); - cur_cross = cross_v2v2(v1, v2); - if (fabsf(cur_cross) <= FLT_EPSILON) - return false; + cur_cross = cross_v2v2(v1, v2); + if (fabsf(cur_cross) <= FLT_EPSILON) + return false; - if (cross == 0.0f) - cross = cur_cross; - else if (cross * cur_cross < 0.0f) - return false; - } + if (cross == 0.0f) + cross = cur_cross; + else if (cross * cur_cross < 0.0f) + return false; + } - return true; + return true; } static void readCornersFromSockets(rcti *rect, SocketReader *readers[4], float corners[4][2]) { - for (int i = 0; i < 4; ++i) { - float result[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - readers[i]->readSampled(result, rect->xmin, rect->ymin, COM_PS_NEAREST); - corners[i][0] = result[0]; - corners[i][1] = result[1]; - } - - /* convexity check: - * concave corners need to be prevented, otherwise - * BKE_tracking_homography_between_two_quads will freeze - */ - if (!check_corners(corners)) { - /* simply revert to default corners - * there could be a more elegant solution, - * this prevents freezing at least. - */ - corners[0][0] = 0.0f; corners[0][1] = 0.0f; - corners[1][0] = 1.0f; corners[1][1] = 0.0f; - corners[2][0] = 1.0f; corners[2][1] = 1.0f; - corners[3][0] = 0.0f; corners[3][1] = 1.0f; - } + for (int i = 0; i < 4; ++i) { + float result[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + readers[i]->readSampled(result, rect->xmin, rect->ymin, COM_PS_NEAREST); + corners[i][0] = result[0]; + corners[i][1] = result[1]; + } + + /* convexity check: + * concave corners need to be prevented, otherwise + * BKE_tracking_homography_between_two_quads will freeze + */ + if (!check_corners(corners)) { + /* simply revert to default corners + * there could be a more elegant solution, + * this prevents freezing at least. + */ + corners[0][0] = 0.0f; + corners[0][1] = 0.0f; + corners[1][0] = 1.0f; + corners[1][1] = 0.0f; + corners[2][0] = 1.0f; + corners[2][1] = 1.0f; + corners[3][0] = 0.0f; + corners[3][1] = 1.0f; + } } - /* ******** PlaneCornerPinMaskOperation ******** */ -PlaneCornerPinMaskOperation::PlaneCornerPinMaskOperation() : - PlaneDistortMaskOperation(), - m_corners_ready(false) +PlaneCornerPinMaskOperation::PlaneCornerPinMaskOperation() + : PlaneDistortMaskOperation(), m_corners_ready(false) { - addInputSocket(COM_DT_VECTOR); - addInputSocket(COM_DT_VECTOR); - addInputSocket(COM_DT_VECTOR); - addInputSocket(COM_DT_VECTOR); - - /* XXX this is stupid: we need to make this "complex", - * so we can use the initializeTileData function - * to read corners from input sockets ... - */ - setComplex(true); + addInputSocket(COM_DT_VECTOR); + addInputSocket(COM_DT_VECTOR); + addInputSocket(COM_DT_VECTOR); + addInputSocket(COM_DT_VECTOR); + + /* XXX this is stupid: we need to make this "complex", + * so we can use the initializeTileData function + * to read corners from input sockets ... + */ + setComplex(true); } void PlaneCornerPinMaskOperation::initExecution() { - PlaneDistortMaskOperation::initExecution(); + PlaneDistortMaskOperation::initExecution(); - initMutex(); + initMutex(); } void PlaneCornerPinMaskOperation::deinitExecution() { - PlaneDistortMaskOperation::deinitExecution(); + PlaneDistortMaskOperation::deinitExecution(); - deinitMutex(); + deinitMutex(); } void *PlaneCornerPinMaskOperation::initializeTileData(rcti *rect) { - void *data = PlaneDistortMaskOperation::initializeTileData(rect); - - /* get corner values once, by reading inputs at (0,0) - * XXX this assumes invariable values (no image inputs), - * we don't have a nice generic system for that yet - */ - lockMutex(); - if (!m_corners_ready) { - SocketReader *readers[4] = { getInputSocketReader(0), - getInputSocketReader(1), - getInputSocketReader(2), - getInputSocketReader(3) }; - float corners[4][2]; - readCornersFromSockets(rect, readers, corners); - calculateCorners(corners, true, 0); - - m_corners_ready = true; - } - unlockMutex(); - - return data; + void *data = PlaneDistortMaskOperation::initializeTileData(rect); + + /* get corner values once, by reading inputs at (0,0) + * XXX this assumes invariable values (no image inputs), + * we don't have a nice generic system for that yet + */ + lockMutex(); + if (!m_corners_ready) { + SocketReader *readers[4] = {getInputSocketReader(0), + getInputSocketReader(1), + getInputSocketReader(2), + getInputSocketReader(3)}; + float corners[4][2]; + readCornersFromSockets(rect, readers, corners); + calculateCorners(corners, true, 0); + + m_corners_ready = true; + } + unlockMutex(); + + return data; } -void PlaneCornerPinMaskOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +void PlaneCornerPinMaskOperation::determineResolution(unsigned int resolution[2], + unsigned int preferredResolution[2]) { - resolution[0] = preferredResolution[0]; - resolution[1] = preferredResolution[1]; + resolution[0] = preferredResolution[0]; + resolution[1] = preferredResolution[1]; } - /* ******** PlaneCornerPinWarpImageOperation ******** */ -PlaneCornerPinWarpImageOperation::PlaneCornerPinWarpImageOperation() : - PlaneDistortWarpImageOperation(), - m_corners_ready(false) +PlaneCornerPinWarpImageOperation::PlaneCornerPinWarpImageOperation() + : PlaneDistortWarpImageOperation(), m_corners_ready(false) { - addInputSocket(COM_DT_VECTOR); - addInputSocket(COM_DT_VECTOR); - addInputSocket(COM_DT_VECTOR); - addInputSocket(COM_DT_VECTOR); + addInputSocket(COM_DT_VECTOR); + addInputSocket(COM_DT_VECTOR); + addInputSocket(COM_DT_VECTOR); + addInputSocket(COM_DT_VECTOR); } void PlaneCornerPinWarpImageOperation::initExecution() { - PlaneDistortWarpImageOperation::initExecution(); + PlaneDistortWarpImageOperation::initExecution(); - initMutex(); + initMutex(); } void PlaneCornerPinWarpImageOperation::deinitExecution() { - PlaneDistortWarpImageOperation::deinitExecution(); + PlaneDistortWarpImageOperation::deinitExecution(); - deinitMutex(); + deinitMutex(); } void *PlaneCornerPinWarpImageOperation::initializeTileData(rcti *rect) { - void *data = PlaneDistortWarpImageOperation::initializeTileData(rect); - - /* get corner values once, by reading inputs at (0,0) - * XXX this assumes invariable values (no image inputs), - * we don't have a nice generic system for that yet - */ - lockMutex(); - if (!m_corners_ready) { - /* corner sockets start at index 1 */ - SocketReader *readers[4] = { getInputSocketReader(1), - getInputSocketReader(2), - getInputSocketReader(3), - getInputSocketReader(4) }; - float corners[4][2]; - readCornersFromSockets(rect, readers, corners); - calculateCorners(corners, true, 0); - - m_corners_ready = true; - } - unlockMutex(); - - return data; + void *data = PlaneDistortWarpImageOperation::initializeTileData(rect); + + /* get corner values once, by reading inputs at (0,0) + * XXX this assumes invariable values (no image inputs), + * we don't have a nice generic system for that yet + */ + lockMutex(); + if (!m_corners_ready) { + /* corner sockets start at index 1 */ + SocketReader *readers[4] = {getInputSocketReader(1), + getInputSocketReader(2), + getInputSocketReader(3), + getInputSocketReader(4)}; + float corners[4][2]; + readCornersFromSockets(rect, readers, corners); + calculateCorners(corners, true, 0); + + m_corners_ready = true; + } + unlockMutex(); + + return data; } -bool PlaneCornerPinWarpImageOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool PlaneCornerPinWarpImageOperation::determineDependingAreaOfInterest( + rcti *input, ReadBufferOperation *readOperation, rcti *output) { - for (int i = 0; i < 4; ++i) - if (getInputOperation(i + 1)->determineDependingAreaOfInterest(input, readOperation, output)) - return true; - - /* XXX this is bad, but unavoidable with the current design: - * we don't know the actual corners and matrix at this point, - * so all we can do is get the full input image - */ - output->xmin = 0; - output->ymin = 0; - output->xmax = getInputOperation(0)->getWidth(); - output->ymax = getInputOperation(0)->getHeight(); - return true; -// return PlaneDistortWarpImageOperation::determineDependingAreaOfInterest(input, readOperation, output); + for (int i = 0; i < 4; ++i) + if (getInputOperation(i + 1)->determineDependingAreaOfInterest(input, readOperation, output)) + return true; + + /* XXX this is bad, but unavoidable with the current design: + * we don't know the actual corners and matrix at this point, + * so all we can do is get the full input image + */ + output->xmin = 0; + output->ymin = 0; + output->xmax = getInputOperation(0)->getWidth(); + output->ymax = getInputOperation(0)->getHeight(); + return true; + // return PlaneDistortWarpImageOperation::determineDependingAreaOfInterest(input, readOperation, output); } diff --git a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.h b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.h index fc22d00c0f2..444616e13f2 100644 --- a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.h +++ b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.h @@ -28,36 +28,36 @@ #include "BLI_listbase.h" #include "BLI_string.h" - class PlaneCornerPinMaskOperation : public PlaneDistortMaskOperation { -private: - bool m_corners_ready; + private: + bool m_corners_ready; -public: - PlaneCornerPinMaskOperation(); + public: + PlaneCornerPinMaskOperation(); - void initExecution(); - void deinitExecution(); + void initExecution(); + void deinitExecution(); - void *initializeTileData(rcti *rect); + void *initializeTileData(rcti *rect); - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); }; - class PlaneCornerPinWarpImageOperation : public PlaneDistortWarpImageOperation { -private: - bool m_corners_ready; + private: + bool m_corners_ready; -public: - PlaneCornerPinWarpImageOperation(); + public: + PlaneCornerPinWarpImageOperation(); - void initExecution(); - void deinitExecution(); + void initExecution(); + void deinitExecution(); - void *initializeTileData(rcti *rect); + void *initializeTileData(rcti *rect); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); }; #endif diff --git a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp index c7f60d0dac2..ef7dfbd4116 100644 --- a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp +++ b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp @@ -35,200 +35,196 @@ extern "C" { BLI_INLINE void warpCoord(float x, float y, float matrix[3][3], float uv[2], float deriv[2][2]) { - float vec[3] = {x, y, 1.0f}; - mul_m3_v3(matrix, vec); - uv[0] = vec[0] / vec[2]; - uv[1] = vec[1] / vec[2]; - - deriv[0][0] = (matrix[0][0] - matrix[0][2] * uv[0]) / vec[2]; - deriv[1][0] = (matrix[0][1] - matrix[0][2] * uv[1]) / vec[2]; - deriv[0][1] = (matrix[1][0] - matrix[1][2] * uv[0]) / vec[2]; - deriv[1][1] = (matrix[1][1] - matrix[1][2] * uv[1]) / vec[2]; + float vec[3] = {x, y, 1.0f}; + mul_m3_v3(matrix, vec); + uv[0] = vec[0] / vec[2]; + uv[1] = vec[1] / vec[2]; + + deriv[0][0] = (matrix[0][0] - matrix[0][2] * uv[0]) / vec[2]; + deriv[1][0] = (matrix[0][1] - matrix[0][2] * uv[1]) / vec[2]; + deriv[0][1] = (matrix[1][0] - matrix[1][2] * uv[0]) / vec[2]; + deriv[1][1] = (matrix[1][1] - matrix[1][2] * uv[1]) / vec[2]; } -PlaneDistortWarpImageOperation::PlaneDistortWarpImageOperation() : - NodeOperation() +PlaneDistortWarpImageOperation::PlaneDistortWarpImageOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); - this->addOutputSocket(COM_DT_COLOR); - this->m_pixelReader = NULL; - this->m_motion_blur_samples = 1; - this->m_motion_blur_shutter = 0.5f; - this->setComplex(true); + this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); + this->addOutputSocket(COM_DT_COLOR); + this->m_pixelReader = NULL; + this->m_motion_blur_samples = 1; + this->m_motion_blur_shutter = 0.5f; + this->setComplex(true); } void PlaneDistortWarpImageOperation::calculateCorners(const float corners[4][2], bool normalized, int sample) { - BLI_assert(sample < this->m_motion_blur_samples); - const int width = this->m_pixelReader->getWidth(); - const int height = this->m_pixelReader->getHeight(); - float frame_corners[4][2] = {{0.0f, 0.0f}, - {(float) width, 0.0f}, - {(float) width, (float) height}, - {0.0f, (float) height}}; - MotionSample *sample_data = &this->m_samples[sample]; - if (normalized) { - for (int i = 0; i < 4; i++) { - sample_data->frameSpaceCorners[i][0] = corners[i][0] * this->getWidth(); - sample_data->frameSpaceCorners[i][1] = corners[i][1] * this->getHeight(); - } - } - else { - for (int i = 0; i < 4; i++) { - sample_data->frameSpaceCorners[i][0] = corners[i][0]; - sample_data->frameSpaceCorners[i][1] = corners[i][1]; - } - } - BKE_tracking_homography_between_two_quads(sample_data->frameSpaceCorners, - frame_corners, - sample_data->perspectiveMatrix); + BLI_assert(sample < this->m_motion_blur_samples); + const int width = this->m_pixelReader->getWidth(); + const int height = this->m_pixelReader->getHeight(); + float frame_corners[4][2] = { + {0.0f, 0.0f}, {(float)width, 0.0f}, {(float)width, (float)height}, {0.0f, (float)height}}; + MotionSample *sample_data = &this->m_samples[sample]; + if (normalized) { + for (int i = 0; i < 4; i++) { + sample_data->frameSpaceCorners[i][0] = corners[i][0] * this->getWidth(); + sample_data->frameSpaceCorners[i][1] = corners[i][1] * this->getHeight(); + } + } + else { + for (int i = 0; i < 4; i++) { + sample_data->frameSpaceCorners[i][0] = corners[i][0]; + sample_data->frameSpaceCorners[i][1] = corners[i][1]; + } + } + BKE_tracking_homography_between_two_quads( + sample_data->frameSpaceCorners, frame_corners, sample_data->perspectiveMatrix); } void PlaneDistortWarpImageOperation::initExecution() { - this->m_pixelReader = this->getInputSocketReader(0); + this->m_pixelReader = this->getInputSocketReader(0); } void PlaneDistortWarpImageOperation::deinitExecution() { - this->m_pixelReader = NULL; + this->m_pixelReader = NULL; } -void PlaneDistortWarpImageOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) +void PlaneDistortWarpImageOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler /*sampler*/) { - float uv[2]; - float deriv[2][2]; - if (this->m_motion_blur_samples == 1) { - warpCoord(x, y, this->m_samples[0].perspectiveMatrix, uv, deriv); - m_pixelReader->readFiltered(output, - uv[0], uv[1], - deriv[0], deriv[1]); - } - else { - zero_v4(output); - for (int sample = 0; sample < this->m_motion_blur_samples; ++sample) { - float color[4]; - warpCoord(x, y, this->m_samples[sample].perspectiveMatrix, uv, deriv); - m_pixelReader->readFiltered(color, - uv[0], uv[1], - deriv[0], deriv[1]); - add_v4_v4(output, color); - } - mul_v4_fl(output, 1.0f / (float)this->m_motion_blur_samples); - } + float uv[2]; + float deriv[2][2]; + if (this->m_motion_blur_samples == 1) { + warpCoord(x, y, this->m_samples[0].perspectiveMatrix, uv, deriv); + m_pixelReader->readFiltered(output, uv[0], uv[1], deriv[0], deriv[1]); + } + else { + zero_v4(output); + for (int sample = 0; sample < this->m_motion_blur_samples; ++sample) { + float color[4]; + warpCoord(x, y, this->m_samples[sample].perspectiveMatrix, uv, deriv); + m_pixelReader->readFiltered(color, uv[0], uv[1], deriv[0], deriv[1]); + add_v4_v4(output, color); + } + mul_v4_fl(output, 1.0f / (float)this->m_motion_blur_samples); + } } -bool PlaneDistortWarpImageOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool PlaneDistortWarpImageOperation::determineDependingAreaOfInterest( + rcti *input, ReadBufferOperation *readOperation, rcti *output) { - float min[2], max[2]; - INIT_MINMAX2(min, max); - - for (int sample = 0; sample < this->m_motion_blur_samples; ++sample) { - float UVs[4][2]; - float deriv[2][2]; - MotionSample *sample_data = &this->m_samples[sample]; - /* TODO(sergey): figure out proper way to do this. */ - warpCoord(input->xmin - 2, input->ymin - 2, sample_data->perspectiveMatrix, UVs[0], deriv); - warpCoord(input->xmax + 2, input->ymin - 2, sample_data->perspectiveMatrix, UVs[1], deriv); - warpCoord(input->xmax + 2, input->ymax + 2, sample_data->perspectiveMatrix, UVs[2], deriv); - warpCoord(input->xmin - 2, input->ymax + 2, sample_data->perspectiveMatrix, UVs[3], deriv); - for (int i = 0; i < 4; i++) { - minmax_v2v2_v2(min, max, UVs[i]); - } - } - - rcti newInput; - - newInput.xmin = min[0] - 1; - newInput.ymin = min[1] - 1; - newInput.xmax = max[0] + 1; - newInput.ymax = max[1] + 1; - - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + float min[2], max[2]; + INIT_MINMAX2(min, max); + + for (int sample = 0; sample < this->m_motion_blur_samples; ++sample) { + float UVs[4][2]; + float deriv[2][2]; + MotionSample *sample_data = &this->m_samples[sample]; + /* TODO(sergey): figure out proper way to do this. */ + warpCoord(input->xmin - 2, input->ymin - 2, sample_data->perspectiveMatrix, UVs[0], deriv); + warpCoord(input->xmax + 2, input->ymin - 2, sample_data->perspectiveMatrix, UVs[1], deriv); + warpCoord(input->xmax + 2, input->ymax + 2, sample_data->perspectiveMatrix, UVs[2], deriv); + warpCoord(input->xmin - 2, input->ymax + 2, sample_data->perspectiveMatrix, UVs[3], deriv); + for (int i = 0; i < 4; i++) { + minmax_v2v2_v2(min, max, UVs[i]); + } + } + + rcti newInput; + + newInput.xmin = min[0] - 1; + newInput.ymin = min[1] - 1; + newInput.xmax = max[0] + 1; + newInput.ymax = max[1] + 1; + + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } - /* ******** PlaneDistort Mask ******** */ -PlaneDistortMaskOperation::PlaneDistortMaskOperation() : - NodeOperation() +PlaneDistortMaskOperation::PlaneDistortMaskOperation() : NodeOperation() { - addOutputSocket(COM_DT_VALUE); + addOutputSocket(COM_DT_VALUE); - /* Currently hardcoded to 8 samples. */ - m_osa = 8; - this->m_motion_blur_samples = 1; - this->m_motion_blur_shutter = 0.5f; + /* Currently hardcoded to 8 samples. */ + m_osa = 8; + this->m_motion_blur_samples = 1; + this->m_motion_blur_shutter = 0.5f; } void PlaneDistortMaskOperation::calculateCorners(const float corners[4][2], bool normalized, int sample) { - BLI_assert(sample < this->m_motion_blur_samples); - MotionSample *sample_data = &this->m_samples[sample]; - if (normalized) { - for (int i = 0; i < 4; i++) { - sample_data->frameSpaceCorners[i][0] = corners[i][0] * this->getWidth(); - sample_data->frameSpaceCorners[i][1] = corners[i][1] * this->getHeight(); - } - } - else { - for (int i = 0; i < 4; i++) { - sample_data->frameSpaceCorners[i][0] = corners[i][0]; - sample_data->frameSpaceCorners[i][1] = corners[i][1]; - } - } + BLI_assert(sample < this->m_motion_blur_samples); + MotionSample *sample_data = &this->m_samples[sample]; + if (normalized) { + for (int i = 0; i < 4; i++) { + sample_data->frameSpaceCorners[i][0] = corners[i][0] * this->getWidth(); + sample_data->frameSpaceCorners[i][1] = corners[i][1] * this->getHeight(); + } + } + else { + for (int i = 0; i < 4; i++) { + sample_data->frameSpaceCorners[i][0] = corners[i][0]; + sample_data->frameSpaceCorners[i][1] = corners[i][1]; + } + } } void PlaneDistortMaskOperation::initExecution() { - BLI_jitter_init(m_jitter, m_osa); + BLI_jitter_init(m_jitter, m_osa); } -void PlaneDistortMaskOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) +void PlaneDistortMaskOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler /*sampler*/) { - float point[2]; - int inside_counter = 0; - if (this->m_motion_blur_samples == 1) { - MotionSample *sample_data = &this->m_samples[0]; - for (int sample = 0; sample < this->m_osa; sample++) { - point[0] = x + this->m_jitter[sample][0]; - point[1] = y + this->m_jitter[sample][1]; - if (isect_point_tri_v2(point, sample_data->frameSpaceCorners[0], - sample_data->frameSpaceCorners[1], - sample_data->frameSpaceCorners[2]) || - isect_point_tri_v2(point, sample_data->frameSpaceCorners[0], - sample_data->frameSpaceCorners[2], - sample_data->frameSpaceCorners[3])) - { - inside_counter++; - } - } - output[0] = (float)inside_counter / this->m_osa; - } - else { - for (int motion_sample = 0; - motion_sample < this->m_motion_blur_samples; - ++motion_sample) - { - MotionSample *sample_data = &this->m_samples[motion_sample]; - for (int osa_sample = 0; osa_sample < this->m_osa; ++osa_sample) { - point[0] = x + this->m_jitter[osa_sample][0]; - point[1] = y + this->m_jitter[osa_sample][1]; - if (isect_point_tri_v2(point, sample_data->frameSpaceCorners[0], - sample_data->frameSpaceCorners[1], - sample_data->frameSpaceCorners[2]) || - isect_point_tri_v2(point, sample_data->frameSpaceCorners[0], - sample_data->frameSpaceCorners[2], - sample_data->frameSpaceCorners[3])) - { - inside_counter++; - } - } - } - output[0] = (float)inside_counter / (this->m_osa * this->m_motion_blur_samples); - } + float point[2]; + int inside_counter = 0; + if (this->m_motion_blur_samples == 1) { + MotionSample *sample_data = &this->m_samples[0]; + for (int sample = 0; sample < this->m_osa; sample++) { + point[0] = x + this->m_jitter[sample][0]; + point[1] = y + this->m_jitter[sample][1]; + if (isect_point_tri_v2(point, + sample_data->frameSpaceCorners[0], + sample_data->frameSpaceCorners[1], + sample_data->frameSpaceCorners[2]) || + isect_point_tri_v2(point, + sample_data->frameSpaceCorners[0], + sample_data->frameSpaceCorners[2], + sample_data->frameSpaceCorners[3])) { + inside_counter++; + } + } + output[0] = (float)inside_counter / this->m_osa; + } + else { + for (int motion_sample = 0; motion_sample < this->m_motion_blur_samples; ++motion_sample) { + MotionSample *sample_data = &this->m_samples[motion_sample]; + for (int osa_sample = 0; osa_sample < this->m_osa; ++osa_sample) { + point[0] = x + this->m_jitter[osa_sample][0]; + point[1] = y + this->m_jitter[osa_sample][1]; + if (isect_point_tri_v2(point, + sample_data->frameSpaceCorners[0], + sample_data->frameSpaceCorners[1], + sample_data->frameSpaceCorners[2]) || + isect_point_tri_v2(point, + sample_data->frameSpaceCorners[0], + sample_data->frameSpaceCorners[2], + sample_data->frameSpaceCorners[3])) { + inside_counter++; + } + } + } + output[0] = (float)inside_counter / (this->m_osa * this->m_motion_blur_samples); + } } diff --git a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h index 216f4ed969d..35e7745cb5d 100644 --- a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h +++ b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h @@ -32,69 +32,70 @@ #define PLANE_DISTORT_MAX_SAMPLES 64 class PlaneDistortWarpImageOperation : public NodeOperation { -protected: - struct MotionSample { - float frameSpaceCorners[4][2]; /* Corners coordinates in pixel space. */ - float perspectiveMatrix[3][3]; - }; - SocketReader *m_pixelReader; - MotionSample m_samples[PLANE_DISTORT_MAX_SAMPLES]; - int m_motion_blur_samples; - float m_motion_blur_shutter; - -public: - PlaneDistortWarpImageOperation(); - - void calculateCorners(const float corners[4][2], - bool normalized, - int sample); - - void initExecution(); - void deinitExecution(); - - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - - void setMotionBlurSamples(int samples) { - BLI_assert(samples <= PLANE_DISTORT_MAX_SAMPLES); - this->m_motion_blur_samples = samples; - } - void setMotionBlurShutter(float shutter) { - this->m_motion_blur_shutter = shutter; - } + protected: + struct MotionSample { + float frameSpaceCorners[4][2]; /* Corners coordinates in pixel space. */ + float perspectiveMatrix[3][3]; + }; + SocketReader *m_pixelReader; + MotionSample m_samples[PLANE_DISTORT_MAX_SAMPLES]; + int m_motion_blur_samples; + float m_motion_blur_shutter; + + public: + PlaneDistortWarpImageOperation(); + + void calculateCorners(const float corners[4][2], bool normalized, int sample); + + void initExecution(); + void deinitExecution(); + + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + + void setMotionBlurSamples(int samples) + { + BLI_assert(samples <= PLANE_DISTORT_MAX_SAMPLES); + this->m_motion_blur_samples = samples; + } + void setMotionBlurShutter(float shutter) + { + this->m_motion_blur_shutter = shutter; + } }; - class PlaneDistortMaskOperation : public NodeOperation { -protected: - struct MotionSample { - float frameSpaceCorners[4][2]; /* Corners coordinates in pixel space. */ - }; - int m_osa; - MotionSample m_samples[PLANE_DISTORT_MAX_SAMPLES]; - float m_jitter[32][2]; - int m_motion_blur_samples; - float m_motion_blur_shutter; - -public: - PlaneDistortMaskOperation(); - - void calculateCorners(const float corners[4][2], - bool normalized, - int sample); - - void initExecution(); - - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - - void setMotionBlurSamples(int samples) { - BLI_assert(samples <= PLANE_DISTORT_MAX_SAMPLES); - this->m_motion_blur_samples = samples; - } - void setMotionBlurShutter(float shutter) { - this->m_motion_blur_shutter = shutter; - } + protected: + struct MotionSample { + float frameSpaceCorners[4][2]; /* Corners coordinates in pixel space. */ + }; + int m_osa; + MotionSample m_samples[PLANE_DISTORT_MAX_SAMPLES]; + float m_jitter[32][2]; + int m_motion_blur_samples; + float m_motion_blur_shutter; + + public: + PlaneDistortMaskOperation(); + + void calculateCorners(const float corners[4][2], bool normalized, int sample); + + void initExecution(); + + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + + void setMotionBlurSamples(int samples) + { + BLI_assert(samples <= PLANE_DISTORT_MAX_SAMPLES); + this->m_motion_blur_samples = samples; + } + void setMotionBlurShutter(float shutter) + { + this->m_motion_blur_shutter = shutter; + } }; #endif diff --git a/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp b/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp index b134bc9ef9e..76ecabb8c8b 100644 --- a/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp +++ b/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp @@ -26,103 +26,99 @@ #include "BLI_math_color.h" extern "C" { -# include "BKE_movieclip.h" -# include "BKE_node.h" -# include "BKE_tracking.h" +#include "BKE_movieclip.h" +#include "BKE_node.h" +#include "BKE_tracking.h" } /* ******** PlaneTrackCommon ******** */ PlaneTrackCommon::PlaneTrackCommon() { - this->m_movieClip = NULL; - this->m_framenumber = 0; - this->m_trackingObjectName[0] = '\0'; - this->m_planeTrackName[0] = '\0'; + this->m_movieClip = NULL; + this->m_framenumber = 0; + this->m_trackingObjectName[0] = '\0'; + this->m_planeTrackName[0] = '\0'; } void PlaneTrackCommon::readCornersFromTrack(float corners[4][2], float frame) { - MovieTracking *tracking; - MovieTrackingObject *object; - - if (!this->m_movieClip) - return; - - tracking = &this->m_movieClip->tracking; - - object = BKE_tracking_object_get_named(tracking, this->m_trackingObjectName); - if (object) { - MovieTrackingPlaneTrack *plane_track; - plane_track = BKE_tracking_plane_track_get_named(tracking, object, this->m_planeTrackName); - if (plane_track) { - float clip_framenr = - BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, - frame); - BKE_tracking_plane_marker_get_subframe_corners(plane_track, - clip_framenr, - corners); - } - } + MovieTracking *tracking; + MovieTrackingObject *object; + + if (!this->m_movieClip) + return; + + tracking = &this->m_movieClip->tracking; + + object = BKE_tracking_object_get_named(tracking, this->m_trackingObjectName); + if (object) { + MovieTrackingPlaneTrack *plane_track; + plane_track = BKE_tracking_plane_track_get_named(tracking, object, this->m_planeTrackName); + if (plane_track) { + float clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, frame); + BKE_tracking_plane_marker_get_subframe_corners(plane_track, clip_framenr, corners); + } + } } -void PlaneTrackCommon::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2]) +void PlaneTrackCommon::determineResolution(unsigned int resolution[2], + unsigned int /*preferredResolution*/[2]) { - resolution[0] = 0; - resolution[1] = 0; - - if (this->m_movieClip) { - int width, height; - MovieClipUser user = {0}; - BKE_movieclip_user_set_frame(&user, this->m_framenumber); - BKE_movieclip_get_size(this->m_movieClip, &user, &width, &height); - resolution[0] = width; - resolution[1] = height; - } + resolution[0] = 0; + resolution[1] = 0; + + if (this->m_movieClip) { + int width, height; + MovieClipUser user = {0}; + BKE_movieclip_user_set_frame(&user, this->m_framenumber); + BKE_movieclip_get_size(this->m_movieClip, &user, &width, &height); + resolution[0] = width; + resolution[1] = height; + } } - /* ******** PlaneTrackMaskOperation ******** */ void PlaneTrackMaskOperation::initExecution() { - PlaneDistortMaskOperation::initExecution(); - float corners[4][2]; - if (this->m_motion_blur_samples == 1) { - readCornersFromTrack(corners, this->m_framenumber); - calculateCorners(corners, true, 0); - } - else { - const float frame = (float)this->m_framenumber - this->m_motion_blur_shutter; - const float frame_step = (this->m_motion_blur_shutter * 2.0f) / this->m_motion_blur_samples; - float frame_iter = frame; - for (int sample = 0; sample < this->m_motion_blur_samples; ++sample) { - readCornersFromTrack(corners, frame_iter); - calculateCorners(corners, true, sample); - frame_iter += frame_step; - } - } + PlaneDistortMaskOperation::initExecution(); + float corners[4][2]; + if (this->m_motion_blur_samples == 1) { + readCornersFromTrack(corners, this->m_framenumber); + calculateCorners(corners, true, 0); + } + else { + const float frame = (float)this->m_framenumber - this->m_motion_blur_shutter; + const float frame_step = (this->m_motion_blur_shutter * 2.0f) / this->m_motion_blur_samples; + float frame_iter = frame; + for (int sample = 0; sample < this->m_motion_blur_samples; ++sample) { + readCornersFromTrack(corners, frame_iter); + calculateCorners(corners, true, sample); + frame_iter += frame_step; + } + } } /* ******** PlaneTrackWarpImageOperation ******** */ void PlaneTrackWarpImageOperation::initExecution() { - PlaneDistortWarpImageOperation::initExecution(); - /* TODO(sergey): De-duplicate with mask operation. */ - float corners[4][2]; - if (this->m_motion_blur_samples == 1) { - readCornersFromTrack(corners, this->m_framenumber); - calculateCorners(corners, true, 0); - } - else { - const float frame = (float)this->m_framenumber - this->m_motion_blur_shutter; - const float frame_step = (this->m_motion_blur_shutter * 2.0f) / this->m_motion_blur_samples; - float frame_iter = frame; - for (int sample = 0; sample < this->m_motion_blur_samples; ++sample) { - readCornersFromTrack(corners, frame_iter); - calculateCorners(corners, true, sample); - frame_iter += frame_step; - } - } + PlaneDistortWarpImageOperation::initExecution(); + /* TODO(sergey): De-duplicate with mask operation. */ + float corners[4][2]; + if (this->m_motion_blur_samples == 1) { + readCornersFromTrack(corners, this->m_framenumber); + calculateCorners(corners, true, 0); + } + else { + const float frame = (float)this->m_framenumber - this->m_motion_blur_shutter; + const float frame_step = (this->m_motion_blur_shutter * 2.0f) / this->m_motion_blur_samples; + float frame_iter = frame; + for (int sample = 0; sample < this->m_motion_blur_samples; ++sample) { + readCornersFromTrack(corners, frame_iter); + calculateCorners(corners, true, sample); + frame_iter += frame_step; + } + } } diff --git a/source/blender/compositor/operations/COM_PlaneTrackOperation.h b/source/blender/compositor/operations/COM_PlaneTrackOperation.h index 217f6dc92c1..875c8ce8fa0 100644 --- a/source/blender/compositor/operations/COM_PlaneTrackOperation.h +++ b/source/blender/compositor/operations/COM_PlaneTrackOperation.h @@ -30,62 +30,71 @@ #include "BLI_string.h" class PlaneTrackCommon { -protected: - MovieClip *m_movieClip; - int m_framenumber; - char m_trackingObjectName[64]; - char m_planeTrackName[64]; - - /* note: this class is not an operation itself (to prevent virtual inheritance issues) - * implementation classes must make wrappers to use these methods, see below. - */ - void readCornersFromTrack(float corners[4][2], float frame); - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); - -public: - PlaneTrackCommon(); - - void setMovieClip(MovieClip *clip) {this->m_movieClip = clip;} - void setTrackingObject(char *object) { BLI_strncpy(this->m_trackingObjectName, object, sizeof(this->m_trackingObjectName)); } - void setPlaneTrackName(char *plane_track) { BLI_strncpy(this->m_planeTrackName, plane_track, sizeof(this->m_planeTrackName)); } - void setFramenumber(int framenumber) { this->m_framenumber = framenumber; } + protected: + MovieClip *m_movieClip; + int m_framenumber; + char m_trackingObjectName[64]; + char m_planeTrackName[64]; + + /* note: this class is not an operation itself (to prevent virtual inheritance issues) + * implementation classes must make wrappers to use these methods, see below. + */ + void readCornersFromTrack(float corners[4][2], float frame); + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); + + public: + PlaneTrackCommon(); + + void setMovieClip(MovieClip *clip) + { + this->m_movieClip = clip; + } + void setTrackingObject(char *object) + { + BLI_strncpy(this->m_trackingObjectName, object, sizeof(this->m_trackingObjectName)); + } + void setPlaneTrackName(char *plane_track) + { + BLI_strncpy(this->m_planeTrackName, plane_track, sizeof(this->m_planeTrackName)); + } + void setFramenumber(int framenumber) + { + this->m_framenumber = framenumber; + } }; - class PlaneTrackMaskOperation : public PlaneDistortMaskOperation, public PlaneTrackCommon { -public: - PlaneTrackMaskOperation() : - PlaneDistortMaskOperation(), - PlaneTrackCommon() - {} + public: + PlaneTrackMaskOperation() : PlaneDistortMaskOperation(), PlaneTrackCommon() + { + } - void initExecution(); + void initExecution(); - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) - { - PlaneTrackCommon::determineResolution(resolution, preferredResolution); + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) + { + PlaneTrackCommon::determineResolution(resolution, preferredResolution); - unsigned int temp[2]; - NodeOperation::determineResolution(temp, resolution); - } + unsigned int temp[2]; + NodeOperation::determineResolution(temp, resolution); + } }; - -class PlaneTrackWarpImageOperation : public PlaneDistortWarpImageOperation, public PlaneTrackCommon { -public: - PlaneTrackWarpImageOperation() : - PlaneDistortWarpImageOperation(), - PlaneTrackCommon() - {} - - void initExecution(); - - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) - { - PlaneTrackCommon::determineResolution(resolution, preferredResolution); - unsigned int temp[2]; - NodeOperation::determineResolution(temp, resolution); - } +class PlaneTrackWarpImageOperation : public PlaneDistortWarpImageOperation, + public PlaneTrackCommon { + public: + PlaneTrackWarpImageOperation() : PlaneDistortWarpImageOperation(), PlaneTrackCommon() + { + } + + void initExecution(); + + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) + { + PlaneTrackCommon::determineResolution(resolution, preferredResolution); + unsigned int temp[2]; + NodeOperation::determineResolution(temp, resolution); + } }; #endif diff --git a/source/blender/compositor/operations/COM_PreviewOperation.cpp b/source/blender/compositor/operations/COM_PreviewOperation.cpp index 22215131ce1..cd2bb3b2928 100644 --- a/source/blender/compositor/operations/COM_PreviewOperation.cpp +++ b/source/blender/compositor/operations/COM_PreviewOperation.cpp @@ -27,118 +27,123 @@ #include "COM_defines.h" #include "BLI_math.h" extern "C" { -# include "MEM_guardedalloc.h" -# include "IMB_imbuf.h" -# include "IMB_imbuf_types.h" -# include "IMB_colormanagement.h" -# include "BKE_node.h" +#include "MEM_guardedalloc.h" +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" +#include "IMB_colormanagement.h" +#include "BKE_node.h" } - -PreviewOperation::PreviewOperation(const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings) : NodeOperation() +PreviewOperation::PreviewOperation(const ColorManagedViewSettings *viewSettings, + const ColorManagedDisplaySettings *displaySettings) + : NodeOperation() { - this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); - this->m_preview = NULL; - this->m_outputBuffer = NULL; - this->m_input = NULL; - this->m_divider = 1.0f; - this->m_viewSettings = viewSettings; - this->m_displaySettings = displaySettings; + this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); + this->m_preview = NULL; + this->m_outputBuffer = NULL; + this->m_input = NULL; + this->m_divider = 1.0f; + this->m_viewSettings = viewSettings; + this->m_displaySettings = displaySettings; } void PreviewOperation::verifyPreview(bNodeInstanceHash *previews, bNodeInstanceKey key) { - /* Size (0, 0) ensures the preview rect is not allocated in advance, - * this is set later in initExecution once the resolution is determined. - */ - this->m_preview = BKE_node_preview_verify(previews, key, 0, 0, true); + /* Size (0, 0) ensures the preview rect is not allocated in advance, + * this is set later in initExecution once the resolution is determined. + */ + this->m_preview = BKE_node_preview_verify(previews, key, 0, 0, true); } void PreviewOperation::initExecution() { - this->m_input = getInputSocketReader(0); - - if (this->getWidth() == (unsigned int)this->m_preview->xsize && - this->getHeight() == (unsigned int)this->m_preview->ysize) - { - this->m_outputBuffer = this->m_preview->rect; - } - - if (this->m_outputBuffer == NULL) { - this->m_outputBuffer = (unsigned char *)MEM_callocN(sizeof(unsigned char) * 4 * getWidth() * getHeight(), "PreviewOperation"); - if (this->m_preview->rect) { - MEM_freeN(this->m_preview->rect); - } - this->m_preview->xsize = getWidth(); - this->m_preview->ysize = getHeight(); - this->m_preview->rect = this->m_outputBuffer; - } + this->m_input = getInputSocketReader(0); + + if (this->getWidth() == (unsigned int)this->m_preview->xsize && + this->getHeight() == (unsigned int)this->m_preview->ysize) { + this->m_outputBuffer = this->m_preview->rect; + } + + if (this->m_outputBuffer == NULL) { + this->m_outputBuffer = (unsigned char *)MEM_callocN( + sizeof(unsigned char) * 4 * getWidth() * getHeight(), "PreviewOperation"); + if (this->m_preview->rect) { + MEM_freeN(this->m_preview->rect); + } + this->m_preview->xsize = getWidth(); + this->m_preview->ysize = getHeight(); + this->m_preview->rect = this->m_outputBuffer; + } } void PreviewOperation::deinitExecution() { - this->m_outputBuffer = NULL; - this->m_input = NULL; + this->m_outputBuffer = NULL; + this->m_input = NULL; } void PreviewOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/) { - int offset; - float color[4]; - struct ColormanageProcessor *cm_processor; - - cm_processor = IMB_colormanagement_display_processor_new(this->m_viewSettings, this->m_displaySettings); - - for (int y = rect->ymin; y < rect->ymax; y++) { - offset = (y * getWidth() + rect->xmin) * 4; - for (int x = rect->xmin; x < rect->xmax; x++) { - float rx = floor(x / this->m_divider); - float ry = floor(y / this->m_divider); - - color[0] = 0.0f; - color[1] = 0.0f; - color[2] = 0.0f; - color[3] = 1.0f; - this->m_input->readSampled(color, rx, ry, COM_PS_NEAREST); - IMB_colormanagement_processor_apply_v4(cm_processor, color); - rgba_float_to_uchar(this->m_outputBuffer + offset, color); - offset += 4; - } - } - - IMB_colormanagement_processor_free(cm_processor); + int offset; + float color[4]; + struct ColormanageProcessor *cm_processor; + + cm_processor = IMB_colormanagement_display_processor_new(this->m_viewSettings, + this->m_displaySettings); + + for (int y = rect->ymin; y < rect->ymax; y++) { + offset = (y * getWidth() + rect->xmin) * 4; + for (int x = rect->xmin; x < rect->xmax; x++) { + float rx = floor(x / this->m_divider); + float ry = floor(y / this->m_divider); + + color[0] = 0.0f; + color[1] = 0.0f; + color[2] = 0.0f; + color[3] = 1.0f; + this->m_input->readSampled(color, rx, ry, COM_PS_NEAREST); + IMB_colormanagement_processor_apply_v4(cm_processor, color); + rgba_float_to_uchar(this->m_outputBuffer + offset, color); + offset += 4; + } + } + + IMB_colormanagement_processor_free(cm_processor); } -bool PreviewOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool PreviewOperation::determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output) { - rcti newInput; + rcti newInput; - newInput.xmin = input->xmin / this->m_divider; - newInput.xmax = input->xmax / this->m_divider; - newInput.ymin = input->ymin / this->m_divider; - newInput.ymax = input->ymax / this->m_divider; + newInput.xmin = input->xmin / this->m_divider; + newInput.xmax = input->xmax / this->m_divider; + newInput.ymin = input->ymin / this->m_divider; + newInput.ymax = input->ymax / this->m_divider; - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } -void PreviewOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +void PreviewOperation::determineResolution(unsigned int resolution[2], + unsigned int preferredResolution[2]) { - NodeOperation::determineResolution(resolution, preferredResolution); - int width = resolution[0]; - int height = resolution[1]; - this->m_divider = 0.0f; - if (width > height) { - this->m_divider = COM_PREVIEW_SIZE / (width - 1); - } - else { - this->m_divider = COM_PREVIEW_SIZE / (height - 1); - } - width = width * this->m_divider; - height = height * this->m_divider; - - resolution[0] = width; - resolution[1] = height; + NodeOperation::determineResolution(resolution, preferredResolution); + int width = resolution[0]; + int height = resolution[1]; + this->m_divider = 0.0f; + if (width > height) { + this->m_divider = COM_PREVIEW_SIZE / (width - 1); + } + else { + this->m_divider = COM_PREVIEW_SIZE / (height - 1); + } + width = width * this->m_divider; + height = height * this->m_divider; + + resolution[0] = width; + resolution[1] = height; } CompositorPriority PreviewOperation::getRenderPriority() const { - return COM_PRIORITY_LOW; + return COM_PRIORITY_LOW; } diff --git a/source/blender/compositor/operations/COM_PreviewOperation.h b/source/blender/compositor/operations/COM_PreviewOperation.h index 76b03b09731..6560db727a8 100644 --- a/source/blender/compositor/operations/COM_PreviewOperation.h +++ b/source/blender/compositor/operations/COM_PreviewOperation.h @@ -25,31 +25,40 @@ #include "BKE_global.h" class PreviewOperation : public NodeOperation { -protected: - unsigned char *m_outputBuffer; + protected: + unsigned char *m_outputBuffer; - /** - * \brief holds reference to the SDNA bNode, where this nodes will render the preview image for - */ - bNodePreview *m_preview; - SocketReader *m_input; - float m_divider; + /** + * \brief holds reference to the SDNA bNode, where this nodes will render the preview image for + */ + bNodePreview *m_preview; + SocketReader *m_input; + float m_divider; - const ColorManagedViewSettings *m_viewSettings; - const ColorManagedDisplaySettings *m_displaySettings; -public: - PreviewOperation(const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings); - void verifyPreview(bNodeInstanceHash *previews, bNodeInstanceKey key); + const ColorManagedViewSettings *m_viewSettings; + const ColorManagedDisplaySettings *m_displaySettings; - bool isOutputOperation(bool /*rendering*/) const { return !G.background; } - void initExecution(); - void deinitExecution(); - CompositorPriority getRenderPriority() const; + public: + PreviewOperation(const ColorManagedViewSettings *viewSettings, + const ColorManagedDisplaySettings *displaySettings); + void verifyPreview(bNodeInstanceHash *previews, bNodeInstanceKey key); - void executeRegion(rcti *rect, unsigned int tileNumber); - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - bool isPreviewOperation() const { return true; } + bool isOutputOperation(bool /*rendering*/) const + { + return !G.background; + } + void initExecution(); + void deinitExecution(); + CompositorPriority getRenderPriority() const; + void executeRegion(rcti *rect, unsigned int tileNumber); + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + bool isPreviewOperation() const + { + return true; + } }; #endif diff --git a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp index fa02f0f3356..40299d33306 100644 --- a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp @@ -22,87 +22,91 @@ ProjectorLensDistortionOperation::ProjectorLensDistortionOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_COLOR); - this->setComplex(true); - this->m_inputProgram = NULL; - this->m_dispersionAvailable = false; - this->m_dispersion = 0.0f; + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_COLOR); + this->setComplex(true); + this->m_inputProgram = NULL; + this->m_dispersionAvailable = false; + this->m_dispersion = 0.0f; } void ProjectorLensDistortionOperation::initExecution() { - this->initMutex(); - this->m_inputProgram = this->getInputSocketReader(0); + this->initMutex(); + this->m_inputProgram = this->getInputSocketReader(0); } void *ProjectorLensDistortionOperation::initializeTileData(rcti * /*rect*/) { - updateDispersion(); - void *buffer = this->m_inputProgram->initializeTileData(NULL); - return buffer; + updateDispersion(); + void *buffer = this->m_inputProgram->initializeTileData(NULL); + return buffer; } void ProjectorLensDistortionOperation::executePixel(float output[4], int x, int y, void *data) { - float inputValue[4]; - const float height = this->getHeight(); - const float width = this->getWidth(); - const float v = (y + 0.5f) / height; - const float u = (x + 0.5f) / width; - MemoryBuffer *inputBuffer = (MemoryBuffer *)data; - inputBuffer->readBilinear(inputValue, (u * width + this->m_kr2) - 0.5f, v * height - 0.5f); - output[0] = inputValue[0]; - inputBuffer->read(inputValue, x, y); - output[1] = inputValue[1]; - inputBuffer->readBilinear(inputValue, (u * width - this->m_kr2) - 0.5f, v * height - 0.5f); - output[2] = inputValue[2]; - output[3] = 1.0f; + float inputValue[4]; + const float height = this->getHeight(); + const float width = this->getWidth(); + const float v = (y + 0.5f) / height; + const float u = (x + 0.5f) / width; + MemoryBuffer *inputBuffer = (MemoryBuffer *)data; + inputBuffer->readBilinear(inputValue, (u * width + this->m_kr2) - 0.5f, v * height - 0.5f); + output[0] = inputValue[0]; + inputBuffer->read(inputValue, x, y); + output[1] = inputValue[1]; + inputBuffer->readBilinear(inputValue, (u * width - this->m_kr2) - 0.5f, v * height - 0.5f); + output[2] = inputValue[2]; + output[3] = 1.0f; } void ProjectorLensDistortionOperation::deinitExecution() { - this->deinitMutex(); - this->m_inputProgram = NULL; + this->deinitMutex(); + this->m_inputProgram = NULL; } -bool ProjectorLensDistortionOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool ProjectorLensDistortionOperation::determineDependingAreaOfInterest( + rcti *input, ReadBufferOperation *readOperation, rcti *output) { - rcti newInput; - if (this->m_dispersionAvailable) { - newInput.ymax = input->ymax; - newInput.ymin = input->ymin; - newInput.xmin = input->xmin - this->m_kr2 - 2; - newInput.xmax = input->xmax + this->m_kr2 + 2; - } - else { - rcti dispInput; - BLI_rcti_init(&dispInput, 0, 5, 0, 5); - if (this->getInputOperation(1)->determineDependingAreaOfInterest(&dispInput, readOperation, output)) { - return true; - } - newInput.xmin = input->xmin - 7; /* (0.25f * 20 * 1) + 2 == worse case dispersion */ - newInput.ymin = input->ymin; - newInput.ymax = input->ymax; - newInput.xmax = input->xmax + 7; /* (0.25f * 20 * 1) + 2 == worse case dispersion */ - } - if (this->getInputOperation(0)->determineDependingAreaOfInterest(&newInput, readOperation, output)) { - return true; - } - return false; + rcti newInput; + if (this->m_dispersionAvailable) { + newInput.ymax = input->ymax; + newInput.ymin = input->ymin; + newInput.xmin = input->xmin - this->m_kr2 - 2; + newInput.xmax = input->xmax + this->m_kr2 + 2; + } + else { + rcti dispInput; + BLI_rcti_init(&dispInput, 0, 5, 0, 5); + if (this->getInputOperation(1)->determineDependingAreaOfInterest( + &dispInput, readOperation, output)) { + return true; + } + newInput.xmin = input->xmin - 7; /* (0.25f * 20 * 1) + 2 == worse case dispersion */ + newInput.ymin = input->ymin; + newInput.ymax = input->ymax; + newInput.xmax = input->xmax + 7; /* (0.25f * 20 * 1) + 2 == worse case dispersion */ + } + if (this->getInputOperation(0)->determineDependingAreaOfInterest( + &newInput, readOperation, output)) { + return true; + } + return false; } void ProjectorLensDistortionOperation::updateDispersion() { - if (this->m_dispersionAvailable) return; - this->lockMutex(); - if (!this->m_dispersionAvailable) { - float result[4]; - this->getInputSocketReader(1)->readSampled(result, 1, 1, COM_PS_NEAREST); - this->m_dispersion = result[0]; - this->m_kr = 0.25f * max_ff(min_ff(this->m_dispersion, 1.0f), 0.0f); - this->m_kr2 = this->m_kr * 20; - this->m_dispersionAvailable = true; - } - this->unlockMutex(); + if (this->m_dispersionAvailable) + return; + this->lockMutex(); + if (!this->m_dispersionAvailable) { + float result[4]; + this->getInputSocketReader(1)->readSampled(result, 1, 1, COM_PS_NEAREST); + this->m_dispersion = result[0]; + this->m_kr = 0.25f * max_ff(min_ff(this->m_dispersion, 1.0f), 0.0f); + this->m_kr2 = this->m_kr * 20; + this->m_dispersionAvailable = true; + } + this->unlockMutex(); } diff --git a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h index b37bd2ab182..3574f40e3bb 100644 --- a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h +++ b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h @@ -22,38 +22,40 @@ #include "DNA_node_types.h" class ProjectorLensDistortionOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputProgram; + private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputProgram; - float m_dispersion; - bool m_dispersionAvailable; + float m_dispersion; + bool m_dispersionAvailable; - float m_kr, m_kr2; -public: - ProjectorLensDistortionOperation(); + float m_kr, m_kr2; - /** - * the inner loop of this program - */ - void executePixel(float output[4], int x, int y, void *data); + public: + ProjectorLensDistortionOperation(); - /** - * Initialize the execution - */ - void initExecution(); + /** + * the inner loop of this program + */ + void executePixel(float output[4], int x, int y, void *data); - void *initializeTileData(rcti *rect); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Initialize the execution + */ + void initExecution(); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + void *initializeTileData(rcti *rect); + /** + * Deinitialize the execution + */ + void deinitExecution(); - void updateDispersion(); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + void updateDispersion(); }; #endif diff --git a/source/blender/compositor/operations/COM_QualityStepHelper.cpp b/source/blender/compositor/operations/COM_QualityStepHelper.cpp index f7af97bb80a..3eb8d528f7a 100644 --- a/source/blender/compositor/operations/COM_QualityStepHelper.cpp +++ b/source/blender/compositor/operations/COM_QualityStepHelper.cpp @@ -20,47 +20,47 @@ QualityStepHelper::QualityStepHelper() { - this->m_quality = COM_QUALITY_HIGH; - this->m_step = 1; - this->m_offsetadd = 4; + this->m_quality = COM_QUALITY_HIGH; + this->m_step = 1; + this->m_offsetadd = 4; } void QualityStepHelper::initExecution(QualityHelper helper) { - switch (helper) { - case COM_QH_INCREASE: - switch (this->m_quality) { - case COM_QUALITY_HIGH: - default: - this->m_step = 1; - this->m_offsetadd = 1; - break; - case COM_QUALITY_MEDIUM: - this->m_step = 2; - this->m_offsetadd = 2; - break; - case COM_QUALITY_LOW: - this->m_step = 3; - this->m_offsetadd = 3; - break; - } - break; - case COM_QH_MULTIPLY: - switch (this->m_quality) { - case COM_QUALITY_HIGH: - default: - this->m_step = 1; - this->m_offsetadd = 4; - break; - case COM_QUALITY_MEDIUM: - this->m_step = 2; - this->m_offsetadd = 8; - break; - case COM_QUALITY_LOW: - this->m_step = 4; - this->m_offsetadd = 16; - break; - } - break; - } + switch (helper) { + case COM_QH_INCREASE: + switch (this->m_quality) { + case COM_QUALITY_HIGH: + default: + this->m_step = 1; + this->m_offsetadd = 1; + break; + case COM_QUALITY_MEDIUM: + this->m_step = 2; + this->m_offsetadd = 2; + break; + case COM_QUALITY_LOW: + this->m_step = 3; + this->m_offsetadd = 3; + break; + } + break; + case COM_QH_MULTIPLY: + switch (this->m_quality) { + case COM_QUALITY_HIGH: + default: + this->m_step = 1; + this->m_offsetadd = 4; + break; + case COM_QUALITY_MEDIUM: + this->m_step = 2; + this->m_offsetadd = 8; + break; + case COM_QUALITY_LOW: + this->m_step = 4; + this->m_offsetadd = 16; + break; + } + break; + } } diff --git a/source/blender/compositor/operations/COM_QualityStepHelper.h b/source/blender/compositor/operations/COM_QualityStepHelper.h index 9cc971f1fe0..0814f5cdb4c 100644 --- a/source/blender/compositor/operations/COM_QualityStepHelper.h +++ b/source/blender/compositor/operations/COM_QualityStepHelper.h @@ -21,29 +21,37 @@ #include "COM_defines.h" typedef enum QualityHelper { - COM_QH_INCREASE, - COM_QH_MULTIPLY, + COM_QH_INCREASE, + COM_QH_MULTIPLY, } QualityHelper; -class QualityStepHelper { -private: - CompositorQuality m_quality; - int m_step; - int m_offsetadd; - -protected: - /** - * Initialize the execution - */ - void initExecution(QualityHelper helper); - - inline int getStep() const { return this->m_step; } - inline int getOffsetAdd() const { return this->m_offsetadd; } - -public: - QualityStepHelper(); - - - void setQuality(CompositorQuality quality) { this->m_quality = quality; } +class QualityStepHelper { + private: + CompositorQuality m_quality; + int m_step; + int m_offsetadd; + + protected: + /** + * Initialize the execution + */ + void initExecution(QualityHelper helper); + + inline int getStep() const + { + return this->m_step; + } + inline int getOffsetAdd() const + { + return this->m_offsetadd; + } + + public: + QualityStepHelper(); + + void setQuality(CompositorQuality quality) + { + this->m_quality = quality; + } }; #endif diff --git a/source/blender/compositor/operations/COM_ReadBufferOperation.cpp b/source/blender/compositor/operations/COM_ReadBufferOperation.cpp index 0901fe418f8..70aaab560cd 100644 --- a/source/blender/compositor/operations/COM_ReadBufferOperation.cpp +++ b/source/blender/compositor/operations/COM_ReadBufferOperation.cpp @@ -22,102 +22,112 @@ ReadBufferOperation::ReadBufferOperation(DataType datatype) : NodeOperation() { - this->addOutputSocket(datatype); - this->m_single_value = false; - this->m_offset = 0; - this->m_buffer = NULL; + this->addOutputSocket(datatype); + this->m_single_value = false; + this->m_offset = 0; + this->m_buffer = NULL; } void *ReadBufferOperation::initializeTileData(rcti * /*rect*/) { - return m_buffer; + return m_buffer; } -void ReadBufferOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +void ReadBufferOperation::determineResolution(unsigned int resolution[2], + unsigned int preferredResolution[2]) { - if (this->m_memoryProxy != NULL) { - WriteBufferOperation *operation = this->m_memoryProxy->getWriteBufferOperation(); - operation->determineResolution(resolution, preferredResolution); - operation->setResolution(resolution); + if (this->m_memoryProxy != NULL) { + WriteBufferOperation *operation = this->m_memoryProxy->getWriteBufferOperation(); + operation->determineResolution(resolution, preferredResolution); + operation->setResolution(resolution); - /// \todo: may not occur!, but does with blur node - if (this->m_memoryProxy->getExecutor()) { - this->m_memoryProxy->getExecutor()->setResolution(resolution); - } + /// \todo: may not occur!, but does with blur node + if (this->m_memoryProxy->getExecutor()) { + this->m_memoryProxy->getExecutor()->setResolution(resolution); + } - m_single_value = operation->isSingleValue(); - } + m_single_value = operation->isSingleValue(); + } } -void ReadBufferOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ReadBufferOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - if (m_single_value) { - /* write buffer has a single value stored at (0,0) */ - m_buffer->read(output, 0, 0); - } - else { - switch (sampler) { - case COM_PS_NEAREST: - m_buffer->read(output, x, y); - break; - case COM_PS_BILINEAR: - default: - m_buffer->readBilinear(output, x, y); - break; - case COM_PS_BICUBIC: - m_buffer->readBilinear(output, x, y); - break; - } - } + if (m_single_value) { + /* write buffer has a single value stored at (0,0) */ + m_buffer->read(output, 0, 0); + } + else { + switch (sampler) { + case COM_PS_NEAREST: + m_buffer->read(output, x, y); + break; + case COM_PS_BILINEAR: + default: + m_buffer->readBilinear(output, x, y); + break; + case COM_PS_BICUBIC: + m_buffer->readBilinear(output, x, y); + break; + } + } } -void ReadBufferOperation::executePixelExtend(float output[4], float x, float y, PixelSampler sampler, - MemoryBufferExtend extend_x, MemoryBufferExtend extend_y) +void ReadBufferOperation::executePixelExtend(float output[4], + float x, + float y, + PixelSampler sampler, + MemoryBufferExtend extend_x, + MemoryBufferExtend extend_y) { - if (m_single_value) { - /* write buffer has a single value stored at (0,0) */ - m_buffer->read(output, 0, 0); - } - else if (sampler == COM_PS_NEAREST) { - m_buffer->read(output, x, y, extend_x, extend_y); - } - else { - m_buffer->readBilinear(output, x, y, extend_x, extend_y); - } + if (m_single_value) { + /* write buffer has a single value stored at (0,0) */ + m_buffer->read(output, 0, 0); + } + else if (sampler == COM_PS_NEAREST) { + m_buffer->read(output, x, y, extend_x, extend_y); + } + else { + m_buffer->readBilinear(output, x, y, extend_x, extend_y); + } } -void ReadBufferOperation::executePixelFiltered(float output[4], float x, float y, float dx[2], float dy[2]) +void ReadBufferOperation::executePixelFiltered( + float output[4], float x, float y, float dx[2], float dy[2]) { - if (m_single_value) { - /* write buffer has a single value stored at (0,0) */ - m_buffer->read(output, 0, 0); - } - else { - const float uv[2] = { x, y }; - const float deriv[2][2] = { {dx[0], dx[1]}, {dy[0], dy[1]} }; - m_buffer->readEWA(output, uv, deriv); - } + if (m_single_value) { + /* write buffer has a single value stored at (0,0) */ + m_buffer->read(output, 0, 0); + } + else { + const float uv[2] = {x, y}; + const float deriv[2][2] = {{dx[0], dx[1]}, {dy[0], dy[1]}}; + m_buffer->readEWA(output, uv, deriv); + } } -bool ReadBufferOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool ReadBufferOperation::determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output) { - if (this == readOperation) { - BLI_rcti_init(output, input->xmin, input->xmax, input->ymin, input->ymax); - return true; - } - return false; + if (this == readOperation) { + BLI_rcti_init(output, input->xmin, input->xmax, input->ymin, input->ymax); + return true; + } + return false; } void ReadBufferOperation::readResolutionFromWriteBuffer() { - if (this->m_memoryProxy != NULL) { - WriteBufferOperation *operation = this->m_memoryProxy->getWriteBufferOperation(); - this->setWidth(operation->getWidth()); - this->setHeight(operation->getHeight()); - } + if (this->m_memoryProxy != NULL) { + WriteBufferOperation *operation = this->m_memoryProxy->getWriteBufferOperation(); + this->setWidth(operation->getWidth()); + this->setHeight(operation->getHeight()); + } } void ReadBufferOperation::updateMemoryBuffer() { - this->m_buffer = this->getMemoryProxy()->getBuffer(); - + this->m_buffer = this->getMemoryProxy()->getBuffer(); } diff --git a/source/blender/compositor/operations/COM_ReadBufferOperation.h b/source/blender/compositor/operations/COM_ReadBufferOperation.h index cd15bb12b28..fee6555c3a9 100644 --- a/source/blender/compositor/operations/COM_ReadBufferOperation.h +++ b/source/blender/compositor/operations/COM_ReadBufferOperation.h @@ -24,29 +24,54 @@ #include "COM_MemoryBuffer.h" class ReadBufferOperation : public NodeOperation { -private: - MemoryProxy *m_memoryProxy; - bool m_single_value; /* single value stored in buffer, copied from associated write operation */ - unsigned int m_offset; - MemoryBuffer *m_buffer; -public: - ReadBufferOperation(DataType datetype); - void setMemoryProxy(MemoryProxy *memoryProxy) { this->m_memoryProxy = memoryProxy; } - MemoryProxy *getMemoryProxy() { return this->m_memoryProxy; } - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); + private: + MemoryProxy *m_memoryProxy; + bool m_single_value; /* single value stored in buffer, copied from associated write operation */ + unsigned int m_offset; + MemoryBuffer *m_buffer; - void *initializeTileData(rcti *rect); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - void executePixelExtend(float output[4], float x, float y, PixelSampler sampler, - MemoryBufferExtend extend_x, MemoryBufferExtend extend_y); - void executePixelFiltered(float output[4], float x, float y, float dx[2], float dy[2]); - bool isReadBufferOperation() const { return true; } - void setOffset(unsigned int offset) { this->m_offset = offset; } - unsigned int getOffset() const { return this->m_offset; } - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - MemoryBuffer *getInputMemoryBuffer(MemoryBuffer **memoryBuffers) { return memoryBuffers[this->m_offset]; } - void readResolutionFromWriteBuffer(); - void updateMemoryBuffer(); + public: + ReadBufferOperation(DataType datetype); + void setMemoryProxy(MemoryProxy *memoryProxy) + { + this->m_memoryProxy = memoryProxy; + } + MemoryProxy *getMemoryProxy() + { + return this->m_memoryProxy; + } + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); + + void *initializeTileData(rcti *rect); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void executePixelExtend(float output[4], + float x, + float y, + PixelSampler sampler, + MemoryBufferExtend extend_x, + MemoryBufferExtend extend_y); + void executePixelFiltered(float output[4], float x, float y, float dx[2], float dy[2]); + bool isReadBufferOperation() const + { + return true; + } + void setOffset(unsigned int offset) + { + this->m_offset = offset; + } + unsigned int getOffset() const + { + return this->m_offset; + } + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + MemoryBuffer *getInputMemoryBuffer(MemoryBuffer **memoryBuffers) + { + return memoryBuffers[this->m_offset]; + } + void readResolutionFromWriteBuffer(); + void updateMemoryBuffer(); }; #endif diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.cpp b/source/blender/compositor/operations/COM_RenderLayersProg.cpp index 060cf7ae91e..0ebb60cff18 100644 --- a/source/blender/compositor/operations/COM_RenderLayersProg.cpp +++ b/source/blender/compositor/operations/COM_RenderLayersProg.cpp @@ -23,223 +23,236 @@ #include "DNA_scene_types.h" extern "C" { -# include "RE_pipeline.h" -# include "RE_shader_ext.h" -# include "RE_render_ext.h" +#include "RE_pipeline.h" +#include "RE_shader_ext.h" +#include "RE_render_ext.h" } /* ******** Render Layers Base Prog ******** */ -RenderLayersProg::RenderLayersProg(const char *passName, DataType type, int elementsize) : NodeOperation(), m_passName(passName) +RenderLayersProg::RenderLayersProg(const char *passName, DataType type, int elementsize) + : NodeOperation(), m_passName(passName) { - this->setScene(NULL); - this->m_inputBuffer = NULL; - this->m_elementsize = elementsize; - this->m_rd = NULL; + this->setScene(NULL); + this->m_inputBuffer = NULL; + this->m_elementsize = elementsize; + this->m_rd = NULL; - this->addOutputSocket(type); + this->addOutputSocket(type); } - void RenderLayersProg::initExecution() { - Scene *scene = this->getScene(); - Render *re = (scene) ? RE_GetSceneRender(scene) : NULL; - RenderResult *rr = NULL; - - if (re) - rr = RE_AcquireResultRead(re); - - if (rr) { - ViewLayer *view_layer = (ViewLayer *)BLI_findlink(&scene->view_layers, getLayerId()); - if (view_layer) { - - RenderLayer *rl = RE_GetRenderLayer(rr, view_layer->name); - if (rl) { - this->m_inputBuffer = RE_RenderLayerGetPass(rl, this->m_passName.c_str(), this->m_viewName); - } - } - } - if (re) { - RE_ReleaseResult(re); - re = NULL; - } + Scene *scene = this->getScene(); + Render *re = (scene) ? RE_GetSceneRender(scene) : NULL; + RenderResult *rr = NULL; + + if (re) + rr = RE_AcquireResultRead(re); + + if (rr) { + ViewLayer *view_layer = (ViewLayer *)BLI_findlink(&scene->view_layers, getLayerId()); + if (view_layer) { + + RenderLayer *rl = RE_GetRenderLayer(rr, view_layer->name); + if (rl) { + this->m_inputBuffer = RE_RenderLayerGetPass( + rl, this->m_passName.c_str(), this->m_viewName); + } + } + } + if (re) { + RE_ReleaseResult(re); + re = NULL; + } } void RenderLayersProg::doInterpolation(float output[4], float x, float y, PixelSampler sampler) { - unsigned int offset; - int width = this->getWidth(), height = this->getHeight(); - - int ix = x, iy = y; - if (ix < 0 || iy < 0 || ix >= width || iy >= height) { - if (this->m_elementsize == 1) - output[0] = 0.0f; - else if (this->m_elementsize == 3) - zero_v3(output); - else - zero_v4(output); - return; - } - - switch (sampler) { - case COM_PS_NEAREST: { - offset = (iy * width + ix) * this->m_elementsize; - - if (this->m_elementsize == 1) - output[0] = this->m_inputBuffer[offset]; - else if (this->m_elementsize == 3) - copy_v3_v3(output, &this->m_inputBuffer[offset]); - else - copy_v4_v4(output, &this->m_inputBuffer[offset]); - break; - } - - case COM_PS_BILINEAR: - BLI_bilinear_interpolation_fl(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y); - break; - - case COM_PS_BICUBIC: - BLI_bicubic_interpolation_fl(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y); - break; - } + unsigned int offset; + int width = this->getWidth(), height = this->getHeight(); + + int ix = x, iy = y; + if (ix < 0 || iy < 0 || ix >= width || iy >= height) { + if (this->m_elementsize == 1) + output[0] = 0.0f; + else if (this->m_elementsize == 3) + zero_v3(output); + else + zero_v4(output); + return; + } + + switch (sampler) { + case COM_PS_NEAREST: { + offset = (iy * width + ix) * this->m_elementsize; + + if (this->m_elementsize == 1) + output[0] = this->m_inputBuffer[offset]; + else if (this->m_elementsize == 3) + copy_v3_v3(output, &this->m_inputBuffer[offset]); + else + copy_v4_v4(output, &this->m_inputBuffer[offset]); + break; + } + + case COM_PS_BILINEAR: + BLI_bilinear_interpolation_fl( + this->m_inputBuffer, output, width, height, this->m_elementsize, x, y); + break; + + case COM_PS_BICUBIC: + BLI_bicubic_interpolation_fl( + this->m_inputBuffer, output, width, height, this->m_elementsize, x, y); + break; + } } void RenderLayersProg::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { #if 0 - const RenderData *rd = this->m_rd; + const RenderData *rd = this->m_rd; - int dx = 0, dy = 0; + int dx = 0, dy = 0; - if (rd->mode & R_BORDER && rd->mode & R_CROP) { - /* see comment in executeRegion describing coordinate mapping, - * here it simply goes other way around - */ - int full_width = rd->xsch * rd->size / 100; - int full_height = rd->ysch * rd->size / 100; + if (rd->mode & R_BORDER && rd->mode & R_CROP) { + /* see comment in executeRegion describing coordinate mapping, + * here it simply goes other way around + */ + int full_width = rd->xsch * rd->size / 100; + int full_height = rd->ysch * rd->size / 100; - dx = rd->border.xmin * full_width - (full_width - this->getWidth()) / 2.0f; - dy = rd->border.ymin * full_height - (full_height - this->getHeight()) / 2.0f; - } + dx = rd->border.xmin * full_width - (full_width - this->getWidth()) / 2.0f; + dy = rd->border.ymin * full_height - (full_height - this->getHeight()) / 2.0f; + } - int ix = x - dx; - int iy = y - dy; + int ix = x - dx; + int iy = y - dy; #endif #ifndef NDEBUG - { - const DataType data_type = this->getOutputSocket()->getDataType(); - int actual_element_size = this->m_elementsize; - int expected_element_size; - if (data_type == COM_DT_VALUE) { - expected_element_size = 1; - } - else if (data_type == COM_DT_VECTOR) { - expected_element_size = 3; - } - else if (data_type == COM_DT_COLOR) { - expected_element_size = 4; - } - else { - expected_element_size = 0; - BLI_assert(!"Something horribly wrong just happened"); - } - BLI_assert(expected_element_size == actual_element_size); - } + { + const DataType data_type = this->getOutputSocket()->getDataType(); + int actual_element_size = this->m_elementsize; + int expected_element_size; + if (data_type == COM_DT_VALUE) { + expected_element_size = 1; + } + else if (data_type == COM_DT_VECTOR) { + expected_element_size = 3; + } + else if (data_type == COM_DT_COLOR) { + expected_element_size = 4; + } + else { + expected_element_size = 0; + BLI_assert(!"Something horribly wrong just happened"); + } + BLI_assert(expected_element_size == actual_element_size); + } #endif - if (this->m_inputBuffer == NULL) { - int elemsize = this->m_elementsize; - if (elemsize == 1) { - output[0] = 0.0f; - } - else if (elemsize == 3) { - zero_v3(output); - } - else { - BLI_assert(elemsize == 4); - zero_v4(output); - } - } - else { - doInterpolation(output, x, y, sampler); - } + if (this->m_inputBuffer == NULL) { + int elemsize = this->m_elementsize; + if (elemsize == 1) { + output[0] = 0.0f; + } + else if (elemsize == 3) { + zero_v3(output); + } + else { + BLI_assert(elemsize == 4); + zero_v4(output); + } + } + else { + doInterpolation(output, x, y, sampler); + } } void RenderLayersProg::deinitExecution() { - this->m_inputBuffer = NULL; + this->m_inputBuffer = NULL; } -void RenderLayersProg::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2]) +void RenderLayersProg::determineResolution(unsigned int resolution[2], + unsigned int /*preferredResolution*/[2]) { - Scene *sce = this->getScene(); - Render *re = (sce) ? RE_GetSceneRender(sce) : NULL; - RenderResult *rr = NULL; - - resolution[0] = 0; - resolution[1] = 0; - - if (re) - rr = RE_AcquireResultRead(re); - - if (rr) { - ViewLayer *view_layer = (ViewLayer *)BLI_findlink(&sce->view_layers, getLayerId()); - if (view_layer) { - RenderLayer *rl = RE_GetRenderLayer(rr, view_layer->name); - if (rl) { - resolution[0] = rl->rectx; - resolution[1] = rl->recty; - } - } - } - - if (re) - RE_ReleaseResult(re); - + Scene *sce = this->getScene(); + Render *re = (sce) ? RE_GetSceneRender(sce) : NULL; + RenderResult *rr = NULL; + + resolution[0] = 0; + resolution[1] = 0; + + if (re) + rr = RE_AcquireResultRead(re); + + if (rr) { + ViewLayer *view_layer = (ViewLayer *)BLI_findlink(&sce->view_layers, getLayerId()); + if (view_layer) { + RenderLayer *rl = RE_GetRenderLayer(rr, view_layer->name); + if (rl) { + resolution[0] = rl->rectx; + resolution[1] = rl->recty; + } + } + } + + if (re) + RE_ReleaseResult(re); } /* ******** Render Layers AO Operation ******** */ -void RenderLayersAOOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void RenderLayersAOOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float *inputBuffer = this->getInputBuffer(); - if (inputBuffer == NULL) { - zero_v3(output); - } - else { - doInterpolation(output, x, y, sampler); - } - output[3] = 1.0f; + float *inputBuffer = this->getInputBuffer(); + if (inputBuffer == NULL) { + zero_v3(output); + } + else { + doInterpolation(output, x, y, sampler); + } + output[3] = 1.0f; } /* ******** Render Layers Alpha Operation ******** */ -void RenderLayersAlphaProg::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void RenderLayersAlphaProg::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float *inputBuffer = this->getInputBuffer(); - - if (inputBuffer == NULL) { - output[0] = 0.0f; - } - else { - float temp[4]; - doInterpolation(temp, x, y, sampler); - output[0] = temp[3]; - } + float *inputBuffer = this->getInputBuffer(); + + if (inputBuffer == NULL) { + output[0] = 0.0f; + } + else { + float temp[4]; + doInterpolation(temp, x, y, sampler); + output[0] = temp[3]; + } } /* ******** Render Layers Depth Operation ******** */ -void RenderLayersDepthProg::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) +void RenderLayersDepthProg::executePixelSampled(float output[4], + float x, + float y, + PixelSampler /*sampler*/) { - int ix = x; - int iy = y; - float *inputBuffer = this->getInputBuffer(); - - if (inputBuffer == NULL || ix < 0 || iy < 0 || ix >= (int)this->getWidth() || iy >= (int)this->getHeight() ) { - output[0] = 10e10f; - } - else { - unsigned int offset = (iy * this->getWidth() + ix); - output[0] = inputBuffer[offset]; - } + int ix = x; + int iy = y; + float *inputBuffer = this->getInputBuffer(); + + if (inputBuffer == NULL || ix < 0 || iy < 0 || ix >= (int)this->getWidth() || + iy >= (int)this->getHeight()) { + output[0] = 10e10f; + } + else { + unsigned int offset = (iy * this->getWidth() + ix); + output[0] = inputBuffer[offset]; + } } diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.h b/source/blender/compositor/operations/COM_RenderLayersProg.h index bce3b40b353..5aa7e879760 100644 --- a/source/blender/compositor/operations/COM_RenderLayersProg.h +++ b/source/blender/compositor/operations/COM_RenderLayersProg.h @@ -16,7 +16,6 @@ * Copyright 2011, Blender Foundation. */ - #ifndef __COM_RENDERLAYERSPROG_H__ #define __COM_RENDERLAYERSPROG_H__ @@ -25,8 +24,8 @@ #include "BLI_listbase.h" #include "BKE_image.h" extern "C" { -# include "RE_pipeline.h" -# include "MEM_guardedalloc.h" +#include "RE_pipeline.h" +#include "MEM_guardedalloc.h" } /** @@ -35,91 +34,122 @@ extern "C" { * \todo: rename to operation. */ class RenderLayersProg : public NodeOperation { -protected: - /** - * Reference to the scene object. - */ - Scene *m_scene; - - /** - * layerId of the layer where this operation needs to get its data from - */ - short m_layerId; - - /** - * viewName of the view to use (unless another view is specified by the node - */ - const char *m_viewName; - - /** - * cached instance to the float buffer inside the layer - */ - float *m_inputBuffer; - - /** - * renderpass where this operation needs to get its data from - */ - std::string m_passName; - - int m_elementsize; - - /** - * \brief render data used for active rendering - */ - const RenderData *m_rd; - - /** - * Determine the output resolution. The resolution is retrieved from the Renderer - */ - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); - - /** - * retrieve the reference to the float buffer of the renderer. - */ - inline float *getInputBuffer() { return this->m_inputBuffer; } - - void doInterpolation(float output[4], float x, float y, PixelSampler sampler); -public: - /** - * Constructor - */ - RenderLayersProg(const char *passName, DataType type, int elementsize); - /** - * setter for the scene field. Will be called from - * \see RenderLayerNode to set the actual scene where - * the data will be retrieved from. - */ - void setScene(Scene *scene) { this->m_scene = scene; } - Scene *getScene() { return this->m_scene; } - void setRenderData(const RenderData *rd) { this->m_rd = rd; } - void setLayerId(short layerId) { this->m_layerId = layerId; } - short getLayerId() { return this->m_layerId; } - void setViewName(const char *viewName) { this->m_viewName = viewName; } - const char *getViewName() { return this->m_viewName; } - void initExecution(); - void deinitExecution(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + protected: + /** + * Reference to the scene object. + */ + Scene *m_scene; + + /** + * layerId of the layer where this operation needs to get its data from + */ + short m_layerId; + + /** + * viewName of the view to use (unless another view is specified by the node + */ + const char *m_viewName; + + /** + * cached instance to the float buffer inside the layer + */ + float *m_inputBuffer; + + /** + * renderpass where this operation needs to get its data from + */ + std::string m_passName; + + int m_elementsize; + + /** + * \brief render data used for active rendering + */ + const RenderData *m_rd; + + /** + * Determine the output resolution. The resolution is retrieved from the Renderer + */ + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); + + /** + * retrieve the reference to the float buffer of the renderer. + */ + inline float *getInputBuffer() + { + return this->m_inputBuffer; + } + + void doInterpolation(float output[4], float x, float y, PixelSampler sampler); + + public: + /** + * Constructor + */ + RenderLayersProg(const char *passName, DataType type, int elementsize); + /** + * setter for the scene field. Will be called from + * \see RenderLayerNode to set the actual scene where + * the data will be retrieved from. + */ + void setScene(Scene *scene) + { + this->m_scene = scene; + } + Scene *getScene() + { + return this->m_scene; + } + void setRenderData(const RenderData *rd) + { + this->m_rd = rd; + } + void setLayerId(short layerId) + { + this->m_layerId = layerId; + } + short getLayerId() + { + return this->m_layerId; + } + void setViewName(const char *viewName) + { + this->m_viewName = viewName; + } + const char *getViewName() + { + return this->m_viewName; + } + void initExecution(); + void deinitExecution(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class RenderLayersAOOperation : public RenderLayersProg { -public: - RenderLayersAOOperation(const char *passName, DataType type, int elementsize) - : RenderLayersProg(passName, type, elementsize) {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + RenderLayersAOOperation(const char *passName, DataType type, int elementsize) + : RenderLayersProg(passName, type, elementsize) + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class RenderLayersAlphaProg : public RenderLayersProg { -public: - RenderLayersAlphaProg(const char *passName, DataType type, int elementsize) - : RenderLayersProg(passName, type, elementsize) {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + RenderLayersAlphaProg(const char *passName, DataType type, int elementsize) + : RenderLayersProg(passName, type, elementsize) + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class RenderLayersDepthProg : public RenderLayersProg { -public: - RenderLayersDepthProg(const char *passName, DataType type, int elementsize) - : RenderLayersProg(passName, type, elementsize) {} - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + RenderLayersDepthProg(const char *passName, DataType type, int elementsize) + : RenderLayersProg(passName, type, elementsize) + { + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; #endif diff --git a/source/blender/compositor/operations/COM_RotateOperation.cpp b/source/blender/compositor/operations/COM_RotateOperation.cpp index bc9fd46e8d7..3ccf36cec2c 100644 --- a/source/blender/compositor/operations/COM_RotateOperation.cpp +++ b/source/blender/compositor/operations/COM_RotateOperation.cpp @@ -21,86 +21,87 @@ RotateOperation::RotateOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_COLOR); - this->setResolutionInputSocketIndex(0); - this->m_imageSocket = NULL; - this->m_degreeSocket = NULL; - this->m_doDegree2RadConversion = false; - this->m_isDegreeSet = false; + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_COLOR); + this->setResolutionInputSocketIndex(0); + this->m_imageSocket = NULL; + this->m_degreeSocket = NULL; + this->m_doDegree2RadConversion = false; + this->m_isDegreeSet = false; } void RotateOperation::initExecution() { - this->m_imageSocket = this->getInputSocketReader(0); - this->m_degreeSocket = this->getInputSocketReader(1); - this->m_centerX = (getWidth() - 1) / 2.0; - this->m_centerY = (getHeight() - 1) / 2.0; + this->m_imageSocket = this->getInputSocketReader(0); + this->m_degreeSocket = this->getInputSocketReader(1); + this->m_centerX = (getWidth() - 1) / 2.0; + this->m_centerY = (getHeight() - 1) / 2.0; } void RotateOperation::deinitExecution() { - this->m_imageSocket = NULL; - this->m_degreeSocket = NULL; + this->m_imageSocket = NULL; + this->m_degreeSocket = NULL; } inline void RotateOperation::ensureDegree() { - if (!this->m_isDegreeSet) { - float degree[4]; - this->m_degreeSocket->readSampled(degree, 0, 0, COM_PS_NEAREST); - double rad; - if (this->m_doDegree2RadConversion) { - rad = DEG2RAD((double)degree[0]); - } - else { - rad = degree[0]; - } - this->m_cosine = cos(rad); - this->m_sine = sin(rad); + if (!this->m_isDegreeSet) { + float degree[4]; + this->m_degreeSocket->readSampled(degree, 0, 0, COM_PS_NEAREST); + double rad; + if (this->m_doDegree2RadConversion) { + rad = DEG2RAD((double)degree[0]); + } + else { + rad = degree[0]; + } + this->m_cosine = cos(rad); + this->m_sine = sin(rad); - this->m_isDegreeSet = true; - } + this->m_isDegreeSet = true; + } } - void RotateOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { - ensureDegree(); - const float dy = y - this->m_centerY; - const float dx = x - this->m_centerX; - const float nx = this->m_centerX + (this->m_cosine * dx + this->m_sine * dy); - const float ny = this->m_centerY + (-this->m_sine * dx + this->m_cosine * dy); - this->m_imageSocket->readSampled(output, nx, ny, sampler); + ensureDegree(); + const float dy = y - this->m_centerY; + const float dx = x - this->m_centerX; + const float nx = this->m_centerX + (this->m_cosine * dx + this->m_sine * dy); + const float ny = this->m_centerY + (-this->m_sine * dx + this->m_cosine * dy); + this->m_imageSocket->readSampled(output, nx, ny, sampler); } -bool RotateOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool RotateOperation::determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output) { - ensureDegree(); - rcti newInput; + ensureDegree(); + rcti newInput; - const float dxmin = input->xmin - this->m_centerX; - const float dymin = input->ymin - this->m_centerY; - const float dxmax = input->xmax - this->m_centerX; - const float dymax = input->ymax - this->m_centerY; + const float dxmin = input->xmin - this->m_centerX; + const float dymin = input->ymin - this->m_centerY; + const float dxmax = input->xmax - this->m_centerX; + const float dymax = input->ymax - this->m_centerY; - const float x1 = this->m_centerX + (this->m_cosine * dxmin + this->m_sine * dymin); - const float x2 = this->m_centerX + (this->m_cosine * dxmax + this->m_sine * dymin); - const float x3 = this->m_centerX + (this->m_cosine * dxmin + this->m_sine * dymax); - const float x4 = this->m_centerX + (this->m_cosine * dxmax + this->m_sine * dymax); - const float y1 = this->m_centerY + (-this->m_sine * dxmin + this->m_cosine * dymin); - const float y2 = this->m_centerY + (-this->m_sine * dxmax + this->m_cosine * dymin); - const float y3 = this->m_centerY + (-this->m_sine * dxmin + this->m_cosine * dymax); - const float y4 = this->m_centerY + (-this->m_sine * dxmax + this->m_cosine * dymax); - const float minx = min(x1, min(x2, min(x3, x4))); - const float maxx = max(x1, max(x2, max(x3, x4))); - const float miny = min(y1, min(y2, min(y3, y4))); - const float maxy = max(y1, max(y2, max(y3, y4))); + const float x1 = this->m_centerX + (this->m_cosine * dxmin + this->m_sine * dymin); + const float x2 = this->m_centerX + (this->m_cosine * dxmax + this->m_sine * dymin); + const float x3 = this->m_centerX + (this->m_cosine * dxmin + this->m_sine * dymax); + const float x4 = this->m_centerX + (this->m_cosine * dxmax + this->m_sine * dymax); + const float y1 = this->m_centerY + (-this->m_sine * dxmin + this->m_cosine * dymin); + const float y2 = this->m_centerY + (-this->m_sine * dxmax + this->m_cosine * dymin); + const float y3 = this->m_centerY + (-this->m_sine * dxmin + this->m_cosine * dymax); + const float y4 = this->m_centerY + (-this->m_sine * dxmax + this->m_cosine * dymax); + const float minx = min(x1, min(x2, min(x3, x4))); + const float maxx = max(x1, max(x2, max(x3, x4))); + const float miny = min(y1, min(y2, min(y3, y4))); + const float maxy = max(y1, max(y2, max(y3, y4))); - newInput.xmax = ceil(maxx) + 1; - newInput.xmin = floor(minx) - 1; - newInput.ymax = ceil(maxy) + 1; - newInput.ymin = floor(miny) - 1; + newInput.xmax = ceil(maxx) + 1; + newInput.xmin = floor(minx) - 1; + newInput.ymax = ceil(maxy) + 1; + newInput.ymin = floor(miny) - 1; - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } diff --git a/source/blender/compositor/operations/COM_RotateOperation.h b/source/blender/compositor/operations/COM_RotateOperation.h index 1ab8fbd87a1..46bdc68161e 100644 --- a/source/blender/compositor/operations/COM_RotateOperation.h +++ b/source/blender/compositor/operations/COM_RotateOperation.h @@ -22,24 +22,30 @@ #include "COM_NodeOperation.h" class RotateOperation : public NodeOperation { -private: - SocketReader *m_imageSocket; - SocketReader *m_degreeSocket; - float m_centerX; - float m_centerY; - float m_cosine; - float m_sine; - bool m_doDegree2RadConversion; - bool m_isDegreeSet; -public: - RotateOperation(); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - void initExecution(); - void deinitExecution(); - void setDoDegree2RadConversion(bool abool) { this->m_doDegree2RadConversion = abool; } + private: + SocketReader *m_imageSocket; + SocketReader *m_degreeSocket; + float m_centerX; + float m_centerY; + float m_cosine; + float m_sine; + bool m_doDegree2RadConversion; + bool m_isDegreeSet; - void ensureDegree(); + public: + RotateOperation(); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void initExecution(); + void deinitExecution(); + void setDoDegree2RadConversion(bool abool) + { + this->m_doDegree2RadConversion = abool; + } + + void ensureDegree(); }; #endif diff --git a/source/blender/compositor/operations/COM_ScaleOperation.cpp b/source/blender/compositor/operations/COM_ScaleOperation.cpp index 7c0c552c34d..3663d56dc87 100644 --- a/source/blender/compositor/operations/COM_ScaleOperation.cpp +++ b/source/blender/compositor/operations/COM_ScaleOperation.cpp @@ -28,275 +28,283 @@ BaseScaleOperation::BaseScaleOperation() { #ifdef USE_FORCE_BILINEAR - m_sampler = (int) COM_PS_BILINEAR; + m_sampler = (int)COM_PS_BILINEAR; #else - m_sampler = -1; + m_sampler = -1; #endif - m_variable_size = false; + m_variable_size = false; } ScaleOperation::ScaleOperation() : BaseScaleOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_COLOR); - this->setResolutionInputSocketIndex(0); - this->m_inputOperation = NULL; - this->m_inputXOperation = NULL; - this->m_inputYOperation = NULL; + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_COLOR); + this->setResolutionInputSocketIndex(0); + this->m_inputOperation = NULL; + this->m_inputXOperation = NULL; + this->m_inputYOperation = NULL; } void ScaleOperation::initExecution() { - this->m_inputOperation = this->getInputSocketReader(0); - this->m_inputXOperation = this->getInputSocketReader(1); - this->m_inputYOperation = this->getInputSocketReader(2); - this->m_centerX = this->getWidth() / 2.0; - this->m_centerY = this->getHeight() / 2.0; + this->m_inputOperation = this->getInputSocketReader(0); + this->m_inputXOperation = this->getInputSocketReader(1); + this->m_inputYOperation = this->getInputSocketReader(2); + this->m_centerX = this->getWidth() / 2.0; + this->m_centerY = this->getHeight() / 2.0; } void ScaleOperation::deinitExecution() { - this->m_inputOperation = NULL; - this->m_inputXOperation = NULL; - this->m_inputYOperation = NULL; + this->m_inputOperation = NULL; + this->m_inputXOperation = NULL; + this->m_inputYOperation = NULL; } - void ScaleOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { - PixelSampler effective_sampler = getEffectiveSampler(sampler); + PixelSampler effective_sampler = getEffectiveSampler(sampler); - float scaleX[4]; - float scaleY[4]; + float scaleX[4]; + float scaleY[4]; - this->m_inputXOperation->readSampled(scaleX, x, y, effective_sampler); - this->m_inputYOperation->readSampled(scaleY, x, y, effective_sampler); + this->m_inputXOperation->readSampled(scaleX, x, y, effective_sampler); + this->m_inputYOperation->readSampled(scaleY, x, y, effective_sampler); - const float scx = scaleX[0]; - const float scy = scaleY[0]; + const float scx = scaleX[0]; + const float scy = scaleY[0]; - float nx = this->m_centerX + (x - this->m_centerX) / scx; - float ny = this->m_centerY + (y - this->m_centerY) / scy; - this->m_inputOperation->readSampled(output, nx, ny, effective_sampler); + float nx = this->m_centerX + (x - this->m_centerX) / scx; + float ny = this->m_centerY + (y - this->m_centerY) / scy; + this->m_inputOperation->readSampled(output, nx, ny, effective_sampler); } -bool ScaleOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool ScaleOperation::determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output) { - rcti newInput; - if (!m_variable_size) { - float scaleX[4]; - float scaleY[4]; - - this->m_inputXOperation->readSampled(scaleX, 0, 0, COM_PS_NEAREST); - this->m_inputYOperation->readSampled(scaleY, 0, 0, COM_PS_NEAREST); - - const float scx = scaleX[0]; - const float scy = scaleY[0]; - - newInput.xmax = this->m_centerX + (input->xmax - this->m_centerX) / scx; - newInput.xmin = this->m_centerX + (input->xmin - this->m_centerX) / scx; - newInput.ymax = this->m_centerY + (input->ymax - this->m_centerY) / scy; - newInput.ymin = this->m_centerY + (input->ymin - this->m_centerY) / scy; - } - else { - newInput.xmax = this->getWidth(); - newInput.xmin = 0; - newInput.ymax = this->getHeight(); - newInput.ymin = 0; - } - return BaseScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + rcti newInput; + if (!m_variable_size) { + float scaleX[4]; + float scaleY[4]; + + this->m_inputXOperation->readSampled(scaleX, 0, 0, COM_PS_NEAREST); + this->m_inputYOperation->readSampled(scaleY, 0, 0, COM_PS_NEAREST); + + const float scx = scaleX[0]; + const float scy = scaleY[0]; + + newInput.xmax = this->m_centerX + (input->xmax - this->m_centerX) / scx; + newInput.xmin = this->m_centerX + (input->xmin - this->m_centerX) / scx; + newInput.ymax = this->m_centerY + (input->ymax - this->m_centerY) / scy; + newInput.ymin = this->m_centerY + (input->ymin - this->m_centerY) / scy; + } + else { + newInput.xmax = this->getWidth(); + newInput.xmin = 0; + newInput.ymax = this->getHeight(); + newInput.ymin = 0; + } + return BaseScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } - // SCALE ABSOLUTE ScaleAbsoluteOperation::ScaleAbsoluteOperation() : BaseScaleOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_COLOR); - this->setResolutionInputSocketIndex(0); - this->m_inputOperation = NULL; - this->m_inputXOperation = NULL; - this->m_inputYOperation = NULL; + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_COLOR); + this->setResolutionInputSocketIndex(0); + this->m_inputOperation = NULL; + this->m_inputXOperation = NULL; + this->m_inputYOperation = NULL; } void ScaleAbsoluteOperation::initExecution() { - this->m_inputOperation = this->getInputSocketReader(0); - this->m_inputXOperation = this->getInputSocketReader(1); - this->m_inputYOperation = this->getInputSocketReader(2); - this->m_centerX = this->getWidth() / 2.0; - this->m_centerY = this->getHeight() / 2.0; + this->m_inputOperation = this->getInputSocketReader(0); + this->m_inputXOperation = this->getInputSocketReader(1); + this->m_inputYOperation = this->getInputSocketReader(2); + this->m_centerX = this->getWidth() / 2.0; + this->m_centerY = this->getHeight() / 2.0; } void ScaleAbsoluteOperation::deinitExecution() { - this->m_inputOperation = NULL; - this->m_inputXOperation = NULL; - this->m_inputYOperation = NULL; + this->m_inputOperation = NULL; + this->m_inputXOperation = NULL; + this->m_inputYOperation = NULL; } - -void ScaleAbsoluteOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ScaleAbsoluteOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - PixelSampler effective_sampler = getEffectiveSampler(sampler); + PixelSampler effective_sampler = getEffectiveSampler(sampler); - float scaleX[4]; - float scaleY[4]; + float scaleX[4]; + float scaleY[4]; - this->m_inputXOperation->readSampled(scaleX, x, y, effective_sampler); - this->m_inputYOperation->readSampled(scaleY, x, y, effective_sampler); + this->m_inputXOperation->readSampled(scaleX, x, y, effective_sampler); + this->m_inputYOperation->readSampled(scaleY, x, y, effective_sampler); - const float scx = scaleX[0]; // target absolute scale - const float scy = scaleY[0]; // target absolute scale + const float scx = scaleX[0]; // target absolute scale + const float scy = scaleY[0]; // target absolute scale - const float width = this->getWidth(); - const float height = this->getHeight(); - //div - float relativeXScale = scx / width; - float relativeYScale = scy / height; + const float width = this->getWidth(); + const float height = this->getHeight(); + //div + float relativeXScale = scx / width; + float relativeYScale = scy / height; - float nx = this->m_centerX + (x - this->m_centerX) / relativeXScale; - float ny = this->m_centerY + (y - this->m_centerY) / relativeYScale; + float nx = this->m_centerX + (x - this->m_centerX) / relativeXScale; + float ny = this->m_centerY + (y - this->m_centerY) / relativeYScale; - this->m_inputOperation->readSampled(output, nx, ny, effective_sampler); + this->m_inputOperation->readSampled(output, nx, ny, effective_sampler); } -bool ScaleAbsoluteOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool ScaleAbsoluteOperation::determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output) { - rcti newInput; - if (!m_variable_size) { - float scaleX[4]; - float scaleY[4]; - - this->m_inputXOperation->readSampled(scaleX, 0, 0, COM_PS_NEAREST); - this->m_inputYOperation->readSampled(scaleY, 0, 0, COM_PS_NEAREST); - - const float scx = scaleX[0]; - const float scy = scaleY[0]; - const float width = this->getWidth(); - const float height = this->getHeight(); - //div - float relateveXScale = scx / width; - float relateveYScale = scy / height; - - newInput.xmax = this->m_centerX + (input->xmax - this->m_centerX) / relateveXScale; - newInput.xmin = this->m_centerX + (input->xmin - this->m_centerX) / relateveXScale; - newInput.ymax = this->m_centerY + (input->ymax - this->m_centerY) / relateveYScale; - newInput.ymin = this->m_centerY + (input->ymin - this->m_centerY) / relateveYScale; - } - else { - newInput.xmax = this->getWidth(); - newInput.xmin = 0; - newInput.ymax = this->getHeight(); - newInput.ymin = 0; - } - - return BaseScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + rcti newInput; + if (!m_variable_size) { + float scaleX[4]; + float scaleY[4]; + + this->m_inputXOperation->readSampled(scaleX, 0, 0, COM_PS_NEAREST); + this->m_inputYOperation->readSampled(scaleY, 0, 0, COM_PS_NEAREST); + + const float scx = scaleX[0]; + const float scy = scaleY[0]; + const float width = this->getWidth(); + const float height = this->getHeight(); + //div + float relateveXScale = scx / width; + float relateveYScale = scy / height; + + newInput.xmax = this->m_centerX + (input->xmax - this->m_centerX) / relateveXScale; + newInput.xmin = this->m_centerX + (input->xmin - this->m_centerX) / relateveXScale; + newInput.ymax = this->m_centerY + (input->ymax - this->m_centerY) / relateveYScale; + newInput.ymin = this->m_centerY + (input->ymin - this->m_centerY) / relateveYScale; + } + else { + newInput.xmax = this->getWidth(); + newInput.xmin = 0; + newInput.ymax = this->getHeight(); + newInput.ymin = 0; + } + + return BaseScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } - // Absolute fixed size ScaleFixedSizeOperation::ScaleFixedSizeOperation() : BaseScaleOperation() { - this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); - this->addOutputSocket(COM_DT_COLOR); - this->setResolutionInputSocketIndex(0); - this->m_inputOperation = NULL; - this->m_is_offset = false; + this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); + this->addOutputSocket(COM_DT_COLOR); + this->setResolutionInputSocketIndex(0); + this->m_inputOperation = NULL; + this->m_is_offset = false; } void ScaleFixedSizeOperation::initExecution() { - this->m_inputOperation = this->getInputSocketReader(0); - this->m_relX = this->m_inputOperation->getWidth() / (float)this->m_newWidth; - this->m_relY = this->m_inputOperation->getHeight() / (float)this->m_newHeight; - - - /* *** all the options below are for a fairly special case - camera framing *** */ - if (this->m_offsetX != 0.0f || this->m_offsetY != 0.0f) { - this->m_is_offset = true; - - if (this->m_newWidth > this->m_newHeight) { - this->m_offsetX *= this->m_newWidth; - this->m_offsetY *= this->m_newWidth; - } - else { - this->m_offsetX *= this->m_newHeight; - this->m_offsetY *= this->m_newHeight; - } - } - - if (this->m_is_aspect) { - /* apply aspect from clip */ - const float w_src = this->m_inputOperation->getWidth(); - const float h_src = this->m_inputOperation->getHeight(); - - /* destination aspect is already applied from the camera frame */ - const float w_dst = this->m_newWidth; - const float h_dst = this->m_newHeight; - - const float asp_src = w_src / h_src; - const float asp_dst = w_dst / h_dst; - - if (fabsf(asp_src - asp_dst) >= FLT_EPSILON) { - if ((asp_src > asp_dst) == (this->m_is_crop == true)) { - /* fit X */ - const float div = asp_src / asp_dst; - this->m_relX /= div; - this->m_offsetX += ((w_src - (w_src * div)) / (w_src / w_dst)) / 2.0f; - } - else { - /* fit Y */ - const float div = asp_dst / asp_src; - this->m_relY /= div; - this->m_offsetY += ((h_src - (h_src * div)) / (h_src / h_dst)) / 2.0f; - } - - this->m_is_offset = true; - } - } - /* *** end framing options *** */ + this->m_inputOperation = this->getInputSocketReader(0); + this->m_relX = this->m_inputOperation->getWidth() / (float)this->m_newWidth; + this->m_relY = this->m_inputOperation->getHeight() / (float)this->m_newHeight; + + /* *** all the options below are for a fairly special case - camera framing *** */ + if (this->m_offsetX != 0.0f || this->m_offsetY != 0.0f) { + this->m_is_offset = true; + + if (this->m_newWidth > this->m_newHeight) { + this->m_offsetX *= this->m_newWidth; + this->m_offsetY *= this->m_newWidth; + } + else { + this->m_offsetX *= this->m_newHeight; + this->m_offsetY *= this->m_newHeight; + } + } + + if (this->m_is_aspect) { + /* apply aspect from clip */ + const float w_src = this->m_inputOperation->getWidth(); + const float h_src = this->m_inputOperation->getHeight(); + + /* destination aspect is already applied from the camera frame */ + const float w_dst = this->m_newWidth; + const float h_dst = this->m_newHeight; + + const float asp_src = w_src / h_src; + const float asp_dst = w_dst / h_dst; + + if (fabsf(asp_src - asp_dst) >= FLT_EPSILON) { + if ((asp_src > asp_dst) == (this->m_is_crop == true)) { + /* fit X */ + const float div = asp_src / asp_dst; + this->m_relX /= div; + this->m_offsetX += ((w_src - (w_src * div)) / (w_src / w_dst)) / 2.0f; + } + else { + /* fit Y */ + const float div = asp_dst / asp_src; + this->m_relY /= div; + this->m_offsetY += ((h_src - (h_src * div)) / (h_src / h_dst)) / 2.0f; + } + + this->m_is_offset = true; + } + } + /* *** end framing options *** */ } void ScaleFixedSizeOperation::deinitExecution() { - this->m_inputOperation = NULL; + this->m_inputOperation = NULL; } - -void ScaleFixedSizeOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ScaleFixedSizeOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - PixelSampler effective_sampler = getEffectiveSampler(sampler); - - if (this->m_is_offset) { - float nx = ((x - this->m_offsetX) * this->m_relX); - float ny = ((y - this->m_offsetY) * this->m_relY); - this->m_inputOperation->readSampled(output, nx, ny, effective_sampler); - } - else { - this->m_inputOperation->readSampled(output, x * this->m_relX, y * this->m_relY, effective_sampler); - } + PixelSampler effective_sampler = getEffectiveSampler(sampler); + + if (this->m_is_offset) { + float nx = ((x - this->m_offsetX) * this->m_relX); + float ny = ((y - this->m_offsetY) * this->m_relY); + this->m_inputOperation->readSampled(output, nx, ny, effective_sampler); + } + else { + this->m_inputOperation->readSampled( + output, x * this->m_relX, y * this->m_relY, effective_sampler); + } } -bool ScaleFixedSizeOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool ScaleFixedSizeOperation::determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output) { - rcti newInput; + rcti newInput; - newInput.xmax = (input->xmax - m_offsetX) * this->m_relX + 1; - newInput.xmin = (input->xmin - m_offsetX) * this->m_relX; - newInput.ymax = (input->ymax - m_offsetY) * this->m_relY + 1; - newInput.ymin = (input->ymin - m_offsetY) * this->m_relY; + newInput.xmax = (input->xmax - m_offsetX) * this->m_relX + 1; + newInput.xmin = (input->xmin - m_offsetX) * this->m_relX; + newInput.ymax = (input->ymax - m_offsetY) * this->m_relY + 1; + newInput.ymin = (input->ymin - m_offsetY) * this->m_relY; - return BaseScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + return BaseScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } -void ScaleFixedSizeOperation::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2]) +void ScaleFixedSizeOperation::determineResolution(unsigned int resolution[2], + unsigned int /*preferredResolution*/[2]) { - unsigned int nr[2]; - nr[0] = this->m_newWidth; - nr[1] = this->m_newHeight; - BaseScaleOperation::determineResolution(resolution, nr); - resolution[0] = this->m_newWidth; - resolution[1] = this->m_newHeight; + unsigned int nr[2]; + nr[0] = this->m_newWidth; + nr[1] = this->m_newHeight; + BaseScaleOperation::determineResolution(resolution, nr); + resolution[0] = this->m_newWidth; + resolution[1] = this->m_newHeight; } diff --git a/source/blender/compositor/operations/COM_ScaleOperation.h b/source/blender/compositor/operations/COM_ScaleOperation.h index d761e441419..28e32ff8606 100644 --- a/source/blender/compositor/operations/COM_ScaleOperation.h +++ b/source/blender/compositor/operations/COM_ScaleOperation.h @@ -22,79 +22,112 @@ #include "COM_NodeOperation.h" class BaseScaleOperation : public NodeOperation { -public: - void setSampler(PixelSampler sampler) { this->m_sampler = (int) sampler; } - void setVariableSize(bool variable_size) { m_variable_size = variable_size; }; + public: + void setSampler(PixelSampler sampler) + { + this->m_sampler = (int)sampler; + } + void setVariableSize(bool variable_size) + { + m_variable_size = variable_size; + }; -protected: - BaseScaleOperation(); + protected: + BaseScaleOperation(); - PixelSampler getEffectiveSampler(PixelSampler sampler) { return (m_sampler == -1) ? sampler : (PixelSampler) m_sampler; } + PixelSampler getEffectiveSampler(PixelSampler sampler) + { + return (m_sampler == -1) ? sampler : (PixelSampler)m_sampler; + } - int m_sampler; - bool m_variable_size; + int m_sampler; + bool m_variable_size; }; class ScaleOperation : public BaseScaleOperation { -private: - SocketReader *m_inputOperation; - SocketReader *m_inputXOperation; - SocketReader *m_inputYOperation; - float m_centerX; - float m_centerY; -public: - ScaleOperation(); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - - void initExecution(); - void deinitExecution(); + private: + SocketReader *m_inputOperation; + SocketReader *m_inputXOperation; + SocketReader *m_inputYOperation; + float m_centerX; + float m_centerY; + + public: + ScaleOperation(); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + + void initExecution(); + void deinitExecution(); }; class ScaleAbsoluteOperation : public BaseScaleOperation { - SocketReader *m_inputOperation; - SocketReader *m_inputXOperation; - SocketReader *m_inputYOperation; - float m_centerX; - float m_centerY; - -public: - ScaleAbsoluteOperation(); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - - void initExecution(); - void deinitExecution(); + SocketReader *m_inputOperation; + SocketReader *m_inputXOperation; + SocketReader *m_inputYOperation; + float m_centerX; + float m_centerY; + + public: + ScaleAbsoluteOperation(); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + + void initExecution(); + void deinitExecution(); }; class ScaleFixedSizeOperation : public BaseScaleOperation { - SocketReader *m_inputOperation; - int m_newWidth; - int m_newHeight; - float m_relX; - float m_relY; - - /* center is only used for aspect correction */ - float m_offsetX; - float m_offsetY; - bool m_is_aspect; - bool m_is_crop; - /* set from other properties on initialization, - * check if we need to apply offset */ - bool m_is_offset; -public: - ScaleFixedSizeOperation(); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - - void initExecution(); - void deinitExecution(); - void setNewWidth(int width) { this->m_newWidth = width; } - void setNewHeight(int height) { this->m_newHeight = height; } - void setIsAspect(bool is_aspect) { this->m_is_aspect = is_aspect; } - void setIsCrop(bool is_crop) { this->m_is_crop = is_crop; } - void setOffset(float x, float y) { this->m_offsetX = x; this->m_offsetY = y; } + SocketReader *m_inputOperation; + int m_newWidth; + int m_newHeight; + float m_relX; + float m_relY; + + /* center is only used for aspect correction */ + float m_offsetX; + float m_offsetY; + bool m_is_aspect; + bool m_is_crop; + /* set from other properties on initialization, + * check if we need to apply offset */ + bool m_is_offset; + + public: + ScaleFixedSizeOperation(); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + + void initExecution(); + void deinitExecution(); + void setNewWidth(int width) + { + this->m_newWidth = width; + } + void setNewHeight(int height) + { + this->m_newHeight = height; + } + void setIsAspect(bool is_aspect) + { + this->m_is_aspect = is_aspect; + } + void setIsCrop(bool is_crop) + { + this->m_is_crop = is_crop; + } + void setOffset(float x, float y) + { + this->m_offsetX = x; + this->m_offsetY = y; + } }; #endif diff --git a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp index 0d7eb189c90..eeefb2a9f3b 100644 --- a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp @@ -19,323 +19,333 @@ #include "COM_ScreenLensDistortionOperation.h" extern "C" { -# include "BLI_math.h" -# include "BLI_utildefines.h" -# include "BLI_rand.h" -# include "PIL_time.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" +#include "BLI_rand.h" +#include "PIL_time.h" } ScreenLensDistortionOperation::ScreenLensDistortionOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_COLOR); - this->setComplex(true); - this->m_inputProgram = NULL; - this->m_distortion = 0.0f; - this->m_dispersion = 0.0f; - this->m_distortion_const = false; - this->m_dispersion_const = false; - this->m_variables_ready = false; + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_COLOR); + this->setComplex(true); + this->m_inputProgram = NULL; + this->m_distortion = 0.0f; + this->m_dispersion = 0.0f; + this->m_distortion_const = false; + this->m_dispersion_const = false; + this->m_variables_ready = false; } void ScreenLensDistortionOperation::setDistortion(float distortion) { - m_distortion = distortion; - m_distortion_const = true; + m_distortion = distortion; + m_distortion_const = true; } void ScreenLensDistortionOperation::setDispersion(float dispersion) { - m_dispersion = dispersion; - m_dispersion_const = true; + m_dispersion = dispersion; + m_dispersion_const = true; } void ScreenLensDistortionOperation::initExecution() { - this->m_inputProgram = this->getInputSocketReader(0); - this->initMutex(); + this->m_inputProgram = this->getInputSocketReader(0); + this->initMutex(); - uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX); - rng_seed ^= (uint)POINTER_AS_INT(m_inputProgram); - this->m_rng = BLI_rng_new(rng_seed); + uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX); + rng_seed ^= (uint)POINTER_AS_INT(m_inputProgram); + this->m_rng = BLI_rng_new(rng_seed); - this->m_cx = 0.5f * (float)getWidth(); - this->m_cy = 0.5f * (float)getHeight(); + this->m_cx = 0.5f * (float)getWidth(); + this->m_cy = 0.5f * (float)getHeight(); - /* if both are constant, init variables once */ - if (m_distortion_const && m_dispersion_const) { - updateVariables(m_distortion, m_dispersion); - m_variables_ready = true; - } + /* if both are constant, init variables once */ + if (m_distortion_const && m_dispersion_const) { + updateVariables(m_distortion, m_dispersion); + m_variables_ready = true; + } } void *ScreenLensDistortionOperation::initializeTileData(rcti * /*rect*/) { - void *buffer = this->m_inputProgram->initializeTileData(NULL); - - /* get distortion/dispersion values once, by reading inputs at (0,0) - * XXX this assumes invariable values (no image inputs), - * we don't have a nice generic system for that yet - */ - if (!m_variables_ready) { - this->lockMutex(); - - if (!m_distortion_const) { - float result[4]; - getInputSocketReader(1)->readSampled(result, 0, 0, COM_PS_NEAREST); - m_distortion = result[0]; - } - if (!m_dispersion_const) { - float result[4]; - getInputSocketReader(2)->readSampled(result, 0, 0, COM_PS_NEAREST); - m_dispersion = result[0]; - } - - updateVariables(m_distortion, m_dispersion); - m_variables_ready = true; - - this->unlockMutex(); - } - - return buffer; + void *buffer = this->m_inputProgram->initializeTileData(NULL); + + /* get distortion/dispersion values once, by reading inputs at (0,0) + * XXX this assumes invariable values (no image inputs), + * we don't have a nice generic system for that yet + */ + if (!m_variables_ready) { + this->lockMutex(); + + if (!m_distortion_const) { + float result[4]; + getInputSocketReader(1)->readSampled(result, 0, 0, COM_PS_NEAREST); + m_distortion = result[0]; + } + if (!m_dispersion_const) { + float result[4]; + getInputSocketReader(2)->readSampled(result, 0, 0, COM_PS_NEAREST); + m_dispersion = result[0]; + } + + updateVariables(m_distortion, m_dispersion); + m_variables_ready = true; + + this->unlockMutex(); + } + + return buffer; } void ScreenLensDistortionOperation::get_uv(const float xy[2], float uv[2]) const { - uv[0] = m_sc * ((xy[0] + 0.5f) - m_cx) / m_cx; - uv[1] = m_sc * ((xy[1] + 0.5f) - m_cy) / m_cy; + uv[0] = m_sc * ((xy[0] + 0.5f) - m_cx) / m_cx; + uv[1] = m_sc * ((xy[1] + 0.5f) - m_cy) / m_cy; } void ScreenLensDistortionOperation::distort_uv(const float uv[2], float t, float xy[2]) const { - float d = 1.0f / (1.0f + sqrtf(t)); - xy[0] = (uv[0] * d + 0.5f) * getWidth() - 0.5f; - xy[1] = (uv[1] * d + 0.5f) * getHeight() - 0.5f; + float d = 1.0f / (1.0f + sqrtf(t)); + xy[0] = (uv[0] * d + 0.5f) * getWidth() - 0.5f; + xy[1] = (uv[1] * d + 0.5f) * getHeight() - 0.5f; } -bool ScreenLensDistortionOperation::get_delta(float r_sq, float k4, const float uv[2], float delta[2]) const +bool ScreenLensDistortionOperation::get_delta(float r_sq, + float k4, + const float uv[2], + float delta[2]) const { - float t = 1.0f - k4 * r_sq; - if (t >= 0.0f) { - distort_uv(uv, t, delta); - return true; - } - else - return false; - + float t = 1.0f - k4 * r_sq; + if (t >= 0.0f) { + distort_uv(uv, t, delta); + return true; + } + else + return false; } void ScreenLensDistortionOperation::accumulate(MemoryBuffer *buffer, - int a, int b, - float r_sq, const float uv[2], + int a, + int b, + float r_sq, + const float uv[2], const float delta[3][2], - float sum[4], int count[3]) const + float sum[4], + int count[3]) const { - float color[4]; + float color[4]; - float dsf = len_v2v2(delta[a], delta[b]) + 1.0f; - int ds = m_jitter ? (dsf < 4.0f ? 2 : (int)sqrtf(dsf)) : (int)dsf; - float sd = 1.0f / (float)ds; + float dsf = len_v2v2(delta[a], delta[b]) + 1.0f; + int ds = m_jitter ? (dsf < 4.0f ? 2 : (int)sqrtf(dsf)) : (int)dsf; + float sd = 1.0f / (float)ds; - float k4 = m_k4[a]; - float dk4 = m_dk4[a]; + float k4 = m_k4[a]; + float dk4 = m_dk4[a]; - for (float z = 0; z < ds; ++z) { - float tz = (z + (m_jitter ? BLI_rng_get_float(m_rng) : 0.5f)) * sd; - float t = 1.0f - (k4 + tz * dk4) * r_sq; + for (float z = 0; z < ds; ++z) { + float tz = (z + (m_jitter ? BLI_rng_get_float(m_rng) : 0.5f)) * sd; + float t = 1.0f - (k4 + tz * dk4) * r_sq; - float xy[2]; - distort_uv(uv, t, xy); - buffer->readBilinear(color, xy[0], xy[1]); + float xy[2]; + distort_uv(uv, t, xy); + buffer->readBilinear(color, xy[0], xy[1]); - sum[a] += (1.0f - tz) * color[a]; - sum[b] += (tz ) * color[b]; - count[a]++; - count[b]++; - } + sum[a] += (1.0f - tz) * color[a]; + sum[b] += (tz)*color[b]; + count[a]++; + count[b]++; + } } void ScreenLensDistortionOperation::executePixel(float output[4], int x, int y, void *data) { - MemoryBuffer *buffer = (MemoryBuffer *)data; - float xy[2] = { (float)x, (float)y }; - float uv[2]; - get_uv(xy, uv); - float uv_dot = len_squared_v2(uv); - - int count[3] = { 0, 0, 0 }; - float delta[3][2]; - float sum[4] = { 0, 0, 0, 0 }; - - bool valid_r = get_delta(uv_dot, m_k4[0], uv, delta[0]); - bool valid_g = get_delta(uv_dot, m_k4[1], uv, delta[1]); - bool valid_b = get_delta(uv_dot, m_k4[2], uv, delta[2]); - - if (valid_r && valid_g && valid_b) { - accumulate(buffer, 0, 1, uv_dot, uv, delta, sum, count); - accumulate(buffer, 1, 2, uv_dot, uv, delta, sum, count); - - if (count[0]) output[0] = 2.0f * sum[0] / (float)count[0]; - if (count[1]) output[1] = 2.0f * sum[1] / (float)count[1]; - if (count[2]) output[2] = 2.0f * sum[2] / (float)count[2]; - - /* set alpha */ - output[3] = 1.0f; - } - else { - zero_v4(output); - } + MemoryBuffer *buffer = (MemoryBuffer *)data; + float xy[2] = {(float)x, (float)y}; + float uv[2]; + get_uv(xy, uv); + float uv_dot = len_squared_v2(uv); + + int count[3] = {0, 0, 0}; + float delta[3][2]; + float sum[4] = {0, 0, 0, 0}; + + bool valid_r = get_delta(uv_dot, m_k4[0], uv, delta[0]); + bool valid_g = get_delta(uv_dot, m_k4[1], uv, delta[1]); + bool valid_b = get_delta(uv_dot, m_k4[2], uv, delta[2]); + + if (valid_r && valid_g && valid_b) { + accumulate(buffer, 0, 1, uv_dot, uv, delta, sum, count); + accumulate(buffer, 1, 2, uv_dot, uv, delta, sum, count); + + if (count[0]) + output[0] = 2.0f * sum[0] / (float)count[0]; + if (count[1]) + output[1] = 2.0f * sum[1] / (float)count[1]; + if (count[2]) + output[2] = 2.0f * sum[2] / (float)count[2]; + + /* set alpha */ + output[3] = 1.0f; + } + else { + zero_v4(output); + } } void ScreenLensDistortionOperation::deinitExecution() { - this->deinitMutex(); - this->m_inputProgram = NULL; - BLI_rng_free(this->m_rng); + this->deinitMutex(); + this->m_inputProgram = NULL; + BLI_rng_free(this->m_rng); } void ScreenLensDistortionOperation::determineUV(float result[6], float x, float y) const { - const float xy[2] = {x, y}; - float uv[2]; - get_uv(xy, uv); - float uv_dot = len_squared_v2(uv); - - copy_v2_v2(result + 0, xy); - copy_v2_v2(result + 2, xy); - copy_v2_v2(result + 4, xy); - get_delta(uv_dot, m_k4[0], uv, result + 0); - get_delta(uv_dot, m_k4[1], uv, result + 2); - get_delta(uv_dot, m_k4[2], uv, result + 4); + const float xy[2] = {x, y}; + float uv[2]; + get_uv(xy, uv); + float uv_dot = len_squared_v2(uv); + + copy_v2_v2(result + 0, xy); + copy_v2_v2(result + 2, xy); + copy_v2_v2(result + 4, xy); + get_delta(uv_dot, m_k4[0], uv, result + 0); + get_delta(uv_dot, m_k4[1], uv, result + 2); + get_delta(uv_dot, m_k4[2], uv, result + 4); } -bool ScreenLensDistortionOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output) +bool ScreenLensDistortionOperation::determineDependingAreaOfInterest( + rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output) { - rcti newInputValue; - newInputValue.xmin = 0; - newInputValue.ymin = 0; - newInputValue.xmax = 2; - newInputValue.ymax = 2; - - NodeOperation *operation = getInputOperation(1); - if (operation->determineDependingAreaOfInterest(&newInputValue, readOperation, output) ) { - return true; - } - - operation = getInputOperation(2); - if (operation->determineDependingAreaOfInterest(&newInputValue, readOperation, output) ) { - return true; - } - - /* XXX the original method of estimating the area-of-interest does not work - * it assumes a linear increase/decrease of mapped coordinates, which does not - * yield correct results for the area and leaves uninitialized buffer areas. - * So now just use the full image area, which may not be as efficient but works at least ... - */ + rcti newInputValue; + newInputValue.xmin = 0; + newInputValue.ymin = 0; + newInputValue.xmax = 2; + newInputValue.ymax = 2; + + NodeOperation *operation = getInputOperation(1); + if (operation->determineDependingAreaOfInterest(&newInputValue, readOperation, output)) { + return true; + } + + operation = getInputOperation(2); + if (operation->determineDependingAreaOfInterest(&newInputValue, readOperation, output)) { + return true; + } + + /* XXX the original method of estimating the area-of-interest does not work + * it assumes a linear increase/decrease of mapped coordinates, which does not + * yield correct results for the area and leaves uninitialized buffer areas. + * So now just use the full image area, which may not be as efficient but works at least ... + */ #if 1 - rcti imageInput; - - operation = getInputOperation(0); - imageInput.xmax = operation->getWidth(); - imageInput.xmin = 0; - imageInput.ymax = operation->getHeight(); - imageInput.ymin = 0; - - if (operation->determineDependingAreaOfInterest(&imageInput, readOperation, output) ) { - return true; - } - return false; + rcti imageInput; + + operation = getInputOperation(0); + imageInput.xmax = operation->getWidth(); + imageInput.xmin = 0; + imageInput.ymax = operation->getHeight(); + imageInput.ymin = 0; + + if (operation->determineDependingAreaOfInterest(&imageInput, readOperation, output)) { + return true; + } + return false; #else - rcti newInput; - const float margin = 2; - - BLI_rcti_init_minmax(&newInput); - - if (m_dispersion_const && m_distortion_const) { - /* update from fixed distortion/dispersion */ -#define UPDATE_INPUT(x, y) \ - { \ - float coords[6]; \ - determineUV(coords, x, y); \ - newInput.xmin = min_ffff(newInput.xmin, coords[0], coords[2], coords[4]); \ - newInput.ymin = min_ffff(newInput.ymin, coords[1], coords[3], coords[5]); \ - newInput.xmax = max_ffff(newInput.xmax, coords[0], coords[2], coords[4]); \ - newInput.ymax = max_ffff(newInput.ymax, coords[1], coords[3], coords[5]); \ - } (void)0 - - UPDATE_INPUT(input->xmin, input->xmax); - UPDATE_INPUT(input->xmin, input->ymax); - UPDATE_INPUT(input->xmax, input->ymax); - UPDATE_INPUT(input->xmax, input->ymin); - -#undef UPDATE_INPUT - } - else { - /* use maximum dispersion 1.0 if not const */ - float dispersion = m_dispersion_const ? m_dispersion : 1.0f; - -#define UPDATE_INPUT(x, y, distortion) \ - { \ - float coords[6]; \ - updateVariables(distortion, dispersion); \ - determineUV(coords, x, y); \ - newInput.xmin = min_ffff(newInput.xmin, coords[0], coords[2], coords[4]); \ - newInput.ymin = min_ffff(newInput.ymin, coords[1], coords[3], coords[5]); \ - newInput.xmax = max_ffff(newInput.xmax, coords[0], coords[2], coords[4]); \ - newInput.ymax = max_ffff(newInput.ymax, coords[1], coords[3], coords[5]); \ - } (void)0 - - if (m_distortion_const) { - /* update from fixed distortion */ - UPDATE_INPUT(input->xmin, input->xmax, m_distortion); - UPDATE_INPUT(input->xmin, input->ymax, m_distortion); - UPDATE_INPUT(input->xmax, input->ymax, m_distortion); - UPDATE_INPUT(input->xmax, input->ymin, m_distortion); - } - else { - /* update from min/max distortion (-1..1) */ - UPDATE_INPUT(input->xmin, input->xmax, -1.0f); - UPDATE_INPUT(input->xmin, input->ymax, -1.0f); - UPDATE_INPUT(input->xmax, input->ymax, -1.0f); - UPDATE_INPUT(input->xmax, input->ymin, -1.0f); - - UPDATE_INPUT(input->xmin, input->xmax, 1.0f); - UPDATE_INPUT(input->xmin, input->ymax, 1.0f); - UPDATE_INPUT(input->xmax, input->ymax, 1.0f); - UPDATE_INPUT(input->xmax, input->ymin, 1.0f); - -#undef UPDATE_INPUT - } - } - - newInput.xmin -= margin; - newInput.ymin -= margin; - newInput.xmax += margin; - newInput.ymax += margin; - - operation = getInputOperation(0); - if (operation->determineDependingAreaOfInterest(&newInput, readOperation, output)) { - return true; - } - return false; + rcti newInput; + const float margin = 2; + + BLI_rcti_init_minmax(&newInput); + + if (m_dispersion_const && m_distortion_const) { + /* update from fixed distortion/dispersion */ +# define UPDATE_INPUT(x, y) \ + { \ + float coords[6]; \ + determineUV(coords, x, y); \ + newInput.xmin = min_ffff(newInput.xmin, coords[0], coords[2], coords[4]); \ + newInput.ymin = min_ffff(newInput.ymin, coords[1], coords[3], coords[5]); \ + newInput.xmax = max_ffff(newInput.xmax, coords[0], coords[2], coords[4]); \ + newInput.ymax = max_ffff(newInput.ymax, coords[1], coords[3], coords[5]); \ + } \ + (void)0 + + UPDATE_INPUT(input->xmin, input->xmax); + UPDATE_INPUT(input->xmin, input->ymax); + UPDATE_INPUT(input->xmax, input->ymax); + UPDATE_INPUT(input->xmax, input->ymin); + +# undef UPDATE_INPUT + } + else { + /* use maximum dispersion 1.0 if not const */ + float dispersion = m_dispersion_const ? m_dispersion : 1.0f; + +# define UPDATE_INPUT(x, y, distortion) \ + { \ + float coords[6]; \ + updateVariables(distortion, dispersion); \ + determineUV(coords, x, y); \ + newInput.xmin = min_ffff(newInput.xmin, coords[0], coords[2], coords[4]); \ + newInput.ymin = min_ffff(newInput.ymin, coords[1], coords[3], coords[5]); \ + newInput.xmax = max_ffff(newInput.xmax, coords[0], coords[2], coords[4]); \ + newInput.ymax = max_ffff(newInput.ymax, coords[1], coords[3], coords[5]); \ + } \ + (void)0 + + if (m_distortion_const) { + /* update from fixed distortion */ + UPDATE_INPUT(input->xmin, input->xmax, m_distortion); + UPDATE_INPUT(input->xmin, input->ymax, m_distortion); + UPDATE_INPUT(input->xmax, input->ymax, m_distortion); + UPDATE_INPUT(input->xmax, input->ymin, m_distortion); + } + else { + /* update from min/max distortion (-1..1) */ + UPDATE_INPUT(input->xmin, input->xmax, -1.0f); + UPDATE_INPUT(input->xmin, input->ymax, -1.0f); + UPDATE_INPUT(input->xmax, input->ymax, -1.0f); + UPDATE_INPUT(input->xmax, input->ymin, -1.0f); + + UPDATE_INPUT(input->xmin, input->xmax, 1.0f); + UPDATE_INPUT(input->xmin, input->ymax, 1.0f); + UPDATE_INPUT(input->xmax, input->ymax, 1.0f); + UPDATE_INPUT(input->xmax, input->ymin, 1.0f); + +# undef UPDATE_INPUT + } + } + + newInput.xmin -= margin; + newInput.ymin -= margin; + newInput.xmax += margin; + newInput.ymax += margin; + + operation = getInputOperation(0); + if (operation->determineDependingAreaOfInterest(&newInput, readOperation, output)) { + return true; + } + return false; #endif } void ScreenLensDistortionOperation::updateVariables(float distortion, float dispersion) { - m_k[1] = max_ff(min_ff(distortion, 1.0f), -0.999f); - // smaller dispersion range for somewhat more control - float d = 0.25f * max_ff(min_ff(dispersion, 1.0f), 0.0f); - m_k[0] = max_ff(min_ff((m_k[1] + d), 1.0f), -0.999f); - m_k[2] = max_ff(min_ff((m_k[1] - d), 1.0f), -0.999f); - m_maxk = max_fff(m_k[0], m_k[1], m_k[2]); - m_sc = (m_fit && (m_maxk > 0.0f)) ? (1.0f / (1.0f + 2.0f * m_maxk)) : - (1.0f / (1.0f + m_maxk)); - m_dk4[0] = 4.0f * (m_k[1] - m_k[0]); - m_dk4[1] = 4.0f * (m_k[2] - m_k[1]); - m_dk4[2] = 0.0f; /* unused */ - - mul_v3_v3fl(m_k4, m_k, 4.0f); + m_k[1] = max_ff(min_ff(distortion, 1.0f), -0.999f); + // smaller dispersion range for somewhat more control + float d = 0.25f * max_ff(min_ff(dispersion, 1.0f), 0.0f); + m_k[0] = max_ff(min_ff((m_k[1] + d), 1.0f), -0.999f); + m_k[2] = max_ff(min_ff((m_k[1] - d), 1.0f), -0.999f); + m_maxk = max_fff(m_k[0], m_k[1], m_k[2]); + m_sc = (m_fit && (m_maxk > 0.0f)) ? (1.0f / (1.0f + 2.0f * m_maxk)) : (1.0f / (1.0f + m_maxk)); + m_dk4[0] = 4.0f * (m_k[1] - m_k[0]); + m_dk4[1] = 4.0f * (m_k[2] - m_k[1]); + m_dk4[2] = 0.0f; /* unused */ + + mul_v3_v3fl(m_k4, m_k, 4.0f); } diff --git a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h index c419378a2a6..c9db5bc88b8 100644 --- a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h +++ b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h @@ -22,64 +22,78 @@ #include "DNA_node_types.h" class ScreenLensDistortionOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputProgram; - struct RNG *m_rng; + private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputProgram; + struct RNG *m_rng; - bool m_fit; - bool m_jitter; + bool m_fit; + bool m_jitter; - float m_dispersion; - float m_distortion; - bool m_dispersion_const; - bool m_distortion_const; - bool m_variables_ready; - float m_k[3]; - float m_k4[3]; - float m_dk4[3]; - float m_maxk; - float m_sc, m_cx, m_cy; -public: - ScreenLensDistortionOperation(); + float m_dispersion; + float m_distortion; + bool m_dispersion_const; + bool m_distortion_const; + bool m_variables_ready; + float m_k[3]; + float m_k4[3]; + float m_dk4[3]; + float m_maxk; + float m_sc, m_cx, m_cy; - /** - * the inner loop of this program - */ - void executePixel(float output[4], int x, int y, void *data); + public: + ScreenLensDistortionOperation(); - /** - * Initialize the execution - */ - void initExecution(); + /** + * the inner loop of this program + */ + void executePixel(float output[4], int x, int y, void *data); - void *initializeTileData(rcti *rect); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Initialize the execution + */ + void initExecution(); - void setFit(bool fit) { m_fit = fit; } - void setJitter(bool jitter) { m_jitter = jitter; } + void *initializeTileData(rcti *rect); + /** + * Deinitialize the execution + */ + void deinitExecution(); - /** Set constant distortion value */ - void setDistortion(float distortion); - /** Set constant dispersion value */ - void setDispersion(float dispersion); + void setFit(bool fit) + { + m_fit = fit; + } + void setJitter(bool jitter) + { + m_jitter = jitter; + } - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + /** Set constant distortion value */ + void setDistortion(float distortion); + /** Set constant dispersion value */ + void setDispersion(float dispersion); -private: - void determineUV(float result[6], float x, float y) const; - void updateVariables(float distortion, float dispersion); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); - void get_uv(const float xy[2], float uv[2]) const; - void distort_uv(const float uv[2], float t, float xy[2]) const; - bool get_delta(float r_sq, float k4, const float uv[2], float delta[2]) const; - void accumulate(MemoryBuffer *buffer, int a, int b, - float r_sq, const float uv[2], const float delta[3][2], - float sum[4], int count[3]) const; + private: + void determineUV(float result[6], float x, float y) const; + void updateVariables(float distortion, float dispersion); + + void get_uv(const float xy[2], float uv[2]) const; + void distort_uv(const float uv[2], float t, float xy[2]) const; + bool get_delta(float r_sq, float k4, const float uv[2], float delta[2]) const; + void accumulate(MemoryBuffer *buffer, + int a, + int b, + float r_sq, + const float uv[2], + const float delta[3][2], + float sum[4], + int count[3]) const; }; #endif diff --git a/source/blender/compositor/operations/COM_SetAlphaOperation.cpp b/source/blender/compositor/operations/COM_SetAlphaOperation.cpp index 441e0835c95..68c165411b2 100644 --- a/source/blender/compositor/operations/COM_SetAlphaOperation.cpp +++ b/source/blender/compositor/operations/COM_SetAlphaOperation.cpp @@ -20,32 +20,35 @@ SetAlphaOperation::SetAlphaOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_COLOR); - this->m_inputColor = NULL; - this->m_inputAlpha = NULL; + this->m_inputColor = NULL; + this->m_inputAlpha = NULL; } void SetAlphaOperation::initExecution() { - this->m_inputColor = getInputSocketReader(0); - this->m_inputAlpha = getInputSocketReader(1); + this->m_inputColor = getInputSocketReader(0); + this->m_inputAlpha = getInputSocketReader(1); } -void SetAlphaOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void SetAlphaOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float alphaInput[4]; + float alphaInput[4]; - this->m_inputColor->readSampled(output, x, y, sampler); - this->m_inputAlpha->readSampled(alphaInput, x, y, sampler); + this->m_inputColor->readSampled(output, x, y, sampler); + this->m_inputAlpha->readSampled(alphaInput, x, y, sampler); - output[3] = alphaInput[0]; + output[3] = alphaInput[0]; } void SetAlphaOperation::deinitExecution() { - this->m_inputColor = NULL; - this->m_inputAlpha = NULL; + this->m_inputColor = NULL; + this->m_inputAlpha = NULL; } diff --git a/source/blender/compositor/operations/COM_SetAlphaOperation.h b/source/blender/compositor/operations/COM_SetAlphaOperation.h index 38cd5135406..24f80b71eae 100644 --- a/source/blender/compositor/operations/COM_SetAlphaOperation.h +++ b/source/blender/compositor/operations/COM_SetAlphaOperation.h @@ -20,28 +20,27 @@ #define __COM_SETALPHAOPERATION_H__ #include "COM_NodeOperation.h" - /** * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ class SetAlphaOperation : public NodeOperation { -private: - SocketReader *m_inputColor; - SocketReader *m_inputAlpha; + private: + SocketReader *m_inputColor; + SocketReader *m_inputAlpha; -public: - /** - * Default constructor - */ - SetAlphaOperation(); + public: + /** + * Default constructor + */ + SetAlphaOperation(); - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - void initExecution(); - void deinitExecution(); + void initExecution(); + void deinitExecution(); }; #endif diff --git a/source/blender/compositor/operations/COM_SetColorOperation.cpp b/source/blender/compositor/operations/COM_SetColorOperation.cpp index d80ed6eb1ca..58bfcb44afd 100644 --- a/source/blender/compositor/operations/COM_SetColorOperation.cpp +++ b/source/blender/compositor/operations/COM_SetColorOperation.cpp @@ -20,18 +20,20 @@ SetColorOperation::SetColorOperation() : NodeOperation() { - this->addOutputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); } void SetColorOperation::executePixelSampled(float output[4], - float /*x*/, float /*y*/, + float /*x*/, + float /*y*/, PixelSampler /*sampler*/) { - copy_v4_v4(output, this->m_color); + copy_v4_v4(output, this->m_color); } -void SetColorOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +void SetColorOperation::determineResolution(unsigned int resolution[2], + unsigned int preferredResolution[2]) { - resolution[0] = preferredResolution[0]; - resolution[1] = preferredResolution[1]; + resolution[0] = preferredResolution[0]; + resolution[1] = preferredResolution[1]; } diff --git a/source/blender/compositor/operations/COM_SetColorOperation.h b/source/blender/compositor/operations/COM_SetColorOperation.h index 376e4633ac8..d16d3806864 100644 --- a/source/blender/compositor/operations/COM_SetColorOperation.h +++ b/source/blender/compositor/operations/COM_SetColorOperation.h @@ -20,41 +20,66 @@ #define __COM_SETCOLOROPERATION_H__ #include "COM_NodeOperation.h" - /** * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ class SetColorOperation : public NodeOperation { -private: - float m_color[4]; - -public: - /** - * Default constructor - */ - SetColorOperation(); + private: + float m_color[4]; - float getChannel1() { return this->m_color[0]; } - void setChannel1(float value) { this->m_color[0] = value; } - float getChannel2() { return this->m_color[1]; } - void setChannel2(float value) { this->m_color[1] = value; } - float getChannel3() { return this->m_color[2]; } - void setChannel3(float value) { this->m_color[2] = value; } - float getChannel4() { return this->m_color[3]; } - void setChannel4(const float value) { this->m_color[3] = value; } - void setChannels(const float value[4]) - { - copy_v4_v4(this->m_color, value); - } + public: + /** + * Default constructor + */ + SetColorOperation(); - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + float getChannel1() + { + return this->m_color[0]; + } + void setChannel1(float value) + { + this->m_color[0] = value; + } + float getChannel2() + { + return this->m_color[1]; + } + void setChannel2(float value) + { + this->m_color[1] = value; + } + float getChannel3() + { + return this->m_color[2]; + } + void setChannel3(float value) + { + this->m_color[2] = value; + } + float getChannel4() + { + return this->m_color[3]; + } + void setChannel4(const float value) + { + this->m_color[3] = value; + } + void setChannels(const float value[4]) + { + copy_v4_v4(this->m_color, value); + } - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); - bool isSetOperation() const { return true; } + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); + bool isSetOperation() const + { + return true; + } }; #endif diff --git a/source/blender/compositor/operations/COM_SetSamplerOperation.cpp b/source/blender/compositor/operations/COM_SetSamplerOperation.cpp index 38039bbf6bb..f3b3ed217f9 100644 --- a/source/blender/compositor/operations/COM_SetSamplerOperation.cpp +++ b/source/blender/compositor/operations/COM_SetSamplerOperation.cpp @@ -20,20 +20,23 @@ SetSamplerOperation::SetSamplerOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); } void SetSamplerOperation::initExecution() { - this->m_reader = this->getInputSocketReader(0); + this->m_reader = this->getInputSocketReader(0); } void SetSamplerOperation::deinitExecution() { - this->m_reader = NULL; + this->m_reader = NULL; } -void SetSamplerOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) +void SetSamplerOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler /*sampler*/) { - this->m_reader->readSampled(output, x, y, this->m_sampler); + this->m_reader->readSampled(output, x, y, this->m_sampler); } diff --git a/source/blender/compositor/operations/COM_SetSamplerOperation.h b/source/blender/compositor/operations/COM_SetSamplerOperation.h index eaa8bbf744d..62f01129ff7 100644 --- a/source/blender/compositor/operations/COM_SetSamplerOperation.h +++ b/source/blender/compositor/operations/COM_SetSamplerOperation.h @@ -20,28 +20,31 @@ #define __COM_SETSAMPLEROPERATION_H__ #include "COM_NodeOperation.h" - /** * this program converts an input color to an output Sampler. * it assumes we are in sRGB color space. */ class SetSamplerOperation : public NodeOperation { -private: - PixelSampler m_sampler; - SocketReader *m_reader; -public: - /** - * Default constructor - */ - SetSamplerOperation(); + private: + PixelSampler m_sampler; + SocketReader *m_reader; + + public: + /** + * Default constructor + */ + SetSamplerOperation(); - void setSampler(PixelSampler sampler) { this->m_sampler = sampler; } + void setSampler(PixelSampler sampler) + { + this->m_sampler = sampler; + } - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - void initExecution(); - void deinitExecution(); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void initExecution(); + void deinitExecution(); }; #endif diff --git a/source/blender/compositor/operations/COM_SetValueOperation.cpp b/source/blender/compositor/operations/COM_SetValueOperation.cpp index 0aa1e2bcbef..e49b6941f49 100644 --- a/source/blender/compositor/operations/COM_SetValueOperation.cpp +++ b/source/blender/compositor/operations/COM_SetValueOperation.cpp @@ -20,18 +20,20 @@ SetValueOperation::SetValueOperation() : NodeOperation() { - this->addOutputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_VALUE); } void SetValueOperation::executePixelSampled(float output[4], - float /*x*/, float /*y*/, + float /*x*/, + float /*y*/, PixelSampler /*sampler*/) { - output[0] = this->m_value; + output[0] = this->m_value; } -void SetValueOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +void SetValueOperation::determineResolution(unsigned int resolution[2], + unsigned int preferredResolution[2]) { - resolution[0] = preferredResolution[0]; - resolution[1] = preferredResolution[1]; + resolution[0] = preferredResolution[0]; + resolution[1] = preferredResolution[1]; } diff --git a/source/blender/compositor/operations/COM_SetValueOperation.h b/source/blender/compositor/operations/COM_SetValueOperation.h index 59bcf28d012..6fb2832450d 100644 --- a/source/blender/compositor/operations/COM_SetValueOperation.h +++ b/source/blender/compositor/operations/COM_SetValueOperation.h @@ -20,31 +20,38 @@ #define __COM_SETVALUEOPERATION_H__ #include "COM_NodeOperation.h" - /** * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ class SetValueOperation : public NodeOperation { -private: - float m_value; - -public: - /** - * Default constructor - */ - SetValueOperation(); - - float getValue() { return this->m_value; } - void setValue(float value) { this->m_value = value; } - - - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); - - bool isSetOperation() const { return true; } + private: + float m_value; + + public: + /** + * Default constructor + */ + SetValueOperation(); + + float getValue() + { + return this->m_value; + } + void setValue(float value) + { + this->m_value = value; + } + + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); + + bool isSetOperation() const + { + return true; + } }; #endif diff --git a/source/blender/compositor/operations/COM_SetVectorOperation.cpp b/source/blender/compositor/operations/COM_SetVectorOperation.cpp index 29407df55e5..d3a0329c9b9 100644 --- a/source/blender/compositor/operations/COM_SetVectorOperation.cpp +++ b/source/blender/compositor/operations/COM_SetVectorOperation.cpp @@ -21,20 +21,22 @@ SetVectorOperation::SetVectorOperation() : NodeOperation() { - this->addOutputSocket(COM_DT_VECTOR); + this->addOutputSocket(COM_DT_VECTOR); } void SetVectorOperation::executePixelSampled(float output[4], - float /*x*/, float /*y*/, + float /*x*/, + float /*y*/, PixelSampler /*sampler*/) { - output[0] = this->m_x; - output[1] = this->m_y; - output[2] = this->m_z; + output[0] = this->m_x; + output[1] = this->m_y; + output[2] = this->m_z; } -void SetVectorOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +void SetVectorOperation::determineResolution(unsigned int resolution[2], + unsigned int preferredResolution[2]) { - resolution[0] = preferredResolution[0]; - resolution[1] = preferredResolution[1]; + resolution[0] = preferredResolution[0]; + resolution[1] = preferredResolution[1]; } diff --git a/source/blender/compositor/operations/COM_SetVectorOperation.h b/source/blender/compositor/operations/COM_SetVectorOperation.h index c00bd125dff..a2f9aaa6b3b 100644 --- a/source/blender/compositor/operations/COM_SetVectorOperation.h +++ b/source/blender/compositor/operations/COM_SetVectorOperation.h @@ -20,45 +20,72 @@ #define __COM_SETVECTOROPERATION_H__ #include "COM_NodeOperation.h" - /** * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ class SetVectorOperation : public NodeOperation { -private: - float m_x; - float m_y; - float m_z; - float m_w; + private: + float m_x; + float m_y; + float m_z; + float m_w; -public: - /** - * Default constructor - */ - SetVectorOperation(); + public: + /** + * Default constructor + */ + SetVectorOperation(); - float getX() { return this->m_x; } - void setX(float value) { this->m_x = value; } - float getY() { return this->m_y; } - void setY(float value) { this->m_y = value; } - float getZ() { return this->m_z; } - void setZ(float value) { this->m_z = value; } - float getW() { return this->m_w; } - void setW(float value) { this->m_w = value; } + float getX() + { + return this->m_x; + } + void setX(float value) + { + this->m_x = value; + } + float getY() + { + return this->m_y; + } + void setY(float value) + { + this->m_y = value; + } + float getZ() + { + return this->m_z; + } + void setZ(float value) + { + this->m_z = value; + } + float getW() + { + return this->m_w; + } + void setW(float value) + { + this->m_w = value; + } - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); - bool isSetOperation() const { return true; } + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); + bool isSetOperation() const + { + return true; + } - void setVector(const float vector[3]) { - setX(vector[0]); - setY(vector[1]); - setZ(vector[2]); - } + void setVector(const float vector[3]) + { + setX(vector[0]); + setY(vector[1]); + setZ(vector[2]); + } }; #endif diff --git a/source/blender/compositor/operations/COM_SocketProxyOperation.cpp b/source/blender/compositor/operations/COM_SocketProxyOperation.cpp index 83ed7af1ffb..2d54d6ae45d 100644 --- a/source/blender/compositor/operations/COM_SocketProxyOperation.cpp +++ b/source/blender/compositor/operations/COM_SocketProxyOperation.cpp @@ -18,10 +18,9 @@ #include "COM_SocketProxyOperation.h" -SocketProxyOperation::SocketProxyOperation(DataType type, bool use_conversion) : - NodeOperation(), - m_use_conversion(use_conversion) +SocketProxyOperation::SocketProxyOperation(DataType type, bool use_conversion) + : NodeOperation(), m_use_conversion(use_conversion) { - this->addInputSocket(type); - this->addOutputSocket(type); + this->addInputSocket(type); + this->addOutputSocket(type); } diff --git a/source/blender/compositor/operations/COM_SocketProxyOperation.h b/source/blender/compositor/operations/COM_SocketProxyOperation.h index 47856031219..3855c26088a 100644 --- a/source/blender/compositor/operations/COM_SocketProxyOperation.h +++ b/source/blender/compositor/operations/COM_SocketProxyOperation.h @@ -22,17 +22,29 @@ #include "COM_NodeOperation.h" class SocketProxyOperation : public NodeOperation { -public: - SocketProxyOperation(DataType type, bool use_conversion); + public: + SocketProxyOperation(DataType type, bool use_conversion); - bool isProxyOperation() const { return true; } - bool useDatatypeConversion() const { return m_use_conversion; } + bool isProxyOperation() const + { + return true; + } + bool useDatatypeConversion() const + { + return m_use_conversion; + } - bool getUseConversion() const { return m_use_conversion; } - void setUseConversion(bool use_conversion) { m_use_conversion = use_conversion; } + bool getUseConversion() const + { + return m_use_conversion; + } + void setUseConversion(bool use_conversion) + { + m_use_conversion = use_conversion; + } -private: - bool m_use_conversion; + private: + bool m_use_conversion; }; #endif diff --git a/source/blender/compositor/operations/COM_SplitOperation.cpp b/source/blender/compositor/operations/COM_SplitOperation.cpp index aebae3c3f19..24978acc8f3 100644 --- a/source/blender/compositor/operations/COM_SplitOperation.cpp +++ b/source/blender/compositor/operations/COM_SplitOperation.cpp @@ -24,53 +24,57 @@ #include "BLI_math_vector.h" extern "C" { -# include "MEM_guardedalloc.h" -# include "IMB_imbuf.h" -# include "IMB_imbuf_types.h" +#include "MEM_guardedalloc.h" +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" } - SplitOperation::SplitOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - this->m_image1Input = NULL; - this->m_image2Input = NULL; + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); + this->m_image1Input = NULL; + this->m_image2Input = NULL; } void SplitOperation::initExecution() { - // When initializing the tree during initial load the width and height can be zero. - this->m_image1Input = getInputSocketReader(0); - this->m_image2Input = getInputSocketReader(1); + // When initializing the tree during initial load the width and height can be zero. + this->m_image1Input = getInputSocketReader(0); + this->m_image2Input = getInputSocketReader(1); } void SplitOperation::deinitExecution() { - this->m_image1Input = NULL; - this->m_image2Input = NULL; + this->m_image1Input = NULL; + this->m_image2Input = NULL; } -void SplitOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) +void SplitOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler /*sampler*/) { - int perc = this->m_xSplit ? this->m_splitPercentage * this->getWidth() / 100.0f : this->m_splitPercentage * this->getHeight() / 100.0f; - bool image1 = this->m_xSplit ? x > perc : y > perc; - if (image1) { - this->m_image1Input->readSampled(output, x, y, COM_PS_NEAREST); - } - else { - this->m_image2Input->readSampled(output, x, y, COM_PS_NEAREST); - } + int perc = this->m_xSplit ? this->m_splitPercentage * this->getWidth() / 100.0f : + this->m_splitPercentage * this->getHeight() / 100.0f; + bool image1 = this->m_xSplit ? x > perc : y > perc; + if (image1) { + this->m_image1Input->readSampled(output, x, y, COM_PS_NEAREST); + } + else { + this->m_image2Input->readSampled(output, x, y, COM_PS_NEAREST); + } } -void SplitOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +void SplitOperation::determineResolution(unsigned int resolution[2], + unsigned int preferredResolution[2]) { - unsigned int tempPreferredResolution[2] = {0, 0}; - unsigned int tempResolution[2]; + unsigned int tempPreferredResolution[2] = {0, 0}; + unsigned int tempResolution[2]; - this->getInputSocket(0)->determineResolution(tempResolution, tempPreferredResolution); - this->setResolutionInputSocketIndex((tempResolution[0] && tempResolution[1]) ? 0 : 1); + this->getInputSocket(0)->determineResolution(tempResolution, tempPreferredResolution); + this->setResolutionInputSocketIndex((tempResolution[0] && tempResolution[1]) ? 0 : 1); - NodeOperation::determineResolution(resolution, preferredResolution); + NodeOperation::determineResolution(resolution, preferredResolution); } diff --git a/source/blender/compositor/operations/COM_SplitOperation.h b/source/blender/compositor/operations/COM_SplitOperation.h index 34cb7f8f1b7..ea923123290 100644 --- a/source/blender/compositor/operations/COM_SplitOperation.h +++ b/source/blender/compositor/operations/COM_SplitOperation.h @@ -21,19 +21,26 @@ #include "COM_NodeOperation.h" class SplitOperation : public NodeOperation { -private: - SocketReader *m_image1Input; - SocketReader *m_image2Input; + private: + SocketReader *m_image1Input; + SocketReader *m_image2Input; - float m_splitPercentage; - bool m_xSplit; -public: - SplitOperation(); - void initExecution(); - void deinitExecution(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); - void setSplitPercentage(float splitPercentage) { this->m_splitPercentage = splitPercentage; } - void setXSplit(bool xsplit) { this->m_xSplit = xsplit; } + float m_splitPercentage; + bool m_xSplit; + + public: + SplitOperation(); + void initExecution(); + void deinitExecution(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); + void setSplitPercentage(float splitPercentage) + { + this->m_splitPercentage = splitPercentage; + } + void setXSplit(bool xsplit) + { + this->m_xSplit = xsplit; + } }; #endif diff --git a/source/blender/compositor/operations/COM_SunBeamsOperation.cpp b/source/blender/compositor/operations/COM_SunBeamsOperation.cpp index 0da63dd1c7a..80b1c1f798a 100644 --- a/source/blender/compositor/operations/COM_SunBeamsOperation.cpp +++ b/source/blender/compositor/operations/COM_SunBeamsOperation.cpp @@ -21,19 +21,19 @@ SunBeamsOperation::SunBeamsOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - this->setResolutionInputSocketIndex(0); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); + this->setResolutionInputSocketIndex(0); - this->setComplex(true); + this->setComplex(true); } void SunBeamsOperation::initExecution() { - /* convert to pixels */ - this->m_source_px[0] = this->m_data.source[0] * this->getWidth(); - this->m_source_px[1] = this->m_data.source[1] * this->getHeight(); - this->m_ray_length_px = this->m_data.ray_length * max(this->getWidth(), this->getHeight()); + /* convert to pixels */ + this->m_source_px[0] = this->m_data.source[0] * this->getWidth(); + this->m_source_px[1] = this->m_data.source[1] * this->getHeight(); + this->m_ray_length_px = this->m_data.ray_length * max(this->getWidth(), this->getHeight()); } /** @@ -53,165 +53,179 @@ void SunBeamsOperation::initExecution() * fyu : buffer increment in y for sector u+1 * fyv : buffer increment in y for sector v+1 */ -template <int fxu, int fxv, int fyu, int fyv> -struct BufferLineAccumulator { - - /* utility functions implementing the matrix transform to/from sector space */ - - static inline void buffer_to_sector(const float source[2], int x, int y, int &u, int &v) - { - int x0 = (int)source[0]; - int y0 = (int)source[1]; - x -= x0; - y -= y0; - u = x * fxu + y * fyu; - v = x * fxv + y * fyv; - } - - static inline void buffer_to_sector(const float source[2], float x, float y, float &u, float &v) - { - int x0 = (int)source[0]; - int y0 = (int)source[1]; - x -= (float)x0; - y -= (float)y0; - u = x * fxu + y * fyu; - v = x * fxv + y * fyv; - } - - static inline void sector_to_buffer(const float source[2], int u, int v, int &x, int &y) - { - int x0 = (int)source[0]; - int y0 = (int)source[1]; - x = x0 + u * fxu + v * fxv; - y = y0 + u * fyu + v * fyv; - } - - static inline void sector_to_buffer(const float source[2], float u, float v, float &x, float &y) - { - int x0 = (int)source[0]; - int y0 = (int)source[1]; - x = (float)x0 + u * fxu + v * fxv; - y = (float)y0 + u * fyu + v * fyv; - } - - /** - * Set up the initial buffer pointer and calculate necessary variables for looping. - * - * Note that sector space is centered around the "source" point while the loop starts - * at dist_min from the target pt. This way the loop can be canceled as soon as it runs - * out of the buffer rect, because no pixels further along the line can contribute. - * - * \param x, y: Start location in the buffer - * \param num: Total steps in the loop - * \param v, dv: Vertical offset in sector space, for line offset perpendicular to the loop axis - */ - static float *init_buffer_iterator(MemoryBuffer *input, const float source[2], const float co[2], - float dist_min, float dist_max, - int &x, int &y, int &num, float &v, float &dv, float &falloff_factor) - { - float pu, pv; - buffer_to_sector(source, co[0], co[1], pu, pv); - - /* line angle */ - float tan_phi = pv / pu; - float dr = sqrtf(tan_phi * tan_phi + 1.0f); - float cos_phi = 1.0f / dr; - - /* clamp u range to avoid influence of pixels "behind" the source */ - float umin = max_ff(pu - cos_phi * dist_min, 0.0f); - float umax = max_ff(pu - cos_phi * dist_max, 0.0f); - v = umin * tan_phi; - dv = tan_phi; - - int start = (int)floorf(umax); - int end = (int)ceilf(umin); - num = end - start; - - sector_to_buffer(source, end, (int)ceilf(v), x, y); - - falloff_factor = dist_max > dist_min ? dr / (float)(dist_max - dist_min) : 0.0f; - - float *iter = input->getBuffer() + COM_NUM_CHANNELS_COLOR * (x + input->getWidth() * y); - return iter; - } - - /** - * Perform the actual accumulation along a ray segment from source to pt. - * Only pixels within dist_min..dist_max contribute. - * - * The loop runs backwards(!) over the primary sector space axis u, i.e. increasing distance to pt. - * After each step it decrements v by dv < 1, adding a buffer shift when necessary. - */ - static void eval(MemoryBuffer *input, float output[4], const float co[2], const float source[2], - float dist_min, float dist_max) - { - rcti rect = *input->getRect(); - int buffer_width = input->getWidth(); - int x, y, num; - float v, dv; - float falloff_factor; - float border[4]; - - zero_v4(output); - - if ((int)(co[0] - source[0]) == 0 && (int)(co[1] - source[1]) == 0) { - copy_v4_v4(output, input->getBuffer() + COM_NUM_CHANNELS_COLOR * ((int)source[0] + input->getWidth() * (int)source[1])); - return; - } - - /* initialise the iteration variables */ - float *buffer = init_buffer_iterator(input, source, co, dist_min, dist_max, x, y, num, v, dv, falloff_factor); - zero_v3(border); - border[3] = 1.0f; - - /* v_local keeps track of when to decrement v (see below) */ - float v_local = v - floorf(v); - - for (int i = 0; i < num; i++) { - float weight = 1.0f - (float)i * falloff_factor; - weight *= weight; - - /* range check, use last valid color when running beyond the image border */ - if (x >= rect.xmin && x < rect.xmax && y >= rect.ymin && y < rect.ymax) { - madd_v4_v4fl(output, buffer, buffer[3] * weight); - /* use as border color in case subsequent pixels are out of bounds */ - copy_v4_v4(border, buffer); - } - else { - madd_v4_v4fl(output, border, border[3] * weight); - } - - /* TODO implement proper filtering here, see - * https://en.wikipedia.org/wiki/Lanczos_resampling - * https://en.wikipedia.org/wiki/Sinc_function - * - * using lanczos with x = distance from the line segment, - * normalized to a == 0.5f, could give a good result - * - * for now just divide equally at the end ... - */ - - /* decrement u */ - x -= fxu; - y -= fyu; - buffer -= (fxu + fyu * buffer_width) * COM_NUM_CHANNELS_COLOR; - - /* decrement v (in steps of dv < 1) */ - v_local -= dv; - if (v_local < 0.0f) { - v_local += 1.0f; - - x -= fxv; - y -= fyv; - buffer -= (fxv + fyv * buffer_width) * COM_NUM_CHANNELS_COLOR; - } - } - - /* normalize */ - if (num > 0) { - mul_v4_fl(output, 1.0f / (float)num); - } - } +template<int fxu, int fxv, int fyu, int fyv> struct BufferLineAccumulator { + + /* utility functions implementing the matrix transform to/from sector space */ + + static inline void buffer_to_sector(const float source[2], int x, int y, int &u, int &v) + { + int x0 = (int)source[0]; + int y0 = (int)source[1]; + x -= x0; + y -= y0; + u = x * fxu + y * fyu; + v = x * fxv + y * fyv; + } + + static inline void buffer_to_sector(const float source[2], float x, float y, float &u, float &v) + { + int x0 = (int)source[0]; + int y0 = (int)source[1]; + x -= (float)x0; + y -= (float)y0; + u = x * fxu + y * fyu; + v = x * fxv + y * fyv; + } + + static inline void sector_to_buffer(const float source[2], int u, int v, int &x, int &y) + { + int x0 = (int)source[0]; + int y0 = (int)source[1]; + x = x0 + u * fxu + v * fxv; + y = y0 + u * fyu + v * fyv; + } + + static inline void sector_to_buffer(const float source[2], float u, float v, float &x, float &y) + { + int x0 = (int)source[0]; + int y0 = (int)source[1]; + x = (float)x0 + u * fxu + v * fxv; + y = (float)y0 + u * fyu + v * fyv; + } + + /** + * Set up the initial buffer pointer and calculate necessary variables for looping. + * + * Note that sector space is centered around the "source" point while the loop starts + * at dist_min from the target pt. This way the loop can be canceled as soon as it runs + * out of the buffer rect, because no pixels further along the line can contribute. + * + * \param x, y: Start location in the buffer + * \param num: Total steps in the loop + * \param v, dv: Vertical offset in sector space, for line offset perpendicular to the loop axis + */ + static float *init_buffer_iterator(MemoryBuffer *input, + const float source[2], + const float co[2], + float dist_min, + float dist_max, + int &x, + int &y, + int &num, + float &v, + float &dv, + float &falloff_factor) + { + float pu, pv; + buffer_to_sector(source, co[0], co[1], pu, pv); + + /* line angle */ + float tan_phi = pv / pu; + float dr = sqrtf(tan_phi * tan_phi + 1.0f); + float cos_phi = 1.0f / dr; + + /* clamp u range to avoid influence of pixels "behind" the source */ + float umin = max_ff(pu - cos_phi * dist_min, 0.0f); + float umax = max_ff(pu - cos_phi * dist_max, 0.0f); + v = umin * tan_phi; + dv = tan_phi; + + int start = (int)floorf(umax); + int end = (int)ceilf(umin); + num = end - start; + + sector_to_buffer(source, end, (int)ceilf(v), x, y); + + falloff_factor = dist_max > dist_min ? dr / (float)(dist_max - dist_min) : 0.0f; + + float *iter = input->getBuffer() + COM_NUM_CHANNELS_COLOR * (x + input->getWidth() * y); + return iter; + } + + /** + * Perform the actual accumulation along a ray segment from source to pt. + * Only pixels within dist_min..dist_max contribute. + * + * The loop runs backwards(!) over the primary sector space axis u, i.e. increasing distance to pt. + * After each step it decrements v by dv < 1, adding a buffer shift when necessary. + */ + static void eval(MemoryBuffer *input, + float output[4], + const float co[2], + const float source[2], + float dist_min, + float dist_max) + { + rcti rect = *input->getRect(); + int buffer_width = input->getWidth(); + int x, y, num; + float v, dv; + float falloff_factor; + float border[4]; + + zero_v4(output); + + if ((int)(co[0] - source[0]) == 0 && (int)(co[1] - source[1]) == 0) { + copy_v4_v4(output, + input->getBuffer() + COM_NUM_CHANNELS_COLOR * + ((int)source[0] + input->getWidth() * (int)source[1])); + return; + } + + /* initialise the iteration variables */ + float *buffer = init_buffer_iterator( + input, source, co, dist_min, dist_max, x, y, num, v, dv, falloff_factor); + zero_v3(border); + border[3] = 1.0f; + + /* v_local keeps track of when to decrement v (see below) */ + float v_local = v - floorf(v); + + for (int i = 0; i < num; i++) { + float weight = 1.0f - (float)i * falloff_factor; + weight *= weight; + + /* range check, use last valid color when running beyond the image border */ + if (x >= rect.xmin && x < rect.xmax && y >= rect.ymin && y < rect.ymax) { + madd_v4_v4fl(output, buffer, buffer[3] * weight); + /* use as border color in case subsequent pixels are out of bounds */ + copy_v4_v4(border, buffer); + } + else { + madd_v4_v4fl(output, border, border[3] * weight); + } + + /* TODO implement proper filtering here, see + * https://en.wikipedia.org/wiki/Lanczos_resampling + * https://en.wikipedia.org/wiki/Sinc_function + * + * using lanczos with x = distance from the line segment, + * normalized to a == 0.5f, could give a good result + * + * for now just divide equally at the end ... + */ + + /* decrement u */ + x -= fxu; + y -= fyu; + buffer -= (fxu + fyu * buffer_width) * COM_NUM_CHANNELS_COLOR; + + /* decrement v (in steps of dv < 1) */ + v_local -= dv; + if (v_local < 0.0f) { + v_local += 1.0f; + + x -= fxv; + y -= fyv; + buffer -= (fxv + fyv * buffer_width) * COM_NUM_CHANNELS_COLOR; + } + } + + /* normalize */ + if (num > 0) { + mul_v4_fl(output, 1.0f / (float)num); + } + } }; /** @@ -221,113 +235,120 @@ struct BufferLineAccumulator { * The BufferLineAccumulator defines the actual loop over the buffer, with an efficient inner loop * due to using compile time constants instead of a local matrix variable defining the sector space. */ -static void accumulate_line(MemoryBuffer *input, float output[4], const float co[2], const float source[2], - float dist_min, float dist_max) +static void accumulate_line(MemoryBuffer *input, + float output[4], + const float co[2], + const float source[2], + float dist_min, + float dist_max) { - /* coordinates relative to source */ - float pt_ofs[2] = {co[0] - source[0], co[1] - source[1]}; - - /* The source sectors are defined like so: - * - * \ 3 | 2 / - * \ | / - * 4 \ | / 1 - * \|/ - * ----------- - * /|\ - * 5 / | \ 8 - * / | \ - * / 6 | 7 \ - * - * The template arguments encode the transformation into "sector space", - * by means of rotation/mirroring matrix elements. - */ - - if (fabsf(pt_ofs[1]) > fabsf(pt_ofs[0])) { - if (pt_ofs[0] > 0.0f) { - if (pt_ofs[1] > 0.0f) { - /* 2 */ - BufferLineAccumulator<0, 1, 1, 0>::eval(input, output, co, source, dist_min, dist_max); - } - else { - /* 7 */ - BufferLineAccumulator<0, 1, -1, 0>::eval(input, output, co, source, dist_min, dist_max); - } - } - else { - if (pt_ofs[1] > 0.0f) { - /* 3 */ - BufferLineAccumulator<0, -1, 1, 0>::eval(input, output, co, source, dist_min, dist_max); - } - else { - /* 6 */ - BufferLineAccumulator<0, -1, -1, 0>::eval(input, output, co, source, dist_min, dist_max); - } - } - } - else { - if (pt_ofs[0] > 0.0f) { - if (pt_ofs[1] > 0.0f) { - /* 1 */ - BufferLineAccumulator< 1, 0, 0, 1>::eval(input, output, co, source, dist_min, dist_max); - } - else { - /* 8 */ - BufferLineAccumulator< 1, 0, 0, -1>::eval(input, output, co, source, dist_min, dist_max); - } - } - else { - if (pt_ofs[1] > 0.0f) { - /* 4 */ - BufferLineAccumulator<-1, 0, 0, 1>::eval(input, output, co, source, dist_min, dist_max); - } - else { - /* 5 */ - BufferLineAccumulator<-1, 0, 0, -1>::eval(input, output, co, source, dist_min, dist_max); - } - } - } + /* coordinates relative to source */ + float pt_ofs[2] = {co[0] - source[0], co[1] - source[1]}; + + /* The source sectors are defined like so: + * + * \ 3 | 2 / + * \ | / + * 4 \ | / 1 + * \|/ + * ----------- + * /|\ + * 5 / | \ 8 + * / | \ + * / 6 | 7 \ + * + * The template arguments encode the transformation into "sector space", + * by means of rotation/mirroring matrix elements. + */ + + if (fabsf(pt_ofs[1]) > fabsf(pt_ofs[0])) { + if (pt_ofs[0] > 0.0f) { + if (pt_ofs[1] > 0.0f) { + /* 2 */ + BufferLineAccumulator<0, 1, 1, 0>::eval(input, output, co, source, dist_min, dist_max); + } + else { + /* 7 */ + BufferLineAccumulator<0, 1, -1, 0>::eval(input, output, co, source, dist_min, dist_max); + } + } + else { + if (pt_ofs[1] > 0.0f) { + /* 3 */ + BufferLineAccumulator<0, -1, 1, 0>::eval(input, output, co, source, dist_min, dist_max); + } + else { + /* 6 */ + BufferLineAccumulator<0, -1, -1, 0>::eval(input, output, co, source, dist_min, dist_max); + } + } + } + else { + if (pt_ofs[0] > 0.0f) { + if (pt_ofs[1] > 0.0f) { + /* 1 */ + BufferLineAccumulator<1, 0, 0, 1>::eval(input, output, co, source, dist_min, dist_max); + } + else { + /* 8 */ + BufferLineAccumulator<1, 0, 0, -1>::eval(input, output, co, source, dist_min, dist_max); + } + } + else { + if (pt_ofs[1] > 0.0f) { + /* 4 */ + BufferLineAccumulator<-1, 0, 0, 1>::eval(input, output, co, source, dist_min, dist_max); + } + else { + /* 5 */ + BufferLineAccumulator<-1, 0, 0, -1>::eval(input, output, co, source, dist_min, dist_max); + } + } + } } void *SunBeamsOperation::initializeTileData(rcti * /*rect*/) { - void *buffer = getInputOperation(0)->initializeTileData(NULL); - return buffer; + void *buffer = getInputOperation(0)->initializeTileData(NULL); + return buffer; } void SunBeamsOperation::executePixel(float output[4], int x, int y, void *data) { - const float co[2] = {(float)x, (float)y}; + const float co[2] = {(float)x, (float)y}; - accumulate_line((MemoryBuffer *)data, output, co, this->m_source_px, 0.0f, this->m_ray_length_px); + accumulate_line( + (MemoryBuffer *)data, output, co, this->m_source_px, 0.0f, this->m_ray_length_px); } static void calc_ray_shift(rcti *rect, float x, float y, const float source[2], float ray_length) { - float co[2] = {(float)x, (float)y}; - float dir[2], dist; + float co[2] = {(float)x, (float)y}; + float dir[2], dist; - /* move (x,y) vector toward the source by ray_length distance */ - sub_v2_v2v2(dir, co, source); - dist = normalize_v2(dir); - mul_v2_fl(dir, min_ff(dist, ray_length)); - sub_v2_v2(co, dir); + /* move (x,y) vector toward the source by ray_length distance */ + sub_v2_v2v2(dir, co, source); + dist = normalize_v2(dir); + mul_v2_fl(dir, min_ff(dist, ray_length)); + sub_v2_v2(co, dir); - int ico[2] = {(int)co[0], (int)co[1]}; - BLI_rcti_do_minmax_v(rect, ico); + int ico[2] = {(int)co[0], (int)co[1]}; + BLI_rcti_do_minmax_v(rect, ico); } -bool SunBeamsOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool SunBeamsOperation::determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output) { - /* Enlarges the rect by moving each corner toward the source. - * This is the maximum distance that pixels can influence each other - * and gives a rect that contains all possible accumulated pixels. - */ - rcti rect = *input; - calc_ray_shift(&rect, input->xmin, input->ymin, this->m_source_px, this->m_ray_length_px); - calc_ray_shift(&rect, input->xmin, input->ymax, this->m_source_px, this->m_ray_length_px); - calc_ray_shift(&rect, input->xmax, input->ymin, this->m_source_px, this->m_ray_length_px); - calc_ray_shift(&rect, input->xmax, input->ymax, this->m_source_px, this->m_ray_length_px); - - return NodeOperation::determineDependingAreaOfInterest(&rect, readOperation, output); + /* Enlarges the rect by moving each corner toward the source. + * This is the maximum distance that pixels can influence each other + * and gives a rect that contains all possible accumulated pixels. + */ + rcti rect = *input; + calc_ray_shift(&rect, input->xmin, input->ymin, this->m_source_px, this->m_ray_length_px); + calc_ray_shift(&rect, input->xmin, input->ymax, this->m_source_px, this->m_ray_length_px); + calc_ray_shift(&rect, input->xmax, input->ymin, this->m_source_px, this->m_ray_length_px); + calc_ray_shift(&rect, input->xmax, input->ymax, this->m_source_px, this->m_ray_length_px); + + return NodeOperation::determineDependingAreaOfInterest(&rect, readOperation, output); } diff --git a/source/blender/compositor/operations/COM_SunBeamsOperation.h b/source/blender/compositor/operations/COM_SunBeamsOperation.h index 22c44b706dc..d8153264d98 100644 --- a/source/blender/compositor/operations/COM_SunBeamsOperation.h +++ b/source/blender/compositor/operations/COM_SunBeamsOperation.h @@ -21,24 +21,29 @@ #include "COM_NodeOperation.h" class SunBeamsOperation : public NodeOperation { -public: - SunBeamsOperation(); + public: + SunBeamsOperation(); - void executePixel(float output[4], int x, int y, void *data); + void executePixel(float output[4], int x, int y, void *data); - void initExecution(); + void initExecution(); - void *initializeTileData(rcti *rect); + void *initializeTileData(rcti *rect); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); - void setData(const NodeSunBeams &data) { m_data = data; } + void setData(const NodeSunBeams &data) + { + m_data = data; + } -private: - NodeSunBeams m_data; + private: + NodeSunBeams m_data; - float m_source_px[2]; - float m_ray_length_px; + float m_source_px[2]; + float m_ray_length_px; }; #endif diff --git a/source/blender/compositor/operations/COM_TextureOperation.cpp b/source/blender/compositor/operations/COM_TextureOperation.cpp index 37d41a2afad..f23057bbe8e 100644 --- a/source/blender/compositor/operations/COM_TextureOperation.cpp +++ b/source/blender/compositor/operations/COM_TextureOperation.cpp @@ -29,126 +29,120 @@ extern "C" { TextureBaseOperation::TextureBaseOperation() : NodeOperation() { - this->addInputSocket(COM_DT_VECTOR); //offset - this->addInputSocket(COM_DT_VECTOR); //size - this->m_texture = NULL; - this->m_inputSize = NULL; - this->m_inputOffset = NULL; - this->m_rd = NULL; - this->m_pool = NULL; - this->m_sceneColorManage = false; - setComplex(true); + this->addInputSocket(COM_DT_VECTOR); //offset + this->addInputSocket(COM_DT_VECTOR); //size + this->m_texture = NULL; + this->m_inputSize = NULL; + this->m_inputOffset = NULL; + this->m_rd = NULL; + this->m_pool = NULL; + this->m_sceneColorManage = false; + setComplex(true); } TextureOperation::TextureOperation() : TextureBaseOperation() { - this->addOutputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); } TextureAlphaOperation::TextureAlphaOperation() : TextureBaseOperation() { - this->addOutputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_VALUE); } void TextureBaseOperation::initExecution() { - this->m_inputOffset = getInputSocketReader(0); - this->m_inputSize = getInputSocketReader(1); - this->m_pool = BKE_image_pool_new(); - if (this->m_texture != NULL && - this->m_texture->nodetree != NULL && - this->m_texture->use_nodes) - { - ntreeTexBeginExecTree(this->m_texture->nodetree); - } - NodeOperation::initExecution(); + this->m_inputOffset = getInputSocketReader(0); + this->m_inputSize = getInputSocketReader(1); + this->m_pool = BKE_image_pool_new(); + if (this->m_texture != NULL && this->m_texture->nodetree != NULL && this->m_texture->use_nodes) { + ntreeTexBeginExecTree(this->m_texture->nodetree); + } + NodeOperation::initExecution(); } void TextureBaseOperation::deinitExecution() { - this->m_inputSize = NULL; - this->m_inputOffset = NULL; - BKE_image_pool_free(this->m_pool); - this->m_pool = NULL; - if (this->m_texture != NULL && - this->m_texture->use_nodes && - this->m_texture->nodetree != NULL && - this->m_texture->nodetree->execdata != NULL) - { - ntreeTexEndExecTree(this->m_texture->nodetree->execdata); - } - NodeOperation::deinitExecution(); + this->m_inputSize = NULL; + this->m_inputOffset = NULL; + BKE_image_pool_free(this->m_pool); + this->m_pool = NULL; + if (this->m_texture != NULL && this->m_texture->use_nodes && this->m_texture->nodetree != NULL && + this->m_texture->nodetree->execdata != NULL) { + ntreeTexEndExecTree(this->m_texture->nodetree->execdata); + } + NodeOperation::deinitExecution(); } -void TextureBaseOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +void TextureBaseOperation::determineResolution(unsigned int resolution[2], + unsigned int preferredResolution[2]) { - if (preferredResolution[0] == 0 || preferredResolution[1] == 0) { - int width = this->m_rd->xsch * this->m_rd->size / 100; - int height = this->m_rd->ysch * this->m_rd->size / 100; - resolution[0] = width; - resolution[1] = height; - } - else { - resolution[0] = preferredResolution[0]; - resolution[1] = preferredResolution[1]; - } + if (preferredResolution[0] == 0 || preferredResolution[1] == 0) { + int width = this->m_rd->xsch * this->m_rd->size / 100; + int height = this->m_rd->ysch * this->m_rd->size / 100; + resolution[0] = width; + resolution[1] = height; + } + else { + resolution[0] = preferredResolution[0]; + resolution[1] = preferredResolution[1]; + } } -void TextureAlphaOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void TextureAlphaOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float color[4]; - TextureBaseOperation::executePixelSampled(color, x, y, sampler); - output[0] = color[3]; + float color[4]; + TextureBaseOperation::executePixelSampled(color, x, y, sampler); + output[0] = color[3]; } -void TextureBaseOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void TextureBaseOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - TexResult texres = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL}; - float textureSize[4]; - float textureOffset[4]; - float vec[3]; - int retval; - const float cx = this->getWidth() / 2; - const float cy = this->getHeight() / 2; - float u = (x - cx) / this->getWidth() * 2; - float v = (y - cy) / this->getHeight() * 2; + TexResult texres = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL}; + float textureSize[4]; + float textureOffset[4]; + float vec[3]; + int retval; + const float cx = this->getWidth() / 2; + const float cy = this->getHeight() / 2; + float u = (x - cx) / this->getWidth() * 2; + float v = (y - cy) / this->getHeight() * 2; - /* When no interpolation/filtering happens in multitex() foce nearest interpolation. - * We do it here because (a) we can't easily say multitex() that we want nearest - * interpolation and (b) in such configuration multitex() sinply floor's the value - * which often produces artifacts. - */ - if (m_texture != NULL && (m_texture->imaflag & TEX_INTERPOL) == 0) { - u += 0.5f / cx; - v += 0.5f / cy; - } + /* When no interpolation/filtering happens in multitex() foce nearest interpolation. + * We do it here because (a) we can't easily say multitex() that we want nearest + * interpolation and (b) in such configuration multitex() sinply floor's the value + * which often produces artifacts. + */ + if (m_texture != NULL && (m_texture->imaflag & TEX_INTERPOL) == 0) { + u += 0.5f / cx; + v += 0.5f / cy; + } - this->m_inputSize->readSampled(textureSize, x, y, sampler); - this->m_inputOffset->readSampled(textureOffset, x, y, sampler); + this->m_inputSize->readSampled(textureSize, x, y, sampler); + this->m_inputOffset->readSampled(textureOffset, x, y, sampler); - vec[0] = textureSize[0] * (u + textureOffset[0]); - vec[1] = textureSize[1] * (v + textureOffset[1]); - vec[2] = textureSize[2] * textureOffset[2]; + vec[0] = textureSize[0] * (u + textureOffset[0]); + vec[1] = textureSize[1] * (v + textureOffset[1]); + vec[2] = textureSize[2] * textureOffset[2]; - const int thread_id = WorkScheduler::current_thread_id(); - retval = multitex_ext(this->m_texture, - vec, - NULL, NULL, - 0, - &texres, - thread_id, - m_pool, - m_sceneColorManage, - false); + const int thread_id = WorkScheduler::current_thread_id(); + retval = multitex_ext( + this->m_texture, vec, NULL, NULL, 0, &texres, thread_id, m_pool, m_sceneColorManage, false); - if (texres.talpha) - output[3] = texres.ta; - else - output[3] = texres.tin; + if (texres.talpha) + output[3] = texres.ta; + else + output[3] = texres.tin; - if ((retval & TEX_RGB)) { - output[0] = texres.tr; - output[1] = texres.tg; - output[2] = texres.tb; - } - else { - output[0] = output[1] = output[2] = output[3]; - } + if ((retval & TEX_RGB)) { + output[0] = texres.tr; + output[1] = texres.tg; + output[2] = texres.tb; + } + else { + output[0] = output[1] = output[2] = output[3]; + } } diff --git a/source/blender/compositor/operations/COM_TextureOperation.h b/source/blender/compositor/operations/COM_TextureOperation.h index 463fe4cc3a0..934b6f8683f 100644 --- a/source/blender/compositor/operations/COM_TextureOperation.h +++ b/source/blender/compositor/operations/COM_TextureOperation.h @@ -16,7 +16,6 @@ * Copyright 2011, Blender Foundation. */ - #ifndef __COM_TEXTUREOPERATION_H__ #define __COM_TEXTUREOPERATION_H__ @@ -24,10 +23,10 @@ #include "DNA_texture_types.h" #include "BLI_listbase.h" extern "C" { -# include "RE_pipeline.h" -# include "RE_shader_ext.h" -# include "RE_render_ext.h" -# include "MEM_guardedalloc.h" +#include "RE_pipeline.h" +#include "RE_shader_ext.h" +#include "RE_render_ext.h" +#include "MEM_guardedalloc.h" } /** @@ -36,45 +35,52 @@ extern "C" { * \todo: rename to operation. */ class TextureBaseOperation : public NodeOperation { -private: - Tex *m_texture; - const RenderData *m_rd; - SocketReader *m_inputSize; - SocketReader *m_inputOffset; - struct ImagePool *m_pool; - bool m_sceneColorManage; + private: + Tex *m_texture; + const RenderData *m_rd; + SocketReader *m_inputSize; + SocketReader *m_inputOffset; + struct ImagePool *m_pool; + bool m_sceneColorManage; -protected: + protected: + /** + * Determine the output resolution. The resolution is retrieved from the Renderer + */ + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); - /** - * Determine the output resolution. The resolution is retrieved from the Renderer - */ - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); + /** + * Constructor + */ + TextureBaseOperation(); - /** - * Constructor - */ - TextureBaseOperation(); -public: - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - void setTexture(Tex *texture) { this->m_texture = texture; } - void initExecution(); - void deinitExecution(); - void setRenderData(const RenderData *rd) { this->m_rd = rd; } - void setSceneColorManage(bool sceneColorManage) { this->m_sceneColorManage = sceneColorManage; } + void setTexture(Tex *texture) + { + this->m_texture = texture; + } + void initExecution(); + void deinitExecution(); + void setRenderData(const RenderData *rd) + { + this->m_rd = rd; + } + void setSceneColorManage(bool sceneColorManage) + { + this->m_sceneColorManage = sceneColorManage; + } }; class TextureOperation : public TextureBaseOperation { -public: - TextureOperation(); - + public: + TextureOperation(); }; class TextureAlphaOperation : public TextureBaseOperation { -public: - TextureAlphaOperation(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - + public: + TextureAlphaOperation(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; #endif diff --git a/source/blender/compositor/operations/COM_TonemapOperation.cpp b/source/blender/compositor/operations/COM_TonemapOperation.cpp index bc2177eefbe..6b408a0a791 100644 --- a/source/blender/compositor/operations/COM_TonemapOperation.cpp +++ b/source/blender/compositor/operations/COM_TonemapOperation.cpp @@ -26,127 +26,131 @@ extern "C" { TonemapOperation::TonemapOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); - this->addOutputSocket(COM_DT_COLOR); - this->m_imageReader = NULL; - this->m_data = NULL; - this->m_cachedInstance = NULL; - this->setComplex(true); + this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); + this->addOutputSocket(COM_DT_COLOR); + this->m_imageReader = NULL; + this->m_data = NULL; + this->m_cachedInstance = NULL; + this->setComplex(true); } void TonemapOperation::initExecution() { - this->m_imageReader = this->getInputSocketReader(0); - NodeOperation::initMutex(); + this->m_imageReader = this->getInputSocketReader(0); + NodeOperation::initMutex(); } void TonemapOperation::executePixel(float output[4], int x, int y, void *data) { - AvgLogLum *avg = (AvgLogLum *)data; + AvgLogLum *avg = (AvgLogLum *)data; - this->m_imageReader->read(output, x, y, NULL); - mul_v3_fl(output, avg->al); - float dr = output[0] + this->m_data->offset; - float dg = output[1] + this->m_data->offset; - float db = output[2] + this->m_data->offset; - output[0] /= ((dr == 0.0f) ? 1.0f : dr); - output[1] /= ((dg == 0.0f) ? 1.0f : dg); - output[2] /= ((db == 0.0f) ? 1.0f : db); - const float igm = avg->igm; - if (igm != 0.0f) { - output[0] = powf(max(output[0], 0.0f), igm); - output[1] = powf(max(output[1], 0.0f), igm); - output[2] = powf(max(output[2], 0.0f), igm); - } + this->m_imageReader->read(output, x, y, NULL); + mul_v3_fl(output, avg->al); + float dr = output[0] + this->m_data->offset; + float dg = output[1] + this->m_data->offset; + float db = output[2] + this->m_data->offset; + output[0] /= ((dr == 0.0f) ? 1.0f : dr); + output[1] /= ((dg == 0.0f) ? 1.0f : dg); + output[2] /= ((db == 0.0f) ? 1.0f : db); + const float igm = avg->igm; + if (igm != 0.0f) { + output[0] = powf(max(output[0], 0.0f), igm); + output[1] = powf(max(output[1], 0.0f), igm); + output[2] = powf(max(output[2], 0.0f), igm); + } } void PhotoreceptorTonemapOperation::executePixel(float output[4], int x, int y, void *data) { - AvgLogLum *avg = (AvgLogLum *)data; - NodeTonemap *ntm = this->m_data; + AvgLogLum *avg = (AvgLogLum *)data; + NodeTonemap *ntm = this->m_data; - const float f = expf(-this->m_data->f); - const float m = (ntm->m > 0.0f) ? ntm->m : (0.3f + 0.7f * powf(avg->auto_key, 1.4f)); - const float ic = 1.0f - ntm->c, ia = 1.0f - ntm->a; + const float f = expf(-this->m_data->f); + const float m = (ntm->m > 0.0f) ? ntm->m : (0.3f + 0.7f * powf(avg->auto_key, 1.4f)); + const float ic = 1.0f - ntm->c, ia = 1.0f - ntm->a; - this->m_imageReader->read(output, x, y, NULL); + this->m_imageReader->read(output, x, y, NULL); - const float L = IMB_colormanagement_get_luminance(output); - float I_l = output[0] + ic * (L - output[0]); - float I_g = avg->cav[0] + ic * (avg->lav - avg->cav[0]); - float I_a = I_l + ia * (I_g - I_l); - output[0] /= (output[0] + powf(f * I_a, m)); - I_l = output[1] + ic * (L - output[1]); - I_g = avg->cav[1] + ic * (avg->lav - avg->cav[1]); - I_a = I_l + ia * (I_g - I_l); - output[1] /= (output[1] + powf(f * I_a, m)); - I_l = output[2] + ic * (L - output[2]); - I_g = avg->cav[2] + ic * (avg->lav - avg->cav[2]); - I_a = I_l + ia * (I_g - I_l); - output[2] /= (output[2] + powf(f * I_a, m)); + const float L = IMB_colormanagement_get_luminance(output); + float I_l = output[0] + ic * (L - output[0]); + float I_g = avg->cav[0] + ic * (avg->lav - avg->cav[0]); + float I_a = I_l + ia * (I_g - I_l); + output[0] /= (output[0] + powf(f * I_a, m)); + I_l = output[1] + ic * (L - output[1]); + I_g = avg->cav[1] + ic * (avg->lav - avg->cav[1]); + I_a = I_l + ia * (I_g - I_l); + output[1] /= (output[1] + powf(f * I_a, m)); + I_l = output[2] + ic * (L - output[2]); + I_g = avg->cav[2] + ic * (avg->lav - avg->cav[2]); + I_a = I_l + ia * (I_g - I_l); + output[2] /= (output[2] + powf(f * I_a, m)); } void TonemapOperation::deinitExecution() { - this->m_imageReader = NULL; - if (this->m_cachedInstance) { - delete this->m_cachedInstance; - } - NodeOperation::deinitMutex(); + this->m_imageReader = NULL; + if (this->m_cachedInstance) { + delete this->m_cachedInstance; + } + NodeOperation::deinitMutex(); } -bool TonemapOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output) +bool TonemapOperation::determineDependingAreaOfInterest(rcti * /*input*/, + ReadBufferOperation *readOperation, + rcti *output) { - rcti imageInput; + rcti imageInput; - NodeOperation *operation = getInputOperation(0); - imageInput.xmax = operation->getWidth(); - imageInput.xmin = 0; - imageInput.ymax = operation->getHeight(); - imageInput.ymin = 0; - if (operation->determineDependingAreaOfInterest(&imageInput, readOperation, output) ) { - return true; - } - return false; + NodeOperation *operation = getInputOperation(0); + imageInput.xmax = operation->getWidth(); + imageInput.xmin = 0; + imageInput.ymax = operation->getHeight(); + imageInput.ymin = 0; + if (operation->determineDependingAreaOfInterest(&imageInput, readOperation, output)) { + return true; + } + return false; } void *TonemapOperation::initializeTileData(rcti *rect) { - lockMutex(); - if (this->m_cachedInstance == NULL) { - MemoryBuffer *tile = (MemoryBuffer *)this->m_imageReader->initializeTileData(rect); - AvgLogLum *data = new AvgLogLum(); + lockMutex(); + if (this->m_cachedInstance == NULL) { + MemoryBuffer *tile = (MemoryBuffer *)this->m_imageReader->initializeTileData(rect); + AvgLogLum *data = new AvgLogLum(); - float *buffer = tile->getBuffer(); + float *buffer = tile->getBuffer(); - float lsum = 0.0f; - int p = tile->getWidth() * tile->getHeight(); - float *bc = buffer; - float avl, maxl = -1e10f, minl = 1e10f; - const float sc = 1.0f / p; - float Lav = 0.0f; - float cav[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - while (p--) { - float L = IMB_colormanagement_get_luminance(bc); - Lav += L; - add_v3_v3(cav, bc); - lsum += logf(MAX2(L, 0.0f) + 1e-5f); - maxl = (L > maxl) ? L : maxl; - minl = (L < minl) ? L : minl; - bc += 4; - } - data->lav = Lav * sc; - mul_v3_v3fl(data->cav, cav, sc); - maxl = log((double)maxl + 1e-5); minl = log((double)minl + 1e-5); avl = lsum * sc; - data->auto_key = (maxl > minl) ? ((maxl - avl) / (maxl - minl)) : 1.0f; - float al = exp((double)avl); - data->al = (al == 0.0f) ? 0.0f : (this->m_data->key / al); - data->igm = (this->m_data->gamma == 0.0f) ? 1 : (1.0f / this->m_data->gamma); - this->m_cachedInstance = data; - } - unlockMutex(); - return this->m_cachedInstance; + float lsum = 0.0f; + int p = tile->getWidth() * tile->getHeight(); + float *bc = buffer; + float avl, maxl = -1e10f, minl = 1e10f; + const float sc = 1.0f / p; + float Lav = 0.0f; + float cav[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + while (p--) { + float L = IMB_colormanagement_get_luminance(bc); + Lav += L; + add_v3_v3(cav, bc); + lsum += logf(MAX2(L, 0.0f) + 1e-5f); + maxl = (L > maxl) ? L : maxl; + minl = (L < minl) ? L : minl; + bc += 4; + } + data->lav = Lav * sc; + mul_v3_v3fl(data->cav, cav, sc); + maxl = log((double)maxl + 1e-5); + minl = log((double)minl + 1e-5); + avl = lsum * sc; + data->auto_key = (maxl > minl) ? ((maxl - avl) / (maxl - minl)) : 1.0f; + float al = exp((double)avl); + data->al = (al == 0.0f) ? 0.0f : (this->m_data->key / al); + data->igm = (this->m_data->gamma == 0.0f) ? 1 : (1.0f / this->m_data->gamma); + this->m_cachedInstance = data; + } + unlockMutex(); + return this->m_cachedInstance; } void TonemapOperation::deinitializeTileData(rcti * /*rect*/, void * /*data*/) { - /* pass */ + /* pass */ } diff --git a/source/blender/compositor/operations/COM_TonemapOperation.h b/source/blender/compositor/operations/COM_TonemapOperation.h index 2b4804e4bfd..11e82c1fc9c 100644 --- a/source/blender/compositor/operations/COM_TonemapOperation.h +++ b/source/blender/compositor/operations/COM_TonemapOperation.h @@ -26,11 +26,11 @@ * \ingroup operation */ typedef struct AvgLogLum { - float al; - float auto_key; - float lav; - float cav[4]; - float igm; + float al; + float auto_key; + float lav; + float cav[4]; + float igm; } AvgLogLum; /** @@ -38,46 +38,51 @@ typedef struct AvgLogLum { * \ingroup operation */ class TonemapOperation : public NodeOperation { -protected: - /** - * \brief Cached reference to the reader - */ - SocketReader *m_imageReader; + protected: + /** + * \brief Cached reference to the reader + */ + SocketReader *m_imageReader; - /** - * \brief settings of the Tonemap - */ - NodeTonemap *m_data; + /** + * \brief settings of the Tonemap + */ + NodeTonemap *m_data; - /** - * \brief temporarily cache of the execution storage - */ - AvgLogLum *m_cachedInstance; + /** + * \brief temporarily cache of the execution storage + */ + AvgLogLum *m_cachedInstance; -public: - TonemapOperation(); + public: + TonemapOperation(); - /** - * the inner loop of this program - */ - void executePixel(float output[4], int x, int y, void *data); + /** + * the inner loop of this program + */ + void executePixel(float output[4], int x, int y, void *data); - /** - * Initialize the execution - */ - void initExecution(); + /** + * Initialize the execution + */ + void initExecution(); - void *initializeTileData(rcti *rect); - void deinitializeTileData(rcti *rect, void *data); + void *initializeTileData(rcti *rect); + void deinitializeTileData(rcti *rect, void *data); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Deinitialize the execution + */ + void deinitExecution(); - void setData(NodeTonemap *data) { this->m_data = data; } + void setData(NodeTonemap *data) + { + this->m_data = data; + } - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); }; /** @@ -87,11 +92,11 @@ public: */ class PhotoreceptorTonemapOperation : public TonemapOperation { -public: - /** - * the inner loop of this program - */ - void executePixel(float output[4], int x, int y, void *data); + public: + /** + * the inner loop of this program + */ + void executePixel(float output[4], int x, int y, void *data); }; #endif diff --git a/source/blender/compositor/operations/COM_TrackPositionOperation.cpp b/source/blender/compositor/operations/COM_TrackPositionOperation.cpp index dbea46a4d85..178a9b57cba 100644 --- a/source/blender/compositor/operations/COM_TrackPositionOperation.cpp +++ b/source/blender/compositor/operations/COM_TrackPositionOperation.cpp @@ -25,111 +25,111 @@ #include "BLI_math_color.h" extern "C" { -# include "BKE_movieclip.h" -# include "BKE_node.h" -# include "BKE_tracking.h" +#include "BKE_movieclip.h" +#include "BKE_node.h" +#include "BKE_tracking.h" } TrackPositionOperation::TrackPositionOperation() : NodeOperation() { - this->addOutputSocket(COM_DT_VALUE); - this->m_movieClip = NULL; - this->m_framenumber = 0; - this->m_trackingObjectName[0] = 0; - this->m_trackName[0] = 0; - this->m_axis = 0; - this->m_position = CMP_TRACKPOS_ABSOLUTE; - this->m_relativeFrame = 0; - this->m_speed_output = false; + this->addOutputSocket(COM_DT_VALUE); + this->m_movieClip = NULL; + this->m_framenumber = 0; + this->m_trackingObjectName[0] = 0; + this->m_trackName[0] = 0; + this->m_axis = 0; + this->m_position = CMP_TRACKPOS_ABSOLUTE; + this->m_relativeFrame = 0; + this->m_speed_output = false; } void TrackPositionOperation::initExecution() { - MovieTracking *tracking = NULL; - MovieClipUser user = {0}; - MovieTrackingObject *object; - - zero_v2(this->m_markerPos); - zero_v2(this->m_relativePos); - - if (!this->m_movieClip) - return; - - tracking = &this->m_movieClip->tracking; - - BKE_movieclip_user_set_frame(&user, this->m_framenumber); - BKE_movieclip_get_size(this->m_movieClip, &user, &this->m_width, &this->m_height); - - object = BKE_tracking_object_get_named(tracking, this->m_trackingObjectName); - if (object) { - MovieTrackingTrack *track; - - track = BKE_tracking_track_get_named(tracking, object, this->m_trackName); - - if (track) { - MovieTrackingMarker *marker; - int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, this->m_framenumber); - - marker = BKE_tracking_marker_get(track, clip_framenr); - - copy_v2_v2(this->m_markerPos, marker->pos); - - if (this->m_speed_output) { - int relative_clip_framenr = - BKE_movieclip_remap_scene_to_clip_frame( - this->m_movieClip, - this->m_relativeFrame); - - marker = BKE_tracking_marker_get_exact(track, - relative_clip_framenr); - if (marker != NULL && (marker->flag & MARKER_DISABLED) == 0) { - copy_v2_v2(this->m_relativePos, marker->pos); - } - else { - copy_v2_v2(this->m_relativePos, this->m_markerPos); - } - if (this->m_relativeFrame < this->m_framenumber) { - swap_v2_v2(this->m_relativePos, this->m_markerPos); - } - } - else if (this->m_position == CMP_TRACKPOS_RELATIVE_START) { - int i; - - for (i = 0; i < track->markersnr; i++) { - marker = &track->markers[i]; - - if ((marker->flag & MARKER_DISABLED) == 0) { - copy_v2_v2(this->m_relativePos, marker->pos); - - break; - } - } - } - else if (this->m_position == CMP_TRACKPOS_RELATIVE_FRAME) { - int relative_clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, - this->m_relativeFrame); - - marker = BKE_tracking_marker_get(track, relative_clip_framenr); - copy_v2_v2(this->m_relativePos, marker->pos); - } - } - } + MovieTracking *tracking = NULL; + MovieClipUser user = {0}; + MovieTrackingObject *object; + + zero_v2(this->m_markerPos); + zero_v2(this->m_relativePos); + + if (!this->m_movieClip) + return; + + tracking = &this->m_movieClip->tracking; + + BKE_movieclip_user_set_frame(&user, this->m_framenumber); + BKE_movieclip_get_size(this->m_movieClip, &user, &this->m_width, &this->m_height); + + object = BKE_tracking_object_get_named(tracking, this->m_trackingObjectName); + if (object) { + MovieTrackingTrack *track; + + track = BKE_tracking_track_get_named(tracking, object, this->m_trackName); + + if (track) { + MovieTrackingMarker *marker; + int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, + this->m_framenumber); + + marker = BKE_tracking_marker_get(track, clip_framenr); + + copy_v2_v2(this->m_markerPos, marker->pos); + + if (this->m_speed_output) { + int relative_clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, + this->m_relativeFrame); + + marker = BKE_tracking_marker_get_exact(track, relative_clip_framenr); + if (marker != NULL && (marker->flag & MARKER_DISABLED) == 0) { + copy_v2_v2(this->m_relativePos, marker->pos); + } + else { + copy_v2_v2(this->m_relativePos, this->m_markerPos); + } + if (this->m_relativeFrame < this->m_framenumber) { + swap_v2_v2(this->m_relativePos, this->m_markerPos); + } + } + else if (this->m_position == CMP_TRACKPOS_RELATIVE_START) { + int i; + + for (i = 0; i < track->markersnr; i++) { + marker = &track->markers[i]; + + if ((marker->flag & MARKER_DISABLED) == 0) { + copy_v2_v2(this->m_relativePos, marker->pos); + + break; + } + } + } + else if (this->m_position == CMP_TRACKPOS_RELATIVE_FRAME) { + int relative_clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, + this->m_relativeFrame); + + marker = BKE_tracking_marker_get(track, relative_clip_framenr); + copy_v2_v2(this->m_relativePos, marker->pos); + } + } + } } void TrackPositionOperation::executePixelSampled(float output[4], - float /*x*/, float /*y*/, + float /*x*/, + float /*y*/, PixelSampler /*sampler*/) { - output[0] = this->m_markerPos[this->m_axis] - this->m_relativePos[this->m_axis]; + output[0] = this->m_markerPos[this->m_axis] - this->m_relativePos[this->m_axis]; - if (this->m_axis == 0) - output[0] *= this->m_width; - else - output[0] *= this->m_height; + if (this->m_axis == 0) + output[0] *= this->m_width; + else + output[0] *= this->m_height; } -void TrackPositionOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +void TrackPositionOperation::determineResolution(unsigned int resolution[2], + unsigned int preferredResolution[2]) { - resolution[0] = preferredResolution[0]; - resolution[1] = preferredResolution[1]; + resolution[0] = preferredResolution[0]; + resolution[1] = preferredResolution[1]; } diff --git a/source/blender/compositor/operations/COM_TrackPositionOperation.h b/source/blender/compositor/operations/COM_TrackPositionOperation.h index 95d27c3a5e4..695e85f4fa3 100644 --- a/source/blender/compositor/operations/COM_TrackPositionOperation.h +++ b/source/blender/compositor/operations/COM_TrackPositionOperation.h @@ -16,7 +16,6 @@ * Copyright 2012, Blender Foundation. */ - #ifndef __COM_TRACKPOSITIONOPERATION_H__ #define __COM_TRACKPOSITIONOPERATION_H__ @@ -34,42 +33,69 @@ * Class with implementation of green screen gradient rasterization */ class TrackPositionOperation : public NodeOperation { -protected: - MovieClip *m_movieClip; - int m_framenumber; - char m_trackingObjectName[64]; - char m_trackName[64]; - int m_axis; - int m_position; - int m_relativeFrame; - bool m_speed_output; + protected: + MovieClip *m_movieClip; + int m_framenumber; + char m_trackingObjectName[64]; + char m_trackName[64]; + int m_axis; + int m_position; + int m_relativeFrame; + bool m_speed_output; - int m_width, m_height; - float m_markerPos[2]; - float m_relativePos[2]; + int m_width, m_height; + float m_markerPos[2]; + float m_relativePos[2]; - /** - * Determine the output resolution. The resolution is retrieved from the Renderer - */ - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); + /** + * Determine the output resolution. The resolution is retrieved from the Renderer + */ + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); -public: - TrackPositionOperation(); + public: + TrackPositionOperation(); - void setMovieClip(MovieClip *clip) {this->m_movieClip = clip;} - void setTrackingObject(char *object) { BLI_strncpy(this->m_trackingObjectName, object, sizeof(this->m_trackingObjectName)); } - void setTrackName(char *track) { BLI_strncpy(this->m_trackName, track, sizeof(this->m_trackName)); } - void setFramenumber(int framenumber) {this->m_framenumber = framenumber;} - void setAxis(int value) {this->m_axis = value;} - void setPosition(int value) {this->m_position = value;} - void setRelativeFrame(int value) {this->m_relativeFrame = value;} - void setSpeedOutput(bool speed_output) {this->m_speed_output = speed_output;} + void setMovieClip(MovieClip *clip) + { + this->m_movieClip = clip; + } + void setTrackingObject(char *object) + { + BLI_strncpy(this->m_trackingObjectName, object, sizeof(this->m_trackingObjectName)); + } + void setTrackName(char *track) + { + BLI_strncpy(this->m_trackName, track, sizeof(this->m_trackName)); + } + void setFramenumber(int framenumber) + { + this->m_framenumber = framenumber; + } + void setAxis(int value) + { + this->m_axis = value; + } + void setPosition(int value) + { + this->m_position = value; + } + void setRelativeFrame(int value) + { + this->m_relativeFrame = value; + } + void setSpeedOutput(bool speed_output) + { + this->m_speed_output = speed_output; + } - void initExecution(); + void initExecution(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - bool isSetOperation() const { return true; } + bool isSetOperation() const + { + return true; + } }; #endif diff --git a/source/blender/compositor/operations/COM_TranslateOperation.cpp b/source/blender/compositor/operations/COM_TranslateOperation.cpp index 3e331a75c8d..b45e6a2b6a1 100644 --- a/source/blender/compositor/operations/COM_TranslateOperation.cpp +++ b/source/blender/compositor/operations/COM_TranslateOperation.cpp @@ -20,59 +20,63 @@ TranslateOperation::TranslateOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_COLOR); - this->setResolutionInputSocketIndex(0); - this->m_inputOperation = NULL; - this->m_inputXOperation = NULL; - this->m_inputYOperation = NULL; - this->m_isDeltaSet = false; - this->m_factorX = 1.0f; - this->m_factorY = 1.0f; + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_COLOR); + this->setResolutionInputSocketIndex(0); + this->m_inputOperation = NULL; + this->m_inputXOperation = NULL; + this->m_inputYOperation = NULL; + this->m_isDeltaSet = false; + this->m_factorX = 1.0f; + this->m_factorY = 1.0f; } void TranslateOperation::initExecution() { - this->m_inputOperation = this->getInputSocketReader(0); - this->m_inputXOperation = this->getInputSocketReader(1); - this->m_inputYOperation = this->getInputSocketReader(2); + this->m_inputOperation = this->getInputSocketReader(0); + this->m_inputXOperation = this->getInputSocketReader(1); + this->m_inputYOperation = this->getInputSocketReader(2); } void TranslateOperation::deinitExecution() { - this->m_inputOperation = NULL; - this->m_inputXOperation = NULL; - this->m_inputYOperation = NULL; + this->m_inputOperation = NULL; + this->m_inputXOperation = NULL; + this->m_inputYOperation = NULL; } - -void TranslateOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) +void TranslateOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler /*sampler*/) { - ensureDelta(); + ensureDelta(); - float originalXPos = x - this->getDeltaX(); - float originalYPos = y - this->getDeltaY(); + float originalXPos = x - this->getDeltaX(); + float originalYPos = y - this->getDeltaY(); - this->m_inputOperation->readSampled(output, originalXPos, originalYPos, COM_PS_BILINEAR); + this->m_inputOperation->readSampled(output, originalXPos, originalYPos, COM_PS_BILINEAR); } -bool TranslateOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool TranslateOperation::determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output) { - rcti newInput; + rcti newInput; - ensureDelta(); + ensureDelta(); - newInput.xmin = input->xmin - this->getDeltaX(); - newInput.xmax = input->xmax - this->getDeltaX(); - newInput.ymin = input->ymin - this->getDeltaY(); - newInput.ymax = input->ymax - this->getDeltaY(); + newInput.xmin = input->xmin - this->getDeltaX(); + newInput.xmax = input->xmax - this->getDeltaX(); + newInput.ymin = input->ymin - this->getDeltaY(); + newInput.ymax = input->ymax - this->getDeltaY(); - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } void TranslateOperation::setFactorXY(float factorX, float factorY) { - m_factorX = factorX; - m_factorY = factorY; + m_factorX = factorX; + m_factorY = factorY; } diff --git a/source/blender/compositor/operations/COM_TranslateOperation.h b/source/blender/compositor/operations/COM_TranslateOperation.h index c8fffaae2d8..2d13813a86a 100644 --- a/source/blender/compositor/operations/COM_TranslateOperation.h +++ b/source/blender/compositor/operations/COM_TranslateOperation.h @@ -22,38 +22,48 @@ #include "COM_NodeOperation.h" class TranslateOperation : public NodeOperation { -private: - SocketReader *m_inputOperation; - SocketReader *m_inputXOperation; - SocketReader *m_inputYOperation; - float m_deltaX; - float m_deltaY; - bool m_isDeltaSet; - float m_factorX; - float m_factorY; -public: - TranslateOperation(); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - - void initExecution(); - void deinitExecution(); - - float getDeltaX() { return this->m_deltaX * this->m_factorX; } - float getDeltaY() { return this->m_deltaY * this->m_factorY; } - - inline void ensureDelta() { - if (!this->m_isDeltaSet) { - float tempDelta[4]; - this->m_inputXOperation->readSampled(tempDelta, 0, 0, COM_PS_NEAREST); - this->m_deltaX = tempDelta[0]; - this->m_inputYOperation->readSampled(tempDelta, 0, 0, COM_PS_NEAREST); - this->m_deltaY = tempDelta[0]; - this->m_isDeltaSet = true; - } - } - - void setFactorXY(float factorX, float factorY); + private: + SocketReader *m_inputOperation; + SocketReader *m_inputXOperation; + SocketReader *m_inputYOperation; + float m_deltaX; + float m_deltaY; + bool m_isDeltaSet; + float m_factorX; + float m_factorY; + + public: + TranslateOperation(); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + + void initExecution(); + void deinitExecution(); + + float getDeltaX() + { + return this->m_deltaX * this->m_factorX; + } + float getDeltaY() + { + return this->m_deltaY * this->m_factorY; + } + + inline void ensureDelta() + { + if (!this->m_isDeltaSet) { + float tempDelta[4]; + this->m_inputXOperation->readSampled(tempDelta, 0, 0, COM_PS_NEAREST); + this->m_deltaX = tempDelta[0]; + this->m_inputYOperation->readSampled(tempDelta, 0, 0, COM_PS_NEAREST); + this->m_deltaY = tempDelta[0]; + this->m_isDeltaSet = true; + } + } + + void setFactorXY(float factorX, float factorY); }; #endif diff --git a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp index 1af4c107419..8b0335754aa 100644 --- a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp @@ -21,354 +21,363 @@ #include "COM_OpenCLDevice.h" extern "C" { -# include "RE_pipeline.h" +#include "RE_pipeline.h" } VariableSizeBokehBlurOperation::VariableSizeBokehBlurOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); // do not resize the bokeh image. - this->addInputSocket(COM_DT_VALUE); // radius + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); // do not resize the bokeh image. + this->addInputSocket(COM_DT_VALUE); // radius #ifdef COM_DEFOCUS_SEARCH - this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); // inverse search radius optimization structure. + this->addInputSocket(COM_DT_COLOR, + COM_SC_NO_RESIZE); // inverse search radius optimization structure. #endif - this->addOutputSocket(COM_DT_COLOR); - this->setComplex(true); - this->setOpenCL(true); - - this->m_inputProgram = NULL; - this->m_inputBokehProgram = NULL; - this->m_inputSizeProgram = NULL; - this->m_maxBlur = 32.0f; - this->m_threshold = 1.0f; - this->m_do_size_scale = false; + this->addOutputSocket(COM_DT_COLOR); + this->setComplex(true); + this->setOpenCL(true); + + this->m_inputProgram = NULL; + this->m_inputBokehProgram = NULL; + this->m_inputSizeProgram = NULL; + this->m_maxBlur = 32.0f; + this->m_threshold = 1.0f; + this->m_do_size_scale = false; #ifdef COM_DEFOCUS_SEARCH - this->m_inputSearchProgram = NULL; + this->m_inputSearchProgram = NULL; #endif } - void VariableSizeBokehBlurOperation::initExecution() { - this->m_inputProgram = getInputSocketReader(0); - this->m_inputBokehProgram = getInputSocketReader(1); - this->m_inputSizeProgram = getInputSocketReader(2); + this->m_inputProgram = getInputSocketReader(0); + this->m_inputBokehProgram = getInputSocketReader(1); + this->m_inputSizeProgram = getInputSocketReader(2); #ifdef COM_DEFOCUS_SEARCH - this->m_inputSearchProgram = getInputSocketReader(3); + this->m_inputSearchProgram = getInputSocketReader(3); #endif - QualityStepHelper::initExecution(COM_QH_INCREASE); + QualityStepHelper::initExecution(COM_QH_INCREASE); } struct VariableSizeBokehBlurTileData { - MemoryBuffer *color; - MemoryBuffer *bokeh; - MemoryBuffer *size; - int maxBlurScalar; + MemoryBuffer *color; + MemoryBuffer *bokeh; + MemoryBuffer *size; + int maxBlurScalar; }; void *VariableSizeBokehBlurOperation::initializeTileData(rcti *rect) { - VariableSizeBokehBlurTileData *data = new VariableSizeBokehBlurTileData(); - data->color = (MemoryBuffer *)this->m_inputProgram->initializeTileData(rect); - data->bokeh = (MemoryBuffer *)this->m_inputBokehProgram->initializeTileData(rect); - data->size = (MemoryBuffer *)this->m_inputSizeProgram->initializeTileData(rect); - + VariableSizeBokehBlurTileData *data = new VariableSizeBokehBlurTileData(); + data->color = (MemoryBuffer *)this->m_inputProgram->initializeTileData(rect); + data->bokeh = (MemoryBuffer *)this->m_inputBokehProgram->initializeTileData(rect); + data->size = (MemoryBuffer *)this->m_inputSizeProgram->initializeTileData(rect); - rcti rect2; - this->determineDependingAreaOfInterest(rect, (ReadBufferOperation *)this->m_inputSizeProgram, &rect2); + rcti rect2; + this->determineDependingAreaOfInterest( + rect, (ReadBufferOperation *)this->m_inputSizeProgram, &rect2); - const float max_dim = max(m_width, m_height); - const float scalar = this->m_do_size_scale ? (max_dim / 100.0f) : 1.0f; + const float max_dim = max(m_width, m_height); + const float scalar = this->m_do_size_scale ? (max_dim / 100.0f) : 1.0f; - data->maxBlurScalar = (int)(data->size->getMaximumValue(&rect2) * scalar); - CLAMP(data->maxBlurScalar, 1.0f, this->m_maxBlur); - return data; + data->maxBlurScalar = (int)(data->size->getMaximumValue(&rect2) * scalar); + CLAMP(data->maxBlurScalar, 1.0f, this->m_maxBlur); + return data; } void VariableSizeBokehBlurOperation::deinitializeTileData(rcti * /*rect*/, void *data) { - VariableSizeBokehBlurTileData *result = (VariableSizeBokehBlurTileData *)data; - delete result; + VariableSizeBokehBlurTileData *result = (VariableSizeBokehBlurTileData *)data; + delete result; } void VariableSizeBokehBlurOperation::executePixel(float output[4], int x, int y, void *data) { - VariableSizeBokehBlurTileData *tileData = (VariableSizeBokehBlurTileData *)data; - MemoryBuffer *inputProgramBuffer = tileData->color; - MemoryBuffer *inputBokehBuffer = tileData->bokeh; - MemoryBuffer *inputSizeBuffer = tileData->size; - float *inputSizeFloatBuffer = inputSizeBuffer->getBuffer(); - float *inputProgramFloatBuffer = inputProgramBuffer->getBuffer(); - float readColor[4]; - float bokeh[4]; - float tempSize[4]; - float multiplier_accum[4]; - float color_accum[4]; - - const float max_dim = max(m_width, m_height); - const float scalar = this->m_do_size_scale ? (max_dim / 100.0f) : 1.0f; - int maxBlurScalar = tileData->maxBlurScalar; - - BLI_assert(inputBokehBuffer->getWidth() == COM_BLUR_BOKEH_PIXELS); - BLI_assert(inputBokehBuffer->getHeight() == COM_BLUR_BOKEH_PIXELS); + VariableSizeBokehBlurTileData *tileData = (VariableSizeBokehBlurTileData *)data; + MemoryBuffer *inputProgramBuffer = tileData->color; + MemoryBuffer *inputBokehBuffer = tileData->bokeh; + MemoryBuffer *inputSizeBuffer = tileData->size; + float *inputSizeFloatBuffer = inputSizeBuffer->getBuffer(); + float *inputProgramFloatBuffer = inputProgramBuffer->getBuffer(); + float readColor[4]; + float bokeh[4]; + float tempSize[4]; + float multiplier_accum[4]; + float color_accum[4]; + + const float max_dim = max(m_width, m_height); + const float scalar = this->m_do_size_scale ? (max_dim / 100.0f) : 1.0f; + int maxBlurScalar = tileData->maxBlurScalar; + + BLI_assert(inputBokehBuffer->getWidth() == COM_BLUR_BOKEH_PIXELS); + BLI_assert(inputBokehBuffer->getHeight() == COM_BLUR_BOKEH_PIXELS); #ifdef COM_DEFOCUS_SEARCH - float search[4]; - this->m_inputSearchProgram->read(search, x / InverseSearchRadiusOperation::DIVIDER, y / InverseSearchRadiusOperation::DIVIDER, NULL); - int minx = search[0]; - int miny = search[1]; - int maxx = search[2]; - int maxy = search[3]; + float search[4]; + this->m_inputSearchProgram->read(search, + x / InverseSearchRadiusOperation::DIVIDER, + y / InverseSearchRadiusOperation::DIVIDER, + NULL); + int minx = search[0]; + int miny = search[1]; + int maxx = search[2]; + int maxy = search[3]; #else - int minx = max(x - maxBlurScalar, 0); - int miny = max(y - maxBlurScalar, 0); - int maxx = min(x + maxBlurScalar, (int)m_width); - int maxy = min(y + maxBlurScalar, (int)m_height); + int minx = max(x - maxBlurScalar, 0); + int miny = max(y - maxBlurScalar, 0); + int maxx = min(x + maxBlurScalar, (int)m_width); + int maxy = min(y + maxBlurScalar, (int)m_height); #endif - { - inputSizeBuffer->readNoCheck(tempSize, x, y); - inputProgramBuffer->readNoCheck(readColor, x, y); - - copy_v4_v4(color_accum, readColor); - copy_v4_fl(multiplier_accum, 1.0f); - float size_center = tempSize[0] * scalar; - - const int addXStepValue = QualityStepHelper::getStep(); - const int addYStepValue = addXStepValue; - const int addXStepColor = addXStepValue * COM_NUM_CHANNELS_COLOR; - - if (size_center > this->m_threshold) { - for (int ny = miny; ny < maxy; ny += addYStepValue) { - float dy = ny - y; - int offsetValueNy = ny * inputSizeBuffer->getWidth(); - int offsetValueNxNy = offsetValueNy + (minx); - int offsetColorNxNy = offsetValueNxNy * COM_NUM_CHANNELS_COLOR; - for (int nx = minx; nx < maxx; nx += addXStepValue) { - if (nx != x || ny != y) { - float size = min(inputSizeFloatBuffer[offsetValueNxNy] * scalar, size_center); - if (size > this->m_threshold) { - float dx = nx - x; - if (size > fabsf(dx) && size > fabsf(dy)) { - float uv[2] = { - (float)(COM_BLUR_BOKEH_PIXELS / 2) + (dx / size) * (float)((COM_BLUR_BOKEH_PIXELS / 2) - 1), - (float)(COM_BLUR_BOKEH_PIXELS / 2) + (dy / size) * (float)((COM_BLUR_BOKEH_PIXELS / 2) - 1)}; - inputBokehBuffer->read(bokeh, uv[0], uv[1]); - madd_v4_v4v4(color_accum, bokeh, &inputProgramFloatBuffer[offsetColorNxNy]); - add_v4_v4(multiplier_accum, bokeh); - } - } - } - offsetColorNxNy += addXStepColor; - offsetValueNxNy += addXStepValue; } - } - } - - output[0] = color_accum[0] / multiplier_accum[0]; - output[1] = color_accum[1] / multiplier_accum[1]; - output[2] = color_accum[2] / multiplier_accum[2]; - output[3] = color_accum[3] / multiplier_accum[3]; - - /* blend in out values over the threshold, otherwise we get sharp, ugly transitions */ - if ((size_center > this->m_threshold) && - (size_center < this->m_threshold * 2.0f)) - { - /* factor from 0-1 */ - float fac = (size_center - this->m_threshold) / this->m_threshold; - interp_v4_v4v4(output, readColor, output, fac); - } - } - + { + inputSizeBuffer->readNoCheck(tempSize, x, y); + inputProgramBuffer->readNoCheck(readColor, x, y); + + copy_v4_v4(color_accum, readColor); + copy_v4_fl(multiplier_accum, 1.0f); + float size_center = tempSize[0] * scalar; + + const int addXStepValue = QualityStepHelper::getStep(); + const int addYStepValue = addXStepValue; + const int addXStepColor = addXStepValue * COM_NUM_CHANNELS_COLOR; + + if (size_center > this->m_threshold) { + for (int ny = miny; ny < maxy; ny += addYStepValue) { + float dy = ny - y; + int offsetValueNy = ny * inputSizeBuffer->getWidth(); + int offsetValueNxNy = offsetValueNy + (minx); + int offsetColorNxNy = offsetValueNxNy * COM_NUM_CHANNELS_COLOR; + for (int nx = minx; nx < maxx; nx += addXStepValue) { + if (nx != x || ny != y) { + float size = min(inputSizeFloatBuffer[offsetValueNxNy] * scalar, size_center); + if (size > this->m_threshold) { + float dx = nx - x; + if (size > fabsf(dx) && size > fabsf(dy)) { + float uv[2] = {(float)(COM_BLUR_BOKEH_PIXELS / 2) + + (dx / size) * (float)((COM_BLUR_BOKEH_PIXELS / 2) - 1), + (float)(COM_BLUR_BOKEH_PIXELS / 2) + + (dy / size) * (float)((COM_BLUR_BOKEH_PIXELS / 2) - 1)}; + inputBokehBuffer->read(bokeh, uv[0], uv[1]); + madd_v4_v4v4(color_accum, bokeh, &inputProgramFloatBuffer[offsetColorNxNy]); + add_v4_v4(multiplier_accum, bokeh); + } + } + } + offsetColorNxNy += addXStepColor; + offsetValueNxNy += addXStepValue; + } + } + } + + output[0] = color_accum[0] / multiplier_accum[0]; + output[1] = color_accum[1] / multiplier_accum[1]; + output[2] = color_accum[2] / multiplier_accum[2]; + output[3] = color_accum[3] / multiplier_accum[3]; + + /* blend in out values over the threshold, otherwise we get sharp, ugly transitions */ + if ((size_center > this->m_threshold) && (size_center < this->m_threshold * 2.0f)) { + /* factor from 0-1 */ + float fac = (size_center - this->m_threshold) / this->m_threshold; + interp_v4_v4v4(output, readColor, output, fac); + } + } } void VariableSizeBokehBlurOperation::executeOpenCL(OpenCLDevice *device, - MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, - MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, - list<cl_kernel> * /*clKernelsToCleanUp*/) + MemoryBuffer *outputMemoryBuffer, + cl_mem clOutputBuffer, + MemoryBuffer **inputMemoryBuffers, + list<cl_mem> *clMemToCleanUp, + list<cl_kernel> * /*clKernelsToCleanUp*/) { - cl_kernel defocusKernel = device->COM_clCreateKernel("defocusKernel", NULL); - - cl_int step = this->getStep(); - cl_int maxBlur; - cl_float threshold = this->m_threshold; - - MemoryBuffer *sizeMemoryBuffer = this->m_inputSizeProgram->getInputMemoryBuffer(inputMemoryBuffers); - - const float max_dim = max(m_width, m_height); - cl_float scalar = this->m_do_size_scale ? (max_dim / 100.0f) : 1.0f; - - maxBlur = (cl_int)min_ff(sizeMemoryBuffer->getMaximumValue() * scalar, - (float)this->m_maxBlur); - - device->COM_clAttachMemoryBufferToKernelParameter(defocusKernel, 0, -1, clMemToCleanUp, inputMemoryBuffers, this->m_inputProgram); - device->COM_clAttachMemoryBufferToKernelParameter(defocusKernel, 1, -1, clMemToCleanUp, inputMemoryBuffers, this->m_inputBokehProgram); - device->COM_clAttachMemoryBufferToKernelParameter(defocusKernel, 2, 4, clMemToCleanUp, inputMemoryBuffers, this->m_inputSizeProgram); - device->COM_clAttachOutputMemoryBufferToKernelParameter(defocusKernel, 3, clOutputBuffer); - device->COM_clAttachMemoryBufferOffsetToKernelParameter(defocusKernel, 5, outputMemoryBuffer); - clSetKernelArg(defocusKernel, 6, sizeof(cl_int), &step); - clSetKernelArg(defocusKernel, 7, sizeof(cl_int), &maxBlur); - clSetKernelArg(defocusKernel, 8, sizeof(cl_float), &threshold); - clSetKernelArg(defocusKernel, 9, sizeof(cl_float), &scalar); - device->COM_clAttachSizeToKernelParameter(defocusKernel, 10, this); - - device->COM_clEnqueueRange(defocusKernel, outputMemoryBuffer, 11, this); + cl_kernel defocusKernel = device->COM_clCreateKernel("defocusKernel", NULL); + + cl_int step = this->getStep(); + cl_int maxBlur; + cl_float threshold = this->m_threshold; + + MemoryBuffer *sizeMemoryBuffer = this->m_inputSizeProgram->getInputMemoryBuffer( + inputMemoryBuffers); + + const float max_dim = max(m_width, m_height); + cl_float scalar = this->m_do_size_scale ? (max_dim / 100.0f) : 1.0f; + + maxBlur = (cl_int)min_ff(sizeMemoryBuffer->getMaximumValue() * scalar, (float)this->m_maxBlur); + + device->COM_clAttachMemoryBufferToKernelParameter( + defocusKernel, 0, -1, clMemToCleanUp, inputMemoryBuffers, this->m_inputProgram); + device->COM_clAttachMemoryBufferToKernelParameter( + defocusKernel, 1, -1, clMemToCleanUp, inputMemoryBuffers, this->m_inputBokehProgram); + device->COM_clAttachMemoryBufferToKernelParameter( + defocusKernel, 2, 4, clMemToCleanUp, inputMemoryBuffers, this->m_inputSizeProgram); + device->COM_clAttachOutputMemoryBufferToKernelParameter(defocusKernel, 3, clOutputBuffer); + device->COM_clAttachMemoryBufferOffsetToKernelParameter(defocusKernel, 5, outputMemoryBuffer); + clSetKernelArg(defocusKernel, 6, sizeof(cl_int), &step); + clSetKernelArg(defocusKernel, 7, sizeof(cl_int), &maxBlur); + clSetKernelArg(defocusKernel, 8, sizeof(cl_float), &threshold); + clSetKernelArg(defocusKernel, 9, sizeof(cl_float), &scalar); + device->COM_clAttachSizeToKernelParameter(defocusKernel, 10, this); + + device->COM_clEnqueueRange(defocusKernel, outputMemoryBuffer, 11, this); } void VariableSizeBokehBlurOperation::deinitExecution() { - this->m_inputProgram = NULL; - this->m_inputBokehProgram = NULL; - this->m_inputSizeProgram = NULL; + this->m_inputProgram = NULL; + this->m_inputBokehProgram = NULL; + this->m_inputSizeProgram = NULL; #ifdef COM_DEFOCUS_SEARCH - this->m_inputSearchProgram = NULL; + this->m_inputSearchProgram = NULL; #endif } -bool VariableSizeBokehBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool VariableSizeBokehBlurOperation::determineDependingAreaOfInterest( + rcti *input, ReadBufferOperation *readOperation, rcti *output) { - rcti newInput; - rcti bokehInput; - - const float max_dim = max(m_width, m_height); - const float scalar = this->m_do_size_scale ? (max_dim / 100.0f) : 1.0f; - int maxBlurScalar = this->m_maxBlur * scalar; - - newInput.xmax = input->xmax + maxBlurScalar + 2; - newInput.xmin = input->xmin - maxBlurScalar + 2; - newInput.ymax = input->ymax + maxBlurScalar - 2; - newInput.ymin = input->ymin - maxBlurScalar - 2; - bokehInput.xmax = COM_BLUR_BOKEH_PIXELS; - bokehInput.xmin = 0; - bokehInput.ymax = COM_BLUR_BOKEH_PIXELS; - bokehInput.ymin = 0; - - - NodeOperation *operation = getInputOperation(2); - if (operation->determineDependingAreaOfInterest(&newInput, readOperation, output) ) { - return true; - } - operation = getInputOperation(1); - if (operation->determineDependingAreaOfInterest(&bokehInput, readOperation, output) ) { - return true; - } + rcti newInput; + rcti bokehInput; + + const float max_dim = max(m_width, m_height); + const float scalar = this->m_do_size_scale ? (max_dim / 100.0f) : 1.0f; + int maxBlurScalar = this->m_maxBlur * scalar; + + newInput.xmax = input->xmax + maxBlurScalar + 2; + newInput.xmin = input->xmin - maxBlurScalar + 2; + newInput.ymax = input->ymax + maxBlurScalar - 2; + newInput.ymin = input->ymin - maxBlurScalar - 2; + bokehInput.xmax = COM_BLUR_BOKEH_PIXELS; + bokehInput.xmin = 0; + bokehInput.ymax = COM_BLUR_BOKEH_PIXELS; + bokehInput.ymin = 0; + + NodeOperation *operation = getInputOperation(2); + if (operation->determineDependingAreaOfInterest(&newInput, readOperation, output)) { + return true; + } + operation = getInputOperation(1); + if (operation->determineDependingAreaOfInterest(&bokehInput, readOperation, output)) { + return true; + } #ifdef COM_DEFOCUS_SEARCH - rcti searchInput; - searchInput.xmax = (input->xmax / InverseSearchRadiusOperation::DIVIDER) + 1; - searchInput.xmin = (input->xmin / InverseSearchRadiusOperation::DIVIDER) - 1; - searchInput.ymax = (input->ymax / InverseSearchRadiusOperation::DIVIDER) + 1; - searchInput.ymin = (input->ymin / InverseSearchRadiusOperation::DIVIDER) - 1; - operation = getInputOperation(3); - if (operation->determineDependingAreaOfInterest(&searchInput, readOperation, output) ) { - return true; - } + rcti searchInput; + searchInput.xmax = (input->xmax / InverseSearchRadiusOperation::DIVIDER) + 1; + searchInput.xmin = (input->xmin / InverseSearchRadiusOperation::DIVIDER) - 1; + searchInput.ymax = (input->ymax / InverseSearchRadiusOperation::DIVIDER) + 1; + searchInput.ymin = (input->ymin / InverseSearchRadiusOperation::DIVIDER) - 1; + operation = getInputOperation(3); + if (operation->determineDependingAreaOfInterest(&searchInput, readOperation, output)) { + return true; + } #endif - operation = getInputOperation(0); - if (operation->determineDependingAreaOfInterest(&newInput, readOperation, output) ) { - return true; - } - return false; + operation = getInputOperation(0); + if (operation->determineDependingAreaOfInterest(&newInput, readOperation, output)) { + return true; + } + return false; } #ifdef COM_DEFOCUS_SEARCH // InverseSearchRadiusOperation InverseSearchRadiusOperation::InverseSearchRadiusOperation() : NodeOperation() { - this->addInputSocket(COM_DT_VALUE, COM_SC_NO_RESIZE); // radius - this->addOutputSocket(COM_DT_COLOR); - this->setComplex(true); - this->m_inputRadius = NULL; + this->addInputSocket(COM_DT_VALUE, COM_SC_NO_RESIZE); // radius + this->addOutputSocket(COM_DT_COLOR); + this->setComplex(true); + this->m_inputRadius = NULL; } void InverseSearchRadiusOperation::initExecution() { - this->m_inputRadius = this->getInputSocketReader(0); + this->m_inputRadius = this->getInputSocketReader(0); } void *InverseSearchRadiusOperation::initializeTileData(rcti *rect) { - MemoryBuffer *data = new MemoryBuffer(COM_DT_COLOR, rect); - float *buffer = data->getBuffer(); - int x, y; - int width = this->m_inputRadius->getWidth(); - int height = this->m_inputRadius->getHeight(); - float temp[4]; - int offset = 0; - for (y = rect->ymin; y < rect->ymax ; y++) { - for (x = rect->xmin; x < rect->xmax ; x++) { - int rx = x * DIVIDER; - int ry = y * DIVIDER; - buffer[offset] = MAX2(rx - m_maxBlur, 0); - buffer[offset + 1] = MAX2(ry - m_maxBlur, 0); - buffer[offset + 2] = MIN2(rx + DIVIDER + m_maxBlur, width); - buffer[offset + 3] = MIN2(ry + DIVIDER + m_maxBlur, height); - offset += 4; - } - } -// for (x = rect->xmin; x < rect->xmax ; x++) { -// for (y = rect->ymin; y < rect->ymax ; y++) { -// int rx = x * DIVIDER; -// int ry = y * DIVIDER; -// float radius = 0.0f; -// float maxx = x; -// float maxy = y; - -// for (int x2 = 0 ; x2 < DIVIDER ; x2 ++) { -// for (int y2 = 0 ; y2 < DIVIDER ; y2 ++) { -// this->m_inputRadius->read(temp, rx+x2, ry+y2, COM_PS_NEAREST); -// if (radius < temp[0]) { -// radius = temp[0]; -// maxx = x2; -// maxy = y2; -// } -// } -// } -// int impactRadius = ceil(radius / DIVIDER); -// for (int x2 = x - impactRadius ; x2 < x + impactRadius ; x2 ++) { -// for (int y2 = y - impactRadius ; y2 < y + impactRadius ; y2 ++) { -// data->read(temp, x2, y2); -// temp[0] = MIN2(temp[0], maxx); -// temp[1] = MIN2(temp[1], maxy); -// temp[2] = MAX2(temp[2], maxx); -// temp[3] = MAX2(temp[3], maxy); -// data->writePixel(x2, y2, temp); -// } -// } -// } -// } - return data; + MemoryBuffer *data = new MemoryBuffer(COM_DT_COLOR, rect); + float *buffer = data->getBuffer(); + int x, y; + int width = this->m_inputRadius->getWidth(); + int height = this->m_inputRadius->getHeight(); + float temp[4]; + int offset = 0; + for (y = rect->ymin; y < rect->ymax; y++) { + for (x = rect->xmin; x < rect->xmax; x++) { + int rx = x * DIVIDER; + int ry = y * DIVIDER; + buffer[offset] = MAX2(rx - m_maxBlur, 0); + buffer[offset + 1] = MAX2(ry - m_maxBlur, 0); + buffer[offset + 2] = MIN2(rx + DIVIDER + m_maxBlur, width); + buffer[offset + 3] = MIN2(ry + DIVIDER + m_maxBlur, height); + offset += 4; + } + } + // for (x = rect->xmin; x < rect->xmax ; x++) { + // for (y = rect->ymin; y < rect->ymax ; y++) { + // int rx = x * DIVIDER; + // int ry = y * DIVIDER; + // float radius = 0.0f; + // float maxx = x; + // float maxy = y; + + // for (int x2 = 0 ; x2 < DIVIDER ; x2 ++) { + // for (int y2 = 0 ; y2 < DIVIDER ; y2 ++) { + // this->m_inputRadius->read(temp, rx+x2, ry+y2, COM_PS_NEAREST); + // if (radius < temp[0]) { + // radius = temp[0]; + // maxx = x2; + // maxy = y2; + // } + // } + // } + // int impactRadius = ceil(radius / DIVIDER); + // for (int x2 = x - impactRadius ; x2 < x + impactRadius ; x2 ++) { + // for (int y2 = y - impactRadius ; y2 < y + impactRadius ; y2 ++) { + // data->read(temp, x2, y2); + // temp[0] = MIN2(temp[0], maxx); + // temp[1] = MIN2(temp[1], maxy); + // temp[2] = MAX2(temp[2], maxx); + // temp[3] = MAX2(temp[3], maxy); + // data->writePixel(x2, y2, temp); + // } + // } + // } + // } + return data; } void InverseSearchRadiusOperation::executePixelChunk(float output[4], int x, int y, void *data) { - MemoryBuffer *buffer = (MemoryBuffer *)data; - buffer->readNoCheck(output, x, y); + MemoryBuffer *buffer = (MemoryBuffer *)data; + buffer->readNoCheck(output, x, y); } void InverseSearchRadiusOperation::deinitializeTileData(rcti *rect, void *data) { - if (data) { - MemoryBuffer *mb = (MemoryBuffer *)data; - delete mb; - } + if (data) { + MemoryBuffer *mb = (MemoryBuffer *)data; + delete mb; + } } void InverseSearchRadiusOperation::deinitExecution() { - this->m_inputRadius = NULL; + this->m_inputRadius = NULL; } -void InverseSearchRadiusOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +void InverseSearchRadiusOperation::determineResolution(unsigned int resolution[2], + unsigned int preferredResolution[2]) { - NodeOperation::determineResolution(resolution, preferredResolution); - resolution[0] = resolution[0] / DIVIDER; - resolution[1] = resolution[1] / DIVIDER; + NodeOperation::determineResolution(resolution, preferredResolution); + resolution[0] = resolution[0] / DIVIDER; + resolution[1] = resolution[1] / DIVIDER; } -bool InverseSearchRadiusOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool InverseSearchRadiusOperation::determineDependingAreaOfInterest( + rcti *input, ReadBufferOperation *readOperation, rcti *output) { - rcti newRect; - newRect.ymin = input->ymin * DIVIDER - m_maxBlur; - newRect.ymax = input->ymax * DIVIDER + m_maxBlur; - newRect.xmin = input->xmin * DIVIDER - m_maxBlur; - newRect.xmax = input->xmax * DIVIDER + m_maxBlur; - return NodeOperation::determineDependingAreaOfInterest(&newRect, readOperation, output); + rcti newRect; + newRect.ymin = input->ymin * DIVIDER - m_maxBlur; + newRect.ymax = input->ymax * DIVIDER + m_maxBlur; + newRect.xmin = input->xmin * DIVIDER - m_maxBlur; + newRect.xmax = input->xmax * DIVIDER + m_maxBlur; + return NodeOperation::determineDependingAreaOfInterest(&newRect, readOperation, output); } #endif diff --git a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.h b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.h index f586bf73dca..930bfd77943 100644 --- a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.h +++ b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.h @@ -24,81 +24,103 @@ //#define COM_DEFOCUS_SEARCH class VariableSizeBokehBlurOperation : public NodeOperation, public QualityStepHelper { -private: - int m_maxBlur; - float m_threshold; - bool m_do_size_scale; /* scale size, matching 'BokehBlurNode' */ - SocketReader *m_inputProgram; - SocketReader *m_inputBokehProgram; - SocketReader *m_inputSizeProgram; + private: + int m_maxBlur; + float m_threshold; + bool m_do_size_scale; /* scale size, matching 'BokehBlurNode' */ + SocketReader *m_inputProgram; + SocketReader *m_inputBokehProgram; + SocketReader *m_inputSizeProgram; #ifdef COM_DEFOCUS_SEARCH - SocketReader *m_inputSearchProgram; + SocketReader *m_inputSearchProgram; #endif -public: - VariableSizeBokehBlurOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], int x, int y, void *data); - - /** - * Initialize the execution - */ - void initExecution(); - - void *initializeTileData(rcti *rect); - - void deinitializeTileData(rcti *rect, void *data); - - /** - * Deinitialize the execution - */ - void deinitExecution(); - - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - - void setMaxBlur(int maxRadius) { this->m_maxBlur = maxRadius; } - - void setThreshold(float threshold) { this->m_threshold = threshold; } - - void setDoScaleSize(bool scale_size) { this->m_do_size_scale = scale_size; } - - void executeOpenCL(OpenCLDevice *device, MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, list<cl_kernel> *clKernelsToCleanUp); + public: + VariableSizeBokehBlurOperation(); + + /** + * the inner loop of this program + */ + void executePixel(float output[4], int x, int y, void *data); + + /** + * Initialize the execution + */ + void initExecution(); + + void *initializeTileData(rcti *rect); + + void deinitializeTileData(rcti *rect, void *data); + + /** + * Deinitialize the execution + */ + void deinitExecution(); + + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + + void setMaxBlur(int maxRadius) + { + this->m_maxBlur = maxRadius; + } + + void setThreshold(float threshold) + { + this->m_threshold = threshold; + } + + void setDoScaleSize(bool scale_size) + { + this->m_do_size_scale = scale_size; + } + + void executeOpenCL(OpenCLDevice *device, + MemoryBuffer *outputMemoryBuffer, + cl_mem clOutputBuffer, + MemoryBuffer **inputMemoryBuffers, + list<cl_mem> *clMemToCleanUp, + list<cl_kernel> *clKernelsToCleanUp); }; #ifdef COM_DEFOCUS_SEARCH class InverseSearchRadiusOperation : public NodeOperation { -private: - int m_maxBlur; - SocketReader *m_inputRadius; -public: - static const int DIVIDER = 4; - - InverseSearchRadiusOperation(); - - /** - * the inner loop of this program - */ - void executePixelChunk(float output[4], int x, int y, void *data); - - /** - * Initialize the execution - */ - void initExecution(); - void *initializeTileData(rcti *rect); - void deinitializeTileData(rcti *rect, void *data); - - /** - * Deinitialize the execution - */ - void deinitExecution(); - - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); - - void setMaxBlur(int maxRadius) { this->m_maxBlur = maxRadius; } + private: + int m_maxBlur; + SocketReader *m_inputRadius; + + public: + static const int DIVIDER = 4; + + InverseSearchRadiusOperation(); + + /** + * the inner loop of this program + */ + void executePixelChunk(float output[4], int x, int y, void *data); + + /** + * Initialize the execution + */ + void initExecution(); + void *initializeTileData(rcti *rect); + void deinitializeTileData(rcti *rect, void *data); + + /** + * Deinitialize the execution + */ + void deinitExecution(); + + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); + + void setMaxBlur(int maxRadius) + { + this->m_maxBlur = maxRadius; + } }; #endif #endif diff --git a/source/blender/compositor/operations/COM_VectorBlurOperation.cpp b/source/blender/compositor/operations/COM_VectorBlurOperation.cpp index 6e408d9860d..26e688e1c97 100644 --- a/source/blender/compositor/operations/COM_VectorBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_VectorBlurOperation.cpp @@ -24,441 +24,470 @@ extern "C" { } #include "COM_VectorBlurOperation.h" - /* Defined */ #define PASS_VECTOR_MAX 10000.0f /* Forward declarations */ struct DrawBufPixel; struct ZSpan; -void zbuf_accumulate_vecblur( - NodeBlurData *nbd, int xsize, int ysize, float *newrect, - const float *imgrect, float *vecbufrect, const float *zbufrect); +void zbuf_accumulate_vecblur(NodeBlurData *nbd, + int xsize, + int ysize, + float *newrect, + const float *imgrect, + float *vecbufrect, + const float *zbufrect); void zbuf_alloc_span(ZSpan *zspan, int rectx, int recty, float clipcrop); void zbuf_free_span(ZSpan *zspan); void antialias_tagbuf(int xsize, int ysize, char *rectmove); - /* VectorBlurOperation */ VectorBlurOperation::VectorBlurOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_VALUE); // ZBUF - this->addInputSocket(COM_DT_COLOR); //SPEED - this->addOutputSocket(COM_DT_COLOR); - this->m_settings = NULL; - this->m_cachedInstance = NULL; - this->m_inputImageProgram = NULL; - this->m_inputSpeedProgram = NULL; - this->m_inputZProgram = NULL; - setComplex(true); + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VALUE); // ZBUF + this->addInputSocket(COM_DT_COLOR); //SPEED + this->addOutputSocket(COM_DT_COLOR); + this->m_settings = NULL; + this->m_cachedInstance = NULL; + this->m_inputImageProgram = NULL; + this->m_inputSpeedProgram = NULL; + this->m_inputZProgram = NULL; + setComplex(true); } void VectorBlurOperation::initExecution() { - initMutex(); - this->m_inputImageProgram = getInputSocketReader(0); - this->m_inputZProgram = getInputSocketReader(1); - this->m_inputSpeedProgram = getInputSocketReader(2); - this->m_cachedInstance = NULL; - QualityStepHelper::initExecution(COM_QH_INCREASE); - + initMutex(); + this->m_inputImageProgram = getInputSocketReader(0); + this->m_inputZProgram = getInputSocketReader(1); + this->m_inputSpeedProgram = getInputSocketReader(2); + this->m_cachedInstance = NULL; + QualityStepHelper::initExecution(COM_QH_INCREASE); } void VectorBlurOperation::executePixel(float output[4], int x, int y, void *data) { - float *buffer = (float *)data; - int index = (y * this->getWidth() + x) * COM_NUM_CHANNELS_COLOR; - copy_v4_v4(output, &buffer[index]); + float *buffer = (float *)data; + int index = (y * this->getWidth() + x) * COM_NUM_CHANNELS_COLOR; + copy_v4_v4(output, &buffer[index]); } void VectorBlurOperation::deinitExecution() { - deinitMutex(); - this->m_inputImageProgram = NULL; - this->m_inputSpeedProgram = NULL; - this->m_inputZProgram = NULL; - if (this->m_cachedInstance) { - MEM_freeN(this->m_cachedInstance); - this->m_cachedInstance = NULL; - } + deinitMutex(); + this->m_inputImageProgram = NULL; + this->m_inputSpeedProgram = NULL; + this->m_inputZProgram = NULL; + if (this->m_cachedInstance) { + MEM_freeN(this->m_cachedInstance); + this->m_cachedInstance = NULL; + } } void *VectorBlurOperation::initializeTileData(rcti *rect) { - if (this->m_cachedInstance) { - return this->m_cachedInstance; - } - - lockMutex(); - if (this->m_cachedInstance == NULL) { - MemoryBuffer *tile = (MemoryBuffer *)this->m_inputImageProgram->initializeTileData(rect); - MemoryBuffer *speed = (MemoryBuffer *)this->m_inputSpeedProgram->initializeTileData(rect); - MemoryBuffer *z = (MemoryBuffer *)this->m_inputZProgram->initializeTileData(rect); - float *data = (float *)MEM_dupallocN(tile->getBuffer()); - this->generateVectorBlur(data, tile, speed, z); - this->m_cachedInstance = data; - } - unlockMutex(); - return this->m_cachedInstance; + if (this->m_cachedInstance) { + return this->m_cachedInstance; + } + + lockMutex(); + if (this->m_cachedInstance == NULL) { + MemoryBuffer *tile = (MemoryBuffer *)this->m_inputImageProgram->initializeTileData(rect); + MemoryBuffer *speed = (MemoryBuffer *)this->m_inputSpeedProgram->initializeTileData(rect); + MemoryBuffer *z = (MemoryBuffer *)this->m_inputZProgram->initializeTileData(rect); + float *data = (float *)MEM_dupallocN(tile->getBuffer()); + this->generateVectorBlur(data, tile, speed, z); + this->m_cachedInstance = data; + } + unlockMutex(); + return this->m_cachedInstance; } -bool VectorBlurOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output) +bool VectorBlurOperation::determineDependingAreaOfInterest(rcti * /*input*/, + ReadBufferOperation *readOperation, + rcti *output) { - if (this->m_cachedInstance == NULL) { - rcti newInput; - newInput.xmax = this->getWidth(); - newInput.xmin = 0; - newInput.ymax = this->getHeight(); - newInput.ymin = 0; - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); - } - else { - return false; - } + if (this->m_cachedInstance == NULL) { + rcti newInput; + newInput.xmax = this->getWidth(); + newInput.xmin = 0; + newInput.ymax = this->getHeight(); + newInput.ymin = 0; + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + } + else { + return false; + } } -void VectorBlurOperation::generateVectorBlur(float *data, MemoryBuffer *inputImage, MemoryBuffer *inputSpeed, MemoryBuffer *inputZ) +void VectorBlurOperation::generateVectorBlur(float *data, + MemoryBuffer *inputImage, + MemoryBuffer *inputSpeed, + MemoryBuffer *inputZ) { - NodeBlurData blurdata; - blurdata.samples = this->m_settings->samples / QualityStepHelper::getStep(); - blurdata.maxspeed = this->m_settings->maxspeed; - blurdata.minspeed = this->m_settings->minspeed; - blurdata.curved = this->m_settings->curved; - blurdata.fac = this->m_settings->fac; - zbuf_accumulate_vecblur(&blurdata, this->getWidth(), this->getHeight(), data, inputImage->getBuffer(), inputSpeed->getBuffer(), inputZ->getBuffer()); - return; + NodeBlurData blurdata; + blurdata.samples = this->m_settings->samples / QualityStepHelper::getStep(); + blurdata.maxspeed = this->m_settings->maxspeed; + blurdata.minspeed = this->m_settings->minspeed; + blurdata.curved = this->m_settings->curved; + blurdata.fac = this->m_settings->fac; + zbuf_accumulate_vecblur(&blurdata, + this->getWidth(), + this->getHeight(), + data, + inputImage->getBuffer(), + inputSpeed->getBuffer(), + inputZ->getBuffer()); + return; } /* ****************** Spans ******************************* */ /* span fill in method, is also used to localize data for zbuffering */ typedef struct ZSpan { - /* range for clipping */ - int rectx, recty; + /* range for clipping */ + int rectx, recty; - /* actual filled in range */ - int miny1, maxy1, miny2, maxy2; - /* vertex pointers detect min/max range in */ - const float *minp1, *maxp1, *minp2, *maxp2; - float *span1, *span2; + /* actual filled in range */ + int miny1, maxy1, miny2, maxy2; + /* vertex pointers detect min/max range in */ + const float *minp1, *maxp1, *minp2, *maxp2; + float *span1, *span2; - /* transform from hoco to zbuf co */ - float zmulx, zmuly, zofsx, zofsy; + /* transform from hoco to zbuf co */ + float zmulx, zmuly, zofsx, zofsy; - int *rectz; - DrawBufPixel *rectdraw; - float clipcrop; + int *rectz; + DrawBufPixel *rectdraw; + float clipcrop; } ZSpan; /* each zbuffer has coordinates transformed to local rect coordinates, so we can simply clip */ void zbuf_alloc_span(ZSpan *zspan, int rectx, int recty, float clipcrop) { - memset(zspan, 0, sizeof(ZSpan)); + memset(zspan, 0, sizeof(ZSpan)); - zspan->rectx = rectx; - zspan->recty = recty; + zspan->rectx = rectx; + zspan->recty = recty; - zspan->span1 = (float *)MEM_mallocN(recty * sizeof(float), "zspan"); - zspan->span2 = (float *)MEM_mallocN(recty * sizeof(float), "zspan"); + zspan->span1 = (float *)MEM_mallocN(recty * sizeof(float), "zspan"); + zspan->span2 = (float *)MEM_mallocN(recty * sizeof(float), "zspan"); - zspan->clipcrop = clipcrop; + zspan->clipcrop = clipcrop; } void zbuf_free_span(ZSpan *zspan) { - if (zspan) { - if (zspan->span1) MEM_freeN(zspan->span1); - if (zspan->span2) MEM_freeN(zspan->span2); - zspan->span1 = zspan->span2 = NULL; - } + if (zspan) { + if (zspan->span1) + MEM_freeN(zspan->span1); + if (zspan->span2) + MEM_freeN(zspan->span2); + zspan->span1 = zspan->span2 = NULL; + } } /* reset range for clipping */ static void zbuf_init_span(ZSpan *zspan) { - zspan->miny1 = zspan->miny2 = zspan->recty + 1; - zspan->maxy1 = zspan->maxy2 = -1; - zspan->minp1 = zspan->maxp1 = zspan->minp2 = zspan->maxp2 = NULL; + zspan->miny1 = zspan->miny2 = zspan->recty + 1; + zspan->maxy1 = zspan->maxy2 = -1; + zspan->minp1 = zspan->maxp1 = zspan->minp2 = zspan->maxp2 = NULL; } static void zbuf_add_to_span(ZSpan *zspan, const float v1[2], const float v2[2]) { - const float *minv, *maxv; - float *span; - float xx1, dx0, xs0; - int y, my0, my2; - - if (v1[1] < v2[1]) { - minv = v1; maxv = v2; - } - else { - minv = v2; maxv = v1; - } - - my0 = ceil(minv[1]); - my2 = floor(maxv[1]); - - if (my2 < 0 || my0 >= zspan->recty) return; - - /* clip top */ - if (my2 >= zspan->recty) my2 = zspan->recty - 1; - /* clip bottom */ - if (my0 < 0) my0 = 0; - - if (my0 > my2) return; - /* if (my0>my2) should still fill in, that way we get spans that skip nicely */ - - xx1 = maxv[1] - minv[1]; - if (xx1 > FLT_EPSILON) { - dx0 = (minv[0] - maxv[0]) / xx1; - xs0 = dx0 * (minv[1] - my2) + minv[0]; - } - else { - dx0 = 0.0f; - xs0 = min_ff(minv[0], maxv[0]); - } - - /* empty span */ - if (zspan->maxp1 == NULL) { - span = zspan->span1; - } - else { /* does it complete left span? */ - if (maxv == zspan->minp1 || minv == zspan->maxp1) { - span = zspan->span1; - } - else { - span = zspan->span2; - } - } - - if (span == zspan->span1) { -// printf("left span my0 %d my2 %d\n", my0, my2); - if (zspan->minp1 == NULL || zspan->minp1[1] > minv[1]) { - zspan->minp1 = minv; - } - if (zspan->maxp1 == NULL || zspan->maxp1[1] < maxv[1]) { - zspan->maxp1 = maxv; - } - if (my0 < zspan->miny1) zspan->miny1 = my0; - if (my2 > zspan->maxy1) zspan->maxy1 = my2; - } - else { -// printf("right span my0 %d my2 %d\n", my0, my2); - if (zspan->minp2 == NULL || zspan->minp2[1] > minv[1]) { - zspan->minp2 = minv; - } - if (zspan->maxp2 == NULL || zspan->maxp2[1] < maxv[1]) { - zspan->maxp2 = maxv; - } - if (my0 < zspan->miny2) zspan->miny2 = my0; - if (my2 > zspan->maxy2) zspan->maxy2 = my2; - } - - for (y = my2; y >= my0; y--, xs0 += dx0) { - /* xs0 is the xcoord! */ - span[y] = xs0; - } + const float *minv, *maxv; + float *span; + float xx1, dx0, xs0; + int y, my0, my2; + + if (v1[1] < v2[1]) { + minv = v1; + maxv = v2; + } + else { + minv = v2; + maxv = v1; + } + + my0 = ceil(minv[1]); + my2 = floor(maxv[1]); + + if (my2 < 0 || my0 >= zspan->recty) + return; + + /* clip top */ + if (my2 >= zspan->recty) + my2 = zspan->recty - 1; + /* clip bottom */ + if (my0 < 0) + my0 = 0; + + if (my0 > my2) + return; + /* if (my0>my2) should still fill in, that way we get spans that skip nicely */ + + xx1 = maxv[1] - minv[1]; + if (xx1 > FLT_EPSILON) { + dx0 = (minv[0] - maxv[0]) / xx1; + xs0 = dx0 * (minv[1] - my2) + minv[0]; + } + else { + dx0 = 0.0f; + xs0 = min_ff(minv[0], maxv[0]); + } + + /* empty span */ + if (zspan->maxp1 == NULL) { + span = zspan->span1; + } + else { /* does it complete left span? */ + if (maxv == zspan->minp1 || minv == zspan->maxp1) { + span = zspan->span1; + } + else { + span = zspan->span2; + } + } + + if (span == zspan->span1) { + // printf("left span my0 %d my2 %d\n", my0, my2); + if (zspan->minp1 == NULL || zspan->minp1[1] > minv[1]) { + zspan->minp1 = minv; + } + if (zspan->maxp1 == NULL || zspan->maxp1[1] < maxv[1]) { + zspan->maxp1 = maxv; + } + if (my0 < zspan->miny1) + zspan->miny1 = my0; + if (my2 > zspan->maxy1) + zspan->maxy1 = my2; + } + else { + // printf("right span my0 %d my2 %d\n", my0, my2); + if (zspan->minp2 == NULL || zspan->minp2[1] > minv[1]) { + zspan->minp2 = minv; + } + if (zspan->maxp2 == NULL || zspan->maxp2[1] < maxv[1]) { + zspan->maxp2 = maxv; + } + if (my0 < zspan->miny2) + zspan->miny2 = my0; + if (my2 > zspan->maxy2) + zspan->maxy2 = my2; + } + + for (y = my2; y >= my0; y--, xs0 += dx0) { + /* xs0 is the xcoord! */ + span[y] = xs0; + } } /* ******************** VECBLUR ACCUM BUF ************************* */ typedef struct DrawBufPixel { - const float *colpoin; - float alpha; + const float *colpoin; + float alpha; } DrawBufPixel; - -static void zbuf_fill_in_rgba(ZSpan *zspan, DrawBufPixel *col, float *v1, float *v2, float *v3, float *v4) +static void zbuf_fill_in_rgba( + ZSpan *zspan, DrawBufPixel *col, float *v1, float *v2, float *v3, float *v4) { - DrawBufPixel *rectpofs, *rp; - double zxd, zyd, zy0, zverg; - float x0, y0, z0; - float x1, y1, z1, x2, y2, z2, xx1; - const float *span1, *span2; - float *rectzofs, *rz; - int x, y; - int sn1, sn2, rectx, my0, my2; - - /* init */ - zbuf_init_span(zspan); - - /* set spans */ - zbuf_add_to_span(zspan, v1, v2); - zbuf_add_to_span(zspan, v2, v3); - zbuf_add_to_span(zspan, v3, v4); - zbuf_add_to_span(zspan, v4, v1); - - /* clipped */ - if (zspan->minp2 == NULL || zspan->maxp2 == NULL) return; - - my0 = max_ii(zspan->miny1, zspan->miny2); - my2 = min_ii(zspan->maxy1, zspan->maxy2); - - // printf("my %d %d\n", my0, my2); - if (my2 < my0) return; - - /* ZBUF DX DY, in floats still */ - x1 = v1[0] - v2[0]; - x2 = v2[0] - v3[0]; - y1 = v1[1] - v2[1]; - y2 = v2[1] - v3[1]; - z1 = v1[2] - v2[2]; - z2 = v2[2] - v3[2]; - x0 = y1 * z2 - z1 * y2; - y0 = z1 * x2 - x1 * z2; - z0 = x1 * y2 - y1 * x2; - - if (z0 == 0.0f) return; - - xx1 = (x0 * v1[0] + y0 * v1[1]) / z0 + v1[2]; - - zxd = -(double)x0 / (double)z0; - zyd = -(double)y0 / (double)z0; - zy0 = ((double)my2) * zyd + (double)xx1; - - /* start-offset in rect */ - rectx = zspan->rectx; - rectzofs = (float *)(zspan->rectz + rectx * my2); - rectpofs = ((DrawBufPixel *)zspan->rectdraw) + rectx * my2; - - /* correct span */ - sn1 = (my0 + my2) / 2; - if (zspan->span1[sn1] < zspan->span2[sn1]) { - span1 = zspan->span1 + my2; - span2 = zspan->span2 + my2; - } - else { - span1 = zspan->span2 + my2; - span2 = zspan->span1 + my2; - } - - for (y = my2; y >= my0; y--, span1--, span2--) { - - sn1 = floor(*span1); - sn2 = floor(*span2); - sn1++; - - if (sn2 >= rectx) sn2 = rectx - 1; - if (sn1 < 0) sn1 = 0; - - if (sn2 >= sn1) { - zverg = (double)sn1 * zxd + zy0; - rz = rectzofs + sn1; - rp = rectpofs + sn1; - x = sn2 - sn1; - - while (x >= 0) { - if (zverg < (double)*rz) { - *rz = zverg; - *rp = *col; - } - zverg += zxd; - rz++; - rp++; - x--; - } - } - - zy0 -= zyd; - rectzofs -= rectx; - rectpofs -= rectx; - } + DrawBufPixel *rectpofs, *rp; + double zxd, zyd, zy0, zverg; + float x0, y0, z0; + float x1, y1, z1, x2, y2, z2, xx1; + const float *span1, *span2; + float *rectzofs, *rz; + int x, y; + int sn1, sn2, rectx, my0, my2; + + /* init */ + zbuf_init_span(zspan); + + /* set spans */ + zbuf_add_to_span(zspan, v1, v2); + zbuf_add_to_span(zspan, v2, v3); + zbuf_add_to_span(zspan, v3, v4); + zbuf_add_to_span(zspan, v4, v1); + + /* clipped */ + if (zspan->minp2 == NULL || zspan->maxp2 == NULL) + return; + + my0 = max_ii(zspan->miny1, zspan->miny2); + my2 = min_ii(zspan->maxy1, zspan->maxy2); + + // printf("my %d %d\n", my0, my2); + if (my2 < my0) + return; + + /* ZBUF DX DY, in floats still */ + x1 = v1[0] - v2[0]; + x2 = v2[0] - v3[0]; + y1 = v1[1] - v2[1]; + y2 = v2[1] - v3[1]; + z1 = v1[2] - v2[2]; + z2 = v2[2] - v3[2]; + x0 = y1 * z2 - z1 * y2; + y0 = z1 * x2 - x1 * z2; + z0 = x1 * y2 - y1 * x2; + + if (z0 == 0.0f) + return; + + xx1 = (x0 * v1[0] + y0 * v1[1]) / z0 + v1[2]; + + zxd = -(double)x0 / (double)z0; + zyd = -(double)y0 / (double)z0; + zy0 = ((double)my2) * zyd + (double)xx1; + + /* start-offset in rect */ + rectx = zspan->rectx; + rectzofs = (float *)(zspan->rectz + rectx * my2); + rectpofs = ((DrawBufPixel *)zspan->rectdraw) + rectx * my2; + + /* correct span */ + sn1 = (my0 + my2) / 2; + if (zspan->span1[sn1] < zspan->span2[sn1]) { + span1 = zspan->span1 + my2; + span2 = zspan->span2 + my2; + } + else { + span1 = zspan->span2 + my2; + span2 = zspan->span1 + my2; + } + + for (y = my2; y >= my0; y--, span1--, span2--) { + + sn1 = floor(*span1); + sn2 = floor(*span2); + sn1++; + + if (sn2 >= rectx) + sn2 = rectx - 1; + if (sn1 < 0) + sn1 = 0; + + if (sn2 >= sn1) { + zverg = (double)sn1 * zxd + zy0; + rz = rectzofs + sn1; + rp = rectpofs + sn1; + x = sn2 - sn1; + + while (x >= 0) { + if (zverg < (double)*rz) { + *rz = zverg; + *rp = *col; + } + zverg += zxd; + rz++; + rp++; + x--; + } + } + + zy0 -= zyd; + rectzofs -= rectx; + rectpofs -= rectx; + } } /* char value==255 is filled in, rest should be zero */ /* returns alpha values, but sets alpha to 1 for zero alpha pixels that have an alpha value as neighbor */ void antialias_tagbuf(int xsize, int ysize, char *rectmove) { - char *row1, *row2, *row3; - char prev, next; - int a, x, y, step; - - /* 1: tag pixels to be candidate for AA */ - for (y = 2; y < ysize; y++) { - /* setup rows */ - row1 = rectmove + (y - 2) * xsize; - row2 = row1 + xsize; - row3 = row2 + xsize; - for (x = 2; x < xsize; x++, row1++, row2++, row3++) { - if (row2[1]) { - if (row2[0] == 0 || row2[2] == 0 || row1[1] == 0 || row3[1] == 0) - row2[1] = 128; - } - } - } - - /* 2: evaluate horizontal scanlines and calculate alphas */ - row1 = rectmove; - for (y = 0; y < ysize; y++) { - row1++; - for (x = 1; x < xsize; x++, row1++) { - if (row1[0] == 128 && row1[1] == 128) { - /* find previous color and next color and amount of steps to blend */ - prev = row1[-1]; - step = 1; - while (x + step < xsize && row1[step] == 128) - step++; - - if (x + step != xsize) { - /* now we can blend values */ - next = row1[step]; - - /* note, prev value can be next value, but we do this loop to clear 128 then */ - for (a = 0; a < step; a++) { - int fac, mfac; - - fac = ((a + 1) << 8) / (step + 1); - mfac = 255 - fac; - - row1[a] = (prev * mfac + next * fac) >> 8; - } - } - } - } - } - - /* 3: evaluate vertical scanlines and calculate alphas */ - /* use for reading a copy of the original tagged buffer */ - for (x = 0; x < xsize; x++) { - row1 = rectmove + x + xsize; - - for (y = 1; y < ysize; y++, row1 += xsize) { - if (row1[0] == 128 && row1[xsize] == 128) { - /* find previous color and next color and amount of steps to blend */ - prev = row1[-xsize]; - step = 1; - while (y + step < ysize && row1[step * xsize] == 128) - step++; - - if (y + step != ysize) { - /* now we can blend values */ - next = row1[step * xsize]; - /* note, prev value can be next value, but we do this loop to clear 128 then */ - for (a = 0; a < step; a++) { - int fac, mfac; - - fac = ((a + 1) << 8) / (step + 1); - mfac = 255 - fac; - - row1[a * xsize] = (prev * mfac + next * fac) >> 8; - } - } - } - } - } - - /* last: pixels with 0 we fill in zbuffer, with 1 we skip for mask */ - for (y = 2; y < ysize; y++) { - /* setup rows */ - row1 = rectmove + (y - 2) * xsize; - row2 = row1 + xsize; - row3 = row2 + xsize; - for (x = 2; x < xsize; x++, row1++, row2++, row3++) { - if (row2[1] == 0) { - if (row2[0] > 1 || row2[2] > 1 || row1[1] > 1 || row3[1] > 1) - row2[1] = 1; - } - } - } + char *row1, *row2, *row3; + char prev, next; + int a, x, y, step; + + /* 1: tag pixels to be candidate for AA */ + for (y = 2; y < ysize; y++) { + /* setup rows */ + row1 = rectmove + (y - 2) * xsize; + row2 = row1 + xsize; + row3 = row2 + xsize; + for (x = 2; x < xsize; x++, row1++, row2++, row3++) { + if (row2[1]) { + if (row2[0] == 0 || row2[2] == 0 || row1[1] == 0 || row3[1] == 0) + row2[1] = 128; + } + } + } + + /* 2: evaluate horizontal scanlines and calculate alphas */ + row1 = rectmove; + for (y = 0; y < ysize; y++) { + row1++; + for (x = 1; x < xsize; x++, row1++) { + if (row1[0] == 128 && row1[1] == 128) { + /* find previous color and next color and amount of steps to blend */ + prev = row1[-1]; + step = 1; + while (x + step < xsize && row1[step] == 128) + step++; + + if (x + step != xsize) { + /* now we can blend values */ + next = row1[step]; + + /* note, prev value can be next value, but we do this loop to clear 128 then */ + for (a = 0; a < step; a++) { + int fac, mfac; + + fac = ((a + 1) << 8) / (step + 1); + mfac = 255 - fac; + + row1[a] = (prev * mfac + next * fac) >> 8; + } + } + } + } + } + + /* 3: evaluate vertical scanlines and calculate alphas */ + /* use for reading a copy of the original tagged buffer */ + for (x = 0; x < xsize; x++) { + row1 = rectmove + x + xsize; + + for (y = 1; y < ysize; y++, row1 += xsize) { + if (row1[0] == 128 && row1[xsize] == 128) { + /* find previous color and next color and amount of steps to blend */ + prev = row1[-xsize]; + step = 1; + while (y + step < ysize && row1[step * xsize] == 128) + step++; + + if (y + step != ysize) { + /* now we can blend values */ + next = row1[step * xsize]; + /* note, prev value can be next value, but we do this loop to clear 128 then */ + for (a = 0; a < step; a++) { + int fac, mfac; + + fac = ((a + 1) << 8) / (step + 1); + mfac = 255 - fac; + + row1[a * xsize] = (prev * mfac + next * fac) >> 8; + } + } + } + } + } + + /* last: pixels with 0 we fill in zbuffer, with 1 we skip for mask */ + for (y = 2; y < ysize; y++) { + /* setup rows */ + row1 = rectmove + (y - 2) * xsize; + row2 = row1 + xsize; + row3 = row2 + xsize; + for (x = 2; x < xsize; x++, row1++, row2++, row3++) { + if (row2[1] == 0) { + if (row2[0] > 1 || row2[2] > 1 || row1[1] > 1 || row3[1] > 1) + row2[1] = 1; + } + } + } } /* in: two vectors, first vector points from origin back in time, 2nd vector points to future */ @@ -467,347 +496,369 @@ void antialias_tagbuf(int xsize, int ysize, char *rectmove) static void quad_bezier_2d(float *result, float *v1, float *v2, float *ipodata) { - float p1[2], p2[2], p3[2]; + float p1[2], p2[2], p3[2]; - p3[0] = -v2[0]; - p3[1] = -v2[1]; + p3[0] = -v2[0]; + p3[1] = -v2[1]; - p1[0] = v1[0]; - p1[1] = v1[1]; + p1[0] = v1[0]; + p1[1] = v1[1]; - /* official formula 2*p2 - 0.5*p1 - 0.5*p3 */ - p2[0] = -0.5f * p1[0] - 0.5f * p3[0]; - p2[1] = -0.5f * p1[1] - 0.5f * p3[1]; + /* official formula 2*p2 - 0.5*p1 - 0.5*p3 */ + p2[0] = -0.5f * p1[0] - 0.5f * p3[0]; + p2[1] = -0.5f * p1[1] - 0.5f * p3[1]; - result[0] = ipodata[0] * p1[0] + ipodata[1] * p2[0] + ipodata[2] * p3[0]; - result[1] = ipodata[0] * p1[1] + ipodata[1] * p2[1] + ipodata[2] * p3[1]; + result[0] = ipodata[0] * p1[0] + ipodata[1] * p2[0] + ipodata[2] * p3[0]; + result[1] = ipodata[0] * p1[1] + ipodata[1] * p2[1] + ipodata[2] * p3[1]; } static void set_quad_bezier_ipo(float fac, float *data) { - float mfac = (1.0f - fac); + float mfac = (1.0f - fac); - data[0] = mfac * mfac; - data[1] = 2.0f * mfac * fac; - data[2] = fac * fac; + data[0] = mfac * mfac; + data[1] = 2.0f * mfac * fac; + data[2] = fac * fac; } -void zbuf_accumulate_vecblur( - NodeBlurData *nbd, int xsize, int ysize, float *newrect, - const float *imgrect, float *vecbufrect, const float *zbufrect) +void zbuf_accumulate_vecblur(NodeBlurData *nbd, + int xsize, + int ysize, + float *newrect, + const float *imgrect, + float *vecbufrect, + const float *zbufrect) { - ZSpan zspan; - DrawBufPixel *rectdraw, *dr; - static float jit[256][2]; - float v1[3], v2[3], v3[3], v4[3], fx, fy; - const float *dimg, *dz, *ro; - float *rectvz, *dvz, *dvec1, *dvec2, *dz1, *dz2, *rectz; - float *minvecbufrect = NULL, *rectweight, *rw, *rectmax, *rm; - float maxspeedsq = (float)nbd->maxspeed * nbd->maxspeed; - int y, x, step, maxspeed = nbd->maxspeed, samples = nbd->samples; - int tsktsk = 0; - static int firsttime = 1; - char *rectmove, *dm; - - zbuf_alloc_span(&zspan, xsize, ysize, 1.0f); - zspan.zmulx = ((float)xsize) / 2.0f; - zspan.zmuly = ((float)ysize) / 2.0f; - zspan.zofsx = 0.0f; - zspan.zofsy = 0.0f; - - /* the buffers */ - rectz = (float *)MEM_mapallocN(sizeof(float) * xsize * ysize, "zbuf accum"); - zspan.rectz = (int *)rectz; - - rectmove = (char *)MEM_mapallocN(xsize * ysize, "rectmove"); - rectdraw = (DrawBufPixel *)MEM_mapallocN(sizeof(DrawBufPixel) * xsize * ysize, "rect draw"); - zspan.rectdraw = rectdraw; - - rectweight = (float *)MEM_mapallocN(sizeof(float) * xsize * ysize, "rect weight"); - rectmax = (float *)MEM_mapallocN(sizeof(float) * xsize * ysize, "rect max"); - - /* debug... check if PASS_VECTOR_MAX still is in buffers */ - dvec1 = vecbufrect; - for (x = 4 * xsize * ysize; x > 0; x--, dvec1++) { - if (dvec1[0] == PASS_VECTOR_MAX) { - dvec1[0] = 0.0f; - tsktsk = 1; - } - } - if (tsktsk) printf("Found uninitialized speed in vector buffer... fixed.\n"); - - /* min speed? then copy speedbuffer to recalculate speed vectors */ - if (nbd->minspeed) { - float minspeed = (float)nbd->minspeed; - float minspeedsq = minspeed * minspeed; - - minvecbufrect = (float *)MEM_mapallocN(4 * sizeof(float) * xsize * ysize, "minspeed buf"); - - dvec1 = vecbufrect; - dvec2 = minvecbufrect; - for (x = 2 * xsize * ysize; x > 0; x--, dvec1 += 2, dvec2 += 2) { - if (dvec1[0] == 0.0f && dvec1[1] == 0.0f) { - dvec2[0] = dvec1[0]; - dvec2[1] = dvec1[1]; - } - else { - float speedsq = dvec1[0] * dvec1[0] + dvec1[1] * dvec1[1]; - if (speedsq <= minspeedsq) { - dvec2[0] = 0.0f; - dvec2[1] = 0.0f; - } - else { - speedsq = 1.0f - minspeed / sqrtf(speedsq); - dvec2[0] = speedsq * dvec1[0]; - dvec2[1] = speedsq * dvec1[1]; - } - } - } - SWAP(float *, minvecbufrect, vecbufrect); - } - - /* make vertex buffer with averaged speed and zvalues */ - rectvz = (float *)MEM_mapallocN(4 * sizeof(float) * (xsize + 1) * (ysize + 1), "vertices"); - dvz = rectvz; - for (y = 0; y <= ysize; y++) { - - if (y == 0) - dvec1 = vecbufrect + 4 * y * xsize; - else - dvec1 = vecbufrect + 4 * (y - 1) * xsize; - - if (y == ysize) - dvec2 = vecbufrect + 4 * (y - 1) * xsize; - else - dvec2 = vecbufrect + 4 * y * xsize; - - for (x = 0; x <= xsize; x++) { - - /* two vectors, so a step loop */ - for (step = 0; step < 2; step++, dvec1 += 2, dvec2 += 2, dvz += 2) { - /* average on minimal speed */ - int div = 0; - - if (x != 0) { - if (dvec1[-4] != 0.0f || dvec1[-3] != 0.0f) { - dvz[0] = dvec1[-4]; - dvz[1] = dvec1[-3]; - div++; - } - if (dvec2[-4] != 0.0f || dvec2[-3] != 0.0f) { - if (div == 0) { - dvz[0] = dvec2[-4]; - dvz[1] = dvec2[-3]; - div++; - } - else if ( (ABS(dvec2[-4]) + ABS(dvec2[-3])) < (ABS(dvz[0]) + ABS(dvz[1])) ) { - dvz[0] = dvec2[-4]; - dvz[1] = dvec2[-3]; - } - } - } - - if (x != xsize) { - if (dvec1[0] != 0.0f || dvec1[1] != 0.0f) { - if (div == 0) { - dvz[0] = dvec1[0]; - dvz[1] = dvec1[1]; - div++; - } - else if ( (ABS(dvec1[0]) + ABS(dvec1[1])) < (ABS(dvz[0]) + ABS(dvz[1])) ) { - dvz[0] = dvec1[0]; - dvz[1] = dvec1[1]; - } - } - if (dvec2[0] != 0.0f || dvec2[1] != 0.0f) { - if (div == 0) { - dvz[0] = dvec2[0]; - dvz[1] = dvec2[1]; - } - else if ( (ABS(dvec2[0]) + ABS(dvec2[1])) < (ABS(dvz[0]) + ABS(dvz[1])) ) { - dvz[0] = dvec2[0]; - dvz[1] = dvec2[1]; - } - } - } - if (maxspeed) { - float speedsq = dvz[0] * dvz[0] + dvz[1] * dvz[1]; - if (speedsq > maxspeedsq) { - speedsq = (float)maxspeed / sqrtf(speedsq); - dvz[0] *= speedsq; - dvz[1] *= speedsq; - } - } - } - } - } - - /* set border speeds to keep border speeds on border */ - dz1 = rectvz; - dz2 = rectvz + 4 * (ysize) * (xsize + 1); - for (x = 0; x <= xsize; x++, dz1 += 4, dz2 += 4) { - dz1[1] = 0.0f; - dz2[1] = 0.0f; - dz1[3] = 0.0f; - dz2[3] = 0.0f; - } - dz1 = rectvz; - dz2 = rectvz + 4 * (xsize); - for (y = 0; y <= ysize; y++, dz1 += 4 * (xsize + 1), dz2 += 4 * (xsize + 1)) { - dz1[0] = 0.0f; - dz2[0] = 0.0f; - dz1[2] = 0.0f; - dz2[2] = 0.0f; - } - - /* tag moving pixels, only these faces we draw */ - dm = rectmove; - dvec1 = vecbufrect; - for (x = xsize * ysize; x > 0; x--, dm++, dvec1 += 4) { - if ((dvec1[0] != 0.0f || dvec1[1] != 0.0f || dvec1[2] != 0.0f || dvec1[3] != 0.0f)) - *dm = 255; - } - - antialias_tagbuf(xsize, ysize, rectmove); - - /* has to become static, the init-jit calls a random-seed, screwing up texture noise node */ - if (firsttime) { - firsttime = 0; - BLI_jitter_init(jit, 256); - } - - memset(newrect, 0, sizeof(float) * xsize * ysize * 4); - - /* accumulate */ - samples /= 2; - for (step = 1; step <= samples; step++) { - float speedfac = 0.5f * nbd->fac * (float)step / (float)(samples + 1); - int side; - - for (side = 0; side < 2; side++) { - float blendfac, ipodata[4]; - - /* clear zbuf, if we draw future we fill in not moving pixels */ - if (0) - for (x = xsize * ysize - 1; x >= 0; x--) rectz[x] = 10e16; - else - for (x = xsize * ysize - 1; x >= 0; x--) { - if (rectmove[x] == 0) - rectz[x] = zbufrect[x]; - else - rectz[x] = 10e16; - } - - /* clear drawing buffer */ - for (x = xsize * ysize - 1; x >= 0; x--) rectdraw[x].colpoin = NULL; - - dimg = imgrect; - dm = rectmove; - dz = zbufrect; - dz1 = rectvz; - dz2 = rectvz + 4 * (xsize + 1); - - if (side) { - if (nbd->curved == 0) { - dz1 += 2; - dz2 += 2; - } - speedfac = -speedfac; - } - - set_quad_bezier_ipo(0.5f + 0.5f * speedfac, ipodata); - - for (fy = -0.5f + jit[step & 255][0], y = 0; y < ysize; y++, fy += 1.0f) { - for (fx = -0.5f + jit[step & 255][1], x = 0; x < xsize; x++, fx += 1.0f, dimg += 4, dz1 += 4, dz2 += 4, dm++, dz++) { - if (*dm > 1) { - float jfx = fx + 0.5f; - float jfy = fy + 0.5f; - DrawBufPixel col; - - /* make vertices */ - if (nbd->curved) { /* curved */ - quad_bezier_2d(v1, dz1, dz1 + 2, ipodata); - v1[0] += jfx; v1[1] += jfy; v1[2] = *dz; - - quad_bezier_2d(v2, dz1 + 4, dz1 + 4 + 2, ipodata); - v2[0] += jfx + 1.0f; v2[1] += jfy; v2[2] = *dz; - - quad_bezier_2d(v3, dz2 + 4, dz2 + 4 + 2, ipodata); - v3[0] += jfx + 1.0f; v3[1] += jfy + 1.0f; v3[2] = *dz; - - quad_bezier_2d(v4, dz2, dz2 + 2, ipodata); - v4[0] += jfx; v4[1] += jfy + 1.0f; v4[2] = *dz; - } - else { - ARRAY_SET_ITEMS(v1, speedfac * dz1[0] + jfx, speedfac * dz1[1] + jfy, *dz); - ARRAY_SET_ITEMS(v2, speedfac * dz1[4] + jfx + 1.0f, speedfac * dz1[5] + jfy, *dz); - ARRAY_SET_ITEMS(v3, speedfac * dz2[4] + jfx + 1.0f, speedfac * dz2[5] + jfy + 1.0f, *dz); - ARRAY_SET_ITEMS(v4, speedfac * dz2[0] + jfx, speedfac * dz2[1] + jfy + 1.0f, *dz); - } - if (*dm == 255) col.alpha = 1.0f; - else if (*dm < 2) col.alpha = 0.0f; - else col.alpha = ((float)*dm) / 255.0f; - col.colpoin = dimg; - - zbuf_fill_in_rgba(&zspan, &col, v1, v2, v3, v4); - } - } - dz1 += 4; - dz2 += 4; - } - - /* blend with a falloff. this fixes the ugly effect you get with - * a fast moving object. then it looks like a solid object overlaid - * over a very transparent moving version of itself. in reality, the - * whole object should become transparent if it is moving fast, be - * we don't know what is behind it so we don't do that. this hack - * overestimates the contribution of foreground pixels but looks a - * bit better without a sudden cutoff. */ - blendfac = ((samples - step) / (float)samples); - /* smoothstep to make it look a bit nicer as well */ - blendfac = 3.0f * pow(blendfac, 2.0f) - 2.0f * pow(blendfac, 3.0f); - - /* accum */ - rw = rectweight; - rm = rectmax; - for (dr = rectdraw, dz2 = newrect, x = xsize * ysize - 1; x >= 0; x--, dr++, dz2 += 4, rw++, rm++) { - if (dr->colpoin) { - float bfac = dr->alpha * blendfac; - - dz2[0] += bfac * dr->colpoin[0]; - dz2[1] += bfac * dr->colpoin[1]; - dz2[2] += bfac * dr->colpoin[2]; - dz2[3] += bfac * dr->colpoin[3]; - - *rw += bfac; - *rm = MAX2(*rm, bfac); - } - } - } - } - - /* blend between original images and accumulated image */ - rw = rectweight; - rm = rectmax; - ro = imgrect; - dm = rectmove; - for (dz2 = newrect, x = xsize * ysize - 1; x >= 0; x--, dz2 += 4, ro += 4, rw++, rm++, dm++) { - float mfac = *rm; - float fac = (*rw == 0.0f) ? 0.0f : mfac / (*rw); - float nfac = 1.0f - mfac; - - dz2[0] = fac * dz2[0] + nfac * ro[0]; - dz2[1] = fac * dz2[1] + nfac * ro[1]; - dz2[2] = fac * dz2[2] + nfac * ro[2]; - dz2[3] = fac * dz2[3] + nfac * ro[3]; - } - - MEM_freeN(rectz); - MEM_freeN(rectmove); - MEM_freeN(rectdraw); - MEM_freeN(rectvz); - MEM_freeN(rectweight); - MEM_freeN(rectmax); - if (minvecbufrect) MEM_freeN(vecbufrect); /* rects were swapped! */ - zbuf_free_span(&zspan); + ZSpan zspan; + DrawBufPixel *rectdraw, *dr; + static float jit[256][2]; + float v1[3], v2[3], v3[3], v4[3], fx, fy; + const float *dimg, *dz, *ro; + float *rectvz, *dvz, *dvec1, *dvec2, *dz1, *dz2, *rectz; + float *minvecbufrect = NULL, *rectweight, *rw, *rectmax, *rm; + float maxspeedsq = (float)nbd->maxspeed * nbd->maxspeed; + int y, x, step, maxspeed = nbd->maxspeed, samples = nbd->samples; + int tsktsk = 0; + static int firsttime = 1; + char *rectmove, *dm; + + zbuf_alloc_span(&zspan, xsize, ysize, 1.0f); + zspan.zmulx = ((float)xsize) / 2.0f; + zspan.zmuly = ((float)ysize) / 2.0f; + zspan.zofsx = 0.0f; + zspan.zofsy = 0.0f; + + /* the buffers */ + rectz = (float *)MEM_mapallocN(sizeof(float) * xsize * ysize, "zbuf accum"); + zspan.rectz = (int *)rectz; + + rectmove = (char *)MEM_mapallocN(xsize * ysize, "rectmove"); + rectdraw = (DrawBufPixel *)MEM_mapallocN(sizeof(DrawBufPixel) * xsize * ysize, "rect draw"); + zspan.rectdraw = rectdraw; + + rectweight = (float *)MEM_mapallocN(sizeof(float) * xsize * ysize, "rect weight"); + rectmax = (float *)MEM_mapallocN(sizeof(float) * xsize * ysize, "rect max"); + + /* debug... check if PASS_VECTOR_MAX still is in buffers */ + dvec1 = vecbufrect; + for (x = 4 * xsize * ysize; x > 0; x--, dvec1++) { + if (dvec1[0] == PASS_VECTOR_MAX) { + dvec1[0] = 0.0f; + tsktsk = 1; + } + } + if (tsktsk) + printf("Found uninitialized speed in vector buffer... fixed.\n"); + + /* min speed? then copy speedbuffer to recalculate speed vectors */ + if (nbd->minspeed) { + float minspeed = (float)nbd->minspeed; + float minspeedsq = minspeed * minspeed; + + minvecbufrect = (float *)MEM_mapallocN(4 * sizeof(float) * xsize * ysize, "minspeed buf"); + + dvec1 = vecbufrect; + dvec2 = minvecbufrect; + for (x = 2 * xsize * ysize; x > 0; x--, dvec1 += 2, dvec2 += 2) { + if (dvec1[0] == 0.0f && dvec1[1] == 0.0f) { + dvec2[0] = dvec1[0]; + dvec2[1] = dvec1[1]; + } + else { + float speedsq = dvec1[0] * dvec1[0] + dvec1[1] * dvec1[1]; + if (speedsq <= minspeedsq) { + dvec2[0] = 0.0f; + dvec2[1] = 0.0f; + } + else { + speedsq = 1.0f - minspeed / sqrtf(speedsq); + dvec2[0] = speedsq * dvec1[0]; + dvec2[1] = speedsq * dvec1[1]; + } + } + } + SWAP(float *, minvecbufrect, vecbufrect); + } + + /* make vertex buffer with averaged speed and zvalues */ + rectvz = (float *)MEM_mapallocN(4 * sizeof(float) * (xsize + 1) * (ysize + 1), "vertices"); + dvz = rectvz; + for (y = 0; y <= ysize; y++) { + + if (y == 0) + dvec1 = vecbufrect + 4 * y * xsize; + else + dvec1 = vecbufrect + 4 * (y - 1) * xsize; + + if (y == ysize) + dvec2 = vecbufrect + 4 * (y - 1) * xsize; + else + dvec2 = vecbufrect + 4 * y * xsize; + + for (x = 0; x <= xsize; x++) { + + /* two vectors, so a step loop */ + for (step = 0; step < 2; step++, dvec1 += 2, dvec2 += 2, dvz += 2) { + /* average on minimal speed */ + int div = 0; + + if (x != 0) { + if (dvec1[-4] != 0.0f || dvec1[-3] != 0.0f) { + dvz[0] = dvec1[-4]; + dvz[1] = dvec1[-3]; + div++; + } + if (dvec2[-4] != 0.0f || dvec2[-3] != 0.0f) { + if (div == 0) { + dvz[0] = dvec2[-4]; + dvz[1] = dvec2[-3]; + div++; + } + else if ((ABS(dvec2[-4]) + ABS(dvec2[-3])) < (ABS(dvz[0]) + ABS(dvz[1]))) { + dvz[0] = dvec2[-4]; + dvz[1] = dvec2[-3]; + } + } + } + + if (x != xsize) { + if (dvec1[0] != 0.0f || dvec1[1] != 0.0f) { + if (div == 0) { + dvz[0] = dvec1[0]; + dvz[1] = dvec1[1]; + div++; + } + else if ((ABS(dvec1[0]) + ABS(dvec1[1])) < (ABS(dvz[0]) + ABS(dvz[1]))) { + dvz[0] = dvec1[0]; + dvz[1] = dvec1[1]; + } + } + if (dvec2[0] != 0.0f || dvec2[1] != 0.0f) { + if (div == 0) { + dvz[0] = dvec2[0]; + dvz[1] = dvec2[1]; + } + else if ((ABS(dvec2[0]) + ABS(dvec2[1])) < (ABS(dvz[0]) + ABS(dvz[1]))) { + dvz[0] = dvec2[0]; + dvz[1] = dvec2[1]; + } + } + } + if (maxspeed) { + float speedsq = dvz[0] * dvz[0] + dvz[1] * dvz[1]; + if (speedsq > maxspeedsq) { + speedsq = (float)maxspeed / sqrtf(speedsq); + dvz[0] *= speedsq; + dvz[1] *= speedsq; + } + } + } + } + } + + /* set border speeds to keep border speeds on border */ + dz1 = rectvz; + dz2 = rectvz + 4 * (ysize) * (xsize + 1); + for (x = 0; x <= xsize; x++, dz1 += 4, dz2 += 4) { + dz1[1] = 0.0f; + dz2[1] = 0.0f; + dz1[3] = 0.0f; + dz2[3] = 0.0f; + } + dz1 = rectvz; + dz2 = rectvz + 4 * (xsize); + for (y = 0; y <= ysize; y++, dz1 += 4 * (xsize + 1), dz2 += 4 * (xsize + 1)) { + dz1[0] = 0.0f; + dz2[0] = 0.0f; + dz1[2] = 0.0f; + dz2[2] = 0.0f; + } + + /* tag moving pixels, only these faces we draw */ + dm = rectmove; + dvec1 = vecbufrect; + for (x = xsize * ysize; x > 0; x--, dm++, dvec1 += 4) { + if ((dvec1[0] != 0.0f || dvec1[1] != 0.0f || dvec1[2] != 0.0f || dvec1[3] != 0.0f)) + *dm = 255; + } + + antialias_tagbuf(xsize, ysize, rectmove); + + /* has to become static, the init-jit calls a random-seed, screwing up texture noise node */ + if (firsttime) { + firsttime = 0; + BLI_jitter_init(jit, 256); + } + + memset(newrect, 0, sizeof(float) * xsize * ysize * 4); + + /* accumulate */ + samples /= 2; + for (step = 1; step <= samples; step++) { + float speedfac = 0.5f * nbd->fac * (float)step / (float)(samples + 1); + int side; + + for (side = 0; side < 2; side++) { + float blendfac, ipodata[4]; + + /* clear zbuf, if we draw future we fill in not moving pixels */ + if (0) + for (x = xsize * ysize - 1; x >= 0; x--) + rectz[x] = 10e16; + else + for (x = xsize * ysize - 1; x >= 0; x--) { + if (rectmove[x] == 0) + rectz[x] = zbufrect[x]; + else + rectz[x] = 10e16; + } + + /* clear drawing buffer */ + for (x = xsize * ysize - 1; x >= 0; x--) + rectdraw[x].colpoin = NULL; + + dimg = imgrect; + dm = rectmove; + dz = zbufrect; + dz1 = rectvz; + dz2 = rectvz + 4 * (xsize + 1); + + if (side) { + if (nbd->curved == 0) { + dz1 += 2; + dz2 += 2; + } + speedfac = -speedfac; + } + + set_quad_bezier_ipo(0.5f + 0.5f * speedfac, ipodata); + + for (fy = -0.5f + jit[step & 255][0], y = 0; y < ysize; y++, fy += 1.0f) { + for (fx = -0.5f + jit[step & 255][1], x = 0; x < xsize; + x++, fx += 1.0f, dimg += 4, dz1 += 4, dz2 += 4, dm++, dz++) { + if (*dm > 1) { + float jfx = fx + 0.5f; + float jfy = fy + 0.5f; + DrawBufPixel col; + + /* make vertices */ + if (nbd->curved) { /* curved */ + quad_bezier_2d(v1, dz1, dz1 + 2, ipodata); + v1[0] += jfx; + v1[1] += jfy; + v1[2] = *dz; + + quad_bezier_2d(v2, dz1 + 4, dz1 + 4 + 2, ipodata); + v2[0] += jfx + 1.0f; + v2[1] += jfy; + v2[2] = *dz; + + quad_bezier_2d(v3, dz2 + 4, dz2 + 4 + 2, ipodata); + v3[0] += jfx + 1.0f; + v3[1] += jfy + 1.0f; + v3[2] = *dz; + + quad_bezier_2d(v4, dz2, dz2 + 2, ipodata); + v4[0] += jfx; + v4[1] += jfy + 1.0f; + v4[2] = *dz; + } + else { + ARRAY_SET_ITEMS(v1, speedfac * dz1[0] + jfx, speedfac * dz1[1] + jfy, *dz); + ARRAY_SET_ITEMS(v2, speedfac * dz1[4] + jfx + 1.0f, speedfac * dz1[5] + jfy, *dz); + ARRAY_SET_ITEMS( + v3, speedfac * dz2[4] + jfx + 1.0f, speedfac * dz2[5] + jfy + 1.0f, *dz); + ARRAY_SET_ITEMS(v4, speedfac * dz2[0] + jfx, speedfac * dz2[1] + jfy + 1.0f, *dz); + } + if (*dm == 255) + col.alpha = 1.0f; + else if (*dm < 2) + col.alpha = 0.0f; + else + col.alpha = ((float)*dm) / 255.0f; + col.colpoin = dimg; + + zbuf_fill_in_rgba(&zspan, &col, v1, v2, v3, v4); + } + } + dz1 += 4; + dz2 += 4; + } + + /* blend with a falloff. this fixes the ugly effect you get with + * a fast moving object. then it looks like a solid object overlaid + * over a very transparent moving version of itself. in reality, the + * whole object should become transparent if it is moving fast, be + * we don't know what is behind it so we don't do that. this hack + * overestimates the contribution of foreground pixels but looks a + * bit better without a sudden cutoff. */ + blendfac = ((samples - step) / (float)samples); + /* smoothstep to make it look a bit nicer as well */ + blendfac = 3.0f * pow(blendfac, 2.0f) - 2.0f * pow(blendfac, 3.0f); + + /* accum */ + rw = rectweight; + rm = rectmax; + for (dr = rectdraw, dz2 = newrect, x = xsize * ysize - 1; x >= 0; + x--, dr++, dz2 += 4, rw++, rm++) { + if (dr->colpoin) { + float bfac = dr->alpha * blendfac; + + dz2[0] += bfac * dr->colpoin[0]; + dz2[1] += bfac * dr->colpoin[1]; + dz2[2] += bfac * dr->colpoin[2]; + dz2[3] += bfac * dr->colpoin[3]; + + *rw += bfac; + *rm = MAX2(*rm, bfac); + } + } + } + } + + /* blend between original images and accumulated image */ + rw = rectweight; + rm = rectmax; + ro = imgrect; + dm = rectmove; + for (dz2 = newrect, x = xsize * ysize - 1; x >= 0; x--, dz2 += 4, ro += 4, rw++, rm++, dm++) { + float mfac = *rm; + float fac = (*rw == 0.0f) ? 0.0f : mfac / (*rw); + float nfac = 1.0f - mfac; + + dz2[0] = fac * dz2[0] + nfac * ro[0]; + dz2[1] = fac * dz2[1] + nfac * ro[1]; + dz2[2] = fac * dz2[2] + nfac * ro[2]; + dz2[3] = fac * dz2[3] + nfac * ro[3]; + } + + MEM_freeN(rectz); + MEM_freeN(rectmove); + MEM_freeN(rectdraw); + MEM_freeN(rectvz); + MEM_freeN(rectweight); + MEM_freeN(rectmax); + if (minvecbufrect) + MEM_freeN(vecbufrect); /* rects were swapped! */ + zbuf_free_span(&zspan); } diff --git a/source/blender/compositor/operations/COM_VectorBlurOperation.h b/source/blender/compositor/operations/COM_VectorBlurOperation.h index acb08890e91..aedc0d85a50 100644 --- a/source/blender/compositor/operations/COM_VectorBlurOperation.h +++ b/source/blender/compositor/operations/COM_VectorBlurOperation.h @@ -23,47 +23,53 @@ #include "COM_QualityStepHelper.h" class VectorBlurOperation : public NodeOperation, public QualityStepHelper { -private: - /** - * \brief Cached reference to the inputProgram - */ - SocketReader *m_inputImageProgram; - SocketReader *m_inputSpeedProgram; - SocketReader *m_inputZProgram; + private: + /** + * \brief Cached reference to the inputProgram + */ + SocketReader *m_inputImageProgram; + SocketReader *m_inputSpeedProgram; + SocketReader *m_inputZProgram; - /** - * \brief settings of the glare node. - */ - NodeBlurData *m_settings; + /** + * \brief settings of the glare node. + */ + NodeBlurData *m_settings; - float *m_cachedInstance; + float *m_cachedInstance; -public: - VectorBlurOperation(); + public: + VectorBlurOperation(); - /** - * the inner loop of this program - */ - void executePixel(float output[4], int x, int y, void *data); + /** + * the inner loop of this program + */ + void executePixel(float output[4], int x, int y, void *data); - /** - * Initialize the execution - */ - void initExecution(); + /** + * Initialize the execution + */ + void initExecution(); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Deinitialize the execution + */ + void deinitExecution(); - void *initializeTileData(rcti *rect); - - void setVectorBlurSettings(NodeBlurData *settings) { this->m_settings = settings; } - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); -protected: - - void generateVectorBlur(float *data, MemoryBuffer *inputImage, MemoryBuffer *inputSpeed, MemoryBuffer *inputZ); + void *initializeTileData(rcti *rect); + void setVectorBlurSettings(NodeBlurData *settings) + { + this->m_settings = settings; + } + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + protected: + void generateVectorBlur(float *data, + MemoryBuffer *inputImage, + MemoryBuffer *inputSpeed, + MemoryBuffer *inputZ); }; #endif diff --git a/source/blender/compositor/operations/COM_VectorCurveOperation.cpp b/source/blender/compositor/operations/COM_VectorCurveOperation.cpp index 2381656a289..850aef122f4 100644 --- a/source/blender/compositor/operations/COM_VectorCurveOperation.cpp +++ b/source/blender/compositor/operations/COM_VectorCurveOperation.cpp @@ -21,36 +21,38 @@ #ifdef __cplusplus extern "C" { #endif -# include "BKE_colortools.h" +#include "BKE_colortools.h" #ifdef __cplusplus } #endif VectorCurveOperation::VectorCurveOperation() : CurveBaseOperation() { - this->addInputSocket(COM_DT_VECTOR); - this->addOutputSocket(COM_DT_VECTOR); + this->addInputSocket(COM_DT_VECTOR); + this->addOutputSocket(COM_DT_VECTOR); - this->m_inputProgram = NULL; + this->m_inputProgram = NULL; } void VectorCurveOperation::initExecution() { - CurveBaseOperation::initExecution(); - this->m_inputProgram = this->getInputSocketReader(0); + CurveBaseOperation::initExecution(); + this->m_inputProgram = this->getInputSocketReader(0); } -void VectorCurveOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void VectorCurveOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float input[4]; + float input[4]; + this->m_inputProgram->readSampled(input, x, y, sampler); - this->m_inputProgram->readSampled(input, x, y, sampler); - - curvemapping_evaluate_premulRGBF(this->m_curveMapping, output, input); + curvemapping_evaluate_premulRGBF(this->m_curveMapping, output, input); } void VectorCurveOperation::deinitExecution() { - CurveBaseOperation::deinitExecution(); - this->m_inputProgram = NULL; + CurveBaseOperation::deinitExecution(); + this->m_inputProgram = NULL; } diff --git a/source/blender/compositor/operations/COM_VectorCurveOperation.h b/source/blender/compositor/operations/COM_VectorCurveOperation.h index 5b704d3504f..c8575de6aa8 100644 --- a/source/blender/compositor/operations/COM_VectorCurveOperation.h +++ b/source/blender/compositor/operations/COM_VectorCurveOperation.h @@ -22,27 +22,28 @@ #include "COM_CurveBaseOperation.h" class VectorCurveOperation : public CurveBaseOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputProgram; -public: - VectorCurveOperation(); + private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputProgram; - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + public: + VectorCurveOperation(); - /** - * Initialize the execution - */ - void initExecution(); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - /** - * Deinitialize the execution - */ - void deinitExecution(); + /** + * Initialize the execution + */ + void initExecution(); + + /** + * Deinitialize the execution + */ + void deinitExecution(); }; #endif diff --git a/source/blender/compositor/operations/COM_ViewerOperation.cpp b/source/blender/compositor/operations/COM_ViewerOperation.cpp index 0f6512de61d..fcf6a2a731d 100644 --- a/source/blender/compositor/operations/COM_ViewerOperation.cpp +++ b/source/blender/compositor/operations/COM_ViewerOperation.cpp @@ -28,168 +28,178 @@ #include "BLI_math_vector.h" extern "C" { -# include "MEM_guardedalloc.h" -# include "IMB_imbuf.h" -# include "IMB_imbuf_types.h" -# include "IMB_colormanagement.h" +#include "MEM_guardedalloc.h" +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" +#include "IMB_colormanagement.h" } - ViewerOperation::ViewerOperation() : NodeOperation() { - this->setImage(NULL); - this->setImageUser(NULL); - this->m_outputBuffer = NULL; - this->m_depthBuffer = NULL; - this->m_active = false; - this->m_doDepthBuffer = false; - this->m_viewSettings = NULL; - this->m_displaySettings = NULL; - this->m_useAlphaInput = false; - - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_VALUE); - - this->m_imageInput = NULL; - this->m_alphaInput = NULL; - this->m_depthInput = NULL; - this->m_rd = NULL; - this->m_viewName = NULL; + this->setImage(NULL); + this->setImageUser(NULL); + this->m_outputBuffer = NULL; + this->m_depthBuffer = NULL; + this->m_active = false; + this->m_doDepthBuffer = false; + this->m_viewSettings = NULL; + this->m_displaySettings = NULL; + this->m_useAlphaInput = false; + + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + + this->m_imageInput = NULL; + this->m_alphaInput = NULL; + this->m_depthInput = NULL; + this->m_rd = NULL; + this->m_viewName = NULL; } void ViewerOperation::initExecution() { - // When initializing the tree during initial load the width and height can be zero. - this->m_imageInput = getInputSocketReader(0); - this->m_alphaInput = getInputSocketReader(1); - this->m_depthInput = getInputSocketReader(2); - this->m_doDepthBuffer = (this->m_depthInput != NULL); - - if (isActiveViewerOutput()) { - initImage(); - } + // When initializing the tree during initial load the width and height can be zero. + this->m_imageInput = getInputSocketReader(0); + this->m_alphaInput = getInputSocketReader(1); + this->m_depthInput = getInputSocketReader(2); + this->m_doDepthBuffer = (this->m_depthInput != NULL); + + if (isActiveViewerOutput()) { + initImage(); + } } void ViewerOperation::deinitExecution() { - this->m_imageInput = NULL; - this->m_alphaInput = NULL; - this->m_depthInput = NULL; - this->m_outputBuffer = NULL; + this->m_imageInput = NULL; + this->m_alphaInput = NULL; + this->m_depthInput = NULL; + this->m_outputBuffer = NULL; } void ViewerOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/) { - float *buffer = this->m_outputBuffer; - float *depthbuffer = this->m_depthBuffer; - if (!buffer) return; - const int x1 = rect->xmin; - const int y1 = rect->ymin; - const int x2 = rect->xmax; - const int y2 = rect->ymax; - const int offsetadd = (this->getWidth() - (x2 - x1)); - const int offsetadd4 = offsetadd * 4; - int offset = (y1 * this->getWidth() + x1); - int offset4 = offset * 4; - float alpha[4], depth[4]; - int x; - int y; - bool breaked = false; - - for (y = y1; y < y2 && (!breaked); y++) { - for (x = x1; x < x2; x++) { - this->m_imageInput->readSampled(&(buffer[offset4]), x, y, COM_PS_NEAREST); - if (this->m_useAlphaInput) { - this->m_alphaInput->readSampled(alpha, x, y, COM_PS_NEAREST); - buffer[offset4 + 3] = alpha[0]; - } - this->m_depthInput->readSampled(depth, x, y, COM_PS_NEAREST); - depthbuffer[offset] = depth[0]; - - offset ++; - offset4 += 4; - } - if (isBreaked()) { - breaked = true; - } - offset += offsetadd; - offset4 += offsetadd4; - } - updateImage(rect); + float *buffer = this->m_outputBuffer; + float *depthbuffer = this->m_depthBuffer; + if (!buffer) + return; + const int x1 = rect->xmin; + const int y1 = rect->ymin; + const int x2 = rect->xmax; + const int y2 = rect->ymax; + const int offsetadd = (this->getWidth() - (x2 - x1)); + const int offsetadd4 = offsetadd * 4; + int offset = (y1 * this->getWidth() + x1); + int offset4 = offset * 4; + float alpha[4], depth[4]; + int x; + int y; + bool breaked = false; + + for (y = y1; y < y2 && (!breaked); y++) { + for (x = x1; x < x2; x++) { + this->m_imageInput->readSampled(&(buffer[offset4]), x, y, COM_PS_NEAREST); + if (this->m_useAlphaInput) { + this->m_alphaInput->readSampled(alpha, x, y, COM_PS_NEAREST); + buffer[offset4 + 3] = alpha[0]; + } + this->m_depthInput->readSampled(depth, x, y, COM_PS_NEAREST); + depthbuffer[offset] = depth[0]; + + offset++; + offset4 += 4; + } + if (isBreaked()) { + breaked = true; + } + offset += offsetadd; + offset4 += offsetadd4; + } + updateImage(rect); } void ViewerOperation::initImage() { - Image *ima = this->m_image; - ImageUser iuser = *this->m_imageUser; - void *lock; - ImBuf *ibuf; - - /* make sure the image has the correct number of views */ - if (ima && BKE_scene_multiview_is_render_view_first(this->m_rd, this->m_viewName)) { - BKE_image_verify_viewer_views(this->m_rd, ima, this->m_imageUser); - } - - BLI_thread_lock(LOCK_DRAW_IMAGE); - - /* local changes to the original ImageUser */ - iuser.multi_index = BKE_scene_multiview_view_id_get(this->m_rd, this->m_viewName); - ibuf = BKE_image_acquire_ibuf(ima, &iuser, &lock); - - if (!ibuf) { - BLI_thread_unlock(LOCK_DRAW_IMAGE); - return; - } - if (ibuf->x != (int)getWidth() || ibuf->y != (int)getHeight()) { - - imb_freerectImBuf(ibuf); - imb_freerectfloatImBuf(ibuf); - IMB_freezbuffloatImBuf(ibuf); - ibuf->x = getWidth(); - ibuf->y = getHeight(); - /* zero size can happen if no image buffers exist to define a sensible resolution */ - if (ibuf->x > 0 && ibuf->y > 0) - imb_addrectfloatImBuf(ibuf); - ima->ok = IMA_OK_LOADED; - - ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; - } - - if (m_doDepthBuffer) { - addzbuffloatImBuf(ibuf); - } - - /* now we combine the input with ibuf */ - this->m_outputBuffer = ibuf->rect_float; - - /* needed for display buffer update */ - this->m_ibuf = ibuf; - - if (m_doDepthBuffer) { - this->m_depthBuffer = ibuf->zbuf_float; - } - - BKE_image_release_ibuf(this->m_image, this->m_ibuf, lock); - - BLI_thread_unlock(LOCK_DRAW_IMAGE); + Image *ima = this->m_image; + ImageUser iuser = *this->m_imageUser; + void *lock; + ImBuf *ibuf; + + /* make sure the image has the correct number of views */ + if (ima && BKE_scene_multiview_is_render_view_first(this->m_rd, this->m_viewName)) { + BKE_image_verify_viewer_views(this->m_rd, ima, this->m_imageUser); + } + + BLI_thread_lock(LOCK_DRAW_IMAGE); + + /* local changes to the original ImageUser */ + iuser.multi_index = BKE_scene_multiview_view_id_get(this->m_rd, this->m_viewName); + ibuf = BKE_image_acquire_ibuf(ima, &iuser, &lock); + + if (!ibuf) { + BLI_thread_unlock(LOCK_DRAW_IMAGE); + return; + } + if (ibuf->x != (int)getWidth() || ibuf->y != (int)getHeight()) { + + imb_freerectImBuf(ibuf); + imb_freerectfloatImBuf(ibuf); + IMB_freezbuffloatImBuf(ibuf); + ibuf->x = getWidth(); + ibuf->y = getHeight(); + /* zero size can happen if no image buffers exist to define a sensible resolution */ + if (ibuf->x > 0 && ibuf->y > 0) + imb_addrectfloatImBuf(ibuf); + ima->ok = IMA_OK_LOADED; + + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; + } + + if (m_doDepthBuffer) { + addzbuffloatImBuf(ibuf); + } + + /* now we combine the input with ibuf */ + this->m_outputBuffer = ibuf->rect_float; + + /* needed for display buffer update */ + this->m_ibuf = ibuf; + + if (m_doDepthBuffer) { + this->m_depthBuffer = ibuf->zbuf_float; + } + + BKE_image_release_ibuf(this->m_image, this->m_ibuf, lock); + + BLI_thread_unlock(LOCK_DRAW_IMAGE); } void ViewerOperation::updateImage(rcti *rect) { - IMB_partial_display_buffer_update(this->m_ibuf, this->m_outputBuffer, NULL, getWidth(), 0, 0, - this->m_viewSettings, this->m_displaySettings, - rect->xmin, rect->ymin, rect->xmax, rect->ymax, false); - - this->updateDraw(); + IMB_partial_display_buffer_update(this->m_ibuf, + this->m_outputBuffer, + NULL, + getWidth(), + 0, + 0, + this->m_viewSettings, + this->m_displaySettings, + rect->xmin, + rect->ymin, + rect->xmax, + rect->ymax, + false); + + this->updateDraw(); } CompositorPriority ViewerOperation::getRenderPriority() const { - if (this->isActiveViewerOutput()) { - return COM_PRIORITY_HIGH; - } - else { - return COM_PRIORITY_LOW; - } + if (this->isActiveViewerOutput()) { + return COM_PRIORITY_HIGH; + } + else { + return COM_PRIORITY_LOW; + } } diff --git a/source/blender/compositor/operations/COM_ViewerOperation.h b/source/blender/compositor/operations/COM_ViewerOperation.h index 49a2b0962d1..29c3b6d8075 100644 --- a/source/blender/compositor/operations/COM_ViewerOperation.h +++ b/source/blender/compositor/operations/COM_ViewerOperation.h @@ -24,55 +24,108 @@ #include "BKE_global.h" class ViewerOperation : public NodeOperation { -private: - float *m_outputBuffer; - float *m_depthBuffer; - Image *m_image; - ImageUser *m_imageUser; - bool m_active; - float m_centerX; - float m_centerY; - OrderOfChunks m_chunkOrder; - bool m_doDepthBuffer; - ImBuf *m_ibuf; - bool m_useAlphaInput; - const RenderData *m_rd; - const char *m_viewName; + private: + float *m_outputBuffer; + float *m_depthBuffer; + Image *m_image; + ImageUser *m_imageUser; + bool m_active; + float m_centerX; + float m_centerY; + OrderOfChunks m_chunkOrder; + bool m_doDepthBuffer; + ImBuf *m_ibuf; + bool m_useAlphaInput; + const RenderData *m_rd; + const char *m_viewName; - const ColorManagedViewSettings *m_viewSettings; - const ColorManagedDisplaySettings *m_displaySettings; + const ColorManagedViewSettings *m_viewSettings; + const ColorManagedDisplaySettings *m_displaySettings; - SocketReader *m_imageInput; - SocketReader *m_alphaInput; - SocketReader *m_depthInput; + SocketReader *m_imageInput; + SocketReader *m_alphaInput; + SocketReader *m_depthInput; -public: - ViewerOperation(); - void initExecution(); - void deinitExecution(); - void executeRegion(rcti *rect, unsigned int tileNumber); - bool isOutputOperation(bool /*rendering*/) const { if (G.background) return false; return isActiveViewerOutput(); } - void setImage(Image *image) { this->m_image = image; } - void setImageUser(ImageUser *imageUser) { this->m_imageUser = imageUser; } - bool isActiveViewerOutput() const { return this->m_active; } - void setActive(bool active) { this->m_active = active; } - void setCenterX(float centerX) { this->m_centerX = centerX;} - void setCenterY(float centerY) { this->m_centerY = centerY;} - void setChunkOrder(OrderOfChunks tileOrder) { this->m_chunkOrder = tileOrder; } - float getCenterX() const { return this->m_centerX; } - float getCenterY() const { return this->m_centerY; } - OrderOfChunks getChunkOrder() const { return this->m_chunkOrder; } - CompositorPriority getRenderPriority() const; - bool isViewerOperation() const { return true; } - void setUseAlphaInput(bool value) { this->m_useAlphaInput = value; } - void setRenderData(const RenderData *rd) { this->m_rd = rd; } - void setViewName(const char *viewName) { this->m_viewName = viewName; } + public: + ViewerOperation(); + void initExecution(); + void deinitExecution(); + void executeRegion(rcti *rect, unsigned int tileNumber); + bool isOutputOperation(bool /*rendering*/) const + { + if (G.background) + return false; + return isActiveViewerOutput(); + } + void setImage(Image *image) + { + this->m_image = image; + } + void setImageUser(ImageUser *imageUser) + { + this->m_imageUser = imageUser; + } + bool isActiveViewerOutput() const + { + return this->m_active; + } + void setActive(bool active) + { + this->m_active = active; + } + void setCenterX(float centerX) + { + this->m_centerX = centerX; + } + void setCenterY(float centerY) + { + this->m_centerY = centerY; + } + void setChunkOrder(OrderOfChunks tileOrder) + { + this->m_chunkOrder = tileOrder; + } + float getCenterX() const + { + return this->m_centerX; + } + float getCenterY() const + { + return this->m_centerY; + } + OrderOfChunks getChunkOrder() const + { + return this->m_chunkOrder; + } + CompositorPriority getRenderPriority() const; + bool isViewerOperation() const + { + return true; + } + void setUseAlphaInput(bool value) + { + this->m_useAlphaInput = value; + } + void setRenderData(const RenderData *rd) + { + this->m_rd = rd; + } + void setViewName(const char *viewName) + { + this->m_viewName = viewName; + } - void setViewSettings(const ColorManagedViewSettings *viewSettings) { this->m_viewSettings = viewSettings; } - void setDisplaySettings(const ColorManagedDisplaySettings *displaySettings) { this->m_displaySettings = displaySettings; } + void setViewSettings(const ColorManagedViewSettings *viewSettings) + { + this->m_viewSettings = viewSettings; + } + void setDisplaySettings(const ColorManagedDisplaySettings *displaySettings) + { + this->m_displaySettings = displaySettings; + } -private: - void updateImage(rcti *rect); - void initImage(); + private: + void updateImage(rcti *rect); + void initImage(); }; #endif diff --git a/source/blender/compositor/operations/COM_WrapOperation.cpp b/source/blender/compositor/operations/COM_WrapOperation.cpp index c43e6961064..e55f63f7d73 100644 --- a/source/blender/compositor/operations/COM_WrapOperation.cpp +++ b/source/blender/compositor/operations/COM_WrapOperation.cpp @@ -20,86 +20,92 @@ WrapOperation::WrapOperation(DataType datatype) : ReadBufferOperation(datatype) { - this->m_wrappingType = CMP_NODE_WRAP_NONE; + this->m_wrappingType = CMP_NODE_WRAP_NONE; } inline float WrapOperation::getWrappedOriginalXPos(float x) { - if (this->getWidth() == 0) return 0; - while (x < 0) x += this->m_width; - return fmodf(x, this->getWidth()); + if (this->getWidth() == 0) + return 0; + while (x < 0) + x += this->m_width; + return fmodf(x, this->getWidth()); } inline float WrapOperation::getWrappedOriginalYPos(float y) { - if (this->getHeight() == 0) return 0; - while (y < 0) y += this->m_height; - return fmodf(y, this->getHeight()); + if (this->getHeight() == 0) + return 0; + while (y < 0) + y += this->m_height; + return fmodf(y, this->getHeight()); } void WrapOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { - float nx, ny; - nx = x; - ny = y; - MemoryBufferExtend extend_x = COM_MB_CLIP, extend_y = COM_MB_CLIP; - switch (m_wrappingType) { - case CMP_NODE_WRAP_NONE: - //Intentionally empty, originalXPos and originalYPos have been set before - break; - case CMP_NODE_WRAP_X: - // wrap only on the x-axis - nx = this->getWrappedOriginalXPos(x); - extend_x = COM_MB_REPEAT; - break; - case CMP_NODE_WRAP_Y: - // wrap only on the y-axis - ny = this->getWrappedOriginalYPos(y); - extend_y = COM_MB_REPEAT; - break; - case CMP_NODE_WRAP_XY: - // wrap on both - nx = this->getWrappedOriginalXPos(x); - ny = this->getWrappedOriginalYPos(y); - extend_x = COM_MB_REPEAT; - extend_y = COM_MB_REPEAT; - break; - } + float nx, ny; + nx = x; + ny = y; + MemoryBufferExtend extend_x = COM_MB_CLIP, extend_y = COM_MB_CLIP; + switch (m_wrappingType) { + case CMP_NODE_WRAP_NONE: + //Intentionally empty, originalXPos and originalYPos have been set before + break; + case CMP_NODE_WRAP_X: + // wrap only on the x-axis + nx = this->getWrappedOriginalXPos(x); + extend_x = COM_MB_REPEAT; + break; + case CMP_NODE_WRAP_Y: + // wrap only on the y-axis + ny = this->getWrappedOriginalYPos(y); + extend_y = COM_MB_REPEAT; + break; + case CMP_NODE_WRAP_XY: + // wrap on both + nx = this->getWrappedOriginalXPos(x); + ny = this->getWrappedOriginalYPos(y); + extend_x = COM_MB_REPEAT; + extend_y = COM_MB_REPEAT; + break; + } - executePixelExtend(output, nx, ny, sampler, extend_x, extend_y); + executePixelExtend(output, nx, ny, sampler, extend_x, extend_y); } -bool WrapOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool WrapOperation::determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output) { - rcti newInput; - newInput.xmin = input->xmin; - newInput.xmax = input->xmax; - newInput.ymin = input->ymin; - newInput.ymax = input->ymax; + rcti newInput; + newInput.xmin = input->xmin; + newInput.xmax = input->xmax; + newInput.ymin = input->ymin; + newInput.ymax = input->ymax; - if (m_wrappingType == CMP_NODE_WRAP_X || m_wrappingType == CMP_NODE_WRAP_XY) { - // wrap only on the x-axis if tile is wrapping - newInput.xmin = getWrappedOriginalXPos(input->xmin); - newInput.xmax = getWrappedOriginalXPos(input->xmax) + 0.5f; - if (newInput.xmin >= newInput.xmax) { - newInput.xmin = 0; - newInput.xmax = this->getWidth(); - } - } - if (m_wrappingType == CMP_NODE_WRAP_Y || m_wrappingType == CMP_NODE_WRAP_XY) { - // wrap only on the y-axis if tile is wrapping - newInput.ymin = getWrappedOriginalYPos(input->ymin); - newInput.ymax = getWrappedOriginalYPos(input->ymax) + 0.5f; - if (newInput.ymin >= newInput.ymax) { - newInput.ymin = 0; - newInput.ymax = this->getHeight(); - } - } + if (m_wrappingType == CMP_NODE_WRAP_X || m_wrappingType == CMP_NODE_WRAP_XY) { + // wrap only on the x-axis if tile is wrapping + newInput.xmin = getWrappedOriginalXPos(input->xmin); + newInput.xmax = getWrappedOriginalXPos(input->xmax) + 0.5f; + if (newInput.xmin >= newInput.xmax) { + newInput.xmin = 0; + newInput.xmax = this->getWidth(); + } + } + if (m_wrappingType == CMP_NODE_WRAP_Y || m_wrappingType == CMP_NODE_WRAP_XY) { + // wrap only on the y-axis if tile is wrapping + newInput.ymin = getWrappedOriginalYPos(input->ymin); + newInput.ymax = getWrappedOriginalYPos(input->ymax) + 0.5f; + if (newInput.ymin >= newInput.ymax) { + newInput.ymin = 0; + newInput.ymax = this->getHeight(); + } + } - return ReadBufferOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + return ReadBufferOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } void WrapOperation::setWrapping(int wrapping_type) { - m_wrappingType = wrapping_type; + m_wrappingType = wrapping_type; } diff --git a/source/blender/compositor/operations/COM_WrapOperation.h b/source/blender/compositor/operations/COM_WrapOperation.h index 2e25cbd552d..6360fa0c246 100644 --- a/source/blender/compositor/operations/COM_WrapOperation.h +++ b/source/blender/compositor/operations/COM_WrapOperation.h @@ -22,18 +22,21 @@ #include "COM_ReadBufferOperation.h" class WrapOperation : public ReadBufferOperation { -private: - int m_wrappingType; -public: - WrapOperation(DataType datetype); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + private: + int m_wrappingType; - void setWrapping(int wrapping_type); - float getWrappedOriginalXPos(float x); - float getWrappedOriginalYPos(float y); + public: + WrapOperation(DataType datetype); + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - void setFactorXY(float factorX, float factorY); + void setWrapping(int wrapping_type); + float getWrappedOriginalXPos(float x); + float getWrappedOriginalYPos(float y); + + void setFactorXY(float factorX, float factorY); }; #endif diff --git a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp index 30c1d4525ab..beba29e6755 100644 --- a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp +++ b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp @@ -23,168 +23,206 @@ WriteBufferOperation::WriteBufferOperation(DataType datatype) : NodeOperation() { - this->addInputSocket(datatype); - this->m_memoryProxy = new MemoryProxy(datatype); - this->m_memoryProxy->setWriteBufferOperation(this); - this->m_memoryProxy->setExecutor(NULL); + this->addInputSocket(datatype); + this->m_memoryProxy = new MemoryProxy(datatype); + this->m_memoryProxy->setWriteBufferOperation(this); + this->m_memoryProxy->setExecutor(NULL); } WriteBufferOperation::~WriteBufferOperation() { - if (this->m_memoryProxy) { - delete this->m_memoryProxy; - this->m_memoryProxy = NULL; - } + if (this->m_memoryProxy) { + delete this->m_memoryProxy; + this->m_memoryProxy = NULL; + } } -void WriteBufferOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void WriteBufferOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - this->m_input->readSampled(output, x, y, sampler); + this->m_input->readSampled(output, x, y, sampler); } void WriteBufferOperation::initExecution() { - this->m_input = this->getInputOperation(0); - this->m_memoryProxy->allocate(this->m_width, this->m_height); + this->m_input = this->getInputOperation(0); + this->m_memoryProxy->allocate(this->m_width, this->m_height); } void WriteBufferOperation::deinitExecution() { - this->m_input = NULL; - this->m_memoryProxy->free(); + this->m_input = NULL; + this->m_memoryProxy->free(); } void WriteBufferOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/) { - MemoryBuffer *memoryBuffer = this->m_memoryProxy->getBuffer(); - float *buffer = memoryBuffer->getBuffer(); - const int num_channels = memoryBuffer->get_num_channels(); - if (this->m_input->isComplex()) { - void *data = this->m_input->initializeTileData(rect); - int x1 = rect->xmin; - int y1 = rect->ymin; - int x2 = rect->xmax; - int y2 = rect->ymax; - int x; - int y; - bool breaked = false; - for (y = y1; y < y2 && (!breaked); y++) { - int offset4 = (y * memoryBuffer->getWidth() + x1) * num_channels; - for (x = x1; x < x2; x++) { - this->m_input->read(&(buffer[offset4]), x, y, data); - offset4 += num_channels; - } - if (isBreaked()) { - breaked = true; - } - - } - if (data) { - this->m_input->deinitializeTileData(rect, data); - data = NULL; - } - } - else { - int x1 = rect->xmin; - int y1 = rect->ymin; - int x2 = rect->xmax; - int y2 = rect->ymax; - - int x; - int y; - bool breaked = false; - for (y = y1; y < y2 && (!breaked); y++) { - int offset4 = (y * memoryBuffer->getWidth() + x1) * num_channels; - for (x = x1; x < x2; x++) { - this->m_input->readSampled(&(buffer[offset4]), x, y, COM_PS_NEAREST); - offset4 += num_channels; - } - if (isBreaked()) { - breaked = true; - } - } - } - memoryBuffer->setCreatedState(); + MemoryBuffer *memoryBuffer = this->m_memoryProxy->getBuffer(); + float *buffer = memoryBuffer->getBuffer(); + const int num_channels = memoryBuffer->get_num_channels(); + if (this->m_input->isComplex()) { + void *data = this->m_input->initializeTileData(rect); + int x1 = rect->xmin; + int y1 = rect->ymin; + int x2 = rect->xmax; + int y2 = rect->ymax; + int x; + int y; + bool breaked = false; + for (y = y1; y < y2 && (!breaked); y++) { + int offset4 = (y * memoryBuffer->getWidth() + x1) * num_channels; + for (x = x1; x < x2; x++) { + this->m_input->read(&(buffer[offset4]), x, y, data); + offset4 += num_channels; + } + if (isBreaked()) { + breaked = true; + } + } + if (data) { + this->m_input->deinitializeTileData(rect, data); + data = NULL; + } + } + else { + int x1 = rect->xmin; + int y1 = rect->ymin; + int x2 = rect->xmax; + int y2 = rect->ymax; + + int x; + int y; + bool breaked = false; + for (y = y1; y < y2 && (!breaked); y++) { + int offset4 = (y * memoryBuffer->getWidth() + x1) * num_channels; + for (x = x1; x < x2; x++) { + this->m_input->readSampled(&(buffer[offset4]), x, y, COM_PS_NEAREST); + offset4 += num_channels; + } + if (isBreaked()) { + breaked = true; + } + } + } + memoryBuffer->setCreatedState(); } -void WriteBufferOperation::executeOpenCLRegion(OpenCLDevice *device, rcti * /*rect*/, unsigned int /*chunkNumber*/, - MemoryBuffer **inputMemoryBuffers, MemoryBuffer *outputBuffer) +void WriteBufferOperation::executeOpenCLRegion(OpenCLDevice *device, + rcti * /*rect*/, + unsigned int /*chunkNumber*/, + MemoryBuffer **inputMemoryBuffers, + MemoryBuffer *outputBuffer) { - float *outputFloatBuffer = outputBuffer->getBuffer(); - cl_int error; - /* - * 1. create cl_mem from outputbuffer - * 2. call NodeOperation (input) executeOpenCLChunk(.....) - * 3. schedule readback from opencl to main device (outputbuffer) - * 4. schedule native callback - * - * note: list of cl_mem will be filled by 2, and needs to be cleaned up by 4 - */ - // STEP 1 - const unsigned int outputBufferWidth = outputBuffer->getWidth(); - const unsigned int outputBufferHeight = outputBuffer->getHeight(); - - const cl_image_format *imageFormat = device->determineImageFormat(outputBuffer); - - cl_mem clOutputBuffer = clCreateImage2D(device->getContext(), CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, imageFormat, outputBufferWidth, outputBufferHeight, 0, outputFloatBuffer, &error); - if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } - - // STEP 2 - list<cl_mem> *clMemToCleanUp = new list<cl_mem>(); - clMemToCleanUp->push_back(clOutputBuffer); - list<cl_kernel> *clKernelsToCleanUp = new list<cl_kernel>(); - - this->m_input->executeOpenCL(device, outputBuffer, clOutputBuffer, inputMemoryBuffers, clMemToCleanUp, clKernelsToCleanUp); - - // STEP 3 - - size_t origin[3] = {0, 0, 0}; - size_t region[3] = {outputBufferWidth, outputBufferHeight, 1}; - -// clFlush(queue); -// clFinish(queue); - - error = clEnqueueBarrier(device->getQueue()); - if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } - error = clEnqueueReadImage(device->getQueue(), clOutputBuffer, CL_TRUE, origin, region, 0, 0, outputFloatBuffer, 0, NULL, NULL); - if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } - - this->getMemoryProxy()->getBuffer()->copyContentFrom(outputBuffer); - - // STEP 4 - while (!clMemToCleanUp->empty()) { - cl_mem mem = clMemToCleanUp->front(); - error = clReleaseMemObject(mem); - if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } - clMemToCleanUp->pop_front(); - } - - while (!clKernelsToCleanUp->empty()) { - cl_kernel kernel = clKernelsToCleanUp->front(); - error = clReleaseKernel(kernel); - if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } - clKernelsToCleanUp->pop_front(); - } - delete clKernelsToCleanUp; + float *outputFloatBuffer = outputBuffer->getBuffer(); + cl_int error; + /* + * 1. create cl_mem from outputbuffer + * 2. call NodeOperation (input) executeOpenCLChunk(.....) + * 3. schedule readback from opencl to main device (outputbuffer) + * 4. schedule native callback + * + * note: list of cl_mem will be filled by 2, and needs to be cleaned up by 4 + */ + // STEP 1 + const unsigned int outputBufferWidth = outputBuffer->getWidth(); + const unsigned int outputBufferHeight = outputBuffer->getHeight(); + + const cl_image_format *imageFormat = device->determineImageFormat(outputBuffer); + + cl_mem clOutputBuffer = clCreateImage2D(device->getContext(), + CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, + imageFormat, + outputBufferWidth, + outputBufferHeight, + 0, + outputFloatBuffer, + &error); + if (error != CL_SUCCESS) { + printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); + } + + // STEP 2 + list<cl_mem> *clMemToCleanUp = new list<cl_mem>(); + clMemToCleanUp->push_back(clOutputBuffer); + list<cl_kernel> *clKernelsToCleanUp = new list<cl_kernel>(); + + this->m_input->executeOpenCL(device, + outputBuffer, + clOutputBuffer, + inputMemoryBuffers, + clMemToCleanUp, + clKernelsToCleanUp); + + // STEP 3 + + size_t origin[3] = {0, 0, 0}; + size_t region[3] = {outputBufferWidth, outputBufferHeight, 1}; + + // clFlush(queue); + // clFinish(queue); + + error = clEnqueueBarrier(device->getQueue()); + if (error != CL_SUCCESS) { + printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); + } + error = clEnqueueReadImage(device->getQueue(), + clOutputBuffer, + CL_TRUE, + origin, + region, + 0, + 0, + outputFloatBuffer, + 0, + NULL, + NULL); + if (error != CL_SUCCESS) { + printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); + } + + this->getMemoryProxy()->getBuffer()->copyContentFrom(outputBuffer); + + // STEP 4 + while (!clMemToCleanUp->empty()) { + cl_mem mem = clMemToCleanUp->front(); + error = clReleaseMemObject(mem); + if (error != CL_SUCCESS) { + printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); + } + clMemToCleanUp->pop_front(); + } + + while (!clKernelsToCleanUp->empty()) { + cl_kernel kernel = clKernelsToCleanUp->front(); + error = clReleaseKernel(kernel); + if (error != CL_SUCCESS) { + printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); + } + clKernelsToCleanUp->pop_front(); + } + delete clKernelsToCleanUp; } -void WriteBufferOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +void WriteBufferOperation::determineResolution(unsigned int resolution[2], + unsigned int preferredResolution[2]) { - NodeOperation::determineResolution(resolution, preferredResolution); - /* make sure there is at least one pixel stored in case the input is a single value */ - m_single_value = false; - if (resolution[0] == 0) { - resolution[0] = 1; - m_single_value = true; - } - if (resolution[1] == 0) { - resolution[1] = 1; - m_single_value = true; - } + NodeOperation::determineResolution(resolution, preferredResolution); + /* make sure there is at least one pixel stored in case the input is a single value */ + m_single_value = false; + if (resolution[0] == 0) { + resolution[0] = 1; + m_single_value = true; + } + if (resolution[1] == 0) { + resolution[1] = 1; + m_single_value = true; + } } void WriteBufferOperation::readResolutionFromInputSocket() { - NodeOperation *inputOperation = this->getInputOperation(0); - this->setWidth(inputOperation->getWidth()); - this->setHeight(inputOperation->getHeight()); + NodeOperation *inputOperation = this->getInputOperation(0); + this->setWidth(inputOperation->getWidth()); + this->setHeight(inputOperation->getHeight()); } diff --git a/source/blender/compositor/operations/COM_WriteBufferOperation.h b/source/blender/compositor/operations/COM_WriteBufferOperation.h index be8a8fb7159..83f7ed1ae56 100644 --- a/source/blender/compositor/operations/COM_WriteBufferOperation.h +++ b/source/blender/compositor/operations/COM_WriteBufferOperation.h @@ -27,26 +27,40 @@ * \ingroup Operation */ class WriteBufferOperation : public NodeOperation { - MemoryProxy *m_memoryProxy; - bool m_single_value; /* single value stored in buffer */ - NodeOperation *m_input; -public: - WriteBufferOperation(DataType datatype); - ~WriteBufferOperation(); - MemoryProxy *getMemoryProxy() { return this->m_memoryProxy; } - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); - bool isWriteBufferOperation() const { return true; } - bool isSingleValue() const { return m_single_value; } + MemoryProxy *m_memoryProxy; + bool m_single_value; /* single value stored in buffer */ + NodeOperation *m_input; - void executeRegion(rcti *rect, unsigned int tileNumber); - void initExecution(); - void deinitExecution(); - void executeOpenCLRegion(OpenCLDevice *device, rcti *rect, unsigned int chunkNumber, MemoryBuffer **memoryBuffers, MemoryBuffer *outputBuffer); - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); - void readResolutionFromInputSocket(); - inline NodeOperation *getInput() { - return m_input; - } + public: + WriteBufferOperation(DataType datatype); + ~WriteBufferOperation(); + MemoryProxy *getMemoryProxy() + { + return this->m_memoryProxy; + } + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + bool isWriteBufferOperation() const + { + return true; + } + bool isSingleValue() const + { + return m_single_value; + } + void executeRegion(rcti *rect, unsigned int tileNumber); + void initExecution(); + void deinitExecution(); + void executeOpenCLRegion(OpenCLDevice *device, + rcti *rect, + unsigned int chunkNumber, + MemoryBuffer **memoryBuffers, + MemoryBuffer *outputBuffer); + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); + void readResolutionFromInputSocket(); + inline NodeOperation *getInput() + { + return m_input; + } }; #endif diff --git a/source/blender/compositor/operations/COM_ZCombineOperation.cpp b/source/blender/compositor/operations/COM_ZCombineOperation.cpp index 5c7472acbe8..222f42e8241 100644 --- a/source/blender/compositor/operations/COM_ZCombineOperation.cpp +++ b/source/blender/compositor/operations/COM_ZCombineOperation.cpp @@ -21,129 +21,140 @@ ZCombineOperation::ZCombineOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_COLOR); - - this->m_image1Reader = NULL; - this->m_depth1Reader = NULL; - this->m_image2Reader = NULL; - this->m_depth2Reader = NULL; - + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_COLOR); + + this->m_image1Reader = NULL; + this->m_depth1Reader = NULL; + this->m_image2Reader = NULL; + this->m_depth2Reader = NULL; } void ZCombineOperation::initExecution() { - this->m_image1Reader = this->getInputSocketReader(0); - this->m_depth1Reader = this->getInputSocketReader(1); - this->m_image2Reader = this->getInputSocketReader(2); - this->m_depth2Reader = this->getInputSocketReader(3); + this->m_image1Reader = this->getInputSocketReader(0); + this->m_depth1Reader = this->getInputSocketReader(1); + this->m_image2Reader = this->getInputSocketReader(2); + this->m_depth2Reader = this->getInputSocketReader(3); } -void ZCombineOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ZCombineOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float depth1[4]; - float depth2[4]; - - this->m_depth1Reader->readSampled(depth1, x, y, sampler); - this->m_depth2Reader->readSampled(depth2, x, y, sampler); - if (depth1[0] < depth2[0]) { - this->m_image1Reader->readSampled(output, x, y, sampler); - } - else { - this->m_image2Reader->readSampled(output, x, y, sampler); - } + float depth1[4]; + float depth2[4]; + + this->m_depth1Reader->readSampled(depth1, x, y, sampler); + this->m_depth2Reader->readSampled(depth2, x, y, sampler); + if (depth1[0] < depth2[0]) { + this->m_image1Reader->readSampled(output, x, y, sampler); + } + else { + this->m_image2Reader->readSampled(output, x, y, sampler); + } } -void ZCombineAlphaOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ZCombineAlphaOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float depth1[4]; - float depth2[4]; - float color1[4]; - float color2[4]; - - this->m_depth1Reader->readSampled(depth1, x, y, sampler); - this->m_depth2Reader->readSampled(depth2, x, y, sampler); - if (depth1[0] <= depth2[0]) { - this->m_image1Reader->readSampled(color1, x, y, sampler); - this->m_image2Reader->readSampled(color2, x, y, sampler); - } - else { - this->m_image1Reader->readSampled(color2, x, y, sampler); - this->m_image2Reader->readSampled(color1, x, y, sampler); - } - float fac = color1[3]; - float ifac = 1.0f - fac; - output[0] = fac * color1[0] + ifac * color2[0]; - output[1] = fac * color1[1] + ifac * color2[1]; - output[2] = fac * color1[2] + ifac * color2[2]; - output[3] = max(color1[3], color2[3]); + float depth1[4]; + float depth2[4]; + float color1[4]; + float color2[4]; + + this->m_depth1Reader->readSampled(depth1, x, y, sampler); + this->m_depth2Reader->readSampled(depth2, x, y, sampler); + if (depth1[0] <= depth2[0]) { + this->m_image1Reader->readSampled(color1, x, y, sampler); + this->m_image2Reader->readSampled(color2, x, y, sampler); + } + else { + this->m_image1Reader->readSampled(color2, x, y, sampler); + this->m_image2Reader->readSampled(color1, x, y, sampler); + } + float fac = color1[3]; + float ifac = 1.0f - fac; + output[0] = fac * color1[0] + ifac * color2[0]; + output[1] = fac * color1[1] + ifac * color2[1]; + output[2] = fac * color1[2] + ifac * color2[2]; + output[3] = max(color1[3], color2[3]); } void ZCombineOperation::deinitExecution() { - this->m_image1Reader = NULL; - this->m_depth1Reader = NULL; - this->m_image2Reader = NULL; - this->m_depth2Reader = NULL; + this->m_image1Reader = NULL; + this->m_depth1Reader = NULL; + this->m_image2Reader = NULL; + this->m_depth2Reader = NULL; } // MASK combine ZCombineMaskOperation::ZCombineMaskOperation() : NodeOperation() { - this->addInputSocket(COM_DT_VALUE); //mask - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - - this->m_maskReader = NULL; - this->m_image1Reader = NULL; - this->m_image2Reader = NULL; + this->addInputSocket(COM_DT_VALUE); //mask + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); + + this->m_maskReader = NULL; + this->m_image1Reader = NULL; + this->m_image2Reader = NULL; } void ZCombineMaskOperation::initExecution() { - this->m_maskReader = this->getInputSocketReader(0); - this->m_image1Reader = this->getInputSocketReader(1); - this->m_image2Reader = this->getInputSocketReader(2); + this->m_maskReader = this->getInputSocketReader(0); + this->m_image1Reader = this->getInputSocketReader(1); + this->m_image2Reader = this->getInputSocketReader(2); } -void ZCombineMaskOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ZCombineMaskOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float mask[4]; - float color1[4]; - float color2[4]; + float mask[4]; + float color1[4]; + float color2[4]; - this->m_maskReader->readSampled(mask, x, y, sampler); - this->m_image1Reader->readSampled(color1, x, y, sampler); - this->m_image2Reader->readSampled(color2, x, y, sampler); + this->m_maskReader->readSampled(mask, x, y, sampler); + this->m_image1Reader->readSampled(color1, x, y, sampler); + this->m_image2Reader->readSampled(color2, x, y, sampler); - interp_v4_v4v4(output, color1, color2, 1.0f - mask[0]); + interp_v4_v4v4(output, color1, color2, 1.0f - mask[0]); } -void ZCombineMaskAlphaOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ZCombineMaskAlphaOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { - float mask[4]; - float color1[4]; - float color2[4]; + float mask[4]; + float color1[4]; + float color2[4]; - this->m_maskReader->readSampled(mask, x, y, sampler); - this->m_image1Reader->readSampled(color1, x, y, sampler); - this->m_image2Reader->readSampled(color2, x, y, sampler); + this->m_maskReader->readSampled(mask, x, y, sampler); + this->m_image1Reader->readSampled(color1, x, y, sampler); + this->m_image2Reader->readSampled(color2, x, y, sampler); - float fac = (1.0f - mask[0]) * (1.0f - color1[3]) + mask[0] * color2[3]; - float mfac = 1.0f - fac; + float fac = (1.0f - mask[0]) * (1.0f - color1[3]) + mask[0] * color2[3]; + float mfac = 1.0f - fac; - output[0] = color1[0] * mfac + color2[0] * fac; - output[1] = color1[1] * mfac + color2[1] * fac; - output[2] = color1[2] * mfac + color2[2] * fac; - output[3] = max(color1[3], color2[3]); + output[0] = color1[0] * mfac + color2[0] * fac; + output[1] = color1[1] * mfac + color2[1] * fac; + output[2] = color1[2] * mfac + color2[2] * fac; + output[3] = max(color1[3], color2[3]); } void ZCombineMaskOperation::deinitExecution() { - this->m_image1Reader = NULL; - this->m_maskReader = NULL; - this->m_image2Reader = NULL; + this->m_image1Reader = NULL; + this->m_maskReader = NULL; + this->m_image2Reader = NULL; } diff --git a/source/blender/compositor/operations/COM_ZCombineOperation.h b/source/blender/compositor/operations/COM_ZCombineOperation.h index 9f9ecfa57e9..9a93d080a2f 100644 --- a/source/blender/compositor/operations/COM_ZCombineOperation.h +++ b/source/blender/compositor/operations/COM_ZCombineOperation.h @@ -20,50 +20,51 @@ #define __COM_ZCOMBINEOPERATION_H__ #include "COM_MixOperation.h" - /** * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ class ZCombineOperation : public NodeOperation { -protected: - SocketReader *m_image1Reader; - SocketReader *m_depth1Reader; - SocketReader *m_image2Reader; - SocketReader *m_depth2Reader; -public: - /** - * Default constructor - */ - ZCombineOperation(); + protected: + SocketReader *m_image1Reader; + SocketReader *m_depth1Reader; + SocketReader *m_image2Reader; + SocketReader *m_depth2Reader; + + public: + /** + * Default constructor + */ + ZCombineOperation(); - void initExecution(); - void deinitExecution(); + void initExecution(); + void deinitExecution(); - /** - * the inner loop of this program - */ - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class ZCombineAlphaOperation : public ZCombineOperation { - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class ZCombineMaskOperation : public NodeOperation { -protected: - SocketReader *m_maskReader; - SocketReader *m_image1Reader; - SocketReader *m_image2Reader; -public: - ZCombineMaskOperation(); + protected: + SocketReader *m_maskReader; + SocketReader *m_image1Reader; + SocketReader *m_image2Reader; + + public: + ZCombineMaskOperation(); - void initExecution(); - void deinitExecution(); - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void initExecution(); + void deinitExecution(); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; class ZCombineMaskAlphaOperation : public ZCombineMaskOperation { - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; #endif |