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