Anti-Grain Geometry - AGG (libagg)  2.5
agg-2.5/include/agg_image_filters.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 #ifndef AGG_IMAGE_FILTERS_INCLUDED
00026 #define AGG_IMAGE_FILTERS_INCLUDED
00027 
00028 #include "agg_array.h"
00029 #include "agg_math.h"
00030 
00031 namespace agg
00032 {
00033 
00034     // See Implementation agg_image_filters.cpp 
00035 
00036     enum image_filter_scale_e
00037     {
00038         image_filter_shift = 14,                      //----image_filter_shift
00039         image_filter_scale = 1 << image_filter_shift, //----image_filter_scale 
00040         image_filter_mask  = image_filter_scale - 1   //----image_filter_mask 
00041     };
00042 
00043     enum image_subpixel_scale_e
00044     {
00045         image_subpixel_shift = 8,                         //----image_subpixel_shift
00046         image_subpixel_scale = 1 << image_subpixel_shift, //----image_subpixel_scale 
00047         image_subpixel_mask  = image_subpixel_scale - 1   //----image_subpixel_mask 
00048     };
00049 
00050 
00051     //-----------------------------------------------------image_filter_lut
00052     class image_filter_lut
00053     {
00054     public:
00055         template<class FilterF> void calculate(const FilterF& filter,
00056                                                bool normalization=true)
00057         {
00058             double r = filter.radius();
00059             realloc_lut(r);
00060             unsigned i;
00061             unsigned pivot = diameter() << (image_subpixel_shift - 1);
00062             for(i = 0; i < pivot; i++)
00063             {
00064                 double x = double(i) / double(image_subpixel_scale);
00065                 double y = filter.calc_weight(x);
00066                 m_weight_array[pivot + i] = 
00067                 m_weight_array[pivot - i] = (int16)iround(y * image_filter_scale);
00068             }
00069             unsigned end = (diameter() << image_subpixel_shift) - 1;
00070             m_weight_array[0] = m_weight_array[end];
00071             if(normalization) 
00072             {
00073                 normalize();
00074             }
00075         }
00076 
00077         image_filter_lut() : m_radius(0), m_diameter(0), m_start(0) {}
00078 
00079         template<class FilterF> image_filter_lut(const FilterF& filter, 
00080                                                  bool normalization=true)
00081         {
00082             calculate(filter, normalization);
00083         }
00084 
00085         double       radius()       const { return m_radius;   }
00086         unsigned     diameter()     const { return m_diameter; }
00087         int          start()        const { return m_start;    }
00088         const int16* weight_array() const { return &m_weight_array[0]; }
00089         void         normalize();
00090 
00091     private:
00092         void realloc_lut(double radius);
00093         image_filter_lut(const image_filter_lut&);
00094         const image_filter_lut& operator = (const image_filter_lut&);
00095 
00096         double           m_radius;
00097         unsigned         m_diameter;
00098         int              m_start;
00099         pod_array<int16> m_weight_array;
00100     };
00101 
00102 
00103 
00104     //--------------------------------------------------------image_filter
00105     template<class FilterF> class image_filter : public image_filter_lut
00106     {
00107     public:
00108         image_filter()
00109         {
00110             calculate(m_filter_function);
00111         }
00112     private:
00113         FilterF m_filter_function;
00114     };
00115 
00116 
00117     //-----------------------------------------------image_filter_bilinear
00118     struct image_filter_bilinear
00119     {
00120         static double radius() { return 1.0; }
00121         static double calc_weight(double x)
00122         {
00123             return 1.0 - x;
00124         }
00125     };
00126 
00127 
00128     //-----------------------------------------------image_filter_hanning
00129     struct image_filter_hanning
00130     {
00131         static double radius() { return 1.0; }
00132         static double calc_weight(double x)
00133         {
00134             return 0.5 + 0.5 * cos(pi * x);
00135         }
00136     };
00137 
00138 
00139     //-----------------------------------------------image_filter_hamming
00140     struct image_filter_hamming
00141     {
00142         static double radius() { return 1.0; }
00143         static double calc_weight(double x)
00144         {
00145             return 0.54 + 0.46 * cos(pi * x);
00146         }
00147     };
00148 
00149     //-----------------------------------------------image_filter_hermite
00150     struct image_filter_hermite
00151     {
00152         static double radius() { return 1.0; }
00153         static double calc_weight(double x)
00154         {
00155             return (2.0 * x - 3.0) * x * x + 1.0;
00156         }
00157     };
00158    
00159     //------------------------------------------------image_filter_quadric
00160     struct image_filter_quadric
00161     {
00162         static double radius() { return 1.5; }
00163         static double calc_weight(double x)
00164         {
00165             double t;
00166             if(x <  0.5) return 0.75 - x * x;
00167             if(x <  1.5) {t = x - 1.5; return 0.5 * t * t;}
00168             return 0.0;
00169         }
00170     };
00171 
00172     //------------------------------------------------image_filter_bicubic
00173     class image_filter_bicubic
00174     {
00175         static double pow3(double x)
00176         {
00177             return (x <= 0.0) ? 0.0 : x * x * x;
00178         }
00179 
00180     public:
00181         static double radius() { return 2.0; }
00182         static double calc_weight(double x)
00183         {
00184             return
00185                 (1.0/6.0) * 
00186                 (pow3(x + 2) - 4 * pow3(x + 1) + 6 * pow3(x) - 4 * pow3(x - 1));
00187         }
00188     };
00189 
00190     //-------------------------------------------------image_filter_kaiser
00191     class image_filter_kaiser
00192     {
00193         double a;
00194         double i0a;
00195         double epsilon;
00196 
00197     public:
00198         image_filter_kaiser(double b = 6.33) :
00199             a(b), epsilon(1e-12)
00200         {
00201             i0a = 1.0 / bessel_i0(b);
00202         }
00203 
00204         static double radius() { return 1.0; }
00205         double calc_weight(double x) const
00206         {
00207             return bessel_i0(a * sqrt(1. - x * x)) * i0a;
00208         }
00209 
00210     private:
00211         double bessel_i0(double x) const
00212         {
00213             int i;
00214             double sum, y, t;
00215 
00216             sum = 1.;
00217             y = x * x / 4.;
00218             t = y;
00219         
00220             for(i = 2; t > epsilon; i++)
00221             {
00222                 sum += t;
00223                 t *= (double)y / (i * i);
00224             }
00225             return sum;
00226         }
00227     };
00228 
00229     //----------------------------------------------image_filter_catrom
00230     struct image_filter_catrom
00231     {
00232         static double radius() { return 2.0; }
00233         static double calc_weight(double x)
00234         {
00235             if(x <  1.0) return 0.5 * (2.0 + x * x * (-5.0 + x * 3.0));
00236             if(x <  2.0) return 0.5 * (4.0 + x * (-8.0 + x * (5.0 - x)));
00237             return 0.;
00238         }
00239     };
00240 
00241     //---------------------------------------------image_filter_mitchell
00242     class image_filter_mitchell
00243     {
00244         double p0, p2, p3;
00245         double q0, q1, q2, q3;
00246 
00247     public:
00248         image_filter_mitchell(double b = 1.0/3.0, double c = 1.0/3.0) :
00249             p0((6.0 - 2.0 * b) / 6.0),
00250             p2((-18.0 + 12.0 * b + 6.0 * c) / 6.0),
00251             p3((12.0 - 9.0 * b - 6.0 * c) / 6.0),
00252             q0((8.0 * b + 24.0 * c) / 6.0),
00253             q1((-12.0 * b - 48.0 * c) / 6.0),
00254             q2((6.0 * b + 30.0 * c) / 6.0),
00255             q3((-b - 6.0 * c) / 6.0)
00256         {}
00257 
00258         static double radius() { return 2.0; }
00259         double calc_weight(double x) const
00260         {
00261             if(x < 1.0) return p0 + x * x * (p2 + x * p3);
00262             if(x < 2.0) return q0 + x * (q1 + x * (q2 + x * q3));
00263             return 0.0;
00264         }
00265     };
00266 
00267 
00268     //----------------------------------------------image_filter_spline16
00269     struct image_filter_spline16
00270     {
00271         static double radius() { return 2.0; }
00272         static double calc_weight(double x)
00273         {
00274             if(x < 1.0)
00275             {
00276                 return ((x - 9.0/5.0 ) * x - 1.0/5.0 ) * x + 1.0;
00277             }
00278             return ((-1.0/3.0 * (x-1) + 4.0/5.0) * (x-1) - 7.0/15.0 ) * (x-1);
00279         }
00280     };
00281 
00282 
00283     //---------------------------------------------image_filter_spline36
00284     struct image_filter_spline36
00285     {
00286         static double radius() { return 3.0; }
00287         static double calc_weight(double x)
00288         {
00289            if(x < 1.0)
00290            {
00291               return ((13.0/11.0 * x - 453.0/209.0) * x - 3.0/209.0) * x + 1.0;
00292            }
00293            if(x < 2.0)
00294            {
00295               return ((-6.0/11.0 * (x-1) + 270.0/209.0) * (x-1) - 156.0/ 209.0) * (x-1);
00296            }
00297            return ((1.0/11.0 * (x-2) - 45.0/209.0) * (x-2) +  26.0/209.0) * (x-2);
00298         }
00299     };
00300 
00301 
00302     //----------------------------------------------image_filter_gaussian
00303     struct image_filter_gaussian
00304     {
00305         static double radius() { return 2.0; }
00306         static double calc_weight(double x) 
00307         {
00308             return exp(-2.0 * x * x) * sqrt(2.0 / pi);
00309         }
00310     };
00311 
00312 
00313     //------------------------------------------------image_filter_bessel
00314     struct image_filter_bessel
00315     {
00316         static double radius() { return 3.2383; } 
00317         static double calc_weight(double x)
00318         {
00319             return (x == 0.0) ? pi / 4.0 : besj(pi * x, 1) / (2.0 * x);
00320         }
00321     };
00322 
00323 
00324     //-------------------------------------------------image_filter_sinc
00325     class image_filter_sinc
00326     {
00327     public:
00328         image_filter_sinc(double r) : m_radius(r < 2.0 ? 2.0 : r) {}
00329         double radius() const { return m_radius; }
00330         double calc_weight(double x) const
00331         {
00332             if(x == 0.0) return 1.0;
00333             x *= pi;
00334             return sin(x) / x;
00335         }
00336     private:
00337         double m_radius;
00338     };
00339 
00340 
00341     //-----------------------------------------------image_filter_lanczos
00342     class image_filter_lanczos
00343     {
00344     public:
00345         image_filter_lanczos(double r) : m_radius(r < 2.0 ? 2.0 : r) {}
00346         double radius() const { return m_radius; }
00347         double calc_weight(double x) const
00348         {
00349            if(x == 0.0) return 1.0;
00350            if(x > m_radius) return 0.0;
00351            x *= pi;
00352            double xr = x / m_radius;
00353            return (sin(x) / x) * (sin(xr) / xr);
00354         }
00355     private:
00356         double m_radius;
00357     };
00358 
00359 
00360     //----------------------------------------------image_filter_blackman
00361     class image_filter_blackman
00362     {
00363     public:
00364         image_filter_blackman(double r) : m_radius(r < 2.0 ? 2.0 : r) {}
00365         double radius() const { return m_radius; }
00366         double calc_weight(double x) const
00367         {
00368            if(x == 0.0) return 1.0;
00369            if(x > m_radius) return 0.0;
00370            x *= pi;
00371            double xr = x / m_radius;
00372            return (sin(x) / x) * (0.42 + 0.5*cos(xr) + 0.08*cos(2*xr));
00373         }
00374     private:
00375         double m_radius;
00376     };
00377 
00378     //------------------------------------------------image_filter_sinc36
00379     class image_filter_sinc36 : public image_filter_sinc
00380     { public: image_filter_sinc36() : image_filter_sinc(3.0){} };
00381 
00382     //------------------------------------------------image_filter_sinc64
00383     class image_filter_sinc64 : public image_filter_sinc
00384     { public: image_filter_sinc64() : image_filter_sinc(4.0){} };
00385 
00386     //-----------------------------------------------image_filter_sinc100
00387     class image_filter_sinc100 : public image_filter_sinc
00388     { public: image_filter_sinc100() : image_filter_sinc(5.0){} };
00389 
00390     //-----------------------------------------------image_filter_sinc144
00391     class image_filter_sinc144 : public image_filter_sinc
00392     { public: image_filter_sinc144() : image_filter_sinc(6.0){} };
00393 
00394     //-----------------------------------------------image_filter_sinc196
00395     class image_filter_sinc196 : public image_filter_sinc
00396     { public: image_filter_sinc196() : image_filter_sinc(7.0){} };
00397 
00398     //-----------------------------------------------image_filter_sinc256
00399     class image_filter_sinc256 : public image_filter_sinc
00400     { public: image_filter_sinc256() : image_filter_sinc(8.0){} };
00401 
00402     //---------------------------------------------image_filter_lanczos36
00403     class image_filter_lanczos36 : public image_filter_lanczos
00404     { public: image_filter_lanczos36() : image_filter_lanczos(3.0){} };
00405 
00406     //---------------------------------------------image_filter_lanczos64
00407     class image_filter_lanczos64 : public image_filter_lanczos
00408     { public: image_filter_lanczos64() : image_filter_lanczos(4.0){} };
00409 
00410     //--------------------------------------------image_filter_lanczos100
00411     class image_filter_lanczos100 : public image_filter_lanczos
00412     { public: image_filter_lanczos100() : image_filter_lanczos(5.0){} };
00413 
00414     //--------------------------------------------image_filter_lanczos144
00415     class image_filter_lanczos144 : public image_filter_lanczos
00416     { public: image_filter_lanczos144() : image_filter_lanczos(6.0){} };
00417 
00418     //--------------------------------------------image_filter_lanczos196
00419     class image_filter_lanczos196 : public image_filter_lanczos
00420     { public: image_filter_lanczos196() : image_filter_lanczos(7.0){} };
00421 
00422     //--------------------------------------------image_filter_lanczos256
00423     class image_filter_lanczos256 : public image_filter_lanczos
00424     { public: image_filter_lanczos256() : image_filter_lanczos(8.0){} };
00425 
00426     //--------------------------------------------image_filter_blackman36
00427     class image_filter_blackman36 : public image_filter_blackman
00428     { public: image_filter_blackman36() : image_filter_blackman(3.0){} };
00429 
00430     //--------------------------------------------image_filter_blackman64
00431     class image_filter_blackman64 : public image_filter_blackman
00432     { public: image_filter_blackman64() : image_filter_blackman(4.0){} };
00433 
00434     //-------------------------------------------image_filter_blackman100
00435     class image_filter_blackman100 : public image_filter_blackman
00436     { public: image_filter_blackman100() : image_filter_blackman(5.0){} };
00437 
00438     //-------------------------------------------image_filter_blackman144
00439     class image_filter_blackman144 : public image_filter_blackman
00440     { public: image_filter_blackman144() : image_filter_blackman(6.0){} };
00441 
00442     //-------------------------------------------image_filter_blackman196
00443     class image_filter_blackman196 : public image_filter_blackman
00444     { public: image_filter_blackman196() : image_filter_blackman(7.0){} };
00445 
00446     //-------------------------------------------image_filter_blackman256
00447     class image_filter_blackman256 : public image_filter_blackman
00448     { public: image_filter_blackman256() : image_filter_blackman(8.0){} };
00449 
00450 
00451 }
00452 
00453 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines