Changeset View
Changeset View
Standalone View
Standalone View
source/blender/compositor/operations/COM_BilateralBlurOperation.cc
| Show All 17 Lines | |||||
| #include "COM_BilateralBlurOperation.h" | #include "COM_BilateralBlurOperation.h" | ||||
| #include "BLI_math.h" | #include "BLI_math.h" | ||||
| #include "RE_pipeline.h" | #include "RE_pipeline.h" | ||||
| namespace blender::compositor { | namespace blender::compositor { | ||||
| BilateralBlurOperation::BilateralBlurOperation() | BilateralBlurOperation::BilateralBlurOperation() : FullFrameBufferedOperation(DataType::Color) | ||||
| { | { | ||||
| this->addInputSocket(DataType::Color); | this->addInputSocket(DataType::Color); | ||||
| this->addInputSocket(DataType::Color); | this->addInputSocket(DataType::Color); | ||||
| this->addOutputSocket(DataType::Color); | this->addOutputSocket(DataType::Color); | ||||
| this->flags.complex = true; | this->flags.complex = true; | ||||
| this->m_inputColorProgram = nullptr; | this->m_inputColorProgram = nullptr; | ||||
| this->m_inputDeterminatorProgram = nullptr; | this->m_inputDeterminatorProgram = nullptr; | ||||
| } | } | ||||
| void BilateralBlurOperation::initExecution() | void BilateralBlurOperation::initExecution() | ||||
| { | { | ||||
| FullFrameBufferedOperation::initExecution(); | |||||
| this->m_inputColorProgram = getInputSocketReader(0); | this->m_inputColorProgram = getInputSocketReader(0); | ||||
| this->m_inputDeterminatorProgram = getInputSocketReader(1); | this->m_inputDeterminatorProgram = getInputSocketReader(1); | ||||
| this->m_space = this->m_data->sigma_space + this->m_data->iter; | this->m_space = this->m_data->sigma_space + this->m_data->iter; | ||||
| QualityStepHelper::initExecution(COM_QH_INCREASE); | QualityStepHelper::initExecution(COM_QH_INCREASE); | ||||
| } | } | ||||
| void BilateralBlurOperation::executePixel(float output[4], int x, int y, void *data) | void BilateralBlurOperation::executePixel(float output[4], int x, int y, void *data) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | void BilateralBlurOperation::executePixel(float output[4], int x, int y, void *data) | ||||
| else { | else { | ||||
| output[0] = 0.0f; | output[0] = 0.0f; | ||||
| output[1] = 0.0f; | output[1] = 0.0f; | ||||
| output[2] = 0.0f; | output[2] = 0.0f; | ||||
| output[3] = 1.0f; | output[3] = 1.0f; | ||||
| } | } | ||||
| } | } | ||||
| void BilateralBlurOperation::update_memory_buffer(MemoryBuffer *output_buffer, | |||||
| rcti *output_rect, | |||||
| blender::Span<MemoryBuffer *> inputs) | |||||
| { | |||||
| MemoryBuffer &output = *output_buffer; | |||||
| MemoryBuffer &input_color = *inputs[0]; | |||||
| MemoryBuffer &input_determinator = *inputs[1]; | |||||
| // this will be used as the reference color for the determinator | |||||
| float *determinatorReferenceColor; | |||||
| float determinator[4]; | |||||
| float tempColor[4]; | |||||
| float blurColor[4]; | |||||
| float blurDivider; | |||||
| float space = this->m_space; | |||||
| float sigmacolor = this->m_data->sigma_color; | |||||
| for (int y = output_rect->ymin; y < output_rect->ymax; y++) { | |||||
| int x = output_rect->xmin; | |||||
| float *output_elem = output.get_elem(x, y); | |||||
| while (x < output_rect->xmax) { | |||||
| int minx = floor(x - space); | |||||
| int maxx = ceil(x + space); | |||||
| int miny = floor(y - space); | |||||
| int maxy = ceil(y + space); | |||||
| float deltaColor; | |||||
| determinatorReferenceColor = input_determinator.get_elem(x, y); | |||||
| 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 | |||||
| input_determinator.read(determinator, xi, yi); | |||||
| 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 | |||||
| input_color.read(tempColor, xi, yi); | |||||
| add_v4_v4(blurColor, tempColor); | |||||
| blurDivider += 1.0f; | |||||
| } | |||||
| } | |||||
| } | |||||
| if (blurDivider > 0.0f) { | |||||
| mul_v4_v4fl(output_elem, blurColor, 1.0f / blurDivider); | |||||
| } | |||||
| else { | |||||
| output_elem[0] = 0.0f; | |||||
| output_elem[1] = 0.0f; | |||||
| output_elem[2] = 0.0f; | |||||
| output_elem[3] = 1.0f; | |||||
| } | |||||
| output_elem += output.elem_jump; | |||||
| x++; | |||||
| } | |||||
| } | |||||
| } | |||||
| void BilateralBlurOperation::deinitExecution() | void BilateralBlurOperation::deinitExecution() | ||||
| { | { | ||||
| this->m_inputColorProgram = nullptr; | this->m_inputColorProgram = nullptr; | ||||
| this->m_inputDeterminatorProgram = nullptr; | this->m_inputDeterminatorProgram = nullptr; | ||||
| FullFrameBufferedOperation::deinitExecution(); | |||||
| } | } | ||||
| bool BilateralBlurOperation::determineDependingAreaOfInterest(rcti *input, | bool BilateralBlurOperation::determineDependingAreaOfInterest(rcti *input, | ||||
| ReadBufferOperation *readOperation, | ReadBufferOperation *readOperation, | ||||
| rcti *output) | rcti *output) | ||||
| { | { | ||||
| rcti newInput; | rcti newInput; | ||||
| int add = ceil(this->m_space) + 1; | int add = ceil(this->m_space) + 1; | ||||
| newInput.xmax = input->xmax + (add); | newInput.xmax = input->xmax + (add); | ||||
| newInput.xmin = input->xmin - (add); | newInput.xmin = input->xmin - (add); | ||||
| newInput.ymax = input->ymax + (add); | newInput.ymax = input->ymax + (add); | ||||
| newInput.ymin = input->ymin - (add); | newInput.ymin = input->ymin - (add); | ||||
| return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); | return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); | ||||
| } | } | ||||
| void BilateralBlurOperation::get_input_area_of_interest(int input_socket_index, | |||||
| const rcti *output_rect, | |||||
| rcti *r_input_area) | |||||
| { | |||||
| *r_input_area = *output_rect; | |||||
| // FullFrameOperation::get_input_area_of_interest(input_socket_index, output_rect, r_input_area); | |||||
| // int add = ceil(this->m_space) + 1; | |||||
| // r_input_area->xmax = output_rect->xmax + (add); | |||||
| // r_input_area->xmin = output_rect->xmin - (add); | |||||
| // r_input_area->ymax = output_rect->ymax + (add); | |||||
| // r_input_area->ymin = output_rect->ymin - (add); | |||||
| } | |||||
| } // namespace blender::compositor | } // namespace blender::compositor | ||||