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

image_perspective.cpp

Go to the documentation of this file.
00001 #include <stdlib.h>
00002 #include <ctype.h>
00003 #include <stdio.h>
00004 #include "agg_basics.h"
00005 #include "agg_rendering_buffer.h"
00006 #include "agg_rasterizer_scanline_aa.h"
00007 #include "agg_scanline_u.h"
00008 #include "agg_renderer_scanline.h"
00009 #include "agg_path_storage.h"
00010 #include "agg_conv_transform.h"
00011 #include "agg_trans_affine.h"
00012 #include "agg_trans_bilinear.h"
00013 #include "agg_trans_perspective.h"
00014 #include "agg_span_allocator.h"
00015 #include "agg_span_interpolator_linear.h"
00016 #include "agg_span_interpolator_trans.h"
00017 #include "agg_span_subdiv_adaptor.h"
00018 #include "agg_pixfmt_rgba.h"
00019 #include "agg_image_accessors.h"
00020 #include "agg_span_image_filter_rgba.h"
00021 #include "ctrl/agg_rbox_ctrl.h"
00022 #include "platform/agg_platform_support.h"
00023 #include "interactive_polygon.h"
00024 
00025 
00026 enum flip_y_e { flip_y = true };
00027 
00028 agg::rasterizer_scanline_aa<> g_rasterizer;
00029 agg::scanline_u8  g_scanline;
00030 double            g_x1 = 0;
00031 double            g_y1 = 0;
00032 double            g_x2 = 0;
00033 double            g_y2 = 0;
00034 
00035 
00036 
00037 class the_application : public agg::platform_support
00038 {
00039 public:
00040     typedef agg::pixfmt_bgra32                             pixfmt;
00041     typedef pixfmt::color_type                             color_type;
00042     typedef agg::renderer_base<pixfmt>                     renderer_base;
00043     typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_solid;
00044 
00045     typedef agg::pixfmt_bgra32_pre         pixfmt_pre;
00046     typedef agg::renderer_base<pixfmt_pre> renderer_base_pre;
00047 
00048     agg::interactive_polygon   m_quad;
00049     agg::rbox_ctrl<agg::rgba8> m_trans_type;
00050 
00051     the_application(agg::pix_format_e format, bool flip_y) :
00052         agg::platform_support(format, flip_y),
00053         m_quad(4, 5.0),
00054         m_trans_type(420, 5.0, 420+170.0, 70.0, !flip_y)
00055     {
00056         m_trans_type.add_item("Affine Parallelogram");
00057         m_trans_type.add_item("Bilinear");
00058         m_trans_type.add_item("Perspective");
00059         m_trans_type.cur_item(2);
00060         add_ctrl(m_trans_type);
00061     }
00062 
00063 
00064     virtual void on_init()
00065     {
00066         double d = 0.0;
00067         g_x1 = d;
00068         g_y1 = d;
00069         g_x2 = rbuf_img(0).width() - d;
00070         g_y2 = rbuf_img(0).height() - d;
00071 
00072         m_quad.xn(0) = 100;
00073         m_quad.yn(0) = 100;
00074         m_quad.xn(1) = width()  - 100;
00075         m_quad.yn(1) = 100;
00076         m_quad.xn(2) = width()  - 100;
00077         m_quad.yn(2) = height() - 100;
00078         m_quad.xn(3) = 100;
00079         m_quad.yn(3) = height() - 100;
00080     }
00081 
00082     virtual void on_draw()
00083     {
00084         pixfmt            pixf(rbuf_window());
00085         pixfmt_pre        pixf_pre(rbuf_window());
00086         renderer_base     rb(pixf);
00087         renderer_base_pre rb_pre(pixf_pre);
00088 
00089         renderer_solid r(rb);
00090 
00091 
00092         rb.clear(agg::rgba(1, 1, 1));
00093 
00094         if(m_trans_type.cur_item() == 0)
00095         {
00096             // For the affine parallelogram transformations we
00097             // calculate the 4-th (implicit) point of the parallelogram
00098             m_quad.xn(3) = m_quad.xn(0) + (m_quad.xn(2) - m_quad.xn(1));
00099             m_quad.yn(3) = m_quad.yn(0) + (m_quad.yn(2) - m_quad.yn(1));
00100         }
00101 
00102         //--------------------------
00103         // Render the "quad" tool and controls
00104         g_rasterizer.add_path(m_quad);
00105         agg::render_scanlines_aa_solid(g_rasterizer, g_scanline, rb, 
00106                                        agg::rgba(0, 0.3, 0.5, 0.6));
00107 
00108         // Prepare the polygon to rasterize. Here we need to fill
00109         // the destination (transformed) polygon.
00110         g_rasterizer.clip_box(0, 0, width(), height());
00111         g_rasterizer.reset();
00112         g_rasterizer.move_to_d(m_quad.xn(0), m_quad.yn(0));
00113         g_rasterizer.line_to_d(m_quad.xn(1), m_quad.yn(1));
00114         g_rasterizer.line_to_d(m_quad.xn(2), m_quad.yn(2));
00115         g_rasterizer.line_to_d(m_quad.xn(3), m_quad.yn(3));
00116 
00117         agg::span_allocator<color_type> sa;
00118         agg::image_filter_bilinear filter_kernel;
00119         agg::image_filter_lut filter(filter_kernel, false);
00120 
00121         pixfmt pixf_img(rbuf_img(0));
00122 
00123         //typedef agg::image_accessor_wrap<pixfmt, 
00124         //                                 agg::wrap_mode_reflect,
00125         //                                 agg::wrap_mode_reflect> img_accessor_type;
00126         //img_accessor_type ia(pixf_img);
00127 
00128         //typedef agg::image_accessor_clip<pixfmt> img_accessor_type;
00129         //img_accessor_type ia(pixf_img, agg::rgba(1,1,1));
00130 
00131         typedef agg::image_accessor_clone<pixfmt> img_accessor_type;
00132         img_accessor_type ia(pixf_img);
00133 
00134         start_timer();
00135         switch(m_trans_type.cur_item())
00136         {
00137             case 0:
00138             {
00139                 // Note that we consruct an affine matrix that transforms
00140                 // a parallelogram to a rectangle, i.e., it's inverted.
00141                 // It's actually the same as:
00142                 // tr(g_x1, g_y1, g_x2, g_y2, m_triangle.polygon());
00143                 // tr.invert();
00144                 agg::trans_affine tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2);
00145 
00146                 // Also note that we can use the linear interpolator instead of 
00147                 // arbitrary span_interpolator_trans. It works much faster, 
00148                 // but the transformations must be linear and parellel.
00149                 typedef agg::span_interpolator_linear<agg::trans_affine> interpolator_type;
00150                 interpolator_type interpolator(tr);
00151 
00152                 typedef agg::span_image_filter_rgba_nn<img_accessor_type,
00153                                                        interpolator_type> span_gen_type;
00154                 span_gen_type sg(ia, interpolator);
00155                 agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg);
00156                 break;
00157             }
00158 
00159             case 1:
00160             {
00161                 agg::trans_bilinear tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2);
00162                 if(tr.is_valid())
00163                 {
00164                     typedef agg::span_interpolator_linear<agg::trans_bilinear> interpolator_type;
00165                     interpolator_type interpolator(tr);
00166 
00167                     typedef agg::span_image_filter_rgba_2x2<img_accessor_type,
00168                                                             interpolator_type> span_gen_type;
00169                     span_gen_type sg(ia, interpolator, filter);
00170                     agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg);
00171                 }
00172                 break;
00173             }
00174 
00175             case 2:
00176             {
00177                 agg::trans_perspective tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2);
00178                 if(tr.is_valid())
00179                 {
00180                     // Subdivision and linear interpolation (faster, but less accurate)
00181                     //-----------------------
00182                     //typedef agg::span_interpolator_linear<agg::trans_perspective> interpolator_type;
00183                     //typedef agg::span_subdiv_adaptor<interpolator_type> subdiv_adaptor_type;
00184                     //interpolator_type interpolator(tr);
00185                     //subdiv_adaptor_type subdiv_adaptor(interpolator);
00186                     //
00187                     //typedef agg::span_image_filter_rgba_2x2<img_accessor_type,
00188                     //                                        subdiv_adaptor_type> span_gen_type;
00189                     //span_gen_type sg(ia, subdiv_adaptor, filter);
00190                     //-----------------------
00191 
00192                     // Direct calculations of the coordinates
00193                     //-----------------------
00194                     typedef agg::span_interpolator_trans<agg::trans_perspective> interpolator_type;
00195                     interpolator_type interpolator(tr);
00196                     typedef agg::span_image_filter_rgba_2x2<img_accessor_type,
00197                                                             interpolator_type> span_gen_type;
00198                     span_gen_type sg(ia, interpolator, filter);
00199                     //-----------------------
00200 
00201                     agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg);
00202                 }
00203                 break;
00204             }
00205         }
00206         double tm = elapsed_time();
00207 
00208         char buf[128]; 
00209         agg::gsv_text t;
00210         t.size(10.0);
00211 
00212         agg::conv_stroke<agg::gsv_text> pt(t);
00213         pt.width(1.5);
00214 
00215         sprintf(buf, "%3.2f ms", tm);
00216         t.start_point(10.0, 10.0);
00217         t.text(buf);
00218 
00219         g_rasterizer.add_path(pt);
00220         agg::render_scanlines_aa_solid(g_rasterizer, g_scanline, rb, 
00221                                        agg::rgba(0,0,0));
00222 
00223         //--------------------------
00224         agg::render_ctrl(g_rasterizer, g_scanline, rb, m_trans_type);
00225     }
00226 
00227 
00228 
00229     virtual void on_mouse_button_down(int x, int y, unsigned flags)
00230     {
00231         if(flags & agg::mouse_left)
00232         {
00233             if(m_quad.on_mouse_button_down(x, y))
00234             {
00235                 force_redraw();
00236             }
00237         }
00238     }
00239 
00240 
00241     virtual void on_mouse_move(int x, int y, unsigned flags)
00242     {
00243         if(flags & agg::mouse_left)
00244         {
00245             if(m_quad.on_mouse_move(x, y))
00246             {
00247                 force_redraw();
00248             }
00249         }
00250         if((flags & agg::mouse_left) == 0)
00251         {
00252             on_mouse_button_up(x, y, flags);
00253         }
00254     }
00255 
00256 
00257     virtual void on_mouse_button_up(int x, int y, unsigned flags)
00258     {
00259         if(m_quad.on_mouse_button_up(x, y))
00260         {
00261             force_redraw();
00262         }
00263     }
00264 
00265 };
00266 
00267 
00268 
00269 
00270 
00271 
00272 int agg_main(int argc, char* argv[])
00273 {
00274     the_application app(agg::pix_format_bgra32, flip_y);
00275     app.caption("AGG Example. Image Perspective Transformations");
00276 
00277     const char* img_name = "spheres";
00278     if(argc >= 2) img_name = argv[1];
00279     if(!app.load_img(0, img_name)) 
00280     {
00281         char buf[256];
00282         if(strcmp(img_name, "spheres") == 0)
00283         {
00284             sprintf(buf, "File not found: %s%s. Download http://www.antigrain.com/%s%s\n"
00285                          "or copy it from another directory if available.",
00286                     img_name, app.img_ext(), img_name, app.img_ext());
00287         }
00288         else
00289         {
00290             sprintf(buf, "File not found: %s%s", img_name, app.img_ext());
00291         }
00292         app.message(buf);
00293         return 1;
00294     }
00295     
00296 /*
00297     // Testing the "black border" issue with alpha channel
00298     //----------------------------------------
00299     the_application::pixfmt pixf(app.rbuf_img(0));
00300     the_application::renderer_base rbase(pixf);
00301     rbase.clear(agg::rgba8(0,0,0,0));
00302     unsigned i;
00303     for(i = 0; i < 50; i++)
00304     {
00305         agg::ellipse ell(rand() % rbase.width(), 
00306                          rand() % rbase.height(),
00307                          rand() % 20 + 5,
00308                          rand() % 20 + 5,
00309                          100);
00310         g_rasterizer.add_path(ell);
00311         agg::render_scanlines_aa_solid(g_rasterizer, g_scanline, rbase, 
00312                                        agg::rgba8((rand() & 0x7F) + 127, 
00313                                                   (rand() & 0x7F) + 127, 
00314                                                   (rand() & 0x7F) + 127, 
00315                                                   255));
00316     }
00317 */
00318 
00319     if(app.init(600, 600, agg::window_resize))
00320     {
00321         return app.run();
00322     }
00323     return 1;
00324 }
00325 
00326 
00327 
00328 
00329 
00330 

© sourcejam.com 2005-2008