converted more mixed tab/space indentations to tabs. only whitespace changes.
[blender.git] / source / blender / nodes / intern / CMP_nodes / CMP_image.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2006 Blender Foundation.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /** \file blender/nodes/intern/CMP_nodes/CMP_image.c
31  *  \ingroup cmpnodes
32  */
33
34
35 #include "../CMP_util.h"
36
37
38 /* **************** IMAGE (and RenderResult, multilayer image) ******************** */
39
40 static bNodeSocketType cmp_node_rlayers_out[]= {
41         {       SOCK_RGBA, 0, "Image",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
42         {       SOCK_VALUE, 0, "Alpha",         1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
43         {       SOCK_VALUE, 0, "Z",                     1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
44         {       SOCK_VECTOR, 0, "Normal",       0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
45         {       SOCK_VECTOR, 0, "UV",           1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
46         {       SOCK_VECTOR, 0, "Speed",        1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
47         {       SOCK_RGBA, 0, "Color",          0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
48         {       SOCK_RGBA, 0, "Diffuse",        0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
49         {       SOCK_RGBA, 0, "Specular",       0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
50         {       SOCK_RGBA, 0, "Shadow",         0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
51         {       SOCK_RGBA, 0, "AO",                     0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
52         {       SOCK_RGBA, 0, "Reflect",        0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
53         {       SOCK_RGBA, 0, "Refract",        0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
54         {       SOCK_RGBA, 0, "Indirect",       0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
55         {       SOCK_VALUE, 0, "IndexOB",       0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
56         {       SOCK_VALUE, 0, "Mist",          0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
57         {       SOCK_RGBA, 0, "Emit",           0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
58         {       SOCK_RGBA, 0, "Environment",0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
59         {       -1, 0, ""       }
60 };
61
62
63 /* note: this function is used for multilayer too, to ensure uniform 
64    handling with BKE_image_get_ibuf() */
65 static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *iuser)
66 {
67         ImBuf *ibuf;
68         CompBuf *stackbuf;
69         int type;
70
71         float *rect;
72         int alloc= FALSE;
73
74         ibuf= BKE_image_get_ibuf(ima, iuser);
75         if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) {
76                 return NULL;
77         }
78
79         if (ibuf->rect_float == NULL) {
80                 IMB_float_from_rect(ibuf);
81         }
82
83         /* now we need a float buffer from the image with matching color management */
84         /* XXX weak code, multilayer is excluded from this */
85         if(ibuf->channels == 4 && ima->rr==NULL) {
86                 if(rd->color_mgt_flag & R_COLOR_MANAGEMENT) {
87                         if(ibuf->profile != IB_PROFILE_NONE) {
88                                 rect= ibuf->rect_float;
89                         }
90                         else {
91                                 rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image");
92                                 srgb_to_linearrgb_rgba_rgba_buf(rect, ibuf->rect_float, ibuf->x * ibuf->y);
93                                 alloc= TRUE;
94                         }
95                 }
96                 else {
97                         if(ibuf->profile == IB_PROFILE_NONE) {
98                                 rect= ibuf->rect_float;
99                         }
100                         else {
101                                 rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image");
102                                 linearrgb_to_srgb_rgba_rgba_buf(rect, ibuf->rect_float, ibuf->x * ibuf->y);
103                                 alloc= TRUE;
104                         }
105                 }
106         }
107         else {
108                 /* non-rgba passes can't use color profiles */
109                 rect= ibuf->rect_float;
110         }
111         /* done coercing into the correct color management */
112
113
114         type= ibuf->channels;
115         
116         if(rd->scemode & R_COMP_CROP) {
117                 stackbuf= get_cropped_compbuf(&rd->disprect, rect, ibuf->x, ibuf->y, type);
118                 if(alloc)
119                         MEM_freeN(rect);
120         }
121         else {
122                 /* we put imbuf copy on stack, cbuf knows rect is from other ibuf when freed! */
123                 stackbuf= alloc_compbuf(ibuf->x, ibuf->y, type, FALSE);
124                 stackbuf->rect= rect;
125                 stackbuf->malloc= alloc;
126         }
127         
128         /*code to respect the premul flag of images; I'm
129           not sure if this is a good idea for multilayer images,
130           since it never worked before for them.
131         if (type==CB_RGBA && ima->flag & IMA_DO_PREMUL) {
132                 //premul the image
133                 int i;
134                 float *pixel = stackbuf->rect;
135                 
136                 for (i=0; i<stackbuf->x*stackbuf->y; i++, pixel += 4) {
137                         pixel[0] *= pixel[3];
138                         pixel[1] *= pixel[3];
139                         pixel[2] *= pixel[3];
140                 }
141         }
142         */
143         return stackbuf;
144 }
145
146 static CompBuf *node_composit_get_zimage(bNode *node, RenderData *rd)
147 {
148         ImBuf *ibuf= BKE_image_get_ibuf((Image *)node->id, node->storage);
149         CompBuf *zbuf= NULL;
150         
151         if(ibuf && ibuf->zbuf_float) {
152                 if(rd->scemode & R_COMP_CROP) {
153                         zbuf= get_cropped_compbuf(&rd->disprect, ibuf->zbuf_float, ibuf->x, ibuf->y, CB_VAL);
154                 }
155                 else {
156                         zbuf= alloc_compbuf(ibuf->x, ibuf->y, CB_VAL, 0);
157                         zbuf->rect= ibuf->zbuf_float;
158                 }
159         }
160         return zbuf;
161 }
162
163 /* check if layer is available, returns pass buffer */
164 static CompBuf *compbuf_multilayer_get(RenderData *rd, RenderLayer *rl, Image *ima, ImageUser *iuser, int passtype)
165 {
166         RenderPass *rpass;
167         short index;
168         
169         for(index=0, rpass= rl->passes.first; rpass; rpass= rpass->next, index++)
170                 if(rpass->passtype==passtype)
171                         break;
172         
173         if(rpass) {
174                 CompBuf *cbuf;
175                 
176                 iuser->pass= index;
177                 BKE_image_multilayer_index(ima->rr, iuser);
178                 cbuf= node_composit_get_image(rd, ima, iuser);
179                 
180                 return cbuf;
181         }
182         return NULL;
183 }
184
185 static void outputs_multilayer_get(RenderData *rd, RenderLayer *rl, bNodeStack **out, Image *ima, ImageUser *iuser)
186 {
187         if(out[RRES_OUT_Z]->hasoutput)
188                 out[RRES_OUT_Z]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_Z);
189         if(out[RRES_OUT_VEC]->hasoutput)
190                 out[RRES_OUT_VEC]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_VECTOR);
191         if(out[RRES_OUT_NORMAL]->hasoutput)
192                 out[RRES_OUT_NORMAL]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_NORMAL);
193         if(out[RRES_OUT_UV]->hasoutput)
194                 out[RRES_OUT_UV]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_UV);
195         
196         if(out[RRES_OUT_RGBA]->hasoutput)
197                 out[RRES_OUT_RGBA]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_RGBA);
198         if(out[RRES_OUT_DIFF]->hasoutput)
199                 out[RRES_OUT_DIFF]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_DIFFUSE);
200         if(out[RRES_OUT_SPEC]->hasoutput)
201                 out[RRES_OUT_SPEC]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_SPEC);
202         if(out[RRES_OUT_SHADOW]->hasoutput)
203                 out[RRES_OUT_SHADOW]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_SHADOW);
204         if(out[RRES_OUT_AO]->hasoutput)
205                 out[RRES_OUT_AO]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_AO);
206         if(out[RRES_OUT_REFLECT]->hasoutput)
207                 out[RRES_OUT_REFLECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_REFLECT);
208         if(out[RRES_OUT_REFRACT]->hasoutput)
209                 out[RRES_OUT_REFRACT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_REFRACT);
210         if(out[RRES_OUT_INDIRECT]->hasoutput)
211                 out[RRES_OUT_INDIRECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDIRECT);
212         if(out[RRES_OUT_INDEXOB]->hasoutput)
213                 out[RRES_OUT_INDEXOB]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDEXOB);
214         if(out[RRES_OUT_MIST]->hasoutput)
215                 out[RRES_OUT_MIST]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_MIST);
216         if(out[RRES_OUT_EMIT]->hasoutput)
217                 out[RRES_OUT_EMIT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_EMIT);
218         if(out[RRES_OUT_ENV]->hasoutput)
219                 out[RRES_OUT_ENV]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_ENVIRONMENT);
220 }
221
222
223 static void node_composit_exec_image(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
224 {
225         
226         /* image assigned to output */
227         /* stack order input sockets: col, alpha */
228         if(node->id) {
229                 RenderData *rd= data;
230                 Image *ima= (Image *)node->id;
231                 ImageUser *iuser= (ImageUser *)node->storage;
232                 CompBuf *stackbuf= NULL;
233                 
234                 /* first set the right frame number in iuser */
235                 BKE_image_user_calc_frame(iuser, rd->cfra, 0);
236                 
237                 /* force a load, we assume iuser index will be set OK anyway */
238                 if(ima->type==IMA_TYPE_MULTILAYER)
239                         BKE_image_get_ibuf(ima, iuser);
240                 
241                 if(ima->type==IMA_TYPE_MULTILAYER && ima->rr) {
242                         RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
243                         
244                         if(rl) {
245                                 out[0]->data= stackbuf= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_COMBINED);
246                                 
247                                 /* go over all layers */
248                                 outputs_multilayer_get(rd, rl, out, ima, iuser);
249                         }
250                 }
251                 else {
252                         stackbuf= node_composit_get_image(rd, ima, iuser);
253
254                         if (stackbuf) {
255                                 /*respect image premul option*/
256                                 if (stackbuf->type==CB_RGBA && ima->flag & IMA_DO_PREMUL) {
257                                         int i;
258                                         float *pixel;
259                         
260                                         /*first duplicate stackbuf->rect, since it's just a pointer
261                                           to the source imbuf, and we don't want to change that.*/
262                                         stackbuf->rect = MEM_dupallocN(stackbuf->rect);
263                                         
264                                         /* since stackbuf now has allocated memory, rather than just a pointer,
265                                          * mark it as allocated so it can be freed properly */
266                                         stackbuf->malloc=1;
267                                         
268                                         /*premul the image*/
269                                         pixel = stackbuf->rect;
270                                         for (i=0; i<stackbuf->x*stackbuf->y; i++, pixel += 4) {
271                                                 pixel[0] *= pixel[3];
272                                                 pixel[1] *= pixel[3];
273                                                 pixel[2] *= pixel[3];
274                                         }
275                                 }
276                         
277                                 /* put image on stack */        
278                                 out[0]->data= stackbuf;
279                         
280                                 if(out[2]->hasoutput)
281                                         out[2]->data= node_composit_get_zimage(node, rd);
282                         }
283                 }
284                 
285                 /* alpha and preview for both types */
286                 if(stackbuf) {
287                         if(out[1]->hasoutput)
288                                 out[1]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
289
290                         generate_preview(data, node, stackbuf);
291                 }
292         }       
293 }
294
295 static void node_composit_init_image(bNode* node)
296 {
297         ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user");
298         node->storage= iuser;
299         iuser->frames= 1;
300         iuser->sfra= 1;
301         iuser->fie_ima= 2;
302         iuser->ok= 1;
303 }
304
305 void register_node_type_cmp_image(ListBase *lb)
306 {
307         static bNodeType ntype;
308
309         node_type_base(&ntype, CMP_NODE_IMAGE, "Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS,
310                 NULL, cmp_node_rlayers_out);
311         node_type_size(&ntype, 120, 80, 300);
312         node_type_init(&ntype, node_composit_init_image);
313         node_type_storage(&ntype, "ImageUser", node_free_standard_storage, node_copy_standard_storage);
314         node_type_exec(&ntype, node_composit_exec_image);
315
316         nodeRegisterType(lb, &ntype);
317 }
318
319
320 /* **************** RENDER RESULT ******************** */
321
322 static CompBuf *compbuf_from_pass(RenderData *rd, RenderLayer *rl, int rectx, int recty, int passcode)
323 {
324         float *fp= RE_RenderLayerGetPass(rl, passcode);
325         if(fp) {
326                 CompBuf *buf;
327                 int buftype= CB_VEC3;
328
329                 if(ELEM3(passcode, SCE_PASS_Z, SCE_PASS_INDEXOB, SCE_PASS_MIST))
330                         buftype= CB_VAL;
331                 else if(passcode==SCE_PASS_VECTOR)
332                         buftype= CB_VEC4;
333                 else if(ELEM(passcode, SCE_PASS_COMBINED, SCE_PASS_RGBA))
334                         buftype= CB_RGBA;
335
336                 if(rd->scemode & R_COMP_CROP)
337                         buf= get_cropped_compbuf(&rd->disprect, fp, rectx, recty, buftype);
338                 else {
339                         buf= alloc_compbuf(rectx, recty, buftype, 0);
340                         buf->rect= fp;
341                 }
342                 return buf;
343         }
344         return NULL;
345 }
346
347 static void node_composit_rlayers_out(RenderData *rd, RenderLayer *rl, bNodeStack **out, int rectx, int recty)
348 {
349    if(out[RRES_OUT_Z]->hasoutput)
350           out[RRES_OUT_Z]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_Z);
351    if(out[RRES_OUT_VEC]->hasoutput)
352           out[RRES_OUT_VEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_VECTOR);
353    if(out[RRES_OUT_NORMAL]->hasoutput)
354           out[RRES_OUT_NORMAL]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_NORMAL);
355    if(out[RRES_OUT_UV]->hasoutput)
356           out[RRES_OUT_UV]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_UV);
357
358    if(out[RRES_OUT_RGBA]->hasoutput)
359           out[RRES_OUT_RGBA]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_RGBA);
360    if(out[RRES_OUT_DIFF]->hasoutput)
361           out[RRES_OUT_DIFF]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE);
362    if(out[RRES_OUT_SPEC]->hasoutput)
363           out[RRES_OUT_SPEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SPEC);
364    if(out[RRES_OUT_SHADOW]->hasoutput)
365           out[RRES_OUT_SHADOW]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SHADOW);
366    if(out[RRES_OUT_AO]->hasoutput)
367           out[RRES_OUT_AO]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_AO);
368    if(out[RRES_OUT_REFLECT]->hasoutput)
369           out[RRES_OUT_REFLECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFLECT);
370    if(out[RRES_OUT_REFRACT]->hasoutput)
371           out[RRES_OUT_REFRACT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFRACT);
372    if(out[RRES_OUT_INDIRECT]->hasoutput)
373           out[RRES_OUT_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDIRECT);
374    if(out[RRES_OUT_INDEXOB]->hasoutput)
375            out[RRES_OUT_INDEXOB]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXOB);
376    if(out[RRES_OUT_MIST]->hasoutput)
377            out[RRES_OUT_MIST]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_MIST);
378    if(out[RRES_OUT_EMIT]->hasoutput)
379            out[RRES_OUT_EMIT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_EMIT);
380    if(out[RRES_OUT_ENV]->hasoutput)
381            out[RRES_OUT_ENV]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_ENVIRONMENT);
382 }
383
384 static void node_composit_exec_rlayers(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
385 {
386         Scene *sce= (Scene *)node->id;
387         Render *re= (sce)? RE_GetRender(sce->id.name): NULL;
388         RenderData *rd= data;
389         RenderResult *rr= NULL;
390
391         if(re)
392                 rr= RE_AcquireResultRead(re);
393
394         if(rr) {
395                 SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1);
396                 if(srl) {
397                         RenderLayer *rl= RE_GetRenderLayer(rr, srl->name);
398                         if(rl && rl->rectf) {
399                                 CompBuf *stackbuf;
400
401                                 /* we put render rect on stack, cbuf knows rect is from other ibuf when freed! */
402                                 if(rd->scemode & R_COMP_CROP)
403                                         stackbuf= get_cropped_compbuf(&rd->disprect, rl->rectf, rr->rectx, rr->recty, CB_RGBA);
404                                 else {
405                                         stackbuf= alloc_compbuf(rr->rectx, rr->recty, CB_RGBA, 0);
406                                         stackbuf->rect= rl->rectf;
407                                 }
408                                 if(stackbuf==NULL) {
409                                         printf("Error; Preview Panel in UV Window returns zero sized image\n");
410                                 }
411                                 else {
412                                         stackbuf->xof= rr->xof;
413                                         stackbuf->yof= rr->yof;
414
415                                         /* put on stack */
416                                         out[RRES_OUT_IMAGE]->data= stackbuf;
417
418                                         if(out[RRES_OUT_ALPHA]->hasoutput)
419                                                 out[RRES_OUT_ALPHA]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
420
421                                         node_composit_rlayers_out(rd, rl, out, rr->rectx, rr->recty);
422
423                                         generate_preview(data, node, stackbuf);
424                                 }
425                         }
426                 }
427         }
428
429         if(re)
430                 RE_ReleaseResult(re);
431 }
432
433
434 void register_node_type_cmp_rlayers(ListBase *lb)
435 {
436         static bNodeType ntype;
437
438         node_type_base(&ntype, CMP_NODE_R_LAYERS, "Render Layers", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS,
439                 NULL, cmp_node_rlayers_out);
440         node_type_size(&ntype, 150, 100, 300);
441         node_type_exec(&ntype, node_composit_exec_rlayers);
442
443         nodeRegisterType(lb, &ntype);
444 }
445
446
447