AGG高质量图形输出 下载本文

内容发布更新时间 : 2024/4/28 19:31:05星期一 下面是文章的全部内容请认真阅读。

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

使用前AGG的准备工作

? 下载AGG库,它的家在http://www.antigrain.com/,目前最高版本是AGG2.5 ? 解压,后面以[AGG]表示AGG的解压目录. ? 把[AGG]\\include加入到include搜索目录中

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

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

?

如果要用AGG的控件和窗体,要加入[AGG]\\src\\ctrl\\*.cpp和

[AGG]\\src\\platform\\\\*.cpp,头文件在[AGG]\\include\\ctrl和[AGG]\\include\\platform里

? 如果要用到TrueType字体显示,要加入[AGG]\\font_win32_tt目录下的源码和头文件。利用freetype库,则是[AGG]\\font_freetype目录。

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

AGG图形显示原理见下图:

其中:

? Vertex Source 顶点源,里面存放了一堆2D顶点以及对应的命令,如\、

\等。

? Coordinate conversion pipeline 坐标转换管道,它可以变换Vertex Source中的顶点,

比如矩阵变换,轮廓提取,转换为虚线等。

? Scanline Rasterizer 把顶点数据(矢量数据)转换成一组水平扫描线,扫描线由一组线段(Span)组成,线段(Span)包含了起始位置、长度和覆盖率(可以理解为透明度)信息。AGG的抗锯齿(Anti-Aliasing)功能也是在这时引入的。

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

?? Rendering Buffer 用于存放像素点阵数据的内存块,这里是最终形成的图像数据。 要理解AGG的工作原理,先看一段代码:

? #include \

? #include \

? #include \? #include \? #include \? #include \

? #include \? #include \? #include \?? #include \

?? 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 renderer_base_type; ?? renderer_base_type renb(pixf);

?? typedef agg::renderer_scanline_aa_solid renderer_scanline_type;

?? renderer_scanline_type rensl(renb); ??

?? // Vertex Source

?? agg::ellipse ell(100,100,50,50); ??

?? // Coordinate conversion pipeline

?? typedef agg::conv_contour ell_cc_type;

?? ell_cc_type ccell(ell); ?? ?? ?? ??

typedef agg::conv_stroke ell_cc_cs_type; ell_cc_cs_type csccell(ccell);

?? // Scanline Rasterizer

?? agg::rasterizer_scanline_aa<> ras; ?? agg::scanline_u8 sl; ?? ?? // Draw

?? renb.clear(agg::rgba8(255,255,255)); ?? 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); ?? } ?? } ?? };

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

{

the_application app(agg::pix_format_bgr24, false); app.caption(\ if(app.init(600, 400, agg::window_resize))

?? {

?? return app.run(); ?? }

?? return -1; ?? }

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

? 新建空白GUI项目(就是有WinMain的项目) ? 把[AGG]\\src里所有*.cpp加入到项目中

? 把[AGG]\\src\\platform\\Win32\\*.cpp加入到项目中 ? Ctrl+C/Ctrl+V 上面的代码 ? 编译! 显示效果:

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

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

现在直接从on_draw()开始看

? 通过rbuf_window()方法得到一个agg::rendering_buffer,它就是“Rendering Buffer”,

是一块用于存放图像的内存块。通过pixfmt_bgr24包装,我们就可以以像素为单位存取图像。

? agg::renderer_base和agg::renderer_scanline_aa_solid都属于\渲染器Renderer\。renderer_base为底层渲染器,它支撑起所有的高层渲染器。这里的renderer_scanline_aa_solid就是一个高层渲染器。

? agg::ellipse是“顶点源Vertex Source”,这个顶点源呈现的是一个圆形。

? agg::conv_contour和agg::conv_stroke作为“坐标转换管道Coordinate conversion pipeline”,conv_contour扩展轮廓线,conv_stroke只显示轮廓线(如果没有conv_stroke就会显示实心圆,可以去掉试试)。 ?? agg::rasterizer_scanline_aa<>就是“Scanline Rasterizer”啦。 ?? agg::render_scanlines函数执行这个AGG工作流程。

下面,我们来考察AGG显示流程中的每个环节。理解每个环节最好的方法是编写实验代码,建议先参照这里建 立一个可以运行的AGG实验环境。

顶点源(Vertex Source)

顶点源是一种可以产生多边形所需要的“带命令的顶点”的对象。比如三角形顶点源,就应该会产生一个带“MoveTo”命令的点,另外二 个带\命令的点和最终闭合的“ClosePoly”命令。 头文件

#include //path_storage #include // ellipse #include // arc

#include // arrowhead #include // curve3, curve4

#include // gsv_text, gsv_text_outline #include // rounded_rect ... 类型 自定义类 ellipse arc curve3 curve4

所有实现了void rewind(unsigned path_id);和unsigned vertex(double* x, double* y);的类。

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

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

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

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

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

可变换文字,输入为gsv_text和变换矩阵(默认为trans_affine,后文会提到)。width方法设置文 字宽度

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

路径存储器,可以用join_path方法加入多个顶点源。而且path_storage本身支持move_to, line_to,curve和arc_to等画线功能 箭头,它是作为标记点来用的

gsv_text gsv_text_outline<> rounded_rect path_storage arrowhead

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

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