whitespace only, no functional change mixed tabs/spaces --> tabs.
[blender.git] / source / blender / nodes / intern / CMP_nodes / CMP_colorSpill.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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): Bob Holcomb, Xavier Thomas
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /** \file blender/nodes/intern/CMP_nodes/CMP_colorSpill.c
31  *  \ingroup cmpnodes
32  */
33
34
35
36 #include "../CMP_util.h"
37
38 #define avg(a,b) ((a+b)/2)
39
40 /* ******************* Color Spill Supression ********************************* */
41 static bNodeSocketType cmp_node_color_spill_in[]={
42    {SOCK_RGBA,1,"Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
43    {SOCK_VALUE, 1, "Fac",       1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
44         {-1,0,""}
45 };
46
47 static bNodeSocketType cmp_node_color_spill_out[]={
48         {SOCK_RGBA,0,"Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
49         {-1,0,""}
50 };
51
52 static void do_simple_spillmap_red(bNode *node, float* out, float *in)
53 {
54    NodeColorspill *ncs;
55         ncs=node->storage;
56         out[0]=in[0]-( ncs->limscale * in[ncs->limchan] );
57 }
58
59 static void do_simple_spillmap_red_fac(bNode *node, float* out, float *in, float *fac)
60 {
61    NodeColorspill *ncs;
62    ncs=node->storage;
63
64    out[0] = *fac * (in[0]-( ncs->limscale * in[ncs->limchan]));
65 }
66
67 static void do_simple_spillmap_green(bNode *node, float* out, float *in)
68 {
69         NodeColorspill *ncs;
70         ncs=node->storage;
71         out[0]=in[1]-( ncs->limscale * in[ncs->limchan] );
72 }
73
74 static void do_simple_spillmap_green_fac(bNode *node, float* out, float *in, float *fac)
75 {
76    NodeColorspill *ncs;
77    ncs=node->storage;
78
79    out[0] = *fac * (in[1]-( ncs->limscale * in[ncs->limchan]));
80 }
81
82 static void do_simple_spillmap_blue(bNode *node, float* out, float *in)
83 {
84         NodeColorspill *ncs;
85         ncs=node->storage;
86         out[0]=in[2]-( ncs->limscale * in[ncs->limchan] );
87 }
88
89 static void do_simple_spillmap_blue_fac(bNode *node, float* out, float *in, float *fac)
90 {
91    NodeColorspill *ncs;
92    ncs=node->storage;
93
94    out[0] = *fac * (in[2]-( ncs->limscale * in[ncs->limchan]));
95 }
96
97 static void do_average_spillmap_red(bNode *node, float* out, float *in)
98 {
99         NodeColorspill *ncs;
100         ncs=node->storage;
101         out[0]=in[0]-(ncs->limscale * avg(in[1], in[2]) );
102 }
103
104 static void do_average_spillmap_red_fac(bNode *node, float* out, float *in, float *fac)
105 {
106    NodeColorspill *ncs;
107    ncs=node->storage;
108
109    out[0] = *fac * (in[0]-(ncs->limscale * avg(in[1], in[2]) ));
110 }
111
112 static void do_average_spillmap_green(bNode *node, float* out, float *in)
113 {
114         NodeColorspill *ncs;
115         ncs=node->storage;
116         out[0]=in[1]-(ncs->limscale * avg(in[0], in[2]) );
117 }
118
119 static void do_average_spillmap_green_fac(bNode *node, float* out, float *in, float *fac)
120 {
121    NodeColorspill *ncs;
122    ncs=node->storage;
123
124    out[0] = *fac * (in[0]-(ncs->limscale * avg(in[0], in[2]) ));
125 }
126
127 static void do_average_spillmap_blue(bNode *node, float* out, float *in)
128 {
129         NodeColorspill *ncs;
130         ncs=node->storage;
131         out[0]=in[2]-(ncs->limscale * avg(in[0], in[1]) );
132 }
133
134 static void do_average_spillmap_blue_fac(bNode *node, float* out, float *in, float *fac)
135 {
136    NodeColorspill *ncs;
137    ncs=node->storage;
138
139    out[0] = *fac * (in[0]-(ncs->limscale * avg(in[0], in[1]) ));
140 }
141
142 static void do_apply_spillmap_red(bNode *node, float* out, float *in, float *map)
143 {       
144         NodeColorspill *ncs;
145         ncs=node->storage;
146         if(map[0]>0) {
147                 out[0]=in[0]-(ncs->uspillr*map[0]);
148                 out[1]=in[1]+(ncs->uspillg*map[0]);
149                 out[2]=in[2]+(ncs->uspillb*map[0]);
150         }
151         else {
152                 out[0]=in[0];
153                 out[1]=in[1];
154                 out[2]=in[2];
155         }
156 }
157
158 static void do_apply_spillmap_green(bNode *node, float* out, float *in, float *map)
159 {
160         NodeColorspill *ncs;
161         ncs=node->storage;
162         if(map[0]>0) {
163                 out[0]=in[0]+(ncs->uspillr*map[0]);
164                 out[1]=in[1]-(ncs->uspillg*map[0]);
165                 out[2]=in[2]+(ncs->uspillb*map[0]);
166    }
167         else {
168                 out[0]=in[0];
169                 out[1]=in[1];
170                 out[2]=in[2];
171         }
172 }
173
174 static void do_apply_spillmap_blue(bNode *node, float* out, float *in, float *map)
175 {
176         NodeColorspill *ncs;
177         ncs=node->storage;
178         if(map[0]>0) {
179                 out[0]=in[0]+(ncs->uspillr*map[0]);
180                 out[1]=in[1]+(ncs->uspillg*map[0]);
181                 out[2]=in[2]-(ncs->uspillb*map[0]);
182    }
183         else {
184                 out[0]=in[0];
185                 out[1]=in[1];
186                 out[2]=in[2];
187         }
188 }
189
190 static void node_composit_exec_color_spill(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
191 {
192         /*
193         Originally based on the information from the book "The Art and Science of Digital Composition" and 
194         discussions from vfxtalk.com.*/
195    CompBuf *cbuf;
196    CompBuf *mask;
197         CompBuf *rgbbuf;
198         CompBuf *spillmap;
199         NodeColorspill *ncs;
200         ncs=node->storage;
201
202    /* early out for missing connections */
203    if(out[0]->hasoutput==0 ) return;
204    if(in[0]->hasinput==0) return;
205    if(in[0]->data==NULL) return;
206         
207    cbuf=typecheck_compbuf(in[0]->data, CB_RGBA);
208    mask=typecheck_compbuf(in[1]->data, CB_VAL);
209         spillmap=alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1);
210         rgbbuf=dupalloc_compbuf(cbuf);
211
212         switch(node->custom1)
213         {
214         case 1:  /*red spill*/
215                 {
216                         switch(node->custom2)
217                         {
218          case 0: /* simple limit */
219             {
220                if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
221                   composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_simple_spillmap_red, CB_RGBA);
222                } else {
223                   composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_simple_spillmap_red_fac, CB_RGBA,  CB_VAL);
224                }
225                                         break;
226                                 }
227          case 1: /* average limit */
228             {
229                if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
230                   composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_average_spillmap_red, CB_RGBA);
231                } else {
232                   composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_average_spillmap_red_fac, CB_RGBA,  CB_VAL);
233                }
234                                         break;
235                                 }
236                         }
237                         if(ncs->unspill==0) {
238                                 ncs->uspillr=1.0f;
239                                 ncs->uspillg=0.0f;
240                                 ncs->uspillb=0.0f;
241                         }
242                         composit2_pixel_processor(node, rgbbuf, cbuf, in[0]->vec, spillmap, NULL, do_apply_spillmap_red, CB_RGBA, CB_VAL);
243                         break;
244                 }
245         case 2: /*green spill*/
246                 {
247                         switch(node->custom2)
248                         {
249          case 0: /* simple limit */
250             {
251                if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
252                   composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_simple_spillmap_green, CB_RGBA);
253                } else {
254                   composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_simple_spillmap_green_fac, CB_RGBA,  CB_VAL);
255                }
256                break;
257             }
258          case 1: /* average limit */
259             {
260                if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
261                   composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_average_spillmap_green, CB_RGBA);
262                } else {
263                   composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_average_spillmap_green_fac, CB_RGBA,  CB_VAL);
264                }
265                break;
266             }
267                         }
268                         if(ncs->unspill==0) {
269                                 ncs->uspillr=0.0f;
270                                 ncs->uspillg=1.0f;
271                                 ncs->uspillb=0.0f;
272          }
273                         composit2_pixel_processor(node, rgbbuf, cbuf, in[0]->vec, spillmap, NULL, do_apply_spillmap_green, CB_RGBA, CB_VAL);
274                         break;
275                 }
276         case 3: /*blue spill*/
277                 {
278                         switch(node->custom2)
279                         {
280          case 0: /* simple limit */
281             {
282                if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
283                   composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_simple_spillmap_blue, CB_RGBA);
284                } else {
285                   composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_simple_spillmap_blue_fac, CB_RGBA,  CB_VAL);
286                }
287                break;
288             }
289          case 1: /* average limit */
290             {
291                if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
292                   composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_average_spillmap_blue, CB_RGBA);
293                } else {
294                   composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_average_spillmap_blue_fac, CB_RGBA,  CB_VAL);
295                }
296                break;
297             }
298                         }
299                         if(ncs->unspill==0) {
300                                 ncs->uspillr=0.0f;
301                                 ncs->uspillg=0.0f;
302                                 ncs->uspillb=1.0f;
303                         }
304                         composit2_pixel_processor(node, rgbbuf, cbuf, in[0]->vec, spillmap, NULL, do_apply_spillmap_blue, CB_RGBA, CB_VAL);
305                         break;
306                 }
307         default:
308                 break;
309         }
310
311         out[0]->data=rgbbuf;
312
313         if(cbuf!=in[0]->data)
314                 free_compbuf(cbuf);
315    
316    free_compbuf(spillmap);
317 }
318
319 static void node_composit_init_color_spill(bNode *node)
320 {
321    NodeColorspill *ncs= MEM_callocN(sizeof(NodeColorspill), "node colorspill");
322    node->storage=ncs;
323    node->custom1= 2; /* green channel */
324    node->custom2= 0; /* simple limit algo*/
325    ncs->limchan= 0;  /* limit by red */
326    ncs->limscale= 1.0f; /* limit scaling factor */
327    ncs->unspill=0;   /* do not use unspill */
328 }
329
330 void register_node_type_cmp_color_spill(ListBase *lb)
331 {
332         static bNodeType ntype;
333         
334         node_type_base(&ntype, CMP_NODE_COLOR_SPILL, "Color Spill", NODE_CLASS_MATTE, NODE_OPTIONS,
335                                    cmp_node_color_spill_in, cmp_node_color_spill_out);
336         node_type_size(&ntype, 140, 80, 200);
337         node_type_init(&ntype, node_composit_init_color_spill);
338         node_type_storage(&ntype, "NodeColorspill", node_free_standard_storage, node_copy_standard_storage);
339         node_type_exec(&ntype, node_composit_exec_color_spill);
340         
341         nodeRegisterType(lb, &ntype);
342 }