Blender  V3.3
COM_KeyingScreenOperation.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2012 Blender Foundation. */
3 
5 
6 #include "DNA_defaults.h"
7 
8 #include "BKE_movieclip.h"
9 #include "BKE_tracking.h"
10 
11 #include "IMB_imbuf.h"
12 #include "IMB_imbuf_types.h"
13 
14 namespace blender::compositor {
15 
17 {
19  movie_clip_ = nullptr;
20  framenumber_ = 0;
21  tracking_object_[0] = 0;
22  flags_.complex = true;
23  cached_triangulation_ = nullptr;
24 }
25 
27 {
28  init_mutex();
31  if (movie_clip_) {
33  }
34  }
35  else {
36  cached_triangulation_ = nullptr;
37  }
38 }
39 
41 {
44 
45  if (triangulation->triangulated_points) {
46  MEM_freeN(triangulation->triangulated_points);
47  }
48 
49  if (triangulation->triangles) {
50  MEM_freeN(triangulation->triangles);
51  }
52 
53  if (triangulation->triangles_AABB) {
54  MEM_freeN(triangulation->triangles_AABB);
55  }
56 
58 
59  cached_triangulation_ = nullptr;
60  }
61 }
62 
64 {
66  TriangulationData *triangulation;
67  MovieTracking *tracking = &movie_clip_->tracking;
68  MovieTrackingTrack *track;
69  VoronoiSite *sites, *site;
70  ImBuf *ibuf;
71  ListBase *tracksbase;
72  ListBase edges = {nullptr, nullptr};
73  int sites_total;
74  int i;
75  int width = this->get_width();
76  int height = this->get_height();
78 
79  if (tracking_object_[0]) {
81 
82  if (!object) {
83  return nullptr;
84  }
85 
86  tracksbase = BKE_tracking_object_get_tracks(tracking, object);
87  }
88  else {
89  tracksbase = BKE_tracking_get_active_tracks(tracking);
90  }
91 
92  /* count sites */
93  for (track = (MovieTrackingTrack *)tracksbase->first, sites_total = 0; track;
94  track = track->next) {
95  MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_frame);
96  float pos[2];
97 
98  if (marker->flag & MARKER_DISABLED) {
99  continue;
100  }
101 
102  add_v2_v2v2(pos, marker->pos, track->offset);
103 
104  if (!IN_RANGE_INCL(pos[0], 0.0f, 1.0f) || !IN_RANGE_INCL(pos[1], 0.0f, 1.0f)) {
105  continue;
106  }
107 
108  sites_total++;
109  }
110 
111  if (!sites_total) {
112  return nullptr;
113  }
114 
115  BKE_movieclip_user_set_frame(&user, clip_frame);
116  ibuf = BKE_movieclip_get_ibuf(movie_clip_, &user);
117 
118  if (!ibuf) {
119  return nullptr;
120  }
121 
122  triangulation = MEM_cnew<TriangulationData>("keying screen triangulation data");
123 
124  sites = (VoronoiSite *)MEM_callocN(sizeof(VoronoiSite) * sites_total,
125  "keyingscreen voronoi sites");
126  track = (MovieTrackingTrack *)tracksbase->first;
127  for (track = (MovieTrackingTrack *)tracksbase->first, site = sites; track; track = track->next) {
128  MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_frame);
129  ImBuf *pattern_ibuf;
130  int j;
131  float pos[2];
132 
133  if (marker->flag & MARKER_DISABLED) {
134  continue;
135  }
136 
137  add_v2_v2v2(pos, marker->pos, track->offset);
138 
139  if (!IN_RANGE_INCL(pos[0], 0.0f, 1.0f) || !IN_RANGE_INCL(pos[1], 0.0f, 1.0f)) {
140  continue;
141  }
142 
143  pattern_ibuf = BKE_tracking_get_pattern_imbuf(ibuf, track, marker, true, false);
144 
145  zero_v3(site->color);
146 
147  if (pattern_ibuf) {
148  for (j = 0; j < pattern_ibuf->x * pattern_ibuf->y; j++) {
149  if (pattern_ibuf->rect_float) {
150  add_v3_v3(site->color, &pattern_ibuf->rect_float[4 * j]);
151  }
152  else {
153  unsigned char *rrgb = (unsigned char *)pattern_ibuf->rect;
154 
155  site->color[0] += srgb_to_linearrgb((float)rrgb[4 * j + 0] / 255.0f);
156  site->color[1] += srgb_to_linearrgb((float)rrgb[4 * j + 1] / 255.0f);
157  site->color[2] += srgb_to_linearrgb((float)rrgb[4 * j + 2] / 255.0f);
158  }
159  }
160 
161  mul_v3_fl(site->color, 1.0f / (pattern_ibuf->x * pattern_ibuf->y));
162  IMB_freeImBuf(pattern_ibuf);
163  }
164 
165  site->co[0] = pos[0] * width;
166  site->co[1] = pos[1] * height;
167 
168  site++;
169  }
170 
171  IMB_freeImBuf(ibuf);
172 
173  BLI_voronoi_compute(sites, sites_total, width, height, &edges);
174 
176  sites_total,
177  &edges,
178  width,
179  height,
180  &triangulation->triangulated_points,
181  &triangulation->triangulated_points_total,
182  &triangulation->triangles,
183  &triangulation->triangles_total);
184 
185  MEM_freeN(sites);
186  BLI_freelistN(&edges);
187 
188  if (triangulation->triangles_total) {
189  rcti *rect;
190  rect = triangulation->triangles_AABB = (rcti *)MEM_callocN(
191  sizeof(rcti) * triangulation->triangles_total, "voronoi triangulation AABB");
192 
193  for (i = 0; i < triangulation->triangles_total; i++, rect++) {
194  int *triangle = triangulation->triangles[i];
195  VoronoiTriangulationPoint *a = &triangulation->triangulated_points[triangle[0]],
196  *b = &triangulation->triangulated_points[triangle[1]],
197  *c = &triangulation->triangulated_points[triangle[2]];
198 
199  float min[2], max[2];
200 
201  INIT_MINMAX2(min, max);
202 
203  minmax_v2v2_v2(min, max, a->co);
204  minmax_v2v2_v2(min, max, b->co);
205  minmax_v2v2_v2(min, max, c->co);
206 
207  rect->xmin = (int)min[0];
208  rect->ymin = (int)min[1];
209 
210  rect->xmax = (int)max[0] + 1;
211  rect->ymax = (int)max[1] + 1;
212  }
213  }
214 
215  return triangulation;
216 }
217 
218 KeyingScreenOperation::TileData *KeyingScreenOperation::triangulate(const rcti *rect)
219 {
220  TileData *tile_data;
221  TriangulationData *triangulation;
222  int triangles_allocated = 0;
223  int chunk_size = 20;
224  int i;
225 
226  triangulation = cached_triangulation_;
227 
228  if (!triangulation) {
229  return nullptr;
230  }
231 
232  tile_data = MEM_cnew<TileData>("keying screen tile data");
233 
234  for (i = 0; i < triangulation->triangles_total; i++) {
235  if (BLI_rcti_isect(rect, &triangulation->triangles_AABB[i], nullptr)) {
236  tile_data->triangles_total++;
237 
238  if (tile_data->triangles_total > triangles_allocated) {
239  if (!tile_data->triangles) {
240  tile_data->triangles = (int *)MEM_mallocN(sizeof(int) * chunk_size,
241  "keying screen tile triangles chunk");
242  }
243  else {
244  tile_data->triangles = (int *)MEM_reallocN(
245  tile_data->triangles, sizeof(int) * (triangles_allocated + chunk_size));
246  }
247 
248  triangles_allocated += chunk_size;
249  }
250 
251  tile_data->triangles[tile_data->triangles_total - 1] = i;
252  }
253  }
254 
255  return tile_data;
256 }
257 
259 {
260  if (movie_clip_ == nullptr) {
261  return nullptr;
262  }
263 
264  if (!cached_triangulation_) {
265  lock_mutex();
266  if (cached_triangulation_ == nullptr) {
268  }
269  unlock_mutex();
270  }
271 
272  return triangulate(rect);
273 }
274 
276 {
277  TileData *tile_data = (TileData *)data;
278 
279  if (tile_data->triangles) {
280  MEM_freeN(tile_data->triangles);
281  }
282 
283  MEM_freeN(tile_data);
284 }
285 
286 void KeyingScreenOperation::determine_canvas(const rcti &preferred_area, rcti &r_area)
287 {
288  r_area = COM_AREA_NONE;
289 
290  if (movie_clip_) {
292  int width, height;
294 
295  BKE_movieclip_user_set_frame(&user, clip_frame);
297  r_area = preferred_area;
298  r_area.xmax = r_area.xmin + width;
299  r_area.ymax = r_area.ymin + height;
300  }
301 }
302 
303 void KeyingScreenOperation::execute_pixel(float output[4], int x, int y, void *data)
304 {
305  output[0] = 0.0f;
306  output[1] = 0.0f;
307  output[2] = 0.0f;
308  output[3] = 1.0f;
309 
310  if (movie_clip_ && data) {
311  TriangulationData *triangulation = cached_triangulation_;
312  TileData *tile_data = (TileData *)data;
313  int i;
314  float co[2] = {(float)x, (float)y};
315 
316  for (i = 0; i < tile_data->triangles_total; i++) {
317  int triangle_idx = tile_data->triangles[i];
318  rcti *rect = &triangulation->triangles_AABB[triangle_idx];
319 
320  if (IN_RANGE_INCL(x, rect->xmin, rect->xmax) && IN_RANGE_INCL(y, rect->ymin, rect->ymax)) {
321  int *triangle = triangulation->triangles[triangle_idx];
322  VoronoiTriangulationPoint *a = &triangulation->triangulated_points[triangle[0]],
323  *b = &triangulation->triangulated_points[triangle[1]],
324  *c = &triangulation->triangulated_points[triangle[2]];
325  float w[3];
326 
327  if (barycentric_coords_v2(a->co, b->co, c->co, co, w)) {
329  output[0] = a->color[0] * w[0] + b->color[0] * w[1] + c->color[0] * w[2];
330  output[1] = a->color[1] * w[0] + b->color[1] * w[1] + c->color[1] * w[2];
331  output[2] = a->color[2] * w[0] + b->color[2] * w[1] + c->color[2] * w[2];
332 
333  break;
334  }
335  }
336  }
337  }
338  }
339 }
340 
342  const rcti &area,
344 {
345  if (movie_clip_ == nullptr) {
346  output->fill(area, COM_COLOR_BLACK);
347  return;
348  }
349 
350  TileData *tri_area = this->triangulate(&area);
351  BLI_assert(tri_area != nullptr);
352 
353  const int *triangles = tri_area->triangles;
354  const int num_triangles = tri_area->triangles_total;
355  const TriangulationData *triangulation = cached_triangulation_;
356  for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
357  copy_v4_v4(it.out, COM_COLOR_BLACK);
358 
359  const float co[2] = {(float)it.x, (float)it.y};
360  for (int i = 0; i < num_triangles; i++) {
361  const int triangle_idx = triangles[i];
362  const rcti *rect = &triangulation->triangles_AABB[triangle_idx];
363 
364  if (!BLI_rcti_isect_pt(rect, it.x, it.y)) {
365  continue;
366  }
367 
368  const int *triangle = triangulation->triangles[triangle_idx];
369  const VoronoiTriangulationPoint &a = triangulation->triangulated_points[triangle[0]];
370  const VoronoiTriangulationPoint &b = triangulation->triangulated_points[triangle[1]];
371  const VoronoiTriangulationPoint &c = triangulation->triangulated_points[triangle[2]];
372 
373  float w[3];
374  if (!barycentric_coords_v2(a.co, b.co, c.co, co, w)) {
375  continue;
376  }
377 
379  it.out[0] = a.color[0] * w[0] + b.color[0] * w[1] + c.color[0] * w[2];
380  it.out[1] = a.color[1] * w[0] + b.color[1] * w[1] + c.color[1] * w[2];
381  it.out[2] = a.color[2] * w[0] + b.color[2] * w[1] + c.color[2] * w[2];
382  break;
383  }
384  }
385  }
386 
387  if (tri_area->triangles) {
388  MEM_freeN(tri_area->triangles);
389  }
390 
391  MEM_freeN(tri_area);
392 }
393 
394 } // namespace blender::compositor
typedef float(TangentPoint)[2]
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)
Definition: movieclip.c:1614
void BKE_movieclip_get_size(struct MovieClip *clip, struct MovieClipUser *user, int *width, int *height)
Definition: movieclip.c:1520
struct ImBuf * BKE_movieclip_get_ibuf(struct MovieClip *clip, struct MovieClipUser *user)
Definition: movieclip.c:1329
struct ImBuf * BKE_tracking_get_pattern_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, bool anchored, bool disable_channels)
Definition: tracking.c:2722
struct ListBase * BKE_tracking_get_active_tracks(struct MovieTracking *tracking)
Definition: tracking.c:346
struct MovieTrackingObject * BKE_tracking_object_get_named(struct MovieTracking *tracking, const char *name)
Definition: tracking.c:2077
struct ListBase * BKE_tracking_object_get_tracks(struct MovieTracking *tracking, struct MovieTrackingObject *object)
Definition: tracking.c:2112
struct MovieTrackingMarker * BKE_tracking_marker_get(struct MovieTrackingTrack *track, int framenr)
Definition: tracking.c:1424
#define BLI_assert(a)
Definition: BLI_assert.h:46
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
float srgb_to_linearrgb(float c)
Definition: math_color.c:403
int barycentric_inside_triangle_v2(const float w[3])
Definition: math_geom.c:3663
bool barycentric_coords_v2(const float v1[2], const float v2[2], const float v3[2], const float co[2], float w[3])
Definition: math_geom.c:3676
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void mul_v3_fl(float r[3], float f)
void minmax_v2v2_v2(float min[2], float max[2], const float vec[2])
Definition: math_vector.c:890
MINLINE void add_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
bool BLI_rcti_isect_pt(const struct rcti *rect, int x, int y)
bool BLI_rcti_isect(const struct rcti *src1, const struct rcti *src2, struct rcti *dest)
#define INIT_MINMAX2(min, max)
#define IN_RANGE_INCL(a, b, c)
void BLI_voronoi_triangulate(const VoronoiSite *sites, int sites_total, struct ListBase *edges, int width, int height, VoronoiTriangulationPoint **r_triangulated_points, int *r_triangulated_points_total, int(**r_triangles)[3], int *r_triangles_total)
Definition: voronoi_2d.c:776
void BLI_voronoi_compute(const VoronoiSite *sites, int sites_total, int width, int height, struct ListBase *edges)
Definition: voronoi_2d.c:651
#define DNA_struct_default_get(struct_name)
Definition: DNA_defaults.h:29
@ MARKER_DISABLED
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
Contains defines and structs used throughout the imbuf module.
#define MEM_reallocN(vmemh, len)
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
void update_memory_buffer_partial(MemoryBuffer *output, const rcti &area, Span< MemoryBuffer * > inputs) override
void deinitialize_tile_data(rcti *rect, void *data) override
void determine_canvas(const rcti &preferred_area, rcti &r_area) override
struct blender::compositor::KeyingScreenOperation::TileData TileData
struct blender::compositor::KeyingScreenOperation::TriangulationData TriangulationData
void execute_pixel(float output[4], int x, int y, void *data) override
calculate a single pixel
a MemoryBuffer contains access to the data of a chunk
void add_output_socket(DataType datatype)
uint pos
void IMB_freeImBuf(ImBuf *UNUSED(ibuf))
ccl_global KernelShaderEvalInput ccl_global float * output
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
static unsigned c
Definition: RandGen.cpp:83
static unsigned a[3]
Definition: RandGen.cpp:78
static void area(int d1, int d2, int e1, int e2, float weights[2])
typename BuffersIteratorBuilder< T >::Iterator BuffersIterator
constexpr rcti COM_AREA_NONE
Definition: COM_defines.h:112
constexpr float COM_COLOR_BLACK[4]
Definition: COM_defines.h:66
static const int chunk_size
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
static bNodeSocketTemplate inputs[]
#define min(a, b)
Definition: sort.c:35
unsigned int * rect
float * rect_float
void * first
Definition: DNA_listBase.h:31
struct MovieTracking tracking
struct MovieTrackingTrack * next
float co[2]
float color[3]
int ymin
Definition: DNA_vec_types.h:64
int ymax
Definition: DNA_vec_types.h:64
int xmin
Definition: DNA_vec_types.h:63
int xmax
Definition: DNA_vec_types.h:63
float max