morph.cpp
上传用户:gdjinyi
上传日期:2013-02-01
资源大小:1701k
文件大小:23k
源码类别:

源码/资料

开发平台:

Visual C++

  1. // ************************************************************************
  2. //  文件名:morph.cpp
  3. //
  4. //  图像形态学变换API函数库:
  5. //
  6. //  ErosionDIB()    - 图像腐蚀
  7. //  DilationDIB() - 图像膨胀
  8. //  OpenDIB() - 图像开运算
  9. //  CloseDIB() - 图像闭运算
  10. //  ThiningDIB() - 图像细化
  11. //
  12. // ************************************************************************
  13. #include "stdafx.h"
  14. #include "morph.h"
  15. #include "DIBAPI.h"
  16. #include <math.h>
  17. #include <direct.h>
  18. /*************************************************************************
  19.  *
  20.  * 函数名称:
  21.  *   ErosiontionDIB()
  22.  *
  23.  * 参数:
  24.  *   LPSTR lpDIBBits    - 指向源DIB图像指针
  25.  *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
  26.  *   LONG  lHeight      - 源图像高度(象素数)
  27.  *   int   nMode - 腐蚀方式,0表示水平方向,1表示垂直方向,2表示自定义结构元素。
  28.  *  int   structure[3][3]
  29. - 自定义的3×3结构元素。
  30.  *
  31.  * 返回值:
  32.  *   BOOL               - 腐蚀成功返回TRUE,否则返回FALSE。
  33.  *
  34.  * 说明:
  35.  * 该函数用于对图像进行腐蚀运算。结构元素为水平方向或垂直方向的三个点,中间点位于原点;
  36.  * 或者由用户自己定义3×3的结构元素。
  37.  * 
  38.  * 要求目标图像为只有0和255两个灰度值的灰度图像。
  39.  ************************************************************************/
  40. BOOL WINAPI ErosionDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, int nMode , int structure[3][3])
  41. {
  42. // 指向源图像的指针
  43. LPSTR lpSrc;
  44. // 指向缓存图像的指针
  45. LPSTR lpDst;
  46. // 指向缓存DIB图像的指针
  47. LPSTR lpNewDIBBits;
  48. HLOCAL hNewDIBBits;
  49. //循环变量
  50. long i;
  51. long j;
  52. int  n;
  53. int  m;
  54. //像素值
  55. unsigned char pixel;
  56. // 暂时分配内存,以保存新图像
  57. hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
  58. if (hNewDIBBits == NULL)
  59. {
  60. // 分配内存失败
  61. return FALSE;
  62. }
  63. // 锁定内存
  64. lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
  65. // 初始化新分配的内存,设定初始值为255
  66. lpDst = (char *)lpNewDIBBits;
  67. memset(lpDst, (BYTE)255, lWidth * lHeight);
  68. if(nMode == 0)
  69. {
  70. //使用水平方向的结构元素进行腐蚀
  71. for(j = 0; j <lHeight; j++)
  72. {
  73. for(i = 1;i <lWidth-1; i++)
  74. {
  75. //由于使用1×3的结构元素,为防止越界,所以不处理最左边和最右边的两列像素
  76. // 指向源图像倒数第j行,第i个象素的指针
  77. lpSrc = (char *)lpDIBBits + lWidth * j + i;
  78. // 指向目标图像倒数第j行,第i个象素的指针
  79. lpDst = (char *)lpNewDIBBits + lWidth * j + i;
  80. //取得当前指针处的像素值,注意要转换为unsigned char型
  81. pixel = (unsigned char)*lpSrc;
  82. //目标图像中含有0和255外的其它灰度值
  83. if(pixel != 255 && *lpSrc != 0)
  84. return FALSE;
  85. //目标图像中的当前点先赋成黑色
  86. *lpDst = (unsigned char)0;
  87. //如果源图像中当前点自身或者左右有一个点不是黑色,
  88. //则将目标图像中的当前点赋成白色
  89. for (n = 0;n < 3;n++ )
  90. {
  91. pixel = *(lpSrc+n-1);
  92. if (pixel == 255 )
  93. {
  94. *lpDst = (unsigned char)255;
  95. break;
  96. }
  97. }
  98. }
  99. }
  100. }
  101. else if(nMode == 1)
  102. {
  103. //使用垂直方向的结构元素进行腐蚀
  104. for(j = 1; j <lHeight-1; j++)
  105. {
  106. for(i = 0;i <lWidth; i++)
  107. {
  108. //由于使用1×3的结构元素,为防止越界,所以不处理最上边和最下边的两列像素
  109. // 指向源图像倒数第j行,第i个象素的指针
  110. lpSrc = (char *)lpDIBBits + lWidth * j + i;
  111. // 指向目标图像倒数第j行,第i个象素的指针
  112. lpDst = (char *)lpNewDIBBits + lWidth * j + i;
  113. //取得当前指针处的像素值,注意要转换为unsigned char型
  114. pixel = (unsigned char)*lpSrc;
  115. //目标图像中含有0和255外的其它灰度值
  116. if(pixel != 255 && *lpSrc != 0)
  117. return FALSE;
  118. //目标图像中的当前点先赋成黑色
  119. *lpDst = (unsigned char)0;
  120. //如果源图像中当前点自身或者上下有一个点不是黑色,
  121. //则将目标图像中的当前点赋成白色
  122. for (n = 0;n < 3;n++ )
  123. {
  124. pixel = *(lpSrc+(n-1)*lWidth);
  125. if (pixel == 255 )
  126. {
  127. *lpDst = (unsigned char)255;
  128. break;
  129. }
  130. }
  131. }
  132. }
  133. }
  134. else
  135. {
  136. //使用自定义的结构元素进行腐蚀
  137. for(j = 1; j <lHeight-1; j++)
  138. {
  139. for(i = 0;i <lWidth; i++)
  140. {
  141. //由于使用3×3的结构元素,为防止越界,所以不处理最左边和最右边的两列像素
  142. //和最上边和最下边的两列像素
  143. // 指向源图像倒数第j行,第i个象素的指针
  144. lpSrc = (char *)lpDIBBits + lWidth * j + i;
  145. // 指向目标图像倒数第j行,第i个象素的指针
  146. lpDst = (char *)lpNewDIBBits + lWidth * j + i;
  147. //取得当前指针处的像素值,注意要转换为unsigned char型
  148. pixel = (unsigned char)*lpSrc;
  149. //目标图像中含有0和255外的其它灰度值
  150. if(pixel != 255 && *lpSrc != 0)
  151. return FALSE;
  152. //目标图像中的当前点先赋成黑色
  153. *lpDst = (unsigned char)0;
  154. //如果原图像中对应结构元素中为黑色的那些点中有一个不是黑色,
  155. //则将目标图像中的当前点赋成白色
  156. //注意在DIB图像中内容是上下倒置的
  157. for (m = 0;m < 3;m++ )
  158. {
  159. for (n = 0;n < 3;n++)
  160. {
  161. if( structure[m][n] == -1)
  162. continue;
  163. pixel = *(lpSrc + ((2-m)-1)*lWidth + (n-1));
  164. if (pixel == 255 )
  165. {
  166. *lpDst = (unsigned char)255;
  167. break;
  168. }
  169. }
  170. }
  171. }
  172. }
  173. }
  174. // 复制腐蚀后的图像
  175. memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
  176. // 释放内存
  177. LocalUnlock(hNewDIBBits);
  178. LocalFree(hNewDIBBits);
  179. // 返回
  180. return TRUE;
  181. }
  182. /*************************************************************************
  183.  *
  184.  * 函数名称:
  185.  *   DilationDIB()
  186.  *
  187.  * 参数:
  188.  *   LPSTR lpDIBBits    - 指向源DIB图像指针
  189.  *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
  190.  *   LONG  lHeight      - 源图像高度(象素数)
  191.  *   int   nMode - 膨胀方式,0表示水平方向,1表示垂直方向,2表示自定义结构元素。
  192.  *  int   structure[3][3]
  193. - 自定义的3×3结构元素。
  194.  *
  195.  * 返回值:
  196.  *   BOOL               - 膨胀成功返回TRUE,否则返回FALSE。
  197.  *
  198.  * 说明:
  199.  * 该函数用于对图像进行膨胀运算。结构元素为水平方向或垂直方向的三个点,中间点位于原点;
  200.  * 或者由用户自己定义3×3的结构元素。
  201.  * 
  202.  * 要求目标图像为只有0和255两个灰度值的灰度图像。
  203.  ************************************************************************/
  204. BOOL WINAPI DilationDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, int nMode , int structure[3][3])
  205. {
  206. // 指向源图像的指针
  207. LPSTR lpSrc;
  208. // 指向缓存图像的指针
  209. LPSTR lpDst;
  210. // 指向缓存DIB图像的指针
  211. LPSTR lpNewDIBBits;
  212. HLOCAL hNewDIBBits;
  213. //循环变量
  214. long i;
  215. long j;
  216. int  n;
  217. int  m;
  218. //像素值
  219. unsigned char pixel;
  220. // 暂时分配内存,以保存新图像
  221. hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
  222. if (hNewDIBBits == NULL)
  223. {
  224. // 分配内存失败
  225. return FALSE;
  226. }
  227. // 锁定内存
  228. lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
  229. // 初始化新分配的内存,设定初始值为255
  230. lpDst = (char *)lpNewDIBBits;
  231. memset(lpDst, (BYTE)255, lWidth * lHeight);
  232. if(nMode == 0)
  233. {
  234. //使用水平方向的结构元素进行膨胀
  235. for(j = 0; j <lHeight; j++)
  236. {
  237. for(i = 1;i <lWidth-1; i++)
  238. {
  239. //由于使用1×3的结构元素,为防止越界,所以不处理最左边和最右边的两列像素
  240. // 指向源图像倒数第j行,第i个象素的指针
  241. lpSrc = (char *)lpDIBBits + lWidth * j + i;
  242. // 指向目标图像倒数第j行,第i个象素的指针
  243. lpDst = (char *)lpNewDIBBits + lWidth * j + i;
  244. //取得当前指针处的像素值,注意要转换为unsigned char型
  245. pixel = (unsigned char)*lpSrc;
  246. //目标图像中含有0和255外的其它灰度值
  247. if(pixel != 255 && pixel != 0)
  248. return FALSE;
  249. //目标图像中的当前点先赋成白色
  250. *lpDst = (unsigned char)255;
  251. //源图像中当前点自身或者左右只要有一个点是黑色,
  252. //则将目标图像中的当前点赋成黑色
  253. for (n = 0;n < 3;n++ )
  254. {
  255. pixel = *(lpSrc+n-1);
  256. if (pixel == 0 )
  257. {
  258. *lpDst = (unsigned char)0;
  259. break;
  260. }
  261. }
  262. }
  263. }
  264. }
  265. else if(nMode == 1)
  266. {
  267. //使用垂直方向的结构元素进行膨胀
  268. for(j = 1; j <lHeight-1; j++)
  269. {
  270. for(i = 0;i <lWidth; i++)
  271. {
  272. //由于使用1×3的结构元素,为防止越界,所以不处理最上边和最下边的两列像素
  273. // 指向源图像倒数第j行,第i个象素的指针
  274. lpSrc = (char *)lpDIBBits + lWidth * j + i;
  275. // 指向目标图像倒数第j行,第i个象素的指针
  276. lpDst = (char *)lpNewDIBBits + lWidth * j + i;
  277. //取得当前指针处的像素值,注意要转换为unsigned char型
  278. pixel = (unsigned char)*lpSrc;
  279. //目标图像中含有0和255外的其它灰度值
  280. if(pixel != 255 && *lpSrc != 0)
  281. return FALSE;
  282. //目标图像中的当前点先赋成白色
  283. *lpDst = (unsigned char)255;
  284. //源图像中当前点自身或者上下只要有一个点是黑色,
  285. //则将目标图像中的当前点赋成黑色
  286. for (n = 0;n < 3;n++ )
  287. {
  288. pixel = *(lpSrc+(n-1)*lWidth);
  289. if (pixel == 0 )
  290. {
  291. *lpDst = (unsigned char)0;
  292. break;
  293. }
  294. }
  295. }
  296. }
  297. }
  298. else
  299. {
  300. //使用自定义的结构元素进行膨胀
  301. for(j = 1; j <lHeight-1; j++)
  302. {
  303. for(i = 0;i <lWidth; i++)
  304. {
  305. //由于使用3×3的结构元素,为防止越界,所以不处理最左边和最右边的两列像素
  306. //和最上边和最下边的两列像素
  307. // 指向源图像倒数第j行,第i个象素的指针
  308. lpSrc = (char *)lpDIBBits + lWidth * j + i;
  309. // 指向目标图像倒数第j行,第i个象素的指针
  310. lpDst = (char *)lpNewDIBBits + lWidth * j + i;
  311. //取得当前指针处的像素值,注意要转换为unsigned char型
  312. pixel = (unsigned char)*lpSrc;
  313. //目标图像中含有0和255外的其它灰度值
  314. if(pixel != 255 && *lpSrc != 0)
  315. return FALSE;
  316. //目标图像中的当前点先赋成白色
  317. *lpDst = (unsigned char)255;
  318. //原图像中对应结构元素中为黑色的那些点中只要有一个是黑色,
  319. //则将目标图像中的当前点赋成黑色
  320. //注意在DIB图像中内容是上下倒置的
  321. for (m = 0;m < 3;m++ )
  322. {
  323. for (n = 0;n < 3;n++)
  324. {
  325. if( structure[m][n] == -1)
  326. continue;
  327. pixel = *(lpSrc + ((2-m)-1)*lWidth + (n-1));
  328. if (pixel == 0 )
  329. {
  330. *lpDst = (unsigned char)0;
  331. break;
  332. }
  333. }
  334. }
  335. }
  336. }
  337. }
  338. // 复制膨胀后的图像
  339. memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
  340. // 释放内存
  341. LocalUnlock(hNewDIBBits);
  342. LocalFree(hNewDIBBits);
  343. // 返回
  344. return TRUE;
  345. }
  346. /*************************************************************************
  347.  *
  348.  * 函数名称:
  349.  *   OpenDIB()
  350.  *
  351.  * 参数:
  352.  *   LPSTR lpDIBBits    - 指向源DIB图像指针
  353.  *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
  354.  *   LONG  lHeight      - 源图像高度(象素数)
  355.  *   int   nMode - 开运算方式,0表示水平方向,1表示垂直方向,2表示自定义结构元素。
  356.  *  int   structure[3][3]
  357. - 自定义的3×3结构元素。
  358.  *
  359.  * 返回值:
  360.  *   BOOL               - 开运算成功返回TRUE,否则返回FALSE。
  361.  *
  362.  * 说明:
  363.  * 该函数用于对图像进行开运算。结构元素为水平方向或垂直方向的三个点,中间点位于原点;
  364.  * 或者由用户自己定义3×3的结构元素。
  365.  * 
  366.  * 要求目标图像为只有0和255两个灰度值的灰度图像。
  367.  ************************************************************************/
  368. BOOL WINAPI OpenDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, int nMode , int structure[3][3])
  369. {
  370. // 指向源图像的指针
  371. LPSTR lpSrc;
  372. // 指向缓存图像的指针
  373. LPSTR lpDst;
  374. // 指向缓存DIB图像的指针
  375. LPSTR lpNewDIBBits;
  376. HLOCAL hNewDIBBits;
  377. //循环变量
  378. long i;
  379. long j;
  380. int  n;
  381. int  m;
  382. //像素值
  383. unsigned char pixel;
  384. // 暂时分配内存,以保存新图像
  385. hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
  386. if (hNewDIBBits == NULL)
  387. {
  388. // 分配内存失败
  389. return FALSE;
  390. }
  391. // 锁定内存
  392. lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
  393. // 初始化新分配的内存,设定初始值为255
  394. lpDst = (char *)lpNewDIBBits;
  395. memset(lpDst, (BYTE)255, lWidth * lHeight);
  396. if(nMode == 0)
  397. {
  398. //使用水平方向的结构元素进行腐蚀
  399. for(j = 0; j <lHeight; j++)
  400. {
  401. for(i = 1;i <lWidth-1; i++)
  402. {
  403. //由于使用1×3的结构元素,为防止越界,所以不处理最左边和最右边的两列像素
  404. // 指向源图像倒数第j行,第i个象素的指针
  405. lpSrc = (char *)lpDIBBits + lWidth * j + i;
  406. // 指向目标图像倒数第j行,第i个象素的指针
  407. lpDst = (char *)lpNewDIBBits + lWidth * j + i;
  408. //取得当前指针处的像素值,注意要转换为unsigned char型
  409. pixel = (unsigned char)*lpSrc;
  410. //目标图像中含有0和255外的其它灰度值
  411. if(pixel != 255 && *lpSrc != 0)
  412. return FALSE;
  413. //目标图像中的当前点先赋成黑色
  414. *lpDst = (unsigned char)0;
  415. //如果源图像中当前点自身或者左右有一个点不是黑色,
  416. //则将目标图像中的当前点赋成白色
  417. for (n = 0;n < 3;n++ )
  418. {
  419. pixel = *(lpSrc+n-1);
  420. if (pixel == 255 )
  421. {
  422. *lpDst = (unsigned char)255;
  423. break;
  424. }
  425. }
  426. }
  427. }
  428. }
  429. else if(nMode == 1)
  430. {
  431. //使用垂直方向的结构元素进行腐蚀
  432. for(j = 1; j <lHeight-1; j++)
  433. {
  434. for(i = 0;i <lWidth; i++)
  435. {
  436. //由于使用1×3的结构元素,为防止越界,所以不处理最上边和最下边的两列像素
  437. // 指向源图像倒数第j行,第i个象素的指针
  438. lpSrc = (char *)lpDIBBits + lWidth * j + i;
  439. // 指向目标图像倒数第j行,第i个象素的指针
  440. lpDst = (char *)lpNewDIBBits + lWidth * j + i;
  441. //取得当前指针处的像素值,注意要转换为unsigned char型
  442. pixel = (unsigned char)*lpSrc;
  443. //目标图像中含有0和255外的其它灰度值
  444. if(pixel != 255 && *lpSrc != 0)
  445. return FALSE;
  446. //目标图像中的当前点先赋成黑色
  447. *lpDst = (unsigned char)0;
  448. //如果源图像中当前点自身或者上下有一个点不是黑色,
  449. //则将目标图像中的当前点赋成白色
  450. for (n = 0;n < 3;n++ )
  451. {
  452. pixel = *(lpSrc+(n-1)*lWidth);
  453. if (pixel == 255 )
  454. {
  455. *lpDst = (unsigned char)255;
  456. break;
  457. }
  458. }
  459. }
  460. }
  461. }
  462. else
  463. {
  464. //使用自定义的结构元素进行腐蚀
  465. for(j = 1; j <lHeight-1; j++)
  466. {
  467. for(i = 0;i <lWidth; i++)
  468. {
  469. //由于使用3×3的结构元素,为防止越界,所以不处理最左边和最右边的两列像素
  470. //和最上边和最下边的两列像素
  471. // 指向源图像倒数第j行,第i个象素的指针
  472. lpSrc = (char *)lpDIBBits + lWidth * j + i;
  473. // 指向目标图像倒数第j行,第i个象素的指针
  474. lpDst = (char *)lpNewDIBBits + lWidth * j + i;
  475. //取得当前指针处的像素值,注意要转换为unsigned char型
  476. pixel = (unsigned char)*lpSrc;
  477. //目标图像中含有0和255外的其它灰度值
  478. if(pixel != 255 && *lpSrc != 0)
  479. return FALSE;
  480. //目标图像中的当前点先赋成黑色
  481. *lpDst = (unsigned char)0;
  482. //如果原图像中对应结构元素中为黑色的那些点中有一个不是黑色,
  483. //则将目标图像中的当前点赋成白色
  484. //注意在DIB图像中内容是上下倒置的
  485. for (m = 0;m < 3;m++ )
  486. {
  487. for (n = 0;n < 3;n++)
  488. {
  489. if( structure[m][n] == -1)
  490. continue;
  491. pixel = *(lpSrc + ((2-m)-1)*lWidth + (n-1));
  492. if (pixel == 255 )
  493. {
  494. *lpDst = (unsigned char)255;
  495. break;
  496. }
  497. }
  498. }
  499. }
  500. }
  501. }
  502. // 复制腐蚀后的图像
  503. memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
  504. // 重新初始化新分配的内存,设定初始值为255
  505. //lpDst = (char *)lpNewDIBBits;
  506. //memset(lpDst, (BYTE)255, lWidth * lHeight);
  507. if(nMode == 0)
  508. {
  509. //使用水平方向的结构元素进行膨胀
  510. for(j = 0; j <lHeight; j++)
  511. {
  512. for(i = 1;i <lWidth-1; i++)
  513. {
  514. //由于使用1×3的结构元素,为防止越界,所以不处理最左边和最右边的两列像素
  515. // 指向源图像倒数第j行,第i个象素的指针
  516. lpSrc = (char *)lpDIBBits + lWidth * j + i;
  517. // 指向目标图像倒数第j行,第i个象素的指针
  518. lpDst = (char *)lpNewDIBBits + lWidth * j + i;
  519. //取得当前指针处的像素值,注意要转换为unsigned char型
  520. pixel = (unsigned char)*lpSrc;
  521. //目标图像中含有0和255外的其它灰度值
  522. if(pixel != 255 && *lpSrc != 0)
  523. return FALSE;
  524. //目标图像中的当前点先赋成白色
  525. *lpDst = (unsigned char)255;
  526. //源图像中当前点自身或者左右只要有一个点是黑色,
  527. //则将目标图像中的当前点赋成黑色
  528. for (n = 0;n < 3;n++ )
  529. {
  530. pixel = *(lpSrc+n-1);
  531. if (pixel == 0 )
  532. {
  533. *lpDst = (unsigned char)0;
  534. break;
  535. }
  536. }
  537. }
  538. }
  539. }
  540. else if(nMode == 1)
  541. {
  542. //使用垂直方向的结构元素进行膨胀
  543. for(j = 1; j <lHeight-1; j++)
  544. {
  545. for(i = 0;i <lWidth; i++)
  546. {
  547. //由于使用1×3的结构元素,为防止越界,所以不处理最上边和最下边的两列像素
  548. // 指向源图像倒数第j行,第i个象素的指针
  549. lpSrc = (char *)lpDIBBits + lWidth * j + i;
  550. // 指向目标图像倒数第j行,第i个象素的指针
  551. lpDst = (char *)lpNewDIBBits + lWidth * j + i;
  552. //取得当前指针处的像素值,注意要转换为unsigned char型
  553. pixel = (unsigned char)*lpSrc;
  554. //目标图像中含有0和255外的其它灰度值
  555. if(pixel != 255 && *lpSrc != 0)
  556. return FALSE;
  557. //目标图像中的当前点先赋成白色
  558. *lpDst = (unsigned char)255;
  559. //源图像中当前点自身或者上下只要有一个点是黑色,
  560. //则将目标图像中的当前点赋成黑色
  561. for (n = 0;n < 3;n++ )
  562. {
  563. pixel = *(lpSrc+(n-1)*lWidth);
  564. if (pixel == 0 )
  565. {
  566. *lpDst = (unsigned char)0;
  567. break;
  568. }
  569. }
  570. }
  571. }
  572. }
  573. else
  574. {
  575. //使用自定义的结构元素进行膨胀
  576. for(j = 1; j <lHeight-1; j++)
  577. {
  578. for(i = 0;i <lWidth; i++)
  579. {
  580. //由于使用3×3的结构元素,为防止越界,所以不处理最左边和最右边的两列像素
  581. //和最上边和最下边的两列像素
  582. // 指向源图像倒数第j行,第i个象素的指针
  583. lpSrc = (char *)lpDIBBits + lWidth * j + i;
  584. // 指向目标图像倒数第j行,第i个象素的指针
  585. lpDst = (char *)lpNewDIBBits + lWidth * j + i;
  586. //取得当前指针处的像素值,注意要转换为unsigned char型
  587. pixel = (unsigned char)*lpSrc;
  588. //目标图像中含有0和255外的其它灰度值
  589. if(pixel != 255 && *lpSrc != 0)
  590. return FALSE;
  591. //目标图像中的当前点先赋成白色
  592. *lpDst = (unsigned char)255;
  593. //原图像中对应结构元素中为黑色的那些点中只要有一个是黑色,
  594. //则将目标图像中的当前点赋成黑色
  595. //注意在DIB图像中内容是上下倒置的
  596. for (m = 0;m < 3;m++ )
  597. {
  598. for (n = 0;n < 3;n++)
  599. {
  600. if( structure[m][n] == -1)
  601. continue;
  602. pixel = *(lpSrc + ((2-m)-1)*lWidth + (n-1));
  603. if (pixel == 0 )
  604. {
  605. *lpDst = (unsigned char)0;
  606. break;
  607. }
  608. }
  609. }
  610. }
  611. }
  612. }
  613. // 复制膨胀后的图像
  614. memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
  615. // 释放内存
  616. LocalUnlock(hNewDIBBits);
  617. LocalFree(hNewDIBBits);
  618. return TRUE;
  619. }
  620. /*************************************************************************
  621.  *
  622.  * 函数名称:
  623.  *   CloseDIB()
  624.  *
  625.  * 参数:
  626.  *   LPSTR lpDIBBits    - 指向源DIB图像指针
  627.  *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
  628.  *   LONG  lHeight      - 源图像高度(象素数)
  629.  *   int   nMode - 闭运算方式,0表示水平方向,1表示垂直方向,2表示自定义结构元素。
  630.  *  int   structure[3][3]
  631. - 自定义的3×3结构元素。
  632.  *
  633.  * 返回值:
  634.  *   BOOL               - 闭运算成功返回TRUE,否则返回FALSE。
  635.  *
  636.  * 说明:
  637.  * 该函数用于对图像进行开运算。结构元素为水平方向或垂直方向的三个点,中间点位于原点;
  638.  * 或者由用户自己定义3×3的结构元素。
  639.  * 
  640.  * 要求目标图像为只有0和255两个灰度值的灰度图像。
  641.  ************************************************************************/
  642. /*************************************************************************
  643.  *
  644.  * 函数名称:
  645.  *   ThinDIB()
  646.  *
  647.  * 参数:
  648.  *   LPSTR lpDIBBits    - 指向源DIB图像指针
  649.  *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
  650.  *   LONG  lHeight      - 源图像高度(象素数)
  651.  *
  652.  * 返回值:
  653.  *   BOOL               - 闭运算成功返回TRUE,否则返回FALSE。
  654.  *
  655.  * 说明:
  656.  * 该函数用于对图像进行细化运算。
  657.  * 
  658.  * 要求目标图像为只有0和255两个灰度值的灰度图像。
  659.  ************************************************************************/
  660. BOOL WINAPI CloseDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, int nMode , int structure[3][3])
  661. {
  662. if (DilationDIB(lpDIBBits, lWidth, lHeight, nMode , structure))
  663. {
  664. if (ErosionDIB(lpDIBBits, lWidth, lHeight, nMode , structure))
  665. {
  666. // 返回
  667. return TRUE;
  668. }
  669. }
  670. return FALSE;
  671. // 返回
  672. return TRUE;
  673. }
  674. BOOL WINAPI ThiningDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
  675. {
  676. // 指向源图像的指针
  677. LPSTR lpSrc;
  678. // 指向缓存图像的指针
  679. LPSTR lpDst;
  680. // 指向缓存DIB图像的指针
  681. LPSTR lpNewDIBBits;
  682. HLOCAL hNewDIBBits;
  683. //脏标记
  684. BOOL bModified;
  685. //循环变量
  686. long i;
  687. long j;
  688. int  n;
  689. int  m;
  690. //四个条件
  691. BOOL bCondition1;
  692. BOOL bCondition2;
  693. BOOL bCondition3;
  694. BOOL bCondition4;
  695. //计数器
  696. unsigned char nCount;
  697. //像素值
  698. unsigned char pixel;
  699. //5×5相邻区域像素值
  700. unsigned char neighbour[5][5];
  701. // 暂时分配内存,以保存新图像
  702. hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
  703. if (hNewDIBBits == NULL)
  704. {
  705. // 分配内存失败
  706. return FALSE;
  707. }
  708. // 锁定内存
  709. lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
  710. // 初始化新分配的内存,设定初始值为255
  711. lpDst = (char *)lpNewDIBBits;
  712. memset(lpDst, (BYTE)255, lWidth * lHeight);
  713. bModified=TRUE;
  714. while(bModified)
  715. {
  716. bModified = FALSE;
  717. // 初始化新分配的内存,设定初始值为255
  718. lpDst = (char *)lpNewDIBBits;
  719. memset(lpDst, (BYTE)255, lWidth * lHeight);
  720. for(j = 2; j <lHeight-2; j++)
  721. {
  722. for(i = 2;i <lWidth-2; i++)
  723. {
  724. bCondition1 = FALSE;
  725. bCondition2 = FALSE;
  726. bCondition3 = FALSE;
  727. bCondition4 = FALSE;
  728. //由于使用5×5的结构元素,为防止越界,所以不处理外围的几行和几列像素
  729. // 指向源图像倒数第j行,第i个象素的指针
  730. lpSrc = (char *)lpDIBBits + lWidth * j + i;
  731. // 指向目标图像倒数第j行,第i个象素的指针
  732. lpDst = (char *)lpNewDIBBits + lWidth * j + i;
  733. //取得当前指针处的像素值,注意要转换为unsigned char型
  734. pixel = (unsigned char)*lpSrc;
  735. //目标图像中含有0和255外的其它灰度值
  736. if(pixel != 255 && *lpSrc != 0)
  737. //return FALSE;
  738. continue;
  739. //如果源图像中当前点为白色,则跳过
  740. else if(pixel == 255)
  741. continue;
  742. //获得当前点相邻的5×5区域内像素值,白色用0代表,黑色用1代表
  743. for (m = 0;m < 5;m++ )
  744. {
  745. for (n = 0;n < 5;n++)
  746. {
  747. neighbour[m][n] =(255 - (unsigned char)*(lpSrc + ((4 - m) - 2)*lWidth + n - 2 )) / 255;
  748. }
  749. }
  750. // neighbour[][]
  751. //逐个判断条件。
  752. //判断2<=NZ(P1)<=6
  753. nCount =  neighbour[1][1] + neighbour[1][2] + neighbour[1][3] 
  754. + neighbour[2][1] + neighbour[2][3] + 
  755. + neighbour[3][1] + neighbour[3][2] + neighbour[3][3];
  756. if ( nCount >= 2 && nCount <=6)
  757. bCondition1 = TRUE;
  758. //判断Z0(P1)=1
  759. nCount = 0;
  760. if (neighbour[1][2] == 0 && neighbour[1][1] == 1)
  761. nCount++;
  762. if (neighbour[1][1] == 0 && neighbour[2][1] == 1)
  763. nCount++;
  764. if (neighbour[2][1] == 0 && neighbour[3][1] == 1)
  765. nCount++;
  766. if (neighbour[3][1] == 0 && neighbour[3][2] == 1)
  767. nCount++;
  768. if (neighbour[3][2] == 0 && neighbour[3][3] == 1)
  769. nCount++;
  770. if (neighbour[3][3] == 0 && neighbour[2][3] == 1)
  771. nCount++;
  772. if (neighbour[2][3] == 0 && neighbour[1][3] == 1)
  773. nCount++;
  774. if (neighbour[1][3] == 0 && neighbour[1][2] == 1)
  775. nCount++;
  776. if (nCount == 1)
  777. bCondition2 = TRUE;
  778. //判断P2*P4*P8=0 or Z0(p2)!=1
  779. if (neighbour[1][2]*neighbour[2][1]*neighbour[2][3] == 0)
  780. bCondition3 = TRUE;
  781. else
  782. {
  783. nCount = 0;
  784. if (neighbour[0][2] == 0 && neighbour[0][1] == 1)
  785. nCount++;
  786. if (neighbour[0][1] == 0 && neighbour[1][1] == 1)
  787. nCount++;
  788. if (neighbour[1][1] == 0 && neighbour[2][1] == 1)
  789. nCount++;
  790. if (neighbour[2][1] == 0 && neighbour[2][2] == 1)
  791. nCount++;
  792. if (neighbour[2][2] == 0 && neighbour[2][3] == 1)
  793. nCount++;
  794. if (neighbour[2][3] == 0 && neighbour[1][3] == 1)
  795. nCount++;
  796. if (neighbour[1][3] == 0 && neighbour[0][3] == 1)
  797. nCount++;
  798. if (neighbour[0][3] == 0 && neighbour[0][2] == 1)
  799. nCount++;
  800. if (nCount != 1)
  801. bCondition3 = TRUE;
  802. }
  803. //判断P2*P4*P6=0 or Z0(p4)!=1
  804. if (neighbour[1][2]*neighbour[2][1]*neighbour[3][2] == 0)
  805. bCondition4 = TRUE;
  806. else
  807. {
  808. nCount = 0;
  809. if (neighbour[1][1] == 0 && neighbour[1][0] == 1)
  810. nCount++;
  811. if (neighbour[1][0] == 0 && neighbour[2][0] == 1)
  812. nCount++;
  813. if (neighbour[2][0] == 0 && neighbour[3][0] == 1)
  814. nCount++;
  815. if (neighbour[3][0] == 0 && neighbour[3][1] == 1)
  816. nCount++;
  817. if (neighbour[3][1] == 0 && neighbour[3][2] == 1)
  818. nCount++;
  819. if (neighbour[3][2] == 0 && neighbour[2][2] == 1)
  820. nCount++;
  821. if (neighbour[2][2] == 0 && neighbour[1][2] == 1)
  822. nCount++;
  823. if (neighbour[1][2] == 0 && neighbour[1][1] == 1)
  824. nCount++;
  825. if (nCount != 1)
  826. bCondition4 = TRUE;
  827. }
  828. if(bCondition1 && bCondition2 && bCondition3 && bCondition4)
  829. {
  830. *lpDst = (unsigned char)255;
  831. bModified = TRUE;
  832. }
  833. else
  834. {
  835. *lpDst = (unsigned char)0;
  836. }
  837. }
  838. }
  839. // 复制腐蚀后的图像
  840. memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
  841. }
  842. // 复制腐蚀后的图像
  843. memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
  844. // 释放内存
  845. LocalUnlock(hNewDIBBits);
  846. LocalFree(hNewDIBBits);
  847. // 返回
  848. return TRUE;
  849. }