Anti-Grain Geometry Tutorial
agg_image_filters.h
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 //
5 // Permission to copy, use, modify, sell and distribute this software
6 // is granted provided this copyright notice appears in all copies.
7 // This software is provided "as is" without express or implied
8 // warranty, and with no claim as to its suitability for any purpose.
9 //
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 // mcseemagg@yahoo.com
13 // http://www.antigrain.com
14 //----------------------------------------------------------------------------
15 //
16 // Image transformation filters,
17 // Filtering classes (image_filter_lut, image_filter),
18 // Basic filter shape classes
19 //----------------------------------------------------------------------------
20 #ifndef AGG_IMAGE_FILTERS_INCLUDED
21 #define AGG_IMAGE_FILTERS_INCLUDED
22 
23 #include "agg_array.h"
24 #include "agg_math.h"
25 
26 namespace agg
27 {
28 
29  // See Implementation agg_image_filters.cpp
30 
31  enum image_filter_scale_e
32  {
33  image_filter_shift = 14, //----image_filter_shift
34  image_filter_scale = 1 << image_filter_shift, //----image_filter_scale
35  image_filter_mask = image_filter_scale - 1 //----image_filter_mask
36  };
37 
38  enum image_subpixel_scale_e
39  {
40  image_subpixel_shift = 8, //----image_subpixel_shift
41  image_subpixel_scale = 1 << image_subpixel_shift, //----image_subpixel_scale
42  image_subpixel_mask = image_subpixel_scale - 1 //----image_subpixel_mask
43  };
44 
45 
46  //-----------------------------------------------------image_filter_lut
48  {
49  public:
50  template<class FilterF> void calculate(const FilterF& filter,
51  bool normalization=true)
52  {
53  filter; // prevent erroneous C4100 in MSVC
54  double r = filter.radius();
55  realloc_lut(r);
56  unsigned i;
57  unsigned pivot = diameter() << (image_subpixel_shift - 1);
58  for(i = 0; i < pivot; i++)
59  {
60  double x = double(i) / double(image_subpixel_scale);
61  double y = filter.calc_weight(x);
62  m_weight_array[pivot + i] =
63  m_weight_array[pivot - i] = (int16)iround(y * image_filter_scale);
64  }
65  unsigned end = (diameter() << image_subpixel_shift) - 1;
66  m_weight_array[0] = m_weight_array[end];
67  if(normalization)
68  {
69  normalize();
70  }
71  }
72 
73  image_filter_lut() : m_radius(0), m_diameter(0), m_start(0) {}
74 
75  template<class FilterF> image_filter_lut(const FilterF& filter,
76  bool normalization=true)
77  {
78  calculate(filter, normalization);
79  }
80 
81  double radius() const { return m_radius; }
82  unsigned diameter() const { return m_diameter; }
83  int start() const { return m_start; }
84  const int16* weight_array() const { return &m_weight_array[0]; }
85  void normalize();
86 
87  private:
88  void realloc_lut(double radius);
90  const image_filter_lut& operator = (const image_filter_lut&);
91 
92  double m_radius;
93  unsigned m_diameter;
94  int m_start;
95  pod_array<int16> m_weight_array;
96  };
97 
98 
99 
100  //--------------------------------------------------------image_filter
101  template<class FilterF> class image_filter : public image_filter_lut
102  {
103  public:
104  image_filter()
105  {
106  calculate(m_filter_function);
107  }
108  private:
109  FilterF m_filter_function;
110  };
111 
112 
113  //-----------------------------------------------image_filter_bilinear
115  {
116  static double radius() { return 1.0; }
117  static double calc_weight(double x)
118  {
119  return 1.0 - x;
120  }
121  };
122 
123 
124  //-----------------------------------------------image_filter_hanning
126  {
127  static double radius() { return 1.0; }
128  static double calc_weight(double x)
129  {
130  return 0.5 + 0.5 * std::cos(pi * x);
131  }
132  };
133 
134 
135  //-----------------------------------------------image_filter_hamming
137  {
138  static double radius() { return 1.0; }
139  static double calc_weight(double x)
140  {
141  return 0.54 + 0.46 * std::cos(pi * x);
142  }
143  };
144 
145  //-----------------------------------------------image_filter_hermite
147  {
148  static double radius() { return 1.0; }
149  static double calc_weight(double x)
150  {
151  return (2.0 * x - 3.0) * x * x + 1.0;
152  }
153  };
154 
155  //------------------------------------------------image_filter_quadric
157  {
158  static double radius() { return 1.5; }
159  static double calc_weight(double x)
160  {
161  double t;
162  if(x < 0.5) return 0.75 - x * x;
163  if(x < 1.5) {t = x - 1.5; return 0.5 * t * t;}
164  return 0.0;
165  }
166  };
167 
168  //------------------------------------------------image_filter_bicubic
170  {
171  static double pow3(double x)
172  {
173  return (x <= 0.0) ? 0.0 : x * x * x;
174  }
175 
176  public:
177  static double radius() { return 2.0; }
178  static double calc_weight(double x)
179  {
180  return
181  (1.0/6.0) *
182  (pow3(x + 2) - 4 * pow3(x + 1) + 6 * pow3(x) - 4 * pow3(x - 1));
183  }
184  };
185 
186  //-------------------------------------------------image_filter_kaiser
188  {
189  double a;
190  double i0a;
191  double epsilon;
192 
193  public:
194  image_filter_kaiser(double b = 6.33) :
195  a(b), epsilon(1e-12)
196  {
197  i0a = 1.0 / bessel_i0(b);
198  }
199 
200  static double radius() { return 1.0; }
201  double calc_weight(double x) const
202  {
203  return bessel_i0(a * std::sqrt(1. - x * x)) * i0a;
204  }
205 
206  private:
207  double bessel_i0(double x) const
208  {
209  int i;
210  double sum, y, t;
211 
212  sum = 1.;
213  y = x * x / 4.;
214  t = y;
215 
216  for(i = 2; t > epsilon; i++)
217  {
218  sum += t;
219  t *= (double)y / (i * i);
220  }
221  return sum;
222  }
223  };
224 
225  //----------------------------------------------image_filter_catrom
227  {
228  static double radius() { return 2.0; }
229  static double calc_weight(double x)
230  {
231  if(x < 1.0) return 0.5 * (2.0 + x * x * (-5.0 + x * 3.0));
232  if(x < 2.0) return 0.5 * (4.0 + x * (-8.0 + x * (5.0 - x)));
233  return 0.;
234  }
235  };
236 
237  //---------------------------------------------image_filter_mitchell
239  {
240  double p0, p2, p3;
241  double q0, q1, q2, q3;
242 
243  public:
244  image_filter_mitchell(double b = 1.0/3.0, double c = 1.0/3.0) :
245  p0((6.0 - 2.0 * b) / 6.0),
246  p2((-18.0 + 12.0 * b + 6.0 * c) / 6.0),
247  p3((12.0 - 9.0 * b - 6.0 * c) / 6.0),
248  q0((8.0 * b + 24.0 * c) / 6.0),
249  q1((-12.0 * b - 48.0 * c) / 6.0),
250  q2((6.0 * b + 30.0 * c) / 6.0),
251  q3((-b - 6.0 * c) / 6.0)
252  {}
253 
254  static double radius() { return 2.0; }
255  double calc_weight(double x) const
256  {
257  if(x < 1.0) return p0 + x * x * (p2 + x * p3);
258  if(x < 2.0) return q0 + x * (q1 + x * (q2 + x * q3));
259  return 0.0;
260  }
261  };
262 
263 
264  //----------------------------------------------image_filter_spline16
266  {
267  static double radius() { return 2.0; }
268  static double calc_weight(double x)
269  {
270  if(x < 1.0)
271  {
272  return ((x - 9.0/5.0 ) * x - 1.0/5.0 ) * x + 1.0;
273  }
274  return ((-1.0/3.0 * (x-1) + 4.0/5.0) * (x-1) - 7.0/15.0 ) * (x-1);
275  }
276  };
277 
278 
279  //---------------------------------------------image_filter_spline36
281  {
282  static double radius() { return 3.0; }
283  static double calc_weight(double x)
284  {
285  if(x < 1.0)
286  {
287  return ((13.0/11.0 * x - 453.0/209.0) * x - 3.0/209.0) * x + 1.0;
288  }
289  if(x < 2.0)
290  {
291  return ((-6.0/11.0 * (x-1) + 270.0/209.0) * (x-1) - 156.0/ 209.0) * (x-1);
292  }
293  return ((1.0/11.0 * (x-2) - 45.0/209.0) * (x-2) + 26.0/209.0) * (x-2);
294  }
295  };
296 
297 
298  //----------------------------------------------image_filter_gaussian
300  {
301  static double radius() { return 2.0; }
302  static double calc_weight(double x)
303  {
304  return std::exp(-2.0 * x * x) * std::sqrt(2.0 / pi);
305  }
306  };
307 
308 
309  //------------------------------------------------image_filter_bessel
311  {
312  static double radius() { return 3.2383; }
313  static double calc_weight(double x)
314  {
315  return (x == 0.0) ? pi / 4.0 : besj(pi * x, 1) / (2.0 * x);
316  }
317  };
318 
319 
320  //-------------------------------------------------image_filter_sinc
322  {
323  public:
324  image_filter_sinc(double r) : m_radius(r < 2.0 ? 2.0 : r) {}
325  double radius() const { return m_radius; }
326  double calc_weight(double x) const
327  {
328  if(x == 0.0) return 1.0;
329  x *= pi;
330  return std::sin(x) / x;
331  }
332  private:
333  double m_radius;
334  };
335 
336 
337  //-----------------------------------------------image_filter_lanczos
339  {
340  public:
341  image_filter_lanczos(double r) : m_radius(r < 2.0 ? 2.0 : r) {}
342  double radius() const { return m_radius; }
343  double calc_weight(double x) const
344  {
345  if(x == 0.0) return 1.0;
346  if(x > m_radius) return 0.0;
347  x *= pi;
348  double xr = x / m_radius;
349  return (std::sin(x) / x) * (std::sin(xr) / xr);
350  }
351  private:
352  double m_radius;
353  };
354 
355 
356  //----------------------------------------------image_filter_blackman
358  {
359  public:
360  image_filter_blackman(double r) : m_radius(r < 2.0 ? 2.0 : r) {}
361  double radius() const { return m_radius; }
362  double calc_weight(double x) const
363  {
364  if(x == 0.0) return 1.0;
365  if(x > m_radius) return 0.0;
366  x *= pi;
367  double xr = x / m_radius;
368  return (std::sin(x) / x) * (0.42 + 0.5*std::cos(xr) + 0.08*std::cos(2*xr));
369  }
370  private:
371  double m_radius;
372  };
373 
374  //------------------------------------------------image_filter_sinc36
376  { public: image_filter_sinc36() : image_filter_sinc(3.0){} };
377 
378  //------------------------------------------------image_filter_sinc64
380  { public: image_filter_sinc64() : image_filter_sinc(4.0){} };
381 
382  //-----------------------------------------------image_filter_sinc100
384  { public: image_filter_sinc100() : image_filter_sinc(5.0){} };
385 
386  //-----------------------------------------------image_filter_sinc144
388  { public: image_filter_sinc144() : image_filter_sinc(6.0){} };
389 
390  //-----------------------------------------------image_filter_sinc196
392  { public: image_filter_sinc196() : image_filter_sinc(7.0){} };
393 
394  //-----------------------------------------------image_filter_sinc256
396  { public: image_filter_sinc256() : image_filter_sinc(8.0){} };
397 
398  //---------------------------------------------image_filter_lanczos36
400  { public: image_filter_lanczos36() : image_filter_lanczos(3.0){} };
401 
402  //---------------------------------------------image_filter_lanczos64
404  { public: image_filter_lanczos64() : image_filter_lanczos(4.0){} };
405 
406  //--------------------------------------------image_filter_lanczos100
408  { public: image_filter_lanczos100() : image_filter_lanczos(5.0){} };
409 
410  //--------------------------------------------image_filter_lanczos144
412  { public: image_filter_lanczos144() : image_filter_lanczos(6.0){} };
413 
414  //--------------------------------------------image_filter_lanczos196
416  { public: image_filter_lanczos196() : image_filter_lanczos(7.0){} };
417 
418  //--------------------------------------------image_filter_lanczos256
420  { public: image_filter_lanczos256() : image_filter_lanczos(8.0){} };
421 
422  //--------------------------------------------image_filter_blackman36
424  { public: image_filter_blackman36() : image_filter_blackman(3.0){} };
425 
426  //--------------------------------------------image_filter_blackman64
428  { public: image_filter_blackman64() : image_filter_blackman(4.0){} };
429 
430  //-------------------------------------------image_filter_blackman100
432  { public: image_filter_blackman100() : image_filter_blackman(5.0){} };
433 
434  //-------------------------------------------image_filter_blackman144
436  { public: image_filter_blackman144() : image_filter_blackman(6.0){} };
437 
438  //-------------------------------------------image_filter_blackman196
440  { public: image_filter_blackman196() : image_filter_blackman(7.0){} };
441 
442  //-------------------------------------------image_filter_blackman256
444  { public: image_filter_blackman256() : image_filter_blackman(8.0){} };
445 
446 
447 }
448 
449 #endif
Definition: agg_arc.cpp:24