1 /* === S Y N F I G ========================================================= */
2 /*! \file synfig/blur.cpp
3 ** \brief Blur Implementation File
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
10 ** This package is free software; you can redistribute it and/or
11 ** modify it under the terms of the GNU General Public License as
12 ** published by the Free Software Foundation; either version 2 of
13 ** the License, or (at your option) any later version.
15 ** This package is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 ** General Public License for more details.
21 /* ========================================================================= */
23 /* === H E A D E R S ======================================================= */
32 #include <synfig/general.h>
33 #include <synfig/surface.h>
38 #include <ETL/stringf>
41 #include <ETL/gaussian>
42 #include <ETL/boxblur>
46 /* === U S I N G =========================================================== */
50 using namespace synfig;
52 /* === M A C R O S ========================================================= */
54 /* === G L O B A L S ======================================================= */
56 /* === P R O C E D U R E S ================================================= */
58 /* === M E T H O D S ======================================================= */
59 Point Blur::operator()(const Point &pos) const
69 blurpos[0]+=(Vector::value_type)( (signed)(RAND_MAX/2)-(signed)rand() )/(Vector::value_type)(RAND_MAX) * size[0];
74 blurpos[1]+=(Vector::value_type)( (signed)(RAND_MAX/2)-(signed)rand() )/(Vector::value_type)(RAND_MAX) * size[1];
80 Angle theta=Angle::rotations((float)rand()/(float)RAND_MAX);
81 Vector::value_type mag=(float)rand()/(float)RAND_MAX;
82 Vector vect((float)Angle::cos(theta).get()*mag,(float)Angle::sin(theta).get()*mag);
84 blurpos[0]+=vect[0]*size[0];
85 blurpos[1]+=vect[1]*size[1];
91 // Not quite a true gaussian blur,
92 // but the results are close enough for me.
95 blurpos[0]+=(Vector::value_type)( (signed)(RAND_MAX/2)-(signed)rand() )/(Vector::value_type)(RAND_MAX) * size[0]*3/4;
96 blurpos[0]+=(Vector::value_type)( (signed)(RAND_MAX/2)-(signed)rand() )/(Vector::value_type)(RAND_MAX) * size[0]*3/4;
100 blurpos[1]+=(Vector::value_type)( (signed)(RAND_MAX/2)-(signed)rand() )/(Vector::value_type)(RAND_MAX) * size[1]*3/4;
101 blurpos[1]+=(Vector::value_type)( (signed)(RAND_MAX/2)-(signed)rand() )/(Vector::value_type)(RAND_MAX) * size[1]*3/4;
108 blurpos[0]+=(Vector::value_type)( (signed)(RAND_MAX/2)-(signed)rand() )/(Vector::value_type)(RAND_MAX) * size[0];
110 blurpos[1]+=(Vector::value_type)( (signed)(RAND_MAX/2)-(signed)rand() )/(Vector::value_type)(RAND_MAX) * size[1];
117 Point Blur::operator()(synfig::Real x, synfig::Real y) const
119 return (*this)(Point(x,y));
122 //blur functions to make my life easier
124 template <typename T>
125 static inline T zero()
131 inline Color zero<Color>()
133 return Color::alpha();
136 template <typename T,typename AT,class VP>
137 static void GuassianBlur_2x2(etl::surface<T,AT,VP> &surface)
142 T *SC0=new T[surface.get_w()];
144 memcpy(SC0,surface[0],surface.get_w()*sizeof(T));
146 for(y=0;y<surface.get_h();y++)
149 for(x=0;x<surface.get_w();x++)
154 surface[y][x]=(SC0[x]+Tmp2)/4;
161 template <typename T,typename AT,class VP>
162 static void GuassianBlur_3x3(etl::surface<T,AT,VP> &surface)
173 // Setup the row buffers
174 for(x=0;x<w;x++)SC0[x]=surface[0][x]*4;
175 // memcpy(SC1,surface[0],w*sizeof(T));
184 SR0=SR1=surface[y][0];
203 surface[y-1][x-1]=(SC1[x]+Tmp2)/16;
212 template <typename T,typename AT,class VP>
213 inline static void GaussianBlur_5x5_(etl::surface<T,AT,VP> &surface,T *SC0,T *SC1,T *SC2,T *SC3)
216 T Tmp1,Tmp2,SR0,SR1,SR2,SR3;
221 // Setup the row buffers
222 for(x=0;x<w;x++)SC0[x+2]=surface[0][x]*24;
223 // memset(SC0,0,(w+2)*sizeof(T));
224 memset(SC1,0,(w+2)*sizeof(T));
225 memset(SC2,0,(w+2)*sizeof(T));
226 memset(SC3,0,(w+2)*sizeof(T));
236 SR0=surface[v][0]*1.5;
263 surface[y-2][x-2]=(SC3[x]+Tmp2)/256;
270 template <typename T,typename AT,class VP>
271 inline static void GaussianBlur_5x5(etl::surface<T,AT,VP> &surface)
273 int w=surface.get_w();
280 GaussianBlur_5x5_(surface,SC0,SC1,SC2,SC3);
288 template <typename T,typename AT,class VP>
289 static void GuassianBlur_nxn(etl::surface<T,AT,VP> &surface,int n)
293 T inv_divisor=pow(2.0,(n-1));
295 inv_divisor=1.0/(inv_divisor*inv_divisor);
305 SC[i]=new T[w+half_n];
308 throw(runtime_error(strprintf(__FILE__":%d:Malloc failure",__LINE__)));
311 memset(SC[i],0,(w+half_n)*sizeof(T));
314 // Setup the first row
315 // for(x=0;x<w;x++)SC[0][x+half_n]=surface[0][x]*550.0;//*pow(2.0,(n-1))*(2.0/n);
317 for(y=0;y<h+half_n;y++)
324 memset(SR,0,(n-1)*sizeof(T));
326 // SR[0]=surface[v][0]*(2.0-1.9/n);
328 for(x=0;x<w+half_n;x++)
337 for(i=0;i<half_n;i++)
346 for(i=0;i<half_n-1;i++)
348 Tmp2=SC[i*2][x]+Tmp1;
350 Tmp1=SC[i*2+1][x]+Tmp2;
353 Tmp2=SC[n-3][x]+Tmp1;
355 if(y>=half_n&&x>=half_n)
356 surface[y-half_n][x-half_n]=(SC[n-2][x]+Tmp2)*inv_divisor;
365 template <typename T,typename AT,class VP>
366 static void GuassianBlur_2x1(etl::surface<T,AT,VP> &surface)
371 for(y=0;y<surface.get_h();y++)
374 for(x=0;x<surface.get_w();x++)
379 surface[y][x]=(Tmp2)/2;
384 template <typename T,typename AT,class VP>
385 static void GuassianBlur_3x1(etl::surface<T,AT,VP> &surface)
388 AT Tmp1,Tmp2,SR0,SR1;
390 for(y=0;y<surface.get_h();y++)
392 SR0=SR1=surface[y][0];
393 for(x=0;x<surface.get_w();x++)
403 surface[y][x-1]=(Tmp1)/4;
408 template <typename T,typename AT,class VP>
409 static void GuassianBlur_1x2(etl::surface<T,AT,VP> &surface)
414 for(x=0;x<surface.get_w();x++)
417 for(y=0;y<surface.get_h();y++)
422 surface[y][x]=(Tmp2)/2;
427 template <typename T,typename AT,class VP>
428 static void GuassianBlur_1x3(etl::surface<T,AT,VP> &surface)
431 AT Tmp1,Tmp2,SR0,SR1;
433 for(x=0;x<surface.get_w();x++)
435 SR0=SR1=surface[0][x];
436 for(y=0;y<surface.get_h();y++)
446 surface[y-1][x]=(Tmp1)/4;
451 //THE GOOD ONE!!!!!!!!!
452 bool Blur::operator()(const Surface &surface,
453 const Vector &resolution,
456 int w = surface.get_w(),
459 if(w == 0 || h == 0 || resolution[0] == 0 || resolution[1] == 0) return false;
461 const Real pw = resolution[0]/w,
462 ph = resolution[1]/h;
464 int halfsizex = (int) (abs(size[0]*.5/pw) + 1),
465 halfsizey = (int) (abs(size[1]*.5/ph) + 1);
469 SuperCallback blurcall(cb,0,5000,5000);
471 Surface worksurface(w,h);
473 //synfig::info("Blur: check surface = %s", surface_valid(surface)?"true":"false");
475 // Premultiply the alpha
480 Color a = surface[y][x];
481 a.set_r(a.get_r()*a.get_a());
482 a.set_g(a.get_g()*a.get_a());
483 a.set_b(a.get_b()*a.get_a());
484 worksurface[y][x] = a;
490 case Blur::DISC: // D I S C ----------------------------------------------------------
495 if(size[0] && size[1] && w*h>2)
498 Surface tmp_surface(worksurface);
504 //accumulate all the pixels in an ellipse of w,h about the current pixel
505 Color color=Color::alpha();
508 for(y2=-bh;y2<=bh;y2++)
510 for(x2=-bw;x2<=bw;x2++)
512 //get the floating point distance away from the origin pixel in relative coords
513 float tmp_x=(float)x2/bw;
514 float tmp_y=(float)y2/bh;
518 //ignore if it's outside of the disc
522 //cap the pixel indices to inside the surface
527 if( u >= w ) u = w-1;
530 if( v >= h ) v = h-1;
532 //accumulate the color, and # of pixels added in
533 color += tmp_surface[v][u];
538 //blend the color with the original color
539 //if(get_amount()==1.0 && get_blend_method()==Color::BLEND_STRAIGHT)
540 worksurface[y][x]=color/total;
542 // worksurface[y][x]=Color::blend(color/total,tmp_surface[y][x],get_amount(),get_blend_method());
544 if(!blurcall.amount_complete(y,h))
546 //if(cb)cb->error(strprintf(__FILE__"%d: Accelerated Renderer Failure",__LINE__));
553 //if we don't qualify for disc blur just use box blur
556 case Blur::BOX: // B O X -------------------------------------------------------
559 //synfig::info("Blur: Starting Box blur (surface valid %d)", (int)surface_valid(worksurface));
561 Surface temp_surface;
562 temp_surface.set_wh(w,h);
566 int length = halfsizex;
567 length=std::max(1,length);
569 //synfig::info("Blur: hbox blur work -> temp %d", length);
570 etl::hbox_blur(worksurface.begin(),worksurface.end(),length,temp_surface.begin());
572 else temp_surface = worksurface;
573 //synfig::info("Blur: hbox finished");
576 //Surface temp_surface2;
577 //temp_surface2.set_wh(w,h);
581 int length = halfsizey;
582 length = std::max(1,length);
584 //synfig::info("Blur: vbox blur temp -> work %d",length);
585 etl::vbox_blur(temp_surface.begin(),temp_surface.end(),length,worksurface.begin());
587 else worksurface = temp_surface;
588 //synfig::info("Blur: vbox finished");
590 //blend with the original surface
596 worksurface[y][x]=temp_surface2[y][x];//Color::blend(temp_surface2[y][x],worksurface[y][x],get_amount(),get_blend_method());
602 case Blur::FASTGAUSSIAN: // F A S T G A U S S I A N ----------------------------------------------
604 //fast gaussian is treated as a 3x3 type of thing, except expanded to work with the length
611 Surface temp_surface;
612 temp_surface.set_wh(w,h);
614 //Surface temp_surface2;
615 //temp_surface2.set_wh(w,h);
620 Real length=abs((float)w/(resolution[0]))*size[0]*0.5+1;
621 length=std::max(1.0,length);
623 //two box blurs produces: 1 2 1
624 etl::hbox_blur(worksurface.begin(),w,h,(int)(length*3/4),temp_surface.begin());
625 etl::hbox_blur(temp_surface.begin(),w,h,(int)(length*3/4),worksurface.begin());
627 //else temp_surface2=worksurface;
632 Real length=abs((float)h/(resolution[1]))*size[1]*0.5+1;
633 length=std::max(1.0,length);
635 //two box blurs produces: 1 2 1 on the horizontal 1 2 1
636 etl::vbox_blur(worksurface.begin(),w,h,(int)(length*3/4),temp_surface.begin());
637 etl::vbox_blur(temp_surface.begin(),w,h,(int)(length*3/4),worksurface.begin());
639 //else temp_surface2=temp_surface2;
646 worksurface[y][x]=temp_surface2[y][x];//Color::blend(temp_surface2[y][x],worksurface[y][x],get_amount(),get_blend_method());
652 case Blur::CROSS: // C R O S S -------------------------------------------------------
655 Surface temp_surface;
656 temp_surface.set_wh(worksurface.get_w(),worksurface.get_h());
660 int length = halfsizex;
661 length = std::max(1,length);
663 etl::hbox_blur(worksurface.begin(),worksurface.end(),length,temp_surface.begin());
665 else temp_surface = worksurface;
668 Surface temp_surface2;
669 temp_surface2.set_wh(worksurface.get_w(),worksurface.get_h());
673 int length = halfsizey;
674 length = std::max(1,length);
676 etl::vbox_blur(worksurface.begin(),worksurface.end(),length,temp_surface2.begin());
678 else temp_surface2 = worksurface;
680 //blend the two together
687 worksurface[y][x] = (temp_surface[y][x]+temp_surface2[y][x])/2;//Color::blend((temp_surface[y][x]+temp_surface2[y][x])/2,worksurface[y][x],get_amount(),get_blend_method());
694 case Blur::GAUSSIAN: // G A U S S I A N ----------------------------------------------
696 #ifndef GAUSSIAN_ADJUSTMENT
697 #define GAUSSIAN_ADJUSTMENT (0.05)
700 Real pw = (Real)w/(resolution[0]);
701 Real ph = (Real)h/(resolution[1]);
703 Surface temp_surface;
704 Surface *gauss_surface;
706 //synfig::warning("Didn't crash yet b1");
708 //if(get_amount()==1.0 && get_blend_method()==Color::BLEND_STRAIGHT)
709 gauss_surface = &worksurface;
712 temp_surface = worksurface;
713 gauss_surface = &temp_surface;
716 /* Squaring the pw and ph values
717 is necessary to insure consistent
718 results when rendered to different
720 Unfortunately, this automatically
721 squares our rendertime.
722 There has got to be a faster way...
727 int bw = (int)(abs(pw)*size[0]*GAUSSIAN_ADJUSTMENT+0.5);
728 int bh = (int)(abs(ph)*size[1]*GAUSSIAN_ADJUSTMENT+0.5);
731 Color *SC0=new class Color[w+2];
732 Color *SC1=new class Color[w+2];
733 Color *SC2=new class Color[w+2];
734 Color *SC3=new class Color[w+2];
735 memset(SC0,0,(w+2)*sizeof(Color));
736 memset(SC0,0,(w+2)*sizeof(Color));
737 memset(SC0,0,(w+2)*sizeof(Color));
738 memset(SC0,0,(w+2)*sizeof(Color));
740 //synfig::warning("Didn't crash yet b2");
745 if(!blurcall.amount_complete(max-(bw+bh),max))return false;
749 etl::gaussian_blur_5x5_(gauss_surface->begin(),gauss_surface->get_w(),gauss_surface->get_h(),SC0,SC1,SC2,SC3);
755 etl::gaussian_blur_3x3(gauss_surface->begin(),gauss_surface->end());
761 GuassianBlur_2x2(*gauss_surface);
765 //synfig::warning("Didn't crash yet bi - %d",i++);
769 if(!blurcall.amount_complete(max-(bw+bh),max))return false;
772 GuassianBlur_3x1(*gauss_surface);
778 GuassianBlur_2x1(*gauss_surface);
781 //synfig::warning("Didn't crash yet bi - %d",i++);
785 if(!blurcall.amount_complete(max-(bw+bh),max))return false;
788 GuassianBlur_1x3(*gauss_surface);
794 GuassianBlur_1x2(*gauss_surface);
797 //synfig::warning("Didn't crash yet bi - %d",i++);
805 /*if(get_amount()!=1.0 || get_blend_method()!=Color::BLEND_STRAIGHT)
808 for(y=0;y<renddesc.get_h();y++)
809 for(x=0;x<renddesc.get_w();x++)
810 worksurface[y][x]=Color::blend(temp_surface[y][x],worksurface[y][x],get_amount(),get_blend_method());
812 //synfig::warning("Didn't crash yet b end",i++);
820 // Scale up the alpha
822 //be sure the surface is of the correct size
823 //surface->set_wh(renddesc.get_w(),renddesc.get_h());
826 //divide out the alpha
831 Color a = worksurface[y][x];
834 a.set_r(a.get_r()/a.get_a());
835 a.set_g(a.get_g()/a.get_a());
836 a.set_b(a.get_b()/a.get_a());
839 else out[y][x]=Color::alpha();
843 //we are FRIGGGIN done....
844 blurcall.amount_complete(100,100);
849 bool Blur::operator()(const etl::surface<float> &surface,
850 const synfig::Vector &resolution,
851 etl::surface<float> &out) const
853 int w = surface.get_w(),
856 if(w == 0 || h == 0 || resolution[0] == 0 || resolution[1] == 0) return false;
858 const Real pw = resolution[0]/w,
859 ph = resolution[1]/h;
861 int halfsizex = (int) (abs(size[0]*.5/pw) + 1),
862 halfsizey = (int) (abs(size[1]*.5/ph) + 1);
865 SuperCallback blurcall(cb,0,5000,5000);
867 etl::surface<float> worksurface(surface);
869 //don't need to premultiply because we are dealing with ONLY alpha
873 case Blur::DISC: // D I S C ----------------------------------------------------------
878 if(size[0] && size[1] && w*h>2)
881 etl::surface<float> tmp_surface(worksurface);
887 //accumulate all the pixels in an ellipse of w,h about the current pixel
891 for(y2=-bh;y2<=bh;y2++)
893 for(x2=-bw;x2<=bw;x2++)
895 //get the floating point distance away from the origin pixel in relative coords
896 float tmp_x=(float)x2/bw;
897 float tmp_y=(float)y2/bh;
901 //ignore if it's outside of the disc
905 //cap the pixel indices to inside the surface
910 if( u >= w ) u = w-1;
913 if( v >= h ) v = h-1;
915 //accumulate the color, and # of pixels added in
916 a += tmp_surface[v][u];
921 //blend the color with the original color
922 //if(get_amount()==1.0 && get_blend_method()==Color::BLEND_STRAIGHT)
923 worksurface[y][x]=a/total;
925 // worksurface[y][x]=Color::blend(color/total,tmp_surface[y][x],get_amount(),get_blend_method());
927 if(!blurcall.amount_complete(y,h))
929 //if(cb)cb->error(strprintf(__FILE__"%d: Accelerated Renderer Failure",__LINE__));
936 //if we don't qualify for disc blur just use box blur
939 case Blur::BOX: // B O X -------------------------------------------------------
942 etl::surface<float> temp_surface;
943 temp_surface.set_wh(w,h);
947 int length = halfsizex;
948 length=std::max(1,length);
950 etl::hbox_blur(worksurface.begin(),worksurface.end(),length,temp_surface.begin());
952 else temp_surface = worksurface;
955 //etl::surface<float> temp_surface2;
956 //temp_surface2.set_wh(w,h);
960 int length = halfsizey;
961 length = std::max(1,length);
962 etl::vbox_blur(temp_surface.begin(),temp_surface.end(),length,worksurface.begin());
964 else worksurface = temp_surface;
966 //blend with the original surface
972 worksurface[y][x]=temp_surface2[y][x];//Color::blend(temp_surface2[y][x],worksurface[y][x],get_amount(),get_blend_method());
978 case Blur::FASTGAUSSIAN: // F A S T G A U S S I A N ----------------------------------------------
980 //fast gaussian is treated as a 3x3 type of thing, except expanded to work with the length
987 etl::surface<float> temp_surface;
988 temp_surface.set_wh(w,h);
990 //etl::surface<float> temp_surface2;
991 //temp_surface2.set_wh(w,h);
996 Real length=abs((float)w/(resolution[0]))*size[0]*0.5+1;
997 length=std::max(1.0,length);
999 //two box blurs produces: 1 2 1
1000 etl::hbox_blur(worksurface.begin(),w,h,(int)(length*3/4),temp_surface.begin());
1001 etl::hbox_blur(temp_surface.begin(),w,h,(int)(length*3/4),worksurface.begin());
1003 //else temp_surface2=worksurface;
1008 Real length=abs((float)h/(resolution[1]))*size[1]*0.5+1;
1009 length=std::max(1.0,length);
1011 //two box blurs produces: 1 2 1 on the horizontal 1 2 1
1012 etl::vbox_blur(worksurface.begin(),w,h,(int)(length*3/4),temp_surface.begin());
1013 etl::vbox_blur(temp_surface.begin(),w,h,(int)(length*3/4),worksurface.begin());
1015 //else temp_surface2=temp_surface2;
1022 worksurface[y][x]=temp_surface2[y][x];//Color::blend(temp_surface2[y][x],worksurface[y][x],get_amount(),get_blend_method());
1028 case Blur::CROSS: // C R O S S -------------------------------------------------------
1031 etl::surface<float> temp_surface;
1032 temp_surface.set_wh(worksurface.get_w(),worksurface.get_h());
1036 int length = halfsizex;
1037 length = std::max(1,length);
1039 etl::hbox_blur(worksurface.begin(),worksurface.end(),length,temp_surface.begin());
1041 else temp_surface = worksurface;
1044 etl::surface<float> temp_surface2;
1045 temp_surface2.set_wh(worksurface.get_w(),worksurface.get_h());
1049 int length = halfsizey;
1050 length = std::max(1,length);
1052 etl::vbox_blur(worksurface.begin(),worksurface.end(),length,temp_surface2.begin());
1054 else temp_surface2 = worksurface;
1056 //blend the two together
1063 worksurface[y][x] = (temp_surface[y][x]+temp_surface2[y][x])/2;//Color::blend((temp_surface[y][x]+temp_surface2[y][x])/2,worksurface[y][x],get_amount(),get_blend_method());
1070 case Blur::GAUSSIAN: // G A U S S I A N ----------------------------------------------
1072 #ifndef GAUSSIAN_ADJUSTMENT
1073 #define GAUSSIAN_ADJUSTMENT (0.05)
1076 Real pw = (Real)w/(resolution[0]);
1077 Real ph = (Real)h/(resolution[1]);
1079 //etl::surface<float> temp_surface;
1080 etl::surface<float> *gauss_surface;
1082 //if(get_amount()==1.0 && get_blend_method()==Color::BLEND_STRAIGHT)
1083 gauss_surface = &worksurface;
1086 temp_surface = worksurface;
1087 gauss_surface = &temp_surface;
1090 /* Squaring the pw and ph values
1091 is necessary to insure consistent
1092 results when rendered to different
1094 Unfortunately, this automatically
1095 squares our rendertime.
1096 There has got to be a faster way...
1101 int bw = (int)(abs(pw)*size[0]*GAUSSIAN_ADJUSTMENT+0.5);
1102 int bh = (int)(abs(ph)*size[1]*GAUSSIAN_ADJUSTMENT+0.5);
1105 float *SC0=new float[w+2];
1106 float *SC1=new float[w+2];
1107 float *SC2=new float[w+2];
1108 float *SC3=new float[w+2];
1110 memset(SC0,0,(w+2)*sizeof(float));
1111 memset(SC0,0,(w+2)*sizeof(float));
1112 memset(SC0,0,(w+2)*sizeof(float));
1113 memset(SC0,0,(w+2)*sizeof(float));
1119 if(!blurcall.amount_complete(max-(bw+bh),max))return false;
1123 etl::gaussian_blur_5x5_(gauss_surface->begin(),gauss_surface->get_w(),gauss_surface->get_h(),SC0,SC1,SC2,SC3);
1129 etl::gaussian_blur_3x3(gauss_surface->begin(),gauss_surface->end());
1135 GuassianBlur_2x2(*gauss_surface);
1142 if(!blurcall.amount_complete(max-(bw+bh),max))return false;
1145 GuassianBlur_3x1(*gauss_surface);
1151 GuassianBlur_2x1(*gauss_surface);
1158 if(!blurcall.amount_complete(max-(bw+bh),max))return false;
1161 GuassianBlur_1x3(*gauss_surface);
1167 GuassianBlur_1x2(*gauss_surface);
1177 /*if(get_amount()!=1.0 || get_blend_method()!=Color::BLEND_STRAIGHT)
1180 for(y=0;y<renddesc.get_h();y++)
1181 for(x=0;x<renddesc.get_w();x++)
1182 worksurface[y][x]=Color::blend(temp_surface[y][x],worksurface[y][x],get_amount(),get_blend_method());
1191 //be sure the surface is of the correct size
1192 //surface->set_wh(renddesc.get_w(),renddesc.get_h());
1195 //divide out the alpha - don't need to cause we rock
1198 //we are FRIGGGIN done....
1199 blurcall.amount_complete(100,100);
1204 /* === E N T R Y P O I N T ================================================= */