用AGG实现高质量图形输出上.docx

上传人:b****7 文档编号:10585598 上传时间:2023-02-21 格式:DOCX 页数:37 大小:172.99KB
下载 相关 举报
用AGG实现高质量图形输出上.docx_第1页
第1页 / 共37页
用AGG实现高质量图形输出上.docx_第2页
第2页 / 共37页
用AGG实现高质量图形输出上.docx_第3页
第3页 / 共37页
用AGG实现高质量图形输出上.docx_第4页
第4页 / 共37页
用AGG实现高质量图形输出上.docx_第5页
第5页 / 共37页
点击查看更多>>
下载资源
资源描述

用AGG实现高质量图形输出上.docx

《用AGG实现高质量图形输出上.docx》由会员分享,可在线阅读,更多相关《用AGG实现高质量图形输出上.docx(37页珍藏版)》请在冰豆网上搜索。

用AGG实现高质量图形输出上.docx

用AGG实现高质量图形输出上

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

AGG是一个开源、高效的跨平台2D图形库。

AGG的功能与GDI+的功能非常类似,但提供了比GDI+更灵活的编程接口,其产生的图形的质量也非常高(自称超过GDI+)

使用前AGG的准备工作

1.下载AGG库,它的家在,目前最高版本是AGG2.5

2.解压,后面以[AGG]表示AGG的解压目录.

3.把[AGG]\include加入到include搜索目录中

4.把[AGG]\src里所有cpp加入到项目中(或者用makefile一起编译)

5.另外,AGG还有一些其它组件,用到时也要把它们(都是些.h和.cpp文件)加入项目:

o如果要用AGG的控件和窗体,要加入[AGG]\src\ctrl\*.cpp和[AGG]\src\platform\\*.cpp,头文件在[AGG]\include\ctrl和[AGG]\include\platform里

o如果要用到TrueType字体显示,要加入[AGG]\font_win32_tt目录下的源码和头文件。

利用freetype库,则是[AGG]\font_freetype目录。

o如果要用到GenericPolygonClipper库(一个区域剪裁计算库),加入[AGG]\gpc目录下的源码和头文件。

AGG图形显示原理见下图:

其中:

1.VertexSource顶点源,里面存放了一堆2D顶点以及对应的命令,如"MoveTo"、"LineTo"等。

2.Coordinateconversionpipeline坐标转换管道,它可以变换VertexSource中的顶点,比如矩阵变换,轮廓提取,转换为虚线等。

3.ScanlineRasterizer把顶点数据(矢量数据)转换成一组水平扫描线,扫描线由一组线段(Span)组成,线段(Span)包含了起始位置、长度和覆盖率(可以理解为透明度)信息。

AGG的抗锯齿(Anti-Aliasing)功能也是在这时引入的。

4.Renderers渲染器,渲染扫描线(Scanline)中的线段(Span),最简单的就是为Span提供单一颜色,复杂的有多种颜色(如渐变)、使用图像数据、Pattern等。

5.RenderingBuffer用于存放像素点阵数据的内存块,这里是最终形成的图像数据。

要理解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

:

pixfmt_bgr24> renderer_base_type;

28.        renderer_base_type renb(pixf);

29. 

30.        typedef agg:

:

renderer_scanline_aa_solid 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

:

ellipse> ell_cc_type;

38.        ell_cc_type ccell(ell);

39.       

40.        typedef agg:

:

conv_stroke 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上)。

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

现在直接从on_draw()开始看

1.通过rbuf_window()方法得到一个agg:

:

rendering_buffer,它就是“RenderingBuffer”,是一块用于存放图像的内存块。

通过pixfmt_bgr24包装,我们就可以以像素为单位存取图像。

2.agg:

:

renderer_base和agg:

:

renderer_scanline_aa_solid都属于"渲染器Renderer"。

renderer_base为底层渲染器,它支撑起所有的高层渲染器。

这里的renderer_scanline_aa_solid就是一个高层渲染器。

3.agg:

:

ellipse是“顶点源VertexSource”,这个顶点源呈现的是一个圆形。

4.agg:

:

conv_contour和agg:

:

conv_stroke作为“坐标转换管道Coordinateconversionpipeline”,conv_contour扩展轮廓线,conv_stroke只显示轮廓线(如果没有conv_stroke就会显示实心圆,可以去掉试试)。

