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