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_scanline_u.h"
00011 #include "agg_scanline_p.h"
00012 #include "agg_image_accessors.h"
00013 #include "agg_renderer_scanline.h"
00014 #include "agg_span_allocator.h"
00015 #include "agg_span_interpolator_linear.h"
00016 #include "ctrl/agg_slider_ctrl.h"
00017 #include "ctrl/agg_rbox_ctrl.h"
00018 #include "ctrl/agg_cbox_ctrl.h"
00019 #include "platform/agg_platform_support.h"
00020
00021
00022 #include "agg_pixfmt_rgb.h"
00023 #include "agg_span_image_filter_rgb.h"
00024 #define span_image_filter span_image_filter_rgb
00025 #define span_image_filter_nn span_image_filter_rgb_nn
00026 #define span_image_filter_bilinear span_image_filter_rgb_bilinear_clip
00027 #define span_image_filter_2x2 span_image_filter_rgb_2x2
00028 #define pix_format agg::pix_format_bgr24
00029 typedef agg::pixfmt_bgr24 pixfmt;
00030 typedef agg::pixfmt_bgr24_pre pixfmt_pre;
00031 typedef pixfmt::color_type color_type;
00032
00033 enum flip_y_e { flip_y = true };
00034
00035
00036
00037
00038
00039
00040 #define AGG_ACCURATE_TIME
00041
00042
00043 class the_application : public agg::platform_support
00044 {
00045 typedef agg::renderer_base<pixfmt> renderer_base;
00046 typedef agg::renderer_base<pixfmt_pre> renderer_base_pre;
00047
00048 agg::slider_ctrl<agg::rgba> m_radius;
00049 agg::slider_ctrl<agg::rgba> m_step;
00050 agg::rbox_ctrl<agg::rgba> m_filters;
00051 agg::cbox_ctrl<agg::rgba> m_normalize;
00052 agg::cbox_ctrl<agg::rgba> m_run;
00053 agg::cbox_ctrl<agg::rgba> m_single_step;
00054 agg::cbox_ctrl<agg::rgba> m_refresh;
00055
00056 double m_cur_angle;
00057 int m_cur_filter;
00058 int m_num_steps;
00059 double m_num_pix;
00060 double m_time1;
00061 double m_time2;
00062
00063 public:
00064 the_application(agg::pix_format_e format, bool flip_y) :
00065 agg::platform_support(format, flip_y),
00066 m_step (115, 5, 400, 11, !flip_y),
00067 m_radius(115, 5+15, 400, 11+15, !flip_y),
00068 m_filters(0.0, 0.0, 110.0, 210.0, !flip_y),
00069 m_normalize (8.0, 215.0, "Normalize Filter", !flip_y),
00070 m_run (8.0, 245.0, "RUN Test!", !flip_y),
00071 m_single_step(8.0, 230.0, "Single Step", !flip_y),
00072 m_refresh (8.0, 265.0, "Refresh", !flip_y),
00073 m_cur_angle(0.0),
00074 m_cur_filter(1),
00075 m_num_steps(0),
00076 m_num_pix(0.0),
00077 m_time1(0),
00078 m_time2(0)
00079 {
00080 add_ctrl(m_radius);
00081 add_ctrl(m_step);
00082 add_ctrl(m_filters);
00083 add_ctrl(m_run);
00084 add_ctrl(m_single_step);
00085 add_ctrl(m_normalize);
00086 add_ctrl(m_refresh);
00087 m_run.text_size(7.5);
00088 m_single_step.text_size(7.5);
00089 m_normalize.text_size(7.5);
00090 m_refresh.text_size(7.5);
00091 m_normalize.status(true);
00092
00093 m_radius.label("Filter Radius=%.3f");
00094 m_step.label("Step=%3.2f");
00095 m_radius.range(2.0, 8.0);
00096 m_radius.value(4.0);
00097 m_step.range(1.0, 10.0);
00098 m_step.value(5.0);
00099
00100 m_filters.add_item("simple (NN)");
00101 m_filters.add_item("bilinear");
00102 m_filters.add_item("bicubic");
00103 m_filters.add_item("spline16");
00104 m_filters.add_item("spline36");
00105 m_filters.add_item("hanning");
00106 m_filters.add_item("hamming");
00107 m_filters.add_item("hermite");
00108 m_filters.add_item("kaiser");
00109 m_filters.add_item("quadric");
00110 m_filters.add_item("catrom");
00111 m_filters.add_item("gaussian");
00112 m_filters.add_item("bessel");
00113 m_filters.add_item("mitchell");
00114 m_filters.add_item("sinc");
00115 m_filters.add_item("lanczos");
00116 m_filters.add_item("blackman");
00117 m_filters.cur_item(1);
00118
00119 m_filters.border_width(0, 0);
00120 m_filters.background_color(agg::rgba(0.0, 0.0, 0.0, 0.1));
00121 m_filters.text_size(6.0);
00122 m_filters.text_thickness(0.85);
00123 }
00124
00125 virtual ~the_application()
00126 {
00127 }
00128
00129 virtual void on_draw()
00130 {
00131 pixfmt pixf(rbuf_window());
00132 renderer_base rb(pixf);
00133
00134 rb.clear(agg::rgba(1.0, 1.0, 1.0));
00135 rb.copy_from(rbuf_img(0), 0, 110, 35);
00136
00137 agg::rasterizer_scanline_aa<> ras;
00138 agg::scanline_p8 sl;
00139
00140 char buf[64];
00141 sprintf(buf, "NSteps=%d", m_num_steps);
00142 agg::gsv_text t;
00143 t.start_point(10.0, 295.0);
00144 t.size(10.0);
00145 t.text(buf);
00146
00147 agg::conv_stroke<agg::gsv_text> pt(t);
00148 pt.width(1.5);
00149
00150 ras.add_path(pt);
00151 agg::render_scanlines_aa_solid(ras, sl, rb, agg::rgba(0,0,0));
00152
00153 if(m_time1 != m_time2 && m_num_pix > 0.0)
00154 {
00155 #ifdef AGG_ACCURATE_TIME
00156 sprintf(buf, "%3.2f Kpix/sec", m_num_pix / (m_time2 - m_time1));
00157 #else
00158 sprintf(buf, "%3.2f Kpix/sec", m_num_pix /
00159 1000.0 /
00160 (double(m_time2 - m_time1) / CLOCKS_PER_SEC));
00161 #endif
00162 t.start_point(10.0, 310.0);
00163 t.text(buf);
00164 ras.add_path(pt);
00165 agg::render_scanlines_aa_solid(ras, sl, rb, agg::rgba(0,0,0));
00166 }
00167
00168 if(m_filters.cur_item() >= 14)
00169 {
00170 agg::render_ctrl(ras, sl, rb, m_radius);
00171 }
00172 agg::render_ctrl(ras, sl, rb, m_step);
00173 agg::render_ctrl(ras, sl, rb, m_filters);
00174 agg::render_ctrl(ras, sl, rb, m_run);
00175 agg::render_ctrl(ras, sl, rb, m_normalize);
00176 agg::render_ctrl(ras, sl, rb, m_single_step);
00177 agg::render_ctrl(ras, sl, rb, m_refresh);
00178 }
00179
00180
00181
00182 void transform_image(double angle)
00183 {
00184 double width = rbuf_img(0).width();
00185 double height = rbuf_img(0).height();
00186
00187 pixfmt pixf(rbuf_img(0));
00188 pixfmt_pre pixf_pre(rbuf_img(0));
00189 renderer_base rb(pixf);
00190 renderer_base_pre rb_pre(pixf_pre);
00191
00192 rb.clear(agg::rgba(1.0, 1.0, 1.0));
00193
00194 agg::rasterizer_scanline_aa<> ras;
00195 agg::scanline_u8 sl;
00196 agg::span_allocator<color_type> sa;
00197
00198 agg::trans_affine src_mtx;
00199 src_mtx *= agg::trans_affine_translation(-width/2.0, -height/2.0);
00200 src_mtx *= agg::trans_affine_rotation(angle * agg::pi / 180.0);
00201 src_mtx *= agg::trans_affine_translation(width/2.0, height/2.0);
00202
00203 agg::trans_affine img_mtx = src_mtx;
00204 img_mtx.invert();
00205
00206 double r = width;
00207 if(height < r) r = height;
00208
00209 r *= 0.5;
00210 r -= 4.0;
00211 agg::ellipse ell(width / 2.0,
00212 height / 2.0,
00213 r, r, 200);
00214 agg::conv_transform<agg::ellipse> tr(ell, src_mtx);
00215
00216 m_num_pix += r * r * agg::pi;
00217
00218 typedef agg::span_interpolator_linear<> interpolator_type;
00219 interpolator_type interpolator(img_mtx);
00220
00221 agg::image_filter_lut filter;
00222 bool norm = m_normalize.status();
00223
00224 typedef agg::image_accessor_clip<pixfmt> source_type;
00225 pixfmt pixf_img(rbuf_img(1));
00226 source_type source(pixf_img, agg::rgba_pre(0,0,0,0));
00227
00228 switch(m_filters.cur_item())
00229 {
00230 case 0:
00231 {
00232 typedef agg::span_image_filter_nn<source_type, interpolator_type> span_gen_type;
00233 span_gen_type sg(source, interpolator);
00234 ras.add_path(tr);
00235 agg::render_scanlines_aa(ras, sl, rb_pre, sa, sg);
00236 }
00237 break;
00238
00239 case 1:
00240 {
00241 typedef agg::span_image_filter_bilinear<pixfmt, interpolator_type> span_gen_type;
00242 span_gen_type sg(pixf_img, agg::rgba_pre(0,0,0,0), interpolator);
00243 ras.add_path(tr);
00244 agg::render_scanlines_aa(ras, sl, rb_pre, sa, sg);
00245 }
00246 break;
00247
00248 case 5:
00249 case 6:
00250 case 7:
00251 {
00252 switch(m_filters.cur_item())
00253 {
00254 case 5: filter.calculate(agg::image_filter_hanning(), norm); break;
00255 case 6: filter.calculate(agg::image_filter_hamming(), norm); break;
00256 case 7: filter.calculate(agg::image_filter_hermite(), norm); break;
00257 }
00258
00259 typedef agg::span_image_filter_2x2<source_type, interpolator_type> span_gen_type;
00260 span_gen_type sg(source, interpolator, filter);
00261 ras.add_path(tr);
00262 agg::render_scanlines_aa(ras, sl, rb_pre, sa, sg);
00263 }
00264 break;
00265
00266 case 2:
00267 case 3:
00268 case 4:
00269 case 8:
00270 case 9:
00271 case 10:
00272 case 11:
00273 case 12:
00274 case 13:
00275 case 14:
00276 case 15:
00277 case 16:
00278 {
00279 switch(m_filters.cur_item())
00280 {
00281 case 2: filter.calculate(agg::image_filter_bicubic(), norm); break;
00282 case 3: filter.calculate(agg::image_filter_spline16(), norm); break;
00283 case 4: filter.calculate(agg::image_filter_spline36(), norm); break;
00284 case 8: filter.calculate(agg::image_filter_kaiser(), norm); break;
00285 case 9: filter.calculate(agg::image_filter_quadric(), norm); break;
00286 case 10: filter.calculate(agg::image_filter_catrom(), norm); break;
00287 case 11: filter.calculate(agg::image_filter_gaussian(), norm); break;
00288 case 12: filter.calculate(agg::image_filter_bessel(), norm); break;
00289 case 13: filter.calculate(agg::image_filter_mitchell(), norm); break;
00290 case 14: filter.calculate(agg::image_filter_sinc(m_radius.value()), norm); break;
00291 case 15: filter.calculate(agg::image_filter_lanczos(m_radius.value()), norm); break;
00292 case 16: filter.calculate(agg::image_filter_blackman(m_radius.value()), norm); break;
00293 }
00294
00295 typedef agg::span_image_filter<source_type, interpolator_type> span_gen_type;
00296 span_gen_type sg(source, interpolator, filter);
00297 ras.add_path(tr);
00298 agg::render_scanlines_aa(ras, sl, rb_pre, sa, sg);
00299 }
00300 break;
00301 }
00302
00303 }
00304
00305
00306 void on_ctrl_change()
00307 {
00308 if(m_single_step.status())
00309 {
00310 m_cur_angle += m_step.value();
00311 copy_img_to_img(1, 0);
00312 transform_image(m_step.value());
00313 m_num_steps++;
00314 force_redraw();
00315 m_single_step.status(false);
00316 }
00317
00318 if(m_run.status())
00319 {
00320 #ifdef AGG_ACCURATE_TIME
00321 start_timer();
00322 m_time1 = m_time2 = elapsed_time();
00323 #else
00324 m_time1 = m_time2 = clock();
00325 #endif
00326 m_num_pix = 0.0;
00327 wait_mode(false);
00328 }
00329 if(m_refresh.status() || m_filters.cur_item() != m_cur_filter)
00330 {
00331 #ifdef AGG_ACCURATE_TIME
00332 start_timer();
00333 m_time1 = m_time2 = 0;
00334 #else
00335 m_time1 = m_time2 = clock();
00336 #endif
00337 m_num_pix = 0.0;
00338 m_cur_angle = 0.0;
00339 copy_img_to_img(1, 2);
00340 transform_image(0.0);
00341 m_refresh.status(false);
00342 m_cur_filter = m_filters.cur_item();
00343 m_num_steps = 0;
00344 force_redraw();
00345 }
00346 }
00347
00348 void on_idle()
00349 {
00350 if(m_run.status())
00351 {
00352 if(m_cur_angle < 360.0)
00353 {
00354 m_cur_angle += m_step.value();
00355 copy_img_to_img(1, 0);
00356 #ifdef AGG_ACCURATE_TIME
00357 start_timer();
00358 #endif
00359 transform_image(m_step.value());
00360 #ifdef AGG_ACCURATE_TIME
00361 m_time2 += elapsed_time();
00362 #endif
00363 m_num_steps++;
00364 }
00365 else
00366 {
00367 m_cur_angle = 0.0;
00368 #ifndef AGG_ACCURATE_TIME
00369 m_time2 = clock();
00370 #endif
00371 wait_mode(true);
00372 m_run.status(false);
00373 }
00374 force_redraw();
00375 }
00376 else
00377 {
00378 wait_mode(true);
00379 }
00380 }
00381
00382
00383 };
00384
00385
00386
00387
00388
00389 int agg_main(int argc, char* argv[])
00390 {
00391 the_application app(pix_format, flip_y);
00392 app.caption("Image transformation filters comparison");
00393
00394 const char* img_name = "spheres";
00395 if(argc >= 2) img_name = argv[1];
00396 if(!app.load_img(0, img_name))
00397 {
00398 char buf[256];
00399 if(strcmp(img_name, "spheres") == 0)
00400 {
00401 sprintf(buf, "File not found: %s%s. Download http://www.antigrain.com/%s%s\n"
00402 "or copy it from another directory if available.",
00403 img_name, app.img_ext(), img_name, app.img_ext());
00404 }
00405 else
00406 {
00407 sprintf(buf, "File not found: %s%s", img_name, app.img_ext());
00408 }
00409 app.message(buf);
00410 return 1;
00411 }
00412
00413 app.copy_img_to_img(1, 0);
00414 app.copy_img_to_img(2, 0);
00415 app.transform_image(0.0);
00416
00417 unsigned w = app.rbuf_img(0).width() + 110;
00418 unsigned h = app.rbuf_img(0).height() + 40;
00419
00420 if(w < 305) w = 305;
00421 if(h < 325) h = 325;
00422
00423 if(app.init(w, h, 0))
00424 {
00425 return app.run();
00426 }
00427 return 0;
00428 }
00429
00430