开源2D图形库AGG简介

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、这下终于可以编译通过了,恭喜你程序上可以看到如下内容:

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

原文链接:https://blog.csdn.net/jx1228/article/details/6457076

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值