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