WIP: Compositor: Add interpolation option to scale node #119902

Draft
Noah Pinales wants to merge 3 commits from Noah-Pinales/blender:com-scale-interp into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
5 changed files with 93 additions and 10 deletions

View File

@ -19,15 +19,31 @@ void ScaleNode::convert_to_operations(NodeConverter &converter,
const CompositorContext &context) const
{
const bNode *bnode = this->get_bnode();
const NodeScaleData *data = (const NodeScaleData *)bnode->storage;
NodeInput *input_socket = this->get_input_socket(0);
NodeInput *input_xsocket = this->get_input_socket(1);
NodeInput *input_ysocket = this->get_input_socket(2);
NodeOutput *output_socket = this->get_output_socket(0);
PixelSampler sampler = PixelSampler::Nearest;
switch (data->interpolation) {
case 0:
sampler = PixelSampler::Nearest;
break;
case 1:
sampler = PixelSampler::Bilinear;
break;
case 2:
sampler = PixelSampler::Bicubic;
break;
}
switch (bnode->custom1) {
case CMP_NODE_SCALE_RELATIVE: {
ScaleRelativeOperation *operation = new ScaleRelativeOperation();
operation->set_sampler(sampler);
converter.add_operation(operation);
converter.map_input_socket(input_socket, operation->get_input_socket(0));
@ -44,6 +60,8 @@ void ScaleNode::convert_to_operations(NodeConverter &converter,
converter.add_operation(scale_factor_operation);
ScaleRelativeOperation *operation = new ScaleRelativeOperation();
operation->set_sampler(sampler);
converter.add_operation(operation);
converter.map_input_socket(input_socket, operation->get_input_socket(0));
@ -68,6 +86,7 @@ void ScaleNode::convert_to_operations(NodeConverter &converter,
operation->set_offset(bnode->custom3, bnode->custom4);
operation->set_new_width(rd->xsch * render_size_factor);
operation->set_new_height(rd->ysch * render_size_factor);
operation->set_sampler(sampler);
converter.add_operation(operation);
converter.map_input_socket(input_socket, operation->get_input_socket(0));
@ -80,6 +99,8 @@ void ScaleNode::convert_to_operations(NodeConverter &converter,
case CMP_NODE_SCALE_ABSOLUTE: {
/* TODO: what is the use of this one.... perhaps some issues when the ui was updated... */
ScaleAbsoluteOperation *operation = new ScaleAbsoluteOperation();
operation->set_sampler(sampler);
converter.add_operation(operation);
converter.map_input_socket(input_socket, operation->get_input_socket(0));

View File

@ -23,9 +23,9 @@ class BaseScaleOperation : public MultiThreadedOperation {
protected:
BaseScaleOperation();
PixelSampler get_effective_sampler(PixelSampler sampler)
PixelSampler get_effective_sampler()
{
return (sampler_ == -1) ? sampler : (PixelSampler)sampler_;
return (PixelSampler)sampler_;
}
int sampler_;

View File

@ -1418,6 +1418,13 @@ typedef struct NodeTranslateData {
char relative;
} NodeTranslateData;
typedef struct NodeScaleData {
int16_t space, frame_method;
float offset_x, offset_y;
short interpolation;
char _pad[2];
} NodeScaleData;
typedef struct NodePlaneTrackDeformData {
char tracking_object[64];
char plane_track_name[64];

View File

@ -6612,28 +6612,55 @@ static void def_cmp_scale(StructRNA *srna)
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem interpolation_items[] = {
{CMP_NODE_STABILIZE_INTERPOLATION_NEAREST,
"NEAREST",
0,
"Nearest",
"Use nearest interpolation"},
{CMP_NODE_STABILIZE_INTERPOLATION_BILINEAR,
"BILINEAR",
0,
"Bilinear",
"Use bilinear interpolation"},
{CMP_NODE_STABILIZE_INTERPOLATION_BICUBIC,
"BICUBIC",
0,
"Bicubic",
"Use bicubic interpolation"},
{0, nullptr, 0, nullptr, nullptr},
};
RNA_def_struct_sdna_from(srna, "NodeScaleData", "storage");
prop = RNA_def_property(srna, "space", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, nullptr, "custom1");
RNA_def_property_enum_sdna(prop, nullptr, "space");
RNA_def_property_enum_items(prop, space_items);
RNA_def_property_ui_text(prop, "Space", "Coordinate space to scale relative to");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_CompositorNodeScale_update");
/* expose 2 flags as a enum of 3 items */
prop = RNA_def_property(srna, "frame_method", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, nullptr, "custom2");
RNA_def_property_enum_bitflag_sdna(prop, nullptr, "frame_method");
RNA_def_property_enum_items(prop, space_frame_items);
RNA_def_property_ui_text(prop, "Frame Method", "How the image fits in the camera frame");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "offset_x", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, nullptr, "custom3");
RNA_def_property_float_sdna(prop, nullptr, "offset_x");
RNA_def_property_ui_text(prop, "X Offset", "Offset image horizontally (factor of image size)");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "offset_y", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, nullptr, "custom4");
RNA_def_property_float_sdna(prop, nullptr, "offset_y");
RNA_def_property_ui_text(prop, "Y Offset", "Offset image vertically (factor of image size)");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "interpolation", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, nullptr, "interpolation");
RNA_def_property_enum_items(prop, interpolation_items);
RNA_def_property_ui_text(prop, "Interpolation", "Which interpolation method to use");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
static void def_cmp_rotate(StructRNA *srna)

View File

@ -28,6 +28,8 @@
namespace blender::nodes::node_composite_scale_cc {
NODE_STORAGE_FUNCS(NodeScaleData)
static void cmp_node_scale_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Color>("Image")
@ -46,6 +48,12 @@ static void cmp_node_scale_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Color>("Image");
}
static void node_composit_init_scale(bNodeTree * /*ntree*/, bNode *node)
{
NodeScaleData *data = MEM_cnew<NodeScaleData>(__func__);
node->storage = data;
}
static void node_composite_update_scale(bNodeTree *ntree, bNode *node)
{
bool use_xy_scale = ELEM(node->custom1, CMP_NODE_SCALE_RELATIVE, CMP_NODE_SCALE_ABSOLUTE);
@ -60,6 +68,7 @@ static void node_composite_update_scale(bNodeTree *ntree, bNode *node)
static void node_composit_buts_scale(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
{
uiItemR(layout, ptr, "interpolation", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
uiItemR(layout, ptr, "space", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
if (RNA_enum_get(ptr, "space") == CMP_NODE_SCALE_RENDER_SIZE) {
@ -93,7 +102,10 @@ class ScaleOperation : public NodeOperation {
const float3x3 transformation = math::from_loc_rot_scale<float3x3>(
translation, rotation, scale);
transform(context(), input, output, transformation, input.get_realization_options());
RealizationOptions realization_options = input.get_realization_options();
realization_options.interpolation = get_interpolation();
transform(context(), input, output, transformation, realization_options);
}
float2 get_scale()
@ -113,6 +125,21 @@ class ScaleOperation : public NodeOperation {
}
}
Interpolation get_interpolation()
{
switch (node_storage(bnode()).interpolation) {
case 0:
return Interpolation::Nearest;
case 1:
return Interpolation::Bilinear;
case 2:
return Interpolation::Bicubic;
}
BLI_assert_unreachable();
return Interpolation::Nearest;
}
/* Scale by the input factors. */
float2 get_scale_relative()
{
@ -201,17 +228,17 @@ class ScaleOperation : public NodeOperation {
CMPNodeScaleMethod get_scale_method()
{
return (CMPNodeScaleMethod)bnode().custom1;
return (CMPNodeScaleMethod)node_storage(bnode()).space;
}
CMPNodeScaleRenderSizeMethod get_scale_render_size_method()
{
return (CMPNodeScaleRenderSizeMethod)bnode().custom2;
return (CMPNodeScaleRenderSizeMethod)node_storage(bnode()).frame_method;
}
float2 get_offset()
{
return float2(bnode().custom3, bnode().custom4);
return float2(node_storage(bnode()).offset_x, node_storage(bnode()).offset_y);
}
};
@ -233,6 +260,7 @@ void register_node_type_cmp_scale()
ntype.draw_buttons = file_ns::node_composit_buts_scale;
ntype.updatefunc = file_ns::node_composite_update_scale;
ntype.get_compositor_operation = file_ns::get_compositor_operation;
ntype.initfunc = file_ns::node_composit_init_scale;
nodeRegisterType(&ntype);
}