/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Copyright 2011, Blender Foundation. */ #include "COM_Stabilize2dNode.h" #include "COM_MovieClipAttributeOperation.h" #include "COM_RotateOperation.h" #include "COM_ScaleOperation.h" #include "COM_SetSamplerOperation.h" #include "COM_TranslateOperation.h" namespace blender::compositor { Stabilize2dNode::Stabilize2dNode(bNode *editor_node) : Node(editor_node) { /* pass */ } void Stabilize2dNode::convert_to_operations(NodeConverter &converter, const CompositorContext &context) const { bNode *editor_node = this->get_bnode(); NodeInput *image_input = this->get_input_socket(0); MovieClip *clip = (MovieClip *)editor_node->id; bool invert = (editor_node->custom2 & CMP_NODEFLAG_STABILIZE_INVERSE) != 0; const PixelSampler sampler = (PixelSampler)editor_node->custom1; MovieClipAttributeOperation *scale_attribute = new MovieClipAttributeOperation(); MovieClipAttributeOperation *angle_attribute = new MovieClipAttributeOperation(); MovieClipAttributeOperation *x_attribute = new MovieClipAttributeOperation(); MovieClipAttributeOperation *y_attribute = new MovieClipAttributeOperation(); scale_attribute->set_attribute(MCA_SCALE); scale_attribute->set_framenumber(context.get_framenumber()); scale_attribute->set_movie_clip(clip); scale_attribute->set_invert(invert); angle_attribute->set_attribute(MCA_ANGLE); angle_attribute->set_framenumber(context.get_framenumber()); angle_attribute->set_movie_clip(clip); angle_attribute->set_invert(invert); x_attribute->set_attribute(MCA_X); x_attribute->set_framenumber(context.get_framenumber()); x_attribute->set_movie_clip(clip); x_attribute->set_invert(invert); y_attribute->set_attribute(MCA_Y); y_attribute->set_framenumber(context.get_framenumber()); y_attribute->set_movie_clip(clip); y_attribute->set_invert(invert); converter.add_operation(scale_attribute); converter.add_operation(angle_attribute); converter.add_operation(x_attribute); converter.add_operation(y_attribute); switch (context.get_execution_model()) { case eExecutionModel::Tiled: { ScaleRelativeOperation *scale_operation = new ScaleRelativeOperation(); scale_operation->set_sampler(sampler); RotateOperation *rotate_operation = new RotateOperation(); rotate_operation->set_do_degree2_rad_conversion(false); TranslateOperation *translate_operation = new TranslateOperation(); SetSamplerOperation *psoperation = new SetSamplerOperation(); psoperation->set_sampler(sampler); converter.add_operation(scale_operation); converter.add_operation(translate_operation); converter.add_operation(rotate_operation); converter.add_operation(psoperation); converter.add_link(scale_attribute->get_output_socket(), scale_operation->get_input_socket(1)); converter.add_link(scale_attribute->get_output_socket(), scale_operation->get_input_socket(2)); converter.add_link(angle_attribute->get_output_socket(), rotate_operation->get_input_socket(1)); converter.add_link(x_attribute->get_output_socket(), translate_operation->get_input_socket(1)); converter.add_link(y_attribute->get_output_socket(), translate_operation->get_input_socket(2)); converter.map_output_socket(get_output_socket(), psoperation->get_output_socket()); if (invert) { /* Translate -> Rotate -> Scale. */ converter.map_input_socket(image_input, translate_operation->get_input_socket(0)); converter.add_link(translate_operation->get_output_socket(), rotate_operation->get_input_socket(0)); converter.add_link(rotate_operation->get_output_socket(), scale_operation->get_input_socket(0)); converter.add_link(scale_operation->get_output_socket(), psoperation->get_input_socket(0)); } else { /* Scale -> Rotate -> Translate. */ converter.map_input_socket(image_input, scale_operation->get_input_socket(0)); converter.add_link(scale_operation->get_output_socket(), rotate_operation->get_input_socket(0)); converter.add_link(rotate_operation->get_output_socket(), translate_operation->get_input_socket(0)); converter.add_link(translate_operation->get_output_socket(), psoperation->get_input_socket(0)); } break; } case eExecutionModel::FullFrame: { ScaleRelativeOperation *scale_operation = new ScaleRelativeOperation(); scale_operation->set_sampler(sampler); RotateOperation *rotate_operation = new RotateOperation(); rotate_operation->set_do_degree2_rad_conversion(false); rotate_operation->set_sampler(sampler); TranslateOperation *translate_operation = new TranslateCanvasOperation(); converter.add_operation(scale_operation); converter.add_operation(translate_operation); converter.add_operation(rotate_operation); converter.add_link(scale_attribute->get_output_socket(), scale_operation->get_input_socket(1)); converter.add_link(scale_attribute->get_output_socket(), scale_operation->get_input_socket(2)); converter.add_link(angle_attribute->get_output_socket(), rotate_operation->get_input_socket(1)); converter.add_link(x_attribute->get_output_socket(), translate_operation->get_input_socket(1)); converter.add_link(y_attribute->get_output_socket(), translate_operation->get_input_socket(2)); NodeOperationInput *stabilization_socket = nullptr; if (invert) { /* Translate -> Rotate -> Scale. */ stabilization_socket = translate_operation->get_input_socket(0); converter.map_input_socket(image_input, translate_operation->get_input_socket(0)); converter.add_link(translate_operation->get_output_socket(), rotate_operation->get_input_socket(0)); converter.add_link(rotate_operation->get_output_socket(), scale_operation->get_input_socket(0)); converter.map_output_socket(get_output_socket(), scale_operation->get_output_socket()); } else { /* Scale -> Rotate -> Translate. */ stabilization_socket = scale_operation->get_input_socket(0); converter.map_input_socket(image_input, scale_operation->get_input_socket(0)); converter.add_link(scale_operation->get_output_socket(), rotate_operation->get_input_socket(0)); converter.add_link(rotate_operation->get_output_socket(), translate_operation->get_input_socket(0)); converter.map_output_socket(get_output_socket(), translate_operation->get_output_socket()); } x_attribute->set_socket_input_resolution_for_stabilization(stabilization_socket); y_attribute->set_socket_input_resolution_for_stabilization(stabilization_socket); scale_attribute->set_socket_input_resolution_for_stabilization(stabilization_socket); angle_attribute->set_socket_input_resolution_for_stabilization(stabilization_socket); break; } } } } // namespace blender::compositor