用AGG实现高质量图形输出(一)

本文介绍AGG(Anti-Grain Geometry)图形库的基本概念及其使用方法。AGG是一个高效且灵活的2D图形库,提供了高质量的图形输出。文章通过示例代码详细解释了AGG的工作流程,包括顶点源、坐标转换管道、扫描线光栅化器和渲染器等关键组件。

来自http://www.cppprog.com/2009/0816/146.html

 

AGG是一个开源、高效的跨平台2D图形库。AGG的功能与GDI+的功能非常类似,但提供了比GDI+更灵活的编程接口,其产生的图形的质量也非常高(自称超过GDI+)

 

使用前AGG的准备工作

  1. 下载AGG库,它的家在http://www.antigrain.com,目前最高版本是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.  
  12. class the_application : public agg::platform_support
  13. {
  14. public:
  15.     the_application(agg::pix_format_e format, bool flip_y) :
  16.         agg::platform_support(format, flip_y)
  17.     {
  18.     }
  19.  
  20.     virtual void on_draw()
  21.     {
  22.         //Rendering Buffer
  23.         agg::rendering_buffer &rbuf = rbuf_window();
  24.         agg::pixfmt_bgr24 pixf(rbuf);
  25.        
  26.         // Renderers
  27.         typedef agg::renderer_base<agg::pixfmt_bgr24> renderer_base_type;
  28.         renderer_base_type renb(pixf);
  29.  
  30.         typedef agg::renderer_scanline_aa_solid<renderer_base_type> renderer_scanline_type;
  31.         renderer_scanline_type rensl(renb);
  32.        
  33.         // Vertex Source
  34.         agg::ellipse ell(100,100,50,50);
  35.        
  36.         // Coordinate conversion pipeline
  37.         typedef agg::conv_contour<agg::ellipse> ell_cc_type;
  38.         ell_cc_type ccell(ell);
  39.        
  40.         typedef agg::conv_stroke<ell_cc_type> ell_cc_cs_type;
  41.         ell_cc_cs_type csccell(ccell);
  42.        
  43.         // Scanline Rasterizer
  44.         agg::rasterizer_scanline_aa<> ras;
  45.         agg::scanline_u8 sl;
  46.        
  47.         // Draw
  48.         renb.clear(agg::rgba8(255,255,255));
  49.         for(int i=0; i<5; i++)
  50.         {
  51.             ccell.width(i*20);
  52.             ras.add_path(csccell);
  53.             rensl.color( agg::rgba8(0,0,i*50));
  54.             agg::render_scanlines(ras,sl,rensl);
  55.         }
  56.     }
  57. };
  58.  
  59. int agg_main(int argc, char* argv[])
  60. {
  61.     the_application app(agg::pix_format_bgr24, false);
  62.     app.caption("AGG Example. Anti-Aliasing Demo");
  63.  
  64.     if(app.init(600, 400, agg::window_resize))
  65.     {
  66.         return app.run();
  67.     }
  68.     return -1;
  69. }

编译这段代码的方法是(以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工作流程。
1 使用AGG的准备工作 1 2 AGG图形显示原理见下图: 1 3 要理解AGG工作原理,先看段代码: 2 4 顶点源(Vertex Source) 5 4.1 头文件 5 4.2 类型 5 4.3 画条简单的箭头直线(基于此处代码) 6 4.4 自定义个顶点源(基于此处代码) 7 5 Coordinate conversion pipeline 坐标转换管道 9 5.1 变换矩阵(trans_affine) 10 5.1.1 头文件 10 5.1.2 类型 10 5.1.3成员变量 10 5.1.4 成员方法 10 5.1.5 实验代码(基于此 处代码) 10 5.2 坐标转换管道 11 5.2.1 头文件 11 5.2.2 类型(演示程序基于基于此处代码) 12 6 Scanline Rasterizer 15 6.1 扫描线Scanline 15 6.1.1 头文件 15 6.1.2 类型 15 6.1.3 成员类型 15 6.1.4 成员方法 16 6.2 Rasterizer 16 6.2.1 头文件 16 6.2.2 类型 16 6.2.3 成员方法 16 7 Renderers 渲染器 17 7.1 Scanline Renderer 17 7.1.1 头文件 17 7.1.2 类型 17 7.1.3 实验代码(基于此 处代码) 18 7.2 Basic Renderers 19 7.2.1头文件 19 7.2.2类型 19 7.2.3 构造函数 19 7.2.4 成员方法 19 7.2.5 实验代码(基于此 处代码) 20 7.3 PixelFormat Renderer 20 7.3.1 头文件 21 7.3.2 类型 21 7.3.3 构造函数 21 7.3.4 类型定义 21 7.3.5 成员方法 21 7.3.6 实验代码(基于此 处代码) 22 8 Rendering Buffer 22 8.1 头文件: 22 8.2 类型: 22 8.3 构造函数: 22 8.4 成员方法: 23 8.5 实验代码(基于此处代码) 23 9 AGGGDI显示 23 10 使用AGG提供的pixel_map类 26 11 线段生成器(Span Generator) 27 12 图案类线段生成器 28 12.1头文件 28 12.2类型 28 12.3 示例代码,使用span_image_filter_rgb_bilinear_clip 29 13 插值器Interpolator 31 13.1 头文件 31 13.2 类型 31 13.3实验代码,使用span_interpolator_persp_lerp 32 14 变换器Transformer 33 14.1 头文件 33 14.2 类型 33 14.3 实验代码,使用trans_warp_magnifier 33 15 图像访问器Image Accessor 34 15.1 头文件 34 15.2 类型 34 15.3 实验代码 35 16 图像过滤器(Image Filter) 36 16.1 头文件 36 16.2 类型 36 16.3 实验代码 37 17 色彩类线段生成器 37 17.1 头文件 37 17.2 类型 38 17.3 示例代码 38 18 渐变颜色 40 18.1 实验代码,使用std::vector实现多颜色渐变 40 18.2 gradient_lut 41 18.2.1 头文件 41 18.2.2 类声明 41 18.2.3 实验代码,使用gradient_lut实现多颜色渐变 41 19 渐变方式 42 20其它色彩类的线段生成器 43 21 组合类线段生成器 44 21.1 头文件 44 21.2 类型 44 21.3 演示代码 45 22 AGG的字符输出 47 22.1 方式、使用gsv_text对象 47 22.2 方式二、使用字体引擎(Font Engine) 50 22.2.1 头文件 50 22.2.2 类型 50 22.2.3 成员类型 51 22.2.4 成员属性 51 22.2.5 成员方法 51 22.2.6示例代码1 - 从顶点源层输出文字 52 22.2.7 示例代码2 - 从Scanline Rasterizer层输出文字 53 22.3 方式三、使用FreeType 54 22.4 方式四、字体缓存管理器(font_cache_manager) 55 22.4.1 头文件 55 22.4.2 类型 55 22.4.3 成员方法 55 22.4.4 示例代码1-作为Rasterizer渲染: 56 22.4.5 示例代码2-作为顶点源渲染: 57 23 小结 58
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值