1a5e3150f53f393cbc9fd5c98cedebe738ca46b8
[blender-staging.git] / source / blender / nodes / composite / nodes / node_composite_directionalblur.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): Alfredo de Greef  (eeshlo)
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /** \file blender/nodes/composite/nodes/node_composite_directionalblur.c
31  *  \ingroup cmpnodes
32  */
33
34
35 #include "node_composite_util.h"
36
37 static bNodeSocketTemplate cmp_node_dblur_in[]= {
38         {       SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.f},
39         {       -1, 0, ""       }
40 };
41
42 static bNodeSocketTemplate cmp_node_dblur_out[]= {
43         {       SOCK_RGBA, 0, "Image"},
44         {       -1, 0, ""       }
45 };
46
47 static CompBuf *dblur(bNode *node, CompBuf *img, int iterations, int wrap,
48                   float center_x, float center_y, float dist, float angle, float spin, float zoom)
49 {
50         if ((dist != 0.f) || (spin != 0.f) || (zoom != 0.f)) {
51                 void (*getpix)(CompBuf*, float, float, float*) = wrap ? qd_getPixelLerpWrap : qd_getPixelLerp;
52                 const float a= angle * (float)M_PI / 180.f;
53                 const float itsc= 1.f / pow(2.f, (float)iterations);
54                 float D;
55                 float center_x_pix, center_y_pix;
56                 float tx, ty;
57                 float sc, rot;
58                 CompBuf *tmp;
59                 int i, j;
60                 
61                 tmp= dupalloc_compbuf(img);
62                 
63                 D= dist * sqrtf(img->x * img->x + img->y * img->y);
64                 center_x_pix= center_x * img->x;
65                 center_y_pix= center_y * img->y;
66
67                 tx=  itsc * D * cos(a);
68                 ty= -itsc * D * sin(a);
69                 sc=  itsc * zoom;
70                 rot= itsc * spin * (float)M_PI / 180.f;
71
72                 /* blur the image */
73                 for(i= 0; i < iterations; ++i) {
74                         const float cs= cos(rot), ss= sin(rot);
75                         const float isc= 1.f / (1.f + sc);
76                         unsigned int x, y;
77                         float col[4]= {0,0,0,0};
78
79                         for(y= 0; y < img->y; ++y) {
80                                 const float v= isc * (y - center_y_pix) + ty;
81
82                                 for(x= 0; x < img->x; ++x) {
83                                         const float  u= isc * (x - center_x_pix) + tx;
84                                         unsigned int p= (x + y * img->x) * img->type;
85
86                                         getpix(tmp, cs * u + ss * v + center_x_pix, cs * v - ss * u + center_y_pix, col);
87
88                                         /* mix img and transformed tmp */
89                                         for(j= 0; j < 4; ++j)
90                                                 img->rect[p + j]= AVG2(img->rect[p + j], col[j]);
91                                 }
92                         }
93
94                         /* copy img to tmp */
95                         if(i != (iterations - 1)) 
96                                 memcpy(tmp->rect, img->rect, sizeof(float) * img->x * img->y * img->type);
97
98                         /* double transformations */
99                         tx *= 2.f, ty  *= 2.f;
100                         sc *= 2.f, rot *= 2.f;
101
102                         if(node->exec & NODE_BREAK) break;
103                 }
104
105                 free_compbuf(tmp);
106         }
107
108         return img;
109 }
110
111 static void node_composit_exec_dblur(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
112 {
113         NodeDBlurData *ndbd= node->storage;
114         CompBuf *new, *img= in[0]->data;
115         
116         if((img == NULL) || (out[0]->hasoutput == 0)) return;
117
118         if (img->type != CB_RGBA)
119                 new = typecheck_compbuf(img, CB_RGBA);
120         else
121                 new = dupalloc_compbuf(img);
122         
123         out[0]->data= dblur(node, new, ndbd->iter, ndbd->wrap, ndbd->center_x, ndbd->center_y, ndbd->distance, ndbd->angle, ndbd->spin, ndbd->zoom);
124 }
125
126 static void node_composit_init_dblur(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp))
127 {
128         NodeDBlurData *ndbd= MEM_callocN(sizeof(NodeDBlurData), "node dblur data");
129         node->storage= ndbd;
130         ndbd->center_x= 0.5;
131         ndbd->center_y= 0.5;
132 }
133
134 void register_node_type_cmp_dblur(ListBase *lb)
135 {
136         static bNodeType ntype;
137
138         node_type_base(&ntype, CMP_NODE_DBLUR, "Directional Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
139         node_type_socket_templates(&ntype, cmp_node_dblur_in, cmp_node_dblur_out);
140         node_type_size(&ntype, 150, 120, 200);
141         node_type_init(&ntype, node_composit_init_dblur);
142         node_type_storage(&ntype, "NodeDBlurData", node_free_standard_storage, node_copy_standard_storage);
143         node_type_exec(&ntype, node_composit_exec_dblur);
144
145         nodeRegisterType(lb, &ntype);
146 }
147