diff options
Diffstat (limited to 'source/blender/compositor/operations/COM_ChromaMatteOperation.cc')
-rw-r--r-- | source/blender/compositor/operations/COM_ChromaMatteOperation.cc | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/source/blender/compositor/operations/COM_ChromaMatteOperation.cc b/source/blender/compositor/operations/COM_ChromaMatteOperation.cc index b7fec5f07e5..0784f266b19 100644 --- a/source/blender/compositor/operations/COM_ChromaMatteOperation.cc +++ b/source/blender/compositor/operations/COM_ChromaMatteOperation.cc @@ -29,6 +29,7 @@ ChromaMatteOperation::ChromaMatteOperation() this->m_inputImageProgram = nullptr; this->m_inputKeyProgram = nullptr; + flags.can_be_constant = true; } void ChromaMatteOperation::initExecution() @@ -110,4 +111,58 @@ void ChromaMatteOperation::executePixelSampled(float output[4], } } +void ChromaMatteOperation::update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span<MemoryBuffer *> inputs) +{ + 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; + for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) { + const float *in_image = it.in(0); + const float *in_key = it.in(1); + + /* Store matte(alpha) value in [0] to go with + * #COM_SetAlphaMultiplyOperation and the Value output. */ + + /* Algorithm from book "Video Demystified", 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`. */ + // const float image_Y = (in_image[0] * 2.0f) - 1.0f; // UNUSED + const float image_cb = (in_image[1] * 2.0f) - 1.0f; + const float image_cr = (in_image[2] * 2.0f) - 1.0f; + + // const float key_Y = (in_key[0] * 2.0f) - 1.0f; // UNUSED + const float key_cb = (in_key[1] * 2.0f) - 1.0f; + const float key_cr = (in_key[2] * 2.0f) - 1.0f; + + const float theta = atan2(key_cr, key_cb); + + /* Rotate the cb and cr into x/z space. */ + const float x_angle = image_cb * cosf(theta) + image_cr * sinf(theta); + const float z_angle = image_cr * cosf(theta) - image_cb * sinf(theta); + + /* If within the acceptance angle. */ + /* If kfg is <0 then the pixel is outside of the key color. */ + const float kfg = x_angle - (fabsf(z_angle) / tanf(acceptance / 2.0f)); + + if (kfg > 0.0f) { /* Found a pixel that is within key color. */ + const float beta = atan2(z_angle, x_angle); + float alpha = 1.0f - (kfg / gain); + + /* Ff 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. */ + it.out[0] = alpha < in_image[3] ? alpha : in_image[3]; + } + else { /* Pixel is outside key color. */ + it.out[0] = in_image[3]; /* Make pixel just as transparent as it was before. */ + } + } +} + } // namespace blender::compositor |