323767b64b1675d8ec30ea45df4b3fab25d577a8
[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                                 /*respect image premul option*/
465                                 if (stackbuf->type==CB_RGBA && ima->flag & IMA_DO_PREMUL) {
466                                         int i;
467                                         float *pixel;
468                         
469                                         /*first duplicate stackbuf->rect, since it's just a pointer
470                                           to the source imbuf, and we don't want to change that.*/
471                                         stackbuf->rect = MEM_dupallocN(stackbuf->rect);
472                                         
473                                         /* since stackbuf now has allocated memory, rather than just a pointer,
474                                          * mark it as allocated so it can be freed properly */
475                                         stackbuf->malloc=1;
476                                         
477                                         /*premul the image*/
478                                         pixel = stackbuf->rect;
479                                         for (i=0; i<stackbuf->x*stackbuf->y; i++, pixel += 4) {
480                                                 pixel[0] *= pixel[3];
481                                                 pixel[1] *= pixel[3];
482                                                 pixel[2] *= pixel[3];
483                                         }
484                                 }
485                         
486                                 /* put image on stack */        
487                                 out[0]->data= stackbuf;
488                                 
489                                 /* alpha output */
490                                 if (out[1]->hasoutput)
491                                         out[1]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
492                                 
493                                 /* Z output */
494                                 if (out[2]->hasoutput)
495                                         out[2]->data= node_composit_get_zimage(node, rd);
496                                 
497                                 /* preview */
498                                 generate_preview(data, node, stackbuf);
499                         }
500                 }
501         }       
502 }
503
504 static void node_composit_init_image(bNodeTree *ntree, bNode* node, bNodeTemplate *UNUSED(ntemp))
505 {
506         ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user");
507         node->storage= iuser;
508         iuser->frames= 1;
509         iuser->sfra= 1;
510         iuser->fie_ima= 2;
511         iuser->ok= 1;
512         
513         /* setup initial outputs */
514         cmp_node_image_verify_outputs(ntree, node);
515 }
516
517 void register_node_type_cmp_image(bNodeTreeType *ttype)
518 {
519         static bNodeType ntype;
520
521         node_type_base(ttype, &ntype, CMP_NODE_IMAGE, "Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
522         node_type_size(&ntype, 120, 80, 300);
523         node_type_init(&ntype, node_composit_init_image);
524         node_type_storage(&ntype, "ImageUser", node_free_standard_storage, node_copy_standard_storage);
525         node_type_update(&ntype, cmp_node_image_update, NULL);
526         node_type_exec(&ntype, node_composit_exec_image);
527
528         nodeRegisterType(ttype, &ntype);
529 }
530
531
532 /* **************** RENDER RESULT ******************** */
533
534 static CompBuf *compbuf_from_pass(RenderData *rd, RenderLayer *rl, int rectx, int recty, int passcode)
535 {
536         float *fp= RE_RenderLayerGetPass(rl, passcode);
537         if (fp) {
538                 CompBuf *buf;
539                 int buftype= CB_VEC3;
540
541                 if (ELEM4(passcode, SCE_PASS_Z, SCE_PASS_INDEXOB, SCE_PASS_MIST, SCE_PASS_INDEXMA))
542                         buftype= CB_VAL;
543                 else if (passcode==SCE_PASS_VECTOR)
544                         buftype= CB_VEC4;
545                 else if (ELEM(passcode, SCE_PASS_COMBINED, SCE_PASS_RGBA))
546                         buftype= CB_RGBA;
547
548                 if (rd->scemode & R_COMP_CROP)
549                         buf= get_cropped_compbuf(&rd->disprect, fp, rectx, recty, buftype);
550                 else {
551                         buf= alloc_compbuf(rectx, recty, buftype, 0);
552                         buf->rect= fp;
553                 }
554                 return buf;
555         }
556         return NULL;
557 }
558
559 static void node_composit_rlayers_out(RenderData *rd, RenderLayer *rl, bNodeStack **out, int rectx, int recty)
560 {
561         if (out[RRES_OUT_Z]->hasoutput)
562                 out[RRES_OUT_Z]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_Z);
563         if (out[RRES_OUT_VEC]->hasoutput)
564                 out[RRES_OUT_VEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_VECTOR);
565         if (out[RRES_OUT_NORMAL]->hasoutput)
566                 out[RRES_OUT_NORMAL]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_NORMAL);
567         if (out[RRES_OUT_UV]->hasoutput)
568                 out[RRES_OUT_UV]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_UV);
569
570         if (out[RRES_OUT_RGBA]->hasoutput)
571                 out[RRES_OUT_RGBA]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_RGBA);
572         if (out[RRES_OUT_DIFF]->hasoutput)
573                 out[RRES_OUT_DIFF]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE);
574         if (out[RRES_OUT_SPEC]->hasoutput)
575                 out[RRES_OUT_SPEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SPEC);
576         if (out[RRES_OUT_SHADOW]->hasoutput)
577                 out[RRES_OUT_SHADOW]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SHADOW);
578         if (out[RRES_OUT_AO]->hasoutput)
579                 out[RRES_OUT_AO]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_AO);
580         if (out[RRES_OUT_REFLECT]->hasoutput)
581                 out[RRES_OUT_REFLECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFLECT);
582         if (out[RRES_OUT_REFRACT]->hasoutput)
583                 out[RRES_OUT_REFRACT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFRACT);
584         if (out[RRES_OUT_INDIRECT]->hasoutput)
585                 out[RRES_OUT_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDIRECT);
586         if (out[RRES_OUT_INDEXOB]->hasoutput)
587                 out[RRES_OUT_INDEXOB]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXOB);
588         if (out[RRES_OUT_INDEXMA]->hasoutput)
589                 out[RRES_OUT_INDEXMA]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXMA);
590         if (out[RRES_OUT_MIST]->hasoutput)
591                 out[RRES_OUT_MIST]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_MIST);
592         if (out[RRES_OUT_EMIT]->hasoutput)
593                 out[RRES_OUT_EMIT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_EMIT);
594         if (out[RRES_OUT_ENV]->hasoutput)
595                 out[RRES_OUT_ENV]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_ENVIRONMENT);
596         if (out[RRES_OUT_DIFF_DIRECT]->hasoutput)
597                 out[RRES_OUT_DIFF_DIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE_DIRECT);
598         if (out[RRES_OUT_DIFF_INDIRECT]->hasoutput)
599                 out[RRES_OUT_DIFF_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE_INDIRECT);
600         if (out[RRES_OUT_DIFF_COLOR]->hasoutput)
601                 out[RRES_OUT_DIFF_COLOR]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE_COLOR);
602         if (out[RRES_OUT_GLOSSY_DIRECT]->hasoutput)
603                 out[RRES_OUT_GLOSSY_DIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_GLOSSY_DIRECT);
604         if (out[RRES_OUT_GLOSSY_INDIRECT]->hasoutput)
605                 out[RRES_OUT_GLOSSY_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_GLOSSY_INDIRECT);
606         if (out[RRES_OUT_GLOSSY_COLOR]->hasoutput)
607                 out[RRES_OUT_GLOSSY_COLOR]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_GLOSSY_COLOR);
608         if (out[RRES_OUT_TRANSM_DIRECT]->hasoutput)
609                 out[RRES_OUT_TRANSM_DIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_TRANSM_DIRECT);
610         if (out[RRES_OUT_TRANSM_INDIRECT]->hasoutput)
611                 out[RRES_OUT_TRANSM_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_TRANSM_INDIRECT);
612         if (out[RRES_OUT_TRANSM_COLOR]->hasoutput)
613                 out[RRES_OUT_TRANSM_COLOR]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_TRANSM_COLOR);
614 }
615
616
617
618 static void node_composit_exec_rlayers(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
619 {
620         Scene *sce= (Scene *)node->id;
621         Render *re= (sce)? RE_GetRender(sce->id.name): NULL;
622         RenderData *rd= data;
623         RenderResult *rr= NULL;
624
625         if (re)
626                 rr= RE_AcquireResultRead(re);
627
628         if (rr) {
629                 SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1);
630                 if (srl) {
631                         RenderLayer *rl= RE_GetRenderLayer(rr, srl->name);
632                         if (rl && rl->rectf) {
633                                 CompBuf *stackbuf;
634
635                                 /* we put render rect on stack, cbuf knows rect is from other ibuf when freed! */
636                                 if (rd->scemode & R_COMP_CROP)
637                                         stackbuf= get_cropped_compbuf(&rd->disprect, rl->rectf, rr->rectx, rr->recty, CB_RGBA);
638                                 else {
639                                         stackbuf= alloc_compbuf(rr->rectx, rr->recty, CB_RGBA, 0);
640                                         stackbuf->rect= rl->rectf;
641                                 }
642                                 if (stackbuf==NULL) {
643                                         printf("Error; Preview Panel in UV Window returns zero sized image\n");
644                                 }
645                                 else {
646                                         stackbuf->xof= rr->xof;
647                                         stackbuf->yof= rr->yof;
648
649                                         /* put on stack */
650                                         out[RRES_OUT_IMAGE]->data= stackbuf;
651
652                                         if (out[RRES_OUT_ALPHA]->hasoutput)
653                                                 out[RRES_OUT_ALPHA]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
654
655                                         node_composit_rlayers_out(rd, rl, out, rr->rectx, rr->recty);
656
657                                         generate_preview(data, node, stackbuf);
658                                 }
659                         }
660                 }
661         }
662
663         if (re)
664                 RE_ReleaseResult(re);
665 }
666
667
668 void register_node_type_cmp_rlayers(bNodeTreeType *ttype)
669 {
670         static bNodeType ntype;
671
672         node_type_base(ttype, &ntype, CMP_NODE_R_LAYERS, "Render Layers", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
673         node_type_socket_templates(&ntype, NULL, cmp_node_rlayers_out);
674         node_type_size(&ntype, 150, 100, 300);
675         node_type_exec(&ntype, node_composit_exec_rlayers);
676
677         nodeRegisterType(ttype, &ntype);
678 }