精华内容
下载资源
问答
  • CImg

    千次阅读 2015-10-28 20:44:17
    C++中图像处理的类之二 CImg 转自:http://hi.baidu.com/fengjingge815/item/c44caaf0a7a2601ec6dc45f3 http://www.cnblogs.com/milier-otw/archive/2013/03/13/2958101.html 数字图像处理--CImg...

    C++中图像处理的类之二 CImg

    转自:http://hi.baidu.com/fengjingge815/item/c44caaf0a7a2601ec6dc45f3

    http://www.cnblogs.com/milier-otw/archive/2013/03/13/2958101.html

    数字图像处理--CImg类

    class CImg  
    {
    public:
     // 构造函数
     CImg();
     // Copy构造函数
     CImg(CImg& gray);
     // 重载“=”操作符来创建新的对象
     void operator = (CImg& gray); //图像赋值

     BOOL operator == (CImg& gray); //判断2幅图像是否相同
     CImg operator & (CImg& gray); //图像按位与
     CImg operator | (CImg& gray); //图像按位或
     CImg operator + (CImg gray); //图像相加
     CImg operator - (CImg& gray); //图像减法
     CImg operator ! (); //图像反色
     

     // 析构函数
     virtual ~CImg();

    public: 
     
     // 判断位图是否有效
     BOOL IsValidate() { return m_pBMIH != NULL; }

     // 将所有像素的值初始化为color
     void InitPixels(BYTE color);

     // 从文件加载位图
     BOOL AttachFromFile(LPCTSTR lpcPathName);
     BOOL AttachFromFile(CFile &file);
     // 将位图保存到文件
     BOOL SaveToFile(LPCTSTR lpcPathName);
     BOOL SaveToFile(CFile &file);

     // 在DC上绘制位图
     BOOL Draw(CDC* pDC);
     BOOL Draw(CDC* pDC, CRect rt);

     // 设置像素的值
     void SetPixel(int x, int y, COLORREF color);
     // 获取像素的值
     COLORREF GetPixel(int x, int y);
     // 获取灰度值
     BYTE GetGray(int x, int y);


     // 获取一行的字节数
     int GetWidthByte();
     // 获取一行的像素数
     int GetWidthPixel();
     // 获取高度
     int GetHeight();

     //改变位图的尺寸
     void ImResize(int nHeight, int nWidth);
    public:

     // 绘画函数 
     // 绘制直线
     void Line(POINT ptStart, POINT ptEnd);
     void Line(POINT ptStart, int nLen, int nWide, BOOL bHor);
     // 绘制矩形
     void Rectangle(int x, int y, int r = 5);
     void Rectangle(POINT ptLT, int r = 5);
     void Rectangle(POINT ptLT, POINT ptRB);
     void Circle(int x, int y, int r = 5){};

    public:
     // 判断是否是二值图像
     BOOL IsBinaryImg();
     // 判断是否是索引图像
     BOOL IsIndexedImg();
     // 256色索引图像转灰度图像
     bool Index2Gray();

     LPVOID GetColorTable(){return m_lpvColorTable;}
     int GetColorTableEntriesNum(){return m_nColorTableEntries;}
    private:
     void CleanUp(); 

    public:
     // 文件数据
     BITMAPINFOHEADER *m_pBMIH;
     LPBYTE  *m_lpData;
    protected:
     int m_nColorTableEntries;
     LPVOID m_lpvColorTable;
    };

     

     

    下文转自:http://blog.163.com/xglla_1129/blog/static/81073510201061145439483/

    CImg是一个跨平台的C++的图像处理库,提供了加载、处理、显示、保存等一系列功能,其中的图像处理功能尤其强大。
     

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

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

    CImg的Hello World

    这段代码是从《CImg参考手册》里抄的,可以大致了解一下CImg的框架。
    以VC为例:新建控制台程序,输入下面的代码。项目属性的链接器附加依赖项加入kernel32.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.     CImg<unsigned char> 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<charT>不代表图像,而是一个一维的字符串数据,这时它只是一个容器而已,可以把它看作是vector<charT>。
    3. CImg< charT >  value_string (const char separator=',', const unsigned int max_size=0);

     

    上回介绍了CImg模板类的一些函数,象我这种不在图像处理行业混的人来说很多术语实在是太专业了-_-,不理不理,看不懂就直接写测试代码看它们的作用是什么不就知道啦~~嘿嘿^_^。

    上测试代码先:

    1. #include "CImg.h"
    2. using namespace cimg_library;
    3.  
    4. int main() 
    5. {
    6.  
    7.     CImg<unsigned char> src("test.bmp");
    8.     // 设置原图大小,貌似haar计算要求图像宽高是4的倍数
    9.     src.resize( src.width-src.width%4, src.height-src.height%4);
    10.     CImgList<unsigned char> visu;
    11.     visu
    12.         <<src.get_crop(0,0,src.width/2,src.height/2)
    13.         <<src.get_quantize(5)
    14.         <<src.get_rotate(45,1)
    15.         <<src.get_permute_axes("yxzv")
    16.         <<src.get_erode(5)
    17.         <<src.get_haar()
    18.         <<src.get_dilate(3)
    19.         <<src.get_blur(3)
    20.         <<src.get_noise(3)
    21.         <<src.get_deriche(3)
    22.         <<src.get_blur_anisotropic(8)
    23.         <<src.get_blur_bilateral(1,2)
    24.         <<src.get_blur_patch(4,3)
    25.         <<src.get_sharpen(3)
    26.         <<src.get_blur_median(3)
    27.         ; //如果愿意可以测试更多CImg的图像处理方法
    28.    
    29.     // 用来显示效果
    30.     CImgDisplay disp(src.width*2, src.height);
    31.     int i=0;
    32.     unsigned char textcolor[] = { 255,255,255 };
    33.     while(!disp.is_closed && !disp.is_keyQ && !disp.is_keyESC)
    34.     {
    35.         i = i % visu.size;
    36.         char buf[20];
    37.         ::sprintf(buf,"img:%d",i);
    38.         //显示效果,(CImg << CImg)会生成一个新的CImgList
    39.         //左边是原图,右边是处理图,外加写了个序号在上面以便区别
    40.         disp.display( src << (+visu[i]).draw_text(0,0,buf,textcolor) ).wait();
    41.         //按方向键下则显示下一个
    42.         if(disp.is_keyARROWDOWN) i++;
    43.         //方向键上则显示上一个
    44.         if(disp.is_keyARROWUP)
    45.         {
    46.             i--;
    47.             if(i<0) i=visu.size-1;
    48.         }
    49.     }
    50.     return 0;
    51. }

    这个例子用到了CImgCImgListCImgDisplay三个类。

    CImg类前面已有介绍。

    CImgList是CImg的容器,用来保存一组CImg,主要方法有:

    1. CImgList<T>& remove(const unsigned int pos) //删除指定位置
    2. CImgList<T>& pop_back()            //删除最后一个
    3. CImgList<T>& pop_front()        //删除前端
    4. CImgList<T>& push_back(const CImg<t>& img)//从后面添加
    5. CImgList<T>& push_front(const CImg<t>& img)//从前面添加
    6. CImgList<T>& insert(const CImg<t>& img, const unsigned int pos)    //插入到指定位置之前
    7. CImgList<T>& clear()    //清空
    8. CImg<T>& operator[](const unsigned int pos) //取指定位置的图像

    上面这些是它作为容器的基本功能,同时它也重载了一些操作符以便于使用,比如本例中的"<<"操作其实就是push_back方法。另外,它还有大量的运算功能用于给容器中的图像批量运算。最后,还有一些好玩的方法不可错过:从视频中载入或把图像保存到视频中:

    1. CImgList<T>& load_ffmpeg(const char *const filename,
    2.     const unsigned int first_frame=0,
    3.     const unsigned int last_frame=~0U,
    4.     const unsigned int step_frame=1,
    5.     const bool pixel_format=true,
    6.     const bool resume=false)
    7.  
    8. const CImgList<T>& save_ffmpeg(
    9.     const char *const filename,
    10.     const unsigned int first_frame=0,
    11.     const unsigned int last_frame=~0U,
    12.     const unsigned int fps=25)

    这两个方法要求链接ffmpeg库,如果没有这个库文件,还可以使用load_ffmpeg_externalsave_ffmpeg_external方法调用已外部安装的ffmpeg程序编解码。

    CImgDisplay类是一个窗口类,它主要用来显示CImg和CImgList。一般使用它的流程是:

    1. 新建CImgDisplay对象
    2. 设置它的大小,除直接输入宽高外也能用直接用CImg、CImgList或另一个CImgDisplay对象作为调整大小的依据。这时,CImgDisplay对象内部已经建立了一个窗口了。
    3. 使用display方法显示图像
    4. 使用wait方法等待事件发生(键盘、鼠标、超时等)
    5. 检查is_keyXXXX、is_closed、button、wheel等成员变量确定是什么事件,再决定我们该做什么操作。
    6. 如果需要,循环回第三步
    7. 析构时窗口收回。

    在本例中,如果窗体关闭或按了Q键或按了ESC键则退出循环,程序结束。或者显示由原图和处理后的图组成的CImgList图像,如果按了上下方向键,则改变当前显示的处理图。

    这是本例运行时的截图:
    \
    水墨画风格的《清明上河图》

    CImg的图像处理方法绝不止上面例子中写的那么一点点,

     

    CImg库不仅可以处理二维图像,也能处理三维图像,这篇文章介绍了CImg处理三维图像的方法。
     

    之前我们一直玩的是CImg的二维图像处理,从CImg<>类的成员方法上看,显然它还有更多能力。比如那些带3d后缀的方法显然是为三维图像准备的,还有dijkstra方法,貌似是图论方面的内容,CImg库管得可真够宽的-_- 图论方面的先不管它,这方面还是Boost::Graph比较在行,我比较感兴趣的还是它的三维能力,毕竟这是个Head Only的跨平台库,并且没有调用OpenGL,有三维处理能力还是蛮让人兴奋D~~,呵呵:)

    现在,我们从一根三维的直线开始:

    下面的代码使用VC2005 Express编译,为了直观,使用了中文变量名.

    1. #include "CImg.h"
    2. using namespace cimg_library;
    3.  
    4. //三维直线
    5. int main()
    6. {
    7.     CImg<> 顶点(2,3,1,1,
    8.         0,50
    9.         0,50
    10.         0,50);
    11.     CImgList<unsigned int> 图元( CImg<unsigned int>::vector(0,1) );
    12.     CImg<> 不透明度 = CImg<>::vector(1.0f);
    13.     CImgList<unsigned char> 颜色表( CImg<unsigned char>::vector(255,0,255) );
    14.  
    15.     //300*300,深度是1,3个色彩通道,以0填充
    16.     CImg<> visu(300,300,1,3,0);
    17.     visu.display_object3d("三维直线",顶点,图元,颜色表,不透明度);
    18.    
    19.     return 0;
    20. }

    编译运行,显示一条直线,在窗体内按住鼠标拖曳,可以改变视角.不过就一根直线看上去不是很爽,没立体感,下面我们用直接组成一个立方体:

    一个立方体有8个顶点, 12条边

    1. //多根三维直线
    2. int main()
    3. {
    4.     // 8个顶点
    5.     CImg<> 顶点(8,3,1,1,
    6.         0,  0,  50, 50, 50, 0,  0,  50,
    7.         0,  50, 50, 0,  0,  0,  50, 50,
    8.         0,  0,  0,  0,  50, 50, 50, 50);
    9.     // 12条边
    10.     CImgList<unsigned int> 图元 =
    11.         CImg<unsigned int>::vector(0,1) <<
    12.         CImg<unsigned int>::vector(1,2) <<
    13.         CImg<unsigned int>::vector(2,3) <<
    14.         CImg<unsigned int>::vector(3,4) <<
    15.         CImg<unsigned int>::vector(4,5) <<
    16.         CImg<unsigned int>::vector(5,6) <<
    17.         CImg<unsigned int>::vector(6,7) <<
    18.         CImg<unsigned int>::vector(0,5) <<
    19.         CImg<unsigned int>::vector(1,6) <<
    20.         CImg<unsigned int>::vector(2,7) <<
    21.         CImg<unsigned int>::vector(0,3) <<
    22.         CImg<unsigned int>::vector(4,7)
    23.         ;
    24.  
    25.     CImg<> 不透明度(1,12,1,1, 1.0f);
    26.     CImgList<unsigned char> 颜色表( 12, CImg<unsigned char>::vector(255,0,255) );
    27.  
    28.     //300*300,深度是1,3个色彩通道,以0填充
    29.     CImg<> visu(300,300,1,3,0);
    30.     visu.display_object3d("三维直线",顶点,图元,颜色表,不透明度);
    31.    
    32.     return 0;
    33. }

    显示图如下:

    \

    在CImg里,一幅三维图被分解成:顶点(vertices)和图元(primitives)两个部分。

    顶点是一个CImg<>对象,它存放三维图中所有的顶点数据。这个CImg<>对象此时只是一个数据容器,我们姑且把它看作图像的话,那么它相当于一个“宽(width)=顶点数,高(height)=3,深(depth)=1,色彩通道(dim)=1”的图像,在“这个图像指定x位置上的3个y轴数据(因为高度总是为3)”指明了顶点所在的x,y,z方位。

    比如上例中的顶点规格为8*3*1*1,表明顶点数为8,后面的数据从纵向正好是8组三维方位数据。这里这样写只是为了方便,如果要运行期动态加入顶点,可以使用append方法,上面的顶点初始化代码可以改写成:

    1. CImg<> 顶点;
    2. 顶点.append(CImg<>::vector(0,0,0),'x')
    3.     .append(CImg<>::vector(0,50,0),'x')
    4.     .append(CImg<>::vector(50,50,0),'x')
    5.     .append(CImg<>::vector(50,0,0),'x')
    6.     .append(CImg<>::vector(50,0,50),'x')
    7.     .append(CImg<>::vector(0,0,50),'x')
    8.     .append(CImg<>::vector(0,50,50),'x')
    9.     .append(CImg<>::vector(50,50,50),'x');

    这里的静态方法vector返回一个由它的所有参数组成的CImg<>对象,最多可接受16个输入参数。vector生成的CImg<>对象中数据是按列排的,也就是说生成的CImg<>对象宽度总是1,高度正好是参数个数,(0,y)点上的数据对应第y个参数。

    append方法把当前图像和输入的图像按指定轴的方向合成一个新的图像,这是就是以'x'轴方向把这些1X3的“图像”合并到一起。顺便说一下,CImg的大部分方法都是返回自身的引用,所以可以连续用.操作。

    图元是组成三维图的最小图形,一般的三维处理都以三角形作为图元,所以显卡测试里有三角形生成速度一项,扯远了~~:-P

    在CImg中图元是一个CImgList<unsigned int>对象,这个对象中所包含的每个CImg<unsigned int>是一组顶点索引,同样是1Xn的。n个顶点组合成一个面,这个面就是一个图元,所有图元组成一个三维物体。

    另外,显示时还需要给出每个图元的不透明度和颜色表(或纹理),不透明度是CImg<float>对象,存放了与图元数目同样个数的浮点数据(同样是纵向存放的),1.0表示不透明,0.0表示全透明,0~1之间的数据指定透明度。

    颜色表是一个CImgList<>数据,其中至少要有图元数目个CImg<>对象,每个CImg<>以RGB的顺序纵向存放了对应图元的颜色数据(或者纹理,这个后面再说)。

    在本例中我们的所有图元都是直线,我们也可以用四个点把图元描述成一个面,这样,一个三维立方体诞生了:

    1. #include "CImg.h"
    2. using namespace cimg_library;
    3.  
    4. //三维立方体
    5. int main()
    6. {
    7.     //8个顶点
    8.     CImg<> 顶点;
    9.     顶点.append(CImg<>::vector(0,0,0),'x')
    10.         .append(CImg<>::vector(0,50,0),'x')
    11.         .append(CImg<>::vector(50,50,0),'x')
    12.         .append(CImg<>::vector(50,0,0),'x')
    13.         .append(CImg<>::vector(50,0,50),'x')
    14.         .append(CImg<>::vector(0,0,50),'x')
    15.         .append(CImg<>::vector(0,50,50),'x')
    16.         .append(CImg<>::vector(50,50,50),'x');
    17.  
    18.  
    19.     CImgList<unsigned int> 图元 =
    20.         CImg<unsigned int>::vector(0,1,2,3) <<
    21.         CImg<unsigned int>::vector(4,5,6,7) <<
    22.         CImg<unsigned int>::vector(0,1,6,5) <<
    23.         CImg<unsigned int>::vector(2,7,4,3)
    24.         ;
    25.  
    26.     CImg<> 不透明度(1,12,1,1, 1.0f);
    27.     CImgList<unsigned char> 颜色表( 12, CImg<unsigned char>::vector(255,0,255) );
    28.     颜色表[0] = CImg<unsigned char>::vector(255,0,0);
    29.     颜色表[1] = CImg<unsigned char>::vector(0,255,0);
    30.     颜色表[2] = CImg<unsigned char>::vector(0,0,255);
    31.     //300*300,深度是1,3个色彩通道,以0填充
    32.     CImg<> visu(300,300,1,3,0);
    33.     visu.display_object3d("三维立方体",顶点,图元,颜色表,不透明度,true,4,4,true);
    34.    
    35.     return 0;
    36. }

    对了,前面都忘说display_object3d方法了:

    该方法声明如下:

    1. const CImg<T>& cimg_library::CImg< T >::display_object3d  ( CImgDisplay &disp /*或 const char *const title*/, 
    2.   const CImg< tp > &  points, 
    3.   const CImgList< tf > &  primitives, 
    4.   const CImgList< tc > &  colors, 
    5.   const to &  opacities, 
    6.   const bool  centering = true, 
    7.   const int  render_static = 4, 
    8.   const int  render_motion = 1, 
    9.   const bool  double_sided = false, 
    10.   const float  focale = 500, 
    11.   const float  specular_light = 0.2f, 
    12.   const float  specular_shine = 0.1f, 
    13.   const bool  display_axes = true, 
    14.   float *const   pose_matrix = 0  
    15.  ) 
    参数很多,前面的五个不用多说,说说后面几个我知道的:-P
        centering 指定是否把0,0,0点作为窗体中心      render_static和render_motion 指定静态渲染级别和动态渲染级别:          0=点, 1=线, 2=面(没有亮光), 3=面(平面), 4=面(边缘柔和)      double_sided 指定是否双面渲染      focale 焦距

    咳,由于空间想象力太差,组成立方体的六个面偶只放了四个,结果生成的图形如下:


    展开全文
  • CImg 1.6.0

    2014-09-23 23:15:39
    CImg是一个跨平台的C++的图像处理库,提供了加载、处理、显示、保存等一系列功能,其中的图像处理功能尤其强大。
  • CIMG_LABS-源码

    2021-03-30 01:57:20
    CIMG_LABS
  • CImg Reference

    2010-12-19 02:55:39
    CImg Reference English Version
  • CImg开源库

    2016-05-11 10:49:37
    CImg开源库,强大的图像处理功能
  • CImg-1.7.1.rar

    2021-02-23 16:41:07
    CImg开源库,强大的图像处理功能
  • CImg图像处理库

    2018-04-27 08:42:54
    CImg是一个跨平台的开源C++的图像处理库,提供了加载、处理、显示、保存等一系列功能,其中的图像处理功能尤其强大。这个是CImg-2.2.2版本。
  • CImg-2.7.2.zip

    2019-10-10 16:39:29
    CImg-2.727版本
  • cimg on windows7

    2020-11-23 03:51:11
    m trying to compile a program using CImg on Windows7. The errors I get sort of seem like I'm missing some library, but I really have no clue. Any help would be appreciated. <p>The first few lines ...
  • CImg 参考手册
  • 安川电抗器CIMG5A CIMG7A进线出线电抗器(输入输出电抗器)选型样本pdf,安川电抗器CIMG5A CIMG7A进线出线电抗器(输入输出电抗器)选型样本
  • CImg库介绍

    2018-11-10 08:22:36
    CImg库介绍

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

    也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

                   

    转自:http://www.cppprog.com/2009/0424/106.html

     

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

    主页地址:http://cimg.sourceforge.net/
    下载地址:http://cimg.sourceforge.net/download.shtml
    下载时注意应该下载源码包,里面附带的大量的例程。而实际上CImg库只是一个头文件CImg.h,这个头文件里包含了CImg库所有的代码。
    另外不要错过下载列表中的一个部分完成的《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.     CImg<unsigned char> 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.widthy, dy, dimy, height 表示img.heightz, dz, dimz, depth 表示img.depthv, 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<charT>不代表图像,而是一个一维的字符串数据,这时它只是一个容器而已,可以把它看作是vector<charT>。
    3. CImg< charT >  value_string (const char separator=','const unsigned int max_size=0);

    CImg类的画图方法

    draw_pointdraw_linedraw_polygondraw_splinedraw_arrowdraw_imagedraw_rectangledraw_triangledraw_ellipsedraw_circledraw_textdraw_quiverdraw_graphdraw_axisdraw_griddraw_filldraw_plasmadraw_mandelbrotdraw_gaussiandraw_object3d


    CImg的画图方法真的是非常多,每种方法都有2D和3D的重载,具体可以参考手册

    CImg类的图像处理方法

    CImg类的图像处理方法分两种版本:一种是直接在自己的数据上计算和保存;另一种是返回一个计算后的CImg对象,自己的数据不会改变,这个版本以get_作为前缀并且总是const方法。

    1. // 填充图像,其中的valx参数用于顺序填充图像,最多可以有15个。
    2. CImg< T > &  fill (const T val0, const T val1, ...);
    3. // 以values指定的字符串来填充图像,values格式参考上文的构造函数参数
    4. CImg< T > &  fill (const char *const values, const bool repeat_pattern)
    5. // 以values图像里的值填充。
    6. CImg< T > &  fill (const CImg< t > &values, const bool repeat_pattern=true)

    相应的,有get_fill方法,返回填充后的新CImg对象。后面的方法同相也有get_方法,不再累述。

    1. // 只填充指定的yzv位置上的x轴的数据
    2. CImg< T > &  fillX (
    3.     const unsigned int y,
    4.     const unsigned int z,
    5.     const unsigned int v,
    6.     const int a0,...);

    当然,也有fillY,fillZ,fillV。

    1. // 线性规格化图像,即把图像中的所有元素数值线性放大或减小到a和b之间。
    2. CImg< T > &  normalize (const T a, const T b) 

     

    1. // 把图像中的所有元素数值大小限制在a和b之间,若有超出,则直接限制在边界上。
    2. CImg< T > &  cut (const T a, const T b);

     

    1. // 把图像像素数据数字化到n级上,即图像元素数值从小到大被分成n个级别。(类似AD转换)
    2. CImg< T > &  quantize (const unsigned int n, const bool keep_range=true)

     

    1. // 阈值化图像,小于value的为0,大于value的为1。
    2. // 若soft=true,则小于value元素加上value,大于value的元素减去value。
    3. // strict决定比较时使用<操作还是<=操作。
    4. CImg< T > &  threshold (const T value, const bool soft=falseconst bool strict=false

     

    1. // 旋转图像,以cx,cy指定点为中心,旋转angle度,放大zoom倍。
    2. CImg< T > &  rotate (
    3.     const float angle,
    4.     const float cx,
    5.     const float cy,
    6.     const float zoom,
    7.     const unsigned int border_conditions=3,
    8.     const unsigned int interpolation=1);

    参数border_conditions指定怎样处理边界外的值,0-边界以外以0值填充,1-重复边界点的值,2-重复图像
    参数interpolation指定采用何种插值方法,0-不插值,1-线性插值,2-三次插值

    1. // 改变大小
    2. CImg< T > &  resize (
    3.     const int pdx,
    4.     const int pdy=-100,
    5.     const int pdz=-100,
    6.     const int pdv=-100,
    7.     const int interpolation_type=1,
    8.     const int border_condition=-1,
    9.     const bool center=false)

    改变图像到指定大小,当pdx,pdy,pdz或pdv<0时,使用百分比。interpolation_type指定插值方法,分别是:

    -1 = 不插值 : 图像直接按大小剪切0 = 不插值 : 多余空间依据border_condition决定。1 = 临近点插值。2 = 移动平均数插值。3 = 线性插值。4 = 删格插值。5 = 双三次插值。


    另外,还有几个优化的resize版本:

    1. // 优化的缩小至原来的1/2
    2. CImg< T > &  resize_halfXY ()
    3. // 优化的放大至原来的2倍
    4. CImg< T > &  resize_doubleXY ()
    5. // 优化的放大至原来的3倍
    6. CImg< T > &  resize_tripleXY ()

     

    1. // 扭曲图像,由参数warp中相同位置的数据决定该位置元素的去向。
    2. CImg< T > &  warp (
    3.     const CImg< t > &warp,
    4.     const bool relative=false,
    5.     const bool interpolation=true,
    6.     const unsigned int border_conditions=0) 

    参数warp在这里只是一个容器(不要把它看成图像)的作用,其x,y,z点上的数据决定了当前图像x,y,z点上元素的新位置,这个新位置由warp的x,y,z点上的v轴数据给出。如果warp的v轴长度是1时,当前图像元素只会在x轴上移动。如果warp的v轴长度是2时,当前图像元素在x,y轴上移动...relative=ture时,表示wrap中的数据是相对位置。

    1. // 按指定轴镜像,axis可以是'x','y','z','v'
    2. CImg< T > &  mirror (const char axis);

     

    1. // 偏移图像
    2. CImg< T > &  translate (
    3.     const int deltax,
    4.     const int deltay=0,
    5.     const int deltaz=0,
    6.     const int deltav=0,
    7.     const int border_condition=0)

     

    1. // 取原图像中的一块子图
    2. CImg< T > &  crop (
    3.     const int x0, const int y0, const int z0, const int v0,
    4.     const int x1, const int y1, const int z1, const int v1,
    5.     const bool border_condition=false

    crop方法还有其它的版本,分别是省略v轴,z轴和y轴的版本。

    1. // 把3D图像转成2D视图。
    2. CImg< T > &  projections2d (
    3.     const unsigned int x0, const unsigned int y0, const unsigned int z0,
    4.     const int dx=-100, const int dy=-100, const int dz=-100);


    最后,下面的这些方法提供类似Photoshop的滤镜功能,强啊~~:

    noise  噪声deriche Canny-Deriche算法blur 模糊blur_anisotropic 各向异性模糊blur_bilateral 对称模糊blur_patch 面片模糊blur_median 中值模糊sharpen 尖锐haar 小波分析...还有好多


    看了上面的介绍,我想大家肯定对CImg的强大能力有了初步的了解(要知道上面列出的方法只是CImg方法中的冰山一角,而且更强的是CImg库还能通过指定Plugin宏的方式插入新的方法,当CImg自带的方法不能满足我们的要求时,也许已经有人提供了对应的插件了),下次我们开始学习CImg的具体使用吧^_^

    最后放上前面说的CImg的Doxygen手册,猛击这里下载。

               

    给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

    这里写图片描述
    展开全文
  • add cimg 2.9.2

    2020-12-08 20:05:08
    <div><p>Specify library name and version: <strong>cimg/2.9.2</strong></p> <ul><li>[x] I've read the ...
  • <div><p>I believe I can either install imagemagick OR graphicsmagick for cimg to handle jpg, png, etc. <p>I installed graphicsmagick, without imagemagick, cimg gives error 'sh: 1: convert: not ...
  • CIMG1.5.9版本代码

    2015-03-13 22:31:59
    CIMG1.5.9版本代码,主要用于图像处理
  • Cimg库与指导手册

    2015-03-15 22:01:35
    CImg_1.6.1_rolling150311 &CImg中文手册
  • CImg库参考手册中文版CImg库参考手册中文版CImg库参考手册中文版CImg库参考手册中文版CImg库参考手册中文版CImg库参考手册中文版CImg库参考手册中文版
  • CImg-master 图像处理
  • CImg库示例程序

    2016-04-18 17:12:04
    CImg库进行实例开发,实现功能:1、在自建的图像中显示文字;2、从磁盘中载入一幅图像并显示。为了理解方便,对各语句进行详细的注释,方便读者理解。
  • CImg 2.0.5_pre092517

    2017-09-28 18:24:44
    cimg.h 这个头文件在里面,以前对这个lib不熟悉,由于CGAL的原因才用到的。
  • CImg.h" <p>using namespace cimg_library; <p>int main() {<!-- --> <pre><code>// Declare an image CImg<unsigned char> image; // Load an image file into it image.load("lena.ppm"); // ...
  • How to speed up Cimg ?

    2020-11-23 03:26:47
    <p>I have a question related about speeding up cimg executions for image processing, so I think that this is a question more than an issue. Sorry but I don't know where to post general questions ...
  • ../native/CImg.h:175:10: fatal error: 'initializer_list' file not found but when i use cimg version 156, it seems ok</p><p>该提问来源于开源项目:dtschump/CImg</p></div>
  • Upgrade CImg to v2.3.3

    2020-12-05 02:16:13
    <div><p>https://github.com/dtschump/CImg/releases/tag/v.2.3.3</p><p>该提问来源于开源项目:stefanhaustein/TerminalImageViewer</p></div>
  • <div><p>Time to compile my CImg based code is taking around 2mins on a 10core machine with 64GB RAM. I would like to know if there is any way to improve the compilation time. <p>1) What is the bottle...
  • 运行CImg库笔记

    2019-10-01 08:58:38
    1 #include "CImg.h" 2 using namespace cimg_library; 2. (1)Mac下 出现错误“无X11/Xlib.h”,: 解决方案: 安装XQuartz 建立X11到系统库的硬连接 1 sudo ln -s /opt/X11/include/X11 /usr/local/...

     

    1. 在程序代码中加入

    1 #include "CImg.h"
    2 using namespace cimg_library;

    2.

    (1)Mac下

    出现错误“无X11/Xlib.h”,:

    解决方案:

    安装XQuartz

    建立X11到系统库的硬连接

    1 sudo ln -s /opt/X11/include/X11 /usr/local/include/X11
    2 sudo ln -s /opt/X11/include/X11 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/

    (2)ubuntu下

    出现无 X11/Xlib.h 的错误

    解决方案:打开终端,安装X11

    1 $sudo apt-get install libx11-dev

    如果出现未找到软件包:

    在“设置->软件源”中扫描更新为最快的软件源

     

    3. 编译

    样例:代码源文件 test.cpp 输出文件 test

    (1)mac 下

    g++ -o hello test.cpp -O2 -lm -lpthread -L/usr/X11R6/lib -lm -lpthread -lX11

    1 g++ -o test test.cpp -O2 -lm -lpthread -L/usr/X11R6/lib -lm -lpthread -lX11

    (2)ubuntu 下

    1 g++ -o test test.cpp -O2 -L/usr/X11R6/lib -lm -lpthread -lX11

     

    转载于:https://www.cnblogs.com/bindong/p/5832018.html

    展开全文
  • CImg库入门介绍

    2017-09-27 17:17:01
    CImg库早在2004年就已经被使用,它是一个跨平台的C++的图像处理库,提供了加载、处理、显示、保存等一系列功能,其中的图像处理功能尤其强大。如果对图像处理要求不是很严格,可以结合CImg库进行封装和开发。 下面...

    CImg库早在2004年就已经被使用,它是一个跨平台的C++的图像处理库,提供了加载、处理、显示、保存等一系列功能,其中的图像处理功能尤其强大。如果对图像处理要求不是很严格,可以结合CImg库进行封装和开发。
    下面是官方提供的CImg的Demo:
    主页地址:http://cimg.sourceforge.net/
    下载地址:http://cimg.sourceforge.net/download.shtml
    github下载地址:https://github.com/hutianyou123/CImg
    下载时注意应该下载源码包,里面附带的大量的例程。而实际上CImg库只是一个头文件CImg.h,这个头文件里包含了CImg库所有的代码。
    下面演示一个有趣入门例子:

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

    下面来几张截图:
    这里写图片描述

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 779
精华内容 311
关键字:

CImg