Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2012-05-29 18:00:47 +0400
committerSergey Sharybin <sergey.vfx@gmail.com>2012-05-29 18:00:47 +0400
commit876665ac25a731bcf5937d4e06de7337d6e8af6a (patch)
treef8cf21ac7f6a3bbfeebe3a6ee159769062a3f656 /source/blender/nodes
parentf5917b15b5f603f0b9b567915b4aa93320d6dc54 (diff)
Initial commit of new keying nodes
First node is called Keying Screen (Add -> Matte -> Keying Screen) and it's aimed to resolve issues with gradients on green screens by producing image with gradient which is later used as an input for screen color in keying nodes. This node gets motion tracks from given movie clip and trackign object and uses them to define color and position of points of gradient: for position marker's position on current frame is sued, for color average color of pattern area is used. Gradient is calculating in the following way: - On first step voronoi diagram is creating for given tracks. - On second step triangulation of this diagram happens by connecting sites to edges which defines area this site belongs to. - On third step gradient filling of this triangles happens. One of triangle vertices is colored with average track color, two rest vertoces are colored with average color between two neighbor sites. Current pixel's color in triangle is calculating as linear combination of vertices colors and barycentric coordinates of this pixel. This node is implemented for both tile and legacy compositor systems. Second node is basically a combination of several existing nodes to make keying more straighforward and reduce spagetti mess in the compositor, but it also ships some fresh approaches calculating matte which seems to be working better for not actually green screens. This node supports: - Chroma preblur - Dispilling - Clip white/black - Dilate/Erode - Matte post blur This node doesn't support chroma pre-blur for legacy compositor (yet). There're still lots of stuff to be improved here, but this nodes night already be used i think. Some details might be found on this wiki page: http://wiki.blender.org/index.php/User:Nazg-gul/Keying This patch also contains some currently unused code from color math module, but it was used for tests and might be used for tests in the future. Think it's ok to have it in branch at least.
Diffstat (limited to 'source/blender/nodes')
-rw-r--r--source/blender/nodes/CMakeLists.txt2
-rw-r--r--source/blender/nodes/NOD_composite.h3
-rw-r--r--source/blender/nodes/composite/node_composite_util.c16
-rw-r--r--source/blender/nodes/composite/node_composite_util.h4
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_blur.c22
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_dilate.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_keying.c218
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_keyingscreen.c202
8 files changed, 463 insertions, 12 deletions
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 5e36f90f217..d07d00a436d 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -76,6 +76,8 @@ set(SRC
composite/nodes/node_composite_idMask.c
composite/nodes/node_composite_image.c
composite/nodes/node_composite_invert.c
+ composite/nodes/node_composite_keying.c
+ composite/nodes/node_composite_keyingscreen.c
composite/nodes/node_composite_lensdist.c
composite/nodes/node_composite_levels.c
composite/nodes/node_composite_lummaMatte.c
diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h
index f850ea91f12..efa107a2223 100644
--- a/source/blender/nodes/NOD_composite.h
+++ b/source/blender/nodes/NOD_composite.h
@@ -81,6 +81,7 @@ void register_node_type_cmp_bilateralblur(struct bNodeTreeType *ttype);
void register_node_type_cmp_vecblur(struct bNodeTreeType *ttype);
void register_node_type_cmp_dilateerode(struct bNodeTreeType *ttype);
void register_node_type_cmp_defocus(struct bNodeTreeType *ttype);
+void register_node_type_cmp_denoise(struct bNodeTreeType *ttype);
void register_node_type_cmp_valtorgb(struct bNodeTreeType *ttype);
void register_node_type_cmp_rgbtobw(struct bNodeTreeType *ttype);
@@ -105,6 +106,8 @@ void register_node_type_cmp_channel_matte(struct bNodeTreeType *ttype);
void register_node_type_cmp_color_spill(struct bNodeTreeType *ttype);
void register_node_type_cmp_luma_matte(struct bNodeTreeType *ttype);
void register_node_type_cmp_doubleedgemask(struct bNodeTreeType *ttype);
+void register_node_type_cmp_keyingscreen(struct bNodeTreeType *ttype);
+void register_node_type_cmp_keying(struct bNodeTreeType *ttype);
void register_node_type_cmp_translate(struct bNodeTreeType *ttype);
void register_node_type_cmp_rotate(struct bNodeTreeType *ttype);
diff --git a/source/blender/nodes/composite/node_composite_util.c b/source/blender/nodes/composite/node_composite_util.c
index 3806cf4543a..ff223ac83cf 100644
--- a/source/blender/nodes/composite/node_composite_util.c
+++ b/source/blender/nodes/composite/node_composite_util.c
@@ -568,6 +568,22 @@ CompBuf *valbuf_from_rgbabuf(CompBuf *cbuf, int channel)
return valbuf;
}
+void valbuf_to_rgbabuf(CompBuf *valbuf, CompBuf *cbuf, int channel)
+{
+ float *valf, *rectf;
+ int tot;
+
+ valf= valbuf->rect;
+
+ /* defaults to returning alpha channel */
+ if ((channel < CHAN_R) || (channel > CHAN_A)) channel = CHAN_A;
+
+ rectf = cbuf->rect + channel;
+
+ for (tot= cbuf->x*cbuf->y; tot>0; tot--, valf++, rectf+=4)
+ *rectf = *valf;
+}
+
static CompBuf *generate_procedural_preview(CompBuf *cbuf, int newx, int newy)
{
CompBuf *outbuf;
diff --git a/source/blender/nodes/composite/node_composite_util.h b/source/blender/nodes/composite/node_composite_util.h
index 51f047b94ff..18dac5dc5c1 100644
--- a/source/blender/nodes/composite/node_composite_util.h
+++ b/source/blender/nodes/composite/node_composite_util.h
@@ -155,6 +155,7 @@ void composit4_pixel_processor(bNode *node, CompBuf *out, CompBuf *src1_buf, flo
int src1_type, int fac1_type, int src2_type, int fac2_type);
CompBuf *valbuf_from_rgbabuf(CompBuf *cbuf, int channel);
+void valbuf_to_rgbabuf(CompBuf *valbuf, CompBuf *cbuf, int channel);
void generate_preview(void *data, bNode *node, CompBuf *stackbuf);
void do_copy_rgba(bNode *node, float *out, float *in);
@@ -220,6 +221,9 @@ void IIR_gauss(CompBuf* src, float sigma, int chan, int xy);
#define CMP_SCALE_MAX 12000
CompBuf* node_composit_transform(CompBuf *cbuf, float x, float y, float angle, float scale, int filter_type);
+void node_composit_blur_single_image(bNode *node, int filtertype, int sizex, int sizey, CompBuf *new, CompBuf *img, float scale);
+void node_composite_morpho_dilate(CompBuf *cbuf);
+void node_composite_morpho_erode(CompBuf *cbuf);
float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc);
#endif
diff --git a/source/blender/nodes/composite/nodes/node_composite_blur.c b/source/blender/nodes/composite/nodes/node_composite_blur.c
index d19ea3f202f..9afdd6eadb7 100644
--- a/source/blender/nodes/composite/nodes/node_composite_blur.c
+++ b/source/blender/nodes/composite/nodes/node_composite_blur.c
@@ -85,9 +85,8 @@ static float *make_bloomtab(int rad)
}
/* both input images of same type, either 4 or 1 channel */
-static void blur_single_image(bNode *node, CompBuf *new, CompBuf *img, float scale)
+void node_composit_blur_single_image(bNode *node, int filtertype, int sizex, int sizey, CompBuf *new, CompBuf *img, float scale)
{
- NodeBlurData *nbd= node->storage;
CompBuf *work;
register float sum, val;
float rval, gval, bval, aval;
@@ -101,17 +100,17 @@ static void blur_single_image(bNode *node, CompBuf *new, CompBuf *img, float sca
work= alloc_compbuf(imgx, imgy, img->type, 1); /* allocs */
/* horizontal */
- if (nbd->sizex == 0) {
+ if (sizex == 0) {
memcpy(work->rect, img->rect, sizeof(float) * img->type * imgx * imgy);
}
else {
- rad = scale*(float)nbd->sizex;
+ rad = scale*(float)sizex;
if (rad>imgx/2)
rad= imgx/2;
else if (rad<1)
rad= 1;
- gausstab= make_gausstab(nbd->filtertype, rad);
+ gausstab= make_gausstab(filtertype, rad);
gausstabcent= gausstab+rad;
for (y = 0; y < imgy; y++) {
@@ -152,17 +151,17 @@ static void blur_single_image(bNode *node, CompBuf *new, CompBuf *img, float sca
MEM_freeN(gausstab);
}
- if (nbd->sizey == 0) {
+ if (sizey == 0) {
memcpy(new->rect, work->rect, sizeof(float) * img->type * imgx * imgy);
}
else {
- rad = scale*(float)nbd->sizey;
+ rad = scale*(float)sizey;
if (rad>imgy/2)
rad= imgy/2;
else if (rad<1)
rad= 1;
- gausstab= make_gausstab(nbd->filtertype, rad);
+ gausstab= make_gausstab(filtertype, rad);
gausstabcent= gausstab+rad;
bigstep = pix*imgx;
@@ -207,6 +206,13 @@ static void blur_single_image(bNode *node, CompBuf *new, CompBuf *img, float sca
free_compbuf(work);
}
+static void blur_single_image(bNode *node, CompBuf *new, CompBuf *img, float scale)
+{
+ NodeBlurData *nbd = node->storage;
+
+ node_composit_blur_single_image(node, nbd->filtertype, nbd->sizex, nbd->sizey, new, img, scale);
+}
+
/* reference has to be mapped 0-1, and equal in size */
static void bloom_with_reference(CompBuf *new, CompBuf *img, CompBuf *UNUSED(ref), float UNUSED(fac), NodeBlurData *nbd)
{
diff --git a/source/blender/nodes/composite/nodes/node_composite_dilate.c b/source/blender/nodes/composite/nodes/node_composite_dilate.c
index ee857dd0007..1dc56fd4279 100644
--- a/source/blender/nodes/composite/nodes/node_composite_dilate.c
+++ b/source/blender/nodes/composite/nodes/node_composite_dilate.c
@@ -44,7 +44,7 @@ static bNodeSocketTemplate cmp_node_dilateerode_out[]= {
{ -1, 0, "" }
};
-static void morpho_dilate(CompBuf *cbuf)
+void node_composite_morpho_dilate(CompBuf *cbuf)
{
int x, y;
float *p, *rectf = cbuf->rect;
@@ -78,7 +78,7 @@ static void morpho_dilate(CompBuf *cbuf)
}
}
-static void morpho_erode(CompBuf *cbuf)
+void node_composite_morpho_erode(CompBuf *cbuf)
{
int x, y;
float *p, *rectf = cbuf->rect;
@@ -133,11 +133,11 @@ static void node_composit_exec_dilateerode(void *UNUSED(data), bNode *node, bNod
if (node->custom2 > 0) { // positive, dilate
for (i = 0; i < node->custom2; i++)
- morpho_dilate(stackbuf);
+ node_composite_morpho_dilate(stackbuf);
}
else if (node->custom2 < 0) { // negative, erode
for (i = 0; i > node->custom2; i--)
- morpho_erode(stackbuf);
+ node_composite_morpho_erode(stackbuf);
}
if (cbuf!=in[0]->data)
diff --git a/source/blender/nodes/composite/nodes/node_composite_keying.c b/source/blender/nodes/composite/nodes/node_composite_keying.c
new file mode 100644
index 00000000000..8e6fd86eae5
--- /dev/null
+++ b/source/blender/nodes/composite/nodes/node_composite_keying.c
@@ -0,0 +1,218 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/nodes/composite/nodes/node_composite_keying.c
+ * \ingroup cmpnodes
+ */
+
+#include "BLF_translation.h"
+
+#include "DNA_movieclip_types.h"
+
+#include "BKE_movieclip.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math_base.h"
+#include "BLI_math_color.h"
+#include "BLI_voronoi.h"
+
+#include "node_composite_util.h"
+
+/* **************** Translate ******************** */
+
+static bNodeSocketTemplate cmp_node_keying_in[] = {
+ { SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 1, "Key Color", 1.0f, 1.0f, 1.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static bNodeSocketTemplate cmp_node_keying_out[] = {
+ { SOCK_RGBA, 0, "Image"},
+ { SOCK_FLOAT, 0, "Matte"},
+ { -1, 0, "" }
+};
+
+static int get_pixel_primary_channel(float *pixel)
+{
+ float max_value = MAX3(pixel[0], pixel[1], pixel[2]);
+
+ if (max_value == pixel[0])
+ return 0;
+ else if (max_value == pixel[1])
+ return 1;
+
+ return 2;
+}
+
+static float get_pixel_saturation(float *pixel, float screen_balance)
+{
+ float min = MIN3(pixel[0], pixel[1], pixel[2]);
+ float max = MAX3(pixel[0], pixel[1], pixel[2]);
+ float mid = pixel[0] + pixel[1] + pixel[2] - min - max;
+ float val = (1.0f - screen_balance) * min + screen_balance * mid;
+
+ return max - val;
+}
+
+static void despil_pixel(float *out, float *pixel, float *screen, float screen_gain)
+{
+ int screen_primary_channel = get_pixel_primary_channel(screen);
+ float average_value, amount;
+
+ average_value = (pixel[0] + pixel[1] + pixel[2] - pixel[screen_primary_channel]) / 2.0f;
+ amount = pixel[screen_primary_channel] - average_value;
+
+ if (screen_gain * amount > 0) {
+ out[screen_primary_channel] = pixel[screen_primary_channel] - screen_gain * amount;
+ }
+}
+
+static void do_key(bNode *node, float *out, float *pixel, float *screen)
+{
+ NodeKeyingData *data = node->storage;
+
+ float screen_balance = 0.5f;
+ float dispill_factor = data->dispill_factor;
+ float clip_black = data->clip_black;
+ float clip_white = data->clip_white;
+
+ float saturation = get_pixel_saturation(pixel, screen_balance);
+ float screen_saturation = get_pixel_saturation(screen, screen_balance);
+ int primary_channel = get_pixel_primary_channel(pixel);
+ int screen_primary_channel = get_pixel_primary_channel(screen);
+
+ if (primary_channel != screen_primary_channel) {
+ /* different main channel means pixel is on foreground,
+ * but screen color still need to be despilled from it */
+ despil_pixel(out, pixel, screen, dispill_factor);
+ out[3] = 1.0f;
+ }
+ else if (saturation >= screen_saturation) {
+ /* saturation of main channel is more than screen, definitely a background */
+ out[0] = 0.0f;
+ out[1] = 0.0f;
+ out[2] = 0.0f;
+ out[3] = 0.0f;
+ }
+ else {
+ float distance;
+
+ despil_pixel(out, pixel, screen, dispill_factor);
+
+ distance = 1.0f - saturation / screen_saturation;
+
+ out[3] = distance;
+
+ if (out[3] < clip_black)
+ out[3] = 0.0f;
+ else if (out[3] >= clip_white)
+ out[3] = 1.0f;
+ else
+ out[3] = (out[3] - clip_black) / (clip_white - clip_black);
+ }
+}
+
+static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+ if (in[0]->data) {
+ NodeKeyingData *keying_data = node->storage;
+ CompBuf *cbuf = typecheck_compbuf(in[0]->data, CB_RGBA);
+ CompBuf *keybuf, *mattebuf;
+
+ keybuf = dupalloc_compbuf(cbuf);
+
+ /* single color is used for screen detection */
+ composit2_pixel_processor(node, keybuf, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_key, CB_RGBA, CB_VAL);
+
+ /* create a matte from alpha channel */
+ mattebuf = valbuf_from_rgbabuf(keybuf, CHAN_A);
+
+ /* apply dilate/erode if needed */
+ if (keying_data->dilate_distance != 0) {
+ int i;
+
+ if (keying_data->dilate_distance > 0) {
+ for (i = 0; i < keying_data->dilate_distance; i++)
+ node_composite_morpho_dilate(mattebuf);
+ }
+ else {
+ for (i = 0; i < -keying_data->dilate_distance; i++)
+ node_composite_morpho_erode(mattebuf);
+ }
+ }
+
+ if (keying_data->blur_post > 0.0f) {
+ /* post-blur of matte */
+ CompBuf *newmatte = alloc_compbuf(mattebuf->x, mattebuf->y, mattebuf->type, TRUE);
+ int size = keying_data->blur_post;
+
+ node_composit_blur_single_image(node, R_FILTER_BOX, size, size, newmatte, mattebuf, 1.0f);
+
+ free_compbuf(mattebuf);
+ mattebuf = newmatte;
+
+ /* apply blurred matte on output buffer alpha */
+ valbuf_to_rgbabuf(mattebuf, keybuf, CHAN_A);
+ }
+
+ out[0]->data = keybuf;
+ out[1]->data = mattebuf;
+
+ generate_preview(data, node, keybuf);
+
+ if (cbuf!=in[0]->data)
+ free_compbuf(cbuf);
+ }
+}
+
+static void node_composit_init_keying(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp))
+{
+ NodeKeyingData *data;
+
+ data = MEM_callocN(sizeof(NodeKeyingData), "node keying data");
+
+ data->dispill_factor = 1.0f;
+ data->clip_black = 0.0f;
+ data->clip_white = 1.0f;
+
+ node->storage = data;
+}
+
+void register_node_type_cmp_keying(bNodeTreeType *ttype)
+{
+ static bNodeType ntype;
+
+ node_type_base(ttype, &ntype, CMP_NODE_KEYING, "Keying", NODE_CLASS_MATTE, NODE_OPTIONS);
+ node_type_socket_templates(&ntype, cmp_node_keying_in, cmp_node_keying_out);
+ node_type_size(&ntype, 140, 100, 320);
+ node_type_init(&ntype, node_composit_init_keying);
+ node_type_storage(&ntype, "NodeKeyingData", node_free_standard_storage, node_copy_standard_storage);
+ node_type_exec(&ntype, exec);
+
+ nodeRegisterType(ttype, &ntype);
+}
diff --git a/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c b/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c
new file mode 100644
index 00000000000..5cbaf4ae2ba
--- /dev/null
+++ b/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c
@@ -0,0 +1,202 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/nodes/composite/nodes/node_composite_keyingscreen.c
+ * \ingroup cmpnodes
+ */
+
+#include "BLF_translation.h"
+
+#include "DNA_movieclip_types.h"
+
+#include "BKE_movieclip.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math_base.h"
+#include "BLI_math_color.h"
+#include "BLI_voronoi.h"
+
+#include "node_composite_util.h"
+
+/* **************** Translate ******************** */
+
+static bNodeSocketTemplate cmp_node_keyingscreen_out[] = {
+ { SOCK_RGBA, 0, "Screen"},
+ { -1, 0, "" }
+};
+
+
+static void compute_gradient_screen(RenderData *rd, NodeKeyingScreenData *keyingscreen_data, MovieClip *clip, CompBuf *screenbuf)
+{
+ MovieClipUser user = {0};
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingTrack *track;
+ VoronoiTriangulationPoint *triangulated_points;
+ VoronoiSite *sites;
+ ImBuf *ibuf;
+ ListBase *tracksbase;
+ ListBase edges = {NULL, NULL};
+ int sites_total, triangulated_points_total, triangles_total;
+ int (*triangles)[3];
+ int i, x, y;
+ float *rect = screenbuf->rect;
+
+ if (keyingscreen_data->tracking_object[0]) {
+ MovieTrackingObject *object = BKE_tracking_named_object(tracking, keyingscreen_data->tracking_object);
+
+ if (!object)
+ return;
+
+ tracksbase = BKE_tracking_object_tracks(tracking, object);
+ }
+ else
+ tracksbase = BKE_tracking_get_tracks(tracking);
+
+ sites_total = BLI_countlist(tracksbase);
+
+ if (!sites_total)
+ return;
+
+ BKE_movieclip_user_set_frame(&user, rd->cfra);
+ ibuf = BKE_movieclip_get_ibuf(clip, &user);
+
+ sites = MEM_callocN(sizeof(VoronoiSite) * sites_total, "keyingscreen voronoi sites");
+ track = tracksbase->first;
+ i = 0;
+ while (track) {
+ VoronoiSite *site = &sites[i];
+ MovieTrackingMarker *marker = BKE_tracking_get_marker(track, rd->cfra);
+ ImBuf *pattern_ibuf = BKE_tracking_get_pattern_imbuf(ibuf, track, marker, 0, FALSE, NULL, NULL);
+ int j;
+
+ zero_v3(site->color);
+ for (j = 0; j < pattern_ibuf->x * pattern_ibuf->y; j++) {
+ if (pattern_ibuf->rect_float) {
+ add_v3_v3(site->color, &pattern_ibuf->rect_float[4 * j]);
+ }
+ else {
+ unsigned char *rrgb = (unsigned char *)pattern_ibuf->rect;
+
+ site->color[0] += srgb_to_linearrgb((float)rrgb[4 * j + 0] / 255.0f);
+ site->color[1] += srgb_to_linearrgb((float)rrgb[4 * j + 1] / 255.0f);
+ site->color[2] += srgb_to_linearrgb((float)rrgb[4 * j + 2] / 255.0f);
+ }
+ }
+
+ mul_v3_fl(site->color, 1.0f / (pattern_ibuf->x * pattern_ibuf->y));
+ IMB_freeImBuf(pattern_ibuf);
+
+ site->co[0] = marker->pos[0] * screenbuf->x;
+ site->co[1] = marker->pos[1] * screenbuf->y;
+
+ track = track->next;
+ i++;
+ }
+
+ IMB_freeImBuf(ibuf);
+
+ BLI_voronoi_compute(sites, sites_total, screenbuf->x, screenbuf->y, &edges);
+
+ BLI_voronoi_triangulate(sites, sites_total, &edges, screenbuf->x, screenbuf->y,
+ &triangulated_points, &triangulated_points_total,
+ &triangles, &triangles_total);
+
+ for (y = 0; y < screenbuf->y; y++) {
+ for (x = 0; x < screenbuf->x; x++) {
+ int index = 4 * (y * screenbuf->x + x);
+
+ rect[index + 0] = rect[index + 1] = rect[index + 2] = 0.0f;
+ rect[index + 3] = 1.0f;
+
+ for (i = 0; i < triangles_total; i++) {
+ int *triangle = triangles[i];
+ VoronoiTriangulationPoint *a = &triangulated_points[triangle[0]],
+ *b = &triangulated_points[triangle[1]],
+ *c = &triangulated_points[triangle[2]];
+ float co[2] = {x, y}, w[3];
+
+ if (barycentric_coords_v2(a->co, b->co, c->co, co, w)) {
+ if (barycentric_inside_triangle_v2(w)) {
+ rect[index + 0] += a->color[0] * w[0] + b->color[0] * w[1] + c->color[0] * w[2];
+ rect[index + 1] += a->color[1] * w[0] + b->color[1] * w[1] + c->color[1] * w[2];
+ rect[index + 2] += a->color[2] * w[0] + b->color[2] * w[1] + c->color[2] * w[2];
+ }
+ }
+ }
+ }
+ }
+
+ MEM_freeN(triangulated_points);
+ MEM_freeN(triangles);
+ MEM_freeN(sites);
+ BLI_freelistN(&edges);
+}
+
+static void exec(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
+{
+ NodeKeyingScreenData *keyingscreen_data = node->storage;
+ RenderData *rd = data;
+ CompBuf *screenbuf = NULL;
+
+ if (node->id) {
+ MovieClip *clip = (MovieClip *) node->id;
+ MovieClipUser user = {0};
+ int width, height;
+
+ BKE_movieclip_user_set_frame(&user, rd->cfra);
+ BKE_movieclip_get_size(clip, &user, &width, &height);
+
+ screenbuf = alloc_compbuf(width, height, CB_RGBA, TRUE);
+ compute_gradient_screen(rd, keyingscreen_data, clip, screenbuf);
+ }
+
+ out[0]->data = screenbuf;
+}
+
+static void node_composit_init_keyingscreen(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp))
+{
+ NodeKeyingScreenData *data;
+
+ data = MEM_callocN(sizeof(NodeKeyingScreenData), "node keyingscreen data");
+
+ node->storage = data;
+}
+
+void register_node_type_cmp_keyingscreen(bNodeTreeType *ttype)
+{
+ static bNodeType ntype;
+
+ node_type_base(ttype, &ntype, CMP_NODE_KEYINGSCREEN, "Keying Screen", NODE_CLASS_MATTE, NODE_OPTIONS);
+ node_type_socket_templates(&ntype, NULL, cmp_node_keyingscreen_out);
+ node_type_size(&ntype, 140, 100, 320);
+ node_type_init(&ntype, node_composit_init_keyingscreen);
+ node_type_storage(&ntype, "NodeKeyingScreenData", node_free_standard_storage, node_copy_standard_storage);
+ node_type_exec(&ntype, exec);
+
+ nodeRegisterType(ttype, &ntype);
+}