Index: source/blender/blenkernel/BKE_node.h =================================================================== RCS file: /cvsroot/bf-blender/blender/source/blender/blenkernel/BKE_node.h,v retrieving revision 1.20 diff -u -r1.20 BKE_node.h --- source/blender/blenkernel/BKE_node.h 14 Sep 2006 12:21:18 -0000 1.20 +++ source/blender/blenkernel/BKE_node.h 12 Nov 2006 20:52:29 -0000 @@ -88,6 +88,7 @@ #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 @@ #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 Index: source/blender/blenkernel/intern/node.c =================================================================== RCS file: /cvsroot/bf-blender/blender/source/blender/blenkernel/intern/node.c,v retrieving revision 1.47 diff -u -r1.47 node.c --- source/blender/blenkernel/intern/node.c 2 Nov 2006 10:30:35 -0000 1.47 +++ source/blender/blenkernel/intern/node.c 12 Nov 2006 20:52:31 -0000 @@ -809,6 +809,42 @@ 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; + } + 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; + } + 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; + } + 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; Index: source/blender/blenkernel/intern/node_composite.c =================================================================== RCS file: /cvsroot/bf-blender/blender/source/blender/blenkernel/intern/node_composite.c,v retrieving revision 1.66 diff -u -r1.66 node_composite.c --- source/blender/blenkernel/intern/node_composite.c 9 Nov 2006 12:06:06 -0000 1.66 +++ source/blender/blenkernel/intern/node_composite.c 12 Nov 2006 20:52:35 -0000 @@ -557,7 +557,7 @@ 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,834 @@ /* 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", 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]; +} + +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). + */ + int i,max; + float key[3]; + float keymin[3]; + float keymax[3]; + float t[3]; + CompBuf *outbuf; + CompBuf *colorbuf; + CompBuf *inbuf; + NodeChroma *c; + float distance, tolerance, alpha; + + /*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])); + + /*easier for me to do this here by accesssing the rects than try to hack into a pixel processor + due to numerous inputs and my lack of experience with the pixel processors */ + max=inbuf->x*inbuf->y*4; + for(i=0;irect[i+0]>keymin[0] && colorbuf->rect[i+0]rect[i+1]>keymin[1] && colorbuf->rect[i+1]rect[i+2]>keymin[2] && colorbuf->rect[i+2]rect[i+3]<1.0) + { + /*true distance from key*/ + distance=sqrt((colorbuf->rect[i+0]-key[0])*(colorbuf->rect[i+0]-key[0])+ + (colorbuf->rect[i+1]-key[1])*(colorbuf->rect[i+1]-key[1])+ + (colorbuf->rect[i+2]-key[2])*(colorbuf->rect[i+2]-key[2])); + + /*is it less transparent that the prevous pixel*/ + alpha=distance/tolerance; + if(alpha > inbuf->rect[i+3]) alpha=inbuf->rect[i+3]; + if(alpha > c->fstrength) alpha=0.0; + + /*clamp*/ + if (alpha>1.0) alpha=1.0; + if (alpha<0.0) alpha=0.0; + + /*premultiplied picture*/ + colorbuf->rect[i+3]=alpha; + } + else + { + /*foreground object*/ + colorbuf->rect[i+3]=inbuf->rect[i+3]; + } + } + + /*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, 140, + /* 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", 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 */ + + float x,z,alpha; + NodeChroma *c; + + 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; + 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}, + {-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] 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; + 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_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; + out[1]->data=valbuf_from_rgbabuf(rgbbuf, CHAN_A); + generate_preview(node, rgbbuf); +}; + +static bNodeType cmp_node_luma={ + /* type code */ CMP_NODE_LUMA, + /* name */ "Luminence 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 +4023,6 @@ bilinear_interpolation_rotate(cbuf, ofp, u, v); } } - out[0]->data= stackbuf; if(cbuf!=in[0]->data) free_compbuf(cbuf); @@ -3293,6 +4120,7 @@ /* execfunc */ node_composit_exec_scale }; + /* ****************** types array for all shaders ****************** */ bNodeType *node_all_composit[]= { @@ -3325,8 +4153,16 @@ &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 }; Index: source/blender/blenlib/BLI_arithb.h =================================================================== RCS file: /cvsroot/bf-blender/blender/source/blender/blenlib/BLI_arithb.h,v retrieving revision 1.30 diff -u -r1.30 BLI_arithb.h --- source/blender/blenlib/BLI_arithb.h 8 Nov 2006 20:14:04 -0000 1.30 +++ source/blender/blenlib/BLI_arithb.h 12 Nov 2006 20:52:35 -0000 @@ -684,8 +684,37 @@ 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, Index: source/blender/blenlib/intern/arithb.c =================================================================== RCS file: /cvsroot/bf-blender/blender/source/blender/blenlib/intern/arithb.c,v retrieving revision 1.45 diff -u -r1.45 arithb.c --- source/blender/blenlib/intern/arithb.c 8 Nov 2006 20:14:04 -0000 1.45 +++ source/blender/blenlib/intern/arithb.c 12 Nov 2006 20:52:38 -0000 @@ -2721,6 +2721,62 @@ } } +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 @@ { 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]; Index: source/blender/makesdna/DNA_node_types.h =================================================================== RCS file: /cvsroot/bf-blender/blender/source/blender/makesdna/DNA_node_types.h,v retrieving revision 1.16 diff -u -r1.16 DNA_node_types.h --- source/blender/makesdna/DNA_node_types.h 26 Oct 2006 10:13:16 -0000 1.16 +++ source/blender/makesdna/DNA_node_types.h 12 Nov 2006 20:52:38 -0000 @@ -202,5 +202,11 @@ int sfra, efra; } NodeImageFile; +typedef struct NodeChroma { + float t1,t2,t3; + float fsize,fstrength,falpha; + float key[4]; +} NodeChroma; + #endif Index: source/blender/src/drawnode.c =================================================================== RCS file: /cvsroot/bf-blender/blender/source/blender/src/drawnode.c,v retrieving revision 1.41 diff -u -r1.41 drawnode.c --- source/blender/src/drawnode.c 26 Oct 2006 10:13:16 -0000 1.41 +++ source/blender/src/drawnode.c 12 Nov 2006 20:52:41 -0000 @@ -1027,6 +1027,140 @@ 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, NUMSLI, 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, NUMSLI, 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, NUMSLI, 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 Strength ", + 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, NUMSLI, B_NODE_EXEC+node->nr, "Enhancement ", + butr->xmin, butr->ymin+20.0, butr->xmax-butr->xmin, 20, + &c->t1, 0.0f, 0.5f, 100, 0, ""); + uiDefButS(block, ROW,B_DIFF,"R", + butr->xmin,butr->ymin,dx,20, + &node->custom1,1,1, 0, 0, "Red Spill Suppression"); + uiDefButS(block, ROW,B_DIFF,"G", + butr->xmin+dx,butr->ymin,dx,20, + &node->custom1,1,2, 0, 0, "Green Spill Suppression"); + uiDefButS(block, ROW,B_DIFF,"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_DIFF,"Green", + butr->xmin,butr->ymin+80,dx,20, + &node->custom1,1,1, 0, 0, "Green Background"); + uiDefButS(block, ROW,B_DIFF,"Blue", + butr->xmin+dx,butr->ymin+80,dx,20, + &node->custom1,1,2, 0, 0, "Blue Background"); + + uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Cb Slope ", + butr->xmin, butr->ymin+60, dx, 20, + &c->t1, 0.0f, 20.0f, 100, 0, " "); + + uiDefButF(block, NUMSLI, 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, NUMSLI, B_NODE_EXEC+node->nr, "Cb Pos ", + butr->xmin, butr->ymin+40, dx, 20, + &c->t2, 0.0f, 1.0f, 100, 0, " "); + + uiDefButF(block, NUMSLI, 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,8 +1318,21 @@ 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; Index: source/blender/src/toolbox.c =================================================================== RCS file: /cvsroot/bf-blender/blender/source/blender/src/toolbox.c,v retrieving revision 1.142 diff -u -r1.142 toolbox.c --- source/blender/src/toolbox.c 7 Nov 2006 14:25:58 -0000 1.142 +++ source/blender/src/toolbox.c 12 Nov 2006 20:52:44 -0000 @@ -1548,6 +1548,7 @@ #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 @@ { 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 @@ 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 @@ 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 @@ 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); }