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