Add parser error handler.
[blender-staging.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         /* Originally based on the information from the book "The Art and Science of Digital Composition" and
193          * discussions from vfxtalk.com .*/
194         CompBuf *cbuf;
195         CompBuf *mask;
196         CompBuf *rgbbuf;
197         CompBuf *spillmap;
198         NodeColorspill *ncs;
199         ncs=node->storage;
200
201         /* early out for missing connections */
202         if(out[0]->hasoutput==0 ) return;
203         if(in[0]->hasinput==0) return;
204         if(in[0]->data==NULL) return;
205         
206         cbuf=typecheck_compbuf(in[0]->data, CB_RGBA);
207         mask=typecheck_compbuf(in[1]->data, CB_VAL);
208         spillmap=alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1);
209         rgbbuf=dupalloc_compbuf(cbuf);
210
211         switch(node->custom1)
212         {
213                 case 1:  /*red spill*/
214                 {
215                         switch(node->custom2)
216                         {
217                                 case 0: /* simple limit */
218                                 {
219                                         if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
220                                                 composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_simple_spillmap_red, CB_RGBA);
221                                         } else {
222                                                 composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_simple_spillmap_red_fac, CB_RGBA,  CB_VAL);
223                                         }
224                                         break;
225                                 }
226                                 case 1: /* average limit */
227                                 {
228                                         if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
229                                                 composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_average_spillmap_red, CB_RGBA);
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                                         } else {
253                                                 composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_simple_spillmap_green_fac, CB_RGBA,  CB_VAL);
254                                         }
255                                         break;
256                                 }
257                                 case 1: /* average limit */
258                                 {
259                                         if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
260                                                 composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_average_spillmap_green, CB_RGBA);
261                                         } else {
262                                                 composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_average_spillmap_green_fac, CB_RGBA,  CB_VAL);
263                                         }
264                                         break;
265                                 }
266                         }
267                         if(ncs->unspill==0) {
268                                 ncs->uspillr=0.0f;
269                                 ncs->uspillg=1.0f;
270                                 ncs->uspillb=0.0f;
271                         }
272                         composit2_pixel_processor(node, rgbbuf, cbuf, in[0]->vec, spillmap, NULL, do_apply_spillmap_green, CB_RGBA, CB_VAL);
273                         break;
274                 }
275                 case 3: /*blue spill*/
276                 {
277                         switch(node->custom2)
278                         {
279                                 case 0: /* simple limit */
280                                 {
281                                         if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
282                                                 composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_simple_spillmap_blue, CB_RGBA);
283                                         } else {
284                                                 composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_simple_spillmap_blue_fac, CB_RGBA,  CB_VAL);
285                                         }
286                                         break;
287                                 }
288                                 case 1: /* average limit */
289                                 {
290                                         if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
291                                                 composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_average_spillmap_blue, CB_RGBA);
292                                         } else {
293                                                 composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_average_spillmap_blue_fac, CB_RGBA,  CB_VAL);
294                                         }
295                                         break;
296                                 }
297                         }
298                         if(ncs->unspill==0) {
299                                 ncs->uspillr=0.0f;
300                                 ncs->uspillg=0.0f;
301                                 ncs->uspillb=1.0f;
302                         }
303                         composit2_pixel_processor(node, rgbbuf, cbuf, in[0]->vec, spillmap, NULL, do_apply_spillmap_blue, CB_RGBA, CB_VAL);
304                         break;
305                 }
306                 default:
307                         break;
308         }
309
310         out[0]->data=rgbbuf;
311
312         if(cbuf!=in[0]->data)
313                 free_compbuf(cbuf);
314
315         free_compbuf(spillmap);
316 }
317
318 static void node_composit_init_color_spill(bNode *node)
319 {
320         NodeColorspill *ncs= MEM_callocN(sizeof(NodeColorspill), "node colorspill");
321         node->storage=ncs;
322         node->custom1= 2; /* green channel */
323         node->custom2= 0; /* simple limit algo*/
324         ncs->limchan= 0;  /* limit by red */
325         ncs->limscale= 1.0f; /* limit scaling factor */
326         ncs->unspill=0;   /* do not use unspill */
327 }
328
329 void register_node_type_cmp_color_spill(ListBase *lb)
330 {
331         static bNodeType ntype;
332         
333         node_type_base(&ntype, CMP_NODE_COLOR_SPILL, "Color Spill", NODE_CLASS_MATTE, NODE_OPTIONS,
334                                    cmp_node_color_spill_in, cmp_node_color_spill_out);
335         node_type_size(&ntype, 140, 80, 200);
336         node_type_init(&ntype, node_composit_init_color_spill);
337         node_type_storage(&ntype, "NodeColorspill", node_free_standard_storage, node_copy_standard_storage);
338         node_type_exec(&ntype, node_composit_exec_color_spill);
339         
340         nodeRegisterType(lb, &ntype);
341 }