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.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -684,8 +684,37 @@ 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,
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user