Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

image_filters.cpp

Go to the documentation of this file.
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 // Uncomment this for more accurate timings. 
00036 // Well, it currently works well only on Windows, where there's
00037 // high accuracy QueryPerformanceCounter is available. On Unix
00038 // it uses regular clock() anyway, so, it won't work for short
00039 // time periods and will give you totally wrong result (probably #INF).
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 

© sourcejam.com 2005-2008