Blender V4.5
node_composite_movieclip.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "BLI_array.hh"
11
12#include "IMB_imbuf.hh"
13
14#include "BKE_context.hh"
15#include "BKE_lib_id.hh"
16#include "BKE_movieclip.h"
17#include "BKE_tracking.h"
18
19#include "DNA_defaults.h"
20
21#include "RNA_access.hh"
22
23#include "UI_interface.hh"
24
25#include "GPU_texture.hh"
26
27#include "COM_node_operation.hh"
28#include "COM_utilities.hh"
29
31
33
35{
36 b.add_output<decl::Color>("Image");
37 b.add_output<decl::Float>("Alpha");
38 b.add_output<decl::Float>("Offset X");
39 b.add_output<decl::Float>("Offset Y");
40 b.add_output<decl::Float>("Scale");
41 b.add_output<decl::Float>("Angle");
42}
43
44static void init(const bContext *C, PointerRNA *ptr)
45{
46 bNode *node = (bNode *)ptr->data;
47 Scene *scene = CTX_data_scene(C);
49
50 node->id = (ID *)scene->clip;
51 id_us_plus(node->id);
52 node->storage = user;
53 user->framenr = 1;
54}
55
57{
58 uiTemplateID(layout, C, ptr, "clip", nullptr, "CLIP_OT_open", nullptr);
59}
60
62{
63 bNode *node = (bNode *)ptr->data;
64 PointerRNA clipptr;
65
66 uiTemplateID(layout, C, ptr, "clip", nullptr, "CLIP_OT_open", nullptr);
67
68 if (!node->id) {
69 return;
70 }
71
72 clipptr = RNA_pointer_get(ptr, "clip");
73
74 uiTemplateColorspaceSettings(layout, &clipptr, "colorspace_settings");
75}
76
77using namespace blender::compositor;
78
80 public:
82
83 void execute() override
84 {
85 ImBuf *movie_clip_buffer = get_movie_clip_buffer();
86
87 compute_image(movie_clip_buffer);
88 compute_alpha(movie_clip_buffer);
89 compute_stabilization_data(movie_clip_buffer);
90
91 IMB_freeImBuf(movie_clip_buffer);
92 }
93
94 void compute_image(ImBuf *movie_clip_buffer)
95 {
96 if (!should_compute_output("Image")) {
97 return;
98 }
99
100 Result &result = get_result("Image");
101 if (!movie_clip_buffer) {
102 result.allocate_invalid();
103 return;
104 }
105
106 const int2 size = int2(movie_clip_buffer->x, movie_clip_buffer->y);
107 result.allocate_texture(Domain(size));
108
109 if (context().use_gpu()) {
111 }
112 else {
113 parallel_for(size, [&](const int2 texel) {
114 int64_t pixel_index = (int64_t(texel.y) * size.x + texel.x) * 4;
115 result.store_pixel(texel, float4(movie_clip_buffer->float_buffer.data + pixel_index));
116 });
117 }
118 }
119
120 void compute_alpha(ImBuf *movie_clip_buffer)
121 {
122 if (!should_compute_output("Alpha")) {
123 return;
124 }
125
126 Result &result = get_result("Alpha");
127 if (!movie_clip_buffer) {
128 result.allocate_single_value();
129 result.set_single_value(1.0f);
130 return;
131 }
132
133 const int2 size = int2(movie_clip_buffer->x, movie_clip_buffer->y);
134 result.allocate_texture(Domain(size));
135
136 if (context().use_gpu()) {
137 Array<float> alpha_values(size.x * size.y);
138 parallel_for(size, [&](const int2 texel) {
139 int64_t pixel_index = int64_t(texel.y) * size.x + texel.x;
140 int64_t input_pixel_index = pixel_index * 4;
141 alpha_values[pixel_index] = movie_clip_buffer->float_buffer.data[input_pixel_index + 3];
142 });
144 }
145 else {
146 parallel_for(size, [&](const int2 texel) {
147 int64_t pixel_index = (int64_t(texel.y) * size.x + texel.x) * 4;
148 result.store_pixel(texel, movie_clip_buffer->float_buffer.data[pixel_index + 3]);
149 });
150 }
151 }
152
153 void compute_stabilization_data(ImBuf *movie_clip_buffer)
154 {
155 /* The movie clip buffer is invalid or missing, set appropriate fallback values. */
156 if (!movie_clip_buffer) {
157 if (should_compute_output("Offset X")) {
158 Result &result = get_result("Offset X");
159 result.allocate_single_value();
160 result.set_single_value(0.0f);
161 }
162 if (should_compute_output("Offset Y")) {
163 Result &result = get_result("Offset Y");
164 result.allocate_single_value();
165 result.set_single_value(0.0f);
166 }
167 if (should_compute_output("Scale")) {
168 Result &result = get_result("Scale");
169 result.allocate_single_value();
170 result.set_single_value(1.0f);
171 }
172 if (should_compute_output("Angle")) {
173 Result &result = get_result("Angle");
174 result.allocate_single_value();
175 result.set_single_value(0.0f);
176 }
177 return;
178 }
179
180 MovieClip *movie_clip = get_movie_clip();
181 const int frame_number = BKE_movieclip_remap_scene_to_clip_frame(movie_clip,
182 context().get_frame_number());
183 const int width = movie_clip_buffer->x;
184 const int height = movie_clip_buffer->y;
185
186 /* If the movie clip has no stabilization data, it will initialize the given values with
187 * fallback values regardless, so no need to handle that case. */
188 float2 offset;
189 float scale, angle;
191 movie_clip, frame_number, width, height, offset, &scale, &angle);
192
193 if (should_compute_output("Offset X")) {
194 Result &result = get_result("Offset X");
195 result.allocate_single_value();
196 result.set_single_value(offset.x);
197 }
198 if (should_compute_output("Offset Y")) {
199 Result &result = get_result("Offset Y");
200 result.allocate_single_value();
201 result.set_single_value(offset.y);
202 }
203 if (should_compute_output("Scale")) {
204 Result &result = get_result("Scale");
205 result.allocate_single_value();
206 result.set_single_value(scale);
207 }
208 if (should_compute_output("Angle")) {
209 Result &result = get_result("Angle");
210 result.allocate_single_value();
211 result.set_single_value(angle);
212 }
213 }
214
215 /* Get a float image buffer contacting the movie content at the current frame. If the movie clip
216 * does not exist or is invalid, return nullptr. */
218 {
219 MovieClip *movie_clip = get_movie_clip();
220 if (!movie_clip) {
221 return nullptr;
222 }
223
224 MovieClipUser *movie_clip_user = get_movie_clip_user();
225 BKE_movieclip_user_set_frame(movie_clip_user, context().get_frame_number());
226
227 ImBuf *movie_clip_buffer = BKE_movieclip_get_ibuf(movie_clip, movie_clip_user);
228 if (!movie_clip_buffer) {
229 return nullptr;
230 }
231
232 if (movie_clip_buffer->float_buffer.data) {
233 return movie_clip_buffer;
234 }
235
236 /* Create a float buffer from the byte buffer if it exists, if not, return nullptr. */
237 IMB_float_from_byte(movie_clip_buffer);
238 if (!movie_clip_buffer->float_buffer.data) {
239 return nullptr;
240 }
241
242 return movie_clip_buffer;
243 }
244
246 {
247 return reinterpret_cast<MovieClip *>(bnode().id);
248 }
249
251 {
252 return static_cast<MovieClipUser *>(bnode().storage);
253 }
254};
255
257{
258 return new MovieClipOperation(context, node);
259}
260
261} // namespace blender::nodes::node_composite_movieclip_cc
262
264{
266
267 static blender::bke::bNodeType ntype;
268
269 cmp_node_type_base(&ntype, "CompositorNodeMovieClip", CMP_NODE_MOVIECLIP);
270 ntype.ui_name = "Movie Clip";
271 ntype.ui_description =
272 "Input image or movie from a movie clip datablock, typically used for motion tracking";
273 ntype.enum_name_legacy = "MOVIECLIP";
274 ntype.nclass = NODE_CLASS_INPUT;
275 ntype.declare = file_ns::cmp_node_movieclip_declare;
276 ntype.draw_buttons = file_ns::node_composit_buts_movieclip;
277 ntype.draw_buttons_ex = file_ns::node_composit_buts_movieclip_ex;
278 ntype.get_compositor_operation = file_ns::get_compositor_operation;
279 ntype.initfunc_api = file_ns::init;
280 ntype.flag |= NODE_PREVIEW;
283
285}
Scene * CTX_data_scene(const bContext *C)
void id_us_plus(ID *id)
Definition lib_id.cc:353
float BKE_movieclip_remap_scene_to_clip_frame(const struct MovieClip *clip, float framenr)
void BKE_movieclip_user_set_frame(struct MovieClipUser *user, int framenr)
struct ImBuf * BKE_movieclip_get_ibuf(struct MovieClip *clip, const struct MovieClipUser *user)
#define NODE_CLASS_INPUT
Definition BKE_node.hh:433
#define CMP_NODE_MOVIECLIP
void BKE_tracking_stabilization_data_get(struct MovieClip *clip, int framenr, int width, int height, float translation[2], float *scale, float *angle)
#define DNA_struct_default_alloc(struct_name)
@ NODE_PREVIEW
@ GPU_DATA_FLOAT
void GPU_texture_update(GPUTexture *texture, eGPUDataFormat data_format, const void *data)
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:117
void IMB_freeImBuf(ImBuf *ibuf)
void IMB_float_from_byte(ImBuf *ibuf)
#define NOD_REGISTER_NODE(REGISTER_FUNC)
#define C
Definition RandGen.cpp:29
void uiTemplateID(uiLayout *layout, const bContext *C, PointerRNA *ptr, blender::StringRefNull propname, const char *newop, const char *openop, const char *unlinkop, int filter=UI_TEMPLATE_ID_FILTER_ALL, bool live_icon=false, std::optional< blender::StringRef > text=std::nullopt)
void uiTemplateColorspaceSettings(uiLayout *layout, PointerRNA *ptr, blender::StringRefNull propname)
void init()
long long int int64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
const T * data() const
Definition BLI_array.hh:301
bool should_compute_output(StringRef identifier)
NodeOperation(Context &context, DNode node)
Result & get_result(StringRef identifier)
Definition operation.cc:39
void node_register_type(bNodeType &ntype)
Definition node.cc:2748
void node_type_storage(bNodeType &ntype, std::optional< StringRefNull > storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
Definition node.cc:5603
void parallel_for(const int2 range, const Function &function)
static void cmp_node_movieclip_declare(NodeDeclarationBuilder &b)
static void node_composit_buts_movieclip_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
static NodeOperation * get_compositor_operation(Context &context, DNode node)
static void node_composit_buts_movieclip(uiLayout *layout, bContext *C, PointerRNA *ptr)
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
static void register_node_type_cmp_movieclip()
void cmp_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
void node_free_standard_storage(bNode *node)
Definition node_util.cc:42
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
Definition node_util.cc:54
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
Definition DNA_ID.h:404
ImBufFloatBuffer float_buffer
struct MovieClip * clip
struct ID * id
void * storage
Defines a node type.
Definition BKE_node.hh:226
std::string ui_description
Definition BKE_node.hh:232
NodeGetCompositorOperationFunction get_compositor_operation
Definition BKE_node.hh:336
void(* draw_buttons_ex)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:249
const char * enum_name_legacy
Definition BKE_node.hh:235
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:247
NodeDeclareFunction declare
Definition BKE_node.hh:355
void(* initfunc_api)(const bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:290
PointerRNA * ptr
Definition wm_files.cc:4227