日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

CImg库中CImg,CImgList,CImgDisplay三个类的介绍

發布時間:2023/11/27 生活经验 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CImg库中CImg,CImgList,CImgDisplay三个类的介绍 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉自:http://www.cppprog.com/2009/0426/108.html

?

本文簡單介紹了CImg庫中的三個大類:CImg,CImgList,CImgDisplay。然后給出了讓CImg在HDC上繪圖以及與HBITMAP互換的方法,為部署CImg到Windows?GUI程序中提供了基本支持。

上回介紹了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庫吧。

?

在Windows里使用CImg

現在,我們已經可以使用CImg的現成方法做一些圖像處理了。不過,有一個大問題需要解決,怎樣把CImg的強大功能和我們的GUI程序相結合呢?我們總不能只使用CImgDisplay作為最終產品的顯示界面吧?我們急需一個把CImg顯示到指定HDC上的方法!

好在CImg庫就一個頭文件,所有的源代碼都在這個頭文件里。只要看一下它是怎么把CImg對象顯示到CImgDisplay上的,我們就能依樣畫葫蘆地把它顯示到指定HDC上。

經過一番摸索,終于發現可以這樣把一個CImg對象顯示到HDC上:

  1. template<class?T>
  2. void?DrawToHDC(HDC?dc,?const?CImg<T>?&src)
  3. {
  4. ????CImgDisplay?disp;
  5. ????disp.assign(src,0,3,false,true);?//最后一個true指明m_disp不要顯示
  6. ????disp.render(m_src);?//把src的內容解析到disp的data中
  7. ????SetDIBitsToDevice(dc,0,0,disp.width,disp.height,0,0,
  8. ????????0,disp.height,disp.data,&disp.bmi,DIB_RGB_COLORS);
  9. }

CImgDisplay在顯示過程中會填充bmi和data成員變量,而這兩個變量正好是DIB數據,這段代碼正好利用了這點。
但是它的運行效率實在是不怎樣,經調試發現disp.assign方法會生成窗體、互斥量等東東,析構時又要刪除它們,我們在這里根本用不著這些東西,浪費啊~~,于是不得不寫一個新的畫圖方法了。

在說新版本的畫圖方法之前,得先說一下CImg庫的另一個好功能:插件支持。只要在#include "CImg.h"之前
?

#define cimg_plugin "插件文件"
#define cimg_plugin1 "插件文件1"
#define cimg_plugin2 "插件文件2"
...
#define cimg_plugin8 "插件文件8"

CImg庫就會把插件文件中的方法加入到CImg類中,看來起很酷,其實工作原理很簡單,頭文件中CImg類是這樣定義的:

  1. template<typename?T>
  2. struct?CImg?{
  3. ????...
  4. ????#ifdef?cimg_plugin
  5. ????????#include?cimg_plugin
  6. ????#endif
  7. ????#ifdef?cimg_plugin1
  8. ????????#include?cimg_plugin1
  9. ????#endif
  10. ????#ifdef?cimg_plugin2
  11. ????????#include?cimg_plugin2
  12. ????#endif
  13. ????#ifdef?cimg_plugin3
  14. ????????#include?cimg_plugin3
  15. ????#endif
  16. ????#ifdef?cimg_plugin4
  17. ????????#include?cimg_plugin4
  18. ????#endif
  19. ????#ifdef?cimg_plugin5
  20. ????????#include?cimg_plugin5
  21. ????#endif
  22. ????#ifdef?cimg_plugin6
  23. ????????#include?cimg_plugin6
  24. ????#endif
  25. ????#ifdef?cimg_plugin7
  26. ????????#include?cimg_plugin7
  27. ????#endif
  28. ????#ifdef?cimg_plugin8
  29. ????????#include?cimg_plugin8
  30. ????#endif
  31. ...
  32. }

當我們如下定義時

#define cimg_plugin "cimg4hdc.h"cimg4hdc.h"

cimg4hdc.h文件的內容就插入到了CImg類的定義中間。

我們現在就可以寫一個插件文件為CImg類加入與Windows GUI交互的方法了,下面的代碼是我寫的插件文件,文件名為“cimg4hdc.h”,新加了五個方法:

  1. HBITMAP?to_bmp(HDC?dc?=?0)?const??????//??從CImg產生一個HBITMAP,使用完要記得DeleteObject
  2. CImg<T>&?display(HDC?dc,?RECT?&rc)?????//?把CImg顯示到HDC上,rc指定顯示位置和大小
  3. CImg(HBITMAP?bmp)???????????????//?從HBITMAP直接生成一個CImg,HBITMAP必須是16位色以上
  4. CImg<T>&?assign(HBITMAP?bmp)???????????//?同上
  5. CImg<T>&?load_bmp(HBITMAP?bmp)?????????//?同上

