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