Chinaunix首页 | 论坛 | 博客
  • 博客访问: 538956
  • 博文数量: 252
  • 博客积分: 6057
  • 博客等级: 准将
  • 技术积分: 1635
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-21 10:17
文章分类

全部博文(252)

文章存档

2013年(1)

2012年(1)

2011年(32)

2010年(212)

2009年(6)

分类: C/C++

2010-12-01 09:02:09

AGG 库是一个跨平台的2D图形库,全称是“Anti-Grain Geometry”。从名字上就能看出它的特色就是有很好的抗锯齿效果,当然GDI+也有抗锯齿功能,不过GDI+不能跨平台不是?而且有人测试说AGG 比GDI+快10倍以上,虽然有吹牛之嫌,不过比GDI+快是没错的了。

C++Builder用的是VCL库,VCL里的绘图类TCanvas最终调用的是GDI API,所以画的曲线有明显的锯齿

对比一下TCanvas画的和AGG画的:
\ \
TCanvas作品(GDI) AGG作品

下面是源代码:在名为img1的TImage里画一个三角形

用TCanvas画

  1. TCanvas *pCanvas = img1->Canvas;
  2.  
  3. pCanvas->FillRect( img1->ClientRect );
  4. pCanvas->MoveTo(21, 34);
  5. pCanvas->LineTo(398, 123);
  6. pCanvas->LineTo(165, 302);
  7. pCanvas->LineTo(21, 34);

用AGG画

  1. // 生成24位TBitmap给AGG使用
  2. Graphics::TBitmap *pBmp = new Graphics::TBitmap;
  3. pBmp->PixelFormat = pf24bit;
  4. pBmp->Width = img1->Width;
  5. pBmp->Height = img1->Height;
  6.  
  7. // 得到TBitmap的位图数据(点阵缓存,每行字节数等)
  8. BITMAP bmp;
  9. ::GetObject(pBmp->Handle, sizeof(bmp), &bmp);
  10.  
  11. //============================================================
  12. // 轮到 AGG 了
  13. // 把pBmp的点阵缓存包装成AGG认识的rendering_buffer类
  14. agg::rendering_buffer rbuf(
  15.     (unsigned char*)bmp.bmBits,
  16.     pBmp->Width, pBmp->Height,
  17.     -bmp.bmWidthBytes);
  18.  
  19. // Windows的24位BMP是BGR格式,所以用pixfmt_bgr24
  20. agg::pixfmt_bgr24 pixf(rbuf);
  21. agg::renderer_base renb(pixf);
  22. // 以白色填充
  23. renb.clear(agg::rgba8(255, 255, 255));
  24.  
  25. // Rasterizer & scanline
  26. agg::rasterizer_scanline_aa<> ras;
  27. agg::scanline_p8 sl;
  28.  
  29. // 在ras里画个三角形
  30. {
  31.     agg::path_storage ps;
  32.     ps.move_to(21,34);
  33.     ps.line_to(398, 123);
  34.     ps.line_to(165, 302);
  35.     ps.close_polygon();
  36.  
  37.     agg::conv_stroke csps(ps);
  38.     ras.add_path(csps);
  39.     // 把ras里的东东画到renb上,抗锯齿
  40.     agg::render_scanlines_aa_solid(ras, sl, renb, agg::rgba8(80, 90, 60));
  41. }
  42. //============================================================
  43. img1->Picture->Assign(pBmp);
  44.  
  45. delete pBmp;

要编译上面AGG的代码,请按以下步骤配置

  1. 下载AGG库,它的家在,目前最高版本是AGG2.5
  2. 解压,后面以[AGG]表示AGG的解压目录.
  3. 把[AGG]\include加入到C++Builder项目的include目录中
  4. 把[AGG]\src里所有cpp加入到C++Builder项目中
  5. 引用AGG头文件,编译,完成
    1. #include "agg_scanline_p.h"
    2. #include "agg_renderer_scanline.h"
    3. #include "agg_pixfmt_rgba.h"
    4. #include "agg_rasterizer_scanline_aa.h"
    5. #include "agg_path_storage.h"
    6. #include "agg_ellipse.h"
    7. #include "agg_conv_stroke.h"
    8. #include "agg_conv_transform.h"
    9. #include "agg_span_allocator.h"
    10. #include "agg_span_gradient.h"
    11. #include "agg_span_interpolator_linear.h"

注:如果打算经常用AGG,可以考虑把AGG直接编译成lib,

进入控制台模式
cd [AGG]\src
bcc32 -c -b- -O2 -I../include *.cpp
for %1 in (*.obj) do tlib agg_bcc.lib +%1
del *.obj

执行上面命令后会生成一个agg_bcc.lib文件,以后只要把它加入项目即可,注意bcc32的(-b-)选项,如果你的项目里 “Treat enum types as ints”是打开的,就把这个-b-选项去掉。

由于AGG是跨平台库,为了保持通用性,它只负责处理内存中的点阵数据,如本例中的bmp.bmBits。并且AGG对图像的载入和保存支持有限 (实际上它在Windows下只支持bmp),如果要支持jpg,png,gif之类格式的支持,可以考虑先用其它图像库(如CxImage,甚至 GDI+也行)载入图像,然后还原成点阵给AGG处理。

这里不得不再次佩服一下Borland/CodeGear的功力,VCL的TCanvas包装得确实好,相对于AGG来说代码简单得不是一个数量级 (当然,这也和AGG的超强功能有关)。如果哪位有兴趣(+有时间、有能力),把AGG包装成与TCanvas相似的接口那绝对是功德无量啊~~

关于AGG更多的细节,请留意《》



参考文章:

《用AGG实现高质量图形输出》






阅读(1652) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~