显示效果:
在第19行的span_gen_type之前,所有的事情都在为定义这个线段生成器做准备。 首先是用pixel_map读取bmp文件,然后生成rendering_buffer和pixfmt_bgr24作为这个线段生成器的\。
然后是线段分配器,这个没什么特殊要求的话用span_allocator就可以了。
接着是插值器类型,插值器也有几个类型(后面会介绍),它的构造函数需要一个变换矩阵对象,于是我们得为它装备一个。
现在,终于可以组合成一个我们的线段生成器了。这里使用的是span_image_filter_rgb_bilinear_clip,它的Source是PixelFormat Renderer,如本例的pixfmt_bgr24。
span_image_filter_rgb_bilinear_clip的构造函数有三个参数,分别是Source对象,填充来源范围之外的颜色和插值器对象。
我们可以改变插值器的矩阵来变换填充图像,象这里的img_mtx.scale(0.5)和img_mtx.translate(40,40)。要注意的是,插值器的矩阵运算是从目标位置向源位置计算的(即根据目标位置变换得到对应的填充源位置),所以想对源图像变换的话,要记得最后调用矩阵的invert()方法取反。
最后,画圆。由于ell是ellipse对象,没有被conv_stroke转换的ellipse对象是实心的(多边形而不是多义线),于是填充之。
插值器Interpolator
插值器的作用是连接目标位置和源位置,比如要填充一个8*8的图形,对应的填充源是一个4*4的图像,一种简单的线性插值器就要根据目标的位置线性计算得到源对应的位置,如目标点(4,4)、(4,5)、(5,4)、(5,5)这几个位置点对应到源的(2,2)点上。 头文件
? #include
? template
class agg::span_interpolator_linear
template
? class agg::span_interpolator_persp_exact ?? template
?? class agg::span_interpolator_persp_lerp
?? template
不同的插值器对于不同的变换有各自的优势,对于大部分应用来说,span_interpolator_linear是比较简单高效的。
实验代码,使用span_interpolator_persp_lerp
把上面的演示代码里的interpolator_type改成span_interpolator_persp_lerp,这是一个透视变换的插值器,输入为源四个角的坐标和目标的四个角上的坐标。
?? ...
?? // 插值器
?? //typedef agg::span_interpolator_linear<> interpolator_type; //插值器类型 ?? //agg::trans_affine img_mtx; // 变换矩阵不需要了
?? //interpolator_type ip(img_mtx); // 插值器
?? typedef agg::span_interpolator_persp_lerp<> interpolator_type; //插值器类型 ?? const double offset = 50; // 偏移
?? const double scale = 0.5; // 缩放倍数 ?? double src[8]={offset+0,offset+0,
?? offset+pm_img.width()*scale,offset+0,
?? offset+pm_img.width()*scale,offset+pm_img.height()*scale, ?? offset+0,offset+pm_img.height()*scale ?? }; //源四角坐标,按偏移和缩放倍数改变一哈 ?? ?? ?? ?? ??
double dst[8]={0,0, pm_img.width(),0,
pm_img.width()+100,pm_img.height(), 100,pm_img.height()-100
}; //目标四角坐标,左右乱扯一哈
?? interpolator_type ip(src,dst); ?? ...
最后别忘了把img_mtx相关代码注释掉: ?? //img_mtx.scale(0.5);
?? //img_mtx.translate(40,40); ?? //img_mtx.invert(); //注意这里
显示效果:
变换器Transformer
注意一下我们前面用的span_interpolator_linear,以及曾经使用过的conv_transform,默认的模板参数Transformer为trans_affine。我们已经知道trans_affine是一个2*3的变换矩阵。在AGG中,变换器不仅仅只有矩阵,这里将要介绍的就是其它的一些变换器。 头文件
?? #include
?? #include
?? agg::trans_affine ?? agg::trans_bilinear ?? ?? ?? ??
agg::trans_single_path agg::trans_double_path agg::trans_perspective agg::trans_viewport
?? agg::trans_warp_magnifier 实验代码,使用trans_warp_magnifier
同样把示例代码中的插值器部分改成下列代码 ?? ...
?? // 插值器
?? //typedef agg::span_interpolator_linear<> interpolator_type; //插值器类型 ?? //agg::trans_affine img_mtx; // 变换矩阵 ?? //interpolator_type ip(img_mtx); // 插值器
?? typedef agg::span_interpolator_trans<
?? agg::trans_warp_magnifier // 使用trans_warp_magnifier ?? > interpolator_type; //插值器类型 ?? agg::trans_warp_magnifier mag; ?? interpolator_type ip(mag); ?? mag.magnification(0.5); ?? mag.center(100,100); ?? mag.radius(50); ?? ...
建议把后面的ras.add_path(ell)改成ras.add_path(ccell),画得大一点好看清效果,呵呵 显示效果
图像访问器Image Accessor
也许有不少同学看到开头的线段生成器一节时,已经尝试修改示例代码中的span_image_filter_rgb_bilinear_clip了(比如改成span_image_filter_rgb_bilinear)。不过编译时会出错,这是因为大部分的线段生成器类接受的Source模板不是 PixelFormat Renderer,而是Image Accessor即图像存取器。 头文件
? #include
? template
? class agg::image_accessor_clip // 图像以外的地方用指定颜色填充 ? template
? class agg::image_accessor_clone // 图像以外的地方以图像边缘填充 ? template
? class agg::image_accessor_no_clip // 图像以外不可读取,否则引发异常 ? template
? class agg::image_accessor_wrap // 平铺图像,平铺方式由WrapX和WrapY指定 实验代码
把示例代码中的span_image_filter_rgb_bilinear_clip部分改成下面的代码 ?? ...
?? // 线段生成器
?? //typedef agg::span_image_filter_rgb_bilinear_clip
?? //span_gen_type span_gen(pixf_img, agg::rgba(0,1,0), ip); ?? // 图像访问器
?? typedef agg::image_accessor_clone
?? interpolator_type > span_gen_type; ?? span_gen_type span_gen(accessor, ip); ?? ...
建议把后面的ras.add_path(ell)改成ras.add_path(ccell) 显示效果
image_accessor_wrap类要指定WrapX和WrapY,可选的有: wrap_mode_reflect