mydiblib.h
上传用户:yianco
上传日期:2022-07-15
资源大小:2047k
文件大小:19k
源码类别:

图形图象

开发平台:

Visual C++

  1. #include "dibapi.h"
  2. #include <iostream>
  3. #include <deque>
  4. #include <math.h>
  5. using namespace std;
  6. typedef deque<HDIB>  HDIBLink;
  7. HDIB m_hDIB;
  8. CString strPathName;
  9. CString strPathNameSave;
  10. //声明一些必要的全局变量
  11. int m_lianXuShu;
  12. bool fileloaded;
  13. bool gyhfinished;
  14. /********************************function declaration*************************************/
  15. //清楚屏幕
  16. void ClearAll(CDC* pDC);
  17. //在屏幕上显示位图
  18. void DisplayDIB(CDC* pDC,HDIB hDIB);
  19. //将灰度图二值化
  20. void ConvertGrayToWhiteBlack(HDIB hDIB);
  21. //判断是否是离散噪声点
  22. bool DeleteScaterJudge(LPSTR lpDIBBits,WORD lLineBytes, LPBYTE lplab, int lWidth, int lHeight, int x, int y, CPoint lab[], int lianXuShu);
  23. //细化
  24. void Thinning(HDIB hDIB);
  25. void DisplayDIB(CDC* pDC,HDIB hDIB)
  26. {
  27. BYTE* lpDIB=(BYTE*)::GlobalLock((HGLOBAL)hDIB);
  28. // 获取DIB宽度和高度
  29. int cxDIB =  ::DIBWidth((char*) lpDIB);
  30. int cyDIB =  ::DIBHeight((char*)lpDIB);
  31. CRect rcDIB,rcDest;
  32. rcDIB.top = rcDIB.left = 0;
  33. rcDIB.right = cxDIB;
  34. rcDIB.bottom = cyDIB;
  35. //设置目标客户区输出大小尺寸
  36. rcDest = rcDIB;
  37. //CDC* pDC=GetDC();
  38. ClearAll(pDC);
  39. //在客户区显示图像
  40. //for(int ii=0;ii<10;ii++)
  41. ::PaintDIB(pDC->m_hDC,rcDest,hDIB,rcDIB,NULL);
  42. ::GlobalUnlock((HGLOBAL)hDIB);
  43. }
  44. void ClearAll(CDC *pDC)
  45. {
  46. CRect rect;
  47. //GetClientRect(&rect);
  48. rect.left =0;rect.top =0;rect.right =2000;rect.bottom =1000;
  49. CPen pen;
  50. pen.CreatePen (PS_SOLID,1,RGB(255,255,255));
  51. pDC->SelectObject (&pen);
  52. pDC->Rectangle (&rect);
  53. ::DeleteObject (pen);
  54. }
  55. /****************************************************************
  56. * 函数名称:
  57. *      Convert256toGray()
  58. *
  59. * 参数:
  60. *     HDIB hDIB     -图像的句柄
  61. *
  62. *  返回值:
  63. *        无
  64. *
  65. *  功能:
  66. *     将256色位图转化为灰度图
  67. *
  68. ***************************************************************/
  69. void Convert256toGray(HDIB hDIB)
  70. {
  71. LPSTR lpDIB;
  72. // 由DIB句柄得到DIB指针并锁定DIB
  73. lpDIB = (LPSTR) ::GlobalLock((HGLOBAL)hDIB);
  74. // 指向DIB象素数据区的指针
  75. LPSTR   lpDIBBits;
  76. // 指向DIB象素的指针
  77. BYTE * lpSrc;
  78. // 图像宽度
  79. LONG lWidth;
  80. // 图像高度
  81. LONG   lHeight;
  82. // 图像每行的字节数
  83. LONG lLineBytes;
  84. // 指向BITMAPINFO结构的指针(Win3.0)
  85. LPBITMAPINFO lpbmi;
  86. // 指向BITMAPCOREINFO结构的指针
  87. LPBITMAPCOREINFO lpbmc;
  88. // 获取指向BITMAPINFO结构的指针(Win3.0)
  89. lpbmi = (LPBITMAPINFO)lpDIB;
  90. // 获取指向BITMAPCOREINFO结构的指针
  91. lpbmc = (LPBITMAPCOREINFO)lpDIB;
  92. // 灰度映射表
  93. BYTE bMap[256];
  94. // 计算灰度映射表(保存各个颜色的灰度值),并更新DIB调色板
  95. int i,j;
  96. for (i = 0; i < 256; i ++)
  97. {
  98. // 计算该颜色对应的灰度值
  99. bMap[i] = (BYTE)(0.299 * lpbmi->bmiColors[i].rgbRed +
  100.      0.587 * lpbmi->bmiColors[i].rgbGreen +
  101.          0.114 * lpbmi->bmiColors[i].rgbBlue + 0.5);
  102. // 更新DIB调色板红色分量
  103. lpbmi->bmiColors[i].rgbRed = i;
  104. // 更新DIB调色板绿色分量
  105. lpbmi->bmiColors[i].rgbGreen = i;
  106. // 更新DIB调色板蓝色分量
  107. lpbmi->bmiColors[i].rgbBlue = i;
  108. // 更新DIB调色板保留位
  109. lpbmi->bmiColors[i].rgbReserved = 0;
  110. }
  111. // 找到DIB图像象素起始位置
  112. lpDIBBits = ::FindDIBBits(lpDIB);
  113. // 获取图像宽度
  114. lWidth = ::DIBWidth(lpDIB);
  115. // 获取图像高度
  116. lHeight = ::DIBHeight(lpDIB);
  117. // 计算图像每行的字节数
  118. lLineBytes = WIDTHBYTES(lWidth * 8);
  119. // 更换每个象素的颜色索引(即按照灰度映射表换成灰度值)
  120. //逐行扫描
  121. for(i = 0; i < lHeight; i++)
  122. {
  123.   //逐列扫描
  124. for(j = 0; j < lWidth; j++)
  125. {
  126. // 指向DIB第i行,第j个象素的指针
  127. lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
  128. // 变换
  129. *lpSrc = bMap[*lpSrc];
  130. }
  131. }
  132. //解除锁定
  133. ::GlobalUnlock ((HGLOBAL)hDIB);
  134. }
  135. /******************************************************************
  136. *
  137. * 函数名称ConvertGrayToWhiteBlack()
  138. *
  139. * 参数 :HDIB hDIB     -原图的句柄
  140. *
  141. * 返回值:无
  142. *
  143. * 功能: ConvertGrayToWhiteBlack函数采用硬阈值的方法,实现将图像二值化的功能。
  144. * 说明:
  145. 要求待处理的图片为256色
  146. ************************************************************************/
  147. void ConvertGrayToWhiteBlack(HDIB hDIB)
  148. {
  149. // 指向DIB的指针
  150. LPSTR lpDIB;
  151. // 由DIB句柄得到DIB指针并锁定DIB
  152. lpDIB = (LPSTR) ::GlobalLock((HGLOBAL)hDIB);
  153. // 指向DIB象素数据区的指针
  154. LPSTR   lpDIBBits;
  155. // 指向DIB象素的指针
  156. BYTE * lpSrc;
  157. // 图像宽度
  158. LONG lWidth;
  159. // 图像高度
  160. LONG lHeight;
  161. // 图像每行的字节数
  162. LONG lLineBytes;
  163. // 找到DIB图像象素起始位置
  164. lpDIBBits = ::FindDIBBits(lpDIB);
  165. // 获取图像宽度
  166. lWidth = ::DIBWidth(lpDIB);
  167. // 获取图像高度
  168. lHeight = ::DIBHeight(lpDIB);
  169. // 计算图像每行的字节数
  170. lLineBytes = WIDTHBYTES(lWidth * 8);
  171. // 更换每个象素的颜色索引(即按照灰度映射表换成灰度值)
  172. int i,j;
  173.     //逐行扫描
  174. for(i = 0; i < lHeight; i++)
  175.  {
  176.    //逐列扫描
  177. for(j = 0; j < lWidth; j++)
  178. {
  179. // 指向DIB第i行,第j个象素的指针
  180. lpSrc = (unsigned char*)lpDIBBits + lLineBytes * i + j;
  181. // 二值化处理
  182.    //大于220,设置为255,即白点
  183. if(*lpSrc>200) *lpSrc=255;
  184.   //否则设置为0,即黑点
  185. else *lpSrc=0;
  186. }
  187. }
  188.  //解除锁定
  189. ::GlobalUnlock((HGLOBAL)hDIB);
  190. }
  191. /************************************************************
  192. *
  193. *  函数名称:
  194. *       RemoveScatterNoise()
  195. *
  196. *  参数:
  197. *     HDIB    hDIB     -原图像的句柄
  198. *
  199. *  返回值:
  200. *       无
  201. *
  202. *  功能:
  203. *     通过对连续点长度的统计来去除离散杂点
  204. *
  205. *  说明:
  206. *      只能对2值图像进行处理
  207. ****************************************************************/
  208. void RemoveScatterNoise(HDIB hDIB)
  209. {
  210. // 指向DIB的指针
  211. LPSTR lpDIB=(LPSTR) ::GlobalLock((HGLOBAL)hDIB);
  212. // 指向DIB象素指针
  213. LPSTR    lpDIBBits;
  214. // 找到DIB图像象素数据区的起始位置
  215. lpDIBBits = ::FindDIBBits(lpDIB);
  216. //获得图像的长度
  217. LONG lWidth=::DIBWidth ((char*)lpDIB);
  218. //获得图像的高度
  219. LONG lHeight=::DIBHeight ((char*)lpDIB);
  220. //设置判定噪声的长度阈值为15
  221. //即如果与考察点相连接的黑点的数目小于15则认为考察点是噪声点
  222. int length=15;
  223. // 循环变量
  224. m_lianXuShu=0;
  225. LONG i;
  226. LONG j;
  227. LONG    k;
  228. // 图像每行的字节数
  229. LONG lLineBytes;
  230. // 计算图像每行的字节数
  231. lLineBytes = WIDTHBYTES(lWidth * 8);
  232.     
  233. LPSTR lpSrc;
  234. //开辟一块用来存放标志的内存数组
  235. LPBYTE lplab = new BYTE[lHeight * lWidth];
  236. //开辟一块用来保存离散判定结果的内存数组
  237. bool *lpTemp = new bool[lHeight * lWidth];
  238.     //初始化标志数组
  239. for (i=0;i<lHeight*lWidth;i++)
  240.     {
  241.     //将所有的标志位设置为非
  242. lplab[i] = false;
  243. }
  244. //用来存放离散点的坐标的数组
  245. CPoint lab[21];
  246.    
  247. //为循环变量赋初始值
  248. k=0;
  249. //扫描整个图像
  250. //逐行扫描
  251. for(i =0;i<lHeight;i++)
  252. {  
  253.        
  254.    //逐行扫描
  255. for(j=0;j<lWidth;j++)
  256. {
  257. //先把标志位置false
  258. for(k=0;k<m_lianXuShu;k++)
  259. lplab[lab[k].y * lWidth + lab[k].x] = false;
  260. //连续数置0
  261. m_lianXuShu =0;
  262.     //进行离散性判断
  263.     lpTemp[i*lWidth+j] = DeleteScaterJudge(lpDIBBits,(WORD)lLineBytes,lplab,lWidth,lHeight,j,i,lab,length);
  264. }
  265. }
  266. //扫描整个图像,把离散点填充成白色
  267. //逐行扫描
  268. for(i = 0;i<lHeight;i++)
  269. {
  270.       //逐列扫描
  271. for(j=0;j<lWidth;j++)
  272. {       
  273.     //查看标志位,如果为非则将此点设为白点
  274. if(lpTemp[i*lWidth+j] == false)
  275. {
  276.                    //指向第i行第j个象素的指针
  277. lpSrc=(char*)lpDIBBits + lLineBytes * i + j;
  278. //将此象素设为白点
  279. *lpSrc=BYTE(255);
  280. }
  281. }
  282. }
  283. //解除锁定
  284. ::GlobalUnlock ((HGLOBAL)hDIB);
  285. }
  286. /*****************************************************************
  287. *
  288. *  函数名称 
  289. *       DeleteScaterJudge()
  290. *
  291. *  参数:
  292. *     LPSTR   lpDIBBits      -指向象素起始位置的指针
  293. *   WORD    lLineBytes     -图像每行的字节数
  294. *     LPBYTE  lplab          -标志位数组
  295. *     int     lWidth         -图像的宽度
  296. *   int     lHeight        -图像的高度
  297. *     int     x              -当前点的横坐标
  298. *   int     y              -当前点的纵坐标 
  299. *     CPoint  lab[]          -存放议考察过的连续点坐标
  300. *     int     lianXuShu      -离散点的判定长度
  301. *
  302. *  返回值:
  303. *     Bool                   -是离散点返回false 不是离散点返回true
  304. *  
  305. *  功能:
  306. *     利用递归算法统计连续点的个数,通过阈值来判定是否为离散点
  307. *
  308. *  说明:
  309. *     只能对2值图像进行处理
  310. ******************************************************************/     
  311. bool DeleteScaterJudge(LPSTR lpDIBBits, WORD lLineBytes, LPBYTE lplab, int lWidth, int lHeight, int x, int y, CPoint lab[], int lianXuShu)
  312. {
  313. //如果连续长度满足要求,说明不是离散点,返回
  314. if(m_lianXuShu>=lianXuShu)
  315. return TRUE;
  316. //长度加一
  317. m_lianXuShu++;
  318. //设定访问标志
  319. lplab[lWidth * y +x] = true;
  320. //保存访问点坐标
  321. lab[m_lianXuShu-1].x = x;
  322. lab[m_lianXuShu-1].y = y;
  323. //象素的灰度值
  324. int gray;
  325.   
  326. //指向象素的指针
  327. LPSTR lpSrc;
  328. //长度判定
  329.     //如果连续长度满足要求,说明不是离散点,返回
  330. if(m_lianXuShu>=lianXuShu)
  331. return TRUE;
  332. //下面进入递归
  333. else
  334. {
  335. //考察上下左右以及左上、右上、左下、右下八个方向
  336. //如果是黑色点,则调用函数自身进行递归
  337. //考察下面点
  338. lpSrc=(char*)lpDIBBits + lLineBytes * (y-1) + x;
  339. //传递灰度值
  340. gray=*lpSrc;
  341. //如果点在图像内、颜色为黑色并且没有被访问过
  342. if(y-1 >=0 && gray == 0 && lplab[(y-1)*lWidth+x] == false)
  343. //进行递归处理
  344. DeleteScaterJudge(lpDIBBits,lLineBytes,lplab,lWidth,lHeight,x,y-1,lab,lianXuShu);
  345. //判断长度
  346. //如果连续长度满足要求,说明不是离散点,返回
  347. if(m_lianXuShu>=lianXuShu)
  348. return TRUE;
  349. //左下点
  350. lpSrc=(char*)lpDIBBits + lLineBytes * (y-1) + x-1;
  351.         //传递灰度值
  352. gray=*lpSrc;
  353.         //如果点在图像内、颜色为黑色并且没有被访问过
  354. if(y-1 >=0 &&  x-1 >=0 && gray== 0 && lplab[(y-1)*lWidth+x-1] == false)
  355.        //进行递归处理
  356. DeleteScaterJudge(lpDIBBits,lLineBytes,lplab,lWidth,lHeight,x-1,y-1,lab,lianXuShu);
  357.         //判断长度
  358. //如果连续长度满足要求,说明不是离散点,返回
  359. if(m_lianXuShu>=lianXuShu)
  360. return TRUE;
  361. //左边
  362. lpSrc=(char*)lpDIBBits + lLineBytes * y + x-1;
  363. //传递灰度值
  364. gray=*lpSrc;
  365.         //如果点在图像内、颜色为黑色并且没有被访问过
  366. if(x-1 >=0 &&  gray== 0 && lplab[y*lWidth+x-1] == false)
  367.         //进行递归处理
  368. DeleteScaterJudge(lpDIBBits,lLineBytes,lplab,lWidth,lHeight,x-1,y,lab,lianXuShu);
  369.         //判断长度
  370. //如果连续长度满足要求,说明不是离散点,返回
  371. if(m_lianXuShu>=lianXuShu)
  372. return TRUE;
  373. //左上
  374. lpSrc=(char*)lpDIBBits + lLineBytes * (y+1) + x-1;
  375. //传递灰度值
  376. gray=*lpSrc;
  377.         //如果点在图像内、颜色为黑色并且没有被访问过
  378. if(y+1 <lHeight && x-1 >= 0 && gray == 0 && lplab[(y+1)*lWidth+x-1] == false)
  379. //进行递归处理
  380. DeleteScaterJudge(lpDIBBits,lLineBytes,lplab,lWidth,lHeight,x-1,y+1,lab,lianXuShu);
  381.         //判断长度
  382. //如果连续长度满足要求,说明不是离散点,返回
  383. if(m_lianXuShu>=lianXuShu)
  384. return TRUE;
  385. //上面
  386. lpSrc=(char*)lpDIBBits + lLineBytes * (y+1) + x;
  387.         //传递灰度值
  388. gray=*lpSrc;
  389.         //如果点在图像内、颜色为黑色并且没有被访问过
  390. if(y+1 < lHeight && gray == 0 && lplab[(y+1)*lWidth+x] == false)
  391.         //进行递归处理
  392. DeleteScaterJudge(lpDIBBits,lLineBytes,lplab,lWidth,lHeight,x,y+1,lab,lianXuShu);
  393.         //判断长度
  394. //如果连续长度满足要求,说明不是离散点,返回
  395. if(m_lianXuShu>=lianXuShu)
  396. return TRUE;
  397. //右上
  398. lpSrc=(char*)lpDIBBits + lLineBytes * (y+1) + x+1;
  399.         
  400. //传递灰度值
  401. gray=*lpSrc;
  402.         //如果点在图像内、颜色为黑色并且没有被访问过
  403. if(y+1 <lHeight && x+1 <lWidth &&  gray == 0 && lplab[(y+1)*lWidth+x+1] == false)
  404.         //进行递归处理
  405. DeleteScaterJudge(lpDIBBits,lLineBytes,lplab,lWidth,lHeight,x+1,y+1,lab,lianXuShu);
  406.         //判断长度
  407. //如果连续长度满足要求,说明不是离散点,返回
  408. if(m_lianXuShu>=lianXuShu)
  409. return TRUE;
  410. //右边
  411. lpSrc=(char*)lpDIBBits + lLineBytes * y + x+1;
  412.         //传递灰度值
  413. gray=*lpSrc;
  414. //如果点在图像内、颜色为黑色并且没有被访问过
  415. if(x+1 <lWidth && gray==0 && lplab[y*lWidth+x+1] == false)
  416.         //进行递归处理
  417. DeleteScaterJudge(lpDIBBits,lLineBytes,lplab,lWidth,lHeight,x+1,y,lab,lianXuShu);
  418.         //判断长度
  419. //如果连续长度满足要求,说明不是离散点,返回
  420. if(m_lianXuShu>=lianXuShu)
  421. return TRUE;
  422. //右下
  423. lpSrc=(char*)lpDIBBits + lLineBytes * (y-1) + x+1;
  424.         //传递灰度值
  425. gray=*lpSrc;
  426.         //如果点在图像内、颜色为黑色并且没有被访问过
  427. if(y-1 >=0 && x+1 <lWidth && gray == 0 && lplab[(y-1)*lWidth+x+1] == false)
  428.        //进行递归处理
  429.    DeleteScaterJudge(lpDIBBits,lLineBytes,lplab,lWidth,lHeight,x+1,y-1,lab,lianXuShu);
  430.         //判断长度
  431. //如果连续长度满足要求,说明不是离散点,返回
  432. if(m_lianXuShu>=lianXuShu)
  433. return TRUE;
  434. }
  435. //如果递归结束,返回false,说明是离散点
  436. return FALSE;
  437. }
  438. //细化算法
  439. BOOL   WINAPI   ThiningDIB(LPSTR   lpDIBBits,   LONG   lWidth,   LONG   lHeight)   
  440.   {   
  441.     
  442.   //   指向源图像的指针   
  443.   LPSTR lpSrc;   
  444.     
  445.   //   指向缓存图像的指针   
  446.   LPSTR lpDst;   
  447.     
  448.   //   指向缓存DIB图像的指针   
  449.   LPSTR lpNewDIBBits;   
  450.   HLOCAL hNewDIBBits;   
  451.   LONG lLineBytes=WIDTHBYTES(lWidth   *   8);   
  452.   //脏标记   
  453.   BOOL   bModified;   
  454.     
  455.   //循环变量   
  456.   long   i;   
  457.   long   j;   
  458.   int     n;   
  459.   int     m;   
  460.     
  461.   //四个条件   
  462.   BOOL   bCondition1;   
  463.   BOOL   bCondition2;   
  464.   BOOL   bCondition3;   
  465.   BOOL   bCondition4;   
  466.   bool   bNotCondition5;   
  467.     
  468.   //计数器   
  469.   unsigned   char   nCount;   
  470.     
  471.   //像素值   
  472.   unsigned   char   pixel;   
  473.     
  474.   //5×5相邻区域像素值   
  475.   unsigned   char   neighbour[5][5];   
  476.     
  477.   //   暂时分配内存,以保存新图像   
  478.   hNewDIBBits   =   LocalAlloc(LHND,   lLineBytes   *   lHeight);   
  479.     
  480.   if   (hNewDIBBits   ==   NULL)   
  481.   {   
  482.   //   分配内存失败   
  483.   return   FALSE;   
  484.   }   
  485.     
  486.   //   锁定内存   
  487.   lpNewDIBBits   =   (char   *   )LocalLock(hNewDIBBits);   
  488.     
  489.   //   初始化新分配的内存,设定初始值为255   
  490.   lpDst   =   (char   *)lpNewDIBBits;   
  491.   memset(lpDst,   (BYTE)255,lLineBytes   *   lHeight);   
  492.     
  493.   bModified=TRUE;   
  494.     
  495.   while(bModified)   
  496.   {   
  497.     
  498.   bModified   =   FALSE;   
  499.   //   初始化新分配的内存,设定初始值为255   
  500.   lpDst   =   (char   *)lpNewDIBBits;   
  501.   memset(lpDst,   (BYTE)255,   lLineBytes*   lHeight);   
  502.     
  503.   for(j   =   2;   j   <lHeight-2;   j++)   
  504.   {   
  505.   for(i   =   2;i   <lWidth-2;   i++)   
  506.   {   
  507.     
  508.   bCondition1   =   FALSE;   
  509.   bCondition2   =   FALSE;   
  510.   bCondition3   =   FALSE;   
  511.   bCondition4   =   FALSE;   
  512.   bNotCondition5=true;   
  513.     
  514.   //由于使用5×5的结构元素,为防止越界,所以不处理外围的几行和几列像素   
  515.     
  516.   //   指向源图像倒数第j行,第i个象素的指针   
  517.   lpSrc   =   (char   *)lpDIBBits   +   lLineBytes   *   j   +   i;   
  518.     
  519.   //   指向目标图像倒数第j行,第i个象素的指针   
  520.   lpDst   =   (char   *)lpNewDIBBits   +   lLineBytes   *   j   +   i;   
  521.     
  522.   //取得当前指针处的像素值,注意要转换为unsigned   char型   
  523.   pixel   =   (unsigned   char)*lpSrc;   
  524.     
  525.   //目标图像中含有0和255外的其它灰度值   
  526.   if(pixel   !=   255   &&   *lpSrc   !=   0)   
  527.   //return   FALSE;   
  528.   continue;   
  529.   //如果源图像中当前点为白色,则跳过   
  530.   else   if(pixel   ==   255)   
  531.   continue;   
  532.     
  533.   //获得当前点相邻的5×5区域内像素值,白色用0代表,黑色用1代表   
  534.   for   (m   =   0;m   <   5;m++   )   
  535.   {   
  536.   for   (n   =   0;n   <   5;n++)   
  537.   {   
  538.   neighbour[m][n]   =(255   -   (unsigned   char)*(lpSrc   +   ((4   -   m)   -   2)*lLineBytes   +   n   -   2   ))   /   255;   
  539.   }   
  540.   }   
  541.   // neighbour[][]   
  542.   //逐个判断条件。   
  543.   //判断2<=NZ(P1)<=6   
  544.   nCount   =     neighbour[1][1]   +   neighbour[1][2]   +   neighbour[1][3]+   neighbour[2][1]   +   neighbour[2][3]   +    
  545.   +   neighbour[3][1]   +   neighbour[3][2]   +   neighbour[3][3];   
  546.   if   (   nCount   >=   2   &&   nCount   <=6)   
  547.   bCondition1   =   TRUE;   
  548.     
  549.   //判断Z0(P1)=1   
  550.   nCount   =   0;   
  551.   if   (neighbour[1][2]   ==   0   &&   neighbour[1][1]   ==   1)   
  552.   nCount++;   
  553.   if   (neighbour[1][1]   ==   0   &&   neighbour[2][1]   ==   1)   
  554.   nCount++;   
  555.   if   (neighbour[2][1]   ==   0   &&   neighbour[3][1]   ==   1)   
  556.   nCount++;   
  557.   if   (neighbour[3][1]   ==   0   &&   neighbour[3][2]   ==   1)   
  558.   nCount++;   
  559.   if   (neighbour[3][2]   ==   0   &&   neighbour[3][3]   ==   1)   
  560.   nCount++;   
  561.   if   (neighbour[3][3]   ==   0   &&   neighbour[2][3]   ==   1)   
  562.   nCount++;   
  563.   if   (neighbour[2][3]   ==   0   &&   neighbour[1][3]   ==   1)   
  564.   nCount++;   
  565.   if   (neighbour[1][3]   ==   0   &&   neighbour[1][2]   ==   1)   
  566.   nCount++;   
  567.   if   (nCount   ==   1)   
  568.   bCondition2   =   TRUE;   
  569.   if(neighbour[1][2]+neighbour[1][1]+neighbour[2][1]+   
  570.   neighbour[3][1]+neighbour[3][2]+neighbour[3][3]+   
  571.   neighbour[2][3]+neighbour[1][3]==1)   
  572.   bNotCondition5=false;   
  573.     
  574.   //判断P2*P4*P8=0   or   Z0(p2)!=1   
  575.   if   (neighbour[1][2]*neighbour[2][1]*neighbour[2][3]   ==   0)   
  576.   bCondition3   =   TRUE;   
  577.   else   
  578.   {   
  579.   nCount   =   0;   
  580.   if   (neighbour[0][2]   ==   0   &&   neighbour[0][1]   ==   1)   
  581.   nCount++;   
  582.   if   (neighbour[0][1]   ==   0   &&   neighbour[1][1]   ==   1)   
  583.   nCount++;   
  584.   if   (neighbour[1][1]   ==   0   &&   neighbour[2][1]   ==   1)   
  585.   nCount++;   
  586.   if   (neighbour[2][1]   ==   0   &&   neighbour[2][2]   ==   1)   
  587.   nCount++;   
  588.   if   (neighbour[2][2]   ==   0   &&   neighbour[2][3]   ==   1)   
  589.   nCount++;   
  590.   if   (neighbour[2][3]   ==   0   &&   neighbour[1][3]   ==   1)   
  591.   nCount++;   
  592.   if   (neighbour[1][3]   ==   0   &&   neighbour[0][3]   ==   1)   
  593.   nCount++;   
  594.   if   (neighbour[0][3]   ==   0   &&   neighbour[0][2]   ==   1)   
  595.   nCount++;   
  596.   if   (nCount   !=   1)   
  597.   bCondition3   =   TRUE;   
  598.   }   
  599.     
  600.   //判断P2*P4*P6=0   or   Z0(p4)!=1   
  601.   if   (neighbour[1][2]*neighbour[2][1]*neighbour[3][2]   ==   0)   
  602.   bCondition4   =   TRUE;   
  603.   else   
  604.   {   
  605.   nCount   =   0;   
  606.   if   (neighbour[1][1]   ==   0   &&   neighbour[1][0]   ==   1)   
  607.   nCount++;   
  608.   if   (neighbour[1][0]   ==   0   &&   neighbour[2][0]   ==   1)   
  609.   nCount++;   
  610.   if   (neighbour[2][0]   ==   0   &&   neighbour[3][0]   ==   1)   
  611.   nCount++;   
  612.   if   (neighbour[3][0]   ==   0   &&   neighbour[3][1]   ==   1)   
  613.   nCount++;   
  614.   if   (neighbour[3][1]   ==   0   &&   neighbour[3][2]   ==   1)   
  615.   nCount++;   
  616.   if   (neighbour[3][2]   ==   0   &&   neighbour[2][2]   ==   1)   
  617.   nCount++;   
  618.   if   (neighbour[2][2]   ==   0   &&   neighbour[1][2]   ==   1)   
  619.   nCount++;   
  620.   if   (neighbour[1][2]   ==   0   &&   neighbour[1][1]   ==   1)   
  621.   nCount++;   
  622.   if   (nCount   !=   1)   
  623.   bCondition4   =   TRUE;   
  624.     
  625.   }   
  626.   if(bCondition1   &&   bCondition2   &&   bCondition3   &&   bCondition4&&bNotCondition5)   
  627.   {   
  628.   *lpDst   =   (unsigned   char)255;   
  629.   bModified   =   TRUE;   
  630.   }   
  631.   else   
  632.   {   
  633.   *lpDst   =   (unsigned   char)0;   
  634.   }   
  635.   }   
  636.   }   
  637.   //   复制腐蚀后的图像   
  638.   memcpy(lpDIBBits,   lpNewDIBBits,   lLineBytes   *   lHeight);   
  639.     
  640.     
  641.   }   
  642.   //   复制腐蚀后的图像   
  643.   memcpy(lpDIBBits,   lpNewDIBBits,   lLineBytes   *   lHeight);   
  644.     
  645.   //   释放内存   
  646.   LocalUnlock(hNewDIBBits);   
  647.   LocalFree(hNewDIBBits);   
  648.     
  649.   //   返回   
  650.   return   TRUE;   
  651.   }   
  652.   
  653. void Thinning(HDIB hDIB)
  654. {
  655. // 指向DIB的指针
  656. LPSTR lpDIB=(LPSTR) ::GlobalLock((HGLOBAL)hDIB);
  657. // 指向DIB象素指针
  658. LPSTR    lpDIBBits;
  659. // 找到DIB图像象素起始位置
  660. lpDIBBits = ::FindDIBBits(lpDIB);
  661. //图像的高度和宽度
  662. LONG lWidth;
  663. LONG lHeight;
  664. //获取图像的宽度
  665. lWidth=::DIBWidth ((char*)lpDIB);
  666. //获取图像的高度
  667. lHeight=::DIBHeight ((char*)lpDIB);
  668.    ThiningDIB(lpDIBBits,lWidth,lHeight);
  669.  //清空内存
  670.    ::GlobalUnlock ((HGLOBAL)hDIB);
  671. return;
  672. }