Initial commit. Not in build system so shouldn't interfere with anything at this...
[blender.git] / source / blender / nodes / intern / CMP_nodes / CMP_diffMatte.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2006 Blender Foundation.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include "../CMP_util.h"
31
32 /* ******************* channel Difference Matte ********************************* */
33 static bNodeSocketType cmp_node_diff_matte_in[]={
34         {SOCK_RGBA,1,"Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
35         {SOCK_RGBA,1,"Key Color", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
36         {-1,0,""}
37 };
38
39 static bNodeSocketType cmp_node_diff_matte_out[]={
40         {SOCK_RGBA,0,"Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
41         {SOCK_VALUE,0,"Matte",0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
42         {-1,0,""}
43 };
44
45 /* note, keyvals is passed on from caller as stack array */
46 /* might have been nicer as temp struct though... */
47 static void do_diff_matte(bNode *node, float *colorbuf, float *inbuf, float *keyvals)
48 {
49         NodeChroma *c= (NodeChroma *)node->storage;
50         float *keymin= keyvals;
51         float *keymax= keyvals+3;
52         float *key=    keyvals+6;
53         float tolerance= keyvals[9];
54         float distance, alpha;
55         
56         /*process the pixel if it is close to the key or already transparent*/
57         if(((colorbuf[0]>keymin[0] && colorbuf[0]<keymax[0]) &&
58                 (colorbuf[1]>keymin[1] && colorbuf[1]<keymax[1]) &&
59                 (colorbuf[2]>keymin[2] && colorbuf[2]<keymax[2])) || inbuf[3]<1.0f) {
60                 
61                 /*true distance from key*/
62                 distance= sqrt((colorbuf[0]-key[0])*(colorbuf[0]-key[0])+
63                                           (colorbuf[1]-key[1])*(colorbuf[1]-key[1])+
64                                           (colorbuf[2]-key[2])*(colorbuf[2]-key[2]));
65                 
66                 /*is it less transparent than the prevous pixel*/
67                 alpha= distance/tolerance;
68                 if(alpha > inbuf[3]) alpha= inbuf[3];
69                 if(alpha > c->fstrength) alpha= 0.0f;
70                 
71                 /*clamp*/
72                 if (alpha>1.0f) alpha=1.0f;
73                 if (alpha<0.0f) alpha=0.0f;
74                 
75                 /*premultiplied picture*/
76                 colorbuf[3]= alpha;
77         }
78         else {
79                 /*foreground object*/
80                 colorbuf[3]= inbuf[3];
81         }
82 }
83
84 static void node_composit_exec_diff_matte(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
85 {
86         /*
87         Losely based on the Sequencer chroma key plug-in, but enhanced to work in other color spaces and
88         uses a differnt difference function (suggested in forums of vfxtalk.com).
89         */
90         CompBuf *workbuf;
91         CompBuf *inbuf;
92         NodeChroma *c;
93         float keyvals[10];
94         float *keymin= keyvals;
95         float *keymax= keyvals+3;
96         float *key=    keyvals+6;
97         float *tolerance= keyvals+9;
98         float t[3];
99         
100         /*is anything connected?*/
101         if(out[0]->hasoutput==0 && out[1]->hasoutput==0) return;
102         /*must have an image imput*/
103         if(in[0]->data==NULL) return;
104         
105         inbuf=typecheck_compbuf(in[0]->data, CB_RGBA);
106         
107         c=node->storage;
108         workbuf=dupalloc_compbuf(inbuf);
109         
110         /*use the input color*/
111         key[0]= in[1]->vec[0];
112         key[1]= in[1]->vec[1];
113         key[2]= in[1]->vec[2];
114         
115         /*get the tolerances from the UI*/
116         t[0]=c->t1;
117         t[1]=c->t2;
118         t[2]=c->t3;
119         
120         /*convert to colorspace*/
121         switch(node->custom1) {
122                 case 1: /*RGB*/
123                                 break;
124                 case 2: /*HSV*/
125                 /*convert the key (in place)*/
126                         rgb_to_hsv(key[0], key[1], key[2], &key[0], &key[1], &key[2]);
127                         composit1_pixel_processor(node, workbuf, inbuf, in[1]->vec, do_rgba_to_hsva, CB_RGBA);
128                         break;
129                 case 3: /*YUV*/
130                         rgb_to_yuv(key[0], key[1], key[2], &key[0], &key[1], &key[2]);
131                         composit1_pixel_processor(node, workbuf, inbuf, in[1]->vec, do_rgba_to_yuva, CB_RGBA);
132                         break;
133                 case 4: /*YCC*/
134                         rgb_to_ycc(key[0], key[1], key[2], &key[0], &key[1], &key[2]);
135                         composit1_pixel_processor(node, workbuf, inbuf, in[1]->vec, do_rgba_to_ycca, CB_RGBA);
136                         /*account for ycc is on a 0..255 scale*/
137                         t[0]= c->t1*255.0;
138                         t[1]= c->t2*255.0;
139                         t[2]= c->t3*255.0;
140                         break;
141                 default:
142                                 break;
143         }
144         
145         /*find min/max tolerances*/
146         keymin[0]= key[0]-t[0];
147         keymin[1]= key[1]-t[1];
148         keymin[2]= key[2]-t[2];
149         keymax[0]= key[0]+t[0];
150         keymax[1]= key[1]+t[1];
151         keymax[2]= key[2]+t[2];
152         
153         /*tolerance*/
154         *tolerance= sqrt((t[0])*(t[0])+
155                                         (t[1])*(t[1])+
156                                         (t[2])*(t[2]));
157         
158         /* note, processor gets a keyvals array passed on as buffer constant */
159         composit2_pixel_processor(node, workbuf, workbuf, in[0]->vec, NULL, keyvals, do_diff_matte, CB_RGBA, CB_VAL);
160         
161         /*convert back to RGB colorspace*/
162         switch(node->custom1) {
163                 case 1: /*RGB*/
164                         composit1_pixel_processor(node, workbuf, workbuf, in[1]->vec, do_copy_rgba, CB_RGBA);
165                         break;
166                 case 2: /*HSV*/
167                         composit1_pixel_processor(node, workbuf, workbuf, in[1]->vec, do_hsva_to_rgba, CB_RGBA);
168                         break;
169                 case 3: /*YUV*/
170                         composit1_pixel_processor(node, workbuf, workbuf, in[1]->vec, do_yuva_to_rgba, CB_RGBA);
171                         break;
172                 case 4: /*YCC*/
173                         composit1_pixel_processor(node, workbuf, workbuf, in[1]->vec, do_ycca_to_rgba, CB_RGBA);
174                         break;
175                 default:
176                         break;
177         }
178         
179         out[0]->data=workbuf;
180         if(out[1]->hasoutput)
181                 out[1]->data=valbuf_from_rgbabuf(workbuf, CHAN_A);
182         generate_preview(node, workbuf);
183
184         if(inbuf!=in[0]->data)
185                 free_compbuf(inbuf);
186 }
187
188 static int node_composit_buts_diff_matte(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
189 {
190    if(block) {
191       short sx= (butr->xmax-butr->xmin)/4;
192       short dx= (butr->xmax-butr->xmin)/3;
193       NodeChroma *c= node->storage;
194
195       uiBlockBeginAlign(block);
196       /*color space selectors*/
197       uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"RGB",
198          butr->xmin,butr->ymin+60,sx,20,
199          &node->custom1,1,1, 0, 0, "RGB Color Space");
200       uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"HSV",
201          butr->xmin+sx,butr->ymin+60,sx,20,
202          &node->custom1,1,2, 0, 0, "HSV Color Space");
203       uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"YUV",
204          butr->xmin+2*sx,butr->ymin+60,sx,20,
205          &node->custom1,1,3, 0, 0, "YUV Color Space");
206       uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"YCC",
207          butr->xmin+3*sx,butr->ymin+60,sx,20,
208          &node->custom1,1,4, 0, 0, "YCbCr Color Space");
209       /*channel tolorences*/
210       uiDefButF(block, NUM, B_NODE_EXEC+node->nr, " ",
211          butr->xmin, butr->ymin+40, dx, 20,
212          &c->t1, 0.0f, 1.0f, 100, 0, "Channel 1 Tolerance");
213       uiDefButF(block, NUM, B_NODE_EXEC+node->nr, " ",
214          butr->xmin+dx, butr->ymin+40, dx, 20,
215          &c->t2, 0.0f, 1.0f, 100, 0, "Channel 2 Tolorence");
216       uiDefButF(block, NUM, B_NODE_EXEC+node->nr, " ",
217          butr->xmin+2*dx, butr->ymin+40, dx, 20,
218          &c->t3, 0.0f, 1.0f, 100, 0, "Channel 3 Tolorence");
219       /*falloff parameters*/
220       /*
221       uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Falloff Size ",
222       butr->xmin, butr->ymin+20, butr->xmax-butr->xmin, 20,
223       &c->fsize, 0.0f, 1.0f, 100, 0, "");
224       */
225       uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Falloff: ",
226          butr->xmin, butr->ymin+20, butr->xmax-butr->xmin, 20,
227          &c->fstrength, 0.0f, 1.0f, 100, 0, "");
228    }
229    return 80;
230 }
231
232 static void node_composit_init_diff_matte(bNode *node)
233 {
234    NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma");
235    node->storage= c;
236    c->t1= 0.01f;
237    c->t2= 0.01f;
238    c->t3= 0.01f;
239    c->fsize= 0.0f;
240    c->fstrength= 0.0f;
241    node->custom1= 1; /* RGB */
242 }
243
244 bNodeType cmp_node_diff_matte={
245         /* type code   */       CMP_NODE_DIFF_MATTE,
246         /* name        */       "Difference Key",
247         /* width+range */       200, 80, 250,
248         /* class+opts  */       NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS,
249         /* input sock  */       cmp_node_diff_matte_in,
250         /* output sock */       cmp_node_diff_matte_out,
251         /* storage     */       "NodeChroma",
252         /* execfunc    */       node_composit_exec_diff_matte,
253    /* butfunc     */       node_composit_buts_diff_matte,
254                            node_composit_init_diff_matte
255 };
256
257