开源2D图形库AGG研究(一)

本文介绍AGG(Anti-Grain Geometry)图形库的基本使用方法及环境搭建过程。AGG是一个高性能的2D图形库,支持亚像素精度显示和跨平台开发。文章详细讲解了在VC6.0环境下配置AGG并实现高质量图形输出的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      AGG(Anti-Grain Geometry),强大的2D几何图形库。因为GDI+的一些缺陷(不能跨平台,某些应用场合精度差),我一直在寻求可以替换gdi+绘图组件的方案,最终我选择了AGG,提供亚像素精度显示效果,反锯齿效果超好,跨平台,代码精致亦适合嵌入式开发。网上关于2D图形库的组件非常多,类似的还有GOOGLE PICASSO,CAIRO(firefox底层采用的渲染器),QT,OpenGL等等。从易用性的角度来说AGG比较困难,因为官方只给出了C++源代码,没有组件库和封装好的包,其他语言要想直接用是不可能了。从网上关于使用效果的评论来说,AGG是最高效,跨平台最好的。

      起初学习是从看中文档开始的,在网上有写得比较好的文章(目前最全面的),题目是<<用AGG实现高质量图形输出>>。如果按照文章大致做下来就能对AGG有一个初步了解。参考上述文章,自己动手做一下,感觉稍微能熟悉些,不然直接看源码或英文文档比较累。现在是边用边看源码,翻翻原始文档,感觉学习效率会高一些。因为以前专门写过一段时间的GIS数据格式解析有一定基础(要是参考AGG就好了),再过来看AGG源码,还是比较过瘾的,其间有很多数据结构的写法其实也适用于GIS(例如各种图形对象如何用程序表达)。在我看来AGG的代码结构非常清晰和优美,源码使用C++模版中规中矩(本人非常不赞成奇技淫巧式的C++变态语句)。

      什么样的人适合使用AGG类库?稍微有点计算机图形学基础,但是比较熟悉C++的人适合上手。其实一般的开发基本用不上AGG类库,因为太多人去搞应用开发,很少人会关注绘图质量,图像变换的底层实现了。AGG的绘图质量的确很好,在用户列表中有PDFNet,该公司的SDK产品被AutoDesk公司采用了,而此SDK的底层就是采用的AGG图形库。AGG类库非常用于图形学实践,熟悉了源码可以自己在现有类的基础上进行扩展。

      介绍了这么多AGG背景,开始学习使用AGG吧。第一步,Hello World ?不,我们需要下载源码。目前最新版本是2.5在以下网址下载 http://www.antigrain.com/download/index.html。下载后直接解压,文件夹中罗列了一堆的.cpp、.h文件。当然我们的开发环境是VC6.0,所以我们下载的是Windows版本。

     1、VC6.0下新建一个Windows Console工程,名称随便起,姑且叫AggTest.

     2、关键步骤,设置AGG类库的引用,最野蛮和最有效的方式把Include下的.h文件连同其下文件夹全部拷贝到VC6安装目录下的Microsoft Visual Studio/VC98/Include文件夹中,把解压目录中的src文件夹下的cpp文件都添加到AggTest工程中。

    3、拷贝如下代码到你的AggTest.cpp文件中

        
#include "agg_basics.h"
#include "agg_rendering_buffer.h"
#include "agg_rasterizer_scanline_aa.h"
#include "agg_scanline_u.h"
#include "agg_renderer_scanline.h"
#include "agg_pixfmt_rgb.h"
#include "platform/agg_platform_support.h"
#include "agg_ellipse.h" 
#include "agg_conv_contour.h"
#include "agg_conv_stroke.h"

#include "agg_conv_marker.h"
#include "agg_arrowhead.h"
#include "agg_path_storage.h"
#include "agg_vcgen_markers_term.h"


#include <agg_conv_stroke.h> // conv_stroke
#include <agg_conv_dash.h> // conv_dash
#include <agg_conv_marker.h> // conv_marker
#include <agg_conv_curve.h> // conv_curve
#include <agg_conv_contour.h> // conv_contour
#include <agg_conv_smooth_poly1.h> // conv_smooth_poly1.h
#include <agg_conv_bspline.h> // conv_bspline
#include <agg_conv_transform.h> // conv_transform

 


class the_application : public agg::platform_support
{
public:
    the_application(agg::pix_format_e format, bool flip_y) :
   agg::platform_support(format, flip_y)
   {
   }
  
