~siretart/ubuntu/utopic/blender/libav10

« back to all changes in this revision

Viewing changes to source/blender/nodes/composite/nodes/node_composite_image.c

  • Committer: Package Import Robot
  • Author(s): Matteo F. Vescovi
  • Date: 2012-07-23 08:54:18 UTC
  • mfrom: (14.2.16 sid)
  • mto: (14.2.19 sid)
  • mto: This revision was merged to the branch mainline in revision 42.
  • Revision ID: package-import@ubuntu.com-20120723085418-9foz30v6afaf5ffs
Tags: 2.63a-2
* debian/: Cycles support added (Closes: #658075)
  For now, this top feature has been enabled only
  on [any-amd64 any-i386] architectures because
  of OpenImageIO failing on all others
* debian/: scripts installation path changed
  from /usr/lib to /usr/share:
  + debian/patches/: patchset re-worked for path changing
  + debian/control: "Breaks" field added on yafaray-exporter

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}