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:
authorTon Roosendaal <ton@blender.org>2006-11-15 17:41:04 +0300
committerTon Roosendaal <ton@blender.org>2006-11-15 17:41:04 +0300
commit5d8efc975699ae5ca60aa2892d96dd3e361b9c1d (patch)
treef809fd11332107b9e204ad5a855884505a615abd
parentd6e96bd6059d264957a67f24fcce98b8de9c8d40 (diff)
Patch #2307, by Bob Holcomb
Loadsa new compo nodes, most added in new menu "Mattes". - Seperate into YCC - Combine YCC - Seperate into YUV - Combine YUV - (Chroma) Difference Matte - Chroma Key - Luminance Key - Color Spill correction Main problem is missing docs still... Bob is working on it, he'll also make tooltips for all buttons. Some UI things might change too, like more clear names.
-rw-r--r--source/blender/blenkernel/BKE_node.h14
-rw-r--r--source/blender/blenkernel/intern/node.c39
-rw-r--r--source/blender/blenkernel/intern/node_composite.c819
-rw-r--r--source/blender/blenlib/BLI_arithb.h31
-rw-r--r--source/blender/blenlib/intern/arithb.c58
-rw-r--r--source/blender/makesdna/DNA_node_types.h6
-rw-r--r--source/blender/src/drawnode.c145
-rw-r--r--source/blender/src/toolbox.c6
8 files changed, 1112 insertions, 6 deletions
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index ad9966636f1..c6da0b9af98 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -88,6 +88,7 @@ typedef struct bNodeType {
#define NODE_CLASS_GROUP 6
#define NODE_CLASS_FILE 7
#define NODE_CLASS_CONVERTOR 8
+#define NODE_CLASS_MATTE 9
/* ************** GENERIC API, TREES *************** */
@@ -229,10 +230,23 @@ void set_node_shader_lamp_loop(void (*lamp_loop_func)(struct ShadeInput *, str
#define CMP_NODE_ZCOMBINE 226
#define CMP_NODE_COMBRGBA 227
#define CMP_NODE_DILATEERODE 228
+
+#define CMP_NODE_SEPYCCA 231
+#define CMP_NODE_COMBYCCA 232
+#define CMP_NODE_SEPYUVA 233
+#define CMP_NODE_COMBYUVA 234
+#define CMP_NODE_DIFF_MATTE 235
+#define CMP_NODE_COLOR_SPILL 236
+#define CMP_NODE_CHROMA 237
+#define CMP_NODE_LUMA 238
+
+/* filter types */
+
#define CMP_NODE_ROTATE 229
#define CMP_NODE_SCALE 230
/* filter types, in custom1 */
+
#define CMP_FILT_SOFT 0
#define CMP_FILT_SHARP 1
#define CMP_FILT_LAPLACE 2
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index e220a1f6197..82613151113 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -809,6 +809,45 @@ bNode *nodeAddNodeType(bNodeTree *ntree, int type, bNodeTree *ngroup)
nif->sfra= G.scene->r.sfra;
nif->efra= G.scene->r.efra;
}
+ else if(type==CMP_NODE_DIFF_MATTE){
+ NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma");
+ node->storage= c;
+ c->t1= 0.01f;
+ c->t2= 0.01f;
+ c->t3= 0.01f;
+ c->fsize= 0.0f;
+ c->fstrength= 0.0f;
+ node->custom1= 1; /* RGB */
+ }
+ else if(type==CMP_NODE_COLOR_SPILL){
+ NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma");
+ node->storage=c;
+ c->t1= 0.0f;
+ c->t2= 0.0f;
+ c->t3= 0.0f;
+ c->fsize= 0.0f;
+ c->fstrength= 0.0f;
+ node->custom1= 1; /* red channel */
+ }
+ else if(type==CMP_NODE_CHROMA){
+ NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma");
+ node->storage= c;
+ c->t1= 0.0f;
+ c->t2= 0.0f;
+ c->t3= 0.0f;
+ c->fsize= 0.0f;
+ c->fstrength= 0.0f;
+ node->custom1= 1; /* green */
+ }
+ else if(type==CMP_NODE_LUMA){
+ NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma");
+ node->storage= c;
+ c->t1= 0.6f;
+ c->t2= 0.5f;
+ c->t3= 0.0f;
+ c->fsize= 0.0f;
+ c->fstrength= 0.0f;
+ }
}
return node;
diff --git a/source/blender/blenkernel/intern/node_composite.c b/source/blender/blenkernel/intern/node_composite.c
index 49166a1a131..61f9e464d46 100644
--- a/source/blender/blenkernel/intern/node_composite.c
+++ b/source/blender/blenkernel/intern/node_composite.c
@@ -557,7 +557,7 @@ static void node_composit_exec_viewer(void *data, bNode *node, bNodeStack **in,
ima->ibuf->rect_float= MEM_mallocN(4*rectx*recty*sizeof(float), "viewer rect");
/* now we combine the input with ibuf */
- cbuf= alloc_compbuf(rectx, recty, CB_RGBA, 0); // no alloc
+ cbuf= alloc_compbuf(rectx, recty, CB_RGBA, 0); /* no alloc*/
cbuf->rect= ima->ibuf->rect_float;
/* when no alpha, we can simply copy */
@@ -3107,6 +3107,813 @@ static bNodeType cmp_node_dilateerode= {
/* execfunc */ node_composit_exec_dilateerode
};
+
+/* **************** SEPARATE YUVA ******************** */
+static bNodeSocketType cmp_node_sepyuva_in[]= {
+ { SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+static bNodeSocketType cmp_node_sepyuva_out[]= {
+ { SOCK_VALUE, 0, "Y", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VALUE, 0, "U", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VALUE, 0, "V", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VALUE, 0, "A", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static void do_sepyuva(bNode *node, float *out, float *in)
+{
+ float y, u, v;
+
+ rgb_to_yuv(in[0], in[1], in[2], &y, &u, &v);
+
+ out[0]= y;
+ out[1]= u;
+ out[2]= v;
+ out[3]= in[3];
+}
+
+static void node_composit_exec_sepyuva(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+ /* stack order out: bw channels */
+ /* stack order in: col */
+
+ /* input no image? then only color operation */
+ if(in[0]->data==NULL) {
+ float y, u, v;
+
+ rgb_to_yuv(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2], &y, &u, &v);
+
+ out[0]->vec[0] = y;
+ out[1]->vec[0] = u;
+ out[2]->vec[0] = v;
+ out[3]->vec[0] = in[0]->vec[3];
+ }
+ else if ((out[0]->hasoutput) || (out[1]->hasoutput) || (out[2]->hasoutput) || (out[3]->hasoutput)) {
+ /* make output size of input image */
+ CompBuf *cbuf= in[0]->data;
+
+ CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs
+
+ /* convert the RGB stackbuf to an YUV representation */
+ composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_sepyuva, CB_RGBA);
+
+ /* separate each of those channels */
+ if(out[0]->hasoutput)
+ out[0]->data= valbuf_from_rgbabuf(stackbuf, CHAN_R);
+ if(out[1]->hasoutput)
+ out[1]->data= valbuf_from_rgbabuf(stackbuf, CHAN_G);
+ if(out[2]->hasoutput)
+ out[2]->data= valbuf_from_rgbabuf(stackbuf, CHAN_B);
+ if(out[3]->hasoutput)
+ out[3]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
+
+ free_compbuf(stackbuf);
+ }
+}
+
+static bNodeType cmp_node_sepyuva= {
+ /* type code */ CMP_NODE_SEPYUVA,
+ /* name */ "Separate YUVA",
+ /* width+range */ 80, 40, 140,
+ /* class+opts */ NODE_CLASS_CONVERTOR, 0,
+ /* input sock */ cmp_node_sepyuva_in,
+ /* output sock */ cmp_node_sepyuva_out,
+ /* storage */ "",
+ /* execfunc */ node_composit_exec_sepyuva
+};
+
+/* **************** SEPARATE YCCA ******************** */
+static bNodeSocketType cmp_node_sepycca_in[]= {
+ { SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+static bNodeSocketType cmp_node_sepycca_out[]= {
+ { SOCK_VALUE, 0, "Y", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VALUE, 0, "Cb", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VALUE, 0, "Cr", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VALUE, 0, "A", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static void do_sepycca(bNode *node, float *out, float *in)
+{
+ float y, cb, cr;
+
+ rgb_to_ycc(in[0], in[1], in[2], &y, &cb, &cr);
+
+ /*divided by 255 to normalize for viewing in */
+ out[0]= y/255.0;
+ out[1]= cb/255.0;
+ out[2]= cr/255.0;
+ out[3]= in[3];
+}
+
+static void node_composit_exec_sepycca(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+ /* input no image? then only color operation */
+ if(in[0]->data==NULL) {
+ float y, cb, cr;
+
+ rgb_to_ycc(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2], &y, &cb, &cr);
+
+ /*divided by 255 to normalize for viewing in */
+ out[0]->vec[0] = y/255.0;
+ out[1]->vec[0] = cb/255.0;
+ out[2]->vec[0] = cr/255.0;
+ out[3]->vec[0] = in[0]->vec[3];
+ }
+ else if ((out[0]->hasoutput) || (out[1]->hasoutput) || (out[2]->hasoutput) || (out[3]->hasoutput)) {
+ /* make output size of input image */
+ CompBuf *cbuf= in[0]->data;
+
+ CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs
+
+ /* convert the RGB stackbuf to an HSV representation */
+ composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_sepycca, CB_RGBA);
+
+ /* separate each of those channels */
+ if(out[0]->hasoutput)
+ out[0]->data= valbuf_from_rgbabuf(stackbuf, CHAN_R);
+ if(out[1]->hasoutput)
+ out[1]->data= valbuf_from_rgbabuf(stackbuf, CHAN_G);
+ if(out[2]->hasoutput)
+ out[2]->data= valbuf_from_rgbabuf(stackbuf, CHAN_B);
+ if(out[3]->hasoutput)
+ out[3]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
+
+ free_compbuf(stackbuf);
+ }
+}
+
+static bNodeType cmp_node_sepycca= {
+ /* type code */ CMP_NODE_SEPYCCA,
+ /* name */ "Separate YCbCrA",
+ /* width+range */ 80, 40, 140,
+ /* class+opts */ NODE_CLASS_CONVERTOR, 0,
+ /* input sock */ cmp_node_sepycca_in,
+ /* output sock */ cmp_node_sepycca_out,
+ /* storage */ "",
+ /* execfunc */ node_composit_exec_sepycca
+};
+
+
+/* ******************* channel Difference Matte ********************************* */
+static bNodeSocketType cmp_node_diff_matte_in[]={
+ {SOCK_RGBA,1,"Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+ {SOCK_RGBA,1,"Key Color", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+ {-1,0,""}
+};
+
+static bNodeSocketType cmp_node_diff_matte_out[]={
+ {SOCK_RGBA,0,"Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+ {SOCK_VALUE,0,"Matte",0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ {-1,0,""}
+};
+
+static void do_rgba_to_yuva(bNode *node, float *out, float *in)
+{
+ rgb_to_yuv(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
+ out[3]=in[3];
+}
+
+static void do_rgba_to_hsva(bNode *node, float *out, float *in)
+{
+ rgb_to_hsv(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
+ out[3]=in[3];
+}
+
+static void do_rgba_to_ycca(bNode *node, float *out, float *in)
+{
+ rgb_to_ycc(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
+ out[3]=in[3];
+}
+
+static void do_yuva_to_rgba(bNode *node, float *out, float *in)
+{
+ yuv_to_rgb(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
+ out[3]=in[3];
+}
+
+static void do_hsva_to_rgba(bNode *node, float *out, float *in)
+{
+ hsv_to_rgb(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
+ out[3]=in[3];
+}
+
+static void do_ycca_to_rgba(bNode *node, float *out, float *in)
+{
+ ycc_to_rgb(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
+ out[3]=in[3];
+}
+
+/* note, keyvals is passed on from caller as stack array */
+/* might have been nicer as temp struct though... */
+static void do_diff_matte(bNode *node, float *colorbuf, float *inbuf, float *keyvals)
+{
+ NodeChroma *c= (NodeChroma *)node->storage;
+ float *keymin= keyvals;
+ float *keymax= keyvals+3;
+ float *key= keyvals+6;
+ float tolerance= keyvals[9];
+ float distance, alpha;
+
+ /*process the pixel if it is close to the key or already transparent*/
+ if(((colorbuf[0]>keymin[0] && colorbuf[0]<keymax[0]) &&
+ (colorbuf[1]>keymin[1] && colorbuf[1]<keymax[1]) &&
+ (colorbuf[2]>keymin[2] && colorbuf[2]<keymax[2])) || inbuf[3]<1.0f) {
+
+ /*true distance from key*/
+ distance= sqrt((colorbuf[0]-key[0])*(colorbuf[0]-key[0])+
+ (colorbuf[1]-key[1])*(colorbuf[1]-key[1])+
+ (colorbuf[2]-key[2])*(colorbuf[2]-key[2]));
+
+ /*is it less transparent than the prevous pixel*/
+ alpha= distance/tolerance;
+ if(alpha > inbuf[3]) alpha= inbuf[3];
+ if(alpha > c->fstrength) alpha= 0.0f;
+
+ /*clamp*/
+ if (alpha>1.0f) alpha=1.0f;
+ if (alpha<0.0f) alpha=0.0f;
+
+ /*premultiplied picture*/
+ colorbuf[3]= alpha;
+ }
+ else {
+ /*foreground object*/
+ colorbuf[3]= inbuf[3];
+ }
+}
+
+static void node_composit_exec_diff_matte(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+ /*
+ Losely based on the Sequencer chroma key plug-in, but enhanced to work in other color spaces and
+ uses a differnt difference function (suggested in forums of vfxtalk.com).
+ */
+ CompBuf *outbuf;
+ CompBuf *colorbuf;
+ CompBuf *inbuf;
+ NodeChroma *c;
+ float keyvals[10];
+ float *keymin= keyvals;
+ float *keymax= keyvals+3;
+ float *key= keyvals+6;
+ float *tolerance= keyvals+9;
+ float t[3];
+
+ /*is anything connected?*/
+ if(out[0]->hasoutput==0 && out[1]->hasoutput==0) return;
+ /*must have an image imput*/
+ if(in[0]->data==NULL) return;
+
+ inbuf=in[0]->data;
+ if(inbuf->type!=CB_RGBA) return;
+
+ c=node->storage;
+ colorbuf=dupalloc_compbuf(inbuf);
+ outbuf=alloc_compbuf(inbuf->x,inbuf->y,CB_RGBA,1);
+
+ /*use the input color*/
+ key[0]= in[1]->vec[0];
+ key[1]= in[1]->vec[1];
+ key[2]= in[1]->vec[2];
+
+ /*get the tolerances from the UI*/
+ t[0]=c->t1;
+ t[1]=c->t2;
+ t[2]=c->t3;
+
+ /*convert to colorspace*/
+ switch(node->custom1) {
+ case 1: /*RGB*/
+ break;
+ case 2: /*HSV*/
+ /*convert the key (in place)*/
+ rgb_to_hsv(key[0], key[1], key[2], &key[0], &key[1], &key[2]);
+ composit1_pixel_processor(node, colorbuf, inbuf, in[1]->vec, do_rgba_to_hsva, CB_RGBA);
+ break;
+ case 3: /*YUV*/
+ rgb_to_yuv(key[0], key[1], key[2], &key[0], &key[1], &key[2]);
+ composit1_pixel_processor(node, colorbuf, inbuf, in[1]->vec, do_rgba_to_yuva, CB_RGBA);
+ break;
+ case 4: /*YCC*/
+ rgb_to_ycc(key[0], key[1], key[2], &key[0], &key[1], &key[2]);
+ composit1_pixel_processor(node, colorbuf, inbuf, in[1]->vec, do_rgba_to_ycca, CB_RGBA);
+ /*account for ycc is on a 0..255 scale*/
+ t[0]= c->t1*255.0;
+ t[1]= c->t2*255.0;
+ t[2]= c->t3*255.0;
+ break;
+ default:
+ break;
+ }
+
+ /*find min/max tolerances*/
+ keymin[0]= key[0]-t[0];
+ keymin[1]= key[1]-t[1];
+ keymin[2]= key[2]-t[2];
+ keymax[0]= key[0]+t[0];
+ keymax[1]= key[1]+t[1];
+ keymax[2]= key[2]+t[2];
+
+ /*tolerance*/
+ *tolerance= sqrt((t[0])*(t[0])+
+ (t[1])*(t[1])+
+ (t[2])*(t[2]));
+
+ /* note, processor gets a keyvals array passed on as buffer constant */
+ composit2_pixel_processor(node, colorbuf, inbuf, in[0]->vec, NULL, keyvals, do_diff_matte, CB_RGBA, CB_VAL);
+
+ /*convert back to RGB colorspace*/
+ switch(node->custom1) {
+ case 1: /*RGB*/
+ composit1_pixel_processor(node, outbuf, colorbuf, in[1]->vec, do_copy_rgba, CB_RGBA);
+ break;
+ case 2: /*HSV*/
+ composit1_pixel_processor(node, outbuf, colorbuf, in[1]->vec, do_hsva_to_rgba, CB_RGBA);
+ break;
+ case 3: /*YUV*/
+ composit1_pixel_processor(node, outbuf, colorbuf, in[1]->vec, do_yuva_to_rgba, CB_RGBA);
+ break;
+ case 4: /*YCC*/
+ composit1_pixel_processor(node, outbuf, colorbuf, in[1]->vec, do_ycca_to_rgba, CB_RGBA);
+ break;
+ default:
+ break;
+ }
+
+ free_compbuf(colorbuf);
+
+ out[0]->data=outbuf;
+ out[1]->data=valbuf_from_rgbabuf(outbuf, CHAN_A);
+ generate_preview(node, outbuf);
+}
+
+static bNodeType cmp_node_diff_matte={
+ /* type code */ CMP_NODE_DIFF_MATTE,
+ /* name */ "Channel Difference Matte",
+ /* width+range */ 200, 80, 250,
+ /* class+opts */ NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS,
+ /* input sock */ cmp_node_diff_matte_in,
+ /* output sock */ cmp_node_diff_matte_out,
+ /* storage */ "NodeChroma",
+ /* execfunc */ node_composit_exec_diff_matte
+};
+
+
+/* ******************* Color Spill Supression ********************************* */
+static bNodeSocketType cmp_node_color_spill_in[]={
+ {SOCK_RGBA,1,"Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+ {-1,0,""}
+};
+
+static bNodeSocketType cmp_node_color_spill_out[]={
+ {SOCK_RGBA,0,"Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+ {-1,0,""}
+};
+
+static void do_reduce_red(bNode *node, float* out, float *in)
+{
+ NodeChroma *c;
+ c=node->storage;
+
+ if(in[0] > in[1] && in[0] > in[2]) {
+ out[0]=((in[1]+in[2])/2)*(1-c->t1);
+ }
+}
+
+static void do_reduce_green(bNode *node, float* out, float *in)
+{
+ NodeChroma *c;
+ c=node->storage;
+
+ if(in[1] > in[0] && in[1] > in[2]) {
+ out[1]=((in[0]+in[2])/2)*(1-c->t1);
+ }
+}
+
+static void do_reduce_blue(bNode *node, float* out, float *in)
+{
+ NodeChroma *c;
+ c=node->storage;
+
+ if(in[2] > in[1] && in[2] > in[1]) {
+ out[2]=((in[1]+in[0])/2)*(1-c->t1);
+ }
+}
+
+static void node_composit_exec_color_spill(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+ /*
+ Originally based on the information from the book "The Art and Science of Digital Composition" and
+ discussions from vfxtalk.com.*/
+ CompBuf *cbuf;
+ CompBuf *rgbbuf;
+
+ if(out[0]->hasoutput==0 || in[0]->hasinput==0) return;
+ if(in[0]->data==NULL) return;
+
+ cbuf=in[0]->data;
+ /*is it an RGBA image?*/
+ if(cbuf->type==CB_RGBA) {
+
+ rgbbuf=dupalloc_compbuf(cbuf);
+ switch(node->custom1)
+ {
+ case 1: /*red spill*/
+ {
+ composit1_pixel_processor(node, rgbbuf, cbuf, in[1]->vec, do_reduce_red, CB_RGBA);
+ break;
+ }
+ case 2: /*green spill*/
+ {
+ composit1_pixel_processor(node, rgbbuf, cbuf, in[1]->vec, do_reduce_green, CB_RGBA);
+ break;
+ }
+ case 3: /*blue spill*/
+ {
+ composit1_pixel_processor(node, rgbbuf, cbuf, in[1]->vec, do_reduce_blue, CB_RGBA);
+ break;
+ }
+ default:
+ break;
+ }
+
+ out[0]->data=rgbbuf;
+ }
+ else {
+ return;
+ }
+}
+
+static bNodeType cmp_node_color_spill={
+ /* type code */ CMP_NODE_COLOR_SPILL,
+ /* name */ "Color Spill",
+ /* width+range */ 140, 80, 200,
+ /* class+opts */ NODE_CLASS_MATTE, NODE_OPTIONS,
+ /* input sock */ cmp_node_color_spill_in,
+ /* output sock */ cmp_node_color_spill_out,
+ /* storage */ "NodeChroma",
+ /* execfunc */ node_composit_exec_color_spill
+};
+
+/* ******************* Chroma Key ********************************************************** */
+static bNodeSocketType cmp_node_chroma_in[]={
+ {SOCK_RGBA,1,"Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+ {SOCK_RGBA,1,"Key Color", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+ {-1,0,""}
+};
+
+static bNodeSocketType cmp_node_chroma_out[]={
+ {SOCK_RGBA,0,"Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+ {SOCK_VALUE,0,"Matte",0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ {-1,0,""}
+};
+
+static void do_rgba_to_ycca_normalized(bNode *node, float *out, float *in)
+{
+ rgb_to_ycc(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
+ out[0]=(out[0])/255;
+ out[1]=(out[1])/256;
+ out[2]=(out[2])/256;
+ out[3]=in[3];
+}
+
+static void do_normalized_ycca_to_rgba(bNode *node, float *out, float *in)
+{
+ in[0]=in[0]*255;
+ in[1]=in[1]*256;
+ in[2]=in[2]*256;
+ ycc_to_rgb(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
+ out[3]=in[3];
+}
+
+static void do_chroma_key(bNode *node, float *out, float *in)
+{
+ /* Algorithm of my own design-Bob Holcomb */
+
+ /* alpha value is written to in[3] because it is done "in place" so that the value gets copied to the rgbbuffer in
+ the second pixel processor opertation */
+ NodeChroma *c;
+ float x, z, alpha;
+
+ c=node->storage;
+
+ switch(node->custom1)
+ {
+ case 1: /*green*/
+ {
+ x=(atanf((c->t1*in[1])-(c->t1*c->t2))+1)/2;
+ z=(atanf((c->t3*in[2])-(c->t3*c->fsize))+1)/2;
+ break;
+ }
+ case 2: /*blue*/
+ {
+ x=(atanf((c->t1*in[1])-(c->t1*c->t2))+1)/2;
+ z=(atanf((c->t3*in[2])-(c->t3*c->fsize))+1)/2;
+ x=1-x;
+ break;
+ }
+ default:
+ break;
+ }
+
+ /*is chroma values (added) less than strenght?*/
+ if((x+z) < c->fstrength) {
+ alpha=ABS(c->key[0]-in[0]); /*differnce in luminence*/
+ if(alpha > c->falpha) alpha=0;
+ in[3]=alpha;
+ }
+ else {
+ in[3]=1.0;
+ }
+}
+
+static void node_composit_exec_chroma(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+ CompBuf *rgbbuf,*inbuf;
+ CompBuf *chromabuf;
+ NodeChroma *c;
+
+ if(out[0]->hasoutput==0 || in[0]->hasinput==0) return;
+ if(in[0]->data==NULL) return;
+
+ inbuf= in[0]->data;
+ if(inbuf->type!=CB_RGBA) return;
+
+ rgbbuf= dupalloc_compbuf(inbuf);
+ chromabuf= dupalloc_compbuf(rgbbuf);
+
+ c=node->storage;
+ c->key[0]= in[1]->vec[0];
+ c->key[1]= in[1]->vec[1];
+ c->key[2]= in[1]->vec[2];
+
+ /*convert rgbbuf to normalized chroma space*/
+ composit1_pixel_processor(node, chromabuf, inbuf, in[1]->vec, do_rgba_to_ycca_normalized, CB_RGBA);
+
+ /*per pixel chroma key*/
+ composit1_pixel_processor(node, rgbbuf, chromabuf, in[1]->vec, do_chroma_key, CB_RGBA);
+
+ /*convert back*/
+ composit1_pixel_processor(node, rgbbuf, chromabuf, in[1]->vec, do_normalized_ycca_to_rgba, CB_RGBA);
+
+ /*cleanup */
+ free_compbuf(chromabuf);
+
+ out[0]->data= rgbbuf;
+ if(out[1]->hasoutput)
+ out[1]->data= valbuf_from_rgbabuf(rgbbuf, CHAN_A);
+
+ generate_preview(node, rgbbuf);
+};
+
+static bNodeType cmp_node_chroma={
+ /* type code */ CMP_NODE_CHROMA,
+ /* name */ "Chroma Key",
+ /* width+range */ 200, 80, 300,
+ /* class+opts */ NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS,
+ /* input sock */ cmp_node_chroma_in,
+ /* output sock */ cmp_node_chroma_out,
+ /* storage */ "NodeChroma",
+ /* execfunc */ node_composit_exec_chroma
+};
+
+/* ******************* Luminence Key ********************************************************** */
+static bNodeSocketType cmp_node_luma_in[]={
+ {SOCK_RGBA,1,"Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+ {SOCK_RGBA,1,"Key Color", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+ {-1,0,""}
+};
+
+static bNodeSocketType cmp_node_luma_out[]={
+ {SOCK_RGBA,0,"Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+ {SOCK_VALUE,0,"Matte",0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ {-1,0,""}
+};
+
+static void do_luma_key(bNode *node, float *out, float *in)
+{
+ /* Algorithm from Video Demistified */
+
+ /* alpha value is written to in[3] because it is done in place for the conversion back to rgb space in
+ second pixel processor */
+
+ NodeChroma *c;
+
+ c=node->storage;
+
+ if(in[0] > c->t1) { /*Luminence is greater than high, then foreground */
+ in[3]=1.0;
+ }
+ else if(in[0] <c->t2) {/*Luminence is less than low, then background */
+ in[3]=0.0;
+ }
+
+ else { /*key value from mix*/
+ /*keep div by 0 from happening */
+ if(c->t1==c->t2) {
+ c->t1+=0.0001;
+ }
+
+ /*mix*/
+ in[3]=(in[0]-c->t2)/(c->t1-c->t2);
+ }
+}
+
+static void node_composit_exec_luma(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+ CompBuf *rgbbuf,*inbuf;
+ CompBuf *chromabuf;
+
+ if(out[0]->hasoutput==0 || in[0]->hasinput==0) return;
+ if(in[0]->data==NULL) return;
+
+ inbuf= in[0]->data;
+ if(inbuf->type!=CB_RGBA) return;
+
+ rgbbuf= dupalloc_compbuf(inbuf);
+ chromabuf= dupalloc_compbuf(rgbbuf);
+
+ /*convert rgbbuf to normalized chroma space*/
+ composit1_pixel_processor(node, chromabuf, inbuf, in[1]->vec, do_rgba_to_ycca_normalized, CB_RGBA);
+
+ /*per pixel chroma key*/
+ composit1_pixel_processor(node, rgbbuf, chromabuf, in[1]->vec, do_luma_key, CB_RGBA);
+
+ /*convert back*/
+ composit1_pixel_processor(node, rgbbuf, chromabuf, in[1]->vec, do_normalized_ycca_to_rgba, CB_RGBA);
+
+ /*cleanup */
+ free_compbuf(chromabuf);
+
+ out[0]->data= rgbbuf;
+ if(out[1]->hasoutput)
+ out[1]->data= valbuf_from_rgbabuf(rgbbuf, CHAN_A);
+
+ generate_preview(node, rgbbuf);
+}
+
+static bNodeType cmp_node_luma={
+ /* type code */ CMP_NODE_LUMA,
+ /* name */ "Luminance Key",
+ /* width+range */ 200, 80, 300,
+ /* class+opts */ NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS,
+ /* input sock */ cmp_node_luma_in,
+ /* output sock */ cmp_node_luma_out,
+ /* storage */ "NodeChroma",
+ /* execfunc */ node_composit_exec_luma
+};
+
+
+
+/* **************** COMBINE YCCA ******************** */
+static bNodeSocketType cmp_node_combycca_in[]= {
+ { SOCK_VALUE, 1, "Y", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VALUE, 1, "Cb", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VALUE, 1, "Cr", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VALUE, 1, "A", 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+static bNodeSocketType cmp_node_combycca_out[]= {
+ { SOCK_RGBA, 0, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static void do_comb_ycca(bNode *node, float *out, float *in1, float *in2, float *in3, float *in4)
+{
+ float r,g,b;
+ float y, cb, cr;
+
+ /*need to un-normalize the data*/
+ y=in1[0]*255;
+ cb=in2[0]*255;
+ cr=in3[0]*255;
+
+ ycc_to_rgb(y,cb,cr, &r, &g, &b);
+
+ out[0] = r;
+ out[1] = g;
+ out[2] = b;
+ out[3] = in4[0];
+}
+
+static void node_composit_exec_combycca(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+ /* stack order out: 1 ycca channels */
+ /* stack order in: 4 value channels */
+
+ /* input no image? then only color operation */
+ if((in[0]->data==NULL) && (in[1]->data==NULL) && (in[2]->data==NULL) && (in[3]->data==NULL)) {
+ out[0]->vec[0] = in[0]->vec[0];
+ out[0]->vec[1] = in[1]->vec[0];
+ out[0]->vec[2] = in[2]->vec[0];
+ out[0]->vec[3] = in[3]->vec[0];
+ }
+ else {
+ /* make output size of first available input image */
+ CompBuf *cbuf;
+ CompBuf *stackbuf;
+
+ /* allocate a CompBuf the size of the first available input */
+ if (in[0]->data) cbuf = in[0]->data;
+ else if (in[1]->data) cbuf = in[1]->data;
+ else if (in[2]->data) cbuf = in[2]->data;
+ else cbuf = in[3]->data;
+
+ stackbuf = alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs
+
+ composit4_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec,
+ in[2]->data, in[2]->vec, in[3]->data, in[3]->vec,
+ do_comb_ycca, CB_VAL, CB_VAL, CB_VAL, CB_VAL);
+
+ out[0]->data= stackbuf;
+ }
+}
+
+static bNodeType cmp_node_combycca= {
+ /* type code */ CMP_NODE_COMBYCCA,
+ /* name */ "Combine YCbCrA",
+ /* width+range */ 80, 40, 140,
+ /* class+opts */ NODE_CLASS_CONVERTOR, NODE_OPTIONS,
+ /* input sock */ cmp_node_combycca_in,
+ /* output sock */ cmp_node_combycca_out,
+ /* storage */ "",
+ /* execfunc */ node_composit_exec_combycca
+};
+
+
+/* **************** COMBINE YUVA ******************** */
+static bNodeSocketType cmp_node_combyuva_in[]= {
+ { SOCK_VALUE, 1, "Y", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VALUE, 1, "U", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VALUE, 1, "V", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VALUE, 1, "A", 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+static bNodeSocketType cmp_node_combyuva_out[]= {
+ { SOCK_RGBA, 0, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static void do_comb_yuva(bNode *node, float *out, float *in1, float *in2, float *in3, float *in4)
+{
+ float r,g,b;
+ yuv_to_rgb(in1[0], in2[0], in3[0], &r, &g, &b);
+
+ out[0] = r;
+ out[1] = g;
+ out[2] = b;
+ out[3] = in4[0];
+}
+
+static void node_composit_exec_combyuva(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+ /* stack order out: 1 rgba channels */
+ /* stack order in: 4 value channels */
+
+ /* input no image? then only color operation */
+ if((in[0]->data==NULL) && (in[1]->data==NULL) && (in[2]->data==NULL) && (in[3]->data==NULL)) {
+ out[0]->vec[0] = in[0]->vec[0];
+ out[0]->vec[1] = in[1]->vec[0];
+ out[0]->vec[2] = in[2]->vec[0];
+ out[0]->vec[3] = in[3]->vec[0];
+ }
+ else {
+ /* make output size of first available input image */
+ CompBuf *cbuf;
+ CompBuf *stackbuf;
+
+ /* allocate a CompBuf the size of the first available input */
+ if (in[0]->data) cbuf = in[0]->data;
+ else if (in[1]->data) cbuf = in[1]->data;
+ else if (in[2]->data) cbuf = in[2]->data;
+ else cbuf = in[3]->data;
+
+ stackbuf = alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs
+
+ composit4_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec,
+ in[2]->data, in[2]->vec, in[3]->data, in[3]->vec,
+ do_comb_yuva, CB_VAL, CB_VAL, CB_VAL, CB_VAL);
+
+ out[0]->data= stackbuf;
+ }
+}
+
+static bNodeType cmp_node_combyuva= {
+ /* type code */ CMP_NODE_COMBYUVA,
+ /* name */ "Combine YUVA",
+ /* width+range */ 80, 40, 140,
+ /* class+opts */ NODE_CLASS_CONVERTOR, NODE_OPTIONS,
+ /* input sock */ cmp_node_combyuva_in,
+ /* output sock */ cmp_node_combyuva_out,
+ /* storage */ "",
+ /* execfunc */ node_composit_exec_combyuva
+};
+
+
/* **************** Rotate ******************** */
static bNodeSocketType cmp_node_rotate_in[]= {
@@ -3195,7 +4002,6 @@ static void node_composit_exec_rotate(void *data, bNode *node, bNodeStack **in,
bilinear_interpolation_rotate(cbuf, ofp, u, v);
}
}
-
out[0]->data= stackbuf;
if(cbuf!=in[0]->data)
free_compbuf(cbuf);
@@ -3293,6 +4099,7 @@ static bNodeType cmp_node_scale= {
/* execfunc */ node_composit_exec_scale
};
+
/* ****************** types array for all shaders ****************** */
bNodeType *node_all_composit[]= {
@@ -3325,8 +4132,16 @@ bNodeType *node_all_composit[]= {
&cmp_node_translate,
&cmp_node_zcombine,
&cmp_node_dilateerode,
+ &cmp_node_sepyuva,
+ &cmp_node_combyuva,
+ &cmp_node_sepycca,
+ &cmp_node_combycca,
+ &cmp_node_diff_matte,
+ &cmp_node_color_spill,
+ &cmp_node_chroma,
&cmp_node_rotate,
&cmp_node_scale,
+ &cmp_node_luma,
NULL
};
diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h
index 35f4a0bc9f9..c2a81ebed65 100644
--- a/source/blender/blenlib/BLI_arithb.h
+++ b/source/blender/blenlib/BLI_arithb.h
@@ -684,9 +684,38 @@ hsv_to_rgb(
float *g, float *b
);
-void hex_to_rgb(char *hexcol, float *r, float *g, float *b);
+ void
+hex_to_rgb(
+ char *hexcol,
+ float *r,
+ float *g,
+ float *b
+);
+
+ void
+rgb_to_yuv(
+ float r, float g, float b,
+ float *ly, float *lu, float *lv
+);
void
+yuv_to_rgb(
+ float y, float u, float v,
+ float *lr, float *lg, float *lb
+);
+
+ void
+ycc_to_rgb(
+ float y, float cb, float cr,
+ float *lr, float *lg, float *lb
+);
+
+ void
+rgb_to_ycc(
+ float r, float g, float b,
+ float *ly, float *lcb, float *lcr
+);
+ void
rgb_to_hsv(
float r, float g, float b,
float *lh, float *ls, float *lv
diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c
index 21cf2fa2e56..3fd65ca534c 100644
--- a/source/blender/blenlib/intern/arithb.c
+++ b/source/blender/blenlib/intern/arithb.c
@@ -2721,6 +2721,62 @@ void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b)
}
}
+void rgb_to_yuv(float r, float g, float b, float *ly, float *lu, float *lv)
+{
+ float y, u, v;
+ y= 0.299*r + 0.587*g + 0.114*b;
+ u=-0.147*r - 0.289*g + 0.436*b;
+ v= 0.615*r - 0.515*g - 0.100*b;
+
+ *ly=y;
+ *lu=u;
+ *lv=v;
+}
+
+void yuv_to_rgb(float y, float u, float v, float *lr, float *lg, float *lb)
+{
+ float r, g, b;
+ r=y+1.140*v;
+ g=y-0.394*u - 0.581*v;
+ b=y+2.032*u;
+
+ *lr=r;
+ *lg=g;
+ *lb=b;
+}
+
+void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr)
+{
+ float sr,sg, sb;
+ float y, cr, cb;
+
+ sr=255.0*r;
+ sg=255.0*g;
+ sb=255.0*b;
+
+
+ y=(0.257*sr)+(0.504*sg)+(0.098*sb)+16.0;
+ cb=(-0.148*sr)-(0.291*sg)+(0.439*sb)+128.0;
+ cr=(0.439*sr)-(0.368*sg)-(0.071*sb)+128.0;
+
+ *ly=y;
+ *lcb=cb;
+ *lcr=cr;
+}
+
+void ycc_to_rgb(float y, float cb, float cr, float *lr, float *lg, float *lb)
+{
+ float r,g,b;
+
+ r=1.164*(y-16)+1.596*(cr-128);
+ g=1.164*(y-16)-0.813*(cr-128)-0.392*(cb-128);
+ b=1.164*(y-16)+2.017*(cb-128);
+
+ *lr=r/255.0;
+ *lg=g/255.0;
+ *lb=b/255.0;
+}
+
void hex_to_rgb(char *hexcol, float *r, float *g, float *b)
{
unsigned int ri, gi, bi;
@@ -3015,7 +3071,7 @@ void mul_v3_v3m4(float *v1, float *v2, float mat[][4])
{
float x, y;
- x= v2[0]; // work with a copy, v1 can be same as v2
+ x= v2[0]; /* work with a copy, v1 can be same as v2 */
y= v2[1];
v1[0]= x*mat[0][0] + y*mat[1][0] + mat[2][0]*v2[2] + mat[3][0];
v1[1]= x*mat[0][1] + y*mat[1][1] + mat[2][1]*v2[2] + mat[3][1];
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index c7db4a318ac..94e4e26354b 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -202,5 +202,11 @@ typedef struct NodeImageFile {
int sfra, efra;
} NodeImageFile;
+typedef struct NodeChroma {
+ float t1,t2,t3;
+ float fsize,fstrength,falpha;
+ float key[4];
+} NodeChroma;
+
#endif
diff --git a/source/blender/src/drawnode.c b/source/blender/src/drawnode.c
index f7df77c3640..196086799c8 100644
--- a/source/blender/src/drawnode.c
+++ b/source/blender/src/drawnode.c
@@ -1027,6 +1027,136 @@ static int node_composit_buts_dilateerode(uiBlock *block, bNodeTree *ntree, bNod
return 20;
}
+static int node_composit_buts_diff_matte(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ short sx= (butr->xmax-butr->xmin)/4;
+ short dx= (butr->xmax-butr->xmin)/3;
+ NodeChroma *c= node->storage;
+
+ uiBlockBeginAlign(block);
+ /*color space selectors*/
+ uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"RGB",
+ butr->xmin,butr->ymin+60,sx,20,
+ &node->custom1,1,1, 0, 0, "RGB Color Space");
+ uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"HSV",
+ butr->xmin+sx,butr->ymin+60,sx,20,
+ &node->custom1,1,2, 0, 0, "HSV Color Space");
+ uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"YUV",
+ butr->xmin+2*sx,butr->ymin+60,sx,20,
+ &node->custom1,1,3, 0, 0, "YUV Color Space");
+ uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"YCC",
+ butr->xmin+3*sx,butr->ymin+60,sx,20,
+ &node->custom1,1,4, 0, 0, "YCbCr Color Space");
+ /*channel tolorences*/
+ uiDefButF(block, NUM, B_NODE_EXEC+node->nr, " ",
+ butr->xmin, butr->ymin+40, dx, 20,
+ &c->t1, 0.0f, 1.0f, 100, 0, "Channel 1 Tolerance");
+ uiDefButF(block, NUM, B_NODE_EXEC+node->nr, " ",
+ butr->xmin+dx, butr->ymin+40, dx, 20,
+ &c->t2, 0.0f, 1.0f, 100, 0, "Channel 2 Tolorence");
+ uiDefButF(block, NUM, B_NODE_EXEC+node->nr, " ",
+ butr->xmin+2*dx, butr->ymin+40, dx, 20,
+ &c->t3, 0.0f, 1.0f, 100, 0, "Channel 3 Tolorence");
+ /*falloff parameters*/
+ /*
+ uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Falloff Size ",
+ butr->xmin, butr->ymin+20, butr->xmax-butr->xmin, 20,
+ &c->fsize, 0.0f, 1.0f, 100, 0, "");
+ */
+ uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Falloff: ",
+ butr->xmin, butr->ymin+20, butr->xmax-butr->xmin, 20,
+ &c->fstrength, 0.0f, 1.0f, 100, 0, "");
+ }
+ return 80;
+}
+
+static int node_composit_buts_color_spill(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ short dx= (butr->xmax-butr->xmin)/3;
+
+ NodeChroma *c=node->storage;
+ uiBlockBeginAlign(block);
+ uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Enhance: ",
+ butr->xmin, butr->ymin+20.0, butr->xmax-butr->xmin, 20,
+ &c->t1, 0.0f, 0.5f, 100, 2, "");
+ uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "R",
+ butr->xmin,butr->ymin,dx,20,
+ &node->custom1,1,1, 0, 0, "Red Spill Suppression");
+ uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "G",
+ butr->xmin+dx,butr->ymin,dx,20,
+ &node->custom1,1,2, 0, 0, "Green Spill Suppression");
+ uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "B",
+ butr->xmin+2*dx,butr->ymin,dx,20,
+ &node->custom1, 1, 3, 0, 0, "Blue Spill Suppression");
+ uiBlockEndAlign(block);
+ }
+ return 60;
+ }
+
+static int node_composit_buts_chroma_matte(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ short dx= (butr->xmax-butr->xmin)/2;
+
+ NodeChroma *c= node->storage;
+ uiBlockBeginAlign(block);
+
+ uiDefButS(block, ROW, B_NODE_EXEC+node->nr,"Green",
+ butr->xmin,butr->ymin+80,dx,20,
+ &node->custom1,1,1, 0, 0, "Green Background");
+ uiDefButS(block, ROW, B_NODE_EXEC+node->nr,"Blue",
+ butr->xmin+dx,butr->ymin+80,dx,20,
+ &node->custom1,1,2, 0, 0, "Blue Background");
+
+ uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Cb Slope ",
+ butr->xmin, butr->ymin+60, dx, 20,
+ &c->t1, 0.0f, 20.0f, 100, 0, " ");
+
+ uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Cr slope ",
+ butr->xmin+dx, butr->ymin+60, dx, 20,
+ &c->t3, 0.0f, 20.0f, 100, 0, " ");
+
+ uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Cb Pos ",
+ butr->xmin, butr->ymin+40, dx, 20,
+ &c->t2, 0.0f, 1.0f, 100, 0, " ");
+
+ uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Cr pos ",
+ butr->xmin+dx, butr->ymin+40, dx, 20,
+ &c->fsize, 0.0f, 1.0f, 100, 0, " ");
+
+ uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Threshold ",
+ butr->xmin, butr->ymin+20, butr->xmax-butr->xmin, 20,
+ &c->fstrength, 0.0f, 0.25f, 100, 0, " ");
+ uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Alpha Threshold ",
+ butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20,
+ &c->falpha, 0.0f, 1.0f, 100, 0, " ");
+ }
+ return 100;
+}
+
+static int node_composit_buts_luma_matte(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ NodeChroma *c=node->storage;
+ uiBlockBeginAlign(block);
+ uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "High ",
+ butr->xmin, butr->ymin+20.0, butr->xmax-butr->xmin, 20,
+ &c->t1, 0.0f, 1.0f, 100, 0, "");
+ uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Low ",
+ butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20,
+ &c->t2, 0.0f, 1.0f, 100, 0, "");
+ uiBlockEndAlign(block);
+
+ /*keep t2 (low) less than t1 (high) */
+ if(c->t2 > c->t1) {
+ c->t2=c->t1;
+ }
+ }
+ return 60;
+ }
+
/* allocate sufficient! */
static void node_imagetype_string(char *str)
{
@@ -1184,9 +1314,22 @@ static void node_composit_set_butfunc(bNodeType *ntype)
case CMP_NODE_OUTPUT_FILE:
ntype->butfunc= node_composit_buts_file_output;
break;
+
+ case CMP_NODE_DIFF_MATTE:
+ ntype->butfunc=node_composit_buts_diff_matte;
+ break;
+ case CMP_NODE_COLOR_SPILL:
+ ntype->butfunc=node_composit_buts_color_spill;
+ break;
+ case CMP_NODE_CHROMA:
+ ntype->butfunc=node_composit_buts_chroma_matte;
+ break;
case CMP_NODE_SCALE:
ntype->butfunc= node_composit_buts_scale;
break;
+ case CMP_NODE_LUMA:
+ ntype->butfunc= node_composit_buts_luma_matte;
+ break;
default:
ntype->butfunc= NULL;
}
@@ -1494,7 +1637,7 @@ static void node_update(bNode *node)
else {
float oldh= node->prvr.ymax - node->prvr.ymin;
if(oldh==0.0f)
- oldh= node->width-NODE_DY;
+ oldh= 0.6f*node->width-NODE_DY;
dy-= NODE_DYS/2;
node->prvr.ymax= dy;
node->prvr.ymin= dy - oldh;
diff --git a/source/blender/src/toolbox.c b/source/blender/src/toolbox.c
index 4ce4045a170..eefba19b718 100644
--- a/source/blender/src/toolbox.c
+++ b/source/blender/src/toolbox.c
@@ -1548,6 +1548,7 @@ static TBitem tb_node_addsh[]= {
#define TB_CMP_OP_FILTER 4
#define TB_CMP_CONVERTORS 5
#define TB_CMP_GROUPS 6
+#define TB_CMP_MATTE 7
static TBitem tb_node_addcomp[]= {
{ 0, "Input", 1, NULL},
@@ -1557,6 +1558,7 @@ static TBitem tb_node_addcomp[]= {
{ 0, "Filters", 5, NULL},
{ 0, "Convertors", 6, NULL},
{ 0, "Groups", 7, NULL},
+ { 0, "Mattes", 8, NULL},
{ -1, "", 0, NULL}};
/* do_node_addmenu() in header_node.c, prototype in BSE_headerbuttons.h */
@@ -1758,7 +1760,7 @@ void toolbox_n(void)
TBitem *menu1=NULL, *menu2=NULL, *menu3=NULL;
TBitem *menu4=NULL, *menu5=NULL, *menu6=NULL;
TBitem *menu7=NULL, *groupmenu= NULL;
- TBitem *node_add_gen= NULL, *node_add_group= NULL, *node_add_out= NULL, *node_add_in= NULL;
+ TBitem *node_add_gen= NULL, *node_add_group= NULL,*node_add_matte=NULL, *node_add_out= NULL, *node_add_in= NULL;
TBitem *node_add_op_col= NULL, *node_add_op_filt= NULL, *node_add_op_vec= NULL, *node_add_con= NULL;
int dx=0;
short event, mval[2], tot=0;
@@ -1940,6 +1942,7 @@ void toolbox_n(void)
node_add_op_vec= node_add_sublevel(&menu1[TB_CMP_OP_VECTOR].poin, snode->nodetree, NODE_CLASS_OP_VECTOR);
node_add_con= node_add_sublevel(&menu1[TB_CMP_CONVERTORS].poin, snode->nodetree, NODE_CLASS_CONVERTOR);
node_add_group= node_add_sublevel(&menu1[TB_CMP_GROUPS].poin, snode->nodetree, NODE_CLASS_GROUP);
+ node_add_matte= node_add_sublevel(&menu1[TB_CMP_MATTE].poin,snode->nodetree, NODE_CLASS_MATTE);
}
dx= 96;
@@ -2040,6 +2043,7 @@ void toolbox_n(void)
if(node_add_con) MEM_freeN(node_add_con);
if(node_add_gen) MEM_freeN(node_add_gen);
if(node_add_group) MEM_freeN(node_add_group);
+ if(node_add_matte) MEM_freeN(node_add_matte);
mywinset(curarea->win);
}