Fix for image node: has to check the number of actual node sockets before accessing...
[blender.git] / source / blender / nodes / composite / nodes / node_composite_image.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_image.c
29  *  \ingroup cmpnodes
30  */
31
32
33 #include "node_composite_util.h"
34
35 /* **************** IMAGE (and RenderResult, multilayer image) ******************** */
36
37 static bNodeSocketTemplate cmp_node_rlayers_out[]= {
38         {       SOCK_RGBA, 0, "Image",                                  0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
39         {       SOCK_FLOAT, 0, "Alpha",                                 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
40         {       SOCK_FLOAT, 0, "Z",                                             1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
41         {       SOCK_VECTOR, 0, "Normal",                               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
42         {       SOCK_VECTOR, 0, "UV",                                   1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
43         {       SOCK_VECTOR, 0, "Speed",                                1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
44         {       SOCK_RGBA, 0, "Color",                                  0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
45         {       SOCK_RGBA, 0, "Diffuse",                                0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
46         {       SOCK_RGBA, 0, "Specular",                               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
47         {       SOCK_RGBA, 0, "Shadow",                                 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
48         {       SOCK_RGBA, 0, "AO",                                             0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
49         {       SOCK_RGBA, 0, "Reflect",                                0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
50         {       SOCK_RGBA, 0, "Refract",                                0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
51         {       SOCK_RGBA, 0, "Indirect",                               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
52         {       SOCK_FLOAT, 0, "IndexOB",                               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
53         {       SOCK_FLOAT, 0, "IndexMA",                               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
54         {       SOCK_FLOAT, 0, "Mist",                                  0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
55         {       SOCK_RGBA, 0, "Emit",                                   0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
56         {       SOCK_RGBA, 0, "Environment",                    0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
57         {       SOCK_RGBA, 0, "Diffuse Direct",                 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
58         {       SOCK_RGBA, 0, "Diffuse Indirect",               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
59         {       SOCK_RGBA, 0, "Diffuse Color",                  0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
60         {       SOCK_RGBA, 0, "Glossy Direct",                  0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
61         {       SOCK_RGBA, 0, "Glossy Indirect",                0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
62         {       SOCK_RGBA, 0, "Glossy Color",                   0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
63         {       SOCK_RGBA, 0, "Transmission Direct",    0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
64         {       SOCK_RGBA, 0, "Transmission Indirect",  0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
65         {       SOCK_RGBA, 0, "Transmission Color",             0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
66         {       -1, 0, ""       }
67 };
68
69 static bNodeSocket *cmp_node_image_add_render_pass_output(bNodeTree *ntree, bNode *node, int UNUSED(pass), int rres_index)
70 {
71         bNodeSocket *sock;
72         
73         sock = node_add_output_from_template(ntree, node, &cmp_node_rlayers_out[rres_index]);
74         /* for render pass outputs store the pass type index as a lookup key */
75         sock->storage = SET_INT_IN_POINTER(rres_index);
76         
77         return sock;
78 }
79
80 static void cmp_node_image_add_render_pass_outputs(bNodeTree *ntree, bNode *node, int passflag)
81 {
82         if (passflag & SCE_PASS_COMBINED) {
83                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_COMBINED, RRES_OUT_IMAGE);
84                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_COMBINED, RRES_OUT_ALPHA);
85         }
86         
87         if (passflag & SCE_PASS_Z)
88                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_Z, RRES_OUT_Z);
89         if (passflag & SCE_PASS_NORMAL)
90                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_NORMAL, RRES_OUT_NORMAL);
91         if (passflag & SCE_PASS_VECTOR)
92                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_VECTOR, RRES_OUT_VEC);
93         if (passflag & SCE_PASS_UV)
94                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_UV, RRES_OUT_UV);
95         if (passflag & SCE_PASS_RGBA)
96                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_RGBA, RRES_OUT_RGBA);
97         if (passflag & SCE_PASS_DIFFUSE)
98                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE, RRES_OUT_DIFF);
99         if (passflag & SCE_PASS_SPEC)
100                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SPEC, RRES_OUT_SPEC);
101         if (passflag & SCE_PASS_SHADOW)
102                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SHADOW, RRES_OUT_SHADOW);
103         if (passflag & SCE_PASS_AO)
104                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_AO, RRES_OUT_AO);
105         if (passflag & SCE_PASS_REFLECT)
106                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_REFLECT, RRES_OUT_REFLECT);
107         if (passflag & SCE_PASS_REFRACT)
108                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_REFRACT, RRES_OUT_REFRACT);
109         if (passflag & SCE_PASS_INDIRECT)
110                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDIRECT, RRES_OUT_INDIRECT);
111         if (passflag & SCE_PASS_INDEXOB)
112                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDEXOB, RRES_OUT_INDEXOB);
113         if (passflag & SCE_PASS_INDEXMA)
114                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDEXMA, RRES_OUT_INDEXMA);
115         if (passflag & SCE_PASS_MIST)
116                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_MIST, RRES_OUT_MIST);
117         if (passflag & SCE_PASS_EMIT)
118                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_EMIT, RRES_OUT_EMIT);
119         if (passflag & SCE_PASS_ENVIRONMENT)
120                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_ENVIRONMENT, RRES_OUT_ENV);
121         
122         if (passflag & SCE_PASS_DIFFUSE_DIRECT)
123                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_DIRECT, RRES_OUT_DIFF_DIRECT);
124         if (passflag & SCE_PASS_DIFFUSE_INDIRECT)
125                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_INDIRECT, RRES_OUT_DIFF_INDIRECT);
126         if (passflag & SCE_PASS_DIFFUSE_COLOR)
127                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_COLOR, RRES_OUT_DIFF_COLOR);
128         
129         if (passflag & SCE_PASS_GLOSSY_DIRECT)
130                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_DIRECT, RRES_OUT_GLOSSY_DIRECT);
131         if (passflag & SCE_PASS_GLOSSY_INDIRECT)
132                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_INDIRECT, RRES_OUT_GLOSSY_INDIRECT);
133         if (passflag & SCE_PASS_GLOSSY_COLOR)
134                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_COLOR, RRES_OUT_GLOSSY_COLOR);
135         
136         if (passflag & SCE_PASS_TRANSM_DIRECT)
137                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_DIRECT, RRES_OUT_TRANSM_DIRECT);
138         if (passflag & SCE_PASS_TRANSM_INDIRECT)
139                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_INDIRECT, RRES_OUT_TRANSM_INDIRECT);
140         if (passflag & SCE_PASS_TRANSM_COLOR)
141                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_COLOR, RRES_OUT_TRANSM_COLOR);
142 }
143
144 static void cmp_node_image_add_multilayer_outputs(bNodeTree *ntree, bNode *node, RenderLayer *rl)
145 {
146         bNodeSocket *sock;
147         RenderPass *rpass;
148         int index;
149         for (rpass=rl->passes.first, index=0; rpass; rpass=rpass->next, ++index) {
150                 int type;
151                 if (rpass->channels == 1)
152                         type = SOCK_FLOAT;
153                 else
154                         type = SOCK_RGBA;
155                 
156                 sock = nodeAddSocket(ntree, node, SOCK_OUT, rpass->name, type);
157                 /* for multilayer image use pass index directly as key */
158                 sock->storage = SET_INT_IN_POINTER(index);
159         }
160 }
161
162 static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node)
163 {
164         Image *ima= (Image *)node->id;
165         if (ima) {
166                 ImageUser *iuser= node->storage;
167                 
168                 /* make sure ima->type is correct */
169                 BKE_image_get_ibuf(ima, iuser);
170                 
171                 if (ima->rr) {
172                         RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
173                         
174                         if (rl) {
175                                 if (ima->type!=IMA_TYPE_MULTILAYER)
176                                         cmp_node_image_add_render_pass_outputs(ntree, node, rl->passflag);
177                                 else
178                                         cmp_node_image_add_multilayer_outputs(ntree, node, rl);
179                         }
180                         else
181                                 cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE|RRES_OUT_ALPHA);
182                 }
183                 else
184                         cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE|RRES_OUT_ALPHA|RRES_OUT_Z);
185         }
186         else
187                 cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE|RRES_OUT_ALPHA);
188 }
189
190 static bNodeSocket *cmp_node_image_output_find_match(bNode *UNUSED(node), bNodeSocket *newsock, ListBase *oldsocklist)
191 {
192         bNodeSocket *sock;
193         
194         for (sock=oldsocklist->first; sock; sock=sock->next)
195                 if (strcmp(sock->name, newsock->name)==0)
196                         return sock;
197         return NULL;
198 }
199
200 static bNodeSocket *cmp_node_image_output_relink(bNode *node, bNodeSocket *oldsock, int oldindex)
201 {
202         bNodeSocket *sock;
203         
204         /* first try to find matching socket name */
205         for (sock=node->outputs.first; sock; sock=sock->next)
206                 if (strcmp(sock->name, oldsock->name)==0)
207                         return sock;
208         
209         /* no matching name, simply link to same index */
210         return BLI_findlink(&node->outputs, oldindex);
211 }
212
213 static void cmp_node_image_sync_output(bNode *UNUSED(node), bNodeSocket *UNUSED(newsock), bNodeSocket *UNUSED(oldsock))
214 {
215         /* pass */
216 }
217
218 /* XXX make this into a generic socket verification function for dynamic socket replacement (multilayer, groups, static templates) */
219 static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node)
220 {
221         bNodeSocket *newsock, *oldsock, *oldsock_next;
222         ListBase oldsocklist;
223         int oldindex;
224         bNodeLink *link;
225         
226         /* store current nodes in oldsocklist, then clear socket list */
227         oldsocklist = node->outputs;
228         node->outputs.first = node->outputs.last = NULL;
229         
230         /* XXX make callback */
231         cmp_node_image_create_outputs(ntree, node);
232         /* flag all new sockets as dynamic, to prevent removal by socket verification function */
233         for (newsock=node->outputs.first; newsock; newsock=newsock->next)
234                 newsock->flag |= SOCK_DYNAMIC;
235         
236         for (newsock=node->outputs.first; newsock; newsock=newsock->next) {
237                 /* XXX make callback */
238                 oldsock = cmp_node_image_output_find_match(node, newsock, &oldsocklist);
239                 if (oldsock) {
240                         /* XXX make callback */
241                         cmp_node_image_sync_output(node, newsock, oldsock);
242                 }
243         }
244         
245         /* move links to new socket */
246         for (oldsock=oldsocklist.first, oldindex=0; oldsock; oldsock=oldsock->next, ++oldindex) {
247                 newsock = cmp_node_image_output_relink(node, oldsock, oldindex);
248                 
249                 if (newsock) {
250                         for (link=ntree->links.first; link; link=link->next) {
251                                 if (link->fromsock == oldsock)
252                                         link->fromsock = newsock;
253                         }
254                 }
255         }
256         
257         /* delete old sockets
258          * XXX oldsock is not actually in the node->outputs list any more,
259          * but the nodeRemoveSocket function works anyway. In future this
260          * should become part of the core code, so can take care of this behavior.
261          */
262         for (oldsock=oldsocklist.first; oldsock; oldsock=oldsock_next) {
263                 oldsock_next = oldsock->next;
264                 nodeRemoveSocket(ntree, node, oldsock);
265         }
266 }
267
268 static void cmp_node_image_update(bNodeTree *ntree, bNode *node)
269 {
270         /* avoid unnecessary updates, only changes to the image/image user data are of interest */
271         if (node->update & NODE_UPDATE_ID)
272                 cmp_node_image_verify_outputs(ntree, node);
273 }
274
275 /* float buffer from the image with matching color management */
276 float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc)
277 {
278         float *rect;
279         int predivide= (ibuf->flags & IB_cm_predivide);
280
281         *alloc= FALSE;
282
283         if (rd->color_mgt_flag & R_COLOR_MANAGEMENT) {
284                 if (ibuf->profile != IB_PROFILE_NONE) {
285                         rect= ibuf->rect_float;
286                 }
287                 else {
288                         rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image");
289
290                         IMB_buffer_float_from_float(rect, ibuf->rect_float,
291                                 4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, predivide,
292                                 ibuf->x, ibuf->y, ibuf->x, ibuf->x);
293
294                         *alloc= TRUE;
295                 }
296         }
297         else {
298                 if (ibuf->profile == IB_PROFILE_NONE) {
299                         rect= ibuf->rect_float;
300                 }
301                 else {
302                         rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image");
303
304                         IMB_buffer_float_from_float(rect, ibuf->rect_float,
305                                 4, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, predivide,
306                                 ibuf->x, ibuf->y, ibuf->x, ibuf->x);
307
308                         *alloc= TRUE;
309                 }
310         }
311
312         return rect;
313 }
314
315 /* note: this function is used for multilayer too, to ensure uniform 
316    handling with BKE_image_get_ibuf() */
317 static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *iuser)
318 {
319         ImBuf *ibuf;
320         CompBuf *stackbuf;
321         int type;
322
323         float *rect;
324         int alloc= FALSE;
325
326         ibuf= BKE_image_get_ibuf(ima, iuser);
327         if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) {
328                 return NULL;
329         }
330
331         if (ibuf->rect_float == NULL) {
332                 IMB_float_from_rect(ibuf);
333         }
334
335         /* now we need a float buffer from the image with matching color management */
336         /* XXX weak code, multilayer is excluded from this */
337         if (ibuf->channels == 4 && ima->rr==NULL) {
338                 rect= node_composit_get_float_buffer(rd, ibuf, &alloc);
339         }
340         else {
341                 /* non-rgba passes can't use color profiles */
342                 rect= ibuf->rect_float;
343         }
344         /* done coercing into the correct color management */
345
346
347         type= ibuf->channels;
348         
349         if (rd->scemode & R_COMP_CROP) {
350                 stackbuf= get_cropped_compbuf(&rd->disprect, rect, ibuf->x, ibuf->y, type);
351                 if (alloc)
352                         MEM_freeN(rect);
353         }
354         else {
355                 /* we put imbuf copy on stack, cbuf knows rect is from other ibuf when freed! */
356                 stackbuf= alloc_compbuf(ibuf->x, ibuf->y, type, FALSE);
357                 stackbuf->rect= rect;
358                 stackbuf->malloc= alloc;
359         }
360         
361         /*code to respect the premul flag of images; I'm
362           not sure if this is a good idea for multilayer images,
363           since it never worked before for them.
364         if (type==CB_RGBA && ima->flag & IMA_DO_PREMUL) {
365                 //premul the image
366                 int i;
367                 float *pixel = stackbuf->rect;
368                 
369                 for (i=0; i<stackbuf->x*stackbuf->y; i++, pixel += 4) {
370                         pixel[0] *= pixel[3];
371                         pixel[1] *= pixel[3];
372                         pixel[2] *= pixel[3];
373                 }
374         }
375         */
376         return stackbuf;
377 }
378
379 static CompBuf *node_composit_get_zimage(bNode *node, RenderData *rd)
380 {
381         ImBuf *ibuf= BKE_image_get_ibuf((Image *)node->id, node->storage);
382         CompBuf *zbuf= NULL;
383         
384         if (ibuf && ibuf->zbuf_float) {
385                 if (rd->scemode & R_COMP_CROP) {
386                         zbuf= get_cropped_compbuf(&rd->disprect, ibuf->zbuf_float, ibuf->x, ibuf->y, CB_VAL);
387                 }
388                 else {
389                         zbuf= alloc_compbuf(ibuf->x, ibuf->y, CB_VAL, 0);
390                         zbuf->rect= ibuf->zbuf_float;
391                 }
392         }
393         return zbuf;
394 }
395
396 /* check if layer is available, returns pass buffer */
397 static CompBuf *compbuf_multilayer_get(RenderData *rd, RenderLayer *rl, Image *ima, ImageUser *iuser, int passindex)
398 {
399         RenderPass *rpass = BLI_findlink(&rl->passes, passindex);
400         if (rpass) {
401                 CompBuf *cbuf;
402                 
403                 iuser->pass = passindex;
404                 BKE_image_multilayer_index(ima->rr, iuser);
405                 cbuf = node_composit_get_image(rd, ima, iuser);
406                 
407                 return cbuf;
408         }
409         return NULL;
410 }
411
412 static void node_composit_exec_image(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
413 {
414         
415         /* image assigned to output */
416         /* stack order input sockets: col, alpha */
417         if (node->id) {
418                 RenderData *rd= data;
419                 Image *ima= (Image *)node->id;
420                 ImageUser *iuser= (ImageUser *)node->storage;
421                 
422                 /* first set the right frame number in iuser */
423                 BKE_image_user_calc_frame(iuser, rd->cfra, 0);
424                 
425                 /* force a load, we assume iuser index will be set OK anyway */
426                 if (ima->type==IMA_TYPE_MULTILAYER)
427                         BKE_image_get_ibuf(ima, iuser);
428                 
429                 if (ima->type==IMA_TYPE_MULTILAYER && ima->rr) {
430                         RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
431                         
432                         if (rl) {
433                                 bNodeSocket *sock;
434                                 int out_index;
435                                 CompBuf *combinedbuf= NULL, *firstbuf= NULL;
436                                 
437                                 for (sock=node->outputs.first, out_index=0; sock; sock=sock->next, ++out_index) {
438                                         int passindex = GET_INT_FROM_POINTER(sock->storage);
439                                         if (out[out_index]->hasoutput) {
440                                                 CompBuf *stackbuf = out[out_index]->data = compbuf_multilayer_get(rd, rl, ima, iuser, passindex);
441                                                 if (stackbuf) {
442                                                         /* preview policy: take first 'Combined' pass if available,
443                                                          * otherwise just use the first layer.
444                                                          */
445                                                         if (!firstbuf)
446                                                                 firstbuf = stackbuf;
447                                                         if (!combinedbuf &&
448                                                             (strcmp(sock->name, "Combined")==0 || strcmp(sock->name, "Image")==0))
449                                                                 combinedbuf = stackbuf;
450                                                 }
451                                         }
452                                 }
453                                 
454                                 /* preview */
455                                 if (combinedbuf)
456                                         generate_preview(data, node, combinedbuf);
457                                 else if (firstbuf)
458                                         generate_preview(data, node, firstbuf);
459                         }
460                 }
461                 else {
462                         CompBuf *stackbuf = node_composit_get_image(rd, ima, iuser);
463                         if (stackbuf) {
464                                 int num_outputs = BLI_countlist(&node->outputs);
465                                 
466                                 /*respect image premul option*/
467                                 if (stackbuf->type==CB_RGBA && ima->flag & IMA_DO_PREMUL) {
468                                         int i;
469                                         float *pixel;
470                         
471                                         /*first duplicate stackbuf->rect, since it's just a pointer
472                                           to the source imbuf, and we don't want to change that.*/
473                                         stackbuf->rect = MEM_dupallocN(stackbuf->rect);
474                                         
475                                         /* since stackbuf now has allocated memory, rather than just a pointer,
476                                          * mark it as allocated so it can be freed properly */
477                                         stackbuf->malloc=1;
478                                         
479                                         /*premul the image*/
480                                         pixel = stackbuf->rect;
481                                         for (i=0; i<stackbuf->x*stackbuf->y; i++, pixel += 4) {
482                                                 pixel[0] *= pixel[3];
483                                                 pixel[1] *= pixel[3];
484                                                 pixel[2] *= pixel[3];
485                                         }
486                                 }
487                         
488                                 /* put image on stack */
489                                 if (num_outputs > 0)
490                                         out[0]->data= stackbuf;
491                                 
492                                 /* alpha output */
493                                 if (num_outputs > 1 && out[1]->hasoutput)
494                                         out[1]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
495                                 
496                                 /* Z output */
497                                 if (num_outputs > 2 && out[2]->hasoutput)
498                                         out[2]->data= node_composit_get_zimage(node, rd);
499                                 
500                                 /* preview */
501                                 generate_preview(data, node, stackbuf);
502                         }
503                 }
504         }       
505 }
506
507 static void node_composit_init_image(bNodeTree *ntree, bNode* node, bNodeTemplate *UNUSED(ntemp))
508 {
509         ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user");
510         node->storage= iuser;
511         iuser->frames= 1;
512         iuser->sfra= 1;
513         iuser->fie_ima= 2;
514         iuser->ok= 1;
515         
516         /* setup initial outputs */
517         cmp_node_image_verify_outputs(ntree, node);
518 }
519
520 void register_node_type_cmp_image(bNodeTreeType *ttype)
521 {
522         static bNodeType ntype;
523
524         node_type_base(ttype, &ntype, CMP_NODE_IMAGE, "Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
525         node_type_size(&ntype, 120, 80, 300);
526         node_type_init(&ntype, node_composit_init_image);
527         node_type_storage(&ntype, "ImageUser", node_free_standard_storage, node_copy_standard_storage);
528         node_type_update(&ntype, cmp_node_image_update, NULL);
529         node_type_exec(&ntype, node_composit_exec_image);
530
531         nodeRegisterType(ttype, &ntype);
532 }
533
534
535 /* **************** RENDER RESULT ******************** */
536
537 static CompBuf *compbuf_from_pass(RenderData *rd, RenderLayer *rl, int rectx, int recty, int passcode)
538 {
539         float *fp= RE_RenderLayerGetPass(rl, passcode);
540         if (fp) {
541                 CompBuf *buf;
542                 int buftype= CB_VEC3;
543
544                 if (ELEM4(passcode, SCE_PASS_Z, SCE_PASS_INDEXOB, SCE_PASS_MIST, SCE_PASS_INDEXMA))
545                         buftype= CB_VAL;
546                 else if (passcode==SCE_PASS_VECTOR)
547                         buftype= CB_VEC4;
548                 else if (ELEM(passcode, SCE_PASS_COMBINED, SCE_PASS_RGBA))
549                         buftype= CB_RGBA;
550
551                 if (rd->scemode & R_COMP_CROP)
552                         buf= get_cropped_compbuf(&rd->disprect, fp, rectx, recty, buftype);
553                 else {
554                         buf= alloc_compbuf(rectx, recty, buftype, 0);
555                         buf->rect= fp;
556                 }
557                 return buf;
558         }
559         return NULL;
560 }
561
562 static void node_composit_rlayers_out(RenderData *rd, RenderLayer *rl, bNodeStack **out, int rectx, int recty)
563 {
564         if (out[RRES_OUT_Z]->hasoutput)
565                 out[RRES_OUT_Z]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_Z);
566         if (out[RRES_OUT_VEC]->hasoutput)
567                 out[RRES_OUT_VEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_VECTOR);
568         if (out[RRES_OUT_NORMAL]->hasoutput)
569                 out[RRES_OUT_NORMAL]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_NORMAL);
570         if (out[RRES_OUT_UV]->hasoutput)
571                 out[RRES_OUT_UV]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_UV);
572
573         if (out[RRES_OUT_RGBA]->hasoutput)
574                 out[RRES_OUT_RGBA]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_RGBA);
575         if (out[RRES_OUT_DIFF]->hasoutput)
576                 out[RRES_OUT_DIFF]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE);
577         if (out[RRES_OUT_SPEC]->hasoutput)
578                 out[RRES_OUT_SPEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SPEC);
579         if (out[RRES_OUT_SHADOW]->hasoutput)
580                 out[RRES_OUT_SHADOW]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SHADOW);
581         if (out[RRES_OUT_AO]->hasoutput)
582                 out[RRES_OUT_AO]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_AO);
583         if (out[RRES_OUT_REFLECT]->hasoutput)
584                 out[RRES_OUT_REFLECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFLECT);
585         if (out[RRES_OUT_REFRACT]->hasoutput)
586                 out[RRES_OUT_REFRACT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFRACT);
587         if (out[RRES_OUT_INDIRECT]->hasoutput)
588                 out[RRES_OUT_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDIRECT);
589         if (out[RRES_OUT_INDEXOB]->hasoutput)
590                 out[RRES_OUT_INDEXOB]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXOB);
591         if (out[RRES_OUT_INDEXMA]->hasoutput)
592                 out[RRES_OUT_INDEXMA]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXMA);
593         if (out[RRES_OUT_MIST]->hasoutput)
594                 out[RRES_OUT_MIST]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_MIST);
595         if (out[RRES_OUT_EMIT]->hasoutput)
596                 out[RRES_OUT_EMIT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_EMIT);
597         if (out[RRES_OUT_ENV]->hasoutput)
598                 out[RRES_OUT_ENV]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_ENVIRONMENT);
599         if (out[RRES_OUT_DIFF_DIRECT]->hasoutput)
600                 out[RRES_OUT_DIFF_DIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE_DIRECT);
601         if (out[RRES_OUT_DIFF_INDIRECT]->hasoutput)
602                 out[RRES_OUT_DIFF_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE_INDIRECT);
603         if (out[RRES_OUT_DIFF_COLOR]->hasoutput)
604                 out[RRES_OUT_DIFF_COLOR]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE_COLOR);
605         if (out[RRES_OUT_GLOSSY_DIRECT]->hasoutput)
606                 out[RRES_OUT_GLOSSY_DIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_GLOSSY_DIRECT);
607         if (out[RRES_OUT_GLOSSY_INDIRECT]->hasoutput)
608                 out[RRES_OUT_GLOSSY_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_GLOSSY_INDIRECT);
609         if (out[RRES_OUT_GLOSSY_COLOR]->hasoutput)
610                 out[RRES_OUT_GLOSSY_COLOR]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_GLOSSY_COLOR);
611         if (out[RRES_OUT_TRANSM_DIRECT]->hasoutput)
612                 out[RRES_OUT_TRANSM_DIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_TRANSM_DIRECT);
613         if (out[RRES_OUT_TRANSM_INDIRECT]->hasoutput)
614                 out[RRES_OUT_TRANSM_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_TRANSM_INDIRECT);
615         if (out[RRES_OUT_TRANSM_COLOR]->hasoutput)
616                 out[RRES_OUT_TRANSM_COLOR]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_TRANSM_COLOR);
617 }
618
619
620
621 static void node_composit_exec_rlayers(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
622 {
623         Scene *sce= (Scene *)node->id;
624         Render *re= (sce)? RE_GetRender(sce->id.name): NULL;
625         RenderData *rd= data;
626         RenderResult *rr= NULL;
627
628         if (re)
629                 rr= RE_AcquireResultRead(re);
630
631         if (rr) {
632                 SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1);
633                 if (srl) {
634                         RenderLayer *rl= RE_GetRenderLayer(rr, srl->name);
635                         if (rl && rl->rectf) {
636                                 CompBuf *stackbuf;
637
638                                 /* we put render rect on stack, cbuf knows rect is from other ibuf when freed! */
639                                 if (rd->scemode & R_COMP_CROP)
640                                         stackbuf= get_cropped_compbuf(&rd->disprect, rl->rectf, rr->rectx, rr->recty, CB_RGBA);
641                                 else {
642                                         stackbuf= alloc_compbuf(rr->rectx, rr->recty, CB_RGBA, 0);
643                                         stackbuf->rect= rl->rectf;
644                                 }
645                                 if (stackbuf==NULL) {
646                                         printf("Error; Preview Panel in UV Window returns zero sized image\n");
647                                 }
648                                 else {
649                                         stackbuf->xof= rr->xof;
650                                         stackbuf->yof= rr->yof;
651
652                                         /* put on stack */
653                                         out[RRES_OUT_IMAGE]->data= stackbuf;
654
655                                         if (out[RRES_OUT_ALPHA]->hasoutput)
656                                                 out[RRES_OUT_ALPHA]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
657
658                                         node_composit_rlayers_out(rd, rl, out, rr->rectx, rr->recty);
659
660                                         generate_preview(data, node, stackbuf);
661                                 }
662                         }
663                 }
664         }
665
666         if (re)
667                 RE_ReleaseResult(re);
668 }
669
670
671 void register_node_type_cmp_rlayers(bNodeTreeType *ttype)
672 {
673         static bNodeType ntype;
674
675         node_type_base(ttype, &ntype, CMP_NODE_R_LAYERS, "Render Layers", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
676         node_type_socket_templates(&ntype, NULL, cmp_node_rlayers_out);
677         node_type_size(&ntype, 150, 100, 300);
678         node_type_exec(&ntype, node_composit_exec_rlayers);
679
680         nodeRegisterType(ttype, &ntype);
681 }