   virtual void on_draw()
   {
    //Rendering Buffer              //用于存放像素点阵数据的内存块,这里是最终形成的图像数据
    agg::rendering_buffer &rbuf = rbuf_window();
    agg::pixfmt_bgr24 pixf(rbuf);
   
    // Renderers
    typedef agg::renderer_base<agg::pixfmt_bgr24> renderer_base_type;  //底层渲染器
    renderer_base_type renb(pixf);
   
   // typedef agg::renderer_scanline_aa_solid<renderer_base_type> renderer_scanline_type;   //高层渲染器
    typedef agg::renderer_scanline_bin_solid<renderer_base_type> renderer_scanline_type;   //高层渲染器

    renderer_scanline_type rensl(renb);
    /*
    // Vertex Source
    //agg::ellipse ell(100,100,50,50); //顶点源,里面存放了一堆2D顶点以及对应的命令,这个顶点源呈现的是一个圆形
     agg::triangle ell(100,100,50);

        // Coordinate conversion pipeline //坐标转换管道,它可以变换Vertex Source中的顶点,比如矩阵变换,轮廓提取,转换为虚线等。
    //typedef agg::conv_contour<agg::ellipse> ell_cc_type;     //扩展轮廓线
          typedef agg::conv_contour<agg::triangle> ell_cc_type;
    ell_cc_type ccell(ell);
   
    typedef agg::conv_stroke<ell_cc_type> ell_cc_cs_type;    //只显示轮廓线
    ell_cc_cs_type csccell(ccell);
    */

    // Vertex Source
    agg::ellipse ell(0,0,50,50);  // 圆心在中间    
    // Coordinate conversion pipeline
    agg::trans_affine mtx;        // trans_affine不 仅仅用于源顶点的变换,在AGG库中有不少地方都能看到它
    mtx.scale(0.5,1);             // x轴缩小到原来的一半
    mtx.rotate(agg::deg2rad(30)); // 旋转30度
    mtx.translate(100,100); // 平移100,100
    typedef agg::conv_transform<agg::ellipse> ell_ct_type;
    ell_ct_type ctell(ell, mtx); // 矩阵变换
   
    typedef agg::conv_contour<ell_ct_type> ell_cc_type;
    ell_cc_type ccell(ctell); // 轮廓变换
  
    typedef agg::conv_dash<ell_cc_type> ell_cd_type;
    ell_cd_type cdccell(ccell);
    cdccell.add_dash(5,5);
   

    typedef agg::conv_stroke<ell_cd_type> ell_cc_cs_type;
    // ell_cc_cs_type csccell(ccell); // 转换成多义线
     ell_cc_cs_type csccell(cdccell);

         // csccell.width(3);

 
    // Scanline Rasterizer            //把顶点数据(矢量数据)转换成一组水平扫描线,扫描线由一组线段(Span)组成,线段(Span)包含了起始位置、长度和覆盖率(可以理解为透明度)信息。AGG的抗锯齿(Anti-Aliasing)功能也是在这时引入的。
    agg::rasterizer_scanline_aa<> ras;
    agg::scanline_u8 sl;
   
     // Draw          
    renb.clear(agg::rgba8(255,255,255));
  //  renb.clip_box(30,30,160,160); // 设置可写区域

    for(int i=0; i<5; i++)
    {
     ccell.width(i*20);
     ras.add_path(csccell);
     rensl.color( agg::rgba8(0,0,i*50));
   //  agg::render_scanlines(ras,sl,rensl);
     agg::render_scanlines_aa_solid(ras,sl,renb,agg::rgba8(0,0,i*50));

    }

 

    agg::path_storage ps;

          ps.start_new_path();
    ps.move_to(200,60);
    ps.line_to(400,100);
    ps.line_to(300,140);
    ps.end_poly();
         
         

    agg::conv_stroke<agg::path_storage, agg::vcgen_markers_term> csps(ps);  
    ras.add_path(csps);
    agg::render_scanlines_aa_solid(ras,sl,renb,agg::rgba8(0,0,0));
 

 


         /*
    agg::arrowhead ah;
    ah.head(0,10,5,5);
    ah.tail(10,10,5,5);
    // 用path_storage生成一条直线
    agg::path_storage ps;
    ps.move_to(160,60);
    ps.line_to(100,100);
    // 转换
    agg::conv_stroke<agg::path_storage, agg::vcgen_markers_term> csps(ps);
    agg::conv_marker<agg::vcgen_markers_term, agg::arrowhead>
     arrow(csps.markers(), ah);
    // 画线
    ras.add_path(csps);
    agg::render_scanlines_aa_solid(ras,sl,renb,agg::rgba8(0,0,0));
    // 画箭头
    ras.add_path(arrow);
    agg::render_scanlines_aa_solid(ras,sl,renb,agg::rgba8(255,0,0));


    agg::triangle t(100,100,50);//自定义顶点源
    agg::conv_smooth_poly1_curve<agg::triangle> cspct(t);
    ras.add_path(cspct);
    agg::render_scanlines_aa_solid(
    ras,sl,renb,agg::rgba8(255,0,0));
       

    for(int j=0; j<20; j++)
     pixf.blend_vline(50+j,20,100,agg::rgba(j/20.0,0,0),128);
  
   
   
    agg::int8u* p = rbuf.row_ptr(20);//得到第20行指针
    memset(p,0,rbuf.stride_abs());//整行以0填充
         */
    }
};


int  agg_main(int argc, char* argv[])
{


 the_application app(agg::pix_format_bgr24, false);

 app.caption("AGG Example. Anti-Aliasing Demo");
 
    if(app.init(600, 400, agg::window_resize))
    {
        return app.run();
    }
    return -1;

}

 

      4、编译,当然通不过,你懂的。第一步,如果还有文件(如agg_platform_support.cpp)没有找到,你需要添加到工程中。第二步,报错后,看看是不是有两处地方没有修改,stdafx.h是不是注释掉了(纯C++么);是不是按下图设置了VC6下.cpp的设置。

/

      5、这下终于可以编译通过了,恭喜你程序上可以看到如下内容:

      环境配置还是比较简单的,能够成功运行的程序是对我们极大的鼓励下,后续我们开始研究代码。

 

本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/jx1228/archive/2011/05/31/6457076.aspx

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、付费专栏及课程。

余额充值