插件文件代碼(點擊下載,標準做法是右擊,鏈接另存為...):

  1. #ifndef?cimg_plugin_cimg4hdc
  2. #define?cimg_plugin_cimg4hdc
  3. ?
  4. HBITMAP?to_bmp(HDC?dc)?const
  5. {
  6. ????CImgDisplay?disp;
  7. ????disp.width?=?width;
  8. ????disp.height?=?height;
  9. ????disp.normalization?=?3;
  10. ????disp.is_closed?=?true;
  11. ?
  12. ????BITMAPINFO?bmi;
  13. ????BITMAPINFOHEADER?&bh?=?bmi.bmiHeader;
  14. ????bh.biSize?=?sizeof(BITMAPINFOHEADER);
  15. ????bh.biWidth?=?disp.width;
  16. ????bh.biHeight?=?-(int)disp.height;
  17. ????bh.biPlanes?=?1;
  18. ????bh.biBitCount?=?32;
  19. ????bh.biCompression?=?BI_RGB;
  20. ????bh.biSizeImage?=?0;
  21. ????bh.biXPelsPerMeter?=?1;
  22. ????bh.biYPelsPerMeter?=?1;
  23. ????bh.biClrUsed?=?0;
  24. ????bh.biClrImportant?=?0;
  25. ????void?*pvBits;
  26. ?
  27. ????HBITMAP?bmp?=?CreateDIBSection(dc,
  28. ??????&bmi,
  29. ??????DIB_RGB_COLORS,
  30. ??????&pvBits,
  31. ??????NULL,0
  32. ????);???
  33. ????if(bmp?==?NULL)?return?bmp;
  34. ?
  35. ????disp.bmi?=?bmi;???
  36. ????disp.data?=?(unsigned?int*)pvBits;
  37. ????disp.render(*this);
  38. ????disp.width?=?disp.height?=?0;
  39. ????disp.data?=?NULL;
  40. ????return?bmp;
  41. }
  42. ?
  43. CImg<T>&?display(HDC?dc,?RECT?&rc)
  44. {
  45. ????CImgDisplay?disp;
  46. ?
  47. ????disp.width?=?rc.right?-?rc.left;
  48. ????disp.height?=?rc.bottom?-?rc.top;
  49. ????disp.normalization?=?3;
  50. ????disp.is_closed?=?true;
  51. ???
  52. ????BITMAPINFOHEADER?&bh?=?disp.bmi.bmiHeader;
  53. ????bh.biSize?=?sizeof(BITMAPINFOHEADER);
  54. ????bh.biWidth?=?disp.width;
  55. ????bh.biHeight?=?-(int)disp.height;
  56. ????bh.biPlanes?=?1;
  57. ????bh.biBitCount?=?32;
  58. ????bh.biCompression?=?BI_RGB;
  59. ????bh.biSizeImage?=?0;
  60. ????bh.biXPelsPerMeter?=?1;
  61. ????bh.biYPelsPerMeter?=?1;
  62. ????bh.biClrUsed?=?0;
  63. ????bh.biClrImportant?=?0;
  64. ????disp.data?=?new?unsigned?int[disp.width*disp.height];
  65. ?
  66. ????disp.render(*this);
  67. ????::SetDIBitsToDevice(dc,rc.left,rc.top,
  68. ????????disp.width,disp.height,0,0,
  69. ????????0,disp.height,disp.data,&disp.bmi,DIB_RGB_COLORS);
  70. ?
  71. ????disp.width?=?disp.height?=?0;
  72. ????delete?[]disp.data;
  73. ?
  74. ????return?*this;
  75. }
  76. ?
  77. CImg(HBITMAP?bmp)
  78. ????:width(0),height(0),depth(0),dim(0),is_shared(false),data(0)
  79. {
  80. ????load_bmp(bmp);
  81. }
  82. ?
  83. CImg<T>&?assign(HBITMAP?bmp)
  84. {
  85. ????return?load_bmp(bmp);
  86. }
  87. ?
  88. CImg<T>&?load_bmp(HBITMAP?bmp)
  89. {
  90. ????BITMAP?bmpobj;
  91. ????if(!::GetObject(bmp,sizeof(bmpobj),&bmpobj)?||?bmpobj.bmBitsPixel<16)?return?*this;
  92. ?
  93. ????LONG?cbBuffer?=?bmpobj.bmWidthBytes*(bmpobj.bmHeight);
  94. ????BYTE?*lvbit?=?new?BYTE[cbBuffer];
  95. ?
  96. ????if(!::GetBitmapBits(bmp,?cbBuffer,?lvbit))
  97. ????{
  98. ????????delete?[]lvbit;
  99. ????????return??*this;
  100. ????}
  101. ?
  102. ????unsigned?char*?ptrs?=?lvbit;
  103. ????int?align?= (4 - bmpobj.bmWidthBytes%4)%4;
  104. ?
  105. ????//?Read?pixel?data
  106. ????assign(bmpobj.bmWidth,bmpobj.bmHeight,1,3);
  107. ????switch?(bmpobj.bmBitsPixel)?{
  108. ????case?16?:?{?//?16?bits?colors
  109. ????for?(int?y=height-1;?y>=0;?--y)?{?cimg_forX(*this,x)?{
  110. ??????const?unsigned?char?c1?=?*(ptrs++),?c2?=?*(ptrs++);
  111. ??????const?unsigned?short?col?=?(unsigned?short)(c1|(c2<<8));
  112. ??????(*this)(x,y,2)?=?(T)(col&0x1F);
  113. ??????(*this)(x,y,1)?=?(T)((col>>5)&0x1F);
  114. ??????(*this)(x,y,0)?=?(T)((col>>10)&0x1F);
  115. ????}?ptrs+=align;?}
  116. ????}?break;
  117. ????case?24?:?{?//?24?bits?colors
  118. ????for?(int?y=height-1;?y>=0;?--y)?{?cimg_forX(*this,x)?{
  119. ??????(*this)(x,y,2)?=?(T)*(ptrs++);
  120. ??????(*this)(x,y,1)?=?(T)*(ptrs++);
  121. ??????(*this)(x,y,0)?=?(T)*(ptrs++);
  122. ????}?ptrs+=align;?}
  123. ????}?break;
  124. ????case?32?:?{?//?32?bits?colors
  125. ????for?(int?y=height-1;?y>=0;?--y)?{?cimg_forX(*this,x)?{
  126. ??????(*this)(x,y,2)?=?(T)*(ptrs++);
  127. ??????(*this)(x,y,1)?=?(T)*(ptrs++);
  128. ??????(*this)(x,y,0)?=?(T)*(ptrs++);
  129. ??????++ptrs;
  130. ????}?ptrs+=align;?}
  131. ????}?break;
  132. ????}
  133. ????mirror('y');
  134. ???
  135. ????delete?[]lvbit;
  136. ????return?*this;
  137. }
  138. #endif

