Initial commit. Not in build system so shouldn't interfere with anything at this...
[blender-staging.git] / source / blender / nodes / intern / CMP_nodes / CMP_rotate.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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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 #include "../CMP_util.h"
31
32 /* **************** Rotate  ******************** */
33
34 static bNodeSocketType cmp_node_rotate_in[]= {
35         {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
36         {       SOCK_VALUE, 1, "Degr",                  0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f},
37         {       -1, 0, ""       }
38 };
39 static bNodeSocketType cmp_node_rotate_out[]= {
40         {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
41         {       -1, 0, ""       }
42 };
43
44 /* function assumes out to be zero'ed, only does RGBA */
45 static void bilinear_interpolation_rotate(CompBuf *in, float *out, float u, float v)
46 {
47         float *row1, *row2, *row3, *row4, a, b;
48         float a_b, ma_b, a_mb, ma_mb;
49         float empty[4]= {0.0f, 0.0f, 0.0f, 0.0f};
50         int y1, y2, x1, x2;
51
52         x1= (int)floor(u);
53         x2= (int)ceil(u);
54         y1= (int)floor(v);
55         y2= (int)ceil(v);
56
57         /* sample area entirely outside image? */
58         if(x2<0 || x1>in->x-1 || y2<0 || y1>in->y-1)
59                 return;
60         
61         /* sample including outside of edges of image */
62         if(x1<0 || y1<0) row1= empty;
63         else row1= in->rect + in->x * y1 * in->type + in->type*x1;
64         
65         if(x1<0 || y2>in->y-1) row2= empty;
66         else row2= in->rect + in->x * y2 * in->type + in->type*x1;
67         
68         if(x2>in->x-1 || y1<0) row3= empty;
69         else row3= in->rect + in->x * y1 * in->type + in->type*x2;
70         
71         if(x2>in->x-1 || y2>in->y-1) row4= empty;
72         else row4= in->rect + in->x * y2 * in->type + in->type*x2;
73         
74         a= u-floor(u);
75         b= v-floor(v);
76         a_b= a*b; ma_b= (1.0f-a)*b; a_mb= a*(1.0f-b); ma_mb= (1.0f-a)*(1.0f-b);
77         
78         out[0]= ma_mb*row1[0] + a_mb*row3[0] + ma_b*row2[0]+ a_b*row4[0];
79         out[1]= ma_mb*row1[1] + a_mb*row3[1] + ma_b*row2[1]+ a_b*row4[1];
80         out[2]= ma_mb*row1[2] + a_mb*row3[2] + ma_b*row2[2]+ a_b*row4[2];
81         out[3]= ma_mb*row1[3] + a_mb*row3[3] + ma_b*row2[3]+ a_b*row4[3];
82 }
83
84 /* only supports RGBA nodes now */
85 static void node_composit_exec_rotate(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
86 {
87         
88         if(out[0]->hasoutput==0)
89                 return;
90         
91         if(in[0]->data) {
92                 CompBuf *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA);
93                 CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* note, this returns zero'd image */
94                 float *ofp, rad, u, v, s, c, centx, centy, miny, maxy, minx, maxx;
95                 int x, y, yo;
96         
97                 rad= (M_PI*in[1]->vec[0])/180.0f;
98                 
99                 s= sin(rad);
100                 c= cos(rad);
101                 centx= cbuf->x/2;
102                 centy= cbuf->y/2;
103                 
104                 minx= -centx;
105                 maxx= -centx + (float)cbuf->x;
106                 miny= -centy;
107                 maxy= -centy + (float)cbuf->y;
108                 
109                 for(y=miny; y<maxy; y++) {
110                         yo= y+(int)centy;
111                         ofp= stackbuf->rect + 4*yo*stackbuf->x;
112                         
113                         for(x=minx; x<maxx; x++, ofp+=4) {
114                                 u= c*x + y*s + centx;
115                                 v= -s*x + c*y + centy;
116                                 
117                                 bilinear_interpolation_rotate(cbuf, ofp, u, v);
118                         }
119                 }
120                 /* rotate offset vector too, but why negative rad, ehh?? Has to be replaced with [3][3] matrix once (ton) */
121                 s= sin(-rad);
122                 c= cos(-rad);
123                 centx= (float)cbuf->xof; centy= (float)cbuf->yof;
124                 stackbuf->xof= (int)( c*centx + s*centy);
125                 stackbuf->yof= (int)(-s*centx + c*centy);
126                 
127                 /* pass on output and free */
128                 out[0]->data= stackbuf;
129                 if(cbuf!=in[0]->data)
130                         free_compbuf(cbuf);
131                 
132         }
133 }
134
135 bNodeType cmp_node_rotate= {
136         /* type code   */       CMP_NODE_ROTATE,
137         /* name        */       "Rotate",
138         /* width+range */       140, 100, 320,
139         /* class+opts  */       NODE_CLASS_DISTORT, NODE_OPTIONS,
140         /* input sock  */       cmp_node_rotate_in,
141         /* output sock */       cmp_node_rotate_out,
142         /* storage     */       "",
143         /* execfunc    */       node_composit_exec_rotate,
144    /* butfunc     */ NULL
145 };