style cleanup: follow style guide for formatting of if/for/while loops, and else...
[blender.git] / source / blender / nodes / composite / nodes / node_composite_colorSpill.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2006 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Bob Holcomb, Xavier Thomas
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/nodes/composite/nodes/node_composite_colorSpill.c
29  *  \ingroup cmpnodes
30  */
31
32
33
34 #include "node_composite_util.h"
35
36 #define avg(a,b) ((a+b)/2)
37
38 /* ******************* Color Spill Supression ********************************* */
39 static bNodeSocketTemplate cmp_node_color_spill_in[]={
40         {SOCK_RGBA,1,"Image", 1.0f, 1.0f, 1.0f, 1.0f},
41         {SOCK_FLOAT, 1, "Fac",  1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR},
42         {-1,0,""}
43 };
44
45 static bNodeSocketTemplate cmp_node_color_spill_out[]={
46         {SOCK_RGBA,0,"Image"},
47         {-1,0,""}
48 };
49
50 static void do_simple_spillmap_red(bNode *node, float* out, float *in)
51 {
52         NodeColorspill *ncs;
53         ncs=node->storage;
54         out[0]=in[0]-( ncs->limscale * in[ncs->limchan] );
55 }
56
57 static void do_simple_spillmap_red_fac(bNode *node, float* out, float *in, float *fac)
58 {
59         NodeColorspill *ncs;
60         ncs=node->storage;
61
62         out[0] = *fac * (in[0]-( ncs->limscale * in[ncs->limchan]));
63 }
64
65 static void do_simple_spillmap_green(bNode *node, float* out, float *in)
66 {
67         NodeColorspill *ncs;
68         ncs=node->storage;
69         out[0]=in[1]-( ncs->limscale * in[ncs->limchan] );
70 }
71
72 static void do_simple_spillmap_green_fac(bNode *node, float* out, float *in, float *fac)
73 {
74         NodeColorspill *ncs;
75         ncs=node->storage;
76
77         out[0] = *fac * (in[1]-( ncs->limscale * in[ncs->limchan]));
78 }
79
80 static void do_simple_spillmap_blue(bNode *node, float* out, float *in)
81 {
82         NodeColorspill *ncs;
83         ncs=node->storage;
84         out[0]=in[2]-( ncs->limscale * in[ncs->limchan] );
85 }
86
87 static void do_simple_spillmap_blue_fac(bNode *node, float* out, float *in, float *fac)
88 {
89         NodeColorspill *ncs;
90         ncs=node->storage;
91
92         out[0] = *fac * (in[2]-( ncs->limscale * in[ncs->limchan]));
93 }
94
95 static void do_average_spillmap_red(bNode *node, float* out, float *in)
96 {
97         NodeColorspill *ncs;
98         ncs=node->storage;
99         out[0]=in[0]-(ncs->limscale * avg(in[1], in[2]) );
100 }
101
102 static void do_average_spillmap_red_fac(bNode *node, float* out, float *in, float *fac)
103 {
104         NodeColorspill *ncs;
105         ncs=node->storage;
106
107         out[0] = *fac * (in[0]-(ncs->limscale * avg(in[1], in[2]) ));
108 }
109
110 static void do_average_spillmap_green(bNode *node, float* out, float *in)
111 {
112         NodeColorspill *ncs;
113         ncs=node->storage;
114         out[0]=in[1]-(ncs->limscale * avg(in[0], in[2]) );
115 }
116
117 static void do_average_spillmap_green_fac(bNode *node, float* out, float *in, float *fac)
118 {
119         NodeColorspill *ncs;
120         ncs=node->storage;
121
122         out[0] = *fac * (in[0]-(ncs->limscale * avg(in[0], in[2]) ));
123 }
124
125 static void do_average_spillmap_blue(bNode *node, float* out, float *in)
126 {
127         NodeColorspill *ncs;
128         ncs=node->storage;
129         out[0]=in[2]-(ncs->limscale * avg(in[0], in[1]) );
130 }
131
132 static void do_average_spillmap_blue_fac(bNode *node, float* out, float *in, float *fac)
133 {
134         NodeColorspill *ncs;
135         ncs=node->storage;
136
137         out[0] = *fac * (in[0]-(ncs->limscale * avg(in[0], in[1]) ));
138 }
139
140 static void do_apply_spillmap_red(bNode *node, float* out, float *in, float *map)
141 {       
142         NodeColorspill *ncs;
143         ncs=node->storage;
144         if (map[0]>0) {
145                 out[0]=in[0]-(ncs->uspillr*map[0]);
146                 out[1]=in[1]+(ncs->uspillg*map[0]);
147                 out[2]=in[2]+(ncs->uspillb*map[0]);
148         }
149         else {
150                 out[0]=in[0];
151                 out[1]=in[1];
152                 out[2]=in[2];
153         }
154 }
155
156 static void do_apply_spillmap_green(bNode *node, float* out, float *in, float *map)
157 {
158         NodeColorspill *ncs;
159         ncs=node->storage;
160         if (map[0]>0) {
161                 out[0]=in[0]+(ncs->uspillr*map[0]);
162                 out[1]=in[1]-(ncs->uspillg*map[0]);
163                 out[2]=in[2]+(ncs->uspillb*map[0]);
164    }
165         else {
166                 out[0]=in[0];
167                 out[1]=in[1];
168                 out[2]=in[2];
169         }
170 }
171
172 static void do_apply_spillmap_blue(bNode *node, float* out, float *in, float *map)
173 {
174         NodeColorspill *ncs;
175         ncs=node->storage;
176         if (map[0]>0) {
177                 out[0]=in[0]+(ncs->uspillr*map[0]);
178                 out[1]=in[1]+(ncs->uspillg*map[0]);
179                 out[2]=in[2]-(ncs->uspillb*map[0]);
180    }
181         else {
182                 out[0]=in[0];
183                 out[1]=in[1];
184                 out[2]=in[2];
185         }
186 }
187
188 static void node_composit_exec_color_spill(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
189 {
190         /* Originally based on the information from the book "The Art and Science of Digital Composition" and
191          * discussions from vfxtalk.com .*/
192         CompBuf *cbuf;
193         /* CompBuf *mask; */ /* UNUSED */
194         CompBuf *rgbbuf;
195         CompBuf *spillmap;
196         NodeColorspill *ncs;
197         ncs=node->storage;
198
199         /* early out for missing connections */
200         if (out[0]->hasoutput==0 ) return;
201         if (in[0]->hasinput==0) return;
202         if (in[0]->data==NULL) return;
203         
204         cbuf=typecheck_compbuf(in[0]->data, CB_RGBA);
205         /* mask= */ /* UNUSED */ typecheck_compbuf(in[1]->data, CB_VAL);
206         spillmap=alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1);
207         rgbbuf=dupalloc_compbuf(cbuf);
208
209         switch(node->custom1)
210         {
211                 case 1:  /*red spill*/
212                 {
213                         switch(node->custom2)
214                         {
215                                 case 0: /* simple limit */
216                                 {
217                                         if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
218                                                 composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_simple_spillmap_red, CB_RGBA);
219                                         }
220                                         else {
221                                                 composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_simple_spillmap_red_fac, CB_RGBA,  CB_VAL);
222                                         }
223                                         break;
224                                 }
225                                 case 1: /* average limit */
226                                 {
227                                         if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
228                                                 composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_average_spillmap_red, CB_RGBA);
229                                         }
230                                         else {
231                                                 composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_average_spillmap_red_fac, CB_RGBA,  CB_VAL);
232                                         }
233                                         break;
234                                 }
235                         }
236                         if (ncs->unspill==0) {
237                                 ncs->uspillr=1.0f;
238                                 ncs->uspillg=0.0f;
239                                 ncs->uspillb=0.0f;
240                         }
241                         composit2_pixel_processor(node, rgbbuf, cbuf, in[0]->vec, spillmap, NULL, do_apply_spillmap_red, CB_RGBA, CB_VAL);
242                         break;
243                 }
244                 case 2: /*green spill*/
245                 {
246                         switch(node->custom2)
247                         {
248                                 case 0: /* simple limit */
249                                 {
250                                         if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
251                                                 composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_simple_spillmap_green, CB_RGBA);
252                                         }
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                                         }
263                                         else {
264                                                 composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_average_spillmap_green_fac, CB_RGBA,  CB_VAL);
265                                         }
266                                         break;
267                                 }
268                         }
269                         if (ncs->unspill==0) {
270                                 ncs->uspillr=0.0f;
271                                 ncs->uspillg=1.0f;
272                                 ncs->uspillb=0.0f;
273                         }
274                         composit2_pixel_processor(node, rgbbuf, cbuf, in[0]->vec, spillmap, NULL, do_apply_spillmap_green, CB_RGBA, CB_VAL);
275                         break;
276                 }
277                 case 3: /*blue spill*/
278                 {
279                         switch(node->custom2)
280                         {
281                                 case 0: /* simple limit */
282                                 {
283                                         if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
284                                                 composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_simple_spillmap_blue, CB_RGBA);
285                                         }
286                                         else {
287                                                 composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_simple_spillmap_blue_fac, CB_RGBA,  CB_VAL);
288                                         }
289                                         break;
290                                 }
291                                 case 1: /* average limit */
292                                 {
293                                         if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
294                                                 composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_average_spillmap_blue, CB_RGBA);
295                                         }
296                                         else {
297                                                 composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_average_spillmap_blue_fac, CB_RGBA,  CB_VAL);
298                                         }
299                                         break;
300                                 }
301                         }
302                         if (ncs->unspill==0) {
303                                 ncs->uspillr=0.0f;
304                                 ncs->uspillg=0.0f;
305                                 ncs->uspillb=1.0f;
306                         }
307                         composit2_pixel_processor(node, rgbbuf, cbuf, in[0]->vec, spillmap, NULL, do_apply_spillmap_blue, CB_RGBA, CB_VAL);
308                         break;
309                 }
310                 default:
311                         break;
312         }
313
314         out[0]->data=rgbbuf;
315
316         if (cbuf!=in[0]->data)
317                 free_compbuf(cbuf);
318
319         free_compbuf(spillmap);
320 }
321
322 static void node_composit_init_color_spill(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp))
323 {
324         NodeColorspill *ncs= MEM_callocN(sizeof(NodeColorspill), "node colorspill");
325         node->storage=ncs;
326         node->custom1= 2; /* green channel */
327         node->custom2= 0; /* simple limit algo*/
328         ncs->limchan= 0;  /* limit by red */
329         ncs->limscale= 1.0f; /* limit scaling factor */
330         ncs->unspill=0;   /* do not use unspill */
331 }
332
333 void register_node_type_cmp_color_spill(bNodeTreeType *ttype)
334 {
335         static bNodeType ntype;
336         
337         node_type_base(ttype, &ntype, CMP_NODE_COLOR_SPILL, "Color Spill", NODE_CLASS_MATTE, NODE_OPTIONS);
338         node_type_socket_templates(&ntype, cmp_node_color_spill_in, cmp_node_color_spill_out);
339         node_type_size(&ntype, 140, 80, 200);
340         node_type_init(&ntype, node_composit_init_color_spill);
341         node_type_storage(&ntype, "NodeColorspill", node_free_standard_storage, node_copy_standard_storage);
342         node_type_exec(&ntype, node_composit_exec_color_spill);
343         
344         nodeRegisterType(ttype, &ntype);
345 }