style cleanup: follow style guide for formatting of if/for/while loops, and else...
[blender.git] / source / blender / nodes / composite / nodes / node_composite_blur.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2006 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Campbell Barton, Alfredo de Greef, David Millan Escriva,
24  * Juho Vepsäläinen
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 /** \file blender/nodes/composite/nodes/node_composite_blur.c
30  *  \ingroup cmpnodes
31  */
32
33
34 #include "node_composite_util.h"
35
36 /* **************** BLUR ******************** */
37 static bNodeSocketTemplate cmp_node_blur_in[]= {
38         {       SOCK_RGBA, 1, "Image",                  1.0f, 1.0f, 1.0f, 1.0f},
39         {       SOCK_FLOAT, 1, "Size",                  1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
40         {       -1, 0, ""       }
41 };
42 static bNodeSocketTemplate cmp_node_blur_out[]= {
43         {       SOCK_RGBA, 0, "Image"},
44         {       -1, 0, ""       }
45 };
46
47 static float *make_gausstab(int filtertype, int rad)
48 {
49         float *gausstab, sum, val;
50         int i, n;
51         
52         n = 2 * rad + 1;
53         
54         gausstab = (float *) MEM_mallocN(n * sizeof(float), "gauss");
55         
56         sum = 0.0f;
57         for (i = -rad; i <= rad; i++) {
58                 val= RE_filter_value(filtertype, (float)i/(float)rad);
59                 sum += val;
60                 gausstab[i+rad] = val;
61         }
62         
63         sum= 1.0f/sum;
64         for (i=0; i<n; i++)
65                 gausstab[i]*= sum;
66         
67         return gausstab;
68 }
69
70 static float *make_bloomtab(int rad)
71 {
72         float *bloomtab, val;
73         int i, n;
74         
75         n = 2 * rad + 1;
76         
77         bloomtab = (float *) MEM_mallocN(n * sizeof(float), "bloom");
78         
79         for (i = -rad; i <= rad; i++) {
80                 val = powf(1.0f - fabsf((float)i)/((float)rad), 4.0f);
81                 bloomtab[i+rad] = val;
82         }
83         
84         return bloomtab;
85 }
86
87 /* both input images of same type, either 4 or 1 channel */
88 static void blur_single_image(bNode *node, CompBuf *new, CompBuf *img, float scale)
89 {
90         NodeBlurData *nbd= node->storage;
91         CompBuf *work;
92         register float sum, val;
93         float rval, gval, bval, aval;
94         float *gausstab, *gausstabcent;
95         int rad, imgx= img->x, imgy= img->y;
96         int x, y, pix= img->type;
97         int i, bigstep;
98         float *src, *dest;
99         
100         /* helper image */
101         work= alloc_compbuf(imgx, imgy, img->type, 1); /* allocs */
102
103         /* horizontal */
104         if (nbd->sizex == 0) {
105                 memcpy(work->rect, img->rect, sizeof(float) * img->type * imgx * imgy);
106         }
107         else {
108                 rad = scale*(float)nbd->sizex;
109                 if (rad>imgx/2)
110                         rad= imgx/2;
111                 else if (rad<1)
112                         rad= 1;
113                 
114                 gausstab= make_gausstab(nbd->filtertype, rad);
115                 gausstabcent= gausstab+rad;
116                 
117                 for (y = 0; y < imgy; y++) {
118                         float *srcd= img->rect + pix*(y*img->x);
119                         
120                         dest = work->rect + pix*(y * img->x);
121                         
122                         for (x = 0; x < imgx ; x++) {
123                                 int minr= x-rad<0?-x:-rad;
124                                 int maxr= x+rad>imgx?imgx-x:rad;
125                                 
126                                 src= srcd + pix*(x+minr);
127                                 
128                                 sum= gval = rval= bval= aval= 0.0f;
129                                 for (i= minr; i < maxr; i++) {
130                                         val= gausstabcent[i];
131                                         sum+= val;
132                                         rval += val * (*src++);
133                                         if (pix==4) {
134                                                 gval += val * (*src++);
135                                                 bval += val * (*src++);
136                                                 aval += val * (*src++);
137                                         }
138                                 }
139                                 sum= 1.0f/sum;
140                                 *dest++ = rval*sum;
141                                 if (pix==4) {
142                                         *dest++ = gval*sum;
143                                         *dest++ = bval*sum;
144                                         *dest++ = aval*sum;
145                                 }
146                         }
147                         if (node->exec & NODE_BREAK)
148                                 break;
149                 }
150                 
151                 /* vertical */
152                 MEM_freeN(gausstab);
153         }
154         
155         if (nbd->sizey == 0) {
156                 memcpy(new->rect, work->rect, sizeof(float) * img->type * imgx * imgy);
157         }
158         else {
159                 rad = scale*(float)nbd->sizey;
160                 if (rad>imgy/2)
161                         rad= imgy/2;
162                 else if (rad<1)
163                         rad= 1;
164         
165                 gausstab= make_gausstab(nbd->filtertype, rad);
166                 gausstabcent= gausstab+rad;
167                 
168                 bigstep = pix*imgx;
169                 for (x = 0; x < imgx; x++) {
170                         float *srcd= work->rect + pix*x;
171                         
172                         dest = new->rect + pix*x;
173                         
174                         for (y = 0; y < imgy ; y++) {
175                                 int minr= y-rad<0?-y:-rad;
176                                 int maxr= y+rad>imgy?imgy-y:rad;
177                                 
178                                 src= srcd + bigstep*(y+minr);
179                                 
180                                 sum= gval = rval= bval= aval= 0.0f;
181                                 for (i= minr; i < maxr; i++) {
182                                         val= gausstabcent[i];
183                                         sum+= val;
184                                         rval += val * src[0];
185                                         if (pix==4) {
186                                                 gval += val * src[1];
187                                                 bval += val * src[2];
188                                                 aval += val * src[3];
189                                         }
190                                         src += bigstep;
191                                 }
192                                 sum= 1.0f/sum;
193                                 dest[0] = rval*sum;
194                                 if (pix==4) {
195                                         dest[1] = gval*sum;
196                                         dest[2] = bval*sum;
197                                         dest[3] = aval*sum;
198                                 }
199                                 dest+= bigstep;
200                         }
201                         if (node->exec & NODE_BREAK)
202                                 break;
203                 }
204                 MEM_freeN(gausstab);
205         }
206
207         free_compbuf(work);
208 }
209
210 /* reference has to be mapped 0-1, and equal in size */
211 static void bloom_with_reference(CompBuf *new, CompBuf *img, CompBuf *UNUSED(ref), float UNUSED(fac), NodeBlurData *nbd)
212 {
213         CompBuf *wbuf;
214         register float val;
215         float radxf, radyf;
216         float **maintabs;
217         float *gausstabx, *gausstabcenty;
218         float *gausstaby, *gausstabcentx;
219         int radx, rady, imgx= img->x, imgy= img->y;
220         int x, y;
221         int i, j;
222         float *src, *dest, *wb;
223         
224         wbuf= alloc_compbuf(imgx, imgy, CB_VAL, 1);
225         
226         /* horizontal */
227         radx = (float)nbd->sizex;
228         if (radx>imgx/2)
229                 radx= imgx/2;
230         else if (radx<1)
231                 radx= 1;
232         
233         /* vertical */
234         rady = (float)nbd->sizey;
235         if (rady>imgy/2)
236                 rady= imgy/2;
237         else if (rady<1)
238                 rady= 1;
239         
240         x= MAX2(radx, rady);
241         maintabs= MEM_mallocN(x*sizeof(void *), "gauss array");
242         for (i= 0; i<x; i++)
243                 maintabs[i]= make_bloomtab(i+1);
244                 
245         /* vars to store before we go */
246 //      refd= ref->rect;
247         src= img->rect;
248         
249         radxf= (float)radx;
250         radyf= (float)rady;
251         
252         for (y = 0; y < imgy; y++) {
253                 for (x = 0; x < imgx ; x++, src+=4) {//, refd++) {
254                         
255 //                      int refradx= (int)(refd[0]*radxf);
256 //                      int refrady= (int)(refd[0]*radyf);
257                         
258                         int refradx= (int)(radxf*0.3f*src[3]*(src[0]+src[1]+src[2]));
259                         int refrady= (int)(radyf*0.3f*src[3]*(src[0]+src[1]+src[2]));
260                         
261                         if (refradx>radx) refradx= radx;
262                         else if (refradx<1) refradx= 1;
263                         if (refrady>rady) refrady= rady;
264                         else if (refrady<1) refrady= 1;
265                         
266                         if (refradx==1 && refrady==1) {
267                                 wb= wbuf->rect + ( y*imgx + x);
268                                 dest= new->rect + 4*( y*imgx + x);
269                                 wb[0]+= 1.0f;
270                                 dest[0] += src[0];
271                                 dest[1] += src[1];
272                                 dest[2] += src[2];
273                                 dest[3] += src[3];
274                         }
275                         else {
276                                 int minxr= x-refradx<0?-x:-refradx;
277                                 int maxxr= x+refradx>imgx?imgx-x:refradx;
278                                 int minyr= y-refrady<0?-y:-refrady;
279                                 int maxyr= y+refrady>imgy?imgy-y:refrady;
280                                 
281                                 float *destd= new->rect + 4*( (y + minyr)*imgx + x + minxr);
282                                 float *wbufd= wbuf->rect + ( (y + minyr)*imgx + x + minxr);
283                                 
284                                 gausstabx= maintabs[refradx-1];
285                                 gausstabcentx= gausstabx+refradx;
286                                 gausstaby= maintabs[refrady-1];
287                                 gausstabcenty= gausstaby+refrady;
288                                 
289                                 for (i= minyr; i < maxyr; i++, destd+= 4*imgx, wbufd+= imgx) {
290                                         dest= destd;
291                                         wb= wbufd;
292                                         for (j= minxr; j < maxxr; j++, dest+=4, wb++) {
293                                                 
294                                                 val= gausstabcenty[i]*gausstabcentx[j];
295                                                 wb[0]+= val;
296                                                 dest[0] += val * src[0];
297                                                 dest[1] += val * src[1];
298                                                 dest[2] += val * src[2];
299                                                 dest[3] += val * src[3];
300                                         }
301                                 }
302                         }
303                 }
304         }
305         
306         x= imgx*imgy;
307         dest= new->rect;
308         wb= wbuf->rect;
309         while(x--) {
310                 val= 1.0f/wb[0];
311                 dest[0]*= val;
312                 dest[1]*= val;
313                 dest[2]*= val;
314                 dest[3]*= val;
315                 wb++;
316                 dest+= 4;
317         }
318         
319         free_compbuf(wbuf);
320         
321         x= MAX2(radx, rady);
322         for (i= 0; i<x; i++)
323                 MEM_freeN(maintabs[i]);
324         MEM_freeN(maintabs);
325         
326 }
327
328 #if 0
329 static float hexagon_filter(float fi, float fj)
330 {
331         fi= fabs(fi);
332         fj= fabs(fj);
333         
334         if (fj>0.33f) {
335                 fj= (fj-0.33f)/0.66f;
336                 if (fi+fj>1.0f)
337                         return 0.0f;
338                 else
339                         return 1.0f;
340         }
341         else return 1.0f;
342 }
343 #endif
344
345 /* uses full filter, no horizontal/vertical optimize possible */
346 /* both images same type, either 1 or 4 channels */
347 static void bokeh_single_image(bNode *node, CompBuf *new, CompBuf *img, float fac)
348 {
349         NodeBlurData *nbd= node->storage;
350         register float val;
351         float radxf, radyf;
352         float *gausstab, *dgauss;
353         int radx, rady, imgx= img->x, imgy= img->y;
354         int x, y, pix= img->type;
355         int i, j, n;
356         float *src= NULL, *dest, *srcd= NULL;
357         
358         /* horizontal */
359         radxf = fac*(float)nbd->sizex;
360         if (radxf>imgx/2.0f)
361                 radxf= imgx/2.0f;
362         else if (radxf<1.0f)
363                 radxf= 1.0f;
364         
365         /* vertical */
366         radyf = fac*(float)nbd->sizey;
367         if (radyf>imgy/2.0f)
368                 radyf= imgy/2.0f;
369         else if (radyf<1.0f)
370                 radyf= 1.0f;
371         
372         radx= ceil(radxf);
373         rady= ceil(radyf);
374         
375         n = (2*radx+1)*(2*rady+1);
376         
377         /* create a full filter image */
378         gausstab= MEM_mallocN(sizeof(float)*n, "filter tab");
379         dgauss= gausstab;
380         val= 0.0f;
381         for (j=-rady; j<=rady; j++) {
382                 for (i=-radx; i<=radx; i++, dgauss++) {
383                         float fj= (float)j/radyf;
384                         float fi= (float)i/radxf;
385                         float dist= sqrt(fj*fj + fi*fi);
386                         
387                 //*dgauss= hexagon_filter(fi, fj);
388                         *dgauss= RE_filter_value(nbd->filtertype, dist);
389
390                         val+= *dgauss;
391                 }
392         }
393
394         if (val!=0.0f) {
395                 val= 1.0f/val;
396                 for (j= n -1; j>=0; j--)
397                         gausstab[j]*= val;
398         }
399         else gausstab[4]= 1.0f;
400         
401         for (y = -rady+1; y < imgy+rady-1; y++) {
402                 
403                 if (y<=0) srcd= img->rect;
404                 else if (y<imgy) srcd+= pix*imgx;
405                 else srcd= img->rect + pix*(imgy-1)*imgx;
406                         
407                 for (x = -radx+1; x < imgx+radx-1 ; x++) {
408                         int minxr= x-radx<0?-x:-radx;
409                         int maxxr= x+radx>=imgx?imgx-x-1:radx;
410                         int minyr= y-rady<0?-y:-rady;
411                         int maxyr= y+rady>imgy-1?imgy-y-1:rady;
412                         
413                         float *destd= new->rect + pix*( (y + minyr)*imgx + x + minxr);
414                         float *dgausd= gausstab + (minyr+rady)*(2*radx+1) + minxr+radx;
415                         
416                         if (x<=0) src= srcd;
417                         else if (x<imgx) src+= pix;
418                         else src= srcd + pix*(imgx-1);
419                         
420                         for (i= minyr; i <=maxyr; i++, destd+= pix*imgx, dgausd+= 2*radx + 1) {
421                                 dest= destd;
422                                 dgauss= dgausd;
423                                 for (j= minxr; j <=maxxr; j++, dest+=pix, dgauss++) {
424                                         val= *dgauss;
425                                         if (val!=0.0f) {
426                                                 dest[0] += val * src[0];
427                                                 if (pix>1) {
428                                                         dest[1] += val * src[1];
429                                                         dest[2] += val * src[2];
430                                                         dest[3] += val * src[3];
431                                                 }
432                                         }
433                                 }
434                         }
435                 }
436                 if (node->exec & NODE_BREAK)
437                         break;
438         }
439         
440         MEM_freeN(gausstab);
441 }
442
443
444 /* reference has to be mapped 0-1, and equal in size */
445 static void blur_with_reference(bNode *node, CompBuf *new, CompBuf *img, CompBuf *ref)
446 {
447         NodeBlurData *nbd= node->storage;
448         CompBuf *blurbuf, *ref_use;
449         register float sum, val;
450         float rval, gval, bval, aval, radxf, radyf;
451         float **maintabs;
452         float *gausstabx, *gausstabcenty;
453         float *gausstaby, *gausstabcentx;
454         int radx, rady, imgx= img->x, imgy= img->y;
455         int x, y, pix= img->type;
456         int i, j;
457         float *src, *dest, *refd, *blurd;
458         float defcol[4] = {1.0f, 1.0f, 1.0f, 1.0f};     /* default color for compbuf_get_pixel */
459         float proccol[4];       /* local color if compbuf is procedural */
460         int refradx, refrady;
461
462         if (ref->x!=img->x || ref->y!=img->y)
463                 return;
464         
465         ref_use= typecheck_compbuf(ref, CB_VAL);
466         
467         /* trick is; we blur the reference image... but only works with clipped values*/
468         blurbuf= alloc_compbuf(imgx, imgy, CB_VAL, 1);
469         blurbuf->xof= ref_use->xof;
470         blurbuf->yof= ref_use->yof;
471         blurd= blurbuf->rect;
472         refd= ref_use->rect;
473         for (x= imgx*imgy; x>0; x--, refd++, blurd++) {
474                 if (refd[0]<0.0f) blurd[0]= 0.0f;
475                 else if (refd[0]>1.0f) blurd[0]= 1.0f;
476                 else blurd[0]= refd[0];
477         }
478         
479         blur_single_image(node, blurbuf, blurbuf, 1.0f);
480         
481         /* horizontal */
482         radx = (float)nbd->sizex;
483         if (radx>imgx/2)
484                 radx= imgx/2;
485         else if (radx<1)
486                 radx= 1;
487         
488         /* vertical */
489         rady = (float)nbd->sizey;
490         if (rady>imgy/2)
491                 rady= imgy/2;
492         else if (rady<1)
493                 rady= 1;
494         
495         x= MAX2(radx, rady);
496         maintabs= MEM_mallocN(x*sizeof(void *), "gauss array");
497         for (i= 0; i<x; i++)
498                 maintabs[i]= make_gausstab(nbd->filtertype, i+1);
499         
500         dest= new->rect;
501         radxf= (float)radx;
502         radyf= (float)rady;
503         
504         for (y = 0; y < imgy; y++) {
505                 for (x = 0; x < imgx ; x++, dest+=pix) {
506                         refd= compbuf_get_pixel(blurbuf, defcol, proccol, x-blurbuf->xrad, y-blurbuf->yrad, blurbuf->xrad, blurbuf->yrad);
507                         refradx= (int)(refd[0]*radxf);
508                         refrady= (int)(refd[0]*radyf);
509                         
510                         if (refradx>radx) refradx= radx;
511                         else if (refradx<1) refradx= 1;
512                         if (refrady>rady) refrady= rady;
513                         else if (refrady<1) refrady= 1;
514
515                         if (refradx==1 && refrady==1) {
516                                 src= img->rect + pix*( y*imgx + x);
517                                 if (pix==1)
518                                         dest[0]= src[0];
519                                 else
520                                         copy_v4_v4(dest, src);
521                         }
522                         else {
523                                 int minxr= x-refradx<0?-x:-refradx;
524                                 int maxxr= x+refradx>imgx?imgx-x:refradx;
525                                 int minyr= y-refrady<0?-y:-refrady;
526                                 int maxyr= y+refrady>imgy?imgy-y:refrady;
527         
528                                 float *srcd= img->rect + pix*( (y + minyr)*imgx + x + minxr);
529                                 
530                                 gausstabx= maintabs[refradx-1];
531                                 gausstabcentx= gausstabx+refradx;
532                                 gausstaby= maintabs[refrady-1];
533                                 gausstabcenty= gausstaby+refrady;
534
535                                 sum= gval = rval= bval= aval= 0.0f;
536                                 
537                                 for (i= minyr; i < maxyr; i++, srcd+= pix*imgx) {
538                                         src= srcd;
539                                         for (j= minxr; j < maxxr; j++, src+=pix) {
540                                         
541                                                 val= gausstabcenty[i]*gausstabcentx[j];
542                                                 sum+= val;
543                                                 rval += val * src[0];
544                                                 if (pix>1) {
545                                                         gval += val * src[1];
546                                                         bval += val * src[2];
547                                                         aval += val * src[3];
548                                                 }
549                                         }
550                                 }
551                                 sum= 1.0f/sum;
552                                 dest[0] = rval*sum;
553                                 if (pix>1) {
554                                         dest[1] = gval*sum;
555                                         dest[2] = bval*sum;
556                                         dest[3] = aval*sum;
557                                 }
558                         }
559                 }
560                 if (node->exec & NODE_BREAK)
561                         break;
562         }
563         
564         free_compbuf(blurbuf);
565         
566         x= MAX2(radx, rady);
567         for (i= 0; i<x; i++)
568                 MEM_freeN(maintabs[i]);
569         MEM_freeN(maintabs);
570         
571         if (ref_use!=ref)
572                 free_compbuf(ref_use);
573 }
574
575 static void node_composit_exec_blur(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
576 {
577         CompBuf *new, *img= in[0]->data;
578         NodeBlurData *nbd= node->storage;
579         
580         if (img==NULL) return;
581         
582         /* store image in size that is needed for absolute/relative conversions on ui level */
583         nbd->image_in_width= img->x;
584         nbd->image_in_height= img->y;
585         
586         if (out[0]->hasoutput==0) return;
587         
588         if (nbd->relative) {
589                 if (nbd->aspect==CMP_NODE_BLUR_ASPECT_NONE) {
590                         nbd->sizex= (int)(nbd->percentx*0.01f*nbd->image_in_width);
591                         nbd->sizey= (int)(nbd->percenty*0.01f*nbd->image_in_height);
592                 }
593                 else if (nbd->aspect==CMP_NODE_BLUR_ASPECT_Y) {
594                         nbd->sizex= (int)(nbd->percentx*0.01f*nbd->image_in_width);
595                         nbd->sizey= (int)(nbd->percenty*0.01f*nbd->image_in_width);
596                 }
597                 else if (nbd->aspect==CMP_NODE_BLUR_ASPECT_X) {
598                         nbd->sizex= (int)(nbd->percentx*0.01f*nbd->image_in_height);
599                         nbd->sizey= (int)(nbd->percenty*0.01f*nbd->image_in_height);
600                 }
601         }
602
603         if (nbd->sizex==0 && nbd->sizey==0) {
604                 new= pass_on_compbuf(img);
605                 out[0]->data= new;
606         }
607         else if (nbd->filtertype == R_FILTER_FAST_GAUSS) {
608                 CompBuf *new, *img = in[0]->data;
609                 // TODO: can this be mapped with reference, too?
610                 const float sx = ((float)nbd->sizex*in[1]->vec[0])/2.0f, sy = ((float)nbd->sizey*in[1]->vec[0])/2.0f;
611                 int c;
612
613                 if ((img==NULL) || (out[0]->hasoutput==0)) return;
614
615                 if (img->type == CB_VEC2)
616                         new = typecheck_compbuf(img, CB_VAL);
617                 else if (img->type == CB_VEC3)
618                         new = typecheck_compbuf(img, CB_RGBA);
619                 else
620                         new = dupalloc_compbuf(img);
621
622                 if ((sx == sy) && (sx > 0.f)) {
623                         for (c=0; c<new->type; ++c)
624                                 IIR_gauss(new, sx, c, 3);
625                 }
626                 else {
627                         if (sx > 0.f) {
628                                 for (c=0; c<new->type; ++c)
629                                         IIR_gauss(new, sx, c, 1);
630                         }
631                         if (sy > 0.f) {
632                                 for (c=0; c<new->type; ++c)
633                                         IIR_gauss(new, sy, c, 2);
634                         }
635                 }
636                 out[0]->data = new;
637                 
638         }
639         else {
640                 /* All non fast gauss blur methods */
641                 if (img->type==CB_VEC2 || img->type==CB_VEC3) {
642                         img= typecheck_compbuf(in[0]->data, CB_RGBA);
643                 }
644                 
645                 /* if fac input, we do it different */
646                 if (in[1]->data) {
647                         CompBuf *gammabuf;
648                         
649                         /* make output size of input image */
650                         new= alloc_compbuf(img->x, img->y, img->type, 1); /* allocs */
651                         
652                         /* accept image offsets from other nodes */
653                         new->xof = img->xof;
654                         new->yof = img->yof;
655                         
656                         if (nbd->gamma) {
657                                 gammabuf= dupalloc_compbuf(img);
658                                 gamma_correct_compbuf(gammabuf, 0);
659                         }
660                         else gammabuf= img;
661                         
662                         blur_with_reference(node, new, gammabuf, in[1]->data);
663                         
664                         if (nbd->gamma) {
665                                 gamma_correct_compbuf(new, 1);
666                                 free_compbuf(gammabuf);
667                         }
668                         if (node->exec & NODE_BREAK) {
669                                 free_compbuf(new);
670                                 new= NULL;
671                         }
672                         out[0]->data= new;
673                 }
674                 else {
675                         
676                         if (in[1]->vec[0]<=0.001f) {    /* time node inputs can be a tiny value */
677                                 new= pass_on_compbuf(img);
678                         }
679                         else {
680                                 CompBuf *gammabuf;
681                                 
682                                 /* make output size of input image */
683                                 new= alloc_compbuf(img->x, img->y, img->type, 1); /* allocs */
684                                 
685                                 /* accept image offsets from other nodes */
686                                 new->xof = img->xof;
687                                 new->yof = img->yof;
688                                         
689                                 if (nbd->gamma) {
690                                         gammabuf= dupalloc_compbuf(img);
691                                         gamma_correct_compbuf(gammabuf, 0);
692                                 }
693                                 else gammabuf= img;
694                                 
695                                 if (nbd->bokeh)
696                                         bokeh_single_image(node, new, gammabuf, in[1]->vec[0]);
697                                 else if (1)
698                                         blur_single_image(node, new, gammabuf, in[1]->vec[0]);
699                                 else    /* bloom experimental... */
700                                         bloom_with_reference(new, gammabuf, NULL, in[1]->vec[0], nbd);
701                                 
702                                 if (nbd->gamma) {
703                                         gamma_correct_compbuf(new, 1);
704                                         free_compbuf(gammabuf);
705                                 }
706                                 if (node->exec & NODE_BREAK) {
707                                         free_compbuf(new);
708                                         new= NULL;
709                                 }
710                         }
711                         out[0]->data= new;
712                 }
713                 if (img!=in[0]->data)
714                         free_compbuf(img);
715         }
716
717         generate_preview(data, node, out[0]->data);
718 }
719
720 static void node_composit_init_blur(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp))
721 {
722         node->storage= MEM_callocN(sizeof(NodeBlurData), "node blur data");
723 }
724
725 void register_node_type_cmp_blur(bNodeTreeType *ttype)
726 {
727         static bNodeType ntype;
728
729         node_type_base(ttype, &ntype, CMP_NODE_BLUR, "Blur", NODE_CLASS_OP_FILTER, NODE_PREVIEW|NODE_OPTIONS);
730         node_type_socket_templates(&ntype, cmp_node_blur_in, cmp_node_blur_out);
731         node_type_size(&ntype, 120, 80, 200);
732         node_type_init(&ntype, node_composit_init_blur);
733         node_type_storage(&ntype, "NodeBlurData", node_free_standard_storage, node_copy_standard_storage);
734         node_type_exec(&ntype, node_composit_exec_blur);
735
736         nodeRegisterType(ttype, &ntype);
737 }