Chinaunix首页 | 论坛 | 博客
  • 博客访问: 690734
  • 博文数量: 148
  • 博客积分: 4086
  • 博客等级: 上校
  • 技术积分: 1766
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-06 23:27
文章分类

全部博文(148)

文章存档

2013年(19)

2012年(9)

2011年(106)

2009年(14)

分类: C/C++

2009-12-09 22:24:32


CImg是一个跨平台的C++的图像处理库,提供了加载、处理、显示、保存等一系列功能,其中的图像处理功能尤其强大。
首先,建议先到欣赏一下使用CImg代码做的Demo,就是它使我这个没有图像处理经验的童鞋也心动得以致于研究了一星期^_^

主页地址:
下载地址:
下载时注意应该下载源码包,里面附带的大量的例程。而实际上CImg库只是一个头文件CImg.h,这个头文件里包含了CImg库所有的代码。
另外不要错过下载列表中的一个部分完成的《》。

CImg的Hello World

这段代码是从《CImg参考手册》里抄的,可以大致了解一下CImg的框架。
以VC为例:新建控制台程序,输入下面的代码。项目属性的链接器附加依赖项加入kernel.lib user32.lib gdi32.lib。最后,把CImg.h拷贝到项目路径下,即可成功编译运行

  1. #include "CImg.h"
  2. using namespace cimg_library;
  3. int main() 
  4. {
  5.     // 定义一个每个颜色 8 位(bit)的 640x400 的彩色图像
  6.     CImgchar> img(640,400,1,3);  
  7.     //将像素值设为 0(黑色)
  8.     img.fill(0); 
  9.     // 定义一个紫色
  10.     unsigned char purple[] = { 255,0,255 };
  11.     
  12.     // 在坐标(100, 100)处画一个紫色的“Hello world”
  13.     img.draw_text(100,100,"Hello World",purple);  
  14.     // 在一个标题为“My first CImg code”的窗口中显示这幅图像
  15.     img.display("My first CImg code");                  
  16.     
  17.     return 0;

运行这段代码,显示结果:

在CImg体系中,图像有x,y,z,v四个轴,前三个当然是3维空间的三个方向(知道了吧?CImg可以处理3维图像),第四个v一般表示色彩通道数,比如RGB三色就是3。

上面的代码每行的注释已经写得很详细,从代码里可以看出CImg处于namespace cimg_library名空间之下;模板类CImg<>是主要的图像类,提供了大量的图像处理方法。

在CImg库里,还有一个重要的类是CImgDisplay,它提供了一个显示窗口,不仅可以显示CImg的内容,还可以接收键盘鼠标事件,我们可以暂时把它看成是一个CImg专用窗体类。

CImg类介绍

CImg类提供的方法非常多,为了便于查阅,我用Doxygen重新生成了一份CImg库的说明文档,并做成chm格式,可以本文后面找到下载地址。
CImg模板类提供了图像的载入、保存、处理功能,是整个库的核心组件。它的声明如下:

template<typename T>
struct cimg_library::CImg;

模板参数T指明CImg中元素的类型。在自带的参考手册中称这些元素为像素(pixel),不过因为这里的像素和我们平时的像素概念稍微有点不同。因为前 面说过CImg体系中有xyzv四个轴,CImg手册称它为4维图像,把4维图像里的单个元素称为像素。而事实上第四维的v通常就是我们的色彩通道,所以 要在屏幕上显示出一个真正的像素往往要取同一xyz轴上所有v轴的点(所有色彩通道合成一个真正的彩色像素)。在本文中我决定把这个组成图像的最小单位称 为元素,由所有色彩通道v组成一个像素。

CImg类中的6个成员变量:
  1. // 分别对应x,y,z,v四个轴的大小,即宽度、高度、深度和通道数。
  2. unsigned int width, height, depth, dim;
  3. // 指向内存中的图像数据
  4. T *data;
  5. // 指明data是否是共用的,即是否有data的拥有权。
  6. bool is_shared;

CImg类里的成员变量都是public的,我们可以直接存取它们,不过为了防止破坏完整性,建议使用成员方法如dimx(), dimy(), dimz(), dimv() 和ptr()来操作。

CImg的构造函数,大部分构造函数都很直白,就不列出了,可以查看手册,下面列出的是一些特殊的构造函数。

  1. // 以字符串指定的数据填充,其中的values字符串包含了一串十进制数字表示的数据。
  2. // 比如参数values为字符串"20,30,40,50", repeat_pattern为true时
  3. // 图像内的数据就以20,30,40,50,20,30,40,50,20...填充。
  4. CImg (
  5.     const unsigned int dx,
  6.     const unsigned int dy,
  7.     const unsigned int dz,
  8.     const unsigned int dv,
  9.     const char *const values,
  10.     const bool repeat_pattern)

  1. // 由shared参数决定是否直接引用img中的data数据还是自己持有一份拷贝(是否共享)
  2. CImg (const CImg< T > &img, const bool shared)

  1. // 参考img的大小构造一个新的CImg对象
  2. CImg (const CImg< t > &img, const char *const dimensions)

这个构造函数的dimensions参数由一串数字或转义符组成,分别对应x,y,z,v的大小。比如:
参数为"20 20 1 3"时新CImg对象的x,y,z,v的大小分别是20 20 1 3。
转义符以%开头,后缀可以是:

x, dx, dimx, width 表示img.width
y, dy, dimy, height 表示img.height
z, dz, dimz, depth 表示img.depth
v, dv, dimv, dim 表示img.dim

比如CImg(img, "%y %x 1 3");可以生成一个和img的宽高正好互换的CImg对象。

  1. // 从文件里载入图像,文件类型由扩展名确定
  2. CImg (const char *const filename)

CImg库本身支持BMP,RAW,HDR,INR,PGM,PPM,PAN,DLM格式
安装了ImageMagick(Unix系)后可支持JPG,GIF,PNG,TIF等多种格式
CImg也能使用jpeg库,zlib/png库,tiff库等来支持多种图像格式,只需编译时加入这些库即可。可以到这里下载这些库文件。

  1. // 从CImgDisplay对象的内容创建图像
  2. CImg (const CImgDisplay &disp)

CImg部分成员方法

CImg提供了丰富的成员方法,在这里全部列出是不可能的,这里只作一些简单介绍。更多方法请参考手册。
  1. // 赋值,它有多个重载的版本,参数和构造函数一样,实际上构造函数最终都是调用它来实现的。
  2. CImg< T > &  assign ();
  3.  
  4. // 把data数据转交给img,自己不再有data数据的拥有权
  5. CImg< T > &  transfer_to (CImg< T > &img);
  6.  
  7. // 清除数据
  8. CImg< T > &  clear ();
  9.  
  10. // 获得所有元素总数
  11. unsigned long  size () const
  12.  
  13. // 获得某个轴向的大小
  14. int  dimx () const;
  15. int  dimy () const;
  16. int  dimz () const;
  17. int  dimv () const;
  18.  
  19. // 取得遍历元素的迭代器,这里的iterator其实就是T*。
  20. iterator  begin ();
  21. iterator  end ();
  22.  
  23. // 取得首尾数据
  24. T &  first ();
  25. T &  last ();
  26.  
  27. // 取得图像内部数据(第二个版本取得数据并定位到指定位置)
  28. T *  ptr ();
  29. T *  ptr (
  30.     const unsigned int x,
  31.     const unsigned int y=0,
  32.     const unsigned int z=0,
  33.     const unsigned int v=0);
  34.  
  35. // 快速存取指定位置上的数据
  36. T &  operator() (
  37.     const unsigned int x,
  38.     const unsigned int y=0,
  39.     const unsigned int z=0,
  40.     const unsigned int v=0);
  41.  
  42. // 按索引直接存取data数组
  43. T &  operator[] (const unsigned long off)
  44.  
  45. // 得到指定位置的索引
  46. long  offset (
  47.     const int x,
  48.     const int y=0,
  49.     const int z=0,
  50.     const int v=0) const;
  51.  
  52. // 存取指定位置上的数据,当指定的轴的超出边界时返回最边上的值
  53. T &  at (const int off);
  54. T& atX(const int x, const int y, const int z, const int v);
  55. T& atXY(const int x, const int y, const int z, const int v);
  56. T& atXYZ(const int x, const int y, const int z, const int v);
  57. T& atXYZV(const int x, const int y, const int z, const int v);
  58.  
  59. // 存取指定位置上的数据,当指定的轴的超出边界时返回out_val
  60. T &  at (const int off, const T out_val);
  61. T& atX(const int x, const int y, const int z, const int v, const T out_val);
  62. T& atXY(const int x, const int y, const int z, const int v, const T out_val);
  63. T& atXYZ(const int x, const int y, const int z, const int v, const T out_val);
  64. T& atXYZV(const int x, const int y, const int z, const int v, const T out_val);

值得一提的是还有两种插值版本的at方法,分别是线性插值和三次插值。其中线性插值以linear_作为前缀,三次插值以cubic_作为前缀。参数和上面的类似,只是各轴位置的类型不是int而是float,这批方法会按插值法算出小数点位置上的数据。

到这里可以发现CImg类实际上提供了类似于vector容器的编程接口,这样我们的STL算法也能用于CImg的操作了,随后就可以看到库里有时也会把CImg类直接当作数据容器来使用。比如下面CImg中就有这个方法:

  1. // 返回字符串的形式的图像中的数据,默认是逗号分隔的一长串数字。
  2. //这里返回的CImg不代表图像,而是一个一维的字符串数据,这时它只是一个容器而已,可以把它看作是vector
  3. CImg< charT >  value_string (const char separator=','const unsigned int max_size=0);
阅读(1463) | 评论(0) | 转发(0) |
0

上一篇:全排列

下一篇:修改grub.conf

给主人留下些什么吧!~~