Orange; more render & compo stuff!
[blender-staging.git] / source / blender / blenkernel / intern / node_composit.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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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 <stdlib.h>
31 #include <string.h>
32 #include <math.h>
33
34 #include "DNA_ID.h"
35 #include "DNA_image_types.h"
36 #include "DNA_node_types.h"
37 #include "DNA_material_types.h"
38 #include "DNA_scene_types.h"
39 #include "DNA_texture_types.h"
40 #include "DNA_vec_types.h"
41
42 #include "BKE_blender.h"
43 #include "BKE_colortools.h"
44 #include "BKE_global.h"
45 #include "BKE_image.h"
46 #include "BKE_node.h"
47 #include "BKE_material.h"
48 #include "BKE_texture.h"
49 #include "BKE_utildefines.h"
50
51 #include "BLI_arithb.h"
52 #include "BLI_blenlib.h"
53
54 #include "MEM_guardedalloc.h"
55 #include "IMB_imbuf.h"
56 #include "IMB_imbuf_types.h"
57
58 #include "RE_pipeline.h"
59
60 /* *************************** operations support *************************** */
61
62 /* general signal that's in output sockets, and goes over the wires */
63 typedef struct CompBuf {
64         float *rect;
65         int x, y;
66         short type, malloc;
67         rcti disprect;          /* cropped part of image */
68         int xof, yof;           /* relative to center of target image */
69 } CompBuf;
70
71 /* defines also used for pixel size */
72 #define CB_RGBA         4
73 #define CB_VAL          1
74
75 static CompBuf *alloc_compbuf(int sizex, int sizey, int type, int alloc)
76 {
77         CompBuf *cbuf= MEM_callocN(sizeof(CompBuf), "compbuf");
78         
79         cbuf->x= sizex;
80         cbuf->y= sizey;
81         cbuf->type= type;
82         if(alloc) {
83                 if(cbuf->type==CB_RGBA)
84                         cbuf->rect= MEM_mallocN(4*sizeof(float)*sizex*sizey, "new rect");
85                 else
86                         cbuf->rect= MEM_mallocN(sizeof(float)*sizex*sizey, "new rect");
87                 cbuf->malloc= 1;
88         }
89         cbuf->disprect.xmin= 0;
90         cbuf->disprect.ymin= 0;
91         cbuf->disprect.xmax= sizex;
92         cbuf->disprect.ymax= sizey;
93         
94         return cbuf;
95 }
96
97 void free_compbuf(CompBuf *cbuf)
98 {
99         if(cbuf->malloc && cbuf->rect)
100                 MEM_freeN(cbuf->rect);
101         MEM_freeN(cbuf);
102 }
103
104 #if 0
105 /* on first call, disprect should be initialized to 'out', then you can call this on all 'src' images */
106 static void get_overlap_rct(CompBuf *out, CompBuf *src, rcti *disprect)
107 {
108         rcti rect;
109         /* output center is considered (0,0) */
110         
111         if(src==NULL) return;
112         
113         /* translate src into output space */
114         rect= src->disprect;
115         BLI_translate_rcti(&rect, out->xof-src->xof, out->xof-src->xof);
116         /* intersect rect with current disprect */
117         
118         BLI_isect_rcti(&rect, disprect, disprect);
119 }
120
121 static void get_scanline_rcti(CompBuf *out, rcti *disprect, CompBuf *src, rcti *srcrect)
122 {
123         int xof, yof;
124         
125         /* translate src into output space */
126         xof= out->xof-src->xof;
127         yof= out->xof-src->xof;
128         
129         srcrect->xmin= disprect->xmin + xof;
130         srcrect->ymin= disprect->ymin + yof;
131         srcrect->xmax= disprect->xmax + xof;
132         srcrect->ymax= disprect->ymax + yof;
133 }
134 #endif
135
136 /* Pixel-to-Pixel operation, 1 Image in, 1 out */
137 static void composit1_pixel_processor(bNode *node, CompBuf *out, CompBuf *src_buf, float *src_col,
138                                                                           void (*func)(bNode *, float *, float *))
139 {
140         float *outfp, *srcfp, *out_data, *src_data;
141         int outx, outy;
142         int srcx, srcy;
143         int out_pix, out_stride, src_stride, src_pix, x, y;
144         
145         outx= out->x;
146         outy= out->y;
147         out_pix= out->type;
148         out_stride= out->x;
149         out_data= out->rect;
150         
151         /* handle case when input is constant color */
152         if(src_buf==NULL) {
153                 srcx= outx; srcy= outy;
154                 src_stride= 0;
155                 src_pix= 0;
156                 src_data= src_col;
157         }
158         else {
159                 srcx= src_buf->x;
160                 srcy= src_buf->y;
161                 src_stride= srcx;
162                 src_pix= src_buf->type;
163                 src_data= src_buf->rect;
164         }
165         
166         outx= MIN2(outx, srcx);
167         outy= MIN2(outy, srcy);
168
169         for(y=0; y<outy; y++) {
170                 /* set scanlines on right location */
171                 srcfp= src_data + src_pix*y*src_stride;
172                 outfp= out_data + out_pix*y*out_stride;
173                         
174                 for(x=0; x<outx; x++) {
175                         func(node, outfp, srcfp);
176                         srcfp += src_pix;
177                         outfp += out_pix;
178                 }
179         }
180 }
181
182 /* Pixel-to-Pixel operation, 2 Images in, 1 out */
183 static void composit2_pixel_processor(bNode *node, CompBuf *out, CompBuf *src_buf, float *src_col,
184                                                                           CompBuf *fac_buf, float *fac, void (*func)(bNode *, float *, float *, float *))
185 {
186         float *outfp, *srcfp, *src_data, *facfp, *fac_data;
187         int outx= out->x, outy= out->y;
188         int srcx, srcy, facx, facy;
189         int out_pix, src_stride, src_pix, fac_stride, fac_pix, x, y;
190         
191         out_pix= out->type;
192         
193         /* handle case when input is constant color */
194         if(src_buf==NULL) {
195                 srcx= outx; srcy= outy;
196                 src_stride= 0;
197                 src_pix= 0;
198                 src_data= src_col;
199         }
200         else {
201                 srcx= src_buf->x;
202                 srcy= src_buf->y;
203                 src_stride= srcx;
204                 src_pix= src_buf->type;
205                 src_data= src_buf->rect;
206         }
207         
208         /* factor buf or constant? */
209         if(fac_buf==NULL) {
210                 facx= outx; facy= outy;
211                 fac_stride= 0;
212                 fac_pix= 0;
213                 fac_data= fac;
214         }
215         else {
216                 facx= fac_buf->x;
217                 facy= fac_buf->y;
218                 fac_stride= facx;
219                 fac_pix= fac_buf->type;
220                 fac_data= fac_buf->rect;
221         }
222         
223         if(fac_data==NULL) {
224                 printf("fac buffer error, node %s\n", node->name);
225                 return;
226         }
227         
228         facx= MIN2(facx, srcx);
229         facy= MIN2(facy, srcy);
230         
231 #if 0   
232         if(src_buf) {
233                 rcti disprect;
234                 
235                 disprect= out->disprect;
236                 get_overlap_rct(out, src_buf, &disprect);
237                 printf("%s\n", node->name);
238                 printf("union %d %d %d %d\n", disprect.xmin,disprect.ymin,disprect.xmax,disprect.ymax);
239         }
240         /* new approach */
241         outfp= out->rect_float + src.ymin*outx + ;
242         for(y=src.ymin; y<src.ymax; y++) {
243                 
244                 /* all operators available */
245                 if(y>=disp.ymin && y<disp.ymax) {
246                         srcfp= src_data + (src_stride*(y+scrc.ymin) + src.xmin);
247                         facfp= fac_data + (fac_stride*(y+fac.ymin) + fac.xmin);
248                         
249                         for(x= src.xmin; x<src.xmax; x++) {
250                                 if(x>=disp.xmin && x<disp.xmax) {
251                                         
252                                         srcfp+= src_pix;
253                                         facfp+= fac_pix;
254                                 }
255                                 else {
256                                         /* copy src1 */
257                                 }
258                         }
259                 }
260                 else {
261                         /* copy src1 */
262                         srcfp= src_data + (src_stride*(y+scrc.ymin) + src.xmin);
263                         
264                         QUATCOPY(outfp, srcfp);
265                 }
266         }       
267 #endif
268         
269         outfp= out->rect;
270         for(y=0; y<outy; y++) {
271                 /* set source scanline on right location */
272                 srcfp= src_data + src_pix*y*src_stride;
273                 facfp= fac_data + fac_pix*y*fac_stride;
274                 
275                 for(x=0; x<outx; x++, outfp+=out_pix) {
276                         if(x<facx && y<facy)
277                                 func(node, outfp, srcfp, facfp);
278                         srcfp += src_pix;
279                         facfp += fac_pix;
280                 }
281         }
282 }
283
284 /* Pixel-to-Pixel operation, 3 Images in, 1 out */
285 static void composit3_pixel_processor(bNode *node, CompBuf *out, CompBuf *src1_buf, float *src1_col, CompBuf *src2_buf, float *src2_col, 
286                                                                           CompBuf *fac_buf, float fac, void (*func)(bNode *, float *, float *, float *, float))
287 {
288         float *outfp, *src1fp, *src2fp, *facfp, *src1_data, *src2_data, *fac_data;
289         int outx= out->x, outy= out->y;
290         int src1x, src1y, src2x, src2y, facx, facy;
291         int src1_stride, src1_pix, src2_stride, src2_pix, fac_stride, fac_pix, x, y;
292
293         /* handle case when input has constant color */
294         if(src1_buf==NULL) {
295                 src1x= outx; src1y= outy;
296                 src1_stride= 0;
297                 src1_pix= 0;
298                 src1_data= src1_col;
299         }
300         else {
301                 src1x= src1_buf->x;
302                 src1y= src1_buf->y;
303                 src1_stride= src1x;
304                 src1_pix= src1_buf->type;
305                 src1_data= src1_buf->rect;
306         }
307         
308         if(src2_buf==NULL) {
309                 src2x= outx; src2y= outy;
310                 src2_stride= 0;
311                 src2_pix= 0;
312                 src2_data= src2_col;
313         }
314         else {
315                 src2x= src2_buf->x;
316                 src2y= src2_buf->y;
317                 src2_stride= src2x;
318                 src2_pix= src2_buf->type;
319                 src2_data= src2_buf->rect;
320         }
321         
322         /* factor buf or constant? */
323         if(fac_buf==NULL) {
324                 facx= outx; facy= outy;
325                 fac_stride= 0;
326                 fac_pix= 0;
327                 fac_data= &fac;
328         }
329         else {
330                 facx= fac_buf->x;
331                 facy= fac_buf->y;
332                 fac_stride= facx;
333                 fac_pix= 1;
334                 fac_data= fac_buf->rect;
335         }
336         
337         facx= MIN3(facx, src1x, src2x);
338         facy= MIN3(facy, src1y, src2y);
339         
340         outfp= out->rect;
341         for(y=0; y<outy; y++) {
342                 
343                 /* set source scanlines on right location */
344                 src1fp= src1_data + src1_pix*y*src1_stride;
345                 src2fp= src2_data + src2_pix*y*src2_stride;
346                 facfp= fac_data + y*fac_stride;
347                 
348                 for(x=0; x<outx; x++, outfp+=4) {
349                         if(x<facx && y<facy)
350                                 func(node, outfp, src1fp, src2fp, *facfp);
351                         src1fp+= src1_pix;
352                         src2fp+= src2_pix;
353                         facfp+= fac_pix;
354                 }
355         }
356 }
357
358 /*  */
359 static CompBuf *alphabuf_from_rgbabuf(CompBuf *cbuf)
360 {
361         CompBuf *valbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1);
362         float *valf, *rectf;
363         int tot;
364         
365         valf= valbuf->rect;
366         rectf= cbuf->rect + 3;
367         for(tot= cbuf->x*cbuf->y; tot>0; tot--, valf++, rectf+=4)
368                 *valf= *rectf;
369         
370         return valbuf;
371 }
372
373 static void generate_preview(bNode *node, CompBuf *stackbuf)
374 {
375         bNodePreview *preview= node->preview;
376         
377         if(preview) {
378                 ImBuf *ibuf= IMB_allocImBuf(stackbuf->x, stackbuf->y, 32, 0, 0);        /* empty */
379                 
380                 if(stackbuf->x > stackbuf->y) {
381                         preview->xsize= 140;
382                         preview->ysize= (140*stackbuf->y)/stackbuf->x;
383                 }
384                 else {
385                         preview->ysize= 140;
386                         preview->xsize= (140*stackbuf->x)/stackbuf->y;
387                 }
388                 ibuf->rect_float= stackbuf->rect;
389                 ibuf= IMB_scalefastImBuf(ibuf, preview->xsize, preview->ysize);
390                 
391                 /* this ensures free-imbuf does the right stuff */
392                 SWAP(float *, ibuf->rect_float, node->preview->rect);
393                 
394                 IMB_freeImBuf(ibuf);
395         }
396 }
397
398 /* ******************************************************** */
399 /* ********* Composit Node type definitions ***************** */
400 /* ******************************************************** */
401
402 /* SocketType syntax: 
403    socket type, max connections (0 is no limit), name, 4 values for default, 2 values for range */
404
405 /* Verification rule: If name changes, a saved socket and its links will be removed! Type changes are OK */
406
407 /* **************** VIEWER ******************** */
408 static bNodeSocketType cmp_node_viewer_in[]= {
409         {       SOCK_RGBA, 1, "Image",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
410         {       SOCK_VALUE, 1, "Alpha",         1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
411         {       SOCK_VALUE, 1, "Z",             1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
412         {       -1, 0, ""       }
413 };
414
415 static void do_copy_rgba(bNode *node, float *out, float *in)
416 {
417         QUATCOPY(out, in);
418 }
419 static void do_copy_value(bNode *node, float *out, float *in)
420 {
421         out[0]= in[0];
422 }
423 static void do_copy_a_rgba(bNode *node, float *out, float *in, float *fac)
424 {
425         VECCOPY(out, in);
426         out[3]= *fac;
427 }
428
429 static void node_composit_exec_viewer(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
430 {
431         /* image assigned to output */
432         /* stack order input sockets: col, alpha, z */
433         
434         if(node->id && (node->flag & NODE_DO_OUTPUT)) { /* only one works on out */
435                 Image *ima= (Image *)node->id;
436                 CompBuf *cbuf;
437                 int rectx, recty;
438                 
439                 /* scene size? */
440                 if(1) {
441                         RenderData *rd= data;
442
443                         /* re-create output, derive size from scene */
444                         rectx= (rd->size*rd->xsch)/100;
445                         recty= (rd->size*rd->ysch)/100;
446                         
447                         if(ima->ibuf) IMB_freeImBuf(ima->ibuf);
448                         ima->ibuf= IMB_allocImBuf(rectx, recty, 32, IB_rectfloat, 0); // do alloc
449                         
450                         cbuf= alloc_compbuf(rectx, recty, CB_RGBA, 0);  // no alloc
451                         cbuf->rect= ima->ibuf->rect_float;
452                         
453                         /* when no alpha, we can simply copy */
454                         if(in[1]->data==NULL)
455                                 composit1_pixel_processor(node, cbuf, in[0]->data, in[0]->vec, do_copy_rgba);
456                         else
457                                 composit2_pixel_processor(node, cbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_copy_a_rgba);
458                         
459                         if(in[2]->data) {
460                                 CompBuf *zbuf= alloc_compbuf(rectx, recty, CB_VAL, 0);
461                                 addzbuffloatImBuf(ima->ibuf);
462                                 zbuf->rect= ima->ibuf->zbuf_float;
463                                 composit1_pixel_processor(node, zbuf, in[2]->data, in[2]->vec, do_copy_value);
464                                 free_compbuf(zbuf);
465                         }
466
467                         generate_preview(node, cbuf);
468                         free_compbuf(cbuf);
469                 }
470                 else { /* test */
471                         if(ima->ibuf) IMB_freeImBuf(ima->ibuf);
472                         ima->ibuf= IMB_allocImBuf(rectx, recty, 32, 0, 0); // do alloc
473                         ima->ibuf->mall= IB_rectfloat;
474                         cbuf= in[0]->data;
475                         ima->ibuf->rect_float= cbuf->rect;
476                         ima->ibuf->x= cbuf->x;
477                         ima->ibuf->y= cbuf->y;
478                         cbuf->rect= NULL;
479                 }
480
481         }       /* lets make only previews when not done yet, so activating doesnt update */
482         else if(in[0]->data && node->preview && node->preview->rect==NULL)
483                 generate_preview(node, in[0]->data);
484 }
485
486 static bNodeType cmp_node_viewer= {
487         /* type code   */       CMP_NODE_VIEWER,
488         /* name        */       "Viewer",
489         /* width+range */       80, 60, 200,
490         /* class+opts  */       NODE_CLASS_OUTPUT, NODE_PREVIEW,
491         /* input sock  */       cmp_node_viewer_in,
492         /* output sock */       NULL,
493         /* storage     */       "",
494         /* execfunc    */       node_composit_exec_viewer
495         
496 };
497
498 /* **************** COMPOSITE ******************** */
499 static bNodeSocketType cmp_node_composite_in[]= {
500         {       SOCK_RGBA, 1, "Image",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
501         {       SOCK_VALUE, 1, "Alpha",         1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
502         {       SOCK_VALUE, 1, "Z",                     1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
503         {       -1, 0, ""       }
504 };
505
506 /* applies to render pipeline */
507 static void node_composit_exec_composite(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
508 {
509         /* image assigned to output */
510         /* stack order input sockets: col, alpha, z */
511         
512         if(node->flag & NODE_DO_OUTPUT) {       /* only one works on out */
513                 RenderData *rd= data;
514                 if(rd->scemode & R_DOCOMP) {
515                         RenderResult *rr= RE_GetResult(RE_GetRender("Render"));
516                         if(rr) {
517                                 CompBuf *outbuf, *zbuf=NULL;
518                                 
519                                 if(rr->rectf) 
520                                         MEM_freeN(rr->rectf);
521                                 outbuf= alloc_compbuf(rr->rectx, rr->recty, CB_RGBA, 1);
522                                 
523                                 if(in[1]->data==NULL)
524                                         composit1_pixel_processor(node, outbuf, in[0]->data, in[0]->vec, do_copy_rgba);
525                                 else
526                                         composit2_pixel_processor(node, outbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_copy_a_rgba);
527                                 
528                                 if(in[2]->data) {
529                                         if(rr->rectz) 
530                                                 MEM_freeN(rr->rectz);
531                                         zbuf= alloc_compbuf(rr->rectx, rr->recty, CB_VAL, 1);
532                                         composit1_pixel_processor(node, zbuf, in[2]->data, in[2]->vec, do_copy_value);
533                                         rr->rectz= zbuf->rect;
534                                         zbuf->malloc= 0;
535                                         free_compbuf(zbuf);
536                                 }
537                                 generate_preview(node, outbuf);
538                                 
539                                 /* we give outbuf to rr... */
540                                 rr->rectf= outbuf->rect;
541                                 outbuf->malloc= 0;
542                                 free_compbuf(outbuf);
543                                 
544                                 return;
545                         }
546                 }
547         }
548         if(in[0]->data)
549                 generate_preview(node, in[0]->data);
550 }
551
552 static bNodeType cmp_node_composite= {
553         /* type code   */       CMP_NODE_COMPOSITE,
554         /* name        */       "Composite",
555         /* width+range */       80, 60, 200,
556         /* class+opts  */       NODE_CLASS_OUTPUT, NODE_PREVIEW,
557         /* input sock  */       cmp_node_composite_in,
558         /* output sock */       NULL,
559         /* storage     */       "",
560         /* execfunc    */       node_composit_exec_composite
561         
562 };
563
564 /* **************** OUTPUT FILE ******************** */
565 static bNodeSocketType cmp_node_output_file_in[]= {
566         {       SOCK_RGBA, 1, "Image",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
567         {       SOCK_VALUE, 1, "Alpha",         1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
568         {       -1, 0, ""       }
569 };
570
571
572 static void node_composit_exec_output_file(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
573 {
574         /* image assigned to output */
575         /* stack order input sockets: col, alpha */
576         
577         if(node->id && (node->flag & NODE_DO_OUTPUT)) { /* only one works on out */
578         }
579         else if(in[0]->data)
580                 generate_preview(node, in[0]->data);
581 }
582
583 static bNodeType cmp_node_output_file= {
584         /* type code   */       CMP_NODE_OUTPUT_FILE,
585         /* name        */       "File Output",
586         /* width+range */       80, 60, 200,
587         /* class+opts  */       NODE_CLASS_FILE, NODE_PREVIEW,
588         /* input sock  */       cmp_node_output_file_in,
589         /* output sock */       NULL,
590         /* storage     */       "",
591         /* execfunc    */       node_composit_exec_output_file
592         
593 };
594
595 /* **************** IMAGE ******************** */
596 static bNodeSocketType cmp_node_image_out[]= {
597         {       SOCK_RGBA, 0, "Image",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
598         {       SOCK_VALUE, 0, "Alpha",         1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
599         {       SOCK_VALUE, 0, "Z",                     1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
600         {       -1, 0, ""       }
601 };
602
603 static int calcimanr(int cfra, NodeImageAnim *nia)
604 {
605         
606         if(nia->frames==0) return nia->nr;
607         
608         cfra= cfra - nia->sfra;
609         
610         /* cyclic */
611         if(nia->cyclic)
612                 cfra= (cfra % nia->frames);
613         else if(cfra>=nia->frames)
614                 cfra= nia->frames-1;
615         else if(cfra<0)
616                 cfra= 0;
617         
618         cfra+= nia->nr;
619         
620         if(cfra<1) cfra= 1;
621         
622         return cfra;
623 }
624
625
626 static void animated_image(bNode *node, int cfra)
627 {
628         Image *ima;
629         NodeImageAnim *nia;
630         int imanr;
631         unsigned short numlen;
632         char name[FILE_MAXDIR+FILE_MAXFILE], head[FILE_MAXDIR+FILE_MAXFILE], tail[FILE_MAXDIR+FILE_MAXFILE];
633         
634         ima= (Image *)node->id;
635         nia= node->storage;
636         
637         if(nia && nia->frames && ima && ima->name) {    /* frames */
638                 strcpy(name, ima->name);
639                 
640                 imanr= calcimanr(cfra, nia);
641                 if(imanr!=ima->lastframe) {
642                         ima->lastframe= imanr;
643                         
644                         BLI_stringdec(name, head, tail, &numlen);
645                         BLI_stringenc(name, head, tail, numlen, imanr);
646                         
647                         ima= add_image(name);
648                         
649                         if(ima) {
650                                 ima->flag |= IMA_FROMANIM;
651                                 if(node->id) node->id->us--;
652                                 node->id= (ID *)ima;
653                                 
654                                 ima->ok= 1;
655                         }
656                 }
657         }
658 }
659
660
661 static void node_composit_exec_image(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
662 {
663         RenderData *rd= data;
664         
665         /* image assigned to output */
666         /* stack order input sockets: col, alpha */
667         if(node->id) {
668                 Image *ima;
669                 CompBuf *stackbuf;
670                 
671                 /* animated image? */
672                 if(node->storage)
673                         animated_image(node, rd->cfra);
674                 
675                 ima= (Image *)node->id;
676                 
677                 /* test if image is OK */
678                 if(ima->ok==0) return;
679                 
680                 if(ima->ibuf==NULL) {
681                         
682                         load_image(ima, IB_rect, G.sce, rd->cfra);      /* G.sce is current .blend path */
683                         if(ima->ibuf==NULL) {
684                                 ima->ok= 0;
685                                 return;
686                         }
687                 }
688                 if(ima->ibuf->rect_float==NULL)
689                         IMB_float_from_rect(ima->ibuf);
690                 
691                 /* we put imbuf copy on stack, cbuf knows rect is from other ibuf when freed! */
692                 stackbuf= alloc_compbuf(ima->ibuf->x, ima->ibuf->y, CB_RGBA, 0);
693                 stackbuf->rect= ima->ibuf->rect_float;
694                 
695                 /* put ibuf on stack */ 
696                 out[0]->data= stackbuf;
697                 
698                 if(out[1]->hasoutput)
699                         out[1]->data= alphabuf_from_rgbabuf(stackbuf);
700                 
701                 if(out[2]->hasoutput && ima->ibuf->zbuf_float) {
702                         CompBuf *zbuf= alloc_compbuf(ima->ibuf->x, ima->ibuf->y, CB_VAL, 0);
703                         zbuf->rect= ima->ibuf->zbuf_float;
704                         out[2]->data= zbuf;
705                 }
706                 
707                 generate_preview(node, stackbuf);
708         }       
709 }
710
711 /* uses node->storage to indicate animated image */
712
713 static bNodeType cmp_node_image= {
714         /* type code   */       CMP_NODE_IMAGE,
715         /* name        */       "Image",
716         /* width+range */       120, 80, 300,
717         /* class+opts  */       NODE_CLASS_GENERATOR, NODE_PREVIEW|NODE_OPTIONS,
718         /* input sock  */       NULL,
719         /* output sock */       cmp_node_image_out,
720         /* storage     */       "NodeImageAnim",
721         /* execfunc    */       node_composit_exec_image
722         
723 };
724
725 /* **************** RENDER RESULT ******************** */
726 static bNodeSocketType cmp_node_rresult_out[]= {
727         {       SOCK_RGBA, 0, "Image",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
728         {       SOCK_VALUE, 0, "Alpha",         1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
729         {       SOCK_VALUE, 0, "Z",                     1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
730         {       -1, 0, ""       }
731 };
732
733 static void node_composit_exec_rresult(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
734 {
735         RenderResult *rr= RE_GetResult(RE_GetRender("Render"));
736         if(rr) {
737                 RenderLayer *rl= BLI_findlink(&rr->layers, node->custom1);
738                 if(rl) {
739                         CompBuf *stackbuf;
740                         
741                         /* we put render rect on stack, cbuf knows rect is from other ibuf when freed! */
742                         stackbuf= alloc_compbuf(rr->rectx, rr->recty, CB_RGBA, 0);
743                         stackbuf->rect= rl->rectf;
744                         
745                         /* put on stack */      
746                         out[0]->data= stackbuf;
747                         
748                         if(out[1]->hasoutput)
749                                 out[1]->data= alphabuf_from_rgbabuf(stackbuf);
750                         if(out[2]->hasoutput && rl->rectz) {
751                                 CompBuf *zbuf= alloc_compbuf(rr->rectx, rr->recty, CB_VAL, 0);
752                                 zbuf->rect= rl->rectz;
753                                 out[2]->data= zbuf;
754                         }
755                         
756                         generate_preview(node, stackbuf);
757                 }
758         }       
759 }
760
761 /* custom1 = render layer in use */
762 static bNodeType cmp_node_rresult= {
763         /* type code   */       CMP_NODE_R_RESULT,
764         /* name        */       "Render Result",
765         /* width+range */       120, 80, 300,
766         /* class+opts  */       NODE_CLASS_GENERATOR, NODE_PREVIEW|NODE_OPTIONS,
767         /* input sock  */       NULL,
768         /* output sock */       cmp_node_rresult_out,
769         /* storage     */       "",
770         /* execfunc    */       node_composit_exec_rresult
771         
772 };
773
774 /* **************** NORMAL  ******************** */
775 static bNodeSocketType cmp_node_normal_in[]= {
776         {       SOCK_VECTOR, 1, "Normal",       0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
777         {       -1, 0, ""       }
778 };
779
780 static bNodeSocketType cmp_node_normal_out[]= {
781         {       SOCK_VECTOR, 0, "Normal",       0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f},
782         {       SOCK_VALUE, 0, "Dot",           1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
783         {       -1, 0, ""       }
784 };
785
786 /* generates normal, does dot product */
787 static void node_composit_exec_normal(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
788 {
789         bNodeSocket *sock= node->outputs.first;
790         /* stack order input:  normal */
791         /* stack order output: normal, value */
792         
793         VECCOPY(out[0]->vec, sock->ns.vec);
794         /* render normals point inside... the widget points outside */
795         out[1]->vec[0]= -INPR(out[0]->vec, in[0]->vec);
796 }
797
798 static bNodeType cmp_node_normal= {
799         /* type code   */       CMP_NODE_NORMAL,
800         /* name        */       "Normal",
801         /* width+range */       100, 60, 200,
802         /* class+opts  */       NODE_CLASS_OPERATOR, NODE_OPTIONS,
803         /* input sock  */       cmp_node_normal_in,
804         /* output sock */       cmp_node_normal_out,
805         /* storage     */       "",
806         /* execfunc    */       node_composit_exec_normal
807         
808 };
809
810 /* **************** CURVE VEC  ******************** */
811 static bNodeSocketType cmp_node_curve_vec_in[]= {
812         {       SOCK_VECTOR, 1, "Vector",       0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
813         {       -1, 0, ""       }
814 };
815
816 static bNodeSocketType cmp_node_curve_vec_out[]= {
817         {       SOCK_VECTOR, 0, "Vector",       0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f},
818         {       -1, 0, ""       }
819 };
820
821 static void node_composit_exec_curve_vec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
822 {
823         /* stack order input:  vec */
824         /* stack order output: vec */
825         
826         curvemapping_evaluate_premulRGBF(node->storage, out[0]->vec, in[0]->vec);
827 }
828
829 static bNodeType cmp_node_curve_vec= {
830         /* type code   */       CMP_NODE_CURVE_VEC,
831         /* name        */       "Vector Curves",
832         /* width+range */       200, 140, 320,
833         /* class+opts  */       NODE_CLASS_OPERATOR, NODE_OPTIONS,
834         /* input sock  */       cmp_node_curve_vec_in,
835         /* output sock */       cmp_node_curve_vec_out,
836         /* storage     */       "CurveMapping",
837         /* execfunc    */       node_composit_exec_curve_vec
838         
839 };
840
841 /* **************** CURVE RGB  ******************** */
842 static bNodeSocketType cmp_node_curve_rgb_in[]= {
843         {       SOCK_RGBA, 1, "Image",  0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
844         {       -1, 0, ""       }
845 };
846
847 static bNodeSocketType cmp_node_curve_rgb_out[]= {
848         {       SOCK_RGBA, 0, "Image",  0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f},
849         {       -1, 0, ""       }
850 };
851
852 static void do_curves(bNode *node, float *out, float *in)
853 {
854         curvemapping_evaluateRGBF(node->storage, out, in);
855         out[3]= in[3];
856 }
857
858 static void node_composit_exec_curve_rgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
859 {
860         /* stack order input:  vec */
861         /* stack order output: vec */
862         
863         if(out[0]->hasoutput==0)
864                 return;
865
866         /* input no image? then only color operation */
867         if(in[0]->data==NULL) {
868                 curvemapping_evaluateRGBF(node->storage, out[0]->vec, in[0]->vec);
869         }
870         else {
871                 /* make output size of input image */
872                 CompBuf *cbuf= in[0]->data;
873                 CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs
874                 
875                 curvemapping_premultiply(node->storage, 0);
876                 composit1_pixel_processor(node, stackbuf, in[0]->data, NULL, do_curves);
877                 curvemapping_premultiply(node->storage, 1);
878                 
879                 out[0]->data= stackbuf;
880         }
881         
882 }
883
884 static bNodeType cmp_node_curve_rgb= {
885         /* type code   */       CMP_NODE_CURVE_RGB,
886         /* name        */       "RGB Curves",
887         /* width+range */       200, 140, 320,
888         /* class+opts  */       NODE_CLASS_OPERATOR, NODE_OPTIONS,
889         /* input sock  */       cmp_node_curve_rgb_in,
890         /* output sock */       cmp_node_curve_rgb_out,
891         /* storage     */       "CurveMapping",
892         /* execfunc    */       node_composit_exec_curve_rgb
893         
894 };
895
896 /* **************** VALUE ******************** */
897 static bNodeSocketType cmp_node_value_out[]= {
898         {       SOCK_VALUE, 0, "Value",         0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
899         {       -1, 0, ""       }
900 };
901
902 static void node_composit_exec_value(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
903 {
904         bNodeSocket *sock= node->outputs.first;
905         
906         out[0]->vec[0]= sock->ns.vec[0];
907 }
908
909 static bNodeType cmp_node_value= {
910         /* type code   */       CMP_NODE_VALUE,
911         /* name        */       "Value",
912         /* width+range */       80, 40, 120,
913         /* class+opts  */       NODE_CLASS_GENERATOR, NODE_OPTIONS,
914         /* input sock  */       NULL,
915         /* output sock */       cmp_node_value_out,
916         /* storage     */       "", 
917         /* execfunc    */       node_composit_exec_value
918         
919 };
920
921 /* **************** RGB ******************** */
922 static bNodeSocketType cmp_node_rgb_out[]= {
923         {       SOCK_RGBA, 0, "RGBA",                   0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
924         {       -1, 0, ""       }
925 };
926
927 static void node_composit_exec_rgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
928 {
929         bNodeSocket *sock= node->outputs.first;
930         
931         VECCOPY(out[0]->vec, sock->ns.vec);
932 }
933
934 static bNodeType cmp_node_rgb= {
935         /* type code   */       CMP_NODE_RGB,
936         /* name        */       "RGB",
937         /* width+range */       100, 60, 140,
938         /* class+opts  */       NODE_CLASS_GENERATOR, NODE_OPTIONS,
939         /* input sock  */       NULL,
940         /* output sock */       cmp_node_rgb_out,
941         /* storage     */       "",
942         /* execfunc    */       node_composit_exec_rgb
943         
944 };
945
946 /* **************** MIX RGB ******************** */
947 static bNodeSocketType cmp_node_mix_rgb_in[]= {
948         {       SOCK_VALUE, 1, "Fac",                   0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
949         {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
950         {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
951         {       -1, 0, ""       }
952 };
953 static bNodeSocketType cmp_node_mix_rgb_out[]= {
954         {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
955         {       -1, 0, ""       }
956 };
957
958 static void do_mix_rgb(bNode *node, float *out, float *in1, float *in2, float fac)
959 {
960         float col[3];
961         
962         VECCOPY(col, in1);
963         ramp_blend(node->custom1, col, col+1, col+2, fac, in2);
964         VECCOPY(out, col);
965         out[3]= in1[3];
966 }
967
968 static void node_composit_exec_mix_rgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
969 {
970         /* stack order in: fac, Image, Image */
971         /* stack order out: Image */
972         float fac= in[0]->vec[0];
973         
974         CLAMP(fac, 0.0f, 1.0f);
975         
976         /* input no image? then only color operation */
977         if(in[1]->data==NULL && in[2]->data==NULL) {
978                 do_mix_rgb(node, out[0]->vec, in[1]->vec, in[2]->vec, fac);
979         }
980         else {
981                 /* make output size of first available input image */
982                 CompBuf *cbuf= in[1]->data?in[1]->data:in[2]->data;
983                 CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs
984                 
985                 composit3_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[2]->data, in[2]->vec, in[0]->data, fac, do_mix_rgb);
986                 
987                 out[0]->data= stackbuf;
988         }
989 }
990
991 /* custom1 = mix type */
992 static bNodeType cmp_node_mix_rgb= {
993         /* type code   */       CMP_NODE_MIX_RGB,
994         /* name        */       "Mix",
995         /* width+range */       80, 40, 120,
996         /* class+opts  */       NODE_CLASS_OPERATOR, NODE_OPTIONS,
997         /* input sock  */       cmp_node_mix_rgb_in,
998         /* output sock */       cmp_node_mix_rgb_out,
999         /* storage     */       "", 
1000         /* execfunc    */       node_composit_exec_mix_rgb
1001         
1002 };
1003
1004 /* **************** FILTER  ******************** */
1005 static bNodeSocketType cmp_node_filter_in[]= {
1006         {       SOCK_VALUE, 1, "Fac",                   1.0f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
1007         {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
1008         {       -1, 0, ""       }
1009 };
1010 static bNodeSocketType cmp_node_filter_out[]= {
1011         {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
1012         {       -1, 0, ""       }
1013 };
1014
1015 static void do_filter_edge(CompBuf *out, CompBuf *in, float *filter, float fac)
1016 {
1017         float *row1, *row2, *row3;
1018         float *fp, f1, f2, mfac= 1.0f-fac;
1019         int rowlen, x, y, c;
1020         
1021         rowlen= in->x;
1022         
1023         if(in->type==CB_RGBA) {
1024                 
1025                 for(y=2; y<in->y; y++) {
1026                         /* setup rows */
1027                         row1= in->rect + 4*(y-2)*rowlen;
1028                         row2= row1 + 4*rowlen;
1029                         row3= row2 + 4*rowlen;
1030                         fp= out->rect + 4*(y-1)*rowlen + 4;
1031                         
1032                         for(x=2; x<rowlen; x++) {
1033                                 for(c=0; c<3; c++) {
1034                                         f1= filter[0]*row1[0] + filter[1]*row1[4] + filter[2]*row1[8] + filter[3]*row2[0] + filter[4]*row2[4] + filter[5]*row2[8] + filter[6]*row3[0] + filter[7]*row3[4] + filter[8]*row3[8];
1035                                         f2= filter[0]*row1[0] + filter[3]*row1[4] + filter[6]*row1[8] + filter[1]*row2[0] + filter[4]*row2[4] + filter[7]*row2[8] + filter[2]*row3[0] + filter[5]*row3[4] + filter[8]*row3[8];
1036                                         fp[0]= mfac*row2[4] + fac*sqrt(f1*f1 + f2*f2);
1037                                         fp++; row1++; row2++; row3++;
1038                                 }
1039                                 fp[0]= row2[4];
1040                                 /* no alpha... will clear it completely */
1041                                 fp++; row1++; row2++; row3++;
1042                         }
1043                 }
1044         }       
1045 }
1046
1047 static void do_filter3(CompBuf *out, CompBuf *in, float *filter, float fac)
1048 {
1049         float *row1, *row2, *row3;
1050         float *fp, mfac= 1.0f-fac;
1051         int rowlen, x, y, c;
1052         
1053         rowlen= in->x;
1054         
1055         if(in->type==CB_RGBA) {
1056                 
1057                 for(y=2; y<in->y; y++) {
1058                         /* setup rows */
1059                         row1= in->rect + 4*(y-2)*rowlen;
1060                         row2= row1 + 4*rowlen;
1061                         row3= row2 + 4*rowlen;
1062                         
1063                         fp= out->rect + 4*(y-1)*rowlen;
1064                         QUATCOPY(fp, row2);
1065                         fp+= 4;
1066                         
1067                         for(x=2; x<rowlen; x++) {
1068                                 for(c=0; c<4; c++) {
1069                                         fp[0]= mfac*row2[4] + fac*(filter[0]*row1[0] + filter[1]*row1[4] + filter[2]*row1[8] + filter[3]*row2[0] + filter[4]*row2[4] + filter[5]*row2[8] + filter[6]*row3[0] + filter[7]*row3[4] + filter[8]*row3[8]);
1070                                         fp++; row1++; row2++; row3++;
1071                                 }
1072                         }
1073                 }
1074         }       
1075 }
1076
1077 static void node_composit_exec_filter(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
1078 {
1079         float soft[9]= {1/16.0f, 2/16.0f, 1/16.0f, 2/16.0f, 4/16.0f, 2/16.0f, 1/16.0f, 2/16.0f, 1/16.0f};
1080         float sharp[9]= {-1,-1,-1,-1,9,-1,-1,-1,-1};
1081         float laplace[9]= {1/8.0f, -1/8.0f, 1/8.0f, -1/8.0f, 1.0f, -1/8.0f, 1/8.0f, -1/8.0f, 1/8.0f};
1082         float sobel[9]= {1,2,1,0,0,0,-1,-2,-1};
1083         float prewitt[9]= {1,1,1,0,0,0,-1,-1,-1};
1084         float kirsch[9]= {5,5,5,-3,-3,-3,-2,-2,-2};
1085         float shadow[9]= {1,2,1,0,1,0,-1,-2,-1};
1086         
1087         /* stack order in: Image */
1088         /* stack order out: Image */
1089         
1090         if(in[1]->data) {
1091                 /* make output size of first available input image */
1092                 CompBuf *cbuf= in[1]->data;
1093                 CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs
1094                 
1095                 switch(node->custom1) {
1096                         case CMP_FILT_SOFT:
1097                                 do_filter3(stackbuf, cbuf, soft, in[0]->vec[0]);
1098                                 break;
1099                         case CMP_FILT_SHARP:
1100                                 do_filter3(stackbuf, cbuf, sharp, in[0]->vec[0]);
1101                                 break;
1102                         case CMP_FILT_LAPLACE:
1103                                 do_filter3(stackbuf, cbuf, laplace, in[0]->vec[0]);
1104                                 break;
1105                         case CMP_FILT_SOBEL:
1106                                 do_filter_edge(stackbuf, cbuf, sobel, in[0]->vec[0]);
1107                                 break;
1108                         case CMP_FILT_PREWITT:
1109                                 do_filter_edge(stackbuf, cbuf, prewitt, in[0]->vec[0]);
1110                                 break;
1111                         case CMP_FILT_KIRSCH:
1112                                 do_filter_edge(stackbuf, cbuf, kirsch, in[0]->vec[0]);
1113                                 break;
1114                         case CMP_FILT_SHADOW:
1115                                 do_filter3(stackbuf, cbuf, shadow, in[0]->vec[0]);
1116                                 break;
1117                 }
1118                         
1119                 out[0]->data= stackbuf;
1120         }
1121 }
1122
1123 /* custom1 = filter type */
1124 static bNodeType cmp_node_filter= {
1125         /* type code   */       CMP_NODE_FILTER,
1126         /* name        */       "Filter",
1127         /* width+range */       80, 40, 120,
1128         /* class+opts  */       NODE_CLASS_OPERATOR, NODE_OPTIONS,
1129         /* input sock  */       cmp_node_filter_in,
1130         /* output sock */       cmp_node_filter_out,
1131         /* storage     */       "", 
1132         /* execfunc    */       node_composit_exec_filter
1133         
1134 };
1135
1136
1137 /* **************** VALTORGB ******************** */
1138 static bNodeSocketType cmp_node_valtorgb_in[]= {
1139         {       SOCK_VALUE, 1, "Fac",                   0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
1140         {       -1, 0, ""       }
1141 };
1142 static bNodeSocketType cmp_node_valtorgb_out[]= {
1143         {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
1144         {       SOCK_VALUE, 0, "Alpha",                 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
1145         {       -1, 0, ""       }
1146 };
1147
1148 static void do_colorband_composit(bNode *node, float *out, float *in)
1149 {
1150         do_colorband(node->storage, in[0], out);
1151 }
1152
1153 static void node_composit_exec_valtorgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
1154 {
1155         /* stack order in: fac */
1156         /* stack order out: col, alpha */
1157         
1158         if(node->storage) {
1159                 /* input no image? then only color operation */
1160                 if(in[0]->data==NULL) {
1161                         do_colorband(node->storage, in[0]->vec[0], out[0]->vec);
1162                 }
1163                 else {
1164                         /* make output size of input image */
1165                         CompBuf *cbuf= in[0]->data;
1166                         CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs
1167                         
1168                         composit1_pixel_processor(node, stackbuf, in[0]->data, NULL, do_colorband_composit);
1169                         
1170                         out[0]->data= stackbuf;
1171                         
1172                         if(out[1]->hasoutput)
1173                                 out[1]->data= alphabuf_from_rgbabuf(stackbuf);
1174
1175                 }
1176         }
1177 }
1178
1179 static bNodeType cmp_node_valtorgb= {
1180         /* type code   */       CMP_NODE_VALTORGB,
1181         /* name        */       "ColorRamp",
1182         /* width+range */       240, 200, 300,
1183         /* class+opts  */       NODE_CLASS_OPERATOR, NODE_OPTIONS,
1184         /* input sock  */       cmp_node_valtorgb_in,
1185         /* output sock */       cmp_node_valtorgb_out,
1186         /* storage     */       "ColorBand",
1187         /* execfunc    */       node_composit_exec_valtorgb
1188         
1189 };
1190
1191
1192 /* **************** RGBTOBW ******************** */
1193 static bNodeSocketType cmp_node_rgbtobw_in[]= {
1194         {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
1195         {       -1, 0, ""       }
1196 };
1197 static bNodeSocketType cmp_node_rgbtobw_out[]= {
1198         {       SOCK_VALUE, 0, "Val",                   0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
1199         {       -1, 0, ""       }
1200 };
1201
1202 static void do_rgbtobw(bNode *node, float *out, float *in)
1203 {
1204         out[0]= in[0]*0.35f + in[1]*0.45f + in[2]*0.2f;
1205 }
1206
1207 static void node_composit_exec_rgbtobw(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
1208 {
1209         /* stack order out: bw */
1210         /* stack order in: col */
1211         
1212         /* input no image? then only color operation */
1213         if(in[0]->data==NULL) {
1214                 out[0]->vec[0]= in[0]->vec[0]*0.35f + in[0]->vec[1]*0.45f + in[0]->vec[2]*0.2f;
1215         }
1216         else {
1217                 /* make output size of input image */
1218                 CompBuf *cbuf= in[0]->data;
1219                 CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); // allocs
1220                 
1221                 composit1_pixel_processor(node, stackbuf, in[0]->data, NULL, do_rgbtobw);
1222                 
1223                 out[0]->data= stackbuf;
1224         }
1225 }
1226
1227 static bNodeType cmp_node_rgbtobw= {
1228         /* type code   */       CMP_NODE_RGBTOBW,
1229         /* name        */       "RGB to BW",
1230         /* width+range */       80, 40, 120,
1231         /* class+opts  */       NODE_CLASS_OPERATOR, 0,
1232         /* input sock  */       cmp_node_rgbtobw_in,
1233         /* output sock */       cmp_node_rgbtobw_out,
1234         /* storage     */       "",
1235         /* execfunc    */       node_composit_exec_rgbtobw
1236         
1237 };
1238
1239 /* **************** ALPHAOVER ******************** */
1240 static bNodeSocketType cmp_node_alphaover_in[]= {
1241         {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
1242         {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
1243         {       -1, 0, ""       }
1244 };
1245 static bNodeSocketType cmp_node_alphaover_out[]= {
1246         {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
1247         {       -1, 0, ""       }
1248 };
1249
1250 static void do_alphaover(bNode *node, float *out, float *src, float *dest)
1251 {
1252         float mul= 1.0f - dest[3];
1253         
1254         if(mul<=0.0f) {
1255                 QUATCOPY(out, dest);
1256         }
1257         else {
1258                 out[0]= (mul*src[0]) + dest[0];
1259                 out[1]= (mul*src[1]) + dest[1];
1260                 out[2]= (mul*src[2]) + dest[2];
1261                 out[3]= (mul*src[3]) + dest[3];
1262         }       
1263 }
1264
1265 static void node_composit_exec_alphaover(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
1266 {
1267         /* stack order in: col col */
1268         /* stack order out: col */
1269         
1270         /* input no image? then only color operation */
1271         if(in[0]->data==NULL) {
1272                 do_alphaover(node, out[0]->vec, in[0]->vec, in[1]->vec);
1273         }
1274         else {
1275                 /* make output size of input image */
1276                 CompBuf *cbuf= in[0]->data;
1277                 CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs
1278                 
1279                 composit2_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_alphaover);
1280                 
1281                 out[0]->data= stackbuf;
1282         }
1283 }
1284
1285 static bNodeType cmp_node_alphaover= {
1286         /* type code   */       CMP_NODE_ALPHAOVER,
1287         /* name        */       "AlphaOver",
1288         /* width+range */       80, 40, 120,
1289         /* class+opts  */       NODE_CLASS_OPERATOR, 0,
1290         /* input sock  */       cmp_node_alphaover_in,
1291         /* output sock */       cmp_node_alphaover_out,
1292         /* storage     */       "",
1293         /* execfunc    */       node_composit_exec_alphaover
1294         
1295 };
1296
1297 /* **************** MAP VALUE ******************** */
1298 static bNodeSocketType cmp_node_map_value_in[]= {
1299         {       SOCK_VALUE, 1, "Value",                 1.0f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
1300         {       -1, 0, ""       }
1301 };
1302 static bNodeSocketType cmp_node_map_value_out[]= {
1303         {       SOCK_VALUE, 0, "Value",                 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
1304         {       -1, 0, ""       }
1305 };
1306
1307 static void do_map_value(bNode *node, float *out, float *src)
1308 {
1309         TexMapping *texmap= node->storage;
1310         
1311         out[0]= (src[0] + texmap->loc[0])*texmap->size[0];
1312         if(texmap->flag & TEXMAP_CLIP_MIN)
1313                 if(out[0]<texmap->min[0])
1314                         out[0]= texmap->min[0];
1315         if(texmap->flag & TEXMAP_CLIP_MAX)
1316                 if(out[0]>texmap->max[0])
1317                         out[0]= texmap->max[0];
1318 }
1319
1320 static void node_composit_exec_map_value(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
1321 {
1322         /* stack order in: col col */
1323         /* stack order out: col */
1324         
1325         /* input no image? then only value operation */
1326         if(in[0]->data==NULL) {
1327                 do_map_value(node, out[0]->vec, in[0]->vec);
1328         }
1329         else {
1330                 /* make output size of input image */
1331                 CompBuf *cbuf= in[0]->data;
1332                 CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); // allocs
1333                 
1334                 composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_map_value);
1335                 
1336                 out[0]->data= stackbuf;
1337         }
1338 }
1339
1340 static bNodeType cmp_node_map_value= {
1341         /* type code   */       CMP_NODE_MAP_VALUE,
1342         /* name        */       "Map Value",
1343         /* width+range */       100, 60, 150,
1344         /* class+opts  */       NODE_CLASS_OPERATOR, NODE_OPTIONS,
1345         /* input sock  */       cmp_node_map_value_in,
1346         /* output sock */       cmp_node_map_value_out,
1347         /* storage     */       "TexMapping",
1348         /* execfunc    */       node_composit_exec_map_value
1349         
1350 };
1351
1352 /* **************** GAUSS BLUR ******************** */
1353 static bNodeSocketType cmp_node_blur_in[]= {
1354         {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
1355         {       SOCK_VALUE, 1, "Size",                  1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
1356         {       -1, 0, ""       }
1357 };
1358 static bNodeSocketType cmp_node_blur_out[]= {
1359         {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
1360         {       -1, 0, ""       }
1361 };
1362
1363 static float *make_gausstab(int rad)
1364 {
1365         float *gausstab, sum, val;
1366         int i, n;
1367         
1368         n = 2 * rad + 1;
1369         
1370         gausstab = (float *) MEM_mallocN(n * sizeof(float), "gauss");
1371         
1372         sum = 0.0f;
1373         for (i = -rad; i <= rad; i++) {
1374                 val = exp(-4.0*((float)i*i) / (float) (rad*rad));
1375                 sum += val;
1376                 gausstab[i+rad] = val;
1377         }
1378         
1379         sum= 1.0f/sum;
1380         for(i=0; i<n; i++)
1381                 gausstab[i]*= sum;
1382         
1383         return gausstab;
1384 }
1385
1386 static float *make_bloomtab(int rad)
1387 {
1388         float *bloomtab, val;
1389         int i, n;
1390         
1391         n = 2 * rad + 1;
1392         
1393         bloomtab = (float *) MEM_mallocN(n * sizeof(float), "bloom");
1394         
1395         for (i = -rad; i <= rad; i++) {
1396                 val = pow(1.0 - fabs((float)i)/((float)rad), 4.0);
1397                 bloomtab[i+rad] = val;
1398         }
1399         
1400         return bloomtab;
1401 }
1402
1403 static void blur_single_image(CompBuf *new, CompBuf *img, float blurx, float blury)
1404 {
1405         CompBuf *work;
1406         register float sum, val;
1407         float rval, gval, bval, aval;
1408         float *gausstab, *gausstabcent;
1409         int rad, imgx= img->x, imgy= img->y;
1410         int x, y, pix= img->type;
1411         int i, bigstep;
1412         float *src, *dest;
1413
1414         /* helper image */
1415         work= alloc_compbuf(imgx, imgy, img->type, 1); // allocs
1416         
1417         /* horizontal */
1418         rad = ceil(blurx);
1419         if(rad>imgx/2)
1420                 rad= imgx/2;
1421         else if(rad<1) 
1422                 rad= 1;
1423
1424         gausstab= make_gausstab(rad);
1425         gausstabcent= gausstab+rad;
1426         
1427         for (y = 0; y < imgy; y++) {
1428                 float *srcd= img->rect + pix*(y*img->x);
1429                 
1430                 dest = work->rect + pix*(y * img->x);
1431                 
1432                 for (x = 0; x < imgx ; x++) {
1433                         int minr= x-rad<0?-x:-rad;
1434                         int maxr= x+rad>imgx?imgx-x:rad;
1435                         
1436                         src= srcd + pix*(x+minr);
1437                         
1438                         sum= gval = rval= bval= aval= 0.0f;
1439                         for (i= minr; i < maxr; i++) {
1440                                 val= gausstabcent[i];
1441                                 sum+= val;
1442                                 rval += val * (*src++);
1443                                 if(pix==4) {
1444                                         gval += val * (*src++);
1445                                         bval += val * (*src++);
1446                                         aval += val * (*src++);
1447                                 }
1448                         }
1449                         sum= 1.0f/sum;
1450                         *dest++ = rval*sum;
1451                         if(pix==4) {
1452                                 *dest++ = gval*sum;
1453                                 *dest++ = bval*sum;
1454                                 *dest++ = aval*sum;
1455                         }
1456                 }
1457         }
1458         
1459         /* vertical */
1460         MEM_freeN(gausstab);
1461         
1462         rad = ceil(blury);
1463         if(rad>imgy/2)
1464                 rad= imgy/2;
1465         else if(rad<1) 
1466                 rad= 1;
1467
1468         gausstab= make_gausstab(rad);
1469         gausstabcent= gausstab+rad;
1470         
1471         bigstep = pix*imgx;
1472         for (x = 0; x < imgx; x++) {
1473                 float *srcd= work->rect + pix*x;
1474                 
1475                 dest = new->rect + pix*x;
1476                 
1477                 for (y = 0; y < imgy ; y++) {
1478                         int minr= y-rad<0?-y:-rad;
1479                         int maxr= y+rad>imgy?imgy-y:rad;
1480                         
1481                         src= srcd + bigstep*(y+minr);
1482                         
1483                         sum= gval = rval= bval= aval= 0.0f;
1484                         for (i= minr; i < maxr; i++) {
1485                                 val= gausstabcent[i];
1486                                 sum+= val;
1487                                 rval += val * src[0];
1488                                 if(pix==4) {
1489                                         gval += val * src[1];
1490                                         bval += val * src[2];
1491                                         aval += val * src[3];
1492                                 }
1493                                 src += bigstep;
1494                         }
1495                         sum= 1.0f/sum;
1496                         dest[0] = rval*sum;
1497                         if(pix==4) {
1498                                 dest[1] = gval*sum;
1499                                 dest[2] = bval*sum;
1500                                 dest[3] = aval*sum;
1501                         }
1502                         dest+= bigstep;
1503                 }
1504         }
1505         
1506         free_compbuf(work);
1507         MEM_freeN(gausstab);
1508 }
1509
1510 /* reference has to be mapped 0-1, and equal in size */
1511 static void bloom_with_reference(CompBuf *new, CompBuf *img, CompBuf *ref, float blurx, float blury)
1512 {
1513         CompBuf *wbuf;
1514         register float val;
1515         float radxf, radyf;
1516         float **maintabs;
1517         float *gausstabx, *gausstabcenty;
1518         float *gausstaby, *gausstabcentx;
1519         int radx, rady, imgx= img->x, imgy= img->y;
1520         int x, y;
1521         int i, j;
1522         float *src, *dest, *wb;
1523         
1524         wbuf= alloc_compbuf(imgx, imgy, CB_VAL, 1);
1525         memset(wbuf->rect, sizeof(float)*imgx*imgy, 0);
1526         
1527         /* horizontal */
1528         radx = ceil(blurx);
1529         if(radx>imgx/2)
1530                 radx= imgx/2;
1531         else if(radx<1) 
1532                 radx= 1;
1533         
1534         /* vertical */
1535         rady = ceil(blury);
1536         if(rady>imgy/2)
1537                 rady= imgy/2;
1538         else if(rady<1) 
1539                 rady= 1;
1540         
1541         x= MAX2(radx, rady);
1542         maintabs= MEM_mallocN(x*sizeof(void *), "gauss array");
1543         for(i= 0; i<x; i++)
1544                 maintabs[i]= make_bloomtab(i+1);
1545                 
1546         /* vars to store before we go */
1547 //      refd= ref->rect;
1548         src= img->rect;
1549         
1550         memset(new->rect, 4*imgx*imgy, 0);
1551         
1552         radxf= (float)radx;
1553         radyf= (float)rady;
1554         
1555         for (y = 0; y < imgy; y++) {
1556                 for (x = 0; x < imgx ; x++, src+=4) {//, refd++) {
1557                         
1558 //                      int refradx= (int)(refd[0]*radxf);
1559 //                      int refrady= (int)(refd[0]*radyf);
1560                         
1561                         int refradx= (int)(radxf*0.3f*src[3]*(src[0]+src[1]+src[2]));
1562                         int refrady= (int)(radyf*0.3f*src[3]*(src[0]+src[1]+src[2]));
1563                         
1564                         if(refradx>radx) refradx= radx;
1565                         else if(refradx<1) refradx= 1;
1566                         if(refrady>rady) refrady= rady;
1567                         else if(refrady<1) refrady= 1;
1568                         
1569                         if(refradx==1 && refrady==1) {
1570                                 wb= wbuf->rect + ( y*imgx + x);
1571                                 dest= new->rect + 4*( y*imgx + x);
1572                                 wb[0]+= 1.0f;
1573                                 dest[0] += src[0];
1574                                 dest[1] += src[1];
1575                                 dest[2] += src[2];
1576                                 dest[3] += src[3];
1577                         }
1578                         else {
1579                                 int minxr= x-refradx<0?-x:-refradx;
1580                                 int maxxr= x+refradx>imgx?imgx-x:refradx;
1581                                 int minyr= y-refrady<0?-y:-refrady;
1582                                 int maxyr= y+refrady>imgy?imgy-y:refrady;
1583                                 
1584                                 float *destd= new->rect + 4*( (y + minyr)*imgx + x + minxr);
1585                                 float *wbufd= wbuf->rect + ( (y + minyr)*imgx + x + minxr);
1586                                 
1587                                 gausstabx= maintabs[refradx-1];
1588                                 gausstabcentx= gausstabx+refradx;
1589                                 gausstaby= maintabs[refrady-1];
1590                                 gausstabcenty= gausstaby+refrady;
1591                                 
1592                                 for (i= minyr; i < maxyr; i++, destd+= 4*imgx, wbufd+= imgx) {
1593                                         dest= destd;
1594                                         wb= wbufd;
1595                                         for (j= minxr; j < maxxr; j++, dest+=4, wb++) {
1596                                                 
1597                                                 val= gausstabcenty[i]*gausstabcentx[j];
1598                                                 wb[0]+= val;
1599                                                 dest[0] += val * src[0];
1600                                                 dest[1] += val * src[1];
1601                                                 dest[2] += val * src[2];
1602                                                 dest[3] += val * src[3];
1603                                         }
1604                                 }
1605                         }
1606                 }
1607         }
1608         
1609         x= imgx*imgy;
1610         dest= new->rect;
1611         wb= wbuf->rect;
1612         while(x--) {
1613                 val= 1.0f/wb[0];
1614                 dest[0]*= val;
1615                 dest[1]*= val;
1616                 dest[2]*= val;
1617                 dest[3]*= val;
1618                 wb++;
1619                 dest+= 4;
1620         }
1621         
1622         free_compbuf(wbuf);
1623         
1624         x= MAX2(radx, rady);
1625         for(i= 0; i<x; i++)
1626                 MEM_freeN(maintabs[i]);
1627         MEM_freeN(maintabs);
1628         
1629 }
1630
1631 /* reference has to be mapped 0-1, and equal in size */
1632 static void blur_with_reference(CompBuf *new, CompBuf *img, CompBuf *ref, float blurx, float blury)
1633 {
1634         CompBuf *blurbuf;
1635         register float sum, val;
1636         float rval, gval, bval, aval, radxf, radyf;
1637         float **maintabs;
1638         float *gausstabx, *gausstabcenty;
1639         float *gausstaby, *gausstabcentx;
1640         int radx, rady, imgx= img->x, imgy= img->y;
1641         int x, y;
1642         int i, j;
1643         float *src, *dest, *refd, *blurd;
1644
1645         /* trick is; we blur the reference image... but only works with clipped values*/
1646         blurbuf= alloc_compbuf(imgx, imgy, CB_VAL, 1);
1647         blurd= blurbuf->rect;
1648         refd= ref->rect;
1649         for(x= imgx*imgy; x>0; x--, refd++, blurd++) {
1650                 if(refd[0]<0.0f) blurd[0]= 0.0f;
1651                 else if(refd[0]>1.0f) blurd[0]= 1.0f;
1652                 else blurd[0]= refd[0];
1653         }
1654         
1655         blur_single_image(blurbuf, blurbuf, blurx, blury);
1656         
1657         /* horizontal */
1658         radx = ceil(blurx);
1659         if(radx>imgx/2)
1660                 radx= imgx/2;
1661         else if(radx<1) 
1662                 radx= 1;
1663         
1664         /* vertical */
1665         rady = ceil(blury);
1666         if(rady>imgy/2)
1667                 rady= imgy/2;
1668         else if(rady<1) 
1669                 rady= 1;
1670         
1671         x= MAX2(radx, rady);
1672         maintabs= MEM_mallocN(x*sizeof(void *), "gauss array");
1673         for(i= 0; i<x; i++)
1674                 maintabs[i]= make_gausstab(i+1);
1675         
1676         refd= blurbuf->rect;
1677         dest= new->rect;
1678         radxf= (float)radx;
1679         radyf= (float)rady;
1680         
1681         for (y = 0; y < imgy; y++) {
1682                 for (x = 0; x < imgx ; x++, dest+=4, refd++) {
1683                         int refradx= (int)(refd[0]*radxf);
1684                         int refrady= (int)(refd[0]*radyf);
1685                         
1686                         if(refradx>radx) refradx= radx;
1687                         else if(refradx<1) refradx= 1;
1688                         if(refrady>rady) refrady= rady;
1689                         else if(refrady<1) refrady= 1;
1690
1691                         if(refradx==1 && refrady==1) {
1692                                 src= img->rect + 4*( y*imgx + x);
1693                                 QUATCOPY(dest, src);
1694                         }
1695                         else {
1696                                 int minxr= x-refradx<0?-x:-refradx;
1697                                 int maxxr= x+refradx>imgx?imgx-x:refradx;
1698                                 int minyr= y-refrady<0?-y:-refrady;
1699                                 int maxyr= y+refrady>imgy?imgy-y:refrady;
1700         
1701                                 float *srcd= img->rect + 4*( (y + minyr)*imgx + x + minxr);
1702                                 
1703                                 gausstabx= maintabs[refradx-1];
1704                                 gausstabcentx= gausstabx+refradx;
1705                                 gausstaby= maintabs[refrady-1];
1706                                 gausstabcenty= gausstaby+refrady;
1707
1708                                 sum= gval = rval= bval= aval= 0.0f;
1709                                 
1710                                 for (i= minyr; i < maxyr; i++, srcd+= 4*imgx) {
1711                                         src= srcd;
1712                                         for (j= minxr; j < maxxr; j++, src+=4) {
1713                                         
1714                                                 val= gausstabcenty[i]*gausstabcentx[j];
1715                                                 sum+= val;
1716                                                 rval += val * src[0];
1717                                                 gval += val * src[1];
1718                                                 bval += val * src[2];
1719                                                 aval += val * src[3];
1720                                         }
1721                                 }
1722                                 sum= 1.0f/sum;
1723                                 dest[0] = rval*sum;
1724                                 dest[1] = gval*sum;
1725                                 dest[2] = bval*sum;
1726                                 dest[3] = aval*sum;
1727                         }
1728                 }
1729         }
1730         
1731         free_compbuf(blurbuf);
1732         
1733         x= MAX2(radx, rady);
1734         for(i= 0; i<x; i++)
1735                 MEM_freeN(maintabs[i]);
1736         MEM_freeN(maintabs);
1737         
1738 }
1739
1740
1741
1742 static void node_composit_exec_blur(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
1743 {
1744         CompBuf *new, *img= in[0]->data;
1745         
1746         if(img==NULL || out[0]->hasoutput==0)
1747                 return;
1748         
1749         /* if fac input, we do it different */
1750         if(in[1]->data) {
1751                 
1752                 /* test fitness if reference */
1753                 
1754                 /* make output size of input image */
1755                 new= alloc_compbuf(img->x, img->y, CB_RGBA, 1); // allocs
1756                 
1757                 blur_with_reference(new, img, in[1]->data, (float)node->custom1, (float)node->custom2);
1758                 
1759                 out[0]->data= new;
1760         }
1761         else {
1762                 if(in[1]->vec[0]==0.0f) {
1763                         /* pass on image */
1764                         new= alloc_compbuf(img->x, img->y, img->type, 0);
1765                         new->rect= img->rect;
1766                 }
1767                 else {
1768                         /* make output size of input image */
1769                         new= alloc_compbuf(img->x, img->y, img->type, 1); // allocs
1770                         if(1)
1771                                 blur_single_image(new, img, in[1]->vec[0]*(float)node->custom1, in[1]->vec[0]*(float)node->custom2);
1772                         else    /* bloom experimental... */
1773                                 bloom_with_reference(new, img, NULL, in[1]->vec[0]*(float)node->custom1, in[1]->vec[0]*(float)node->custom2);
1774                 }
1775                 out[0]->data= new;
1776         }
1777 }
1778         
1779
1780 /* custom1 custom2 = blur filter size */
1781 static bNodeType cmp_node_blur= {
1782         /* type code   */       CMP_NODE_BLUR,
1783         /* name        */       "Blur",
1784         /* width+range */       120, 80, 200,
1785         /* class+opts  */       NODE_CLASS_OPERATOR, NODE_OPTIONS,
1786         /* input sock  */       cmp_node_blur_in,
1787         /* output sock */       cmp_node_blur_out,
1788         /* storage     */       "",
1789         /* execfunc    */       node_composit_exec_blur
1790         
1791 };
1792
1793
1794 /* ****************** types array for all shaders ****************** */
1795
1796 bNodeType *node_all_composit[]= {
1797         &node_group_typeinfo,
1798         &cmp_node_viewer,
1799         &cmp_node_composite,
1800         &cmp_node_output_file,
1801         &cmp_node_value,
1802         &cmp_node_rgb,
1803         &cmp_node_mix_rgb,
1804         &cmp_node_filter,
1805         &cmp_node_valtorgb,
1806         &cmp_node_rgbtobw,
1807         &cmp_node_normal,
1808         &cmp_node_curve_vec,
1809         &cmp_node_curve_rgb,
1810         &cmp_node_image,
1811         &cmp_node_rresult,
1812         &cmp_node_alphaover,
1813         &cmp_node_blur,
1814         &cmp_node_map_value,
1815         NULL
1816 };
1817
1818 /* ******************* execute and parse ************ */
1819
1820 /* helper call to detect if theres a render-result node */
1821 int ntreeCompositNeedsRender(bNodeTree *ntree)
1822 {
1823         bNode *node;
1824         
1825         if(ntree==NULL) return 1;
1826         
1827         for(node= ntree->nodes.first; node; node= node->next) {
1828                 if(node->type==CMP_NODE_R_RESULT)
1829                         return 1;
1830         }
1831         return 0;
1832 }
1833
1834 /* note; if called without preview, and previews exist, they get updated */
1835 /* render calls it without previews, works nicer for bg render */
1836 void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview)
1837 {
1838         if(ntree==NULL) return;
1839         
1840         if(do_preview)
1841                 ntreeInitPreview(ntree, 0, 0);
1842         
1843         ntreeBeginExecTree(ntree);
1844
1845         /* allocate composit data? */
1846         
1847         ntreeExecTree(ntree, rd, 0);    /* threads */
1848         
1849         ntreeEndExecTree(ntree);
1850         
1851         free_unused_animimages();
1852 }
1853