2 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
18 * The Original Code is Copyright (C) 2006 Blender Foundation.
19 * All rights reserved.
21 * The Original Code is: all of this file.
23 * Contributor(s): none yet.
25 * ***** END GPL LICENSE BLOCK *****
28 /** \file blender/nodes/composite/nodes/node_composite_outputFile.c
34 #include "BLI_path_util.h"
36 #include "BKE_utildefines.h"
38 #include "node_composite_util.h"
40 /* **************** OUTPUT FILE ******************** */
41 static bNodeSocketTemplate cmp_node_output_file_in[]= {
42 { SOCK_RGBA, 1, "Image", 0.0f, 0.0f, 0.0f, 1.0f},
43 { SOCK_FLOAT, 1, "Z", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE},
47 static void node_composit_exec_output_file(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out))
49 /* image assigned to output */
50 /* stack order input sockets: col, alpha */
54 NodeImageFile *nif= node->storage;
55 if(nif->sfra!=nif->efra && (rd->cfra<nif->sfra || rd->cfra>nif->efra)) {
56 return; /* BAIL OUT RETURN */
58 else if (!G.rendering) {
59 /* only output files when rendering a sequence -
60 * otherwise, it overwrites the output files just
61 * scrubbing through the timeline when the compositor updates */
64 Main *bmain= G.main; /* TODO, have this passed along */
65 CompBuf *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA);
66 ImBuf *ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0);
67 char string[FILE_MAX];
69 ibuf->rect_float= cbuf->rect;
70 ibuf->dither= rd->dither_intensity;
72 if (rd->color_mgt_flag & R_COLOR_MANAGEMENT)
73 ibuf->profile = IB_PROFILE_LINEAR_RGB;
76 CompBuf *zbuf= in[1]->data;
77 if(zbuf->type==CB_VAL && zbuf->x==cbuf->x && zbuf->y==cbuf->y) {
78 nif->im_format.flag |= R_IMF_FLAG_ZBUF;
79 ibuf->zbuf_float= zbuf->rect;
83 BKE_makepicstring(string, nif->name, bmain->name, rd->cfra, nif->im_format.imtype, (rd->scemode & R_EXTENSION), TRUE);
85 if(0 == BKE_write_ibuf(ibuf, string, &nif->im_format))
86 printf("Cannot save Node File Output to %s\n", string);
88 printf("Saved: %s\n", string);
92 generate_preview(data, node, cbuf);
94 if(in[0]->data != cbuf)
100 static void node_composit_init_output_file(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *ntemp)
102 RenderData *rd = &ntemp->scene->r;
103 NodeImageFile *nif= MEM_callocN(sizeof(NodeImageFile), "node image file");
106 BLI_strncpy(nif->name, rd->pic, sizeof(nif->name));
107 nif->im_format= rd->im_format;
108 if (BKE_imtype_is_movie(nif->im_format.imtype)) {
109 nif->im_format.imtype= R_IMF_IMTYPE_OPENEXR;
115 void register_node_type_cmp_output_file(bNodeTreeType *ttype)
117 static bNodeType ntype;
119 node_type_base(ttype, &ntype, CMP_NODE_OUTPUT_FILE, "File Output", NODE_CLASS_OUTPUT, NODE_PREVIEW|NODE_OPTIONS);
120 node_type_socket_templates(&ntype, cmp_node_output_file_in, NULL);
121 node_type_size(&ntype, 140, 80, 300);
122 node_type_init(&ntype, node_composit_init_output_file);
123 node_type_storage(&ntype, "NodeImageFile", node_free_standard_storage, node_copy_standard_storage);
124 node_type_exec(&ntype, node_composit_exec_output_file);
126 nodeRegisterType(ttype, &ntype);
130 /* =============================================================================== */
133 void ntreeCompositOutputMultiFileAddSocket(bNodeTree *ntree, bNode *node, ImageFormatData *im_format)
135 bNodeSocket *sock = nodeAddSocket(ntree, node, SOCK_IN, "", SOCK_RGBA);
137 /* create format data for the input socket */
138 NodeImageMultiFileSocket *sockdata = MEM_callocN(sizeof(NodeImageMultiFileSocket), "socket image format");
139 sock->storage = sockdata;
140 sock->struct_type = SOCK_STRUCT_OUTPUT_MULTI_FILE;
143 sockdata->format= *im_format;
144 if (BKE_imtype_is_movie(sockdata->format.imtype)) {
145 sockdata->format.imtype= R_IMF_IMTYPE_OPENEXR;
148 /* use render data format by default */
149 sockdata->use_render_format = 1;
152 int ntreeCompositOutputMultiFileRemoveActiveSocket(bNodeTree *ntree, bNode *node)
154 NodeImageMultiFile *nimf = node->storage;
155 bNodeSocket *sock = BLI_findlink(&node->inputs, nimf->active_input);
160 /* free format data */
161 MEM_freeN(sock->storage);
163 nodeRemoveSocket(ntree, node, sock);
167 static void init_output_multi_file(bNodeTree *ntree, bNode* node, bNodeTemplate *ntemp)
169 RenderData *rd = &ntemp->scene->r;
170 NodeImageMultiFile *nimf= MEM_callocN(sizeof(NodeImageMultiFile), "node image multi file");
173 BLI_strncpy(nimf->base_path, rd->pic, sizeof(nimf->base_path));
175 /* add one socket by default */
176 ntreeCompositOutputMultiFileAddSocket(ntree, node, &rd->im_format);
179 void free_output_multi_file(bNode *node)
183 /* free storage data in sockets */
184 for (sock=node->inputs.first; sock; sock=sock->next) {
185 MEM_freeN(sock->storage);
188 MEM_freeN(node->storage);
191 void copy_output_multi_file(struct bNode *node, struct bNode *target)
193 bNodeSocket *sock, *newsock;
195 target->storage = MEM_dupallocN(node->storage);
197 /* duplicate storage data in sockets */
198 for (sock=node->inputs.first, newsock=target->inputs.first; sock && newsock; sock=sock->next, newsock=newsock->next) {
199 newsock->storage = MEM_dupallocN(sock->storage);
203 static void exec_output_multi_file(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out))
205 RenderData *rd= data;
206 NodeImageMultiFile *nimf= node->storage;
210 for (sock=node->inputs.first, i=0; sock; sock=sock->next, ++i) {
215 /* only output files when rendering a sequence -
216 * otherwise, it overwrites the output files just
217 * scrubbing through the timeline when the compositor updates */
220 Main *bmain= G.main; /* TODO, have this passed along */
221 NodeImageMultiFileSocket *sockdata = sock->storage;
222 CompBuf *cbuf= typecheck_compbuf(in[i]->data, CB_RGBA);
223 ImBuf *ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0);
224 ImageFormatData *format = (sockdata->use_render_format ? &rd->im_format : &sockdata->format);
226 char string[FILE_MAX];
228 ibuf->rect_float= cbuf->rect;
229 ibuf->dither= rd->dither_intensity;
231 if (rd->color_mgt_flag & R_COLOR_MANAGEMENT)
232 ibuf->profile = IB_PROFILE_LINEAR_RGB;
235 BLI_join_dirfile(path, FILE_MAX, nimf->base_path, sock->name);
237 BKE_makepicstring(string, path, bmain->name, rd->cfra, format->imtype, (rd->scemode & R_EXTENSION), TRUE);
239 if(0 == BKE_write_ibuf(ibuf, string, format))
240 printf("Cannot save Node File Output to %s\n", string);
242 printf("Saved: %s\n", string);
246 #if 0 /* XXX not used yet */
247 generate_preview(data, node, cbuf);
250 if(in[i]->data != cbuf)
256 void register_node_type_cmp_output_multi_file(bNodeTreeType *ttype)
258 static bNodeType ntype;
260 node_type_base(ttype, &ntype, CMP_NODE_OUTPUT_MULTI_FILE, "Multi File Output", NODE_CLASS_OUTPUT, NODE_OPTIONS);
261 node_type_socket_templates(&ntype, NULL, NULL);
262 node_type_size(&ntype, 140, 80, 300);
263 node_type_init(&ntype, init_output_multi_file);
264 node_type_storage(&ntype, "NodeImageMultiFile", free_output_multi_file, copy_output_multi_file);
265 node_type_exec(&ntype, exec_output_multi_file);
267 nodeRegisterType(ttype, &ntype);