c21c2633698eb71248dad3e2dc087007eb6971d6
[blender.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 "MEM_guardedalloc.h"
35
36 #include "DNA_camera_types.h" /* qdn: defocus node, need camera info */
37 #include "DNA_ID.h"
38 #include "DNA_image_types.h"
39 #include "DNA_node_types.h"
40 #include "DNA_object_types.h"
41 #include "DNA_material_types.h"
42 #include "DNA_scene_types.h"
43 #include "DNA_texture_types.h"
44 #include "DNA_vec_types.h"
45
46 #include "BKE_blender.h"
47 #include "BKE_colortools.h"
48 #include "BKE_global.h"
49 #include "BKE_image.h"
50 #include "BKE_node.h"
51 #include "BKE_material.h"
52 #include "BKE_texture.h"
53 #include "BKE_utildefines.h"
54
55 #include "BLI_arithb.h"
56 #include "BLI_blenlib.h"
57 #include "BLI_rand.h"
58 #include "BLI_threads.h"
59
60 #include "IMB_imbuf_types.h"
61 #include "IMB_imbuf.h"
62
63 #include "RE_pipeline.h"
64 #include "RE_shader_ext.h"              /* <- TexResult */
65 #include "RE_render_ext.h"              /* <- ibuf_sample() */
66
67 #ifndef atanf
68         #define atanf(a)        atan((double)(a))
69 #endif
70
71
72 /* *************************** operations support *************************** */
73
74 /* general signal that's in output sockets, and goes over the wires */
75 typedef struct CompBuf {
76         float *rect;
77         int x, y, xrad, yrad;
78         short type, malloc;
79         rcti disprect;          /* cropped part of image */
80         int xof, yof;           /* relative to center of target image */
81         
82         void (*rect_procedural)(struct CompBuf *, float *, float, float);
83         bNode *node;            /* only in use for procedural bufs */
84         
85         struct CompBuf *next, *prev;    /* for pass-on, works nicer than reference counting */
86 } CompBuf;
87
88 /* defines also used for pixel size */
89 #define CB_RGBA         4
90 #define CB_VEC4         4
91 #define CB_VEC3         3
92 #define CB_VEC2         2
93 #define CB_VAL          1
94
95 /* defines for RGBA channels */
96 #define CHAN_R  0
97 #define CHAN_G  1
98 #define CHAN_B  2
99 #define CHAN_A  3
100
101 static CompBuf *alloc_compbuf(int sizex, int sizey, int type, int alloc)
102 {
103         CompBuf *cbuf= MEM_callocN(sizeof(CompBuf), "compbuf");
104         
105         cbuf->x= sizex;
106         cbuf->y= sizey;
107         cbuf->xrad= sizex/2;
108         cbuf->yrad= sizey/2;
109         
110         cbuf->type= type;
111         if(alloc) {
112                 if(cbuf->type==CB_RGBA)
113                         cbuf->rect= MEM_mapallocN(4*sizeof(float)*sizex*sizey, "compbuf RGBA rect");
114                 else if(cbuf->type==CB_VEC3)
115                         cbuf->rect= MEM_mapallocN(3*sizeof(float)*sizex*sizey, "compbuf Vector3 rect");
116                 else if(cbuf->type==CB_VEC2)
117                         cbuf->rect= MEM_mapallocN(2*sizeof(float)*sizex*sizey, "compbuf Vector2 rect");
118                 else
119                         cbuf->rect= MEM_mapallocN(sizeof(float)*sizex*sizey, "compbuf Fac rect");
120                 cbuf->malloc= 1;
121         }
122         cbuf->disprect.xmin= 0;
123         cbuf->disprect.ymin= 0;
124         cbuf->disprect.xmax= sizex;
125         cbuf->disprect.ymax= sizey;
126         
127         return cbuf;
128 }
129
130 static CompBuf *dupalloc_compbuf(CompBuf *cbuf)
131 {
132         CompBuf *dupbuf= alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 1);
133         if(dupbuf) {
134                 memcpy(dupbuf->rect, cbuf->rect, cbuf->type*sizeof(float)*cbuf->x*cbuf->y);
135         
136                 dupbuf->xof= cbuf->xof;
137                 dupbuf->yof= cbuf->yof;
138         }       
139         return dupbuf;
140 }
141
142 /* instead of reference counting, we create a list */
143 static CompBuf *pass_on_compbuf(CompBuf *cbuf)
144 {
145         CompBuf *dupbuf= alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 0);
146         CompBuf *lastbuf;
147         
148         if(dupbuf) {
149                 dupbuf->rect= cbuf->rect;
150                 dupbuf->xof= cbuf->xof;
151                 dupbuf->yof= cbuf->yof;
152                 dupbuf->malloc= 0;
153                 
154                 /* get last buffer in list, and append dupbuf */
155                 for(lastbuf= dupbuf; lastbuf; lastbuf= lastbuf->next)
156                         if(lastbuf->next==NULL)
157                                 break;
158                 lastbuf->next= dupbuf;
159                 dupbuf->prev= lastbuf;
160         }       
161         return dupbuf;
162 }
163
164
165 void free_compbuf(CompBuf *cbuf)
166 {
167         /* check referencing, then remove from list and set malloc tag */
168         if(cbuf->prev || cbuf->next) {
169                 if(cbuf->prev)
170                         cbuf->prev->next= cbuf->next;
171                 if(cbuf->next)
172                         cbuf->next->prev= cbuf->prev;
173                 if(cbuf->malloc) {
174                         if(cbuf->prev)
175                                 cbuf->prev->malloc= 1;
176                         else
177                                 cbuf->next->malloc= 1;
178                         cbuf->malloc= 0;
179                 }
180         }
181         
182         if(cbuf->malloc && cbuf->rect)
183                 MEM_freeN(cbuf->rect);
184
185         MEM_freeN(cbuf);
186 }
187
188 void print_compbuf(char *str, CompBuf *cbuf)
189 {
190         printf("Compbuf %s %d %d %p\n", str, cbuf->x, cbuf->y, cbuf->rect);
191         
192 }
193
194 static CompBuf *get_cropped_compbuf(rcti *drect, float *rectf, int rectx, int recty, int type)
195 {
196         CompBuf *cbuf;
197         rcti disprect= *drect;
198         float *outfp;
199         int dx, y;
200         
201         if(disprect.xmax>rectx) disprect.xmax= rectx;
202         if(disprect.ymax>recty) disprect.ymax= recty;
203         if(disprect.xmin>= disprect.xmax) return NULL;
204         if(disprect.ymin>= disprect.ymax) return NULL;
205         
206         cbuf= alloc_compbuf(disprect.xmax-disprect.xmin, disprect.ymax-disprect.ymin, type, 1);
207         outfp= cbuf->rect;
208         rectf += type*(disprect.ymin*rectx + disprect.xmin);
209         dx= type*cbuf->x;
210         for(y=cbuf->y; y>0; y--, outfp+=dx, rectf+=type*rectx)
211                 memcpy(outfp, rectf, sizeof(float)*dx);
212         
213         return cbuf;
214 }
215
216 static CompBuf *scalefast_compbuf(CompBuf *inbuf, int newx, int newy)
217 {
218         CompBuf *outbuf; 
219         float *rectf, *newrectf, *rf;
220         int x, y, c, pixsize= inbuf->type;
221         int ofsx, ofsy, stepx, stepy;
222         
223         if(inbuf->x==newx && inbuf->y==newy)
224                 return dupalloc_compbuf(inbuf);
225         
226         outbuf= alloc_compbuf(newx, newy, inbuf->type, 1);
227         newrectf= outbuf->rect;
228         
229         stepx = (65536.0 * (inbuf->x - 1.0) / (newx - 1.0)) + 0.5;
230         stepy = (65536.0 * (inbuf->y - 1.0) / (newy - 1.0)) + 0.5;
231         ofsy = 32768;
232         
233         for (y = newy; y > 0 ; y--){
234                 rectf = inbuf->rect;
235                 rectf += pixsize * (ofsy >> 16) * inbuf->x;
236
237                 ofsy += stepy;
238                 ofsx = 32768;
239                 
240                 for (x = newx ; x>0 ; x--) {
241                         
242                         rf= rectf + pixsize*(ofsx >> 16);
243                         for(c=0; c<pixsize; c++)
244                                 newrectf[c] = rf[c];
245                         
246                         newrectf+= pixsize;
247                         
248                         ofsx += stepx;
249                 }
250         }
251         
252         return outbuf;
253 }
254
255 static CompBuf *typecheck_compbuf(CompBuf *inbuf, int type)
256 {
257         if(inbuf && inbuf->type!=type && inbuf->rect_procedural==NULL) {
258                 CompBuf *outbuf= alloc_compbuf(inbuf->x, inbuf->y, type, 1); 
259                 float *inrf= inbuf->rect;
260                 float *outrf= outbuf->rect;
261                 int x= inbuf->x*inbuf->y;
262                 
263                 /* warning note: xof and yof are applied in pixelprocessor, but should be copied otherwise? */
264                 outbuf->xof= inbuf->xof;
265                 outbuf->yof= inbuf->yof;
266                 
267                 if(type==CB_VAL) {
268                         if(inbuf->type==CB_VEC2) {
269                                 for(; x>0; x--, outrf+= 1, inrf+= 2)
270                                         *outrf= 0.5f*(inrf[0]+inrf[1]);
271                         }
272                         else if(inbuf->type==CB_VEC3) {
273                                 for(; x>0; x--, outrf+= 1, inrf+= 3)
274                                         *outrf= 0.333333f*(inrf[0]+inrf[1]+inrf[2]);
275                         }
276                         else if(inbuf->type==CB_RGBA) {
277                                 for(; x>0; x--, outrf+= 1, inrf+= 4)
278                                         *outrf= inrf[0]*0.35f + inrf[1]*0.45f + inrf[2]*0.2f;
279                         }
280                 }
281                 else if(type==CB_VEC2) {
282                         if(inbuf->type==CB_VAL) {
283                                 for(; x>0; x--, outrf+= 2, inrf+= 1) {
284                                         outrf[0]= inrf[0];
285                                         outrf[1]= inrf[0];
286                                 }
287                         }
288                         else if(inbuf->type==CB_VEC3) {
289                                 for(; x>0; x--, outrf+= 2, inrf+= 3) {
290                                         outrf[0]= inrf[0];
291                                         outrf[1]= inrf[1];
292                                 }
293                         }
294                         else if(inbuf->type==CB_RGBA) {
295                                 for(; x>0; x--, outrf+= 2, inrf+= 4) {
296                                         outrf[0]= inrf[0];
297                                         outrf[1]= inrf[1];
298                                 }
299                         }
300                 }
301                 else if(type==CB_VEC3) {
302                         if(inbuf->type==CB_VAL) {
303                                 for(; x>0; x--, outrf+= 3, inrf+= 1) {
304                                         outrf[0]= inrf[0];
305                                         outrf[1]= inrf[0];
306                                         outrf[2]= inrf[0];
307                                 }
308                         }
309                         else if(inbuf->type==CB_VEC2) {
310                                 for(; x>0; x--, outrf+= 3, inrf+= 2) {
311                                         outrf[0]= inrf[0];
312                                         outrf[1]= inrf[1];
313                                         outrf[2]= 0.0f;
314                                 }
315                         }
316                         else if(inbuf->type==CB_RGBA) {
317                                 for(; x>0; x--, outrf+= 3, inrf+= 4) {
318                                         outrf[0]= inrf[0];
319                                         outrf[1]= inrf[1];
320                                         outrf[2]= inrf[2];
321                                 }
322                         }
323                 }
324                 else if(type==CB_RGBA) {
325                         if(inbuf->type==CB_VAL) {
326                                 for(; x>0; x--, outrf+= 4, inrf+= 1) {
327                                         outrf[0]= inrf[0];
328                                         outrf[1]= inrf[0];
329                                         outrf[2]= inrf[0];
330                                         outrf[3]= inrf[0];
331                                 }
332                         }
333                         else if(inbuf->type==CB_VEC2) {
334                                 for(; x>0; x--, outrf+= 4, inrf+= 2) {
335                                         outrf[0]= inrf[0];
336                                         outrf[1]= inrf[1];
337                                         outrf[2]= 0.0f;
338                                         outrf[3]= 1.0f;
339                                 }
340                         }
341                         else if(inbuf->type==CB_VEC3) {
342                                 for(; x>0; x--, outrf+= 4, inrf+= 3) {
343                                         outrf[0]= inrf[0];
344                                         outrf[1]= inrf[1];
345                                         outrf[2]= inrf[2];
346                                         outrf[3]= 1.0f;
347                                 }
348                         }
349                 }
350                 
351                 return outbuf;
352         }
353         return inbuf;
354 }
355
356 float *compbuf_get_pixel(CompBuf *cbuf, float *rectf, int x, int y, int xrad, int yrad)
357 {
358         if(cbuf) {
359                 if(cbuf->rect_procedural) {
360                         cbuf->rect_procedural(cbuf, rectf, (float)x/(float)xrad, (float)y/(float)yrad);
361                         return rectf;
362                 }
363                 else {
364                         static float col[4]= {0.0f, 0.0f, 0.0f, 0.0f};
365                         
366                         /* map coords */
367                         x-= cbuf->xof;
368                         y-= cbuf->yof;
369                         
370                         if(y<-cbuf->yrad || y>= -cbuf->yrad+cbuf->y) return col;
371                         if(x<-cbuf->xrad || x>= -cbuf->xrad+cbuf->x) return col;
372                         
373                         return cbuf->rect + cbuf->type*( (cbuf->yrad+y)*cbuf->x + (cbuf->xrad+x) );
374                 }
375         }
376         else return rectf;
377 }
378
379 /* **************************************************** */
380
381 /* Pixel-to-Pixel operation, 1 Image in, 1 out */
382 static void composit1_pixel_processor(bNode *node, CompBuf *out, CompBuf *src_buf, float *src_col,
383                                                                           void (*func)(bNode *, float *, float *), 
384                                                                           int src_type)
385 {
386         CompBuf *src_use;
387         float *outfp=out->rect, *srcfp;
388         int xrad, yrad, x, y;
389         
390         src_use= typecheck_compbuf(src_buf, src_type);
391         
392         xrad= out->xrad;
393         yrad= out->yrad;
394         
395         for(y= -yrad; y<-yrad+out->y; y++) {
396                 for(x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) {
397                         srcfp= compbuf_get_pixel(src_use, src_col, x, y, xrad, yrad);
398                         func(node, outfp, srcfp);
399                 }
400         }
401         
402         if(src_use!=src_buf)
403                 free_compbuf(src_use);
404 }
405
406 /* Pixel-to-Pixel operation, 2 Images in, 1 out */
407 static void composit2_pixel_processor(bNode *node, CompBuf *out, CompBuf *src_buf, float *src_col,
408                                                                           CompBuf *fac_buf, float *fac, void (*func)(bNode *, float *, float *, float *), 
409                                                                           int src_type, int fac_type)
410 {
411         CompBuf *src_use, *fac_use;
412         float *outfp=out->rect, *srcfp, *facfp;
413         int xrad, yrad, x, y;
414         
415         src_use= typecheck_compbuf(src_buf, src_type);
416         fac_use= typecheck_compbuf(fac_buf, fac_type);
417
418         xrad= out->xrad;
419         yrad= out->yrad;
420         
421         for(y= -yrad; y<-yrad+out->y; y++) {
422                 for(x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) {
423                         srcfp= compbuf_get_pixel(src_use, src_col, x, y, xrad, yrad);
424                         facfp= compbuf_get_pixel(fac_use, fac, x, y, xrad, yrad);
425                         
426                         func(node, outfp, srcfp, facfp);
427                 }
428         }
429         if(src_use!=src_buf)
430                 free_compbuf(src_use);
431         if(fac_use!=fac_buf)
432                 free_compbuf(fac_use);
433 }
434
435 /* Pixel-to-Pixel operation, 3 Images in, 1 out */
436 static void composit3_pixel_processor(bNode *node, CompBuf *out, CompBuf *src1_buf, float *src1_col, CompBuf *src2_buf, float *src2_col, 
437                                                                           CompBuf *fac_buf, float *fac, void (*func)(bNode *, float *, float *, float *, float *), 
438                                                                           int src1_type, int src2_type, int fac_type)
439 {
440         CompBuf *src1_use, *src2_use, *fac_use;
441         float *outfp=out->rect, *src1fp, *src2fp, *facfp;
442         int xrad, yrad, x, y;
443         
444         src1_use= typecheck_compbuf(src1_buf, src1_type);
445         src2_use= typecheck_compbuf(src2_buf, src2_type);
446         fac_use= typecheck_compbuf(fac_buf, fac_type);
447         
448         xrad= out->xrad;
449         yrad= out->yrad;
450         
451         for(y= -yrad; y<-yrad+out->y; y++) {
452                 for(x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) {
453                         src1fp= compbuf_get_pixel(src1_use, src1_col, x, y, xrad, yrad);
454                         src2fp= compbuf_get_pixel(src2_use, src2_col, x, y, xrad, yrad);
455                         facfp= compbuf_get_pixel(fac_use, fac, x, y, xrad, yrad);
456                         
457                         func(node, outfp, src1fp, src2fp, facfp);
458                 }
459         }
460         
461         if(src1_use!=src1_buf)
462                 free_compbuf(src1_use);
463         if(src2_use!=src2_buf)
464                 free_compbuf(src2_use);
465         if(fac_use!=fac_buf)
466                 free_compbuf(fac_use);
467 }
468
469 /* Pixel-to-Pixel operation, 4 Images in, 1 out */
470 static void composit4_pixel_processor(bNode *node, CompBuf *out, CompBuf *src1_buf, float *src1_col, CompBuf *fac1_buf, float *fac1, 
471                                                                           CompBuf *src2_buf, float *src2_col, CompBuf *fac2_buf, float *fac2, 
472                                                                           void (*func)(bNode *, float *, float *, float *, float *, float *), 
473                                                                           int src1_type, int fac1_type, int src2_type, int fac2_type)
474 {
475         CompBuf *src1_use, *src2_use, *fac1_use, *fac2_use;
476         float *outfp=out->rect, *src1fp, *src2fp, *fac1fp, *fac2fp;
477         int xrad, yrad, x, y;
478         
479         src1_use= typecheck_compbuf(src1_buf, src1_type);
480         src2_use= typecheck_compbuf(src2_buf, src2_type);
481         fac1_use= typecheck_compbuf(fac1_buf, fac1_type);
482         fac2_use= typecheck_compbuf(fac2_buf, fac2_type);
483         
484         xrad= out->xrad;
485         yrad= out->yrad;
486         
487         for(y= -yrad; y<-yrad+out->y; y++) {
488                 for(x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) {
489                         src1fp= compbuf_get_pixel(src1_use, src1_col, x, y, xrad, yrad);
490                         src2fp= compbuf_get_pixel(src2_use, src2_col, x, y, xrad, yrad);
491                         fac1fp= compbuf_get_pixel(fac1_use, fac1, x, y, xrad, yrad);
492                         fac2fp= compbuf_get_pixel(fac2_use, fac2, x, y, xrad, yrad);
493                         
494                         func(node, outfp, src1fp, fac1fp, src2fp, fac2fp);
495                 }
496         }
497         
498         if(src1_use!=src1_buf)
499                 free_compbuf(src1_use);
500         if(src2_use!=src2_buf)
501                 free_compbuf(src2_use);
502         if(fac1_use!=fac1_buf)
503                 free_compbuf(fac1_use);
504         if(fac2_use!=fac2_buf)
505                 free_compbuf(fac2_use);
506 }
507
508
509 static CompBuf *valbuf_from_rgbabuf(CompBuf *cbuf, int channel)
510 {
511         CompBuf *valbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1);
512         float *valf, *rectf;
513         int tot;
514         
515         /* warning note: xof and yof are applied in pixelprocessor, but should be copied otherwise? */
516         valbuf->xof= cbuf->xof;
517         valbuf->yof= cbuf->yof;
518         
519         valf= valbuf->rect;
520         
521         /* defaults to returning alpha channel */
522         if ((channel < CHAN_R) && (channel > CHAN_A)) channel = CHAN_A;
523
524         rectf= cbuf->rect + channel;
525         
526         for(tot= cbuf->x*cbuf->y; tot>0; tot--, valf++, rectf+=4)
527                 *valf= *rectf;
528         
529         return valbuf;
530 }
531
532 static void generate_preview(bNode *node, CompBuf *stackbuf)
533 {
534         bNodePreview *preview= node->preview;
535         
536         if(preview && stackbuf) {
537                 CompBuf *cbuf, *stackbuf_use;
538                 
539                 if(stackbuf->rect==NULL) return;
540                 
541                 stackbuf_use= typecheck_compbuf(stackbuf, CB_RGBA);
542                 
543                 if(stackbuf->x > stackbuf->y) {
544                         preview->xsize= 140;
545                         preview->ysize= (140*stackbuf->y)/stackbuf->x;
546                 }
547                 else {
548                         preview->ysize= 140;
549                         preview->xsize= (140*stackbuf->x)/stackbuf->y;
550                 }
551                 
552                 cbuf= scalefast_compbuf(stackbuf_use, preview->xsize, preview->ysize);
553                 
554                 /* this ensures free-compbuf does the right stuff */
555                 SWAP(float *, cbuf->rect, node->preview->rect);
556                 
557                 free_compbuf(cbuf);
558                 if(stackbuf_use!=stackbuf)
559                         free_compbuf(stackbuf_use);
560
561         }
562 }
563
564 /* ******************************************************** */
565 /* ********* Composit Node type definitions ***************** */
566 /* ******************************************************** */
567
568 /* SocketType syntax: 
569    socket type, max connections (0 is no limit), name, 4 values for default, 2 values for range */
570
571 /* Verification rule: If name changes, a saved socket and its links will be removed! Type changes are OK */
572
573 /* **************** VIEWER ******************** */
574 static bNodeSocketType cmp_node_viewer_in[]= {
575         {       SOCK_RGBA, 1, "Image",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
576         {       SOCK_VALUE, 1, "Alpha",         1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
577         {       SOCK_VALUE, 1, "Z",                     1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
578         {       -1, 0, ""       }
579 };
580
581 static void do_copy_rgba(bNode *node, float *out, float *in)
582 {
583         QUATCOPY(out, in);
584 }
585 static void do_copy_rgb(bNode *node, float *out, float *in)
586 {
587         VECCOPY(out, in);
588         out[3]= 1.0f;
589 }
590 static void do_copy_value(bNode *node, float *out, float *in)
591 {
592         out[0]= in[0];
593 }
594 static void do_copy_a_rgba(bNode *node, float *out, float *in, float *fac)
595 {
596         VECCOPY(out, in);
597         out[3]= *fac;
598 }
599
600 static void node_composit_exec_viewer(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
601 {
602         /* image assigned to output */
603         /* stack order input sockets: col, alpha, z */
604         
605         if(node->id && (node->flag & NODE_DO_OUTPUT)) { /* only one works on out */
606                 RenderData *rd= data;
607                 Image *ima= (Image *)node->id;
608                 ImBuf *ibuf;
609                 CompBuf *cbuf, *tbuf;
610                 int rectx, recty;
611                 
612                 BKE_image_user_calc_imanr(node->storage, rd->cfra, 0);
613
614                 /* always returns for viewer image, but we check nevertheless */
615                 ibuf= BKE_image_get_ibuf(ima, node->storage);
616                 if(ibuf==NULL) {
617                         printf("node_composit_exec_viewer error\n");
618                         return;
619                 }
620                 
621                 /* free all in ibuf */
622                 imb_freerectImBuf(ibuf);
623                 imb_freerectfloatImBuf(ibuf);
624                 IMB_freezbuffloatImBuf(ibuf);
625                 
626                 /* get size */
627                 tbuf= in[0]->data?in[0]->data:(in[1]->data?in[1]->data:in[2]->data);
628                 if(tbuf==NULL) {
629                         rectx= 320; recty= 256;
630                 }
631                 else {
632                         rectx= tbuf->x;
633                         recty= tbuf->y;
634                 }
635                 
636                 /* make ibuf, and connect to ima */
637                 ibuf->x= rectx;
638                 ibuf->y= recty;
639                 imb_addrectfloatImBuf(ibuf);
640                 
641                 ima->ok= IMA_OK_LOADED;
642
643                 /* now we combine the input with ibuf */
644                 cbuf= alloc_compbuf(rectx, recty, CB_RGBA, 0);  /* no alloc*/
645                 cbuf->rect= ibuf->rect_float;
646                 
647                 /* when no alpha, we can simply copy */
648                 if(in[1]->data==NULL) {
649                         composit1_pixel_processor(node, cbuf, in[0]->data, in[0]->vec, do_copy_rgba, CB_RGBA);
650                 }
651                 else
652                         composit2_pixel_processor(node, cbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_copy_a_rgba, CB_RGBA, CB_VAL);
653                 
654                 /* zbuf option */
655                 if(in[2]->data) {
656                         CompBuf *zbuf= alloc_compbuf(rectx, recty, CB_VAL, 1);
657                         ibuf->zbuf_float= zbuf->rect;
658                         ibuf->mall |= IB_zbuffloat;
659                         
660                         composit1_pixel_processor(node, zbuf, in[2]->data, in[2]->vec, do_copy_value, CB_VAL);
661                         
662                         /* free compbuf, but not the rect */
663                         zbuf->malloc= 0;
664                         free_compbuf(zbuf);
665                 }
666
667                 generate_preview(node, cbuf);
668                 free_compbuf(cbuf);
669
670         }
671         else if(in[0]->data) {
672                 generate_preview(node, in[0]->data);
673         }
674 }
675
676 static bNodeType cmp_node_viewer= {
677         /* type code   */       CMP_NODE_VIEWER,
678         /* name        */       "Viewer",
679         /* width+range */       80, 60, 200,
680         /* class+opts  */       NODE_CLASS_OUTPUT, NODE_PREVIEW,
681         /* input sock  */       cmp_node_viewer_in,
682         /* output sock */       NULL,
683         /* storage     */       "ImageUser",
684         /* execfunc    */       node_composit_exec_viewer
685         
686 };
687
688 /* **************** SPLIT VIEWER ******************** */
689 static bNodeSocketType cmp_node_splitviewer_in[]= {
690         {       SOCK_RGBA, 1, "Image",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
691         {       SOCK_RGBA, 1, "Image",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
692         {       -1, 0, ""       }
693 };
694
695 static void do_copy_split_rgba(bNode *node, float *out, float *in1, float *in2, float *fac)
696 {
697         if(*fac==0.0f) {
698                 QUATCOPY(out, in1);
699         }
700         else {
701                 QUATCOPY(out, in2);
702         }
703 }
704
705 static void node_composit_exec_splitviewer(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
706 {
707         /* image assigned to output */
708         /* stack order input sockets: image image */
709         
710         if(in[0]->data==NULL || in[1]->data==NULL)
711                 return;
712         
713         if(node->id && (node->flag & NODE_DO_OUTPUT)) { /* only one works on out */
714                 Image *ima= (Image *)node->id;
715                 RenderData *rd= data;
716                 ImBuf *ibuf;
717                 CompBuf *cbuf, *buf1, *buf2, *mask;
718                 int x, y;
719                 
720                 buf1= typecheck_compbuf(in[0]->data, CB_RGBA);
721                 buf2= typecheck_compbuf(in[1]->data, CB_RGBA);
722                 
723                 BKE_image_user_calc_imanr(node->storage, rd->cfra, 0);
724                 
725                 /* always returns for viewer image, but we check nevertheless */
726                 ibuf= BKE_image_get_ibuf(ima, node->storage);
727                 if(ibuf==NULL) {
728                         printf("node_composit_exec_viewer error\n");
729                         return;
730                 }
731                 
732                 /* free all in ibuf */
733                 imb_freerectImBuf(ibuf);
734                 imb_freerectfloatImBuf(ibuf);
735                 IMB_freezbuffloatImBuf(ibuf);
736                 
737                 /* make ibuf, and connect to ima */
738                 ibuf->x= buf1->x;
739                 ibuf->y= buf1->y;
740                 imb_addrectfloatImBuf(ibuf);
741                 
742                 ima->ok= IMA_OK_LOADED;
743
744                 /* output buf */
745                 cbuf= alloc_compbuf(buf1->x, buf1->y, CB_RGBA, 0);      /* no alloc*/
746                 cbuf->rect= ibuf->rect_float;
747                 
748                 /* mask buf */
749                 mask= alloc_compbuf(buf1->x, buf1->y, CB_VAL, 1);
750                 for(y=0; y<buf1->y; y++) {
751                         float *fac= mask->rect + y*buf1->x;
752                         for(x=buf1->x/2; x>0; x--, fac++)
753                                 *fac= 1.0f;
754                 }
755                 
756                 composit3_pixel_processor(node, cbuf, buf1, in[0]->vec, buf2, in[1]->vec, mask, NULL, do_copy_split_rgba, CB_RGBA, CB_RGBA, CB_VAL);
757                 
758                 generate_preview(node, cbuf);
759                 free_compbuf(cbuf);
760                 free_compbuf(mask);
761                 
762                 if(in[0]->data != buf1) 
763                         free_compbuf(buf1);
764                 if(in[1]->data != buf2) 
765                         free_compbuf(buf2);
766         }
767 }
768
769 static bNodeType cmp_node_splitviewer= {
770         /* type code   */       CMP_NODE_SPLITVIEWER,
771         /* name        */       "SplitViewer",
772         /* width+range */       80, 60, 200,
773         /* class+opts  */       NODE_CLASS_OUTPUT, NODE_PREVIEW,
774         /* input sock  */       cmp_node_splitviewer_in,
775         /* output sock */       NULL,
776         /* storage     */       "ImageUser",
777         /* execfunc    */       node_composit_exec_splitviewer
778         
779 };
780
781
782 /* **************** COMPOSITE ******************** */
783 static bNodeSocketType cmp_node_composite_in[]= {
784         {       SOCK_RGBA, 1, "Image",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
785         {       SOCK_VALUE, 1, "Alpha",         1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
786         {       SOCK_VALUE, 1, "Z",                     1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
787         {       -1, 0, ""       }
788 };
789
790 /* applies to render pipeline */
791 static void node_composit_exec_composite(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
792 {
793         /* image assigned to output */
794         /* stack order input sockets: col, alpha, z */
795         
796         if(node->flag & NODE_DO_OUTPUT) {       /* only one works on out */
797                 RenderData *rd= data;
798                 if(rd->scemode & R_DOCOMP) {
799                         RenderResult *rr= RE_GetResult(RE_GetRender(G.scene->id.name)); /* G.scene is WEAK! */
800                         if(rr) {
801                                 CompBuf *outbuf, *zbuf=NULL;
802                                 
803                                 if(rr->rectf) 
804                                         MEM_freeN(rr->rectf);
805                                 outbuf= alloc_compbuf(rr->rectx, rr->recty, CB_RGBA, 1);
806                                 
807                                 if(in[1]->data==NULL)
808                                         composit1_pixel_processor(node, outbuf, in[0]->data, in[0]->vec, do_copy_rgba, CB_RGBA);
809                                 else
810                                         composit2_pixel_processor(node, outbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_copy_a_rgba, CB_RGBA, CB_VAL);
811                                 
812                                 if(in[2]->data) {
813                                         if(rr->rectz) 
814                                                 MEM_freeN(rr->rectz);
815                                         zbuf= alloc_compbuf(rr->rectx, rr->recty, CB_VAL, 1);
816                                         composit1_pixel_processor(node, zbuf, in[2]->data, in[2]->vec, do_copy_value, CB_VAL);
817                                         rr->rectz= zbuf->rect;
818                                         zbuf->malloc= 0;
819                                         free_compbuf(zbuf);
820                                 }
821                                 generate_preview(node, outbuf);
822                                 
823                                 /* we give outbuf to rr... */
824                                 rr->rectf= outbuf->rect;
825                                 outbuf->malloc= 0;
826                                 free_compbuf(outbuf);
827                                 
828                                 /* signal for imageviewer to refresh (it converts to byte rects...) */
829                                 BKE_image_signal(BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"), NULL, IMA_SIGNAL_FREE);
830                                 return;
831                         }
832                 }
833         }
834         if(in[0]->data)
835                 generate_preview(node, in[0]->data);
836 }
837
838 static bNodeType cmp_node_composite= {
839         /* type code   */       CMP_NODE_COMPOSITE,
840         /* name        */       "Composite",
841         /* width+range */       80, 60, 200,
842         /* class+opts  */       NODE_CLASS_OUTPUT, NODE_PREVIEW,
843         /* input sock  */       cmp_node_composite_in,
844         /* output sock */       NULL,
845         /* storage     */       "",
846         /* execfunc    */       node_composit_exec_composite
847         
848 };
849
850 /* **************** OUTPUT FILE ******************** */
851 static bNodeSocketType cmp_node_output_file_in[]= {
852         {       SOCK_RGBA, 1, "Image",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
853         {       SOCK_VALUE, 1, "Z",             0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
854         {       -1, 0, ""       }
855 };
856
857 static void node_composit_exec_output_file(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
858 {
859         /* image assigned to output */
860         /* stack order input sockets: col, alpha */
861         
862         if(in[0]->data) {
863                 RenderData *rd= data;
864                 NodeImageFile *nif= node->storage;
865                 if(nif->sfra!=nif->efra && (rd->cfra<nif->sfra || rd->cfra>nif->efra)) {
866                         return; /* BAIL OUT RETURN */
867                 }
868                 else {
869                         CompBuf *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA);
870                         ImBuf *ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0, 0);
871                         char string[256];
872                         
873                         ibuf->rect_float= cbuf->rect;
874                         ibuf->dither= rd->dither_intensity;
875                         if(in[1]->data) {
876                                 CompBuf *zbuf= in[1]->data;
877                                 if(zbuf->type==CB_VAL && zbuf->x==cbuf->x && zbuf->y==cbuf->y) {
878                                         nif->subimtype|= R_OPENEXR_ZBUF;
879                                         ibuf->zbuf_float= zbuf->rect;
880                                 }
881                         }
882                         
883                         BKE_makepicstring(string, nif->name, rd->cfra, nif->imtype);
884                         
885                         if(0 == BKE_write_ibuf(ibuf, string, nif->imtype, nif->subimtype, nif->imtype==R_OPENEXR?nif->codec:nif->quality))
886                                 printf("Cannot save Node File Output to %s\n", string);
887                         else
888                                 printf("Saved: %s\n", string);
889                         
890                         IMB_freeImBuf(ibuf);    
891                         
892                         generate_preview(node, cbuf);
893                         
894                         if(in[0]->data != cbuf) 
895                                 free_compbuf(cbuf);
896                 }
897         }
898 }
899
900 static bNodeType cmp_node_output_file= {
901         /* type code   */       CMP_NODE_OUTPUT_FILE,
902         /* name        */       "File Output",
903         /* width+range */       140, 80, 300,
904         /* class+opts  */       NODE_CLASS_OUTPUT, NODE_PREVIEW|NODE_OPTIONS,
905         /* input sock  */       cmp_node_output_file_in,
906         /* output sock */       NULL,
907         /* storage     */       "NodeImageFile",
908         /* execfunc    */       node_composit_exec_output_file
909         
910 };
911
912 /* **************** IMAGE (and RenderResult, multilayer image) ******************** */
913
914 /* output socket defines */
915 #define RRES_OUT_IMAGE  0
916 #define RRES_OUT_ALPHA  1
917 #define RRES_OUT_Z              2
918 #define RRES_OUT_NORMAL 3
919 #define RRES_OUT_UV             4
920 #define RRES_OUT_VEC    5
921 #define RRES_OUT_RGBA   6
922 #define RRES_OUT_DIFF   7
923 #define RRES_OUT_SPEC   8
924 #define RRES_OUT_SHADOW 9
925 #define RRES_OUT_AO             10
926 #define RRES_OUT_REFLECT 11
927 #define RRES_OUT_REFRACT 12
928 #define RRES_OUT_RADIO   13
929 #define RRES_OUT_INDEXOB 14
930
931 static bNodeSocketType cmp_node_rlayers_out[]= {
932         {       SOCK_RGBA, 0, "Image",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
933         {       SOCK_VALUE, 0, "Alpha",         1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
934         {       SOCK_VALUE, 0, "Z",                     1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
935         {       SOCK_VECTOR, 0, "Normal",       0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
936         {       SOCK_VECTOR, 0, "UV",           1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
937         {       SOCK_VECTOR, 0, "Speed",        1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
938         {       SOCK_RGBA, 0, "Color",          0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
939         {       SOCK_RGBA, 0, "Diffuse",        0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
940         {       SOCK_RGBA, 0, "Specular",       0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
941         {       SOCK_RGBA, 0, "Shadow",         0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
942         {       SOCK_RGBA, 0, "AO",                     0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
943         {       SOCK_RGBA, 0, "Reflect",        0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
944         {       SOCK_RGBA, 0, "Refract",        0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
945         {       SOCK_RGBA, 0, "Radio",          0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
946         {       SOCK_VALUE, 0, "IndexOB",       0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
947         {       -1, 0, ""       }
948 };
949
950
951 /* note: this function is used for multilayer too, to ensure uniform 
952    handling with BKE_image_get_ibuf() */
953 static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *iuser)
954 {
955         ImBuf *ibuf;
956         CompBuf *stackbuf;
957         int type;
958         
959         ibuf= BKE_image_get_ibuf(ima, iuser);
960         if(ibuf==NULL)
961                 return NULL;
962         
963         if(ibuf->rect_float==NULL)
964                 IMB_float_from_rect(ibuf);
965         
966         type= ibuf->channels;
967         
968         if(rd->scemode & R_COMP_CROP) {
969                 stackbuf= get_cropped_compbuf(&rd->disprect, ibuf->rect_float, ibuf->x, ibuf->y, type);
970         }
971         else {
972                 /* we put imbuf copy on stack, cbuf knows rect is from other ibuf when freed! */
973                 stackbuf= alloc_compbuf(ibuf->x, ibuf->y, type, 0);
974                 stackbuf->rect= ibuf->rect_float;
975         }
976         
977         return stackbuf;
978 }
979
980 static CompBuf *node_composit_get_zimage(bNode *node, RenderData *rd)
981 {
982         ImBuf *ibuf= BKE_image_get_ibuf((Image *)node->id, node->storage);
983         CompBuf *zbuf= NULL;
984         
985         if(ibuf && ibuf->zbuf_float) {
986                 if(rd->scemode & R_COMP_CROP) {
987                         zbuf= get_cropped_compbuf(&rd->disprect, ibuf->zbuf_float, ibuf->x, ibuf->y, CB_VAL);
988                 }
989                 else {
990                         zbuf= alloc_compbuf(ibuf->x, ibuf->y, CB_VAL, 0);
991                         zbuf->rect= ibuf->zbuf_float;
992                 }
993         }
994         return zbuf;
995 }
996
997 /* check if layer is available, returns pass buffer */
998 static CompBuf *compbuf_multilayer_get(RenderData *rd, RenderLayer *rl, Image *ima, ImageUser *iuser, int passtype)
999 {
1000         RenderPass *rpass;
1001         short index;
1002         
1003         for(index=0, rpass= rl->passes.first; rpass; rpass= rpass->next, index++)
1004                 if(rpass->passtype==passtype)
1005                         break;
1006         
1007         if(rpass) {
1008                 CompBuf *cbuf;
1009                 
1010                 iuser->pass= index;
1011                 BKE_image_multilayer_index(ima->rr, iuser);
1012                 cbuf= node_composit_get_image(rd, ima, iuser);
1013                 
1014                 return cbuf;
1015         }
1016         return NULL;
1017 }
1018
1019 void outputs_multilayer_get(RenderData *rd, RenderLayer *rl, bNodeStack **out, Image *ima, ImageUser *iuser)
1020 {
1021         if(out[RRES_OUT_Z]->hasoutput)
1022                 out[RRES_OUT_Z]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_Z);
1023         if(out[RRES_OUT_VEC]->hasoutput)
1024                 out[RRES_OUT_VEC]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_VECTOR);
1025         if(out[RRES_OUT_NORMAL]->hasoutput)
1026                 out[RRES_OUT_NORMAL]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_NORMAL);
1027         if(out[RRES_OUT_UV]->hasoutput)
1028                 out[RRES_OUT_UV]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_UV);
1029         
1030         if(out[RRES_OUT_RGBA]->hasoutput)
1031                 out[RRES_OUT_RGBA]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_RGBA);
1032         if(out[RRES_OUT_DIFF]->hasoutput)
1033                 out[RRES_OUT_DIFF]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_DIFFUSE);
1034         if(out[RRES_OUT_SPEC]->hasoutput)
1035                 out[RRES_OUT_SPEC]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_SPEC);
1036         if(out[RRES_OUT_SHADOW]->hasoutput)
1037                 out[RRES_OUT_SHADOW]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_SHADOW);
1038         if(out[RRES_OUT_AO]->hasoutput)
1039                 out[RRES_OUT_AO]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_AO);
1040         if(out[RRES_OUT_REFLECT]->hasoutput)
1041                 out[RRES_OUT_REFLECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_REFLECT);
1042         if(out[RRES_OUT_REFRACT]->hasoutput)
1043                 out[RRES_OUT_REFRACT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_REFRACT);
1044         if(out[RRES_OUT_RADIO]->hasoutput)
1045                 out[RRES_OUT_RADIO]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_RADIO);
1046         if(out[RRES_OUT_INDEXOB]->hasoutput)
1047                 out[RRES_OUT_INDEXOB]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDEXOB);
1048         
1049 }
1050
1051
1052 static void node_composit_exec_image(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
1053 {
1054         
1055         /* image assigned to output */
1056         /* stack order input sockets: col, alpha */
1057         if(node->id) {
1058                 RenderData *rd= data;
1059                 Image *ima= (Image *)node->id;
1060                 ImageUser *iuser= (ImageUser *)node->storage;
1061                 CompBuf *stackbuf= NULL;
1062                 
1063                 /* first set the right frame number in iuser */
1064                 BKE_image_user_calc_imanr(iuser, rd->cfra, 0);
1065                 
1066                 /* force a load, we assume iuser index will be set OK anyway */
1067                 if(ima->type==IMA_TYPE_MULTILAYER)
1068                         BKE_image_get_ibuf(ima, iuser);
1069                 
1070                 if(ima->type==IMA_TYPE_MULTILAYER && ima->rr) {
1071                         RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
1072                         
1073                         if(rl) {
1074                                 out[0]->data= stackbuf= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_COMBINED);
1075                                 
1076                                 /* go over all layers */
1077                                 outputs_multilayer_get(rd, rl, out, ima, iuser);
1078                         }
1079                 }
1080                 else {
1081                         stackbuf= node_composit_get_image(rd, ima, iuser);
1082
1083                         /* put image on stack */        
1084                         out[0]->data= stackbuf;
1085                         
1086                         if(out[2]->hasoutput)
1087                                 out[2]->data= node_composit_get_zimage(node, rd);
1088                 }
1089                 
1090                 /* alpha and preview for both types */
1091                 if(stackbuf) {
1092                         if(out[1]->hasoutput)
1093                                 out[1]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
1094
1095                         generate_preview(node, stackbuf);
1096                 }
1097         }       
1098 }
1099
1100 /* uses node->storage to indicate animated image */
1101
1102 static bNodeType cmp_node_image= {
1103         /* type code   */       CMP_NODE_IMAGE,
1104         /* name        */       "Image",
1105         /* width+range */       120, 80, 300,
1106         /* class+opts  */       NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS,
1107         /* input sock  */       NULL,
1108         /* output sock */       cmp_node_rlayers_out,
1109         /* storage     */       "ImageUser",
1110         /* execfunc    */       node_composit_exec_image
1111         
1112 };
1113
1114 /* **************** RENDER RESULT ******************** */
1115
1116 static CompBuf *compbuf_from_pass(RenderData *rd, RenderLayer *rl, int rectx, int recty, int passcode)
1117 {
1118         float *fp= RE_RenderLayerGetPass(rl, passcode);
1119         if(fp) {
1120                 CompBuf *buf;
1121                 int buftype= CB_VEC3;
1122                 
1123                 if(ELEM(passcode, SCE_PASS_Z, SCE_PASS_INDEXOB))
1124                         buftype= CB_VAL;
1125                 else if(passcode==SCE_PASS_VECTOR)
1126                         buftype= CB_VEC4;
1127                 else if(ELEM(passcode, SCE_PASS_COMBINED, SCE_PASS_RGBA))
1128                         buftype= CB_RGBA;
1129                 
1130                 if(rd->scemode & R_COMP_CROP)
1131                         buf= get_cropped_compbuf(&rd->disprect, fp, rectx, recty, buftype);
1132                 else {
1133                         buf= alloc_compbuf(rectx, recty, buftype, 0);
1134                         buf->rect= fp;
1135                 }
1136                 return buf;
1137         }
1138         return NULL;
1139 }
1140
1141 void node_composit_rlayers_out(RenderData *rd, RenderLayer *rl, bNodeStack **out, int rectx, int recty)
1142 {
1143         if(out[RRES_OUT_Z]->hasoutput)
1144                 out[RRES_OUT_Z]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_Z);
1145         if(out[RRES_OUT_VEC]->hasoutput)
1146                 out[RRES_OUT_VEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_VECTOR);
1147         if(out[RRES_OUT_NORMAL]->hasoutput)
1148                 out[RRES_OUT_NORMAL]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_NORMAL);
1149         if(out[RRES_OUT_UV]->hasoutput)
1150                 out[RRES_OUT_UV]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_UV);
1151         
1152         if(out[RRES_OUT_RGBA]->hasoutput)
1153                 out[RRES_OUT_RGBA]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_RGBA);
1154         if(out[RRES_OUT_DIFF]->hasoutput)
1155                 out[RRES_OUT_DIFF]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE);
1156         if(out[RRES_OUT_SPEC]->hasoutput)
1157                 out[RRES_OUT_SPEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SPEC);
1158         if(out[RRES_OUT_SHADOW]->hasoutput)
1159                 out[RRES_OUT_SHADOW]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SHADOW);
1160         if(out[RRES_OUT_AO]->hasoutput)
1161                 out[RRES_OUT_AO]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_AO);
1162         if(out[RRES_OUT_REFLECT]->hasoutput)
1163                 out[RRES_OUT_REFLECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFLECT);
1164         if(out[RRES_OUT_REFRACT]->hasoutput)
1165                 out[RRES_OUT_REFRACT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFRACT);
1166         if(out[RRES_OUT_RADIO]->hasoutput)
1167                 out[RRES_OUT_RADIO]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_RADIO);
1168         if(out[RRES_OUT_INDEXOB]->hasoutput)
1169                 out[RRES_OUT_INDEXOB]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXOB);
1170         
1171 }
1172
1173 static void node_composit_exec_rlayers(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
1174 {
1175         Scene *sce= node->id?(Scene *)node->id:G.scene; /* G.scene is WEAK! */
1176         RenderData *rd= data;
1177         RenderResult *rr;
1178         
1179         rr= RE_GetResult(RE_GetRender(sce->id.name));
1180                 
1181         if(rr) {
1182                 SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1);
1183                 if(srl) {
1184                         RenderLayer *rl= RE_GetRenderLayer(rr, srl->name);
1185                         if(rl && rl->rectf) {
1186                                 CompBuf *stackbuf;
1187                                 
1188                                 /* we put render rect on stack, cbuf knows rect is from other ibuf when freed! */
1189                                 if(rd->scemode & R_COMP_CROP)
1190                                         stackbuf= get_cropped_compbuf(&rd->disprect, rl->rectf, rr->rectx, rr->recty, CB_RGBA);
1191                                 else {
1192                                         stackbuf= alloc_compbuf(rr->rectx, rr->recty, CB_RGBA, 0);
1193                                         stackbuf->rect= rl->rectf;
1194                                 }
1195                                 if(stackbuf==NULL) {
1196                                         printf("Error; Preview Panel in UV Window returns zero sized image\n");
1197                                 }
1198                                 else {
1199                                         stackbuf->xof= rr->xof;
1200                                         stackbuf->yof= rr->yof;
1201                                         
1202                                         /* put on stack */      
1203                                         out[RRES_OUT_IMAGE]->data= stackbuf;
1204                                         
1205                                         if(out[RRES_OUT_ALPHA]->hasoutput)
1206                                                 out[RRES_OUT_ALPHA]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
1207                                         
1208                                         node_composit_rlayers_out(rd, rl, out, rr->rectx, rr->recty);
1209
1210                                         generate_preview(node, stackbuf);
1211                                 }
1212                         }
1213                 }
1214         }       
1215 }
1216
1217 /* custom1 = render layer in use */
1218 /* custom2 = re-render tag */
1219 static bNodeType cmp_node_rlayers= {
1220         /* type code   */       CMP_NODE_R_LAYERS,
1221         /* name        */       "Render Layers",
1222         /* width+range */       150, 100, 300,
1223         /* class+opts  */       NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS,
1224         /* input sock  */       NULL,
1225         /* output sock */       cmp_node_rlayers_out,
1226         /* storage     */       "",
1227         /* execfunc    */       node_composit_exec_rlayers
1228         
1229 };
1230
1231 /* **************** TEXTURE ******************** */
1232 static bNodeSocketType cmp_node_texture_in[]= {
1233         {       SOCK_VECTOR, 0, "Offset",               0.0f, 0.0f, 0.0f, 0.0f, -2.0f, 2.0f},
1234         {       SOCK_VECTOR, 0, "Scale",                1.0f, 1.0f, 1.0f, 1.0f, -10.0f, 10.0f},
1235         {       -1, 0, ""       }
1236 };
1237 static bNodeSocketType cmp_node_texture_out[]= {
1238         {       SOCK_VALUE, 0, "Value",         1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
1239         {       SOCK_RGBA , 0, "Color",         1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f},
1240         {       -1, 0, ""       }
1241 };
1242
1243 /* called without rect allocated */
1244 static void texture_procedural(CompBuf *cbuf, float *col, float xco, float yco)
1245 {
1246         bNode *node= cbuf->node;
1247         bNodeSocket *sock= node->inputs.first;
1248         TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
1249         float vec[3], *size, nor[3]={0.0f, 0.0f, 0.0f};
1250         int retval, type= cbuf->type;
1251         
1252         size= sock->next->ns.vec;
1253         
1254         vec[0]= size[0]*(xco + sock->ns.vec[0]);
1255         vec[1]= size[1]*(yco + sock->ns.vec[1]);
1256         vec[2]= size[2]*sock->ns.vec[2];
1257         
1258         retval= multitex_ext((Tex *)node->id, vec, NULL, NULL, 0, &texres);
1259         
1260         if(type==CB_VAL) {
1261                 if(texres.talpha)
1262                         col[0]= texres.ta;
1263                 else
1264                         col[0]= texres.tin;
1265         }
1266         else if(type==CB_RGBA) {
1267                 if(texres.talpha)
1268                         col[3]= texres.ta;
1269                 else
1270                         col[3]= texres.tin;
1271                 
1272                 if((retval & TEX_RGB)) {
1273                         col[0]= texres.tr;
1274                         col[1]= texres.tg;
1275                         col[2]= texres.tb;
1276                 }
1277                 else col[0]= col[1]= col[2]= col[3];
1278         }
1279         else { 
1280                 VECCOPY(col, nor);
1281         }
1282 }
1283
1284 /* texture node outputs get a small rect, to make sure all other nodes accept it */
1285 /* only the pixel-processor nodes do something with it though */
1286 static void node_composit_exec_texture(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
1287 {
1288         /* outputs: value, color, normal */
1289         
1290         if(node->id) {
1291                 /* first make the preview image */
1292                 CompBuf *prevbuf= alloc_compbuf(140, 140, CB_RGBA, 1); // alloc
1293                 
1294                 prevbuf->rect_procedural= texture_procedural;
1295                 prevbuf->node= node;
1296                 composit1_pixel_processor(node, prevbuf, prevbuf, out[0]->vec, do_copy_rgba, CB_RGBA);
1297                 generate_preview(node, prevbuf);
1298                 free_compbuf(prevbuf);
1299                 
1300                 if(out[0]->hasoutput) {
1301                         CompBuf *stackbuf= alloc_compbuf(140, 140, CB_VAL, 1); // alloc
1302                         
1303                         stackbuf->rect_procedural= texture_procedural;
1304                         stackbuf->node= node;
1305                         
1306                         out[0]->data= stackbuf;
1307                 }
1308                 if(out[1]->hasoutput) {
1309                         CompBuf *stackbuf= alloc_compbuf(140, 140, CB_RGBA, 1); // alloc
1310                         
1311                         stackbuf->rect_procedural= texture_procedural;
1312                         stackbuf->node= node;
1313                         
1314                         out[1]->data= stackbuf;
1315                 }
1316         }
1317 }
1318
1319 static bNodeType cmp_node_texture= {
1320         /* type code   */       CMP_NODE_TEXTURE,
1321         /* name        */       "Texture",
1322         /* width+range */       120, 80, 240,
1323         /* class+opts  */       NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW,
1324         /* input sock  */       cmp_node_texture_in,
1325         /* output sock */       cmp_node_texture_out,
1326         /* storage     */       "",
1327         /* execfunc    */       node_composit_exec_texture
1328         
1329 };
1330
1331 /* **************** NORMAL  ******************** */
1332 static bNodeSocketType cmp_node_normal_in[]= {
1333         {       SOCK_VECTOR, 1, "Normal",       0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
1334         {       -1, 0, ""       }
1335 };
1336
1337 static bNodeSocketType cmp_node_normal_out[]= {
1338         {       SOCK_VECTOR, 0, "Normal",       0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f},
1339         {       SOCK_VALUE, 0, "Dot",           1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
1340         {       -1, 0, ""       }
1341 };
1342
1343 static void do_normal(bNode *node, float *out, float *in)
1344 {
1345         bNodeSocket *sock= node->outputs.first;
1346         float *nor= sock->ns.vec;
1347         
1348         /* render normals point inside... the widget points outside */
1349         out[0]= -INPR(nor, in);
1350 }
1351
1352 /* generates normal, does dot product */
1353 static void node_composit_exec_normal(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
1354 {
1355         bNodeSocket *sock= node->outputs.first;
1356         /* stack order input:  normal */
1357         /* stack order output: normal, value */
1358         
1359         /* input no image? then only vector op */
1360         if(in[0]->data==NULL) {
1361                 VECCOPY(out[0]->vec, sock->ns.vec);
1362                 /* render normals point inside... the widget points outside */
1363                 out[1]->vec[0]= -INPR(out[0]->vec, in[0]->vec);
1364         }
1365         else if(out[1]->hasoutput) {
1366                 /* make output size of input image */
1367                 CompBuf *cbuf= in[0]->data;
1368                 CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); // allocs
1369                 
1370                 composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_normal, CB_VEC3);
1371                 
1372                 out[1]->data= stackbuf;
1373         }
1374         
1375         
1376 }
1377
1378 static bNodeType cmp_node_normal= {
1379         /* type code   */       CMP_NODE_NORMAL,
1380         /* name        */       "Normal",
1381         /* width+range */       100, 60, 200,
1382         /* class+opts  */       NODE_CLASS_OP_VECTOR, NODE_OPTIONS,
1383         /* input sock  */       cmp_node_normal_in,
1384         /* output sock */       cmp_node_normal_out,
1385         /* storage     */       "",
1386         /* execfunc    */       node_composit_exec_normal
1387         
1388 };
1389
1390 /* **************** CURVE Time  ******************** */
1391
1392 /* custom1 = sfra, custom2 = efra */
1393 static bNodeSocketType cmp_node_time_out[]= {
1394         {       SOCK_VALUE, 0, "Fac",   1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f},
1395         {       -1, 0, ""       }
1396 };
1397
1398 static void node_composit_exec_time(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
1399 {
1400         /* stack order output: fac */
1401         float fac= 0.0f;
1402         
1403         if(node->custom1 < node->custom2)
1404                 fac= (G.scene->r.cfra - node->custom1)/(float)(node->custom2-node->custom1);
1405         
1406         out[0]->vec[0]= curvemapping_evaluateF(node->storage, 0, fac);
1407 }
1408
1409 static bNodeType cmp_node_time= {
1410         /* type code   */       CMP_NODE_TIME,
1411         /* name        */       "Time",
1412         /* width+range */       140, 100, 320,
1413         /* class+opts  */       NODE_CLASS_INPUT, NODE_OPTIONS,
1414         /* input sock  */       NULL,
1415         /* output sock */       cmp_node_time_out,
1416         /* storage     */       "CurveMapping",
1417         /* execfunc    */       node_composit_exec_time
1418 };
1419
1420 /* **************** CURVE VEC  ******************** */
1421 static bNodeSocketType cmp_node_curve_vec_in[]= {
1422         {       SOCK_VECTOR, 1, "Vector",       0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
1423         {       -1, 0, ""       }
1424 };
1425
1426 static bNodeSocketType cmp_node_curve_vec_out[]= {
1427         {       SOCK_VECTOR, 0, "Vector",       0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f},
1428         {       -1, 0, ""       }
1429 };
1430
1431 static void node_composit_exec_curve_vec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
1432 {
1433         /* stack order input:  vec */
1434         /* stack order output: vec */
1435         
1436         curvemapping_evaluate_premulRGBF(node->storage, out[0]->vec, in[0]->vec);
1437 }
1438
1439 static bNodeType cmp_node_curve_vec= {
1440         /* type code   */       CMP_NODE_CURVE_VEC,
1441         /* name        */       "Vector Curves",
1442         /* width+range */       200, 140, 320,
1443         /* class+opts  */       NODE_CLASS_OP_VECTOR, NODE_OPTIONS,
1444         /* input sock  */       cmp_node_curve_vec_in,
1445         /* output sock */       cmp_node_curve_vec_out,
1446         /* storage     */       "CurveMapping",
1447         /* execfunc    */       node_composit_exec_curve_vec
1448         
1449 };
1450
1451 /* **************** CURVE RGB  ******************** */
1452 static bNodeSocketType cmp_node_curve_rgb_in[]= {
1453         {       SOCK_VALUE, 1, "Fac",   1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
1454         {       SOCK_RGBA, 1, "Image",  0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
1455         {       -1, 0, ""       }
1456 };
1457
1458 static bNodeSocketType cmp_node_curve_rgb_out[]= {
1459         {       SOCK_RGBA, 0, "Image",  0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f},
1460         {       -1, 0, ""       }
1461 };
1462
1463 static void do_curves(bNode *node, float *out, float *in)
1464 {
1465         curvemapping_evaluate_premulRGBF(node->storage, out, in);
1466         out[3]= in[3];
1467 }
1468
1469 static void do_curves_fac(bNode *node, float *out, float *in, float *fac)
1470 {
1471         
1472         if(*fac>=1.0)
1473                 curvemapping_evaluate_premulRGBF(node->storage, out, in);
1474         else if(*fac<=0.0) {
1475                 VECCOPY(out, in);
1476         }
1477         else {
1478                 float col[4], mfac= 1.0f-*fac;
1479                 curvemapping_evaluate_premulRGBF(node->storage, col, in);
1480                 out[0]= mfac*in[0] + *fac*col[0];
1481                 out[1]= mfac*in[1] + *fac*col[1];
1482                 out[2]= mfac*in[2] + *fac*col[2];
1483         }
1484         out[3]= in[3];
1485 }
1486
1487 static void node_composit_exec_curve_rgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
1488 {
1489         /* stack order input:  fac, image */
1490         /* stack order output: image */
1491         
1492         if(out[0]->hasoutput==0)
1493                 return;
1494
1495         /* input no image? then only color operation */
1496         if(in[1]->data==NULL) {
1497                 curvemapping_evaluateRGBF(node->storage, out[0]->vec, in[1]->vec);
1498         }
1499         else {
1500                 /* make output size of input image */
1501                 CompBuf *cbuf= in[1]->data;
1502                 CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs
1503                 
1504                 if(in[0]->data)
1505                         composit2_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[0]->data, in[0]->vec, do_curves_fac, CB_RGBA, CB_VAL);
1506                 else
1507                         composit1_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, do_curves, CB_RGBA);
1508                 
1509                 out[0]->data= stackbuf;
1510         }
1511         
1512 }
1513
1514 static bNodeType cmp_node_curve_rgb= {
1515         /* type code   */       CMP_NODE_CURVE_RGB,
1516         /* name        */       "RGB Curves",
1517         /* width+range */       200, 140, 320,
1518         /* class+opts  */       NODE_CLASS_OP_COLOR, NODE_OPTIONS,
1519         /* input sock  */       cmp_node_curve_rgb_in,
1520         /* output sock */       cmp_node_curve_rgb_out,
1521         /* storage     */       "CurveMapping",
1522         /* execfunc    */       node_composit_exec_curve_rgb
1523         
1524 };
1525
1526 /* **************** VALUE ******************** */
1527 static bNodeSocketType cmp_node_value_out[]= {
1528         {       SOCK_VALUE, 0, "Value",         0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
1529         {       -1, 0, ""       }
1530 };
1531
1532 static void node_composit_exec_value(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
1533 {
1534         bNodeSocket *sock= node->outputs.first;
1535         
1536         out[0]->vec[0]= sock->ns.vec[0];
1537 }
1538
1539 static bNodeType cmp_node_value= {
1540         /* type code   */       CMP_NODE_VALUE,
1541         /* name        */       "Value",
1542         /* width+range */       80, 40, 120,
1543         /* class+opts  */       NODE_CLASS_INPUT, NODE_OPTIONS,
1544         /* input sock  */       NULL,
1545         /* output sock */       cmp_node_value_out,
1546         /* storage     */       "", 
1547         /* execfunc    */       node_composit_exec_value
1548         
1549 };
1550
1551 /* **************** RGB ******************** */
1552 static bNodeSocketType cmp_node_rgb_out[]= {
1553         {       SOCK_RGBA, 0, "RGBA",                   0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
1554         {       -1, 0, ""       }
1555 };
1556
1557 static void node_composit_exec_rgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
1558 {
1559         bNodeSocket *sock= node->outputs.first;
1560         
1561         VECCOPY(out[0]->vec, sock->ns.vec);
1562 }
1563
1564 static bNodeType cmp_node_rgb= {
1565         /* type code   */       CMP_NODE_RGB,
1566         /* name        */       "RGB",
1567         /* width+range */       100, 60, 140,
1568         /* class+opts  */       NODE_CLASS_INPUT, NODE_OPTIONS,
1569         /* input sock  */       NULL,
1570         /* output sock */       cmp_node_rgb_out,
1571         /* storage     */       "",
1572         /* execfunc    */       node_composit_exec_rgb
1573         
1574 };
1575
1576 /* **************** Hue Saturation ******************** */
1577 static bNodeSocketType cmp_node_hue_sat_in[]= {
1578         {       SOCK_VALUE, 1, "Fac",                   1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
1579         {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
1580         {       -1, 0, ""       }
1581 };
1582 static bNodeSocketType cmp_node_hue_sat_out[]= {
1583         {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
1584         {       -1, 0, ""       }
1585 };
1586
1587 static void do_hue_sat_fac(bNode *node, float *out, float *in, float *fac)
1588 {
1589         NodeHueSat *nhs= node->storage;
1590         
1591         if(*fac!=0.0f && (nhs->hue!=0.5f || nhs->sat!=1.0 || nhs->val!=1.0)) {
1592                 float col[3], hsv[3], mfac= 1.0f - *fac;
1593                 
1594                 rgb_to_hsv(in[0], in[1], in[2], hsv, hsv+1, hsv+2);
1595                 hsv[0]+= (nhs->hue - 0.5f);
1596                 if(hsv[0]>1.0) hsv[0]-=1.0; else if(hsv[0]<0.0) hsv[0]+= 1.0;
1597                 hsv[1]*= nhs->sat;
1598                 if(hsv[1]>1.0) hsv[1]= 1.0; else if(hsv[1]<0.0) hsv[1]= 0.0;
1599                 hsv[2]*= nhs->val;
1600                 if(hsv[2]>1.0) hsv[2]= 1.0; else if(hsv[2]<0.0) hsv[2]= 0.0;
1601                 hsv_to_rgb(hsv[0], hsv[1], hsv[2], col, col+1, col+2);
1602                 
1603                 out[0]= mfac*in[0] + *fac*col[0];
1604                 out[1]= mfac*in[1] + *fac*col[1];
1605                 out[2]= mfac*in[2] + *fac*col[2];
1606                 out[3]= in[3];
1607         }
1608         else {
1609                 QUATCOPY(out, in);
1610         }
1611 }
1612
1613 static void node_composit_exec_hue_sat(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
1614 {
1615         /* stack order in: Fac, Image */
1616         /* stack order out: Image */
1617         if(out[0]->hasoutput==0) return;
1618         
1619         /* input no image? then only color operation */
1620         if(in[1]->data==NULL) {
1621                 do_hue_sat_fac(node, out[0]->vec, in[1]->vec, in[0]->vec);
1622         }
1623         else {
1624                 /* make output size of input image */
1625                 CompBuf *cbuf= in[1]->data;
1626                 CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs
1627                 
1628                 composit2_pixel_processor(node, stackbuf, cbuf, in[1]->vec, in[0]->data, in[0]->vec, do_hue_sat_fac, CB_RGBA, CB_VAL);
1629
1630                 out[0]->data= stackbuf;
1631         }
1632 }
1633
1634 static bNodeType cmp_node_hue_sat= {
1635         /* type code   */       CMP_NODE_HUE_SAT,
1636         /* name        */       "Hue Saturation Value",
1637         /* width+range */       150, 80, 250,
1638         /* class+opts  */       NODE_CLASS_OP_COLOR, NODE_OPTIONS,
1639         /* input sock  */       cmp_node_hue_sat_in,
1640         /* output sock */       cmp_node_hue_sat_out,
1641         /* storage     */       "NodeHueSat", 
1642         /* execfunc    */       node_composit_exec_hue_sat
1643         
1644 };
1645
1646 /* **************** MIX RGB ******************** */
1647 static bNodeSocketType cmp_node_mix_rgb_in[]= {
1648         {       SOCK_VALUE, 1, "Fac",                   0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 5.0f},
1649         {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
1650         {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
1651         {       -1, 0, ""       }
1652 };
1653 static bNodeSocketType cmp_node_mix_rgb_out[]= {
1654         {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
1655         {       -1, 0, ""       }
1656 };
1657
1658 static void do_mix_rgb(bNode *node, float *out, float *in1, float *in2, float *fac)
1659 {
1660         float col[3];
1661         
1662         VECCOPY(col, in1);
1663         if(node->custom2)
1664                 ramp_blend(node->custom1, col, col+1, col+2, in2[3]*fac[0], in2);
1665         else
1666                 ramp_blend(node->custom1, col, col+1, col+2, fac[0], in2);
1667         VECCOPY(out, col);
1668         out[3]= in1[3];
1669 }
1670
1671 static void node_composit_exec_mix_rgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
1672 {
1673         /* stack order in: fac, Image, Image */
1674         /* stack order out: Image */
1675         float *fac= in[0]->vec;
1676         
1677         if(out[0]->hasoutput==0) return;
1678         
1679         /* input no image? then only color operation */
1680         if(in[1]->data==NULL && in[2]->data==NULL) {
1681                 do_mix_rgb(node, out[0]->vec, in[1]->vec, in[2]->vec, fac);
1682         }
1683         else {
1684                 /* make output size of first available input image */
1685                 CompBuf *cbuf= in[1]->data?in[1]->data:in[2]->data;
1686                 CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs
1687                 
1688                 composit3_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[2]->data, in[2]->vec, in[0]->data, fac, do_mix_rgb, CB_RGBA, CB_RGBA, CB_VAL);
1689                 
1690                 out[0]->data= stackbuf;
1691         }
1692 }
1693
1694 /* custom1 = mix type */
1695 static bNodeType cmp_node_mix_rgb= {
1696         /* type code   */       CMP_NODE_MIX_RGB,
1697         /* name        */       "Mix",
1698         /* width+range */       80, 60, 120,
1699         /* class+opts  */       NODE_CLASS_OP_COLOR, NODE_OPTIONS,
1700         /* input sock  */       cmp_node_mix_rgb_in,
1701         /* output sock */       cmp_node_mix_rgb_out,
1702         /* storage     */       "", 
1703         /* execfunc    */       node_composit_exec_mix_rgb
1704         
1705 };
1706
1707 /* **************** FILTER  ******************** */
1708 static bNodeSocketType cmp_node_filter_in[]= {
1709         {       SOCK_VALUE, 1, "Fac",                   1.0f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
1710         {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
1711         {       -1, 0, ""       }
1712 };
1713 static bNodeSocketType cmp_node_filter_out[]= {
1714         {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
1715         {       -1, 0, ""       }
1716 };
1717
1718 static void do_filter_edge(CompBuf *out, CompBuf *in, float *filter, float fac)
1719 {
1720         float *row1, *row2, *row3;
1721         float *fp, f1, f2, mfac= 1.0f-fac;
1722         int rowlen, x, y, c, pix= in->type;
1723         
1724         rowlen= in->x;
1725         
1726         for(y=0; y<in->y; y++) {
1727                 /* setup rows */
1728                 if(y==0) row1= in->rect;
1729                 else row1= in->rect + pix*(y-1)*rowlen;
1730                 
1731                 row2= in->rect + y*pix*rowlen;
1732                 
1733                 if(y==in->y-1) row3= row2;
1734                 else row3= row2 + pix*rowlen;
1735                 
1736                 fp= out->rect + pix*y*rowlen;
1737                 
1738                 if(pix==CB_RGBA) {
1739                         QUATCOPY(fp, row2);
1740                         fp+= pix;
1741                         
1742                         for(x=2; x<rowlen; x++) {
1743                                 for(c=0; c<3; c++) {
1744                                         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];
1745                                         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];
1746                                         fp[0]= mfac*row2[4] + fac*sqrt(f1*f1 + f2*f2);
1747                                         fp++; row1++; row2++; row3++;
1748                                 }
1749                                 fp[0]= row2[4];
1750                                 /* no alpha... will clear it completely */
1751                                 fp++; row1++; row2++; row3++;
1752                         }
1753                         QUATCOPY(fp, row2+4);
1754                 }
1755                 else if(pix==CB_VAL) {
1756                         for(x=2; x<rowlen; x++) {
1757                                 f1= filter[0]*row1[0] + filter[1]*row1[1] + filter[2]*row1[2] + filter[3]*row2[0] + filter[4]*row2[1] + filter[5]*row2[2] + filter[6]*row3[0] + filter[7]*row3[1] + filter[8]*row3[2];
1758                                 f2= filter[0]*row1[0] + filter[3]*row1[1] + filter[6]*row1[2] + filter[1]*row2[0] + filter[4]*row2[1] + filter[7]*row2[2] + filter[2]*row3[0] + filter[5]*row3[1] + filter[8]*row3[2];
1759                                 fp[0]= mfac*row2[1] + fac*sqrt(f1*f1 + f2*f2);
1760                                 fp++; row1++; row2++; row3++;
1761                         }
1762                 }
1763         }
1764 }
1765
1766 static void do_filter3(CompBuf *out, CompBuf *in, float *filter, float fac)
1767 {
1768         float *row1, *row2, *row3;
1769         float *fp, mfac= 1.0f-fac;
1770         int rowlen, x, y, c;
1771         int pixlen= in->type;
1772         
1773         rowlen= in->x;
1774         
1775         for(y=0; y<in->y; y++) {
1776                 /* setup rows */
1777                 if(y==0) row1= in->rect;
1778                 else row1= in->rect + pixlen*(y-1)*rowlen;
1779                 
1780                 row2= in->rect + y*pixlen*rowlen;
1781                 
1782                 if(y==in->y-1) row3= row2;
1783                 else row3= row2 + pixlen*rowlen;
1784                 
1785                 fp= out->rect + pixlen*(y)*rowlen;
1786                 
1787                 if(pixlen==1) {
1788                         fp[0]= row2[0];
1789                         fp+= 1;
1790                         
1791                         for(x=2; x<rowlen; x++) {
1792                                 fp[0]= mfac*row2[1] + fac*(filter[0]*row1[0] + filter[1]*row1[1] + filter[2]*row1[2] + filter[3]*row2[0] + filter[4]*row2[1] + filter[5]*row2[2] + filter[6]*row3[0] + filter[7]*row3[1] + filter[8]*row3[2]);
1793                                 fp++; row1++; row2++; row3++;
1794                         }
1795                         fp[0]= row2[1];
1796                 }
1797                 else if(pixlen==2) {
1798                         fp[0]= row2[0];
1799                         fp[1]= row2[1];
1800                         fp+= 2;
1801                         
1802                         for(x=2; x<rowlen; x++) {
1803                                 for(c=0; c<2; c++) {
1804                                         fp[0]= mfac*row2[2] + fac*(filter[0]*row1[0] + filter[1]*row1[2] + filter[2]*row1[4] + filter[3]*row2[0] + filter[4]*row2[2] + filter[5]*row2[4] + filter[6]*row3[0] + filter[7]*row3[2] + filter[8]*row3[4]);
1805                                         fp++; row1++; row2++; row3++;
1806                                 }
1807                         }
1808                         fp[0]= row2[2];
1809                         fp[1]= row2[3];
1810                 }
1811                 else if(pixlen==3) {
1812                         VECCOPY(fp, row2);
1813                         fp+= 3;
1814                         
1815                         for(x=2; x<rowlen; x++) {
1816                                 for(c=0; c<3; c++) {
1817                                         fp[0]= mfac*row2[3] + fac*(filter[0]*row1[0] + filter[1]*row1[3] + filter[2]*row1[6] + filter[3]*row2[0] + filter[4]*row2[3] + filter[5]*row2[6] + filter[6]*row3[0] + filter[7]*row3[3] + filter[8]*row3[6]);
1818                                         fp++; row1++; row2++; row3++;
1819                                 }
1820                         }
1821                         VECCOPY(fp, row2+3);
1822                 }
1823                 else {
1824                         QUATCOPY(fp, row2);
1825                         fp+= 4;
1826                         
1827                         for(x=2; x<rowlen; x++) {
1828                                 for(c=0; c<4; c++) {
1829                                         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]);
1830                                         fp++; row1++; row2++; row3++;
1831                                 }
1832                         }
1833                         QUATCOPY(fp, row2+4);
1834                 }
1835         }
1836 }
1837
1838
1839 static void node_composit_exec_filter(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
1840 {
1841         static 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};
1842         float sharp[9]= {-1,-1,-1,-1,9,-1,-1,-1,-1};
1843         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};
1844         float sobel[9]= {1,2,1,0,0,0,-1,-2,-1};
1845         float prewitt[9]= {1,1,1,0,0,0,-1,-1,-1};
1846         float kirsch[9]= {5,5,5,-3,-3,-3,-2,-2,-2};
1847         float shadow[9]= {1,2,1,0,1,0,-1,-2,-1};
1848         
1849         if(out[0]->hasoutput==0) return;
1850         
1851         /* stack order in: Image */
1852         /* stack order out: Image */
1853         
1854         if(in[1]->data) {
1855                 /* make output size of first available input image */
1856                 CompBuf *cbuf= in[1]->data;
1857                 CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 1); // allocs
1858                 
1859                 /* warning note: xof and yof are applied in pixelprocessor, but should be copied otherwise? */
1860                 stackbuf->xof= cbuf->xof;
1861                 stackbuf->yof= cbuf->yof;
1862                 
1863                 switch(node->custom1) {
1864                         case CMP_FILT_SOFT:
1865                                 do_filter3(stackbuf, cbuf, soft, in[0]->vec[0]);
1866                                 break;
1867                         case CMP_FILT_SHARP:
1868                                 do_filter3(stackbuf, cbuf, sharp, in[0]->vec[0]);
1869                                 break;
1870                         case CMP_FILT_LAPLACE:
1871                                 do_filter3(stackbuf, cbuf, laplace, in[0]->vec[0]);
1872                                 break;
1873                         case CMP_FILT_SOBEL:
1874                                 do_filter_edge(stackbuf, cbuf, sobel, in[0]->vec[0]);
1875                                 break;
1876                         case CMP_FILT_PREWITT:
1877                                 do_filter_edge(stackbuf, cbuf, prewitt, in[0]->vec[0]);
1878                                 break;
1879                         case CMP_FILT_KIRSCH:
1880                                 do_filter_edge(stackbuf, cbuf, kirsch, in[0]->vec[0]);
1881                                 break;
1882                         case CMP_FILT_SHADOW:
1883                                 do_filter3(stackbuf, cbuf, shadow, in[0]->vec[0]);
1884                                 break;
1885                 }
1886                         
1887                 out[0]->data= stackbuf;
1888         }
1889 }
1890
1891 /* custom1 = filter type */
1892 static bNodeType cmp_node_filter= {
1893         /* type code   */       CMP_NODE_FILTER,
1894         /* name        */       "Filter",
1895         /* width+range */       80, 40, 120,
1896         /* class+opts  */       NODE_CLASS_OP_FILTER, NODE_OPTIONS,
1897         /* input sock  */       cmp_node_filter_in,
1898         /* output sock */       cmp_node_filter_out,
1899         /* storage     */       "", 
1900         /* execfunc    */       node_composit_exec_filter
1901         
1902 };
1903
1904
1905 /* **************** VALTORGB ******************** */
1906 static bNodeSocketType cmp_node_valtorgb_in[]= {
1907         {       SOCK_VALUE, 1, "Fac",                   0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
1908         {       -1, 0, ""       }
1909 };
1910 static bNodeSocketType cmp_node_valtorgb_out[]= {
1911         {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
1912         {       SOCK_VALUE, 0, "Alpha",                 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
1913         {       -1, 0, ""       }
1914 };
1915
1916 static void do_colorband_composit(bNode *node, float *out, float *in)
1917 {
1918         do_colorband(node->storage, in[0], out);
1919 }
1920
1921 static void node_composit_exec_valtorgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
1922 {
1923         /* stack order in: fac */
1924         /* stack order out: col, alpha */
1925         
1926         if(out[0]->hasoutput==0 && out[1]->hasoutput==0) 
1927                 return;
1928         
1929         if(node->storage) {
1930                 /* input no image? then only color operation */
1931                 if(in[0]->data==NULL) {
1932                         do_colorband(node->storage, in[0]->vec[0], out[0]->vec);
1933                 }
1934                 else {
1935                         /* make output size of input image */
1936                         CompBuf *cbuf= in[0]->data;
1937                         CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs
1938                         
1939                         composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_colorband_composit, CB_VAL);
1940                         
1941                         out[0]->data= stackbuf;
1942                         
1943                         if(out[1]->hasoutput)
1944                                 out[1]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
1945
1946                 }
1947         }
1948 }
1949
1950 static bNodeType cmp_node_valtorgb= {
1951         /* type code   */       CMP_NODE_VALTORGB,
1952         /* name        */       "ColorRamp",
1953         /* width+range */       240, 200, 300,
1954         /* class+opts  */       NODE_CLASS_CONVERTOR, NODE_OPTIONS,
1955         /* input sock  */       cmp_node_valtorgb_in,
1956         /* output sock */       cmp_node_valtorgb_out,
1957         /* storage     */       "ColorBand",
1958         /* execfunc    */       node_composit_exec_valtorgb
1959         
1960 };
1961
1962
1963 /* **************** RGBTOBW ******************** */
1964 static bNodeSocketType cmp_node_rgbtobw_in[]= {
1965         {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
1966         {       -1, 0, ""       }
1967 };
1968 static bNodeSocketType cmp_node_rgbtobw_out[]= {
1969         {       SOCK_VALUE, 0, "Val",                   0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
1970         {       -1, 0, ""       }
1971 };
1972
1973 static void do_rgbtobw(bNode *node, float *out, float *in)
1974 {
1975         out[0]= in[0]*0.35f + in[1]*0.45f + in[2]*0.2f;
1976 }
1977
1978 static void node_composit_exec_rgbtobw(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
1979 {
1980         /* stack order out: bw */
1981         /* stack order in: col */
1982         
1983         if(out[0]->hasoutput==0)
1984                 return;
1985         
1986         /* input no image? then only color operation */
1987         if(in[0]->data==NULL) {
1988                 do_rgbtobw(node, out[0]->vec, in[0]->vec);
1989         }
1990         else {
1991                 /* make output size of input image */
1992                 CompBuf *cbuf= in[0]->data;
1993                 CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); // allocs
1994                 
1995                 composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_rgbtobw, CB_RGBA);
1996                 
1997                 out[0]->data= stackbuf;
1998         }
1999 }
2000
2001 static bNodeType cmp_node_rgbtobw= {
2002         /* type code   */       CMP_NODE_RGBTOBW,
2003         /* name        */       "RGB to BW",
2004         /* width+range */       80, 40, 120,
2005         /* class+opts  */       NODE_CLASS_CONVERTOR, 0,
2006         /* input sock  */       cmp_node_rgbtobw_in,
2007         /* output sock */       cmp_node_rgbtobw_out,
2008         /* storage     */       "",
2009         /* execfunc    */       node_composit_exec_rgbtobw
2010         
2011 };
2012
2013 /* **************** SEPARATE RGBA ******************** */
2014 static bNodeSocketType cmp_node_seprgba_in[]= {
2015         {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
2016         {       -1, 0, ""       }
2017 };
2018 static bNodeSocketType cmp_node_seprgba_out[]= {
2019         {       SOCK_VALUE, 0, "R",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
2020         {       SOCK_VALUE, 0, "G",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
2021         {       SOCK_VALUE, 0, "B",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
2022         {       SOCK_VALUE, 0, "A",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
2023         {       -1, 0, ""       }
2024 };
2025
2026 static void node_composit_exec_seprgba(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
2027 {
2028         /* stack order out: bw channels */
2029         /* stack order in: col */
2030         
2031         /* input no image? then only color operation */
2032         if(in[0]->data==NULL) {
2033                 out[0]->vec[0] = in[0]->vec[0];
2034                 out[1]->vec[0] = in[0]->vec[1];
2035                 out[2]->vec[0] = in[0]->vec[2];
2036                 out[3]->vec[0] = in[0]->vec[3];
2037         }
2038         else {
2039                 /* make sure we get right rgba buffer */
2040                 CompBuf *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA);
2041
2042                 /* don't do any pixel processing, just copy the stack directly (faster, I presume) */
2043                 if(out[0]->hasoutput)
2044                         out[0]->data= valbuf_from_rgbabuf(cbuf, CHAN_R);
2045                 if(out[1]->hasoutput)
2046                         out[1]->data= valbuf_from_rgbabuf(cbuf, CHAN_G);
2047                 if(out[2]->hasoutput)
2048                         out[2]->data= valbuf_from_rgbabuf(cbuf, CHAN_B);
2049                 if(out[3]->hasoutput)
2050                         out[3]->data= valbuf_from_rgbabuf(cbuf, CHAN_A);
2051                 
2052                 if(cbuf!=in[0]->data) 
2053                         free_compbuf(cbuf);
2054
2055         }
2056 }
2057
2058 static bNodeType cmp_node_seprgba= {
2059         /* type code   */       CMP_NODE_SEPRGBA,
2060         /* name        */       "Separate RGBA",
2061         /* width+range */       80, 40, 140,
2062         /* class+opts  */       NODE_CLASS_CONVERTOR, 0,
2063         /* input sock  */       cmp_node_seprgba_in,
2064         /* output sock */       cmp_node_seprgba_out,
2065         /* storage     */       "",
2066         /* execfunc    */       node_composit_exec_seprgba
2067         
2068 };
2069
2070 /* **************** SEPARATE HSVA ******************** */
2071 static bNodeSocketType cmp_node_sephsva_in[]= {
2072         {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
2073         {       -1, 0, ""       }
2074 };
2075 static bNodeSocketType cmp_node_sephsva_out[]= {
2076         {       SOCK_VALUE, 0, "H",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
2077         {       SOCK_VALUE, 0, "S",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
2078         {       SOCK_VALUE, 0, "V",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
2079         {       SOCK_VALUE, 0, "A",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
2080         {       -1, 0, ""       }
2081 };
2082
2083 static void do_sephsva(bNode *node, float *out, float *in)
2084 {
2085         float h, s, v;
2086         
2087         rgb_to_hsv(in[0], in[1], in[2], &h, &s, &v);
2088         
2089         out[0]= h;
2090         out[1]= s;
2091         out[2]= v;
2092         out[3]= in[3];
2093 }
2094
2095 static void node_composit_exec_sephsva(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
2096 {
2097         /* stack order out: bw channels */
2098         /* stack order in: col */
2099
2100         /* input no image? then only color operation */
2101         if(in[0]->data==NULL) {
2102                 float h, s, v;
2103         
2104                 rgb_to_hsv(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2], &h, &s, &v);
2105                 
2106                 out[0]->vec[0] = h;
2107                 out[1]->vec[0] = s;
2108                 out[2]->vec[0] = v;
2109                 out[3]->vec[0] = in[0]->vec[3];
2110         }
2111         else if ((out[0]->hasoutput) || (out[1]->hasoutput) || (out[2]->hasoutput) || (out[3]->hasoutput)) {
2112                 /* make output size of input image */
2113                 CompBuf *cbuf= in[0]->data;
2114
2115                 CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs
2116
2117                 /* convert the RGB stackbuf to an HSV representation */
2118                 composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_sephsva, CB_RGBA);
2119
2120                 /* separate each of those channels */
2121                 if(out[0]->hasoutput)
2122                         out[0]->data= valbuf_from_rgbabuf(stackbuf, CHAN_R);
2123                 if(out[1]->hasoutput)
2124                         out[1]->data= valbuf_from_rgbabuf(stackbuf, CHAN_G);
2125                 if(out[2]->hasoutput)
2126                         out[2]->data= valbuf_from_rgbabuf(stackbuf, CHAN_B);
2127                 if(out[3]->hasoutput)
2128                         out[3]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
2129                         
2130                 free_compbuf(stackbuf);
2131         }
2132 }
2133
2134 static bNodeType cmp_node_sephsva= {
2135         /* type code   */       CMP_NODE_SEPHSVA,
2136         /* name        */       "Separate HSVA",
2137         /* width+range */       80, 40, 140,
2138         /* class+opts  */       NODE_CLASS_CONVERTOR, 0,
2139         /* input sock  */       cmp_node_sephsva_in,
2140         /* output sock */       cmp_node_sephsva_out,
2141         /* storage     */       "",
2142         /* execfunc    */       node_composit_exec_sephsva
2143         
2144 };
2145
2146 /* **************** COMBINE RGBA ******************** */
2147 static bNodeSocketType cmp_node_combrgba_in[]= {
2148         {       SOCK_VALUE, 1, "R",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
2149         {       SOCK_VALUE, 1, "G",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
2150         {       SOCK_VALUE, 1, "B",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
2151         {       SOCK_VALUE, 1, "A",                     1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
2152         {       -1, 0, ""       }
2153 };
2154 static bNodeSocketType cmp_node_combrgba_out[]= {
2155         {       SOCK_RGBA, 0, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
2156         {       -1, 0, ""       }
2157 };
2158
2159 static void do_combrgba(bNode *node, float *out, float *in1, float *in2, float *in3, float *in4)
2160 {
2161         out[0] = in1[0];
2162         out[1] = in2[0];
2163         out[2] = in3[0];
2164         out[3] = in4[0];
2165 }
2166
2167 static void node_composit_exec_combrgba(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
2168 {
2169         /* stack order out: 1 rgba channels */
2170         /* stack order in: 4 value channels */
2171         
2172         /* input no image? then only color operation */
2173         if((in[0]->data==NULL) && (in[1]->data==NULL) && (in[2]->data==NULL) && (in[3]->data==NULL)) {
2174                 out[0]->vec[0] = in[0]->vec[0];
2175                 out[0]->vec[1] = in[1]->vec[0];
2176                 out[0]->vec[2] = in[2]->vec[0];
2177                 out[0]->vec[3] = in[3]->vec[0];
2178         }
2179         else {
2180                 /* make output size of first available input image */
2181                 CompBuf *cbuf;
2182                 CompBuf *stackbuf;
2183
2184                 /* allocate a CompBuf the size of the first available input */
2185                 if (in[0]->data) cbuf = in[0]->data;
2186                 else if (in[1]->data) cbuf = in[1]->data;
2187                 else if (in[2]->data) cbuf = in[2]->data;
2188                 else cbuf = in[3]->data;
2189                 
2190                 stackbuf = alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs
2191                 
2192                 composit4_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, 
2193                                                                   in[2]->data, in[2]->vec, in[3]->data, in[3]->vec, 
2194                                                                   do_combrgba, CB_VAL, CB_VAL, CB_VAL, CB_VAL);
2195                 
2196                 out[0]->data= stackbuf;
2197         }       
2198 }
2199
2200 static bNodeType cmp_node_combrgba= {
2201         /* type code   */       CMP_NODE_COMBRGBA,
2202         /* name        */       "Combine RGBA",
2203         /* width+range */       80, 40, 140,
2204         /* class+opts  */       NODE_CLASS_CONVERTOR, NODE_OPTIONS,
2205         /* input sock  */       cmp_node_combrgba_in,
2206         /* output sock */       cmp_node_combrgba_out,
2207         /* storage     */       "",
2208         /* execfunc    */       node_composit_exec_combrgba
2209         
2210 };
2211
2212 /* **************** SET ALPHA ******************** */
2213 static bNodeSocketType cmp_node_setalpha_in[]= {
2214         {       SOCK_RGBA, 1, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
2215         {       SOCK_VALUE, 1, "Alpha",                 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
2216         {       -1, 0, ""       }
2217 };
2218 static bNodeSocketType cmp_node_setalpha_out[]= {
2219         {       SOCK_RGBA, 0, "Image",  0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f},
2220         {       -1, 0, ""       }
2221 };
2222
2223 static void node_composit_exec_setalpha(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
2224 {
2225         /* stack order out: RGBA image */
2226         /* stack order in: col, alpha */
2227         
2228         /* input no image? then only color operation */
2229         if(in[0]->data==NULL) {
2230                 out[0]->vec[0] = in[0]->vec[0];
2231                 out[0]->vec[1] = in[0]->vec[1];
2232                 out[0]->vec[2] = in[0]->vec[2];
2233                 out[0]->vec[3] = in[1]->vec[0];
2234         }
2235         else {
2236                 /* make output size of input image */
2237                 CompBuf *cbuf= in[0]->data;
2238                 CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs
2239                 
2240                 if(in[1]->data==NULL && in[1]->vec[0]==1.0f) {
2241                         /* pass on image */
2242                         composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_copy_rgb, CB_RGBA);
2243                 }
2244                 else {
2245                         /* send an compbuf or a value to set as alpha - composit2_pixel_processor handles choosing the right one */
2246                         composit2_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_copy_a_rgba, CB_RGBA, CB_VAL);
2247                 }
2248         
2249                 out[0]->data= stackbuf;
2250         }
2251 }
2252
2253 static bNodeType cmp_node_setalpha= {
2254         /* type code   */       CMP_NODE_SETALPHA,
2255         /* name        */       "Set Alpha",
2256         /* width+range */       120, 40, 140,
2257         /* class+opts  */       NODE_CLASS_CONVERTOR, NODE_OPTIONS,
2258         /* input sock  */       cmp_node_setalpha_in,
2259         /* output sock */       cmp_node_setalpha_out,
2260         /* storage     */       "",
2261         /* execfunc    */       node_composit_exec_setalpha
2262         
2263 };
2264
2265 /* **************** ALPHAOVER ******************** */
2266 static bNodeSocketType cmp_node_alphaover_in[]= {
2267         {       SOCK_VALUE, 0, "Fac",                   1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f},
2268         {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
2269         {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
2270         {       -1, 0, ""       }
2271 };
2272 static bNodeSocketType cmp_node_alphaover_out[]= {
2273         {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
2274         {       -1, 0, ""       }
2275 };
2276
2277 static void do_alphaover_premul(bNode *node, float *out, float *src, float *over, float *fac)
2278 {
2279         
2280         if(over[3]<=0.0f) {
2281                 QUATCOPY(out, src);
2282         }
2283         else if(*fac==1.0f && over[3]>=1.0f) {
2284                 QUATCOPY(out, over);
2285         }
2286         else {
2287                 float mul= 1.0f - *fac*over[3];
2288
2289                 out[0]= (mul*src[0]) + *fac*over[0];
2290                 out[1]= (mul*src[1]) + *fac*over[1];
2291                 out[2]= (mul*src[2]) + *fac*over[2];
2292                 out[3]= (mul*src[3]) + *fac*over[3];
2293         }       
2294 }
2295
2296 /* result will be still premul, but the over part is premulled */
2297 static void do_alphaover_key(bNode *node, float *out, float *src, float *over, float *fac)
2298 {
2299         
2300         if(over[3]<=0.0f) {
2301                 QUATCOPY(out, src);
2302         }
2303         else if(*fac==1.0f && over[3]>=1.0f) {
2304                 QUATCOPY(out, over);
2305         }
2306         else {
2307                 float premul= fac[0]*over[3];
2308                 float mul= 1.0f - premul;
2309
2310                 out[0]= (mul*src[0]) + premul*over[0];
2311                 out[1]= (mul*src[1]) + premul*over[1];
2312                 out[2]= (mul*src[2]) + premul*over[2];
2313                 out[3]= (mul*src[3]) + fac[0]*over[3];
2314         }
2315 }
2316
2317
2318 static void node_composit_exec_alphaover(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
2319 {
2320         /* stack order in: col col */
2321         /* stack order out: col */
2322         if(out[0]->hasoutput==0) 
2323                 return;
2324         
2325         /* input no image? then only color operation */
2326         if(in[1]->data==NULL) {
2327                 do_alphaover_premul(node, out[0]->vec, in[1]->vec, in[2]->vec, in[0]->vec);
2328         }
2329         else {
2330                 /* make output size of input image */
2331                 CompBuf *cbuf= in[1]->data;
2332                 CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs
2333                 
2334                 if(node->custom1)
2335                         composit3_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[2]->data, in[2]->vec, in[0]->data, in[0]->vec, do_alphaover_key, CB_RGBA, CB_RGBA, CB_VAL);
2336                 else
2337                         composit3_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[2]->data, in[2]->vec, in[0]->data, in[0]->vec, do_alphaover_premul, CB_RGBA, CB_RGBA, CB_VAL);
2338                 
2339                 out[0]->data= stackbuf;
2340         }
2341 }
2342
2343 /* custom1: convert 'over' to premul */
2344 static bNodeType cmp_node_alphaover= {
2345         /* type code   */       CMP_NODE_ALPHAOVER,
2346         /* name        */       "AlphaOver",
2347         /* width+range */       80, 40, 120,
2348         /* class+opts  */       NODE_CLASS_OP_COLOR, NODE_OPTIONS,
2349         /* input sock  */       cmp_node_alphaover_in,
2350         /* output sock */       cmp_node_alphaover_out,
2351         /* storage     */       "",
2352         /* execfunc    */       node_composit_exec_alphaover
2353         
2354 };
2355
2356 /* **************** Z COMBINE ******************** */
2357     /* lazy coder note: node->custom1 is abused to send signal */
2358 static bNodeSocketType cmp_node_zcombine_in[]= {
2359         {       SOCK_RGBA, 1, "Image",          0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
2360         {       SOCK_VALUE, 1, "Z",                     0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 10000.0f},
2361         {       SOCK_RGBA, 1, "Image",          0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
2362         {       SOCK_VALUE, 1, "Z",                     0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 10000.0f},
2363         {       -1, 0, ""       }
2364 };
2365 static bNodeSocketType cmp_node_zcombine_out[]= {
2366         {       SOCK_RGBA, 0, "Image",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
2367         {       SOCK_VALUE, 1, "Z",                     0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 10000.0f},
2368         {       -1, 0, ""       }
2369 };
2370
2371 static void do_zcombine_mask(bNode *node, float *out, float *z1, float *z2)
2372 {
2373         if(*z1 > *z2) {
2374                 *out= 1.0f;
2375                 if(node->custom1)
2376                         *z1= *z2;
2377         }
2378 }
2379
2380 static void do_zcombine_add(bNode *node, float *out, float *col1, float *col2, float *acol)
2381 {
2382         float alpha= *acol;
2383         float malpha= 1.0f - alpha;
2384         
2385         out[0]= malpha*col1[0] + alpha*col2[0];
2386         out[1]= malpha*col1[1] + alpha*col2[1];
2387         out[2]= malpha*col1[2] + alpha*col2[2];
2388         out[3]= malpha*col1[3] + alpha*col2[3];
2389 }
2390
2391 static void node_composit_exec_zcombine(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
2392 {
2393         /* stack order in: col z col z */
2394         /* stack order out: col z */
2395         if(out[0]->hasoutput==0) 
2396                 return;
2397         
2398         /* no input image; do nothing now */
2399         if(in[0]->data==NULL) {
2400                 return;
2401         }
2402         else {
2403                 /* make output size of first input image */
2404                 CompBuf *cbuf= in[0]->data;
2405                 CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs
2406                 CompBuf *zbuf, *mbuf;
2407                 float *fp;
2408                 int x;
2409                 char *aabuf;
2410                 
2411                 if(out[1]->hasoutput) {
2412                         /* copy or make a buffer for for the first z value, here we write result in */
2413                         if(in[1]->data)
2414                                 zbuf= dupalloc_compbuf(in[1]->data);
2415                         else {
2416                                 float *zval;
2417                                 int tot= cbuf->x*cbuf->y;
2418                                 
2419                                 zbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1);
2420                                 for(zval= zbuf->rect; tot; tot--, zval++)
2421                                         *zval= in[1]->vec[0];
2422                         }
2423                         /* lazy coder hack */
2424                         node->custom1= 1;
2425                 }
2426                 else {
2427                         node->custom1= 0;
2428                         zbuf= in[1]->data;
2429                 }
2430                 
2431                 /* make a mask based on comparison, optionally write zvalue */
2432                 mbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1);
2433                 composit2_pixel_processor(node, mbuf, zbuf, in[1]->vec, in[3]->data, in[3]->vec, do_zcombine_mask, CB_VAL, CB_VAL);
2434                 
2435                 /* convert to char */
2436                 aabuf= MEM_mallocN(cbuf->x*cbuf->y, "aa buf");
2437                 fp= mbuf->rect;
2438                 for(x= cbuf->x*cbuf->y-1; x>=0; x--)
2439                         if(fp[x]==0.0f) aabuf[x]= 0;
2440                         else aabuf[x]= 255;
2441                 
2442                 antialias_tagbuf(cbuf->x, cbuf->y, aabuf);
2443                 
2444                 /* convert to float */
2445                 fp= mbuf->rect;
2446                 for(x= cbuf->x*cbuf->y-1; x>=0; x--)
2447                         if(aabuf[x]>1)
2448                                 fp[x]= (1.0f/255.0f)*(float)aabuf[x];
2449                 
2450                 composit3_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[2]->data, in[2]->vec, mbuf, NULL, 
2451                                                                   do_zcombine_add, CB_RGBA, CB_RGBA, CB_VAL);
2452                 /* free */
2453                 free_compbuf(mbuf);
2454                 MEM_freeN(aabuf);
2455                 
2456                 out[0]->data= stackbuf;
2457                 if(node->custom1)
2458                         out[1]->data= zbuf;
2459         }
2460 }
2461
2462 static bNodeType cmp_node_zcombine= {
2463         /* type code   */       CMP_NODE_ZCOMBINE,
2464         /* name        */       "Z Combine",
2465         /* width+range */       80, 40, 120,
2466         /* class+opts  */       NODE_CLASS_OP_COLOR, NODE_OPTIONS,
2467         /* input sock  */       cmp_node_zcombine_in,
2468         /* output sock */       cmp_node_zcombine_out,
2469         /* storage     */       "",
2470         /* execfunc    */       node_composit_exec_zcombine
2471         
2472 };
2473
2474 /* **************** MAP VALUE ******************** */
2475 static bNodeSocketType cmp_node_map_value_in[]= {
2476         {       SOCK_VALUE, 1, "Value",                 1.0f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
2477         {       -1, 0, ""       }
2478 };
2479 static bNodeSocketType cmp_node_map_value_out[]= {
2480         {       SOCK_VALUE, 0, "Value",                 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
2481         {       -1, 0, ""       }
2482 };
2483
2484 static void do_map_value(bNode *node, float *out, float *src)
2485 {
2486         TexMapping *texmap= node->storage;
2487         
2488         out[0]= (src[0] + texmap->loc[0])*texmap->size[0];
2489         if(texmap->flag & TEXMAP_CLIP_MIN)
2490                 if(out[0]<texmap->min[0])
2491                         out[0]= texmap->min[0];
2492         if(texmap->flag & TEXMAP_CLIP_MAX)
2493                 if(out[0]>texmap->max[0])
2494                         out[0]= texmap->max[0];
2495 }
2496
2497 static void node_composit_exec_map_value(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
2498 {
2499         /* stack order in: valbuf */
2500         /* stack order out: valbuf */
2501         if(out[0]->hasoutput==0) return;
2502         
2503         /* input no image? then only value operation */
2504         if(in[0]->data==NULL) {
2505                 do_map_value(node, out[0]->vec, in[0]->vec);
2506         }
2507         else {
2508                 /* make output size of input image */
2509                 CompBuf *cbuf= in[0]->data;
2510                 CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); // allocs
2511                 
2512                 composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_map_value, CB_VAL);
2513                 
2514                 out[0]->data= stackbuf;
2515         }
2516 }
2517
2518 static bNodeType cmp_node_map_value= {
2519         /* type code   */       CMP_NODE_MAP_VALUE,
2520         /* name        */       "Map Value",
2521         /* width+range */       100, 60, 150,
2522         /* class+opts  */       NODE_CLASS_OP_VECTOR, NODE_OPTIONS,
2523         /* input sock  */       cmp_node_map_value_in,
2524         /* output sock */       cmp_node_map_value_out,
2525         /* storage     */       "TexMapping",
2526         /* execfunc    */       node_composit_exec_map_value
2527         
2528 };
2529
2530 /* **************** BLUR ******************** */
2531 static bNodeSocketType cmp_node_blur_in[]= {
2532         {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
2533         {       SOCK_VALUE, 1, "Size",                  1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
2534         {       -1, 0, ""       }
2535 };
2536 static bNodeSocketType cmp_node_blur_out[]= {
2537         {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
2538         {       -1, 0, ""       }
2539 };
2540
2541 static float *make_gausstab(int filtertype, int rad)
2542 {
2543         float *gausstab, sum, val;
2544         int i, n;
2545         
2546         n = 2 * rad + 1;
2547         
2548         gausstab = (float *) MEM_mallocN(n * sizeof(float), "gauss");
2549         
2550         sum = 0.0f;
2551         for (i = -rad; i <= rad; i++) {
2552                 val= RE_filter_value(filtertype, (float)i/(float)rad);
2553                 sum += val;
2554                 gausstab[i+rad] = val;
2555         }
2556         
2557         sum= 1.0f/sum;
2558         for(i=0; i<n; i++)
2559                 gausstab[i]*= sum;
2560         
2561         return gausstab;
2562 }
2563
2564 static float *make_bloomtab(int rad)
2565 {
2566         float *bloomtab, val;
2567         int i, n;
2568         
2569         n = 2 * rad + 1;
2570         
2571         bloomtab = (float *) MEM_mallocN(n * sizeof(float), "bloom");
2572         
2573         for (i = -rad; i <= rad; i++) {
2574                 val = pow(1.0 - fabs((float)i)/((float)rad), 4.0);
2575                 bloomtab[i+rad] = val;
2576         }
2577         
2578         return bloomtab;
2579 }
2580
2581 /* both input images of same type, either 4 or 1 channel */
2582 static void blur_single_image(CompBuf *new, CompBuf *img, float scale, NodeBlurData *nbd)
2583 {
2584         CompBuf *work;
2585         register float sum, val;
2586         float rval, gval, bval, aval;
2587         float *gausstab, *gausstabcent;
2588         int rad, imgx= img->x, imgy= img->y;
2589         int x, y, pix= img->type;
2590         int i, bigstep;
2591         float *src, *dest;
2592
2593         /* helper image */
2594         work= alloc_compbuf(imgx, imgy, img->type, 1); // allocs
2595         
2596         /* horizontal */
2597         rad = scale*(float)nbd->sizex;
2598         if(rad>imgx/2)
2599                 rad= imgx/2;
2600         else if(rad<1) 
2601                 rad= 1;
2602
2603         gausstab= make_gausstab(nbd->filtertype, rad);
2604         gausstabcent= gausstab+rad;
2605         
2606         for (y = 0; y < imgy; y++) {
2607                 float *srcd= img->rect + pix*(y*img->x);
2608                 
2609                 dest = work->rect + pix*(y * img->x);
2610                 
2611                 for (x = 0; x < imgx ; x++) {
2612                         int minr= x-rad<0?-x:-rad;
2613                         int maxr= x+rad>imgx?imgx-x:rad;
2614                         
2615                         src= srcd + pix*(x+minr);
2616                         
2617                         sum= gval = rval= bval= aval= 0.0f;
2618                         for (i= minr; i < maxr; i++) {
2619                                 val= gausstabcent[i];
2620                                 sum+= val;
2621                                 rval += val * (*src++);
2622                                 if(pix==4) {
2623                                         gval += val * (*src++);
2624                                         bval += val * (*src++);
2625                                         aval += val * (*src++);
2626                                 }
2627                         }
2628                         sum= 1.0f/sum;
2629                         *dest++ = rval*sum;
2630                         if(pix==4) {
2631                                 *dest++ = gval*sum;
2632                                 *dest++ = bval*sum;
2633                                 *dest++ = aval*sum;
2634                         }
2635                 }
2636         }
2637         
2638         /* vertical */
2639         MEM_freeN(gausstab);
2640         
2641         rad = scale*(float)nbd->sizey;
2642         if(rad>imgy/2)
2643                 rad= imgy/2;
2644         else if(rad<1) 
2645                 rad= 1;
2646
2647         gausstab= make_gausstab(nbd->filtertype, rad);
2648         gausstabcent= gausstab+rad;
2649         
2650         bigstep = pix*imgx;
2651         for (x = 0; x < imgx; x++) {
2652                 float *srcd= work->rect + pix*x;
2653                 
2654                 dest = new->rect + pix*x;
2655                 
2656                 for (y = 0; y < imgy ; y++) {
2657                         int minr= y-rad<0?-y:-rad;
2658                         int maxr= y+rad>imgy?imgy-y:rad;
2659                         
2660                         src= srcd + bigstep*(y+minr);
2661                         
2662                         sum= gval = rval= bval= aval= 0.0f;
2663                         for (i= minr; i < maxr; i++) {
2664                                 val= gausstabcent[i];
2665                                 sum+= val;
2666                                 rval += val * src[0];
2667                                 if(pix==4) {
2668                                         gval += val * src[1];
2669                                         bval += val * src[2];
2670                                         aval += val * src[3];
2671                                 }
2672                                 src += bigstep;
2673                         }
2674                         sum= 1.0f/sum;
2675                         dest[0] = rval*sum;
2676                         if(pix==4) {
2677                                 dest[1] = gval*sum;
2678                                 dest[2] = bval*sum;
2679                                 dest[3] = aval*sum;
2680                         }
2681                         dest+= bigstep;
2682                 }
2683         }
2684         
2685         free_compbuf(work);
2686         MEM_freeN(gausstab);
2687 }
2688
2689 /* reference has to be mapped 0-1, and equal in size */
2690 static void bloom_with_reference(CompBuf *new, CompBuf *img, CompBuf *ref, float fac, NodeBlurData *nbd)
2691 {
2692         CompBuf *wbuf;
2693         register float val;
2694         float radxf, radyf;
2695         float **maintabs;
2696         float *gausstabx, *gausstabcenty;
2697         float *gausstaby, *gausstabcentx;
2698         int radx, rady, imgx= img->x, imgy= img->y;
2699         int x, y;
2700         int i, j;
2701         float *src, *dest, *wb;
2702         
2703         wbuf= alloc_compbuf(imgx, imgy, CB_VAL, 1);
2704         
2705         /* horizontal */
2706         radx = (float)nbd->sizex;
2707         if(radx>imgx/2)
2708                 radx= imgx/2;
2709         else if(radx<1) 
2710                 radx= 1;
2711         
2712         /* vertical */
2713         rady = (float)nbd->sizey;
2714         if(rady>imgy/2)
2715                 rady= imgy/2;
2716         else if(rady<1) 
2717                 rady= 1;
2718         
2719         x= MAX2(radx, rady);
2720         maintabs= MEM_mallocN(x*sizeof(void *), "gauss array");
2721         for(i= 0; i<x; i++)
2722                 maintabs[i]= make_bloomtab(i+1);
2723                 
2724         /* vars to store before we go */
2725 //      refd= ref->rect;
2726         src= img->rect;
2727         
2728         radxf= (float)radx;
2729         radyf= (float)rady;
2730         
2731         for (y = 0; y < imgy; y++) {
2732                 for (x = 0; x < imgx ; x++, src+=4) {//, refd++) {
2733                         
2734 //                      int refradx= (int)(refd[0]*radxf);
2735 //                      int refrady= (int)(refd[0]*radyf);
2736                         
2737                         int refradx= (int)(radxf*0.3f*src[3]*(src[0]+src[1]+src[2]));
2738                         int refrady= (int)(radyf*0.3f*src[3]*(src[0]+src[1]+src[2]));
2739                         
2740                         if(refradx>radx) refradx= radx;
2741                         else if(refradx<1) refradx= 1;
2742                         if(refrady>rady) refrady= rady;
2743                         else if(refrady<1) refrady= 1;
2744                         
2745                         if(refradx==1 && refrady==1) {
2746                                 wb= wbuf->rect + ( y*imgx + x);
2747                                 dest= new->rect + 4*( y*imgx + x);
2748                                 wb[0]+= 1.0f;
2749                                 dest[0] += src[0];
2750                                 dest[1] += src[1];
2751                                 dest[2] += src[2];
2752                                 dest[3] += src[3];
2753                         }
2754                         else {
2755                                 int minxr= x-refradx<0?-x:-refradx;
2756                                 int maxxr= x+refradx>imgx?imgx-x:refradx;
2757                                 int minyr= y-refrady<0?-y:-refrady;
2758                                 int maxyr= y+refrady>imgy?imgy-y:refrady;
2759                                 
2760                                 float *destd= new->rect + 4*( (y + minyr)*imgx + x + minxr);
2761                                 float *wbufd= wbuf->rect + ( (y + minyr)*imgx + x + minxr);
2762                                 
2763                                 gausstabx= maintabs[refradx-1];
2764                                 gausstabcentx= gausstabx+refradx;
2765                                 gausstaby= maintabs[refrady-1];
2766                                 gausstabcenty= gausstaby+refrady;
2767                                 
2768                                 for (i= minyr; i < maxyr; i++, destd+= 4*imgx, wbufd+= imgx) {
2769                                         dest= destd;
2770                                         wb= wbufd;
2771                                         for (j= minxr; j < maxxr; j++, dest+=4, wb++) {
2772                                                 
2773                                                 val= gausstabcenty[i]*gausstabcentx[j];
2774                                                 wb[0]+= val;
2775                                                 dest[0] += val * src[0];
2776                                                 dest[1] += val * src[1];
2777                                                 dest[2] += val * src[2];
2778                                                 dest[3] += val * src[3];
2779                                         }
2780                                 }
2781                         }
2782                 }
2783         }
2784         
2785         x= imgx*imgy;
2786         dest= new->rect;
2787         wb= wbuf->rect;
2788         while(x--) {
2789                 val= 1.0f/wb[0];
2790                 dest[0]*= val;
2791                 dest[1]*= val;
2792                 dest[2]*= val;
2793                 dest[3]*= val;
2794                 wb++;
2795                 dest+= 4;
2796         }
2797         
2798         free_compbuf(wbuf);
2799         
2800         x= MAX2(radx, rady);
2801         for(i= 0; i<x; i++)
2802                 MEM_freeN(maintabs[i]);
2803         MEM_freeN(maintabs);
2804         
2805 }
2806
2807 /* only accepts RGBA buffers */
2808 static void gamma_correct_compbuf(CompBuf *img, int inversed)
2809 {
2810         float *drect;
2811         int x;
2812         
2813         if(img->type!=CB_RGBA) return;
2814         
2815         drect= img->rect;
2816         if(inversed) {
2817                 for(x=img->x*img->y; x>0; x--, drect+=4) {
2818                         if(drect[0]>0.0f) drect[0]= sqrt(drect[0]); else drect[0]= 0.0f;
2819                         if(drect[1]>0.0f) drect[1]= sqrt(drect[1]); else drect[1]= 0.0f;
2820                         if(drect[2]>0.0f) drect[2]= sqrt(drect[2]); else drect[2]= 0.0f;
2821                 }
2822         }
2823         else {
2824                 for(x=img->x*img->y; x>0; x--, drect+=4) {
2825                         if(drect[0]>0.0f) drect[0]*= drect[0]; else drect[0]= 0.0f;
2826                         if(drect[1]>0.0f) drect[1]*= drect[1]; else drect[1]= 0.0f;
2827                         if(drect[2]>0.0f) drect[2]*= drect[2]; else drect[2]= 0.0f;
2828                 }
2829         }
2830 }
2831 #if 0
2832 static float hexagon_filter(float fi, float fj)
2833 {
2834         fi= fabs(fi);
2835         fj= fabs(fj);
2836         
2837         if(fj>0.33f) {
2838                 fj= (fj-0.33f)/0.66f;
2839                 if(fi+fj>1.0f)
2840                         return 0.0f;
2841                 else
2842                         return 1.0f;
2843         }
2844         else return 1.0f;
2845 }
2846 #endif
2847
2848 /* uses full filter, no horizontal/vertical optimize possible */
2849 /* both images same type, either 1 or 4 channels */
2850 static void bokeh_single_image(CompBuf *new, CompBuf *img, float fac, NodeBlurData *nbd)
2851 {
2852         register float val;
2853         float radxf, radyf;
2854         float *gausstab, *dgauss;
2855         int radx, rady, imgx= img->x, imgy= img->y;
2856         int x, y, pix= img->type;
2857         int i, j, n;
2858         float *src= NULL, *dest, *srcd= NULL;
2859         
2860         /* horizontal */
2861         radxf = fac*(float)nbd->sizex;
2862         if(radxf>imgx/2.0f)
2863                 radxf= imgx/2.0f;
2864         else if(radxf<1.0f) 
2865                 radxf= 1.0f;
2866         
2867         /* vertical */
2868         radyf = fac*(float)nbd->sizey;
2869         if(radyf>imgy/2.0f)
2870                 radyf= imgy/2.0f;
2871         else if(radyf<1.0f) 
2872                 radyf= 1.0f;
2873         
2874         radx= ceil(radxf);
2875         rady= ceil(radyf);
2876         
2877         n = (2*radx+1)*(2*rady+1);
2878         
2879         /* create a full filter image */
2880         gausstab= MEM_mallocN(sizeof(float)*n, "filter tab");
2881         dgauss= gausstab;
2882         val= 0.0f;
2883         for(j=-rady; j<=rady; j++) {
2884                 for(i=-radx; i<=radx; i++, dgauss++) {
2885                         float fj= (float)j/radyf;
2886                         float fi= (float)i/radxf;
2887                         float dist= sqrt(fj*fj + fi*fi);
2888                         
2889                 //*dgauss= hexagon_filter(fi, fj);
2890                         *dgauss= RE_filter_value(nbd->filtertype, 2.0f*dist - 1.0f);
2891
2892                         val+= *dgauss;
2893                 }
2894         }
2895
2896         if(val!=0.0f) {
2897                 val= 1.0f/val;
2898                 for(j= n -1; j>=0; j--)
2899                         gausstab[j]*= val;
2900         }
2901         else gausstab[4]= 1.0f;
2902         
2903         for (y = -rady+1; y < imgy+rady-1; y++) {
2904                 
2905                 if(y<=0) srcd= img->rect;
2906                 else if(y<imgy) srcd+= pix*imgx;
2907                 else srcd= img->rect + pix*(imgy-1)*imgx;
2908                         
2909                 for (x = -radx+1; x < imgx+radx-1 ; x++) {
2910                         int minxr= x-radx<0?-x:-radx;
2911                         int maxxr= x+radx>=imgx?imgx-x-1:radx;
2912                         int minyr= y-rady<0?-y:-rady;
2913                         int maxyr= y+rady>imgy-1?imgy-y-1:rady;
2914                         
2915                         float *destd= new->rect + pix*( (y + minyr)*imgx + x + minxr);
2916                         float *dgausd= gausstab + (minyr+rady)*2*radx + minxr+radx;
2917                         
2918                         if(x<=0) src= srcd;
2919                         else if(x<imgx) src+= pix;
2920                         else src= srcd + pix*(imgx-1);
2921                         
2922                         for (i= minyr; i <=maxyr; i++, destd+= pix*imgx, dgausd+= 2*radx + 1) {
2923                                 dest= destd;
2924                                 dgauss= dgausd;
2925                                 for (j= minxr; j <=maxxr; j++, dest+=pix, dgauss++) {
2926                                         val= *dgauss;
2927                                         if(val!=0.0f) {
2928                                                 dest[0] += val * src[0];
2929                                                 if(pix>1) {
2930                                                         dest[1] += val * src[1];
2931                                                         dest[2] += val * src[2];
2932                                                         dest[3] += val * src[3];
2933                                                 }
2934                                         }
2935                                 }
2936                         }
2937                 }
2938         }
2939         
2940         MEM_freeN(gausstab);
2941 }
2942
2943
2944 /* reference has to be mapped 0-1, and equal in size */
2945 static void blur_with_reference(CompBuf *new, CompBuf *img, CompBuf *ref, NodeBlurData *nbd)
2946 {
2947         CompBuf *blurbuf, *ref_use;
2948         register float sum, val;
2949         float rval, gval, bval, aval, radxf, radyf;
2950         float **maintabs;
2951         float *gausstabx, *gausstabcenty;
2952         float *gausstaby, *gausstabcentx;
2953         int radx, rady, imgx= img->x, imgy= img->y;
2954         int x, y, pix= img->type;
2955         int i, j;
2956         float *src, *dest, *refd, *blurd;
2957
2958         if(ref->x!=img->x && ref->y!=img->y)
2959                 return;
2960         
2961         ref_use= typecheck_compbuf(ref, CB_VAL);
2962         
2963         /* trick is; we blur the reference image... but only works with clipped values*/
2964         blurbuf= alloc_compbuf(imgx, imgy, CB_VAL, 1);
2965         blurd= blurbuf->rect;
2966         refd= ref_use->rect;
2967         for(x= imgx*imgy; x>0; x--, refd++, blurd++) {
2968                 if(refd[0]<0.0f) blurd[0]= 0.0f;
2969                 else if(refd[0]>1.0f) blurd[0]= 1.0f;
2970                 else blurd[0]= refd[0];
2971         }
2972         
2973         blur_single_image(blurbuf, blurbuf, 1.0f, nbd);
2974         
2975         /* horizontal */
2976         radx = (float)nbd->sizex;
2977         if(radx>imgx/2)
2978                 radx= imgx/2;
2979         else if(radx<1) 
2980                 radx= 1;
2981         
2982         /* vertical */
2983         rady = (float)nbd->sizey;
2984         if(rady>imgy/2)
2985                 rady= imgy/2;
2986         else if(rady<1) 
2987                 rady= 1;
2988         
2989         x= MAX2(radx, rady);
2990         maintabs= MEM_mallocN(x*sizeof(void *), "gauss array");
2991         for(i= 0; i<x; i++)
2992                 maintabs[i]= make_gausstab(nbd->filtertype, i+1);
2993         
2994         refd= blurbuf->rect;
2995         dest= new->rect;
2996         radxf= (float)radx;
2997         radyf= (float)rady;
2998         
2999         for (y = 0; y < imgy; y++) {
3000                 for (x = 0; x < imgx ; x++, dest+=pix, refd++) {
3001                         int refradx= (int)(refd[0]*radxf);
3002                         int refrady= (int)(refd[0]*radyf);
3003                         
3004                         if(refradx>radx) refradx= radx;
3005                         else if(refradx<1) refradx= 1;
3006                         if(refrady>rady) refrady= rady;
3007                         else if(refrady<1) refrady= 1;
3008
3009                         if(refradx==1 && refrady==1) {
3010                                 src= img->rect + pix*( y*imgx + x);
3011                                 if(pix==1)
3012                                         dest[0]= src[0];
3013                                 else
3014                                         QUATCOPY(dest, src);