摘自:http://www.cnblogs.com/muxue/archive/2010/06/03/1751094.html
看看这个声明:
agg::pixfmt_rgb24 pixf(rbuf);
这里我们创建了一个底层的像素渲染对象(pixel rendering object)并将它附着到渲染内存区(rendering buffer)上,它是这样定义的:
typedef pixel_formats_rgb24<order_rgb24>pixfmt_rgb24;
类模板 pixel_formats_rgb24 掌握了内存中具体的像素格式信息。唯一的模板参数可以是 order_rgb24 或是 order_rgb23,它们定义了颜色字节(color channels)的顺序。
与 rendering buffer 不同的是,这些类使用整型的像素坐标进行操作,因为它们知道怎么计算对于特定点 X 的偏移。你可能会说,如果在 rendering buffer 中保存像素的宽度值的话会更容易,但是在实践中会有很多限制。别忘了,像素宽度可能比一个字节还小,比如在打印机渲染高解析度的 B&W 图像的时候就是这样。因此,我们需要将这个功能分离出来,rendering_buffer 这个类就用于加速对“行”的访问,而 pixelformat renderers 就负责如何解析“行”是什么。
重要!
像素格式相关的类并不进行任何的裁剪操作,也就是说直接使用这些类进行工作一般来说不***全。裁剪是上层类的功能。采用这样设计的理由很简单:要让用户设计自定义的像素格式类越简单越好。像素格式可能会五花八门,但裁剪操作的代码一般都没有什么区别。
pixel_formats_rgb24(rendering_buffer&rb);
像素格式渲染器(pixecl format renderers)的构造函数需要一已经创建并良好初始化的rendering_buffer对象的引用。这个构建工作的开销很小,基本上只是初始化一个指针。
Member Functions
像素格式渲染器(pixecl format renderers)必须要实现以下这些接口:
unsigned width() const { return m_rbuf->width(); }
unsigned height() const { returnm_rbuf->height(); }
返回内存区的宽和高(以像素数来衡量)
color_type pixel(int x, int y);
返回(x,y)坐标处的像素的颜色
void copy_pixel(int x, int y, constcolor_type& c);
将带颜色的像素拷入缓存区中。如果是本身 RGB 像素格式,那么它就不考虑 rgba8 拷贝源中的存在的 alpha 通道。如果本身是 RGBA,那么它就简单地把所有值都拷贝过来,包括 R、G、B,以及 alpha 通道值。
void blend_pixel(int x, int y, constcolor_type& c, int8u cover);
这个函数将带颜色信息的像素 c 与缓存区(x,y)处的像素进行混合(blending)。现在我们来解释一下“混合”的概念。混合(blending)是抗锯齿(anti-aliasing)的关键特性。在 RGBA 的颜色空间中,我们使用 rgba8 结构体来代表颜色。这个结构体有一个数据成员int8u a ,它就是 alpha 通道。不过,在这个函数里,我们还看到一个参数 cover ,表示像素的覆盖值大小,比如,这个像素被多边形所“覆盖”的部分的大小(译注:这涉及到亚像素精度,因为一个像素可以分为 256*256 份,所以这个像素并不一定全部被“覆盖”,详细可参考AGG 对于亚像素的说明)。其实你可以把它看成是另一个 alpha(或者应该叫它Beta?:))。这么做有两个原因,首先,颜色类型(color type)不一定非要包含 alpha 值)。就算颜色类型带有 alpha 值,它的类型也不一定非要与抗锯齿算法中使用的颜色类型一致。假设你现在使用的是 "Hi-End" RGBA 颜色空间,这种颜色空间使用4个取值范围是[0,1]浮点型来表示,alpha通道值也使用浮点数――――对于这种情况来说,混合时使用一个byte实在太少了,但在去锯齿时却非常够用。所以,cover 值就是为去锯齿而使用的一个统一的备用 alpha 值。在大部分情况来说,用 cover_type 来定义它,但在光栅化处理器(rasterizers)中是直接显示地使用 int8u 类型的。这是故意这么定义的,因为如果需要加强 cover_type 的能力时,会使得所有已经存在的像素格式光栅化处理器(pixel format rasterizres)变得与cover_type 不兼容。它们确实是不兼容的,在进行颜色混合时,如果中间值使用 32-bit 值来暂存的话,那么最大只能使用 8-bit 的覆盖值(coverage value)和 8-bit 的 alpha 值(alpha) 。如果使用 16-bit 的值的话,就要用64-bit 的中间值暂存,这对于 32-bit 的平台来说会有非常昂贵的开销。
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, unsignedlen, const color_type& c, int8u cover);
void blend_vline(int x, int y, unsignedlen, const color_type& c, int8u cover);
采用混合颜色的模式描画一带某种颜色的水平(或垂直线)线。之所以要分开 copy 和 blend 两个版本,是因为考虑到效率问题。虽然可以使用一个if/else (其实在 blend 版的描画函数中就有)来区分,但对于某些场合,比如要描画很多小型标识(markers)时,这会很影响效率,这种场景在不同的散点图描画程序(scatter plot applicatioin)中常常遇到。
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);
混合描画一条水平或是垂直的 solid-color 的 span, Span与 hline 和 vline 几乎是一样的,但它拥有一个存有 coveragevalue 的数组。这两个函数在渲染实心的去锯齿多边形时会用到。
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, unsignedlen,
const color_type*colors, const int8u* covers);
混合描画水平或是垂直的颜色 span ,这两个函数用于不同的 span 产生器中,比如说 gradient,image,patterns,Gouraud interpolation 等等。函数接受一个颜色数组参数,这个颜色数组必须与所使用的像素格式兼容。比如说,所有 AGG 中已经有的 RGB 像素格式都与 rgb8类型是兼容的。 covers 参数是一个 coverage value 的数组,这与 blend_solid_hspan 中的是一样的。这是参数可选,可以设置为 0 。
下面这个例子是描画阳光的光谱。rgba 类包含有 4 个浮点数的颜色部分(包括alpha),这个类有一个静态函数 from_wavelength ,以及相应的构造函数。rgba8 可以用 rgba 来构造(在 AGG 中这是一个常见的策略,也就是任何的颜色类型都可以用 rgba 来构造)。
该类是从像素的角度,来填充渲染缓存,通过指定rgb8结构体,来填充位图的像素值。在这里根据代码的浏览,可以发现copy_pixel,blend_pixel两个函数并没有采用任何的抗锯齿和反走样算法,而是直接根据颜色的次序进行填充,可以说这种方式在渲染横条或者竖条的情况下,效果是可以的,至少目前看不出来,设备显示有限。稍后会对上面的两个函数进行分析。