Anti-Grain Geometry - AGG (libagg)
2.5
|
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