00001 #include <stdio.h> 00002 #include <stdlib.h> 00003 #include <math.h> 00004 #include <time.h> 00005 #include "agg_rendering_buffer.h" 00006 #include "agg_rasterizer_scanline_aa.h" 00007 #include "agg_ellipse.h" 00008 #include "agg_trans_affine.h" 00009 #include "agg_conv_transform.h" 00010 #include "agg_conv_stroke.h" 00011 #include "agg_pixfmt_rgb.h" 00012 #include "agg_scanline_p.h" 00013 #include "agg_renderer_scanline.h" 00014 #include "agg_image_filters.h" 00015 #include "ctrl/agg_slider_ctrl.h" 00016 #include "ctrl/agg_rbox_ctrl.h" 00017 #include "ctrl/agg_cbox_ctrl.h" 00018 #include "platform/agg_platform_support.h" 00019 00020 00021 enum flip_y_e { flip_y = true }; 00022 00023 00024 struct filter_base 00025 { 00026 virtual double radius() const = 0; 00027 virtual void set_radius(double r) = 0; 00028 virtual double calc_weight(double x) const = 0; 00029 }; 00030 00031 00032 template<class Filter> struct image_filter_const_radius_adaptor : filter_base 00033 { 00034 virtual double radius() const { return m_filter.radius(); } 00035 virtual void set_radius(double r) {} 00036 virtual double calc_weight(double x) const { return m_filter.calc_weight(fabs(x)); } 00037 Filter m_filter; 00038 }; 00039 00040 00041 template<class Filter> struct image_filter_variable_radius_adaptor : filter_base 00042 { 00043 virtual double radius() const { return m_filter.radius(); } 00044 virtual double calc_weight(double x) const { return m_filter.calc_weight(fabs(x)); } 00045 virtual void set_radius(double r) { m_filter = Filter(r); } 00046 image_filter_variable_radius_adaptor() : m_filter(2.0) {} 00047 Filter m_filter; 00048 }; 00049 00050 00051 00052 class the_application : public agg::platform_support 00053 { 00054 agg::slider_ctrl<agg::rgba> m_radius; 00055 agg::cbox_ctrl<agg::rgba> m_bilinear; 00056 agg::cbox_ctrl<agg::rgba> m_bicubic; 00057 agg::cbox_ctrl<agg::rgba> m_spline16; 00058 agg::cbox_ctrl<agg::rgba> m_spline36; 00059 agg::cbox_ctrl<agg::rgba> m_hanning; 00060 agg::cbox_ctrl<agg::rgba> m_hamming; 00061 agg::cbox_ctrl<agg::rgba> m_hermite; 00062 agg::cbox_ctrl<agg::rgba> m_kaiser; 00063 agg::cbox_ctrl<agg::rgba> m_quadric; 00064 agg::cbox_ctrl<agg::rgba> m_catrom; 00065 agg::cbox_ctrl<agg::rgba> m_gaussian; 00066 agg::cbox_ctrl<agg::rgba> m_bessel; 00067 agg::cbox_ctrl<agg::rgba> m_mitchell; 00068 agg::cbox_ctrl<agg::rgba> m_sinc; 00069 agg::cbox_ctrl<agg::rgba> m_lanczos; 00070 agg::cbox_ctrl<agg::rgba> m_blackman; 00071 agg::cbox_ctrl<agg::rgba>* m_filters[32]; 00072 00073 image_filter_const_radius_adaptor<agg::image_filter_bilinear> m_filter_bilinear; 00074 image_filter_const_radius_adaptor<agg::image_filter_bicubic> m_filter_bicubic; 00075 image_filter_const_radius_adaptor<agg::image_filter_spline16> m_filter_spline16; 00076 image_filter_const_radius_adaptor<agg::image_filter_spline36> m_filter_spline36; 00077 image_filter_const_radius_adaptor<agg::image_filter_hanning> m_filter_hanning; 00078 image_filter_const_radius_adaptor<agg::image_filter_hamming> m_filter_hamming; 00079 image_filter_const_radius_adaptor<agg::image_filter_hermite> m_filter_hermite; 00080 image_filter_const_radius_adaptor<agg::image_filter_kaiser> m_filter_kaiser; 00081 image_filter_const_radius_adaptor<agg::image_filter_quadric> m_filter_quadric; 00082 image_filter_const_radius_adaptor<agg::image_filter_catrom> m_filter_catrom; 00083 image_filter_const_radius_adaptor<agg::image_filter_gaussian> m_filter_gaussian; 00084 image_filter_const_radius_adaptor<agg::image_filter_bessel> m_filter_bessel; 00085 image_filter_const_radius_adaptor<agg::image_filter_mitchell> m_filter_mitchell; 00086 image_filter_variable_radius_adaptor<agg::image_filter_sinc> m_filter_sinc; 00087 image_filter_variable_radius_adaptor<agg::image_filter_lanczos> m_filter_lanczos; 00088 image_filter_variable_radius_adaptor<agg::image_filter_blackman> m_filter_blackman; 00089 00090 filter_base* m_filter_func[32]; 00091 unsigned m_num_filters; 00092 00093 00094 public: 00095 the_application(agg::pix_format_e format, bool flip_y) : 00096 agg::platform_support(format, flip_y), 00097 m_radius (5.0, 5.0, 780-5, 10.0, !flip_y), 00098 m_bilinear (8.0, 30.0+15*0, "bilinear", !flip_y), 00099 m_bicubic (8.0, 30.0+15*1, "bicubic ", !flip_y), 00100 m_spline16 (8.0, 30.0+15*2, "spline16", !flip_y), 00101 m_spline36 (8.0, 30.0+15*3, "spline36", !flip_y), 00102 m_hanning (8.0, 30.0+15*4, "hanning ", !flip_y), 00103 m_hamming (8.0, 30.0+15*5, "hamming ", !flip_y), 00104 m_hermite (8.0, 30.0+15*6, "hermite ", !flip_y), 00105 m_kaiser (8.0, 30.0+15*7, "kaiser ", !flip_y), 00106 m_quadric (8.0, 30.0+15*8, "quadric ", !flip_y), 00107 m_catrom (8.0, 30.0+15*9, "catrom ", !flip_y), 00108 m_gaussian (8.0, 30.0+15*10, "gaussian", !flip_y), 00109 m_bessel (8.0, 30.0+15*11, "bessel ", !flip_y), 00110 m_mitchell (8.0, 30.0+15*12, "mitchell", !flip_y), 00111 m_sinc (8.0, 30.0+15*13, "sinc ", !flip_y), 00112 m_lanczos (8.0, 30.0+15*14, "lanczos ", !flip_y), 00113 m_blackman (8.0, 30.0+15*15, "blackman", !flip_y), 00114 m_num_filters(0) 00115 { 00116 m_filters[m_num_filters++] = &m_bilinear; 00117 m_filters[m_num_filters++] = &m_bicubic; 00118 m_filters[m_num_filters++] = &m_spline16; 00119 m_filters[m_num_filters++] = &m_spline36; 00120 m_filters[m_num_filters++] = &m_hanning; 00121 m_filters[m_num_filters++] = &m_hamming; 00122 m_filters[m_num_filters++] = &m_hermite; 00123 m_filters[m_num_filters++] = &m_kaiser; 00124 m_filters[m_num_filters++] = &m_quadric; 00125 m_filters[m_num_filters++] = &m_catrom; 00126 m_filters[m_num_filters++] = &m_gaussian; 00127 m_filters[m_num_filters++] = &m_bessel; 00128 m_filters[m_num_filters++] = &m_mitchell; 00129 m_filters[m_num_filters++] = &m_sinc; 00130 m_filters[m_num_filters++] = &m_lanczos; 00131 m_filters[m_num_filters++] = &m_blackman; 00132 00133 unsigned i = 0; 00134 00135 m_filter_func[i++] = &m_filter_bilinear; 00136 m_filter_func[i++] = &m_filter_bicubic; 00137 m_filter_func[i++] = &m_filter_spline16; 00138 m_filter_func[i++] = &m_filter_spline36; 00139 m_filter_func[i++] = &m_filter_hanning; 00140 m_filter_func[i++] = &m_filter_hamming; 00141 m_filter_func[i++] = &m_filter_hermite; 00142 m_filter_func[i++] = &m_filter_kaiser; 00143 m_filter_func[i++] = &m_filter_quadric; 00144 m_filter_func[i++] = &m_filter_catrom; 00145 m_filter_func[i++] = &m_filter_gaussian; 00146 m_filter_func[i++] = &m_filter_bessel; 00147 m_filter_func[i++] = &m_filter_mitchell; 00148 m_filter_func[i++] = &m_filter_sinc; 00149 m_filter_func[i++] = &m_filter_lanczos; 00150 m_filter_func[i++] = &m_filter_blackman; 00151 for(i = 0; i < m_num_filters; i++) 00152 { 00153 add_ctrl(*m_filters[i]); 00154 } 00155 00156 m_radius.range(2.0, 8.0); 00157 m_radius.value(4.0); 00158 m_radius.label("Radius=%.3f"); 00159 add_ctrl(m_radius); 00160 } 00161 00162 virtual ~the_application() 00163 { 00164 } 00165 00166 virtual void on_draw() 00167 { 00168 typedef agg::pixfmt_bgr24 pixfmt; 00169 typedef agg::renderer_base<pixfmt> renderer_base; 00170 typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_solid; 00171 00172 pixfmt pixf(rbuf_window()); 00173 renderer_base rb(pixf); 00174 renderer_solid rs(rb); 00175 00176 rb.clear(agg::rgba(1.0, 1.0, 1.0)); 00177 agg::rasterizer_scanline_aa<> ras; 00178 agg::scanline_p8 sl; 00179 00180 double x_start = 125.0; 00181 double x_end = initial_width() - 15.0; 00182 double y_start = 10.0; 00183 double y_end = initial_height() - 10.0; 00184 double x_center = (x_start + x_end) / 2; 00185 00186 unsigned i; 00187 00188 agg::path_storage p; 00189 agg::conv_stroke<agg::path_storage> pl(p); 00190 agg::conv_transform<agg::conv_stroke<agg::path_storage> > tr(pl, trans_affine_resizing()); 00191 00192 for(i = 0; i <= 16; i++) 00193 { 00194 double x = x_start + (x_end - x_start) * i / 16.0; 00195 p.remove_all(); 00196 p.move_to(x+0.5, y_start); 00197 p.line_to(x+0.5, y_end); 00198 ras.add_path(tr); 00199 rs.color(agg::rgba8(0, 0, 0, i == 8 ? 255 : 100)); 00200 agg::render_scanlines(ras, sl, rs); 00201 } 00202 00203 double ys = y_start + (y_end - y_start) / 6.0; 00204 00205 p.remove_all(); 00206 p.move_to(x_start, ys); 00207 p.line_to(x_end, ys); 00208 ras.add_path(tr); 00209 rs.color(agg::rgba8(0, 0, 0)); 00210 agg::render_scanlines(ras, sl, rs); 00211 00212 00213 pl.width(1.0); 00214 00215 for(i = 0; i < m_num_filters; i++) 00216 { 00217 if(m_filters[i]->status()) 00218 { 00219 m_filter_func[i]->set_radius(m_radius.value()); 00220 unsigned j; 00221 00222 double radius = m_filter_func[i]->radius(); 00223 unsigned n = unsigned(radius * 256 * 2); 00224 double dy = y_end - ys; 00225 00226 double xs = (x_end + x_start)/2.0 - (radius * (x_end - x_start) / 16.0); 00227 double dx = (x_end - x_start) * radius / 8.0; 00228 00229 p.remove_all(); 00230 p.move_to(xs+0.5, ys + dy * m_filter_func[i]->calc_weight(-radius)); 00231 for(j = 1; j < n; j++) 00232 { 00233 p.line_to(xs + dx * j / n + 0.5, 00234 ys + dy * m_filter_func[i]->calc_weight(j / 256.0 - radius)); 00235 } 00236 ras.add_path(tr); 00237 rs.color(agg::rgba8(100, 0, 0)); 00238 agg::render_scanlines(ras, sl, rs); 00239 00240 p.remove_all(); 00241 unsigned xint; 00242 int ir = int(ceil(radius) + 0.1); 00243 00244 for(xint = 0; xint < 256; xint++) 00245 { 00246 int xfract; 00247 double sum = 0; 00248 for(xfract = -ir; xfract < ir; xfract++) 00249 { 00250 double xf = xint/256.0 + xfract; 00251 if(xf >= -radius || xf <= radius) 00252 { 00253 sum += m_filter_func[i]->calc_weight(xf); 00254 } 00255 } 00256 00257 double x = x_center + ((-128.0 + xint) / 128.0) * radius * (x_end - x_start) / 16.0; 00258 double y = ys + sum * 256 - 256; 00259 00260 if(xint == 0) p.move_to(x, y); 00261 else p.line_to(x, y); 00262 } 00263 ras.add_path(tr); 00264 rs.color(agg::rgba8(0, 100, 0)); 00265 agg::render_scanlines(ras, sl, rs); 00266 00267 agg::image_filter_lut normalized(*m_filter_func[i]); 00268 const agg::int16* weights = normalized.weight_array(); 00269 00270 xs = (x_end + x_start)/2.0 - (normalized.diameter() * (x_end - x_start) / 32.0); 00271 unsigned nn = normalized.diameter() * 256; 00272 p.remove_all(); 00273 p.move_to(xs+0.5, ys + dy * weights[0] / agg::image_filter_scale); 00274 for(j = 1; j < nn; j++) 00275 { 00276 p.line_to(xs + dx * j / n + 0.5, 00277 ys + dy * weights[j] / agg::image_filter_scale); 00278 } 00279 ras.add_path(tr); 00280 rs.color(agg::rgba8(0, 0, 100, 255)); 00281 agg::render_scanlines(ras, sl, rs); 00282 } 00283 } 00284 00285 for(i = 0; i < m_num_filters; i++) 00286 { 00287 agg::render_ctrl(ras, sl, rb, *m_filters[i]); 00288 } 00289 if(m_sinc.status() || m_lanczos.status() || m_blackman.status()) 00290 { 00291 agg::render_ctrl(ras, sl, rb, m_radius); 00292 } 00293 } 00294 }; 00295 00296 00297 00298 00299 00300 00301 00302 int agg_main(int argc, char* argv[]) 00303 { 00304 the_application app(agg::pix_format_bgr24, flip_y); 00305 app.caption("Image filters' shape comparison"); 00306 00307 if(app.init(780, 300, agg::window_resize)) 00308 { 00309 return app.run(); 00310 } 00311 return 0; 00312 } 00313 00314