Blender V2.61 - r43446

node_composite_blur.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version. 
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2006 Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): Campbell Barton, Alfredo de Greef, David Millan Escriva,
00024  * Juho Vepsäläinen
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00034 #include "node_composite_util.h"
00035 
00036 /* **************** BLUR ******************** */
00037 static bNodeSocketTemplate cmp_node_blur_in[]= {
00038     {   SOCK_RGBA, 1, "Image",          1.0f, 1.0f, 1.0f, 1.0f},
00039     {   SOCK_FLOAT, 1, "Size",          1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
00040     {   -1, 0, ""   }
00041 };
00042 static bNodeSocketTemplate cmp_node_blur_out[]= {
00043     {   SOCK_RGBA, 0, "Image"},
00044     {   -1, 0, ""   }
00045 };
00046 
00047 static float *make_gausstab(int filtertype, int rad)
00048 {
00049     float *gausstab, sum, val;
00050     int i, n;
00051     
00052     n = 2 * rad + 1;
00053     
00054     gausstab = (float *) MEM_mallocN(n * sizeof(float), "gauss");
00055     
00056     sum = 0.0f;
00057     for (i = -rad; i <= rad; i++) {
00058         val= RE_filter_value(filtertype, (float)i/(float)rad);
00059         sum += val;
00060         gausstab[i+rad] = val;
00061     }
00062     
00063     sum= 1.0f/sum;
00064     for(i=0; i<n; i++)
00065         gausstab[i]*= sum;
00066     
00067     return gausstab;
00068 }
00069 
00070 static float *make_bloomtab(int rad)
00071 {
00072     float *bloomtab, val;
00073     int i, n;
00074     
00075     n = 2 * rad + 1;
00076     
00077     bloomtab = (float *) MEM_mallocN(n * sizeof(float), "bloom");
00078     
00079     for (i = -rad; i <= rad; i++) {
00080         val = powf(1.0f - fabsf((float)i)/((float)rad), 4.0f);
00081         bloomtab[i+rad] = val;
00082     }
00083     
00084     return bloomtab;
00085 }
00086 
00087 /* both input images of same type, either 4 or 1 channel */
00088 static void blur_single_image(bNode *node, CompBuf *new, CompBuf *img, float scale)
00089 {
00090     NodeBlurData *nbd= node->storage;
00091     CompBuf *work;
00092     register float sum, val;
00093     float rval, gval, bval, aval;
00094     float *gausstab, *gausstabcent;
00095     int rad, imgx= img->x, imgy= img->y;
00096     int x, y, pix= img->type;
00097     int i, bigstep;
00098     float *src, *dest;
00099     
00100     /* helper image */
00101     work= alloc_compbuf(imgx, imgy, img->type, 1); /* allocs */
00102 
00103     /* horizontal */
00104     if(nbd->sizex == 0) {
00105         memcpy(work->rect, img->rect, sizeof(float) * img->type * imgx * imgy);
00106     }
00107     else {
00108         rad = scale*(float)nbd->sizex;
00109         if(rad>imgx/2)
00110             rad= imgx/2;
00111         else if(rad<1) 
00112             rad= 1;
00113         
00114         gausstab= make_gausstab(nbd->filtertype, rad);
00115         gausstabcent= gausstab+rad;
00116         
00117         for (y = 0; y < imgy; y++) {
00118             float *srcd= img->rect + pix*(y*img->x);
00119             
00120             dest = work->rect + pix*(y * img->x);
00121             
00122             for (x = 0; x < imgx ; x++) {
00123                 int minr= x-rad<0?-x:-rad;
00124                 int maxr= x+rad>imgx?imgx-x:rad;
00125                 
00126                 src= srcd + pix*(x+minr);
00127                 
00128                 sum= gval = rval= bval= aval= 0.0f;
00129                 for (i= minr; i < maxr; i++) {
00130                     val= gausstabcent[i];
00131                     sum+= val;
00132                     rval += val * (*src++);
00133                     if(pix==4) {
00134                         gval += val * (*src++);
00135                         bval += val * (*src++);
00136                         aval += val * (*src++);
00137                     }
00138                 }
00139                 sum= 1.0f/sum;
00140                 *dest++ = rval*sum;
00141                 if(pix==4) {
00142                     *dest++ = gval*sum;
00143                     *dest++ = bval*sum;
00144                     *dest++ = aval*sum;
00145                 }
00146             }
00147             if(node->exec & NODE_BREAK)
00148                 break;
00149         }
00150         
00151         /* vertical */
00152         MEM_freeN(gausstab);
00153     }
00154     
00155     if(nbd->sizey == 0) {
00156         memcpy(new->rect, work->rect, sizeof(float) * img->type * imgx * imgy);
00157     }
00158     else {
00159         rad = scale*(float)nbd->sizey;
00160         if(rad>imgy/2)
00161             rad= imgy/2;
00162         else if(rad<1) 
00163             rad= 1;
00164     
00165         gausstab= make_gausstab(nbd->filtertype, rad);
00166         gausstabcent= gausstab+rad;
00167         
00168         bigstep = pix*imgx;
00169         for (x = 0; x < imgx; x++) {
00170             float *srcd= work->rect + pix*x;
00171             
00172             dest = new->rect + pix*x;
00173             
00174             for (y = 0; y < imgy ; y++) {
00175                 int minr= y-rad<0?-y:-rad;
00176                 int maxr= y+rad>imgy?imgy-y:rad;
00177                 
00178                 src= srcd + bigstep*(y+minr);
00179                 
00180                 sum= gval = rval= bval= aval= 0.0f;
00181                 for (i= minr; i < maxr; i++) {
00182                     val= gausstabcent[i];
00183                     sum+= val;
00184                     rval += val * src[0];
00185                     if(pix==4) {
00186                         gval += val * src[1];
00187                         bval += val * src[2];
00188                         aval += val * src[3];
00189                     }
00190                     src += bigstep;
00191                 }
00192                 sum= 1.0f/sum;
00193                 dest[0] = rval*sum;
00194                 if(pix==4) {
00195                     dest[1] = gval*sum;
00196                     dest[2] = bval*sum;
00197                     dest[3] = aval*sum;
00198                 }
00199                 dest+= bigstep;
00200             }
00201             if(node->exec & NODE_BREAK)
00202                 break;
00203         }
00204         MEM_freeN(gausstab);
00205     }
00206 
00207     free_compbuf(work);
00208 }
00209 
00210 /* reference has to be mapped 0-1, and equal in size */
00211 static void bloom_with_reference(CompBuf *new, CompBuf *img, CompBuf *UNUSED(ref), float UNUSED(fac), NodeBlurData *nbd)
00212 {
00213     CompBuf *wbuf;
00214     register float val;
00215     float radxf, radyf;
00216     float **maintabs;
00217     float *gausstabx, *gausstabcenty;
00218     float *gausstaby, *gausstabcentx;
00219     int radx, rady, imgx= img->x, imgy= img->y;
00220     int x, y;
00221     int i, j;
00222     float *src, *dest, *wb;
00223     
00224     wbuf= alloc_compbuf(imgx, imgy, CB_VAL, 1);
00225     
00226     /* horizontal */
00227     radx = (float)nbd->sizex;
00228     if(radx>imgx/2)
00229         radx= imgx/2;
00230     else if(radx<1) 
00231         radx= 1;
00232     
00233     /* vertical */
00234     rady = (float)nbd->sizey;
00235     if(rady>imgy/2)
00236         rady= imgy/2;
00237     else if(rady<1) 
00238         rady= 1;
00239     
00240     x= MAX2(radx, rady);
00241     maintabs= MEM_mallocN(x*sizeof(void *), "gauss array");
00242     for(i= 0; i<x; i++)
00243         maintabs[i]= make_bloomtab(i+1);
00244         
00245     /* vars to store before we go */
00246 //  refd= ref->rect;
00247     src= img->rect;
00248     
00249     radxf= (float)radx;
00250     radyf= (float)rady;
00251     
00252     for (y = 0; y < imgy; y++) {
00253         for (x = 0; x < imgx ; x++, src+=4) {//, refd++) {
00254             
00255 //          int refradx= (int)(refd[0]*radxf);
00256 //          int refrady= (int)(refd[0]*radyf);
00257             
00258             int refradx= (int)(radxf*0.3f*src[3]*(src[0]+src[1]+src[2]));
00259             int refrady= (int)(radyf*0.3f*src[3]*(src[0]+src[1]+src[2]));
00260             
00261             if(refradx>radx) refradx= radx;
00262             else if(refradx<1) refradx= 1;
00263             if(refrady>rady) refrady= rady;
00264             else if(refrady<1) refrady= 1;
00265             
00266             if(refradx==1 && refrady==1) {
00267                 wb= wbuf->rect + ( y*imgx + x);
00268                 dest= new->rect + 4*( y*imgx + x);
00269                 wb[0]+= 1.0f;
00270                 dest[0] += src[0];
00271                 dest[1] += src[1];
00272                 dest[2] += src[2];
00273                 dest[3] += src[3];
00274             }
00275             else {
00276                 int minxr= x-refradx<0?-x:-refradx;
00277                 int maxxr= x+refradx>imgx?imgx-x:refradx;
00278                 int minyr= y-refrady<0?-y:-refrady;
00279                 int maxyr= y+refrady>imgy?imgy-y:refrady;
00280                 
00281                 float *destd= new->rect + 4*( (y + minyr)*imgx + x + minxr);
00282                 float *wbufd= wbuf->rect + ( (y + minyr)*imgx + x + minxr);
00283                 
00284                 gausstabx= maintabs[refradx-1];
00285                 gausstabcentx= gausstabx+refradx;
00286                 gausstaby= maintabs[refrady-1];
00287                 gausstabcenty= gausstaby+refrady;
00288                 
00289                 for (i= minyr; i < maxyr; i++, destd+= 4*imgx, wbufd+= imgx) {
00290                     dest= destd;
00291                     wb= wbufd;
00292                     for (j= minxr; j < maxxr; j++, dest+=4, wb++) {
00293                         
00294                         val= gausstabcenty[i]*gausstabcentx[j];
00295                         wb[0]+= val;
00296                         dest[0] += val * src[0];
00297                         dest[1] += val * src[1];
00298                         dest[2] += val * src[2];
00299                         dest[3] += val * src[3];
00300                     }
00301                 }
00302             }
00303         }
00304     }
00305     
00306     x= imgx*imgy;
00307     dest= new->rect;
00308     wb= wbuf->rect;
00309     while(x--) {
00310         val= 1.0f/wb[0];
00311         dest[0]*= val;
00312         dest[1]*= val;
00313         dest[2]*= val;
00314         dest[3]*= val;
00315         wb++;
00316         dest+= 4;
00317     }
00318     
00319     free_compbuf(wbuf);
00320     
00321     x= MAX2(radx, rady);
00322     for(i= 0; i<x; i++)
00323         MEM_freeN(maintabs[i]);
00324     MEM_freeN(maintabs);
00325     
00326 }
00327 
00328 #if 0
00329 static float hexagon_filter(float fi, float fj)
00330 {
00331     fi= fabs(fi);
00332     fj= fabs(fj);
00333     
00334     if(fj>0.33f) {
00335         fj= (fj-0.33f)/0.66f;
00336         if(fi+fj>1.0f)
00337             return 0.0f;
00338         else
00339             return 1.0f;
00340     }
00341     else return 1.0f;
00342 }
00343 #endif
00344 
00345 /* uses full filter, no horizontal/vertical optimize possible */
00346 /* both images same type, either 1 or 4 channels */
00347 static void bokeh_single_image(bNode *node, CompBuf *new, CompBuf *img, float fac)
00348 {
00349     NodeBlurData *nbd= node->storage;
00350     register float val;
00351     float radxf, radyf;
00352     float *gausstab, *dgauss;
00353     int radx, rady, imgx= img->x, imgy= img->y;
00354     int x, y, pix= img->type;
00355     int i, j, n;
00356     float *src= NULL, *dest, *srcd= NULL;
00357     
00358     /* horizontal */
00359     radxf = fac*(float)nbd->sizex;
00360     if(radxf>imgx/2.0f)
00361         radxf= imgx/2.0f;
00362     else if(radxf<1.0f) 
00363         radxf= 1.0f;
00364     
00365     /* vertical */
00366     radyf = fac*(float)nbd->sizey;
00367     if(radyf>imgy/2.0f)
00368         radyf= imgy/2.0f;
00369     else if(radyf<1.0f) 
00370         radyf= 1.0f;
00371     
00372     radx= ceil(radxf);
00373     rady= ceil(radyf);
00374     
00375     n = (2*radx+1)*(2*rady+1);
00376     
00377     /* create a full filter image */
00378     gausstab= MEM_mallocN(sizeof(float)*n, "filter tab");
00379     dgauss= gausstab;
00380     val= 0.0f;
00381     for(j=-rady; j<=rady; j++) {
00382         for(i=-radx; i<=radx; i++, dgauss++) {
00383             float fj= (float)j/radyf;
00384             float fi= (float)i/radxf;
00385             float dist= sqrt(fj*fj + fi*fi);
00386             
00387         //*dgauss= hexagon_filter(fi, fj);
00388             *dgauss= RE_filter_value(nbd->filtertype, dist);
00389 
00390             val+= *dgauss;
00391         }
00392     }
00393 
00394     if(val!=0.0f) {
00395         val= 1.0f/val;
00396         for(j= n -1; j>=0; j--)
00397             gausstab[j]*= val;
00398     }
00399     else gausstab[4]= 1.0f;
00400     
00401     for (y = -rady+1; y < imgy+rady-1; y++) {
00402         
00403         if(y<=0) srcd= img->rect;
00404         else if(y<imgy) srcd+= pix*imgx;
00405         else srcd= img->rect + pix*(imgy-1)*imgx;
00406             
00407         for (x = -radx+1; x < imgx+radx-1 ; x++) {
00408             int minxr= x-radx<0?-x:-radx;
00409             int maxxr= x+radx>=imgx?imgx-x-1:radx;
00410             int minyr= y-rady<0?-y:-rady;
00411             int maxyr= y+rady>imgy-1?imgy-y-1:rady;
00412             
00413             float *destd= new->rect + pix*( (y + minyr)*imgx + x + minxr);
00414             float *dgausd= gausstab + (minyr+rady)*(2*radx+1) + minxr+radx;
00415             
00416             if(x<=0) src= srcd;
00417             else if(x<imgx) src+= pix;
00418             else src= srcd + pix*(imgx-1);
00419             
00420             for (i= minyr; i <=maxyr; i++, destd+= pix*imgx, dgausd+= 2*radx + 1) {
00421                 dest= destd;
00422                 dgauss= dgausd;
00423                 for (j= minxr; j <=maxxr; j++, dest+=pix, dgauss++) {
00424                     val= *dgauss;
00425                     if(val!=0.0f) {
00426                         dest[0] += val * src[0];
00427                         if(pix>1) {
00428                             dest[1] += val * src[1];
00429                             dest[2] += val * src[2];
00430                             dest[3] += val * src[3];
00431                         }
00432                     }
00433                 }
00434             }
00435         }
00436         if(node->exec & NODE_BREAK)
00437             break;
00438     }
00439     
00440     MEM_freeN(gausstab);
00441 }
00442 
00443 
00444 /* reference has to be mapped 0-1, and equal in size */
00445 static void blur_with_reference(bNode *node, CompBuf *new, CompBuf *img, CompBuf *ref)
00446 {
00447     NodeBlurData *nbd= node->storage;
00448     CompBuf *blurbuf, *ref_use;
00449     register float sum, val;
00450     float rval, gval, bval, aval, radxf, radyf;
00451     float **maintabs;
00452     float *gausstabx, *gausstabcenty;
00453     float *gausstaby, *gausstabcentx;
00454     int radx, rady, imgx= img->x, imgy= img->y;
00455     int x, y, pix= img->type;
00456     int i, j;
00457     float *src, *dest, *refd, *blurd;
00458     float defcol[4] = {1.0f, 1.0f, 1.0f, 1.0f}; /* default color for compbuf_get_pixel */
00459     float proccol[4];   /* local color if compbuf is procedural */
00460     int refradx, refrady;
00461 
00462     if(ref->x!=img->x || ref->y!=img->y)
00463         return;
00464     
00465     ref_use= typecheck_compbuf(ref, CB_VAL);
00466     
00467     /* trick is; we blur the reference image... but only works with clipped values*/
00468     blurbuf= alloc_compbuf(imgx, imgy, CB_VAL, 1);
00469     blurbuf->xof= ref_use->xof;
00470     blurbuf->yof= ref_use->yof;
00471     blurd= blurbuf->rect;
00472     refd= ref_use->rect;
00473     for(x= imgx*imgy; x>0; x--, refd++, blurd++) {
00474         if(refd[0]<0.0f) blurd[0]= 0.0f;
00475         else if(refd[0]>1.0f) blurd[0]= 1.0f;
00476         else blurd[0]= refd[0];
00477     }
00478     
00479     blur_single_image(node, blurbuf, blurbuf, 1.0f);
00480     
00481     /* horizontal */
00482     radx = (float)nbd->sizex;
00483     if(radx>imgx/2)
00484         radx= imgx/2;
00485     else if(radx<1) 
00486         radx= 1;
00487     
00488     /* vertical */
00489     rady = (float)nbd->sizey;
00490     if(rady>imgy/2)
00491         rady= imgy/2;
00492     else if(rady<1) 
00493         rady= 1;
00494     
00495     x= MAX2(radx, rady);
00496     maintabs= MEM_mallocN(x*sizeof(void *), "gauss array");
00497     for(i= 0; i<x; i++)
00498         maintabs[i]= make_gausstab(nbd->filtertype, i+1);
00499     
00500     dest= new->rect;
00501     radxf= (float)radx;
00502     radyf= (float)rady;
00503     
00504     for (y = 0; y < imgy; y++) {
00505         for (x = 0; x < imgx ; x++, dest+=pix) {
00506             refd= compbuf_get_pixel(blurbuf, defcol, proccol, x-blurbuf->xrad, y-blurbuf->yrad, blurbuf->xrad, blurbuf->yrad);
00507             refradx= (int)(refd[0]*radxf);
00508             refrady= (int)(refd[0]*radyf);
00509             
00510             if(refradx>radx) refradx= radx;
00511             else if(refradx<1) refradx= 1;
00512             if(refrady>rady) refrady= rady;
00513             else if(refrady<1) refrady= 1;
00514 
00515             if(refradx==1 && refrady==1) {
00516                 src= img->rect + pix*( y*imgx + x);
00517                 if(pix==1)
00518                     dest[0]= src[0];
00519                 else
00520                     copy_v4_v4(dest, src);
00521             }
00522             else {
00523                 int minxr= x-refradx<0?-x:-refradx;
00524                 int maxxr= x+refradx>imgx?imgx-x:refradx;
00525                 int minyr= y-refrady<0?-y:-refrady;
00526                 int maxyr= y+refrady>imgy?imgy-y:refrady;
00527     
00528                 float *srcd= img->rect + pix*( (y + minyr)*imgx + x + minxr);
00529                 
00530                 gausstabx= maintabs[refradx-1];
00531                 gausstabcentx= gausstabx+refradx;
00532                 gausstaby= maintabs[refrady-1];
00533                 gausstabcenty= gausstaby+refrady;
00534 
00535                 sum= gval = rval= bval= aval= 0.0f;
00536                 
00537                 for (i= minyr; i < maxyr; i++, srcd+= pix*imgx) {
00538                     src= srcd;
00539                     for (j= minxr; j < maxxr; j++, src+=pix) {
00540                     
00541                         val= gausstabcenty[i]*gausstabcentx[j];
00542                         sum+= val;
00543                         rval += val * src[0];
00544                         if(pix>1) {
00545                             gval += val * src[1];
00546                             bval += val * src[2];
00547                             aval += val * src[3];
00548                         }
00549                     }
00550                 }
00551                 sum= 1.0f/sum;
00552                 dest[0] = rval*sum;
00553                 if(pix>1) {
00554                     dest[1] = gval*sum;
00555                     dest[2] = bval*sum;
00556                     dest[3] = aval*sum;
00557                 }
00558             }
00559         }
00560         if(node->exec & NODE_BREAK)
00561             break;
00562     }
00563     
00564     free_compbuf(blurbuf);
00565     
00566     x= MAX2(radx, rady);
00567     for(i= 0; i<x; i++)
00568         MEM_freeN(maintabs[i]);
00569     MEM_freeN(maintabs);
00570     
00571     if(ref_use!=ref)
00572         free_compbuf(ref_use);
00573 }
00574 
00575 static void node_composit_exec_blur(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
00576 {
00577     CompBuf *new, *img= in[0]->data;
00578     NodeBlurData *nbd= node->storage;
00579     
00580     if(img==NULL) return;
00581     
00582     /* store image in size that is needed for absolute/relative conversions on ui level */
00583     nbd->image_in_width= img->x;
00584     nbd->image_in_height= img->y;
00585     
00586     if(out[0]->hasoutput==0) return;
00587     
00588     if(nbd->relative) {
00589         if (nbd->aspect==CMP_NODE_BLUR_ASPECT_NONE) {
00590             nbd->sizex= (int)(nbd->percentx*0.01f*nbd->image_in_width);
00591             nbd->sizey= (int)(nbd->percenty*0.01f*nbd->image_in_height);
00592         }
00593         else if (nbd->aspect==CMP_NODE_BLUR_ASPECT_Y) {
00594             nbd->sizex= (int)(nbd->percentx*0.01f*nbd->image_in_width);
00595             nbd->sizey= (int)(nbd->percenty*0.01f*nbd->image_in_width);
00596         }
00597         else if (nbd->aspect==CMP_NODE_BLUR_ASPECT_X) {
00598             nbd->sizex= (int)(nbd->percentx*0.01f*nbd->image_in_height);
00599             nbd->sizey= (int)(nbd->percenty*0.01f*nbd->image_in_height);
00600         }
00601     }
00602 
00603     if (nbd->sizex==0 && nbd->sizey==0) {
00604         new= pass_on_compbuf(img);
00605         out[0]->data= new;
00606     }
00607     else if (nbd->filtertype == R_FILTER_FAST_GAUSS) {
00608         CompBuf *new, *img = in[0]->data;
00609         // TODO: can this be mapped with reference, too?
00610         const float sx = ((float)nbd->sizex*in[1]->vec[0])/2.0f, sy = ((float)nbd->sizey*in[1]->vec[0])/2.0f;
00611         int c;
00612 
00613         if ((img==NULL) || (out[0]->hasoutput==0)) return;
00614 
00615         if (img->type == CB_VEC2)
00616             new = typecheck_compbuf(img, CB_VAL);
00617         else if (img->type == CB_VEC3)
00618             new = typecheck_compbuf(img, CB_RGBA);
00619         else
00620             new = dupalloc_compbuf(img);
00621 
00622         if ((sx == sy) && (sx > 0.f)) {
00623             for (c=0; c<new->type; ++c)
00624                 IIR_gauss(new, sx, c, 3);
00625         }
00626         else {
00627             if (sx > 0.f) {
00628                 for (c=0; c<new->type; ++c)
00629                     IIR_gauss(new, sx, c, 1);
00630             }
00631             if (sy > 0.f) {
00632                 for (c=0; c<new->type; ++c)
00633                     IIR_gauss(new, sy, c, 2);
00634             }
00635         }
00636         out[0]->data = new;
00637         
00638     } else { 
00639         /* All non fast gauss blur methods */
00640         if(img->type==CB_VEC2 || img->type==CB_VEC3) {
00641             img= typecheck_compbuf(in[0]->data, CB_RGBA);
00642         }
00643         
00644         /* if fac input, we do it different */
00645         if(in[1]->data) {
00646             CompBuf *gammabuf;
00647             
00648             /* make output size of input image */
00649             new= alloc_compbuf(img->x, img->y, img->type, 1); /* allocs */
00650             
00651             /* accept image offsets from other nodes */
00652             new->xof = img->xof;
00653             new->yof = img->yof;
00654             
00655             if(nbd->gamma) {
00656                 gammabuf= dupalloc_compbuf(img);
00657                 gamma_correct_compbuf(gammabuf, 0);
00658             }
00659             else gammabuf= img;
00660             
00661             blur_with_reference(node, new, gammabuf, in[1]->data);
00662             
00663             if(nbd->gamma) {
00664                 gamma_correct_compbuf(new, 1);
00665                 free_compbuf(gammabuf);
00666             }
00667             if(node->exec & NODE_BREAK) {
00668                 free_compbuf(new);
00669                 new= NULL;
00670             }
00671             out[0]->data= new;
00672         }
00673         else {
00674             
00675             if(in[1]->vec[0]<=0.001f) { /* time node inputs can be a tiny value */
00676                 new= pass_on_compbuf(img);
00677             }
00678             else {
00679                 CompBuf *gammabuf;
00680                 
00681                 /* make output size of input image */
00682                 new= alloc_compbuf(img->x, img->y, img->type, 1); /* allocs */
00683                 
00684                 /* accept image offsets from other nodes */
00685                 new->xof = img->xof;
00686                 new->yof = img->yof;
00687                     
00688                 if(nbd->gamma) {
00689                     gammabuf= dupalloc_compbuf(img);
00690                     gamma_correct_compbuf(gammabuf, 0);
00691                 }
00692                 else gammabuf= img;
00693                 
00694                 if(nbd->bokeh)
00695                     bokeh_single_image(node, new, gammabuf, in[1]->vec[0]);
00696                 else if(1)
00697                     blur_single_image(node, new, gammabuf, in[1]->vec[0]);
00698                 else    /* bloom experimental... */
00699                     bloom_with_reference(new, gammabuf, NULL, in[1]->vec[0], nbd);
00700                 
00701                 if(nbd->gamma) {
00702                     gamma_correct_compbuf(new, 1);
00703                     free_compbuf(gammabuf);
00704                 }
00705                 if(node->exec & NODE_BREAK) {
00706                     free_compbuf(new);
00707                     new= NULL;
00708                 }
00709             }
00710             out[0]->data= new;
00711         }
00712         if(img!=in[0]->data)
00713             free_compbuf(img);
00714     }
00715 
00716     generate_preview(data, node, out[0]->data);
00717 }
00718 
00719 static void node_composit_init_blur(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp))
00720 {
00721     node->storage= MEM_callocN(sizeof(NodeBlurData), "node blur data");
00722 }
00723 
00724 void register_node_type_cmp_blur(bNodeTreeType *ttype)
00725 {
00726     static bNodeType ntype;
00727 
00728     node_type_base(ttype, &ntype, CMP_NODE_BLUR, "Blur", NODE_CLASS_OP_FILTER, NODE_PREVIEW|NODE_OPTIONS);
00729     node_type_socket_templates(&ntype, cmp_node_blur_in, cmp_node_blur_out);
00730     node_type_size(&ntype, 120, 80, 200);
00731     node_type_init(&ntype, node_composit_init_blur);
00732     node_type_storage(&ntype, "NodeBlurData", node_free_standard_storage, node_copy_standard_storage);
00733     node_type_exec(&ntype, node_composit_exec_blur);
00734 
00735     nodeRegisterType(ttype, &ntype);
00736 }