1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <math.h>
4 #include <time.h>
5 #include "agg_rendering_buffer.h"
6 #include "agg_rasterizer_scanline_aa.h"
7 #include "agg_ellipse.h"
8 #include "agg_trans_affine.h"
9 #include "agg_conv_transform.h"
10 #include "agg_conv_stroke.h"
11 #include "agg_pixfmt_rgb.h"
12 #include "agg_scanline_p.h"
13 #include "agg_renderer_scanline.h"
14 #include "agg_image_filters.h"
15 #include "ctrl/agg_slider_ctrl.h"
16 #include "ctrl/agg_rbox_ctrl.h"
17 #include "ctrl/agg_cbox_ctrl.h"
18 #include "platform/agg_platform_support.h"
19
20
21 enum flip_y_e { flip_y = true };
22
23
24 struct filter_base
25 {
26 virtual double radius() const = 0;
27 virtual void set_radius(double r) = 0;
28 virtual double calc_weight(double x) const = 0;
29 };
30
31
32 template<class Filter> struct image_filter_const_radius_adaptor : filter_base
33 {
radiusimage_filter_const_radius_adaptor34 virtual double radius() const { return m_filter.radius(); }
set_radiusimage_filter_const_radius_adaptor35 virtual void set_radius(double r) {}
calc_weightimage_filter_const_radius_adaptor36 virtual double calc_weight(double x) const { return m_filter.calc_weight(fabs(x)); }
37 Filter m_filter;
38 };
39
40
41 template<class Filter> struct image_filter_variable_radius_adaptor : filter_base
42 {
radiusimage_filter_variable_radius_adaptor43 virtual double radius() const { return m_filter.radius(); }
calc_weightimage_filter_variable_radius_adaptor44 virtual double calc_weight(double x) const { return m_filter.calc_weight(fabs(x)); }
set_radiusimage_filter_variable_radius_adaptor45 virtual void set_radius(double r) { m_filter = Filter(r); }
image_filter_variable_radius_adaptorimage_filter_variable_radius_adaptor46 image_filter_variable_radius_adaptor() : m_filter(2.0) {}
47 Filter m_filter;
48 };
49
50
51
52 class the_application : public agg::platform_support
53 {
54 agg::slider_ctrl<agg::rgba> m_radius;
55 agg::cbox_ctrl<agg::rgba> m_bilinear;
56 agg::cbox_ctrl<agg::rgba> m_bicubic;
57 agg::cbox_ctrl<agg::rgba> m_spline16;
58 agg::cbox_ctrl<agg::rgba> m_spline36;
59 agg::cbox_ctrl<agg::rgba> m_hanning;
60 agg::cbox_ctrl<agg::rgba> m_hamming;
61 agg::cbox_ctrl<agg::rgba> m_hermite;
62 agg::cbox_ctrl<agg::rgba> m_kaiser;
63 agg::cbox_ctrl<agg::rgba> m_quadric;
64 agg::cbox_ctrl<agg::rgba> m_catrom;
65 agg::cbox_ctrl<agg::rgba> m_gaussian;
66 agg::cbox_ctrl<agg::rgba> m_bessel;
67 agg::cbox_ctrl<agg::rgba> m_mitchell;
68 agg::cbox_ctrl<agg::rgba> m_sinc;
69 agg::cbox_ctrl<agg::rgba> m_lanczos;
70 agg::cbox_ctrl<agg::rgba> m_blackman;
71 agg::cbox_ctrl<agg::rgba>* m_filters[32];
72
73 image_filter_const_radius_adaptor<agg::image_filter_bilinear> m_filter_bilinear;
74 image_filter_const_radius_adaptor<agg::image_filter_bicubic> m_filter_bicubic;
75 image_filter_const_radius_adaptor<agg::image_filter_spline16> m_filter_spline16;
76 image_filter_const_radius_adaptor<agg::image_filter_spline36> m_filter_spline36;
77 image_filter_const_radius_adaptor<agg::image_filter_hanning> m_filter_hanning;
78 image_filter_const_radius_adaptor<agg::image_filter_hamming> m_filter_hamming;
79 image_filter_const_radius_adaptor<agg::image_filter_hermite> m_filter_hermite;
80 image_filter_const_radius_adaptor<agg::image_filter_kaiser> m_filter_kaiser;
81 image_filter_const_radius_adaptor<agg::image_filter_quadric> m_filter_quadric;
82 image_filter_const_radius_adaptor<agg::image_filter_catrom> m_filter_catrom;
83 image_filter_const_radius_adaptor<agg::image_filter_gaussian> m_filter_gaussian;
84 image_filter_const_radius_adaptor<agg::image_filter_bessel> m_filter_bessel;
85 image_filter_const_radius_adaptor<agg::image_filter_mitchell> m_filter_mitchell;
86 image_filter_variable_radius_adaptor<agg::image_filter_sinc> m_filter_sinc;
87 image_filter_variable_radius_adaptor<agg::image_filter_lanczos> m_filter_lanczos;
88 image_filter_variable_radius_adaptor<agg::image_filter_blackman> m_filter_blackman;
89
90 filter_base* m_filter_func[32];
91 unsigned m_num_filters;
92
93
94 public:
the_application(agg::pix_format_e format,bool flip_y)95 the_application(agg::pix_format_e format, bool flip_y) :
96 agg::platform_support(format, flip_y),
97 m_radius (5.0, 5.0, 780-5, 10.0, !flip_y),
98 m_bilinear (8.0, 30.0+15*0, "bilinear", !flip_y),
99 m_bicubic (8.0, 30.0+15*1, "bicubic ", !flip_y),
100 m_spline16 (8.0, 30.0+15*2, "spline16", !flip_y),
101 m_spline36 (8.0, 30.0+15*3, "spline36", !flip_y),
102 m_hanning (8.0, 30.0+15*4, "hanning ", !flip_y),
103 m_hamming (8.0, 30.0+15*5, "hamming ", !flip_y),
104 m_hermite (8.0, 30.0+15*6, "hermite ", !flip_y),
105 m_kaiser (8.0, 30.0+15*7, "kaiser ", !flip_y),
106 m_quadric (8.0, 30.0+15*8, "quadric ", !flip_y),
107 m_catrom (8.0, 30.0+15*9, "catrom ", !flip_y),
108 m_gaussian (8.0, 30.0+15*10, "gaussian", !flip_y),
109 m_bessel (8.0, 30.0+15*11, "bessel ", !flip_y),
110 m_mitchell (8.0, 30.0+15*12, "mitchell", !flip_y),
111 m_sinc (8.0, 30.0+15*13, "sinc ", !flip_y),
112 m_lanczos (8.0, 30.0+15*14, "lanczos ", !flip_y),
113 m_blackman (8.0, 30.0+15*15, "blackman", !flip_y),
114 m_num_filters(0)
115 {
116 m_filters[m_num_filters++] = &m_bilinear;
117 m_filters[m_num_filters++] = &m_bicubic;
118 m_filters[m_num_filters++] = &m_spline16;
119 m_filters[m_num_filters++] = &m_spline36;
120 m_filters[m_num_filters++] = &m_hanning;
121 m_filters[m_num_filters++] = &m_hamming;
122 m_filters[m_num_filters++] = &m_hermite;
123 m_filters[m_num_filters++] = &m_kaiser;
124 m_filters[m_num_filters++] = &m_quadric;
125 m_filters[m_num_filters++] = &m_catrom;
126 m_filters[m_num_filters++] = &m_gaussian;
127 m_filters[m_num_filters++] = &m_bessel;
128 m_filters[m_num_filters++] = &m_mitchell;
129 m_filters[m_num_filters++] = &m_sinc;
130 m_filters[m_num_filters++] = &m_lanczos;
131 m_filters[m_num_filters++] = &m_blackman;
132
133 unsigned i = 0;
134
135 m_filter_func[i++] = &m_filter_bilinear;
136 m_filter_func[i++] = &m_filter_bicubic;
137 m_filter_func[i++] = &m_filter_spline16;
138 m_filter_func[i++] = &m_filter_spline36;
139 m_filter_func[i++] = &m_filter_hanning;
140 m_filter_func[i++] = &m_filter_hamming;
141 m_filter_func[i++] = &m_filter_hermite;
142 m_filter_func[i++] = &m_filter_kaiser;
143 m_filter_func[i++] = &m_filter_quadric;
144 m_filter_func[i++] = &m_filter_catrom;
145 m_filter_func[i++] = &m_filter_gaussian;
146 m_filter_func[i++] = &m_filter_bessel;
147 m_filter_func[i++] = &m_filter_mitchell;
148 m_filter_func[i++] = &m_filter_sinc;
149 m_filter_func[i++] = &m_filter_lanczos;
150 m_filter_func[i++] = &m_filter_blackman;
151 for(i = 0; i < m_num_filters; i++)
152 {
153 add_ctrl(*m_filters[i]);
154 }
155
156 m_radius.range(2.0, 8.0);
157 m_radius.value(4.0);
158 m_radius.label("Radius=%.3f");
159 add_ctrl(m_radius);
160 }
161
~the_application()162 virtual ~the_application()
163 {
164 }
165
on_draw()166 virtual void on_draw()
167 {
168 typedef agg::pixfmt_bgr24 pixfmt;
169 typedef agg::renderer_base<pixfmt> renderer_base;
170 typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_solid;
171
172 pixfmt pixf(rbuf_window());
173 renderer_base rb(pixf);
174 renderer_solid rs(rb);
175
176 rb.clear(agg::rgba(1.0, 1.0, 1.0));
177 agg::rasterizer_scanline_aa<> ras;
178 agg::scanline_p8 sl;
179
180 double x_start = 125.0;
181 double x_end = initial_width() - 15.0;
182 double y_start = 10.0;
183 double y_end = initial_height() - 10.0;
184 double x_center = (x_start + x_end) / 2;
185
186 unsigned i;
187
188 agg::path_storage p;
189 agg::conv_stroke<agg::path_storage> pl(p);
190 agg::conv_transform<agg::conv_stroke<agg::path_storage> > tr(pl, trans_affine_resizing());
191
192 for(i = 0; i <= 16; i++)
193 {
194 double x = x_start + (x_end - x_start) * i / 16.0;
195 p.remove_all();
196 p.move_to(x+0.5, y_start);
197 p.line_to(x+0.5, y_end);
198 ras.add_path(tr);
199 rs.color(agg::rgba8(0, 0, 0, i == 8 ? 255 : 100));
200 agg::render_scanlines(ras, sl, rs);
201 }
202
203 double ys = y_start + (y_end - y_start) / 6.0;
204
205 p.remove_all();
206 p.move_to(x_start, ys);
207 p.line_to(x_end, ys);
208 ras.add_path(tr);
209 rs.color(agg::rgba8(0, 0, 0));
210 agg::render_scanlines(ras, sl, rs);
211
212
213 pl.width(1.0);
214
215 for(i = 0; i < m_num_filters; i++)
216 {
217 if(m_filters[i]->status())
218 {
219 m_filter_func[i]->set_radius(m_radius.value());
220 unsigned j;
221
222 double radius = m_filter_func[i]->radius();
223 unsigned n = unsigned(radius * 256 * 2);
224 double dy = y_end - ys;
225
226 double xs = (x_end + x_start)/2.0 - (radius * (x_end - x_start) / 16.0);
227 double dx = (x_end - x_start) * radius / 8.0;
228
229 p.remove_all();
230 p.move_to(xs+0.5, ys + dy * m_filter_func[i]->calc_weight(-radius));
231 for(j = 1; j < n; j++)
232 {
233 p.line_to(xs + dx * j / n + 0.5,
234 ys + dy * m_filter_func[i]->calc_weight(j / 256.0 - radius));
235 }
236 ras.add_path(tr);
237 rs.color(agg::rgba8(100, 0, 0));
238 agg::render_scanlines(ras, sl, rs);
239
240 p.remove_all();
241 unsigned xint;
242 int ir = int(ceil(radius) + 0.1);
243
244 for(xint = 0; xint < 256; xint++)
245 {
246 int xfract;
247 double sum = 0;
248 for(xfract = -ir; xfract < ir; xfract++)
249 {
250 double xf = xint/256.0 + xfract;
251 if(xf >= -radius || xf <= radius)
252 {
253 sum += m_filter_func[i]->calc_weight(xf);
254 }
255 }
256
257 double x = x_center + ((-128.0 + xint) / 128.0) * radius * (x_end - x_start) / 16.0;
258 double y = ys + sum * 256 - 256;
259
260 if(xint == 0) p.move_to(x, y);
261 else p.line_to(x, y);
262 }
263 ras.add_path(tr);
264 rs.color(agg::rgba8(0, 100, 0));
265 agg::render_scanlines(ras, sl, rs);
266
267 agg::image_filter_lut normalized(*m_filter_func[i]);
268 const agg::int16* weights = normalized.weight_array();
269
270 xs = (x_end + x_start)/2.0 - (normalized.diameter() * (x_end - x_start) / 32.0);
271 unsigned nn = normalized.diameter() * 256;
272 p.remove_all();
273 p.move_to(xs+0.5, ys + dy * weights[0] / agg::image_filter_scale);
274 for(j = 1; j < nn; j++)
275 {
276 p.line_to(xs + dx * j / n + 0.5,
277 ys + dy * weights[j] / agg::image_filter_scale);
278 }
279 ras.add_path(tr);
280 rs.color(agg::rgba8(0, 0, 100, 255));
281 agg::render_scanlines(ras, sl, rs);
282 }
283 }
284
285 for(i = 0; i < m_num_filters; i++)
286 {
287 agg::render_ctrl(ras, sl, rb, *m_filters[i]);
288 }
289 if(m_sinc.status() || m_lanczos.status() || m_blackman.status())
290 {
291 agg::render_ctrl(ras, sl, rb, m_radius);
292 }
293 }
294 };
295
296
297
298
299
300
301
agg_main(int argc,char * argv[])302 int agg_main(int argc, char* argv[])
303 {
304 the_application app(agg::pix_format_bgr24, flip_y);
305 app.caption("Image filters' shape comparison");
306
307 if(app.init(780, 300, agg::window_resize))
308 {
309 return app.run();
310 }
311 return 0;
312 }
313
314
315