5.agg:

:

rasterizer_scanline_aa<>就是“ScanlineRasterizer”啦。

6.agg:

:

render_scanlines函数执行这个AGG工作流程。

用AGG实现高质量图形输出

(二)

本文上接《用AGG实现高质量图形输出

(一)》,分别介绍了AGG显示流程中的各个环节。

顶点源(VertexSource)

顶点源是一种可以产生多边形所需要的“带命令的顶点”的对象。

比如三角形顶点源,就应该会产生一个带“MoveTo”命令的点,另外二个带"LineTo"命令的点和最终闭合的“ClosePoly”命令。

头文件

#include//path_storage

#include//ellipse

#include//arc

#include//arrowhead

#include//curve3,curve4

#include//gsv_text,gsv_text_outline

#include//rounded_rect

...

类型

自定义类

所有实现了voidrewind(unsignedpath_id);和unsignedvertex(double*x,double*y);的类。

ellipse

圆,输入为中心点坐标和XY轴半径,本文所用的例子就使用了这个顶点源

arc

弧线,输入为中心点坐标和XY轴半径,以及起始和终止角(rad),顺时针/逆时针方向

curve3

贝塞尔曲线,输入为起点坐标、第一控制点坐标、终点点坐标

curve4

贝塞尔曲线,输入为起点坐标、第一控制点坐标、第二控制点坐标、终点坐标

gsv_text

使用AGG自带字模的文字输出(只支持ASCII码),使用start_point方法指定文字位置,text方法指定文字,flip指定是否上下倒转,size指定文字大小,适合与conv_stroke或gsv_text_outline配合。

gsv_text_outline<>

可变换文字,输入为gsv_text和变换矩阵(默认为trans_affine,后文会提到)。

width方法设置文字宽度

rounded_rect

圆角方形,输入为左上角右下角坐标和圆角半径

path_storage

路径存储器,可以用join_path方法加入多个顶点源。

而且path_storage本身支持move_to,line_to,curve和arc_to等画线功能

arrowhead

箭头,它是作为标记点来用的

其中的arrowhead颇为特殊,它一般作为线段的标记点,具体用法是这样的:

arrowheadah;

ah.head(d1,d2,d3,d4);//定义箭头

ah.tail(d1,d2,d3,d4);//定义箭尾

VertexSourceVS;//其它顶点源

//使用顶点转换器,并指定Markers类型为vcgen_markers_term

//顶点转换器可以是conv_dash、conv_stroke或conv_marker_adaptor,见后文《坐标转换管道》

//vcgen_markers_term:

以端点作为标记点

conv_strokecsVS(VS);

...draw_term

//用conv_marker指定ah作为线段marker点的标记

conv_markerarrow(csVS.markers(),ah);

ras.add_path(csVS);

ras.add_path(arrow);//marker要紧随其后加入

...render

ah.head()和ah.tail()方法中的d1,d2,d3,d4参数的意义见下图

例,画一条简单的箭头直线(基于此处代码)

在on_draw()方法最后加上下列代码:

1.agg:

:

arrowhead ah;

2. ah.head(0,10,5,5);

3. ah.tail(10,10,5,5);

4. // 用path_storage生成一条直线

5. agg:

:

path_storage ps;

6. ps.move_to(160,60);

7. ps.line_to(100,100);

8. // 转换

9. agg:

:

conv_stroke

:

path_storage, agg:

:

vcgen_markers_term> csps(ps);

10. agg:

:

conv_marker

:

vcgen_markers_term, agg:

:

arrowhead>

11.     arrow(csps.markers(), ah);

12. // 画线

13. ras.add_path(csps);

14. agg:

:

render_scanlines_aa_solid(ras,sl,renb,agg:

:

rgba8(0,0,0));

15. // 画箭头

16. ras.add_path(arrow);

17. agg:

:

render_scanlines_aa_solid(ras,sl,renb,agg:

:

rgba8(255,0,0));

得到的图形是:

注意要加头文件:

#include"agg_conv_marker.h"

#include"agg_arrowhead.h"

#include"agg_path_storage.h"

#include"agg_vcgen_markers_term.h"

试验代码,自定义一个顶点源(基于此处代码)

为了对顶点源有更深入的了解,我们要自己实现一个顶点源,这个顶点源只是很简单的一个三角形。

