分享

用AGG实现高质量图形输出

 lhzstudio 2011-10-15
用AGG实现高质量图形输出
2010-07-11 20:39

使用前AGG的准备工作

  1. 下载AGG库,它的家在http://www.,目前最高版本是AGG2.5
  2. 解压,后面以[AGG]表示AGG的解压目录.
  3. 把[AGG]\include加入到include搜索目录中
  4. 把[AGG]\src里所有cpp加入到项目中(或者用makefile一起编译)
  5. 另外,AGG还有一些其它组件,用到时也要把它们(都是些.h和.cpp文件)加入项目:
    • 如果要用AGG的控件和窗体,要加入[AGG]\src\ctrl\*.cpp和[AGG]\src\platform\<OS>\*.cpp,头文件在[AGG]\include\ctrl和[AGG]\include\platform里
    • 如果要用到TrueType字体显示,要加入[AGG]\font_win32_tt目录下的源码和头文件。利用freetype库,则是[AGG]\font_freetype目录。
    • 如果要用到Generic Polygon Clipper库(一个区域剪裁计算库),加入[AGG]\gpc目录下的源码和头文件。

AGG图形显示原理见下图:

\

其中:

  1. Vertex Source 顶点源,里面存放了一堆2D顶点以及对应的命令,如"MoveTo"、"LineTo"等。
  2. Coordinate conversion pipeline 坐标转换管道,它可以变换Vertex Source中的顶点,比如矩阵变换,轮廓提取,转换为虚线等。
  3. Scanline Rasterizer 把顶点数据(矢量数据)转换成一组水平扫描线,扫描线由一组线段(Span)组成,线段(Span)包含了起始位置、长度和覆盖率(可以理解为透明度)信息。AGG的抗锯齿(Anti-Aliasing)功能也是在这时引入的。
  4. Renderers 渲染器,渲染扫描线(Scanline)中的线段(Span),最简单的就是为Span提供单一颜色,复杂的有多种颜色(如渐变)、使用图像数据、Pattern等。
  5. Rendering Buffer 用于存放像素点阵数据的内存块,这里是最终形成的图像数据。

要理解AGG的工作原理,先看一段代码:

  1. #include "agg_basics.h"
  2. #include "agg_rendering_buffer.h"
  3. #include "agg_rasterizer_scanline_aa.h"
  4. #include "agg_scanline_u.h"
  5. #include "agg_renderer_scanline.h"
  6. #include "agg_pixfmt_rgb.h"
  7. #include "platform/agg_platform_support.h"
  8. #include "agg_ellipse.h"
  9. #include "agg_conv_contour.h"
  10. #include "agg_conv_stroke.h"
  11. class the_application : public agg::platform_support
  12. {
  13. public:
  14.      the_application(agg::pix_format_e format, bool flip_y) :
  15.          agg::platform_support(format, flip_y)
  16.      {
  17.      }
  18.     virtual void on_draw()
  19.      {
  20.         //Rendering Buffer
  21.          agg::rendering_buffer &rbuf = rbuf_window();
  22.          agg::pixfmt_bgr24 pixf(rbuf);
  23.        
  24.         // Renderers
  25.         typedef agg::renderer_base<agg::pixfmt_bgr24> renderer_base_type;
  26.          renderer_base_type renb(pixf);
  27.         typedef agg::renderer_scanline_aa_solid<renderer_base_type> renderer_scanline_type;
  28.          renderer_scanline_type rensl(renb);
  29.        
  30.         // Vertex Source
  31.          agg::ellipse ell(100,100,50,50);
  32.        
  33.         // Coordinate conversion pipeline
  34.         typedef agg::conv_contour<agg::ellipse> ell_cc_type;
  35.          ell_cc_type ccell(ell);
  36.        
  37.         typedef agg::conv_stroke<ell_cc_type> ell_cc_cs_type;
  38.          ell_cc_cs_type csccell(ccell);
  39.        
  40.         // Scanline Rasterizer
  41.          agg::rasterizer_scanline_aa<> ras;
  42.          agg::scanline_u8 sl;
  43.        
  44.         // Draw
  45.          renb.clear(agg::rgba8(255,255,255));
  46.         for(int i=0; i<5; i++)
  47.          {
  48.              ccell.width(i*20);
  49.              ras.add_path(csccell);
  50.              rensl.color( agg::rgba8(0,0,i*50));
  51.              agg::render_scanlines(ras,sl,rensl);
  52.          }
  53.      }
  54. };
  55. int agg_main(int argc, char* argv[])
  56. {
  57.      the_application app(agg::pix_format_bgr24, false);
  58.      app.caption("AGG Example. Anti-Aliasing Demo");
  59.     if(app.init(600, 400, agg::window_resize))
  60.      {
  61.         return app.run();
  62.      }
  63.     return -1;
  64. }

编译这段代码的方法是(以VC为例):

  1. 新建空白GUI项目(就是有WinMain的项目)
  2. 把[AGG]\src里所有*.cpp加入到项目中
  3. 把[AGG]\src\platform\Win32\*.cpp加入到项目中
  4. Ctrl+C/Ctrl+V 上面的代码
  5. 编译!

显示效果:

\

我们先不管agg_main及agg::platform_support的问题,实际上agg::platform_support只是AGG给我们方便显示AGG图形用的,真正应用时几乎不会用到(后面会讲到怎样把AGG图形画到HDC上)。

现在我们只需要知道这个框架可以生成一个窗体,当窗体重画时会调用virtual void on_draw()就行了。

现在直接从on_draw()开始看

  1. 通过rbuf_window()方法得到一个agg::rendering_buffer,它就是“Rendering Buffer”,是一块用于存放图像的内存块。通过pixfmt_bgr24包装,我们就可以以像素为单位存取图像。
  2. agg::renderer_baseagg::renderer_scanline_aa_solid都属于"渲染器Renderer"。renderer_base为底层渲染器,它支撑起所有的高层渲染器。这里的renderer_scanline_aa_solid就是一个高层渲染器。
  3. agg::ellipse是“顶点源Vertex Source”,这个顶点源呈现的是一个圆形。
  4. agg::conv_contouragg::conv_stroke作为“坐标转换管道Coordinate conversion pipeline”,conv_contour扩展轮廓线,conv_stroke只显示轮廓线(如果没有conv_stroke就会显示实心圆,可以去掉试试)。
  5. agg::rasterizer_scanline_aa<>就是“Scanline Rasterizer”啦。
  6. agg::render_scanlines函数执行这个AGG工作流程。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多