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