Anti-Grain Geometry - AGG (libagg)  2.5
agg-2.5/include/agg_blur.h
Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 // Anti-Grain Geometry (AGG) - Version 2.5
00003 // A high quality rendering engine for C++
00004 // Copyright (C) 2002-2006 Maxim Shemanarev
00005 // Contact: mcseem@antigrain.com
00006 //          mcseemagg@yahoo.com
00007 //          http://antigrain.com
00008 // 
00009 // AGG is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU General Public License
00011 // as published by the Free Software Foundation; either version 2
00012 // of the License, or (at your option) any later version.
00013 // 
00014 // AGG is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 // GNU General Public License for more details.
00018 // 
00019 // You should have received a copy of the GNU General Public License
00020 // along with AGG; if not, write to the Free Software
00021 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
00022 // MA 02110-1301, USA.
00023 //----------------------------------------------------------------------------
00024 //
00025 // The Stack Blur Algorithm was invented by Mario Klingemann, 
00026 // mario@quasimondo.com and described here:
00027 // http://incubator.quasimondo.com/processing/fast_blur_deluxe.php
00028 // (search phrase "Stackblur: Fast But Goodlooking"). 
00029 // The major improvement is that there's no more division table
00030 // that was very expensive to create for large blur radii. Insted, 
00031 // for 8-bit per channel and radius not exceeding 254 the division is 
00032 // replaced by multiplication and shift. 
00033 //
00034 //----------------------------------------------------------------------------
00035 
00036 #ifndef AGG_BLUR_INCLUDED
00037 #define AGG_BLUR_INCLUDED
00038 
00039 #include "agg_array.h"
00040 #include "agg_pixfmt_transposer.h"
00041 
00042 namespace agg
00043 {
00044 
00045     template<class T> struct stack_blur_tables
00046     {
00047         static int16u const g_stack_blur8_mul[255];
00048         static int8u  const g_stack_blur8_shr[255];
00049     };
00050 
00051     //------------------------------------------------------------------------
00052     template<class T> 
00053     int16u const stack_blur_tables<T>::g_stack_blur8_mul[255] = 
00054     {
00055         512,512,456,512,328,456,335,512,405,328,271,456,388,335,292,512,
00056         454,405,364,328,298,271,496,456,420,388,360,335,312,292,273,512,
00057         482,454,428,405,383,364,345,328,312,298,284,271,259,496,475,456,
00058         437,420,404,388,374,360,347,335,323,312,302,292,282,273,265,512,
00059         497,482,468,454,441,428,417,405,394,383,373,364,354,345,337,328,
00060         320,312,305,298,291,284,278,271,265,259,507,496,485,475,465,456,
00061         446,437,428,420,412,404,396,388,381,374,367,360,354,347,341,335,
00062         329,323,318,312,307,302,297,292,287,282,278,273,269,265,261,512,
00063         505,497,489,482,475,468,461,454,447,441,435,428,422,417,411,405,
00064         399,394,389,383,378,373,368,364,359,354,350,345,341,337,332,328,
00065         324,320,316,312,309,305,301,298,294,291,287,284,281,278,274,271,
00066         268,265,262,259,257,507,501,496,491,485,480,475,470,465,460,456,
00067         451,446,442,437,433,428,424,420,416,412,408,404,400,396,392,388,
00068         385,381,377,374,370,367,363,360,357,354,350,347,344,341,338,335,
00069         332,329,326,323,320,318,315,312,310,307,304,302,299,297,294,292,
00070         289,287,285,282,280,278,275,273,271,269,267,265,263,261,259
00071     };
00072 
00073     //------------------------------------------------------------------------
00074     template<class T> 
00075     int8u const stack_blur_tables<T>::g_stack_blur8_shr[255] = 
00076     {
00077           9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 
00078          17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 
00079          19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20,
00080          20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,
00081          21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
00082          21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 
00083          22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
00084          22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 
00085          23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
00086          23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
00087          23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 
00088          23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 
00089          24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
00090          24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
00091          24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
00092          24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24
00093     };
00094 
00095 
00096 
00097     //==============================================================stack_blur
00098     template<class ColorT, class CalculatorT> class stack_blur
00099     {
00100     public:
00101         typedef ColorT      color_type;
00102         typedef CalculatorT calculator_type;
00103 
00104         //--------------------------------------------------------------------
00105         template<class Img> void blur_x(Img& img, unsigned radius)
00106         {
00107             if(radius < 1) return;
00108 
00109             unsigned x, y, xp, i;
00110             unsigned stack_ptr;
00111             unsigned stack_start;
00112 
00113             color_type      pix;
00114             color_type*     stack_pix;
00115             calculator_type sum;
00116             calculator_type sum_in;
00117             calculator_type sum_out;
00118 
00119             unsigned w   = img.width();
00120             unsigned h   = img.height();
00121             unsigned wm  = w - 1;
00122             unsigned div = radius * 2 + 1;
00123 
00124             unsigned div_sum = (radius + 1) * (radius + 1);
00125             unsigned mul_sum = 0;
00126             unsigned shr_sum = 0;
00127             unsigned max_val = color_type::base_mask;
00128 
00129             if(max_val <= 255 && radius < 255)
00130             {
00131                 mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[radius];
00132                 shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[radius];
00133             }
00134 
00135             m_buf.allocate(w, 128);
00136             m_stack.allocate(div, 32);
00137 
00138             for(y = 0; y < h; y++)
00139             {
00140                 sum.clear();
00141                 sum_in.clear();
00142                 sum_out.clear();
00143 
00144                 pix = img.pixel(0, y);
00145                 for(i = 0; i <= radius; i++)
00146                 {
00147                     m_stack[i] = pix;
00148                     sum.add(pix, i + 1);
00149                     sum_out.add(pix);
00150                 }
00151                 for(i = 1; i <= radius; i++)
00152                 {
00153                     pix = img.pixel((i > wm) ? wm : i, y);
00154                     m_stack[i + radius] = pix;
00155                     sum.add(pix, radius + 1 - i);
00156                     sum_in.add(pix);
00157                 }
00158 
00159                 stack_ptr = radius;
00160                 for(x = 0; x < w; x++)
00161                 {
00162                     if(mul_sum) sum.calc_pix(m_buf[x], mul_sum, shr_sum);
00163                     else        sum.calc_pix(m_buf[x], div_sum);
00164 
00165                     sum.sub(sum_out);
00166            
00167                     stack_start = stack_ptr + div - radius;
00168                     if(stack_start >= div) stack_start -= div;
00169                     stack_pix = &m_stack[stack_start];
00170 
00171                     sum_out.sub(*stack_pix);
00172 
00173                     xp = x + radius + 1;
00174                     if(xp > wm) xp = wm;
00175                     pix = img.pixel(xp, y);
00176             
00177                     *stack_pix = pix;
00178             
00179                     sum_in.add(pix);
00180                     sum.add(sum_in);
00181             
00182                     ++stack_ptr;
00183                     if(stack_ptr >= div) stack_ptr = 0;
00184                     stack_pix = &m_stack[stack_ptr];
00185 
00186                     sum_out.add(*stack_pix);
00187                     sum_in.sub(*stack_pix);
00188                 }
00189                 img.copy_color_hspan(0, y, w, &m_buf[0]);
00190             }
00191         }
00192 
00193         //--------------------------------------------------------------------
00194         template<class Img> void blur_y(Img& img, unsigned radius)
00195         {
00196             pixfmt_transposer<Img> img2(img);
00197             blur_x(img2, radius);
00198         }
00199 
00200         //--------------------------------------------------------------------
00201         template<class Img> void blur(Img& img, unsigned radius)
00202         {
00203             blur_x(img, radius);
00204             pixfmt_transposer<Img> img2(img);
00205             blur_x(img2, radius);
00206         }
00207 
00208     private:
00209         pod_vector<color_type> m_buf;
00210         pod_vector<color_type> m_stack;
00211     };
00212 
00213     //====================================================stack_blur_calc_rgba
00214     template<class T=unsigned> struct stack_blur_calc_rgba
00215     {
00216         typedef T value_type;
00217         value_type r,g,b,a;
00218 
00219         AGG_INLINE void clear() 
00220         { 
00221             r = g = b = a = 0; 
00222         }
00223 
00224         template<class ArgT> AGG_INLINE void add(const ArgT& v)
00225         {
00226             r += v.r;
00227             g += v.g;
00228             b += v.b;
00229             a += v.a;
00230         }
00231 
00232         template<class ArgT> AGG_INLINE void add(const ArgT& v, unsigned k)
00233         {
00234             r += v.r * k;
00235             g += v.g * k;
00236             b += v.b * k;
00237             a += v.a * k;
00238         }
00239 
00240         template<class ArgT> AGG_INLINE void sub(const ArgT& v)
00241         {
00242             r -= v.r;
00243             g -= v.g;
00244             b -= v.b;
00245             a -= v.a;
00246         }
00247 
00248         template<class ArgT> AGG_INLINE void calc_pix(ArgT& v, unsigned div)
00249         {
00250             typedef typename ArgT::value_type value_type;
00251             v.r = value_type(r / div);
00252             v.g = value_type(g / div);
00253             v.b = value_type(b / div);
00254             v.a = value_type(a / div);
00255         }
00256 
00257         template<class ArgT> 
00258         AGG_INLINE void calc_pix(ArgT& v, unsigned mul, unsigned shr)
00259         {
00260             typedef typename ArgT::value_type value_type;
00261             v.r = value_type((r * mul) >> shr);
00262             v.g = value_type((g * mul) >> shr);
00263             v.b = value_type((b * mul) >> shr);
00264             v.a = value_type((a * mul) >> shr);
00265         }
00266     };
00267 
00268 
00269     //=====================================================stack_blur_calc_rgb
00270     template<class T=unsigned> struct stack_blur_calc_rgb
00271     {
00272         typedef T value_type;
00273         value_type r,g,b;
00274 
00275         AGG_INLINE void clear() 
00276         { 
00277             r = g = b = 0; 
00278         }
00279 
00280         template<class ArgT> AGG_INLINE void add(const ArgT& v)
00281         {
00282             r += v.r;
00283             g += v.g;
00284             b += v.b;
00285         }
00286 
00287         template<class ArgT> AGG_INLINE void add(const ArgT& v, unsigned k)
00288         {
00289             r += v.r * k;
00290             g += v.g * k;
00291             b += v.b * k;
00292         }
00293 
00294         template<class ArgT> AGG_INLINE void sub(const ArgT& v)
00295         {
00296             r -= v.r;
00297             g -= v.g;
00298             b -= v.b;
00299         }
00300 
00301         template<class ArgT> AGG_INLINE void calc_pix(ArgT& v, unsigned div)
00302         {
00303             typedef typename ArgT::value_type value_type;
00304             v.r = value_type(r / div);
00305             v.g = value_type(g / div);
00306             v.b = value_type(b / div);
00307         }
00308 
00309         template<class ArgT> 
00310         AGG_INLINE void calc_pix(ArgT& v, unsigned mul, unsigned shr)
00311         {
00312             typedef typename ArgT::value_type value_type;
00313             v.r = value_type((r * mul) >> shr);
00314             v.g = value_type((g * mul) >> shr);
00315             v.b = value_type((b * mul) >> shr);
00316         }
00317     };
00318 
00319 
00320     //====================================================stack_blur_calc_gray
00321     template<class T=unsigned> struct stack_blur_calc_gray
00322     {
00323         typedef T value_type;
00324         value_type v;
00325 
00326         AGG_INLINE void clear() 
00327         { 
00328             v = 0; 
00329         }
00330 
00331         template<class ArgT> AGG_INLINE void add(const ArgT& a)
00332         {
00333             v += a.v;
00334         }
00335 
00336         template<class ArgT> AGG_INLINE void add(const ArgT& a, unsigned k)
00337         {
00338             v += a.v * k;
00339         }
00340 
00341         template<class ArgT> AGG_INLINE void sub(const ArgT& a)
00342         {
00343             v -= a.v;
00344         }
00345 
00346         template<class ArgT> AGG_INLINE void calc_pix(ArgT& a, unsigned div)
00347         {
00348             typedef typename ArgT::value_type value_type;
00349             a.v = value_type(v / div);
00350         }
00351 
00352         template<class ArgT> 
00353         AGG_INLINE void calc_pix(ArgT& a, unsigned mul, unsigned shr)
00354         {
00355             typedef typename ArgT::value_type value_type;
00356             a.v = value_type((v * mul) >> shr);
00357         }
00358     };
00359 
00360 
00361 
00362     //========================================================stack_blur_gray8
00363     template<class Img> 
00364     void stack_blur_gray8(Img& img, unsigned rx, unsigned ry)
00365     {
00366         unsigned x, y, xp, yp, i;
00367         unsigned stack_ptr;
00368         unsigned stack_start;
00369 
00370         const int8u* src_pix_ptr;
00371               int8u* dst_pix_ptr;
00372         unsigned pix;
00373         unsigned stack_pix;
00374         unsigned sum;
00375         unsigned sum_in;
00376         unsigned sum_out;
00377 
00378         unsigned w   = img.width();
00379         unsigned h   = img.height();
00380         unsigned wm  = w - 1;
00381         unsigned hm  = h - 1;
00382 
00383         unsigned div;
00384         unsigned mul_sum;
00385         unsigned shr_sum;
00386 
00387         pod_vector<int8u> stack;
00388 
00389         if(rx > 0)
00390         {
00391             if(rx > 254) rx = 254;
00392             div = rx * 2 + 1;
00393             mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[rx];
00394             shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[rx];
00395             stack.allocate(div);
00396 
00397             for(y = 0; y < h; y++)
00398             {
00399                 sum = sum_in = sum_out = 0;
00400 
00401                 src_pix_ptr = img.pix_ptr(0, y);
00402                 pix = *src_pix_ptr;
00403                 for(i = 0; i <= rx; i++)
00404                 {
00405                     stack[i] = pix;
00406                     sum     += pix * (i + 1);
00407                     sum_out += pix;
00408                 }
00409                 for(i = 1; i <= rx; i++)
00410                 {
00411                     if(i <= wm) src_pix_ptr += Img::pix_step; 
00412                     pix = *src_pix_ptr; 
00413                     stack[i + rx] = pix;
00414                     sum    += pix * (rx + 1 - i);
00415                     sum_in += pix;
00416                 }
00417 
00418                 stack_ptr = rx;
00419                 xp = rx;
00420                 if(xp > wm) xp = wm;
00421                 src_pix_ptr = img.pix_ptr(xp, y);
00422                 dst_pix_ptr = img.pix_ptr(0, y);
00423                 for(x = 0; x < w; x++)
00424                 {
00425                     *dst_pix_ptr = (sum * mul_sum) >> shr_sum;
00426                     dst_pix_ptr += Img::pix_step;
00427 
00428                     sum -= sum_out;
00429        
00430                     stack_start = stack_ptr + div - rx;
00431                     if(stack_start >= div) stack_start -= div;
00432                     sum_out -= stack[stack_start];
00433 
00434                     if(xp < wm) 
00435                     {
00436                         src_pix_ptr += Img::pix_step;
00437                         pix = *src_pix_ptr;
00438                         ++xp;
00439                     }
00440         
00441                     stack[stack_start] = pix;
00442         
00443                     sum_in += pix;
00444                     sum    += sum_in;
00445         
00446                     ++stack_ptr;
00447                     if(stack_ptr >= div) stack_ptr = 0;
00448                     stack_pix = stack[stack_ptr];
00449 
00450                     sum_out += stack_pix;
00451                     sum_in  -= stack_pix;
00452                 }
00453             }
00454         }
00455 
00456         if(ry > 0)
00457         {
00458             if(ry > 254) ry = 254;
00459             div = ry * 2 + 1;
00460             mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[ry];
00461             shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[ry];
00462             stack.allocate(div);
00463 
00464             int stride = img.stride();
00465             for(x = 0; x < w; x++)
00466             {
00467                 sum = sum_in = sum_out = 0;
00468 
00469                 src_pix_ptr = img.pix_ptr(x, 0);
00470                 pix = *src_pix_ptr;
00471                 for(i = 0; i <= ry; i++)
00472                 {
00473                     stack[i] = pix;
00474                     sum     += pix * (i + 1);
00475                     sum_out += pix;
00476                 }
00477                 for(i = 1; i <= ry; i++)
00478                 {
00479                     if(i <= hm) src_pix_ptr += stride; 
00480                     pix = *src_pix_ptr; 
00481                     stack[i + ry] = pix;
00482                     sum    += pix * (ry + 1 - i);
00483                     sum_in += pix;
00484                 }
00485 
00486                 stack_ptr = ry;
00487                 yp = ry;
00488                 if(yp > hm) yp = hm;
00489                 src_pix_ptr = img.pix_ptr(x, yp);
00490                 dst_pix_ptr = img.pix_ptr(x, 0);
00491                 for(y = 0; y < h; y++)
00492                 {
00493                     *dst_pix_ptr = (sum * mul_sum) >> shr_sum;
00494                     dst_pix_ptr += stride;
00495 
00496                     sum -= sum_out;
00497        
00498                     stack_start = stack_ptr + div - ry;
00499                     if(stack_start >= div) stack_start -= div;
00500                     sum_out -= stack[stack_start];
00501 
00502                     if(yp < hm) 
00503                     {
00504                         src_pix_ptr += stride;
00505                         pix = *src_pix_ptr;
00506                         ++yp;
00507                     }
00508         
00509                     stack[stack_start] = pix;
00510         
00511                     sum_in += pix;
00512                     sum    += sum_in;
00513         
00514                     ++stack_ptr;
00515                     if(stack_ptr >= div) stack_ptr = 0;
00516                     stack_pix = stack[stack_ptr];
00517 
00518                     sum_out += stack_pix;
00519                     sum_in  -= stack_pix;
00520                 }
00521             }
00522         }
00523     }
00524 
00525 
00526 
00527     //========================================================stack_blur_rgb24
00528     template<class Img> 
00529     void stack_blur_rgb24(Img& img, unsigned rx, unsigned ry)
00530     {
00531         typedef typename Img::color_type color_type;
00532         typedef typename Img::order_type order_type;
00533         enum order_e 
00534         { 
00535             R = order_type::R, 
00536             G = order_type::G, 
00537             B = order_type::B 
00538         };
00539 
00540         unsigned x, y, xp, yp, i;
00541         unsigned stack_ptr;
00542         unsigned stack_start;
00543 
00544         const int8u* src_pix_ptr;
00545               int8u* dst_pix_ptr;
00546         color_type*  stack_pix_ptr;
00547 
00548         unsigned sum_r;
00549         unsigned sum_g;
00550         unsigned sum_b;
00551         unsigned sum_in_r;
00552         unsigned sum_in_g;
00553         unsigned sum_in_b;
00554         unsigned sum_out_r;
00555         unsigned sum_out_g;
00556         unsigned sum_out_b;
00557 
00558         unsigned w   = img.width();
00559         unsigned h   = img.height();
00560         unsigned wm  = w - 1;
00561         unsigned hm  = h - 1;
00562 
00563         unsigned div;
00564         unsigned mul_sum;
00565         unsigned shr_sum;
00566 
00567         pod_vector<color_type> stack;
00568 
00569         if(rx > 0)
00570         {
00571             if(rx > 254) rx = 254;
00572             div = rx * 2 + 1;
00573             mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[rx];
00574             shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[rx];
00575             stack.allocate(div);
00576 
00577             for(y = 0; y < h; y++)
00578             {
00579                 sum_r = 
00580                 sum_g = 
00581                 sum_b = 
00582                 sum_in_r = 
00583                 sum_in_g = 
00584                 sum_in_b = 
00585                 sum_out_r = 
00586                 sum_out_g = 
00587                 sum_out_b = 0;
00588 
00589                 src_pix_ptr = img.pix_ptr(0, y);
00590                 for(i = 0; i <= rx; i++)
00591                 {
00592                     stack_pix_ptr    = &stack[i];
00593                     stack_pix_ptr->r = src_pix_ptr[R];
00594                     stack_pix_ptr->g = src_pix_ptr[G];
00595                     stack_pix_ptr->b = src_pix_ptr[B];
00596                     sum_r           += src_pix_ptr[R] * (i + 1);
00597                     sum_g           += src_pix_ptr[G] * (i + 1);
00598                     sum_b           += src_pix_ptr[B] * (i + 1);
00599                     sum_out_r       += src_pix_ptr[R];
00600                     sum_out_g       += src_pix_ptr[G];
00601                     sum_out_b       += src_pix_ptr[B];
00602                 }
00603                 for(i = 1; i <= rx; i++)
00604                 {
00605                     if(i <= wm) src_pix_ptr += Img::pix_width; 
00606                     stack_pix_ptr = &stack[i + rx];
00607                     stack_pix_ptr->r = src_pix_ptr[R];
00608                     stack_pix_ptr->g = src_pix_ptr[G];
00609                     stack_pix_ptr->b = src_pix_ptr[B];
00610                     sum_r           += src_pix_ptr[R] * (rx + 1 - i);
00611                     sum_g           += src_pix_ptr[G] * (rx + 1 - i);
00612                     sum_b           += src_pix_ptr[B] * (rx + 1 - i);
00613                     sum_in_r        += src_pix_ptr[R];
00614                     sum_in_g        += src_pix_ptr[G];
00615                     sum_in_b        += src_pix_ptr[B];
00616                 }
00617 
00618                 stack_ptr = rx;
00619                 xp = rx;
00620                 if(xp > wm) xp = wm;
00621                 src_pix_ptr = img.pix_ptr(xp, y);
00622                 dst_pix_ptr = img.pix_ptr(0, y);
00623                 for(x = 0; x < w; x++)
00624                 {
00625                     dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum;
00626                     dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum;
00627                     dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum;
00628                     dst_pix_ptr   += Img::pix_width;
00629 
00630                     sum_r -= sum_out_r;
00631                     sum_g -= sum_out_g;
00632                     sum_b -= sum_out_b;
00633        
00634                     stack_start = stack_ptr + div - rx;
00635                     if(stack_start >= div) stack_start -= div;
00636                     stack_pix_ptr = &stack[stack_start];
00637 
00638                     sum_out_r -= stack_pix_ptr->r;
00639                     sum_out_g -= stack_pix_ptr->g;
00640                     sum_out_b -= stack_pix_ptr->b;
00641 
00642                     if(xp < wm) 
00643                     {
00644                         src_pix_ptr += Img::pix_width;
00645                         ++xp;
00646                     }
00647         
00648                     stack_pix_ptr->r = src_pix_ptr[R];
00649                     stack_pix_ptr->g = src_pix_ptr[G];
00650                     stack_pix_ptr->b = src_pix_ptr[B];
00651         
00652                     sum_in_r += src_pix_ptr[R];
00653                     sum_in_g += src_pix_ptr[G];
00654                     sum_in_b += src_pix_ptr[B];
00655                     sum_r    += sum_in_r;
00656                     sum_g    += sum_in_g;
00657                     sum_b    += sum_in_b;
00658         
00659                     ++stack_ptr;
00660                     if(stack_ptr >= div) stack_ptr = 0;
00661                     stack_pix_ptr = &stack[stack_ptr];
00662 
00663                     sum_out_r += stack_pix_ptr->r;
00664                     sum_out_g += stack_pix_ptr->g;
00665                     sum_out_b += stack_pix_ptr->b;
00666                     sum_in_r  -= stack_pix_ptr->r;
00667                     sum_in_g  -= stack_pix_ptr->g;
00668                     sum_in_b  -= stack_pix_ptr->b;
00669                 }
00670             }
00671         }
00672 
00673         if(ry > 0)
00674         {
00675             if(ry > 254) ry = 254;
00676             div = ry * 2 + 1;
00677             mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[ry];
00678             shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[ry];
00679             stack.allocate(div);
00680 
00681             int stride = img.stride();
00682             for(x = 0; x < w; x++)
00683             {
00684                 sum_r = 
00685                 sum_g = 
00686                 sum_b = 
00687                 sum_in_r = 
00688                 sum_in_g = 
00689                 sum_in_b = 
00690                 sum_out_r = 
00691                 sum_out_g = 
00692                 sum_out_b = 0;
00693 
00694                 src_pix_ptr = img.pix_ptr(x, 0);
00695                 for(i = 0; i <= ry; i++)
00696                 {
00697                     stack_pix_ptr    = &stack[i];
00698                     stack_pix_ptr->r = src_pix_ptr[R];
00699                     stack_pix_ptr->g = src_pix_ptr[G];
00700                     stack_pix_ptr->b = src_pix_ptr[B];
00701                     sum_r           += src_pix_ptr[R] * (i + 1);
00702                     sum_g           += src_pix_ptr[G] * (i + 1);
00703                     sum_b           += src_pix_ptr[B] * (i + 1);
00704                     sum_out_r       += src_pix_ptr[R];
00705                     sum_out_g       += src_pix_ptr[G];
00706                     sum_out_b       += src_pix_ptr[B];
00707                 }
00708                 for(i = 1; i <= ry; i++)
00709                 {
00710                     if(i <= hm) src_pix_ptr += stride; 
00711                     stack_pix_ptr = &stack[i + ry];
00712                     stack_pix_ptr->r = src_pix_ptr[R];
00713                     stack_pix_ptr->g = src_pix_ptr[G];
00714                     stack_pix_ptr->b = src_pix_ptr[B];
00715                     sum_r           += src_pix_ptr[R] * (ry + 1 - i);
00716                     sum_g           += src_pix_ptr[G] * (ry + 1 - i);
00717                     sum_b           += src_pix_ptr[B] * (ry + 1 - i);
00718                     sum_in_r        += src_pix_ptr[R];
00719                     sum_in_g        += src_pix_ptr[G];
00720                     sum_in_b        += src_pix_ptr[B];
00721                 }
00722 
00723                 stack_ptr = ry;
00724                 yp = ry;
00725                 if(yp > hm) yp = hm;
00726                 src_pix_ptr = img.pix_ptr(x, yp);
00727                 dst_pix_ptr = img.pix_ptr(x, 0);
00728                 for(y = 0; y < h; y++)
00729                 {
00730                     dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum;
00731                     dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum;
00732                     dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum;
00733                     dst_pix_ptr += stride;
00734 
00735                     sum_r -= sum_out_r;
00736                     sum_g -= sum_out_g;
00737                     sum_b -= sum_out_b;
00738        
00739                     stack_start = stack_ptr + div - ry;
00740                     if(stack_start >= div) stack_start -= div;
00741 
00742                     stack_pix_ptr = &stack[stack_start];
00743                     sum_out_r -= stack_pix_ptr->r;
00744                     sum_out_g -= stack_pix_ptr->g;
00745                     sum_out_b -= stack_pix_ptr->b;
00746 
00747                     if(yp < hm) 
00748                     {
00749                         src_pix_ptr += stride;
00750                         ++yp;
00751                     }
00752         
00753                     stack_pix_ptr->r = src_pix_ptr[R];
00754                     stack_pix_ptr->g = src_pix_ptr[G];
00755                     stack_pix_ptr->b = src_pix_ptr[B];
00756         
00757                     sum_in_r += src_pix_ptr[R];
00758                     sum_in_g += src_pix_ptr[G];
00759                     sum_in_b += src_pix_ptr[B];
00760                     sum_r    += sum_in_r;
00761                     sum_g    += sum_in_g;
00762                     sum_b    += sum_in_b;
00763         
00764                     ++stack_ptr;
00765                     if(stack_ptr >= div) stack_ptr = 0;
00766                     stack_pix_ptr = &stack[stack_ptr];
00767 
00768                     sum_out_r += stack_pix_ptr->r;
00769                     sum_out_g += stack_pix_ptr->g;
00770                     sum_out_b += stack_pix_ptr->b;
00771                     sum_in_r  -= stack_pix_ptr->r;
00772                     sum_in_g  -= stack_pix_ptr->g;
00773                     sum_in_b  -= stack_pix_ptr->b;
00774                 }
00775             }
00776         }
00777     }
00778 
00779 
00780 
00781     //=======================================================stack_blur_rgba32
00782     template<class Img> 
00783     void stack_blur_rgba32(Img& img, unsigned rx, unsigned ry)
00784     {
00785         typedef typename Img::color_type color_type;
00786         typedef typename Img::order_type order_type;
00787         enum order_e 
00788         { 
00789             R = order_type::R, 
00790             G = order_type::G, 
00791             B = order_type::B,
00792             A = order_type::A 
00793         };
00794 
00795         unsigned x, y, xp, yp, i;
00796         unsigned stack_ptr;
00797         unsigned stack_start;
00798 
00799         const int8u* src_pix_ptr;
00800               int8u* dst_pix_ptr;
00801         color_type*  stack_pix_ptr;
00802 
00803         unsigned sum_r;
00804         unsigned sum_g;
00805         unsigned sum_b;
00806         unsigned sum_a;
00807         unsigned sum_in_r;
00808         unsigned sum_in_g;
00809         unsigned sum_in_b;
00810         unsigned sum_in_a;
00811         unsigned sum_out_r;
00812         unsigned sum_out_g;
00813         unsigned sum_out_b;
00814         unsigned sum_out_a;
00815 
00816         unsigned w   = img.width();
00817         unsigned h   = img.height();
00818         unsigned wm  = w - 1;
00819         unsigned hm  = h - 1;
00820 
00821         unsigned div;
00822         unsigned mul_sum;
00823         unsigned shr_sum;
00824 
00825         pod_vector<color_type> stack;
00826 
00827         if(rx > 0)
00828         {
00829             if(rx > 254) rx = 254;
00830             div = rx * 2 + 1;
00831             mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[rx];
00832             shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[rx];
00833             stack.allocate(div);
00834 
00835             for(y = 0; y < h; y++)
00836             {
00837                 sum_r = 
00838                 sum_g = 
00839                 sum_b = 
00840                 sum_a = 
00841                 sum_in_r = 
00842                 sum_in_g = 
00843                 sum_in_b = 
00844                 sum_in_a = 
00845                 sum_out_r = 
00846                 sum_out_g = 
00847                 sum_out_b = 
00848                 sum_out_a = 0;
00849 
00850                 src_pix_ptr = img.pix_ptr(0, y);
00851                 for(i = 0; i <= rx; i++)
00852                 {
00853                     stack_pix_ptr    = &stack[i];
00854                     stack_pix_ptr->r = src_pix_ptr[R];
00855                     stack_pix_ptr->g = src_pix_ptr[G];
00856                     stack_pix_ptr->b = src_pix_ptr[B];
00857                     stack_pix_ptr->a = src_pix_ptr[A];
00858                     sum_r           += src_pix_ptr[R] * (i + 1);
00859                     sum_g           += src_pix_ptr[G] * (i + 1);
00860                     sum_b           += src_pix_ptr[B] * (i + 1);
00861                     sum_a           += src_pix_ptr[A] * (i + 1);
00862                     sum_out_r       += src_pix_ptr[R];
00863                     sum_out_g       += src_pix_ptr[G];
00864                     sum_out_b       += src_pix_ptr[B];
00865                     sum_out_a       += src_pix_ptr[A];
00866                 }
00867                 for(i = 1; i <= rx; i++)
00868                 {
00869                     if(i <= wm) src_pix_ptr += Img::pix_width; 
00870                     stack_pix_ptr = &stack[i + rx];
00871                     stack_pix_ptr->r = src_pix_ptr[R];
00872                     stack_pix_ptr->g = src_pix_ptr[G];
00873                     stack_pix_ptr->b = src_pix_ptr[B];
00874                     stack_pix_ptr->a = src_pix_ptr[A];
00875                     sum_r           += src_pix_ptr[R] * (rx + 1 - i);
00876                     sum_g           += src_pix_ptr[G] * (rx + 1 - i);
00877                     sum_b           += src_pix_ptr[B] * (rx + 1 - i);
00878                     sum_a           += src_pix_ptr[A] * (rx + 1 - i);
00879                     sum_in_r        += src_pix_ptr[R];
00880                     sum_in_g        += src_pix_ptr[G];
00881                     sum_in_b        += src_pix_ptr[B];
00882                     sum_in_a        += src_pix_ptr[A];
00883                 }
00884 
00885                 stack_ptr = rx;
00886                 xp = rx;
00887                 if(xp > wm) xp = wm;
00888                 src_pix_ptr = img.pix_ptr(xp, y);
00889                 dst_pix_ptr = img.pix_ptr(0, y);
00890                 for(x = 0; x < w; x++)
00891                 {
00892                     dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum;
00893                     dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum;
00894                     dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum;
00895                     dst_pix_ptr[A] = (sum_a * mul_sum) >> shr_sum;
00896                     dst_pix_ptr += Img::pix_width;
00897 
00898                     sum_r -= sum_out_r;
00899                     sum_g -= sum_out_g;
00900                     sum_b -= sum_out_b;
00901                     sum_a -= sum_out_a;
00902        
00903                     stack_start = stack_ptr + div - rx;
00904                     if(stack_start >= div) stack_start -= div;
00905                     stack_pix_ptr = &stack[stack_start];
00906 
00907                     sum_out_r -= stack_pix_ptr->r;
00908                     sum_out_g -= stack_pix_ptr->g;
00909                     sum_out_b -= stack_pix_ptr->b;
00910                     sum_out_a -= stack_pix_ptr->a;
00911 
00912                     if(xp < wm) 
00913                     {
00914                         src_pix_ptr += Img::pix_width;
00915                         ++xp;
00916                     }
00917         
00918                     stack_pix_ptr->r = src_pix_ptr[R];
00919                     stack_pix_ptr->g = src_pix_ptr[G];
00920                     stack_pix_ptr->b = src_pix_ptr[B];
00921                     stack_pix_ptr->a = src_pix_ptr[A];
00922         
00923                     sum_in_r += src_pix_ptr[R];
00924                     sum_in_g += src_pix_ptr[G];
00925                     sum_in_b += src_pix_ptr[B];
00926                     sum_in_a += src_pix_ptr[A];
00927                     sum_r    += sum_in_r;
00928                     sum_g    += sum_in_g;
00929                     sum_b    += sum_in_b;
00930                     sum_a    += sum_in_a;
00931         
00932                     ++stack_ptr;
00933                     if(stack_ptr >= div) stack_ptr = 0;
00934                     stack_pix_ptr = &stack[stack_ptr];
00935 
00936                     sum_out_r += stack_pix_ptr->r;
00937                     sum_out_g += stack_pix_ptr->g;
00938                     sum_out_b += stack_pix_ptr->b;
00939                     sum_out_a += stack_pix_ptr->a;
00940                     sum_in_r  -= stack_pix_ptr->r;
00941                     sum_in_g  -= stack_pix_ptr->g;
00942                     sum_in_b  -= stack_pix_ptr->b;
00943                     sum_in_a  -= stack_pix_ptr->a;
00944                 }
00945             }
00946         }
00947 
00948         if(ry > 0)
00949         {
00950             if(ry > 254) ry = 254;
00951             div = ry * 2 + 1;
00952             mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[ry];
00953             shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[ry];
00954             stack.allocate(div);
00955 
00956             int stride = img.stride();
00957             for(x = 0; x < w; x++)
00958             {
00959                 sum_r = 
00960                 sum_g = 
00961                 sum_b = 
00962                 sum_a = 
00963                 sum_in_r = 
00964                 sum_in_g = 
00965                 sum_in_b = 
00966                 sum_in_a = 
00967                 sum_out_r = 
00968                 sum_out_g = 
00969                 sum_out_b = 
00970                 sum_out_a = 0;
00971 
00972                 src_pix_ptr = img.pix_ptr(x, 0);
00973                 for(i = 0; i <= ry; i++)
00974                 {
00975                     stack_pix_ptr    = &stack[i];
00976                     stack_pix_ptr->r = src_pix_ptr[R];
00977                     stack_pix_ptr->g = src_pix_ptr[G];
00978                     stack_pix_ptr->b = src_pix_ptr[B];
00979                     stack_pix_ptr->a = src_pix_ptr[A];
00980                     sum_r           += src_pix_ptr[R] * (i + 1);
00981                     sum_g           += src_pix_ptr[G] * (i + 1);
00982                     sum_b           += src_pix_ptr[B] * (i + 1);
00983                     sum_a           += src_pix_ptr[A] * (i + 1);
00984                     sum_out_r       += src_pix_ptr[R];
00985                     sum_out_g       += src_pix_ptr[G];
00986                     sum_out_b       += src_pix_ptr[B];
00987                     sum_out_a       += src_pix_ptr[A];
00988                 }
00989                 for(i = 1; i <= ry; i++)
00990                 {
00991                     if(i <= hm) src_pix_ptr += stride; 
00992                     stack_pix_ptr = &stack[i + ry];
00993                     stack_pix_ptr->r = src_pix_ptr[R];
00994                     stack_pix_ptr->g = src_pix_ptr[G];
00995                     stack_pix_ptr->b = src_pix_ptr[B];
00996                     stack_pix_ptr->a = src_pix_ptr[A];
00997                     sum_r           += src_pix_ptr[R] * (ry + 1 - i);
00998                     sum_g           += src_pix_ptr[G] * (ry + 1 - i);
00999                     sum_b           += src_pix_ptr[B] * (ry + 1 - i);
01000                     sum_a           += src_pix_ptr[A] * (ry + 1 - i);
01001                     sum_in_r        += src_pix_ptr[R];
01002                     sum_in_g        += src_pix_ptr[G];
01003                     sum_in_b        += src_pix_ptr[B];
01004                     sum_in_a        += src_pix_ptr[A];
01005                 }
01006 
01007                 stack_ptr = ry;
01008                 yp = ry;
01009                 if(yp > hm) yp = hm;
01010                 src_pix_ptr = img.pix_ptr(x, yp);
01011                 dst_pix_ptr = img.pix_ptr(x, 0);
01012                 for(y = 0; y < h; y++)
01013                 {
01014                     dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum;
01015                     dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum;
01016                     dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum;
01017                     dst_pix_ptr[A] = (sum_a * mul_sum) >> shr_sum;
01018                     dst_pix_ptr += stride;
01019 
01020                     sum_r -= sum_out_r;
01021                     sum_g -= sum_out_g;
01022                     sum_b -= sum_out_b;
01023                     sum_a -= sum_out_a;
01024        
01025                     stack_start = stack_ptr + div - ry;
01026                     if(stack_start >= div) stack_start -= div;
01027 
01028                     stack_pix_ptr = &stack[stack_start];
01029                     sum_out_r -= stack_pix_ptr->r;
01030                     sum_out_g -= stack_pix_ptr->g;
01031                     sum_out_b -= stack_pix_ptr->b;
01032                     sum_out_a -= stack_pix_ptr->a;
01033 
01034                     if(yp < hm) 
01035                     {
01036                         src_pix_ptr += stride;
01037                         ++yp;
01038                     }
01039         
01040                     stack_pix_ptr->r = src_pix_ptr[R];
01041                     stack_pix_ptr->g = src_pix_ptr[G];
01042                     stack_pix_ptr->b = src_pix_ptr[B];
01043                     stack_pix_ptr->a = src_pix_ptr[A];
01044         
01045                     sum_in_r += src_pix_ptr[R];
01046                     sum_in_g += src_pix_ptr[G];
01047                     sum_in_b += src_pix_ptr[B];
01048                     sum_in_a += src_pix_ptr[A];
01049                     sum_r    += sum_in_r;
01050                     sum_g    += sum_in_g;
01051                     sum_b    += sum_in_b;
01052                     sum_a    += sum_in_a;
01053         
01054                     ++stack_ptr;
01055                     if(stack_ptr >= div) stack_ptr = 0;
01056                     stack_pix_ptr = &stack[stack_ptr];
01057 
01058                     sum_out_r += stack_pix_ptr->r;
01059                     sum_out_g += stack_pix_ptr->g;
01060                     sum_out_b += stack_pix_ptr->b;
01061                     sum_out_a += stack_pix_ptr->a;
01062                     sum_in_r  -= stack_pix_ptr->r;
01063                     sum_in_g  -= stack_pix_ptr->g;
01064                     sum_in_b  -= stack_pix_ptr->b;
01065                     sum_in_a  -= stack_pix_ptr->a;
01066                 }
01067             }
01068         }
01069     }
01070 
01071 
01072 
01073     //===========================================================recursive_blur
01074     template<class ColorT, class CalculatorT> class recursive_blur
01075     {
01076     public:
01077         typedef ColorT color_type;
01078         typedef CalculatorT calculator_type;
01079         typedef typename color_type::value_type value_type;
01080         typedef typename calculator_type::value_type calc_type;
01081 
01082         //--------------------------------------------------------------------
01083         template<class Img> void blur_x(Img& img, double radius)
01084         {
01085             if(radius < 0.62) return;
01086             if(img.width() < 3) return;
01087 
01088             calc_type s = calc_type(radius * 0.5);
01089             calc_type q = calc_type((s < 2.5) ?
01090                                     3.97156 - 4.14554 * sqrt(1 - 0.26891 * s) :
01091                                     0.98711 * s - 0.96330);
01092 
01093             calc_type q2 = calc_type(q * q);
01094             calc_type q3 = calc_type(q2 * q);
01095 
01096             calc_type b0 = calc_type(1.0 / (1.578250 + 
01097                                             2.444130 * q + 
01098                                             1.428100 * q2 + 
01099                                             0.422205 * q3));
01100 
01101             calc_type b1 = calc_type( 2.44413 * q + 
01102                                       2.85619 * q2 + 
01103                                       1.26661 * q3);
01104 
01105             calc_type b2 = calc_type(-1.42810 * q2 + 
01106                                      -1.26661 * q3);
01107 
01108             calc_type b3 = calc_type(0.422205 * q3);
01109 
01110             calc_type b  = calc_type(1 - (b1 + b2 + b3) * b0);
01111 
01112             b1 *= b0;
01113             b2 *= b0;
01114             b3 *= b0;
01115 
01116             int w = img.width();
01117             int h = img.height();
01118             int wm = w-1;
01119             int x, y;
01120 
01121             m_sum1.allocate(w);
01122             m_sum2.allocate(w);
01123             m_buf.allocate(w);
01124 
01125             for(y = 0; y < h; y++)
01126             {
01127                 calculator_type c;
01128                 c.from_pix(img.pixel(0, y));
01129                 m_sum1[0].calc(b, b1, b2, b3, c, c, c, c);
01130                 c.from_pix(img.pixel(1, y));
01131                 m_sum1[1].calc(b, b1, b2, b3, c, m_sum1[0], m_sum1[0], m_sum1[0]);
01132                 c.from_pix(img.pixel(2, y));
01133                 m_sum1[2].calc(b, b1, b2, b3, c, m_sum1[1], m_sum1[0], m_sum1[0]);
01134 
01135                 for(x = 3; x < w; ++x)
01136                 {
01137                     c.from_pix(img.pixel(x, y));
01138                     m_sum1[x].calc(b, b1, b2, b3, c, m_sum1[x-1], m_sum1[x-2], m_sum1[x-3]);
01139                 }
01140     
01141                 m_sum2[wm  ].calc(b, b1, b2, b3, m_sum1[wm  ], m_sum1[wm  ], m_sum1[wm], m_sum1[wm]);
01142                 m_sum2[wm-1].calc(b, b1, b2, b3, m_sum1[wm-1], m_sum2[wm  ], m_sum2[wm], m_sum2[wm]);
01143                 m_sum2[wm-2].calc(b, b1, b2, b3, m_sum1[wm-2], m_sum2[wm-1], m_sum2[wm], m_sum2[wm]);
01144                 m_sum2[wm  ].to_pix(m_buf[wm  ]);
01145                 m_sum2[wm-1].to_pix(m_buf[wm-1]);
01146                 m_sum2[wm-2].to_pix(m_buf[wm-2]);
01147 
01148                 for(x = wm-3; x >= 0; --x)
01149                 {
01150                     m_sum2[x].calc(b, b1, b2, b3, m_sum1[x], m_sum2[x+1], m_sum2[x+2], m_sum2[x+3]);
01151                     m_sum2[x].to_pix(m_buf[x]);
01152                 }
01153                 img.copy_color_hspan(0, y, w, &m_buf[0]);
01154             }
01155         }
01156 
01157         //--------------------------------------------------------------------
01158         template<class Img> void blur_y(Img& img, double radius)
01159         {
01160             pixfmt_transposer<Img> img2(img);
01161             blur_x(img2, radius);
01162         }
01163 
01164         //--------------------------------------------------------------------
01165         template<class Img> void blur(Img& img, double radius)
01166         {
01167             blur_x(img, radius);
01168             pixfmt_transposer<Img> img2(img);
01169             blur_x(img2, radius);
01170         }
01171 
01172     private:
01173         agg::pod_vector<calculator_type> m_sum1;
01174         agg::pod_vector<calculator_type> m_sum2;
01175         agg::pod_vector<color_type>      m_buf;
01176     };
01177 
01178 
01179     //=================================================recursive_blur_calc_rgba
01180     template<class T=double> struct recursive_blur_calc_rgba
01181     {
01182         typedef T value_type;
01183         typedef recursive_blur_calc_rgba<T> self_type;
01184 
01185         value_type r,g,b,a;
01186 
01187         template<class ColorT> 
01188         AGG_INLINE void from_pix(const ColorT& c)
01189         {
01190             r = c.r;
01191             g = c.g;
01192             b = c.b;
01193             a = c.a;
01194         }
01195 
01196         AGG_INLINE void calc(value_type b1, 
01197                              value_type b2, 
01198                              value_type b3, 
01199                              value_type b4,
01200                              const self_type& c1, 
01201                              const self_type& c2, 
01202                              const self_type& c3, 
01203                              const self_type& c4)
01204         {
01205             r = b1*c1.r + b2*c2.r + b3*c3.r + b4*c4.r;
01206             g = b1*c1.g + b2*c2.g + b3*c3.g + b4*c4.g;
01207             b = b1*c1.b + b2*c2.b + b3*c3.b + b4*c4.b;
01208             a = b1*c1.a + b2*c2.a + b3*c3.a + b4*c4.a;
01209         }
01210 
01211         template<class ColorT> 
01212         AGG_INLINE void to_pix(ColorT& c) const
01213         {
01214             typedef typename ColorT::value_type cv_type;
01215             c.r = (cv_type)uround(r);
01216             c.g = (cv_type)uround(g);
01217             c.b = (cv_type)uround(b);
01218             c.a = (cv_type)uround(a);
01219         }
01220     };
01221 
01222 
01223     //=================================================recursive_blur_calc_rgb
01224     template<class T=double> struct recursive_blur_calc_rgb
01225     {
01226         typedef T value_type;
01227         typedef recursive_blur_calc_rgb<T> self_type;
01228 
01229         value_type r,g,b;
01230 
01231         template<class ColorT> 
01232         AGG_INLINE void from_pix(const ColorT& c)
01233         {
01234             r = c.r;
01235             g = c.g;
01236             b = c.b;
01237         }
01238 
01239         AGG_INLINE void calc(value_type b1, 
01240                              value_type b2, 
01241                              value_type b3, 
01242                              value_type b4,
01243                              const self_type& c1, 
01244                              const self_type& c2, 
01245                              const self_type& c3, 
01246                              const self_type& c4)
01247         {
01248             r = b1*c1.r + b2*c2.r + b3*c3.r + b4*c4.r;
01249             g = b1*c1.g + b2*c2.g + b3*c3.g + b4*c4.g;
01250             b = b1*c1.b + b2*c2.b + b3*c3.b + b4*c4.b;
01251         }
01252 
01253         template<class ColorT> 
01254         AGG_INLINE void to_pix(ColorT& c) const
01255         {
01256             typedef typename ColorT::value_type cv_type;
01257             c.r = (cv_type)uround(r);
01258             c.g = (cv_type)uround(g);
01259             c.b = (cv_type)uround(b);
01260         }
01261     };
01262 
01263 
01264     //================================================recursive_blur_calc_gray
01265     template<class T=double> struct recursive_blur_calc_gray
01266     {
01267         typedef T value_type;
01268         typedef recursive_blur_calc_gray<T> self_type;
01269 
01270         value_type v;
01271 
01272         template<class ColorT> 
01273         AGG_INLINE void from_pix(const ColorT& c)
01274         {
01275             v = c.v;
01276         }
01277 
01278         AGG_INLINE void calc(value_type b1, 
01279                              value_type b2, 
01280                              value_type b3, 
01281                              value_type b4,
01282                              const self_type& c1, 
01283                              const self_type& c2, 
01284                              const self_type& c3, 
01285                              const self_type& c4)
01286         {
01287             v = b1*c1.v + b2*c2.v + b3*c3.v + b4*c4.v;
01288         }
01289 
01290         template<class ColorT> 
01291         AGG_INLINE void to_pix(ColorT& c) const
01292         {
01293             typedef typename ColorT::value_type cv_type;
01294             c.v = (cv_type)uround(v);
01295         }
01296     };
01297 
01298 }
01299 
01300 
01301 
01302 
01303 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines