Compositor: implement bicubic interpolation for Stabilize2DNode

This patch also fixes a crash when image input of `Stabilize2DNode` is unconnected and interpolation is set to bicubic.

Differences to GPU compositor:
- ~1px difference is observed due to different rounding of domain size vs. canvas size. This difference is constant for all image sizes.
- If image input is unconnected but other inputs are, CPU compositor doesn't consider the operation to be constant, whereas GPU compositor still outputs a constant result.

Pull Request: https://projects.blender.org/blender/blender/pulls/122288
This commit is contained in:
Habib Gahbiche 2024-05-30 17:38:41 +02:00 committed by Habib Gahbiche
parent 2fc2280e0e
commit 192d4dc9dc
5 changed files with 18 additions and 4 deletions

@ -288,8 +288,18 @@ class MemoryBuffer {
void read_elem_bicubic_bspline(float x, float y, float *out) const
{
math::interpolate_cubic_bspline_fl(
buffer_, out, this->get_width(), this->get_height(), num_channels_, x, y);
if (is_a_single_elem_) {
memcpy(out, buffer_, get_elem_bytes_len());
return;
}
math::interpolate_cubic_bspline_fl(buffer_,
out,
this->get_width(),
this->get_height(),
num_channels_,
get_relative_x(x),
get_relative_y(y));
}
void read_elem_sampled(float x, float y, PixelSampler sampler, float *out) const

@ -61,6 +61,7 @@ void Stabilize2dNode::convert_to_operations(NodeConverter &converter,
rotate_operation->set_do_degree2_rad_conversion(false);
rotate_operation->set_sampler(sampler);
TranslateOperation *translate_operation = new TranslateCanvasOperation();
translate_operation->set_sampler(sampler);
converter.add_operation(scale_operation);
converter.add_operation(translate_operation);

@ -37,6 +37,7 @@ void TransformNode::convert_to_operations(NodeConverter &converter,
PixelSampler sampler = (PixelSampler)this->get_bnode()->custom1;
scale_operation->set_sampler(sampler);
rotate_operation->set_sampler(sampler);
translate_operation->set_sampler(sampler);
converter.map_input_socket(image_input, scale_operation->get_input_socket(0));
converter.map_input_socket(scale_input, scale_operation->get_input_socket(1));

@ -80,7 +80,9 @@ void TranslateOperation::update_memory_buffer_partial(MemoryBuffer *output,
Span<MemoryBuffer *> inputs)
{
MemoryBuffer *input = inputs[0];
if (input->is_a_single_elem()) {
/* Linking X and Y input sockets to non-constant input may result in a non-constant output, see
* Stabilize2dNode for example. */
if (input->is_a_single_elem() && output->is_a_single_elem()) {
copy_v4_v4(output->get_elem(0, 0), input->get_elem(0, 0));
return;
}

@ -1 +1 @@
Subproject commit 753727081d73e1469f45fb9b36ad081c12cfcfab
Subproject commit 25b7bed33c02c797178fe752ae0374b22d0b2bf2