Internal refactoring of tracking module, should be no functional changes
[blender.git] / source / blender / nodes / composite / nodes / node_composite_movieclip.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_movieclip.c
30  *  \ingroup cmpnodes
31  */
32
33
34 #include "node_composite_util.h"
35
36 static bNodeSocketTemplate cmp_node_movieclip_out[] = {
37         {       SOCK_RGBA,              0,      N_("Image")},
38         {       SOCK_FLOAT,             1,      N_("Offset X")},
39         {       SOCK_FLOAT,             1,      N_("Offset Y")},
40         {       SOCK_FLOAT,             1,      N_("Scale")},
41         {       SOCK_FLOAT,             1,      N_("Angle")},
42         {       -1, 0, ""       }
43 };
44
45 static CompBuf *node_composit_get_movieclip(RenderData *rd, MovieClip *clip, MovieClipUser *user)
46 {
47         ImBuf *orig_ibuf, *ibuf;
48         CompBuf *stackbuf;
49         int type;
50
51         float *rect;
52         int alloc = FALSE;
53
54         orig_ibuf = BKE_movieclip_get_ibuf(clip, user);
55
56         if (orig_ibuf == NULL || (orig_ibuf->rect == NULL && orig_ibuf->rect_float == NULL)) {
57                 IMB_freeImBuf(orig_ibuf);
58                 return NULL;
59         }
60
61         ibuf = IMB_dupImBuf(orig_ibuf);
62         IMB_freeImBuf(orig_ibuf);
63
64         if (ibuf->rect_float == NULL || (ibuf->userflags & IB_RECT_INVALID)) {
65                 IMB_float_from_rect(ibuf);
66                 ibuf->userflags &= ~IB_RECT_INVALID;
67         }
68
69         /* now we need a float buffer from the image with matching color management */
70         if (ibuf->channels == 4) {
71                 rect = node_composit_get_float_buffer(rd, ibuf, &alloc);
72         }
73         else {
74                 /* non-rgba passes can't use color profiles */
75                 rect = ibuf->rect_float;
76         }
77         /* done coercing into the correct color management */
78
79         if (!alloc) {
80                 rect = MEM_dupallocN(rect);
81                 alloc = TRUE;
82         }
83
84         type = ibuf->channels;
85
86         if (rd->scemode & R_COMP_CROP) {
87                 stackbuf = get_cropped_compbuf(&rd->disprect, rect, ibuf->x, ibuf->y, type);
88                 if (alloc)
89                         MEM_freeN(rect);
90         }
91         else {
92                 /* we put imbuf copy on stack, cbuf knows rect is from other ibuf when freed! */
93                 stackbuf = alloc_compbuf(ibuf->x, ibuf->y, type, FALSE);
94                 stackbuf->rect = rect;
95                 stackbuf->malloc = alloc;
96         }
97
98         IMB_freeImBuf(ibuf);
99
100         return stackbuf;
101 }
102
103 static void node_composit_exec_movieclip(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
104 {
105         if (node->id) {
106                 RenderData *rd = data;
107                 MovieClip *clip = (MovieClip *)node->id;
108                 MovieClipUser *user = (MovieClipUser *)node->storage;
109                 CompBuf *stackbuf = NULL;
110
111                 BKE_movieclip_user_set_frame(user, rd->cfra);
112
113                 stackbuf = node_composit_get_movieclip(rd, clip, user);
114
115                 if (stackbuf) {
116                         MovieTrackingStabilization *stab = &clip->tracking.stabilization;
117
118                         /* put image on stack */
119                         out[0]->data = stackbuf;
120
121                         if (stab->flag & TRACKING_2D_STABILIZATION) {
122                                 float loc[2], scale, angle;
123
124                                 BKE_tracking_stabilization_data_get(&clip->tracking, rd->cfra, stackbuf->x, stackbuf->y,
125                                                         loc, &scale, &angle);
126
127                                 out[1]->vec[0] = loc[0];
128                                 out[2]->vec[0] = loc[1];
129
130                                 out[3]->vec[0] = scale;
131                                 out[4]->vec[0] = angle;
132                         }
133
134                         /* generate preview */
135                         generate_preview(data, node, stackbuf);
136                 }
137         }
138 }
139
140 static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
141 {
142         MovieClipUser *user = MEM_callocN(sizeof(MovieClipUser), "node movie clip user");
143
144         node->storage = user;
145         user->framenr = 1;
146 }
147
148 void register_node_type_cmp_movieclip(bNodeTreeType *ttype)
149 {
150         static bNodeType ntype;
151
152         node_type_base(ttype, &ntype, CMP_NODE_MOVIECLIP, "Movie Clip", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
153         node_type_socket_templates(&ntype, NULL, cmp_node_movieclip_out);
154         node_type_size(&ntype, 120, 80, 300);
155         node_type_init(&ntype, init);
156         node_type_storage(&ntype, "MovieClipUser", node_free_standard_storage, node_copy_standard_storage);
157         node_type_exec(&ntype, node_composit_exec_movieclip);
158
159         nodeRegisterType(ttype, &ntype);
160 }