90aa03997c167052ebf1bc33afd84f2639576d9c
[blender.git] / source / blender / nodes / composite / nodes / node_composite_outputFile.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) 2006 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/nodes/composite/nodes/node_composite_outputFile.c
29  *  \ingroup cmpnodes
30  */
31
32
33 #include <string.h>
34 #include "BLI_path_util.h"
35
36 #include "BKE_utildefines.h"
37
38 #include "node_composite_util.h"
39
40 #include "IMB_imbuf.h"
41 #include "IMB_imbuf_types.h"
42
43 #include "intern/openexr/openexr_multi.h"
44
45
46 /* **************** OUTPUT FILE ******************** */
47
48 bNodeSocket *ntreeCompositOutputFileAddSocket(bNodeTree *ntree, bNode *node, const char *name, ImageFormatData *im_format)
49 {
50         bNodeSocket *sock = nodeAddSocket(ntree, node, SOCK_IN, name, SOCK_RGBA);
51         
52         /* create format data for the input socket */
53         NodeImageMultiFileSocket *sockdata = MEM_callocN(sizeof(NodeImageMultiFileSocket), "socket image format");
54         sock->storage = sockdata;
55         sock->struct_type = SOCK_STRUCT_OUTPUT_FILE;
56         
57         if(im_format) {
58                 sockdata->format= *im_format;
59                 if (BKE_imtype_is_movie(sockdata->format.imtype)) {
60                         sockdata->format.imtype= R_IMF_IMTYPE_OPENEXR;
61                 }
62         }
63         /* use node data format by default */
64         sockdata->use_node_format = 1;
65         
66         return sock;
67 }
68
69 int ntreeCompositOutputFileRemoveActiveSocket(bNodeTree *ntree, bNode *node)
70 {
71         NodeImageMultiFile *nimf = node->storage;
72         bNodeSocket *sock = BLI_findlink(&node->inputs, nimf->active_input);
73         
74         if (!sock)
75                 return 0;
76         
77         /* free format data */
78         MEM_freeN(sock->storage);
79         
80         nodeRemoveSocket(ntree, node, sock);
81         return 1;
82 }
83
84 static void init_output_file(bNodeTree *ntree, bNode* node, bNodeTemplate *ntemp)
85 {
86         RenderData *rd = &ntemp->scene->r;
87         NodeImageMultiFile *nimf= MEM_callocN(sizeof(NodeImageMultiFile), "node image multi file");
88         node->storage= nimf;
89
90         BLI_strncpy(nimf->base_path, rd->pic, sizeof(nimf->base_path));
91         nimf->format = rd->im_format;
92         
93         /* add one socket by default */
94         ntreeCompositOutputFileAddSocket(ntree, node, "Image", &rd->im_format);
95 }
96
97 static void free_output_file(bNode *node)
98 {
99         bNodeSocket *sock;
100         
101         /* free storage data in sockets */
102         for (sock=node->inputs.first; sock; sock=sock->next) {
103                 MEM_freeN(sock->storage);
104         }
105         
106         MEM_freeN(node->storage);
107 }
108
109 static void copy_output_file(struct bNode *node, struct bNode *target)
110 {
111         bNodeSocket *sock, *newsock;
112         
113         target->storage = MEM_dupallocN(node->storage);
114         
115         /* duplicate storage data in sockets */
116         for (sock=node->inputs.first, newsock=target->inputs.first; sock && newsock; sock=sock->next, newsock=newsock->next) {
117                 newsock->storage = MEM_dupallocN(sock->storage);
118         }
119 }
120
121 static void update_output_file(bNodeTree *UNUSED(ntree), bNode *node)
122 {
123         bNodeSocket *sock;
124         
125         /* automatically update the socket type based on linked input */
126         for (sock=node->inputs.first; sock; sock=sock->next) {
127                 if (sock->link) {
128                         int linktype = sock->link->fromsock->type;
129                         if (linktype != sock->type)
130                                 nodeSocketSetType(sock, linktype);
131                 }
132         }
133 }
134
135 /* write input data into individual files */
136 static void exec_output_file_singlelayer(RenderData *rd, bNode *node, bNodeStack **in)
137 {
138         Main *bmain= G.main; /* TODO, have this passed along */
139         NodeImageMultiFile *nimf= node->storage;
140         bNodeSocket *sock;
141         int i;
142         int has_preview = 0;
143         
144         for (sock=node->inputs.first, i=0; sock; sock=sock->next, ++i) {
145                 if (in[i]->data) {
146                         NodeImageMultiFileSocket *sockdata = sock->storage;
147                         ImageFormatData *format = (sockdata->use_node_format ? &nimf->format : &sockdata->format);
148                         char path[FILE_MAX];
149                         char filename[FILE_MAX];
150                         CompBuf *cbuf;
151                         ImBuf *ibuf;
152                         
153                         switch (format->planes) {
154                         case R_IMF_PLANES_BW:
155                                 cbuf = typecheck_compbuf(in[i]->data, CB_VAL);
156                                 break;
157                         case R_IMF_PLANES_RGB:
158                                 cbuf = typecheck_compbuf(in[i]->data, CB_VEC3);
159                                 break;
160                         case R_IMF_PLANES_RGBA:
161                                 cbuf = typecheck_compbuf(in[i]->data, CB_RGBA);
162                                 break;
163                         }
164                         
165                         ibuf = IMB_allocImBuf(cbuf->x, cbuf->y, format->planes, 0);
166                         ibuf->rect_float = cbuf->rect;
167                         ibuf->dither = rd->dither_intensity;
168                         
169                         if (rd->color_mgt_flag & R_COLOR_MANAGEMENT)
170                                 ibuf->profile = IB_PROFILE_LINEAR_RGB;
171                         
172                         /* get full path */
173                         BLI_join_dirfile(path, FILE_MAX, nimf->base_path, sock->name);
174                         BKE_makepicstring(filename, path, bmain->name, rd->cfra, format->imtype, (rd->scemode & R_EXTENSION), TRUE);
175                         
176                         if(0 == BKE_write_ibuf(ibuf, filename, format))
177                                 printf("Cannot save Node File Output to %s\n", filename);
178                         else
179                                 printf("Saved: %s\n", filename);
180                         
181                         IMB_freeImBuf(ibuf);
182                         
183                         /* simply pick the first valid input for preview */
184                         if (!has_preview) {
185                                 generate_preview(rd, node, cbuf);
186                                 has_preview = 1;
187                         }
188                         
189                         if(in[i]->data != cbuf) 
190                                 free_compbuf(cbuf);
191                 }
192         }
193 }
194
195 /* write input data into layers */
196 static void exec_output_file_multilayer(RenderData *rd, bNode *node, bNodeStack **in)
197 {
198         Main *bmain= G.main; /* TODO, have this passed along */
199         NodeImageMultiFile *nimf= node->storage;
200         void *exrhandle= IMB_exr_get_handle();
201         char filename[FILE_MAX];
202         bNodeSocket *sock;
203         int i;
204         /* Must have consistent pixel size for exr file, simply take the first valid input size. */
205         int rectx = -1;
206         int recty = -1;
207         int has_preview = 0;
208         
209         BKE_makepicstring(filename, nimf->base_path, bmain->name, rd->cfra, R_IMF_IMTYPE_MULTILAYER, (rd->scemode & R_EXTENSION), TRUE);
210         BLI_make_existing_file(filename);
211         
212         for (sock=node->inputs.first, i=0; sock; sock=sock->next, ++i) {
213                 if (in[i]->data) {
214                         CompBuf *cbuf = in[i]->data;
215                         char layname[EXR_LAY_MAXNAME];
216                         char channelname[EXR_PASS_MAXNAME];
217                         char *channelname_ext;
218                         
219                         if (cbuf->rect_procedural) {
220                                 printf("Error writing multilayer EXR: Procedural buffer not supported\n");
221                                 continue;
222                         }
223                         if (rectx < 0) {
224                                 rectx = cbuf->x;
225                                 recty = cbuf->y;
226                         }
227                         else if (cbuf->x != rectx || cbuf->y != recty) {
228                                 printf("Error: Multilayer EXR output node %s expects same resolution for all input buffers. Layer %s skipped.\n", node->name, sock->name);
229                                 continue;
230                         }
231                         
232                         BLI_strncpy(layname, sock->name, sizeof(layname));
233                         BLI_strncpy(channelname, sock->name, sizeof(channelname)-2);
234                         channelname_ext = channelname + strlen(channelname);
235                         
236                         /* create channels */
237                         switch (cbuf->type) {
238                         case CB_VAL:
239                                 strcpy(channelname_ext, ".V");
240                                 IMB_exr_add_channel(exrhandle, layname, channelname, 1, rectx, cbuf->rect);
241                                 break;
242                         case CB_VEC2:
243                                 strcpy(channelname_ext, ".X");
244                                 IMB_exr_add_channel(exrhandle, layname, channelname, 2, 2*rectx, cbuf->rect);
245                                 strcpy(channelname_ext, ".Y");
246                                 IMB_exr_add_channel(exrhandle, layname, channelname, 2, 2*rectx, cbuf->rect+1);
247                                 break;
248                         case CB_VEC3:
249                                 strcpy(channelname_ext, ".X");
250                                 IMB_exr_add_channel(exrhandle, layname, channelname, 3, 3*rectx, cbuf->rect);
251                                 strcpy(channelname_ext, ".Y");
252                                 IMB_exr_add_channel(exrhandle, layname, channelname, 3, 3*rectx, cbuf->rect+1);
253                                 strcpy(channelname_ext, ".Z");
254                                 IMB_exr_add_channel(exrhandle, layname, channelname, 3, 3*rectx, cbuf->rect+2);
255                                 break;
256                         case CB_RGBA:
257                                 strcpy(channelname_ext, ".R");
258                                 IMB_exr_add_channel(exrhandle, layname, channelname, 4, 4*rectx, cbuf->rect);
259                                 strcpy(channelname_ext, ".G");
260                                 IMB_exr_add_channel(exrhandle, layname, channelname, 4, 4*rectx, cbuf->rect+1);
261                                 strcpy(channelname_ext, ".B");
262                                 IMB_exr_add_channel(exrhandle, layname, channelname, 4, 4*rectx, cbuf->rect+2);
263                                 strcpy(channelname_ext, ".A");
264                                 IMB_exr_add_channel(exrhandle, layname, channelname, 4, 4*rectx, cbuf->rect+3);
265                                 break;
266                         }
267                         
268                         /* simply pick the first valid input for preview */
269                         if (!has_preview) {
270                                 generate_preview(rd, node, cbuf);
271                                 has_preview = 1;
272                         }
273                 }
274         }
275         
276         /* when the filename has no permissions, this can fail */
277         if(IMB_exr_begin_write(exrhandle, filename, rectx, recty, nimf->format.compress)) {
278                 IMB_exr_write_channels(exrhandle);
279         }
280         else {
281                 /* TODO, get the error from openexr's exception */
282                 /* XXX nice way to do report? */
283                 printf("Error Writing Render Result, see console\n");
284         }
285         
286         IMB_exr_close(exrhandle);
287 }
288
289 static void exec_output_file(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out))
290 {
291         RenderData *rd= data;
292         NodeImageMultiFile *nimf= node->storage;
293         
294         if (!G.rendering) {
295                 /* only output files when rendering a sequence -
296                  * otherwise, it overwrites the output files just 
297                  * scrubbing through the timeline when the compositor updates */
298                 return;
299         }
300         
301         if (nimf->format.imtype==R_IMF_IMTYPE_MULTILAYER)
302                 exec_output_file_multilayer(rd, node, in);
303         else
304                 exec_output_file_singlelayer(rd, node, in);
305 }
306
307 void register_node_type_cmp_output_file(bNodeTreeType *ttype)
308 {
309         static bNodeType ntype;
310
311         node_type_base(ttype, &ntype, CMP_NODE_OUTPUT_FILE, "File Output", NODE_CLASS_OUTPUT, NODE_OPTIONS|NODE_PREVIEW);
312         node_type_socket_templates(&ntype, NULL, NULL);
313         node_type_size(&ntype, 140, 80, 300);
314         node_type_init(&ntype, init_output_file);
315         node_type_storage(&ntype, "NodeImageMultiFile", free_output_file, copy_output_file);
316         node_type_update(&ntype, update_output_file, NULL);
317         node_type_exec(&ntype, exec_output_file);
318
319         nodeRegisterType(ttype, &ntype);
320 }