AGG参考手册中文.doc_第1页
AGG参考手册中文.doc_第2页
AGG参考手册中文.doc_第3页
AGG参考手册中文.doc_第4页
AGG参考手册中文.doc_第5页
已阅读5页,还剩24页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

AGG参考手册1. 前言1.1. 简介1.1.1. Anti-Grain Geometry (AGG)是一个用标准的平台无关的C+开发的通用图形工具包。在把高质量二维图形作为关键的计算机程序中,它可以应用被应用于许多方面。例如,AGG可以用于渲染二维地图。AGG仅仅使用C+和标准C的函数,如memcpy,sin,cos,sqrt等。基本的算法甚至没有使用C+的标准模板库。因此,AGG能够在大量的应用程序中使用,包括嵌入式系统。另一方面,AGG允许使用者替换图形库的任何部分,比如当它不能满足性能的要求时进行库的替换。使用者也可以根据需要添加其它的颜色空间。这一切的实现都是因为AGG广泛采用了C+的模板机制。AGG不是一个结构紧密的图形库,且不容易使用。我认为AGG是一个“创建其它工具的工具”。这意味着AGG中没有“Graphics”对象或其它类似的结构,它包含了许多组织松散、能组合或是单独使用的算法。这些算法都有定义良好的接口,并且算法之间隐式或显式的依赖关系尽可能最小。1.1.2. 大部分图形库都有一个包含成百上千方法的单独类,如GDI+中的“Graphics”。这个对象也可以隐式存在,如OpenGL。总之,所有常用的图形工具包,包括Java2D,DispalyPDF,SVG以及其它优秀的图形工具包都显式或隐式的含有这个类。这种做法简单而且非常适用于一些场合,但是去一直受到限制。它在简单的场合中性能很好,但至少我仍未遇到可以完全满足所有需求的图形库。此外,所有此种类型的库或标准都过于庞大。大部分功能从未被使用,而一些简单的操作却不能实现。图形引擎(或库)是一兆字节来计算的。如果使用最先进的SVG浏览器,它只在显示最简单的基元时表现良好。只要试图使用一些高级操作,如用不同的图形过滤器与SVG交互,将会发生内存泄露,甚至崩溃。这并不是因为它有不良设计,而是因为采取了极端复杂的设计。这种设计本身成为了不可能完成的任务,不能被人感知,就像不能感知无穷大一样。1.1.3. 建议AGG主要的目标是要打破上述的传统,展现其稳定、轻巧、灵活、自由的优点。它的基本概念开始似乎并不遵循惯例,非常接近于STL,但还是存在着很大的区别。STL是一个通用的C+工具,而AGG是C+图形库。STL作为一个方便的工具包直接在应用程序中使用,但我并不建议以同样的方式使用AGG。比较好的方法是针对需要处理的问题,对AGG进行轻量级的、面向问题的封装后再使用。这与GDI+又有什么不同呢?首先,可以完全控制封装后的AGG。AGG只是提供了一系列基本的算法和灵活的设计,使得算法间显式或隐式的联系都最小。使用者可以只定义接口、转换管道和输出格式,甚至可以模拟任何已经存在的图形接口的一部分。例如,使用AGG光栅化器来在屏幕上显示图形并直接调用Windows GDI来打印,并合并为一个单独的API。不信吗?下图是GDI+和AGG的渲染质量的比较。但是最重要的是,如果设计足够灵活,程序将是完全可移植的。AGG还是一个可以将不同的输出合并为一个统一的API的工具。另外,在基于Web的应用程序中,可以使用AGG在服务器端生成栅格图像。而且AGG是完全跨平台的。1.1.4. 反走样和子像素精度反走样是在低分辨率设备上显示图像时用于改善视觉质量的一种广为人知的技术。它基于人的视觉特性。看看下图,尝试猜测一下它表达的意思。这是用反走样发生绘制的单词。根据Kotelnikov-Shannon定理,图像的最大频率远高于Shannon极限。现在来看看正常大小的同一幅图,能够很容易地认出“stereo”这个词。然而,这两幅图是完全相同的。第一幅仅仅是第二副的放大版本。这个特性允许在累积经验的基础上重新构建缺失的信息。反走样并没有让你看得更清楚,只是让你的大脑更好得运转并重构丢失的信息。反走样的成果显而易见。如它使得我们可以绘制出更加详尽的地图。但是关键并不是反走样本身,而是可以利用子像素精度的技术绘制基元。这对于线的视觉厚度尤其重要。首先,如果利用了子像素精度,即使只使用简单的Bresenham线插值法也可以获得比较好的效果。下图显示了使用简单的Bresenham插值后放大的结果。如图中的(2)和(3),细的黑线就是需要插值的线。如果利用子像素精度,虽然线的起点和终点落在同一个像元中,但是会显示两种不同的像素集合。而且两条线有完全不同的切线,这是非常重要的。如果只使用经典的Bresenham插值算法而不考虑子像素精度,结果都会如图中的(1)。这在用短线段近似表示曲线时尤为重要。但是如果同时考虑反走样和子像素精度,能够获得更好的效果。观察下图的不同。 这三个螺旋形都是由短的直线段近似表示的。左边的那幅图采用的是规则的整数Bresenham,坐标与像素匹配(使用Winwows GDI的MoveTo和LineTo函数也可以得到类似的结果)。中间的采用了改进的整数Bresenham,精度为1/256像素。而右边的图同样采用1/256像素的精度,但同时使用了反走样技术。注意,将线段中的真实字像素定位的能力非常重要。如果对规则像素坐标进行反走样,螺旋形会看起来更平滑,但仍然同左边的图一样难看。子像素精度甚至比控制线的视觉厚度更加重要。只有当有了好的反走样算法,精确性才能成为可能。另一方面,如果只用一个像素的离散性来确定线的宽度,反走样就没有什么意义了。反走样和子像素精度总是配合使用。现在显示器的分辨率最多是120DPI,而利用子像素精度可以达到300DPI。下图显示的线的宽度从0.3像素开始,并以0.3像素递增。用反走样和子像素精度渲染的线下面是另外两个用字像素精度渲染的例子。用反走样和子像素精度渲染的圆形可爱的狮子注意,那些小狮子虽然丢失了一些细节,但还是保持了与大狮子的一致性。1.2. 基本概念1.2.1. 库的设计AGG被设计成为由共同理念结合的一系列松散耦合的算法和类模板,因此所有的组件都能很容易的组合起来。同时,以模板为基础的设计使得不需要修改已有代码就能替换图形库中的任何部分。AGG的设计也考虑了扩展性和灵活性。我想创建一个允许我(和任何人)很容易得添加新算法的工具。AGG没有指定任何的使用形式,可以自由得使用它的任何部分。然而,AGG常被当作一个在内存中渲染图像的工具。这并不十分准确,却是一个学习AGG的不错的着手点。教程中介绍AGG的使用是从处理帧缓冲和像素的简单功能的。然后,将逐渐了解到怎样提取库中的不同部分和怎样单独的使用它们。记住栅格图像常常并不是要获取的唯一结果,你可能想要打印高质量的图形,在这种情况下,可以简单地把库中的矢量部分与一些类似于Windows GDI的API结合起来,从而形成一个统一的对外接口。如果API能够用non-zero和even-odd的填充规则渲染多个多边形,那么你要做的就只是将AGG合并到应用程序中。例如,Windows 的API PolyPolygon完全符合这些要求,除了像梯度填充、Gouraud着色、图形变换等高级功能。或者,换一种方式,可以使用所有AGG的算法生成高分辨率的像素图像,然后把结果作为一个像素地图发送到打印机。下面是一个AGG渲染管道的典型结构。渲染管道的典型结构请注意在“Vertex Source”和“Screen Output”之间的组件并不是必要的,取决于应用的需要。例如,你可以使用自己的基于Windows API的光栅化器。这种情况下不需要AGG的光栅化器和渲染器。另外,如果只要绘制线,可以使用AGG的外形线光栅化器,这样虽然有一定的限制,但运行得更快。还有许多其他的可能性。u Vertex Source通过“MoveTo”, “LineTo”等命令产生多边形或者多段线作为一系列连续的二维顶点的对象。它可以是一个容器或按需产生顶点的其它对象。u Coordinate conversion pipeline由许多的坐标转换器组成。它通常作用于由浮点数(双精度)表达的矢量数据(X,Y)。例如,它可以包括仿射变换器、轮廓生成器、标记生成器(如箭头/箭尾)、虚线生成器等。管道有分支并且可以你拥有任意数量的不同管道,也可以自己写转换器并将其加入管道中。u Scanline Rasterizer把矢量数据转换成许多的水平扫描线。扫描线通常(非必须)以“coverage”值携带反走样的信息。u Renderers重复进行扫描线的渲染。最简单的例子是固体填充,渲染器只向扫描线添加一种颜色并将结果写入渲染缓冲区。其它复杂的渲染器可以产生彩色的渲染结果,如梯度填充、Gouraud着色、图形变换、样式等等。Rendering Buffer是一个内存中的缓冲区,用于之后的显示。它通常(非必须)包含适合显示系统的像素格式。例如,24位的B-G-R格式、32位的B-G-R-A格式,Windows的15 位R-G-B-555格式。但是一般来说,如果自定义支持像素格式或颜色空间的底层类,那么就不存在任何限制。1.2.2. 颜色,颜色空间和像素格式AGG中颜色仅仅在渲染器中出现,即将数据放入渲染缓冲区的过程。通常不存在一般意义的“color”结构体和类,AGG总是对具体的颜色空间进行操作。颜色空间的种类很多,包括RGB,,HSV,CMYK等,并且所有的颜色空间都有一定的限制。例如,RGB空间仅仅是人眼可见颜色的一个很小的子集。如果看完整的CIE色度图,会发现RGB三角仅仅是其中的一小部分。CIE色度图和RGB域换句话说,在现实世界中有很多颜色是不能用RGB,CMYK,HSV等颜色空间来表示的。除了自然中存在的,任何一种颜色空间都是有限制的。因此,为了避免将来可能出现的限制,决定不引入类似于“color”的对象。相反,AGG 中存在对具体颜色空间进行操作的对象。目前对最普遍的RGB颜色空间(严格的说是RGB+Alpha)进行操作的对象有agg:gba 和agg:rgba8。RGB 颜色空间用于许多像素格式,如24位RGB或者不同排列顺序的32位RGBA。虽然AGG没有明确支持其它任何颜色空间,但是至少有增加的可能性。这意味着所有依赖“color”类型的类和功能模板都被“ColorT”参数化。1.2.3. 坐标单位AGG主要使用输出设备的坐标,在屏幕上表现为像素。但是与其它库和APIs不同,AGG开始支持子像素精度。这意味着在小数部分会产生影响的地方,坐标由双精度的浮点数来表达。为了不限制使用者的自由,AGG没有嵌入从世界坐标到屏幕坐标的转换机制。所以,当不同的应用程序需要不同的转换方法时,何时何处作转换就显得尤为重要。AGG仅提供了从视口到设备的进行转换的转换器。并且必须将其加到管道的合适位置。同时也可以添加自定义的简单类来支持以毫米、英寸或其它任何物理单位为单位进行的转换。光栅化器在内部使用24.8位格式的整数坐标,整数部分24位,小数部分8位,即所有的内部坐标都被乘以256。如果想要在不能处理浮点数的嵌入系统中使用AGG,尽管不能使用浮点坐标管道,但仍然可以采用带整数接口的光栅化器。1.2.4. AGG 创建和编码注意事项 Anti-Grain Geometry 没有丰富和自动的创建环境。AGG主张“仅编译和运行”(“It just compiles and works”)。它没有其他的安装包。假如从自动配置并工作的making 的应用程序角度来看它可能不是非常好的,但是所有你需要做的仅是将AGG源文件当作是你自己的文件一样,添加到你的分发包中。这种方法的好处是,你不会有任何配置文件和无止境的#ifdef#elif#endif 宏定义的问题。这可能是因为AGG 绝对有最小的外部依赖。对于Unix有最简单的Makefiles 来创建.a 库,对于Windows已经有个创建好的库。这实际上使得调试过程更便利。事实上,几乎所有都真实地实现并调用了其算法。这也进一步地稳定了库,因为所有算法都在操作的情况下通过了深度测试。注意如果想要在Windows Visual C+环境下使用 AGG,请注意其没有使用 “stdafx.h”文件。它是Microsoft特殊的并且不是C/C+标准库的一部分,但是Microsoft强迫使用它。为了成功地在Visual C+工程中使用 AGG ,不要忘记关掉所有AGG 源文件的“预编译头文件” (“Precompiled Headers”)的选项 。此外,如果将AGG 和静态的MFC连接,在连接的时候或许需要重复新建new 和销毁delete操作。 这不是因为AGG,而是因为MFC。在调用其他C+代码而不包含stdafx.h的时候,都会有同样的问题new/delete,需要调用。为了解决这个情况,请参考Microsoft recommendations 或者在Google上搜索“148652 LNK2005”.如上所述, AGG 积极使用 C+ 的模板机制。但是,它仅使用知名的并已被验证过的语句。良好的兼容性是首要追求。C+的领袖们可能惊讶,例如AGG 竟然不使用STL。它不是故意的,为了避免额外的依赖,使用STL 容器的必要性则微乎其微。当然,它不会阻碍你在高层使用STL或者其它流行的工具。 AGG被设计成绝对与已存在的C+库,工具和技术潜在冲突最小。1.2.5. 关于这个手册如上所说,AGG提供一些不同层次上的功能,因此你可以不同的方式使用它。例如,你可能想使用没有扫描线渲染器的AGG 光栅。但为了连贯性和渐进性,我们将从头开始,并通过例子来描述所有功能。该方法可能比快速开头“Quick Start”要更慢,但是它将使你理解设计的理念。这是非常有用的因为ini将会知道如何自己替代特定的类和算法,或者如何扩展库。特别是,扫描线是没有平台依赖的,但不是最快的。你可能想自己写,优化,但是请面向相同的硬件体系架构,诸如 SSE2。2. 基本渲染器从简单的控制台应用程序开始2.1. 渲染缓冲区我们从在内存中创建一桢缓冲,并将其以最简单的光栅格式写到文件中,也就是PPM (Portable Pixel Map)。虽然,它本身并不支持Microsoft Windows,但是有很多阅读器和转换器都是基于它实现的,例如IrfanView( )。所有AGG控制台例子是用P6 256格式,也就是RGB,每个通道占一字节。假设我们操作的RGB-缓冲在内存中的组织如下所示:2.1.1. 第一个示例也是最简单的一个这是第一个例子,在agg2/tutorial/t01_rendering_buffer.cpp中#include #include #include agg_rendering_buffer.henum frame_width = 320, frame_height = 200;/ Writing the buffer to a .PPM file, assuming it has / RGB-structure, one byte per color component/-bool write_ppm(const unsigned char* buf, unsigned width, unsigned height, const char* file_name) FILE* fd = fopen(file_name, wb); if(fd) fprintf(fd, P6 %d %d 255 , width, height); fwrite(buf, 1, width * height * 3, fd); fclose(fd); return true; return false;/ Draw a black frame around the rendering buffer, assuming it has / RGB-structure, one byte per color component/-void draw_black_frame(agg:rendering_buffer& rbuf) unsigned i; for(i = 0; i rbuf.height(); +i) unsigned char* p = rbuf.row_ptr(i); *p+ = 0; *p+ = 0; *p+ = 0; p += (rbuf.width() - 2) * 3; *p+ = 0; *p+ = 0; *p+ = 0; memset(rbuf.row_ptr(0), 0, rbuf.width() * 3); memset(rbuf.row_ptr(rbuf.height() - 1), 0, rbuf.width() * 3);int main() / In the first example we do the following: /- / Allocate the buffer. / Clear the buffer, for now manually / Create the rendering buffer object / Do something simple, draw a diagonal line / Write the buffer to agg_test.ppm / Free memory unsigned char* buffer = new unsigned charframe_width * frame_height * 3; memset(buffer, 255, frame_width * frame_height * 3); agg:rendering_buffer rbuf(buffer, frame_width, frame_height, frame_width * 3); unsigned i; for(i = 0; i rbuf.height()/2; +i) / Get the pointer to the beginning of the i-th row (Y-coordinate) / and shift it to the i-th position, that is, X-coordinate. /- unsigned char* ptr = rbuf.row_ptr(i) + i * 3; / PutPixel, very sophisticated, huh? :) /- *ptr+ = 127; / R *ptr+ = 200; / G *ptr+ = 98; / B draw_black_frame(rbuf); write_ppm(buffer, frame_width, frame_height, agg_test.ppm); delete buffer; return 0;在这个例子中,你甚至都不需要连接任何AGG文件,你只需要在你编译器的命令行中说明AGG的include目录。当你编译并运行这个程序,你可以看到下面的结果。这里几乎都是手动编码的。我们只使用了一个类“redering_buffer”。这个类不知道内存中像素格式,它只是保存了指向每一行的指针数组。你应当分配和销毁缓冲区的实际内存。可以使用一些可行的机制来做,比如:系统API函数,简单内存分配,或者静态定义的数组。在上面这个例子里我们分配宽*高*3字节的内存,因为每个像素使用3个字节。行数据并不需要内存对齐,但是如果使用API,他们仍拥有很好的性能。2.1.2. rendering_buffer 类包含文件: agg_rendering_buffer.h渲染缓冲区类保存每一行的指针,这就是它主要做的。这看上去不像个伟大的实现,但是尝试保持可读性。它的接口和功能都是非常简单的。这是一个类模板的定义类型(typedef)用法。模板类 row_ptr_cache的类型定义:typedef row_ptr_cache rendering_buffer;row_ptr_cache类的接口和函数是: template class row_ptr_cachepublic: row_ptr_cache(); row_ptr_cache(T* buf, unsigned width, unsigned height, int stride); void attach(T* buf, unsigned width, unsigned height, int stride); T* buf(); const T* buf() const; unsigned width() const; unsigned height() const; int stride() const; unsigned stride_abs() const; T* row_ptr(int, int y, unsigned) T* row_ptr(int y); const T* row_ptr(int y) const; row_data row (int y) const; T const* const* rows() const; template void copy_from(const RenBuf& src); void clear(T value);源码: row_ptr_cache这个类没有任何声明或者验证码,因此,在使用前应当将实际内存缓冲区合适地绑定到对象。既可以在构造函数又可以通过attach()函数来完成。它的参数有:buf 内存缓冲区的指针width 图像像素(pixels)的宽度. 渲染缓冲区不晓得像素格式以及内存中一个像素的大小。这个值通过数据成员m_width简单的存储,并通过width()函数返回。 height 缓冲区像素(pixels)的高度(行数) stride 行间的跨度stride(大步)是指T类型里的对象数。Class rendering_buffer类被定义类型“typedefed”为 row_ptr_cache,所以,这个值是以字节为单位的。跨度Stride决定了内存中一行的物理宽度。如果这个值是负数,那么Y轴的方向是反向的, 也就是说,Y=0 将指向缓冲区的最后一行,Y=height-1 到第一个。跨度值的绝对值也是很重要的,因为它允许操作内存中那些行对齐的缓冲区(例如,像在Windows BMP)。此外,这个参数允许就像操作完整的缓冲区一样去操作缓冲区中一些矩形区域,函数attach()更换缓冲区或者参数。它为row-pointers 缓冲区重新分配内存, 因此,可以随时调用。如果新的高度比以前任何一次绑定的都大,那么将会重新分配内存。创建的代价就是初始化变量(设置为0),attach()的代价是分配sizeof(ptr) * height个字节的内存以及初始化行的指针。最经常使用的函数是row_ptr(y),简单的返回第yth行起始的指针,考虑Y-轴的方向。重要!渲染器缓冲不执行任何裁剪或者边界校验,这是高层次类的任务。buf(), width(), height(), stride(), stride_abs()的存取应当是显式的。copy_from()函数拷贝另一个缓冲区的内容到这个“this” 缓冲区. 这个函数是安全的,如果宽width或者高height是不同的,它将会拷贝最大可能的区域。基本上,它用来拷贝相同大小的渲染缓冲区。2.1.3. 例子的两个修改第一个,在创建渲染缓冲区对象的时候将跨度设置为负the stride: agg:rendering_buffer rbuf(buffer, frame_width, frame_height, -frame_width * 3); 结果是:第二,允许尝试绑定到一些已分配的缓冲区的局部。这个修改实际上两次绑定到同一个缓冲区,第一次,到整个帧,然后到它的局部,有20像素的间隙。int main() unsigned char* buffer = new unsigned charframe_width * frame_height * 3; memset(buffer, 255, frame_width * frame_height * 3); agg:rendering_buffer rbuf(buffer, frame_width, frame_height, frame_width * 3); / Draw the outer black frame /- draw_black_frame(rbuf); / Attach to the part of the buffer, / with 20 pixel margins at each side. rbuf.attach(buffer + frame_width * 3 * 20 + / initial Y-offset 3 * 20, / initial X-offset frame_width - 40, frame_height - 40, frame_width * 3 / Note that the stride / remains the same ); / Draw a diagonal line /- unsigned i; for(i = 0; i width(); unsigned height() const return m_rbuf-height(); Returns width and height of the buffer in pixels.color_type pixel(int x, int y);以坐标形式(x,y)返回像素的颜色值。void copy_pixel(int x, int y, const color_type& c);复制颜色c的一个像素到缓冲区。RGB像素格式不考虑在rgba8类型中存在的透明alpha通道, RGBA 简单地和R, G, 和 B一起拷贝透明alpha值到缓冲区 。void blend_pixel(int x, int y, const color_type& c, int8u cover);将颜色c的一个像素和缓冲区中的一个像素进行混合。现在是解释混合blending的时候了。混合是反走样的一个关键特征。在RGBA色彩空间,使用rgba8结构来表示颜色。这个结构已经具有数据成员int8u a;这就是透明alpha通道。但是在这个函数中,我们还可以看到cover参数用来指定deterines像素的覆盖值,等等。即像素中的部分是被一个多边形覆盖的。实际上,你可以解释成第二个Alpha (Beta?)。这么做有两个原因。首先,色彩类型并不是要必须包括透明alpha值。另外,就算色彩类型具有透明alpha域,它的类型也不需要非得和反走样算法中使用的兼容。假设用四个浮点数01表示“Hi-End” RGBA色彩空间。它的透明值alpha也是浮点数的在这个情况下一个字节是很不适合通常的混合,但是却很合适反走样。因此,覆盖值仅是特定的用于反走样目的一个统一的辅助alpha值。全局的,它定义成cover_type,但是在已描述的光栅中直接使用int8u类型。这不是故意的,因为如果增加cover_type的功能是必要的话,所有已经存在的像素格式光栅就和cover_type不兼容了。它们实际上将会不兼容,事实上,8-位覆盖值加8-位透明值是最大的,这与颜色混合时的32-位中间值符合。在16-位的情况下,我们将使用64-位的整数,这对32-位的系统平台而言实在是代价高昂。void copy_hline(int x, int y, unsigned len, const color_type& c);void copy_vline(int x, int y, unsigned len, const color_type& c);以某个颜色画一条水平的或者垂直的线。void blend_hline(int x, int y, unsigned len, const color_type& c, int8u cover);void blend_vline(int x, int y, unsigned len, const color_type& c, int8u cover);混合某个颜色的一条水平的或者垂直的线,分离拷贝“copy”和混合“blend”版本的原因是为了实现。当然,这可能是一个额外的if/else语句(在“blend”版本中),但是尽管如此,在不同的散点图应用程序中使用hline/vline来绘制一些小的标识的时候这还是比较关键critical的。void blend_solid_hspan(int x, int y, unsigned len, const color_type& c, const int8u* covers);void blend_solid_vspan(int x, int y, unsigned len, const color_type& c, const int8u* covers);混合一个水平的或者一个垂直的纯色的跨度。跨度和 hline/vline差不多,但是有一个覆盖值的数组。这些函数被用来渲染纯色的反走样多边形。void blend_color_hspan(int x, int y, unsigned len, const color_type* colors, const int8u* covers);void blend_color_vspan(int x, int y, unsigned len, const color_type* colors, const int8u* covers);混合一个水平的或者垂直的颜色跨度。该函数被用在不同跨度产生器中,比如,渐变,图像,图案,高洛德过滤等。他们接受一个颜色数组,其类型必须与已使用的像素格式兼容。例如,所有已经存在的RGB像素格式与rgba8类型兼容。参数covers是blend_solid_hspan中的一个覆盖值的数组。它是可选的并且可以为0.另一个例子是绘制太阳光谱,rgba类, 以双精度doubles的形式保存四个组成,具有静态的from_wavelength方法和各自的构造函数,rgba8类可以从rgba中创建 (这在AGG中是很普通的一个策略, 一些颜色类型可以从rgba类型构造). 我们将这么使用.#include #include #include agg_pixfmt_rgb24.henum frame_width = 320, frame_height = 200;/ .write_ppm is main() /- / Allocate the buffer. / Clear the buffer, for now manually / Create the rendering buffer object / Create the Pixel Format renderer / Create one line (span) of type rgba8. / Fill the buffer using blend_color_span / Write the buffer to agg_test.ppm / Free memory unsigned char* buffer = new unsigned charframe_width * frame_height * 3; memset(buffer, 255, frame_width * frame_height * 3); agg:rendering_buffer rbuf(buffer, frame_width, frame_height, frame_width * 3); agg:pixfmt_rgb24 pixf(rbuf); agg:rgba8 spanframe_width; unsigned i; for(i = 0; i frame_width; +i) agg:rgba c(380.0 + 400.0 * i / frame_width, 0.8); spani = agg:rgba8(c); for(i = 0; i frame_height; +i) pixf.blend_color_hspan(0, i, frame_width, span, 0); write_ppm(buffer, frame_width, frame_height, agg_test.ppm); delete buffer; return 0;这是结果:2.2.3. 透明掩膜适配器(Alpha-Mask Adaptor )透明掩膜是一个分离的缓冲,通常被用于实现低级裁剪,生成任意的形状。这有一个特殊的适配器类,通过透明掩膜过滤器调用所有的像素格式渲染器。通常透明掩膜以一个同等大小的灰

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论