Merged the particles-2010 branch with node improvements into trunk.
[blender-staging.git] / source / blender / nodes / composite / nodes / node_composite_filter.c
1 /*
2  * $Id: CMP_filter.c 36593 2011-05-10 11:19:26Z lukastoenne $
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): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /** \file blender/nodes/composite/nodes/node_composite_filter.c
31  *  \ingroup cmpnodes
32  */
33
34
35 #include "node_composite_util.h"
36
37 /* **************** FILTER  ******************** */
38 static bNodeSocketTemplate cmp_node_filter_in[]= {
39         {       SOCK_FLOAT, 1, "Fac",                   1.0f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f, PROP_FACTOR},
40         {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f},
41         {       -1, 0, ""       }
42 };
43 static bNodeSocketTemplate cmp_node_filter_out[]= {
44         {       SOCK_RGBA, 0, "Image"},
45         {       -1, 0, ""       }
46 };
47
48 static void do_filter_edge(CompBuf *out, CompBuf *in, float *filter, float fac)
49 {
50         float *row1, *row2, *row3;
51         float *fp, f1, f2, mfac= 1.0f-fac;
52         int rowlen, x, y, c, pix= in->type;
53         
54         rowlen= in->x;
55         
56         for(y=0; y<in->y; y++) {
57                 /* setup rows */
58                 if(y==0) row1= in->rect;
59                 else row1= in->rect + pix*(y-1)*rowlen;
60                 
61                 row2= in->rect + y*pix*rowlen;
62                 
63                 if(y==in->y-1) row3= row2;
64                 else row3= row2 + pix*rowlen;
65                 
66                 fp= out->rect + pix*y*rowlen;
67                 
68                 if(pix==CB_RGBA) {
69                         QUATCOPY(fp, row2);
70                         fp+= pix;
71                         
72                         for(x=2; x<rowlen; x++) {
73                                 for(c=0; c<3; c++) {
74                                         f1= filter[0]*row1[0] + filter[1]*row1[4] + filter[2]*row1[8] + filter[3]*row2[0] + filter[4]*row2[4] + filter[5]*row2[8] + filter[6]*row3[0] + filter[7]*row3[4] + filter[8]*row3[8];
75                                         f2= filter[0]*row1[0] + filter[3]*row1[4] + filter[6]*row1[8] + filter[1]*row2[0] + filter[4]*row2[4] + filter[7]*row2[8] + filter[2]*row3[0] + filter[5]*row3[4] + filter[8]*row3[8];
76                                         fp[0]= mfac*row2[4] + fac*sqrt(f1*f1 + f2*f2);
77                                         fp++; row1++; row2++; row3++;
78                                 }
79                                 fp[0]= row2[4];
80                                 /* no alpha... will clear it completely */
81                                 fp++; row1++; row2++; row3++;
82                         }
83                         QUATCOPY(fp, row2+4);
84                 }
85                 else if(pix==CB_VAL) {
86                         fp+= pix;
87                         for(x=2; x<rowlen; x++) {
88                                 f1= filter[0]*row1[0] + filter[1]*row1[1] + filter[2]*row1[2] + filter[3]*row2[0] + filter[4]*row2[1] + filter[5]*row2[2] + filter[6]*row3[0] + filter[7]*row3[1] + filter[8]*row3[2];
89                                 f2= filter[0]*row1[0] + filter[3]*row1[1] + filter[6]*row1[2] + filter[1]*row2[0] + filter[4]*row2[1] + filter[7]*row2[2] + filter[2]*row3[0] + filter[5]*row3[1] + filter[8]*row3[2];
90                                 fp[0]= mfac*row2[1] + fac*sqrt(f1*f1 + f2*f2);
91                                 fp++; row1++; row2++; row3++;
92                         }
93                 }
94         }
95 }
96
97 static void do_filter3(CompBuf *out, CompBuf *in, float *filter, float fac)
98 {
99         float *row1, *row2, *row3;
100         float *fp, mfac= 1.0f-fac;
101         int rowlen, x, y, c;
102         int pixlen= in->type;
103         
104         rowlen= in->x;
105         
106         for(y=0; y<in->y; y++) {
107                 /* setup rows */
108                 if(y==0) row1= in->rect;
109                 else row1= in->rect + pixlen*(y-1)*rowlen;
110                 
111                 row2= in->rect + y*pixlen*rowlen;
112                 
113                 if(y==in->y-1) row3= row2;
114                 else row3= row2 + pixlen*rowlen;
115                 
116                 fp= out->rect + pixlen*(y)*rowlen;
117                 
118                 if(pixlen==1) {
119                         fp[0]= row2[0];
120                         fp+= 1;
121                         
122                         for(x=2; x<rowlen; x++) {
123                                 fp[0]= mfac*row2[1] + fac*(filter[0]*row1[0] + filter[1]*row1[1] + filter[2]*row1[2] + filter[3]*row2[0] + filter[4]*row2[1] + filter[5]*row2[2] + filter[6]*row3[0] + filter[7]*row3[1] + filter[8]*row3[2]);
124                                 fp++; row1++; row2++; row3++;
125                         }
126                         fp[0]= row2[1];
127                 }
128                 else if(pixlen==2) {
129                         fp[0]= row2[0];
130                         fp[1]= row2[1];
131                         fp+= 2;
132                         
133                         for(x=2; x<rowlen; x++) {
134                                 for(c=0; c<2; c++) {
135                                         fp[0]= mfac*row2[2] + fac*(filter[0]*row1[0] + filter[1]*row1[2] + filter[2]*row1[4] + filter[3]*row2[0] + filter[4]*row2[2] + filter[5]*row2[4] + filter[6]*row3[0] + filter[7]*row3[2] + filter[8]*row3[4]);
136                                         fp++; row1++; row2++; row3++;
137                                 }
138                         }
139                         fp[0]= row2[2];
140                         fp[1]= row2[3];
141                 }
142                 else if(pixlen==3) {
143                         VECCOPY(fp, row2);
144                         fp+= 3;
145                         
146                         for(x=2; x<rowlen; x++) {
147                                 for(c=0; c<3; c++) {
148                                         fp[0]= mfac*row2[3] + fac*(filter[0]*row1[0] + filter[1]*row1[3] + filter[2]*row1[6] + filter[3]*row2[0] + filter[4]*row2[3] + filter[5]*row2[6] + filter[6]*row3[0] + filter[7]*row3[3] + filter[8]*row3[6]);
149                                         fp++; row1++; row2++; row3++;
150                                 }
151                         }
152                         VECCOPY(fp, row2+3);
153                 }
154                 else {
155                         QUATCOPY(fp, row2);
156                         fp+= 4;
157                         
158                         for(x=2; x<rowlen; x++) {
159                                 for(c=0; c<4; c++) {
160                                         fp[0]= mfac*row2[4] + fac*(filter[0]*row1[0] + filter[1]*row1[4] + filter[2]*row1[8] + filter[3]*row2[0] + filter[4]*row2[4] + filter[5]*row2[8] + filter[6]*row3[0] + filter[7]*row3[4] + filter[8]*row3[8]);
161                                         fp++; row1++; row2++; row3++;
162                                 }
163                         }
164                         QUATCOPY(fp, row2+4);
165                 }
166         }
167 }
168
169
170 static void node_composit_exec_filter(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
171 {
172         static float soft[9]= {1/16.0f, 2/16.0f, 1/16.0f, 2/16.0f, 4/16.0f, 2/16.0f, 1/16.0f, 2/16.0f, 1/16.0f};
173         float sharp[9]= {-1,-1,-1,-1,9,-1,-1,-1,-1};
174         float laplace[9]= {-1/8.0f, -1/8.0f, -1/8.0f, -1/8.0f, 1.0f, -1/8.0f, -1/8.0f, -1/8.0f, -1/8.0f};
175         float sobel[9]= {1,2,1,0,0,0,-1,-2,-1};
176         float prewitt[9]= {1,1,1,0,0,0,-1,-1,-1};
177         float kirsch[9]= {5,5,5,-3,-3,-3,-2,-2,-2};
178         float shadow[9]= {1,2,1,0,1,0,-1,-2,-1};
179         
180         if(out[0]->hasoutput==0) return;
181         
182         /* stack order in: Image */
183         /* stack order out: Image */
184         
185         if(in[1]->data) {
186                 /* make output size of first available input image */
187                 CompBuf *cbuf= in[1]->data;
188                 CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 1); /* allocs */
189                 
190                 /* warning note: xof and yof are applied in pixelprocessor, but should be copied otherwise? */
191                 stackbuf->xof= cbuf->xof;
192                 stackbuf->yof= cbuf->yof;
193                 
194                 switch(node->custom1) {
195                         case CMP_FILT_SOFT:
196                                 do_filter3(stackbuf, cbuf, soft, in[0]->vec[0]);
197                                 break;
198                         case CMP_FILT_SHARP:
199                                 do_filter3(stackbuf, cbuf, sharp, in[0]->vec[0]);
200                                 break;
201                         case CMP_FILT_LAPLACE:
202                                 do_filter3(stackbuf, cbuf, laplace, in[0]->vec[0]);
203                                 break;
204                         case CMP_FILT_SOBEL:
205                                 do_filter_edge(stackbuf, cbuf, sobel, in[0]->vec[0]);
206                                 break;
207                         case CMP_FILT_PREWITT:
208                                 do_filter_edge(stackbuf, cbuf, prewitt, in[0]->vec[0]);
209                                 break;
210                         case CMP_FILT_KIRSCH:
211                                 do_filter_edge(stackbuf, cbuf, kirsch, in[0]->vec[0]);
212                                 break;
213                         case CMP_FILT_SHADOW:
214                                 do_filter3(stackbuf, cbuf, shadow, in[0]->vec[0]);
215                                 break;
216                 }
217                         
218                 out[0]->data= stackbuf;
219                 
220                 generate_preview(data, node, out[0]->data);
221         }
222 }
223
224
225 void register_node_type_cmp_filter(ListBase *lb)
226 {
227         static bNodeType ntype;
228
229         node_type_base(&ntype, CMP_NODE_FILTER, "Filter", NODE_CLASS_OP_FILTER, NODE_PREVIEW|NODE_OPTIONS);
230         node_type_socket_templates(&ntype, cmp_node_filter_in, cmp_node_filter_out);
231         node_type_size(&ntype, 80, 40, 120);
232         node_type_label(&ntype, node_filter_label);
233         node_type_exec(&ntype, node_composit_exec_filter);
234
235         nodeRegisterType(lb, &ntype);
236 }
237
238
239