style cleanup: follow style guide for formatting of if/for/while loops, and else...
[blender.git] / source / blender / nodes / composite / nodes / node_composite_transform.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) 2011 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Blender Foundation,
24  *                 Sergey Sharybin
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 /** \file blender/nodes/composite/nodes/node_composite_transform.c
30  *  \ingroup cmpnodes
31  */
32
33 #include "node_composite_util.h"
34
35 /* **************** Transform  ******************** */
36
37 static bNodeSocketTemplate cmp_node_transform_in[]= {
38         {       SOCK_RGBA,              1,      "Image",                        0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
39         {       SOCK_FLOAT,             1,      "X",                            0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f},
40         {       SOCK_FLOAT,             1,      "Y",                            0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f},
41         {       SOCK_FLOAT,             1,      "Angle",                        0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f, PROP_ANGLE},
42         {       SOCK_FLOAT,             1,      "Scale",                        1.0f, 0.0f, 0.0f, 0.0f, 0.0001f, CMP_SCALE_MAX},
43         {       -1, 0, ""       }
44 };
45
46 static bNodeSocketTemplate cmp_node_transform_out[]= {
47         {       SOCK_RGBA, 0, "Image"},
48         {       -1, 0, ""       }
49 };
50
51 CompBuf* node_composit_transform(CompBuf *cbuf, float x, float y, float angle, float scale, int filter_type)
52 {
53         CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1);
54         ImBuf *ibuf, *obuf;
55         float mat[4][4], lmat[4][4], rmat[4][4], smat[4][4], cmat[4][4], icmat[4][4];
56         float svec[3]= {scale, scale, scale}, loc[2]= {x, y};
57
58         unit_m4(rmat);
59         unit_m4(lmat);
60         unit_m4(smat);
61         unit_m4(cmat);
62
63         /* image center as rotation center */
64         cmat[3][0]= (float)cbuf->x/2.0f;
65         cmat[3][1]= (float)cbuf->y/2.0f;
66         invert_m4_m4(icmat, cmat);
67
68         size_to_mat4(smat, svec);               /* scale matrix */
69         add_v2_v2(lmat[3], loc);                /* tranlation matrix */
70         rotate_m4(rmat, 'Z', angle);    /* rotation matrix */
71
72         /* compose transformation matrix */
73         mul_serie_m4(mat, lmat, cmat, rmat, smat, icmat, NULL, NULL, NULL);
74
75         invert_m4(mat);
76
77         ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0);
78         obuf= IMB_allocImBuf(stackbuf->x, stackbuf->y, 32, 0);
79
80         if (ibuf && obuf) {
81                 int i, j;
82
83                 ibuf->rect_float= cbuf->rect;
84                 obuf->rect_float= stackbuf->rect;
85
86                 for (j=0; j<cbuf->y; j++) {
87                         for (i=0; i<cbuf->x;i++) {
88                                 float vec[3]= {i, j, 0};
89
90                                 mul_v3_m4v3(vec, mat, vec);
91
92                                 switch(filter_type) {
93                                         case 0:
94                                                 neareast_interpolation(ibuf, obuf, vec[0], vec[1], i, j);
95                                                 break;
96                                         case 1:
97                                                 bilinear_interpolation(ibuf, obuf, vec[0], vec[1], i, j);
98                                                 break;
99                                         case 2:
100                                                 bicubic_interpolation(ibuf, obuf, vec[0], vec[1], i, j);
101                                                 break;
102                                 }
103                         }
104                 }
105
106                 IMB_freeImBuf(ibuf);
107                 IMB_freeImBuf(obuf);
108         }
109
110         /* pass on output and free */
111         return stackbuf;
112 }
113
114 static void node_composit_exec_transform(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
115 {
116         if (in[0]->data) {
117                 CompBuf *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA);
118                 CompBuf *stackbuf;
119
120                 stackbuf= node_composit_transform(cbuf, in[1]->vec[0], in[2]->vec[0], in[3]->vec[0], in[4]->vec[0], node->custom1);
121
122                 /* pass on output and free */
123                 out[0]->data= stackbuf;
124
125                 if (cbuf!=in[0]->data)
126                         free_compbuf(cbuf);
127         }
128 }
129
130 void register_node_type_cmp_transform(bNodeTreeType *ttype)
131 {
132         static bNodeType ntype;
133
134         node_type_base(ttype, &ntype, CMP_NODE_TRANSFORM, "Transform", NODE_CLASS_DISTORT, NODE_OPTIONS);
135         node_type_socket_templates(&ntype, cmp_node_transform_in, cmp_node_transform_out);
136         node_type_size(&ntype, 140, 100, 320);
137         node_type_exec(&ntype, node_composit_exec_transform);
138
139         nodeRegisterType(ttype, &ntype);
140 }