測試代碼(在WTL里測試):

  1. #define?cimg_plugin?"cimg4hdc.h"
  2. #include?"CImg.h"
  3. using?namespace?cimg_library;
  4. ????CImg<unsigned?char>?m_show;
  5. ???
  6. ????//?生成部分
  7. ????{
  8. ????//?生成一個100*100的HBITMAP
  9. ????HDC?dc?=?::CreateCompatibleDC(0);
  10. ????HBITMAP?bmp?=?::CreateCompatibleBitmap(::GetDC(0),?100,100);
  11. ????::SelectObject(dc,?bmp);
  12. ????::TextOut(dc,?10,?10,?_T("Hello?World"),?11);
  13. ????//?從HBITMAP生成一個CImg
  14. ????CImg<unsigned?char>?src(bmp);
  15. ????//?模糊計算,結果與原圖并排送給m_show
  16. ????m_show?=?(src?<<?src.get_blur(2)).get_append('x');
  17. ????//?刪除HBITMAP和內存DC
  18. ????::DeleteObject(bmp);
  19. ????::DeleteDC(dc);
  20. ????}
  21. ???
  22. ????//?顯示部分
  23. ????LRESULT?OnPaint(UINT?/*uMsg*/,?WPARAM?/*wParam*/,?LPARAM?/*lParam*/,?BOOL&?/*bHandled*/)
  24. ????{
  25. ????????CPaintDC?dc(m_hWnd);
  26. ????????RECT?rc={
  27. ????????????10,10,10+m_show.width,10+m_show.height
  28. ????????};
  29. ????????//?在HDC上顯示m_show
  30. ????????m_show.display(dc,?rc);
  31. ????????return?0;
  32. ????}


效果如下:

總結

以上是生活随笔為你收集整理的CImg库中CImg,CImgList,CImgDisplay三个类的介绍的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

歡迎分享!

轉載請說明來源于"生活随笔",并保留原作者的名字。

本文地址:CImg库中CImg,CImgList,CImgDispla