前面说过,只要实现了voidrewind(unsignedpath_id);和unsignedvertex(double*x,double*y);方法就可以作为顶点源。

rewind方法指示顶点源回到第一个顶点;vertex方法取出当前顶点然后把当前顶点下移,返回值是当前顶点所带的命令。

所谓的命令是一个enumpath_commands_e类型,定义如下:

1.enum path_commands_e

2.{

3.    path_cmd_stop     = 0,        //----path_cmd_stop   

4.    path_cmd_move_to  = 1,        //----path_cmd_move_to

5.    path_cmd_line_to  = 2,        //----path_cmd_line_to

6.    path_cmd_curve3   = 3,        //----path_cmd_curve3 

7.    path_cmd_curve4   = 4,        //----path_cmd_curve4 

8.    path_cmd_curveN   = 5,        //----path_cmd_curveN

9.    path_cmd_catrom   = 6,        //----path_cmd_catrom

10.    path_cmd_ubspline = 7,        //----path_cmd_ubspline

11.    path_cmd_end_poly = 0x0F,     //----path_cmd_end_poly

12.    path_cmd_mask     = 0x0F      //----path_cmd_mask   

13.};

path_commands_e还能和path_flags_e组合:

1.enum path_flags_e

2.{

3.    path_flags_none  = 0,         //----path_flags_none

4.    path_flags_ccw   = 0x10,      //----path_flags_ccw 

5.    path_flags_cw    = 0x20,      //----path_flags_cw  

6.    path_flags_close = 0x40,      //----path_flags_close

7.    path_flags_mask  = 0xF0       //----path_flags_mask

8.}; 

vertex()返回的命令中含有path_cmd_stop时表示结束。

1.// 等边三角形

2.class triangle{

3.public:

4.    triangle(double cx, double cy, double r)//中心点,r为中心点到边的长度

5.    {

6.        // 直接准备好三个点

7.        m_step = 0;

8.        m_pt[0].x = cx; m_pt[0].y = cy-r;

9.        m_pt[1].x = cx+r*0.866; m_pt[1].y = cy+r*0.5;

10.        m_pt[2].x = cx-r*0.866; m_pt[2].y = cy+r*0.5;

11.        //AGG把方向作为区分多边形内部和外部的依据,可以试试m_pt[1]和m_pt[2]对调

12.    }

13.    void rewind(unsigned)

14.    {

15.        m_step = 0;

16.    }

17.    unsigned vertex(double* x, double* y)

18.    {

19.        switch(m_step++)

20.        {

21.        case 0:

22.            //第一步,move_to

23.            *x = m_pt[0].x;

24.            *y = m_pt[0].y;

25.            return agg:

:

path_cmd_move_to;

26.        case 1:

27.        case 2:

28.            //第二、三步,line_to

29.            *x = m_pt[m_step-1].x;

30.            *y = m_pt[m_step-1].y;

31.            return agg:

:

path_cmd_line_to;

32.        case 3:

33.            // 第四步,闭合多边形

34.            return agg:

:

path_cmd_end_poly|agg:

:

path_flags_close;

35.        default:

36.            // 第五步,结束

37.            return agg:

:

path_cmd_stop;

38.        }

39.    }

40.private:

41.    agg:

:

point_d m_pt[3];

42.    unsigned m_step;

43.};

在on_draw()方法里把

   agg:

:

ellipseell(100,100,50,50);改成triangleell(100,100,50);

   typedefagg:

:

conv_contour

:

ellipse>ell_cc_type;改成typedefagg:

:

conv_contourell_cc_type;

得到的图形是:

除了文字输出功能(gsv_text只能输出ASCII文字),上面这些顶点源提供的图形丰富程度已经超过了系统API。

文字输出功能将以单独的篇幅讲述。

Coordinateconversionpipeline坐标转换管道

坐标转换管道用于改变顶点源产生的顶点,包括坐标、命令、产生新顶点等。

如对顶点进行矩阵变换、插入顶点形成虚线之类的功能。

变换矩阵(trans_affine)

在认识转换管道之前,先了解一下AGG的变换矩阵。

通过顶点坐标与矩阵的运行,我们可以得到新的坐标。

关于图像的矩阵运算,MSDN里有一篇关于GDI+矩阵运算的文章,很值得一看

头文件

   #include<

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 人文社科 > 法律资料

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1