suanfa1.cpp
上传用户:jiele008
上传日期:2008-02-01
资源大小:2679k
文件大小:22k
源码类别:

图形/文字识别

开发平台:

Visual C++

  1. /**************************************************************************
  2. *  文件名:suanfa1.cpp
  3. *
  4. *  车牌定位函数库:
  5. *
  6. *  myMedianFilter() - 图像中值滤波。
  7. *  myGetMedianNum()     - 获取中值。被函数MedianFilter()调用来求中值。
  8. *  ReplaceColorPal()     - 更换伪彩色编码表。
  9. *  ConvertToGrayScale();   - 24位真彩色图转换成灰度图
  10. *  ThresholdTrans();       - 阀值变换
  11. *  myTemplate();           - 图像模板变换,通过改变模板,可以用它实现
  12. *       图像的平滑、锐化、边缘识别等操作。
  13. *  myHprojectDIB();        - 水平投影
  14. *  myVprojectDIB() ;       - 垂直投影 
  15. *  myCropDIB();            - 区域剪裁
  16. *************************************************************************/
  17. #include "stdafx.h"
  18. #include "suanfa1.h"
  19. #include <math.h>
  20. #include <direct.h>
  21. /*************************************************************************
  22. *
  23. * 函数名称:
  24. *   ConvertToGrayScale()
  25. *
  26. * 参数:
  27. *   LPSTR lpDIB - 指向源DIB图像指针
  28. *   
  29. * 返回值:
  30. *   BOOL - 成功返回TRUE,否则返回FALSE。
  31. *
  32. * 说明:
  33. *   该函数将24位真彩色图转换成256级灰度图
  34. *
  35. ************************************************************************/
  36. BOOL WINAPI ConvertToGrayScale(LPSTR lpDIB)   
  37. {
  38. LPSTR lpDIBBits;                //指向DIB的象素的指针
  39. LPSTR lpNewDIBBits;             //指向DIB灰度图图像(新图像)开始处象素的指针
  40.     LONG lLineBytes;
  41. unsigned char * lpSrc;          //指向原图像象素点的指针
  42. unsigned char * lpdest;         //指向目标图像象素点的指针
  43.     unsigned  char *ired,*igreen,*iblue;
  44.     long lWidth;                    //图像宽度和高度
  45. long lHeight;
  46. long i,j;           //循环变量
  47. lWidth = ::DIBWidth(lpDIB);   //DIB 宽度
  48. lHeight = ::DIBHeight(lpDIB); //DIB 高度
  49. RGBQUAD  *lpRGBquad;
  50. lpRGBquad = (RGBQUAD *)&lpDIB[sizeof(BITMAPINFOHEADER)]; //INFOHEADER后为调色板
  51.     if(::DIBNumColors(lpDIB) == 256)  //256色位图不作任何处理
  52. {
  53. return TRUE;
  54.     }
  55. if(::DIBNumColors(lpDIB) != 256)  //非256色位图将它灰度化
  56. {
  57. lLineBytes = WIDTHBYTES(lWidth*8*3);
  58. lpdest=  new  BYTE[lHeight*lWidth];
  59. lpDIBBits = (LPSTR)lpDIB + sizeof(BITMAPINFOHEADER);//指向DIB象素
  60. for(i = 0;i < lHeight; i++)
  61. for(j = 0;j < lWidth*3; j+=3)
  62. {
  63. ired   =  (unsigned  char*)lpDIBBits + lLineBytes * i + j + 2;
  64. igreen =  (unsigned  char*)lpDIBBits + lLineBytes * i + j + 1;
  65. iblue  =  (unsigned  char*)lpDIBBits + lLineBytes * i + j ;
  66. lpdest[i*lWidth + j/3]  = (unsigned  char)((*ired)*0.299 + (*igreen)*0.588 + (*iblue)*0.114);
  67. }
  68. //需要做三件事情:1、修改INFOHEADER 2、增加调色板 3、修改原图像灰度值
  69. LPBITMAPINFOHEADER  lpBI;
  70. lpBI  =  (LPBITMAPINFOHEADER)lpDIB;
  71. lpBI->biBitCount = 8;
  72. //设置灰度调色板
  73. for(i = 0;i < 256;i++)
  74. {
  75. lpRGBquad[i].rgbRed   = (unsigned char)i;
  76. lpRGBquad[i].rgbGreen = (unsigned char)i;
  77. lpRGBquad[i].rgbBlue  = (unsigned char)i;
  78. lpRGBquad[i].rgbReserved = 0;
  79. }
  80. lpNewDIBBits= ::FindDIBBits(lpDIB);  //找到DIB图像象素起始位置
  81. lLineBytes=WIDTHBYTES(lWidth  *  8);
  82. //修改灰度值
  83. for(i = 0;i < lHeight; i++)
  84. for(j = 0;j < lWidth; j++)
  85. {
  86. lpSrc = (unsigned  char*)lpNewDIBBits + lLineBytes * i+ j ;
  87. *lpSrc=lpdest[i*lWidth+j];
  88. }
  89. delete  lpdest;
  90. }
  91. return true;
  92. }
  93. /*************************************************************************
  94. *
  95. * 函数名称:
  96. *   ThresholdTrans()
  97. *
  98. * 参数:
  99. *   LPSTR lpDIBBits    - 指向源DIB图像指针
  100. *   LONG  lWidth       - 源图像宽度(象素数)
  101. *   LONG  lHeight      - 源图像高度(象素数)
  102. *   BYTE  bThre     - 阈值
  103. *
  104. * 返回值:
  105. *   BOOL               - 成功返回TRUE,否则返回FALSE。
  106. *
  107. * 说明:
  108. *   该函数用来对图像进行阈值变换。对于灰度值小于阈值的象素直接设置
  109. * 灰度值为0;灰度值大于阈值的象素直接设置为255。
  110. *
  111. ************************************************************************/
  112. BOOL WINAPI ThresholdTrans(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BYTE bThre)
  113. {
  114. // 指向源图像的指针
  115. unsigned char* lpSrc;
  116. // 循环变量
  117. LONG i;
  118. LONG j;
  119. // 图像每行的字节数
  120. LONG lLineBytes;
  121. // 计算图像每行的字节数
  122. lLineBytes = WIDTHBYTES(lWidth * 8);
  123. // 每行
  124. for(i = 0; i < lHeight; i++)
  125. {
  126. // 每列
  127. for(j = 0; j < lWidth; j++)
  128. {
  129. // 指向DIB第i行,第j个象素的指针
  130. lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
  131. // 判断是否小于阈值
  132. if ((*lpSrc) < bThre)
  133. {
  134. // 直接赋值为0
  135. *lpSrc = 0;
  136. }
  137. else
  138. {
  139. // 直接赋值为255
  140. *lpSrc = 255;
  141. }
  142. }
  143. }
  144. // 返回
  145. return TRUE;
  146. }
  147. /*************************************************************************
  148. *
  149. * 函数名称:
  150. *   Template()
  151. *
  152. * 参数:
  153. *   LPSTR lpDIBBits    - 指向源DIB图像指针
  154. *   LONG  lWidth       - 源图像宽度(象素数)
  155. *   LONG  lHeight      - 源图像高度(象素数)
  156. *   int   iTempH - 模板的高度
  157. *   int   iTempW - 模板的宽度
  158. *   int   iTempMX - 模板的中心元素X坐标 ( < iTempW - 1)
  159. *   int   iTempMY - 模板的中心元素Y坐标 ( < iTempH - 1)
  160. *  FLOAT * fpArray - 指向模板数组的指针
  161. *  FLOAT fCoef - 模板系数
  162. *
  163. * 返回值:
  164. *   BOOL               - 成功返回TRUE,否则返回FALSE。
  165. *
  166. * 说明:
  167. *   该函数用指定的模板(任意大小)来对图像进行操作,参数iTempH指定模板
  168. * 的高度,参数iTempW指定模板的宽度,参数iTempMX和iTempMY指定模板的中心
  169. * 元素坐标,参数fpArray指定模板元素,fCoef指定系数。
  170. *
  171. ************************************************************************/
  172. BOOL WINAPI myTemplate(LPSTR lpDIB)
  173. {
  174. // 指向复制图像的指针
  175. LPSTR lpNewDIBBits;
  176. HLOCAL hNewDIBBits;
  177. // 指向要复制区域的指针
  178. unsigned char* lpDst;
  179. LPSTR lpDIBBits;                   //指向DIB的象素的指针
  180.     LONG lLineBytes;                   // 图像每行的字节数
  181. unsigned char * lpSrc;             //指向原图像象素点的指针
  182.     long lWidth;                       //图像宽度和高度
  183. long lHeight;
  184. // 计算结果
  185. INT fResult;
  186. // 找到DIB图像象素起始位置
  187. lpDIBBits = ::FindDIBBits(lpDIB);
  188. lWidth = ::DIBWidth(lpDIB);   //DIB 宽度
  189. lHeight = ::DIBHeight(lpDIB); //DIB 高度
  190. // 计算图像每行的字节数
  191. lLineBytes = WIDTHBYTES(lWidth * 8);
  192. // 暂时分配内存,以保存新图像
  193. hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight);
  194. // 判断是否内存分配失败
  195. if (hNewDIBBits == NULL)
  196. {
  197. // 分配内存失败
  198. return false;
  199. }
  200. // 锁定内存
  201. lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
  202. // 初始化图像为原始图像
  203. memcpy(lpNewDIBBits, lpDIBBits, lLineBytes * lHeight);
  204. long i,j;           //循环变量
  205. //
  206. //
  207. for(i = 0; i < lHeight-1; i++)
  208. {
  209. // 每列
  210. for(j = 0; j < lWidth-1; j++)
  211. {
  212. // 指向新DIB第i行,第j个象素的指针
  213. lpDst = (unsigned char*)lpNewDIBBits + lLineBytes * (lHeight - 1 - i) + j;
  214. // 指向DIB第i行,第j个象素的指针
  215. lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
  216. fResult=(*lpSrc)-(*(lpSrc+1));
  217. // 取绝对值
  218. if(fResult<0) fResult=-fResult;
  219. // 判断是否超过255
  220. if(fResult > 255)
  221. {
  222. // 直接赋值为255
  223. * lpDst = 255;
  224. }
  225. else
  226. {
  227. // 赋值
  228. * lpDst = (unsigned char) (fResult + 0.5);
  229. }
  230. }
  231. }
  232. // 复制变换后的图像
  233. memcpy(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight);
  234. // 释放内存
  235. LocalUnlock(hNewDIBBits);
  236. LocalFree(hNewDIBBits);
  237. // 返回
  238. return TRUE;
  239. }
  240. /*************************************************************************
  241. *
  242. * 函数名称:
  243. *   myHprojectDIB()
  244. *
  245. * 参数:
  246. *   LPSTR lpDIBBits    - 指向源DIB图像指针
  247. *   LONG  lWidth       - 源图像宽度(象素数)
  248. *   LONG  lHeight      - 源图像高度(象素数)
  249. *   INT*  iTop         - 车牌上边缘
  250. *   INT*  iBottom      - 车牌下边缘
  251. * 返回值:
  252. *   BOOL               - 成功返回TRUE,否则返回FALSE。
  253. *
  254. * 说明:
  255. *   该函数用于对含车牌图像进行水平投影运算,求取车牌子图像的上下边缘位置
  256. *
  257. ************************************************************************/
  258. BOOL WINAPI myHprojectDIB(LPSTR lpDIB, LONG lWidth, LONG lHeight, 
  259.   int* iTop, int* iBottom) 
  260. {
  261. LPSTR lpDIBBits;                   //指向DIB的象素的指针
  262.     LONG lLineBytes;                   // 图像每行的字节数
  263. unsigned char * lpSrc;             //指向原图像象素点的指针
  264. unsigned char pixel; //像素值
  265. int i,j;
  266. // 计算结果
  267. INT* iResult;
  268. INT pzBottom,pzTop;
  269. bool findPZ=false;
  270. // 找到DIB图像象素起始位置
  271. lpDIBBits = ::FindDIBBits(lpDIB);
  272. // 计算图像每行的字节数
  273. lLineBytes = WIDTHBYTES(lWidth * 8);
  274. iResult=new INT[lHeight];
  275. for(i=0;i<lHeight;i++)
  276. iResult[i]=0;
  277. for(j=lHeight/5;j<lHeight*0.8;j++)
  278. {
  279. iResult[j]=0;
  280. for(i=0;i<lWidth;i++)
  281. {
  282. lpSrc=(unsigned char*)lpDIBBits+lLineBytes*j+i;
  283. pixel=(unsigned char)(*lpSrc);
  284. if(pixel==255)
  285. {
  286. iResult[j]++;
  287. }
  288. }
  289. if((!findPZ)&&iResult[j]>12)
  290. {
  291. pzBottom=j;
  292. findPZ=true;
  293. }
  294. if(findPZ&&iResult[j]<12)
  295. {
  296. pzTop=j;
  297. break;
  298. }
  299. }
  300. pzTop=pzBottom+55;
  301. pzBottom=pzBottom-20;   //微量调整
  302. *iBottom=lHeight-pzBottom;
  303. *iTop=lHeight-pzTop;
  304. return true;
  305. }
  306. /*************************************************************************
  307. *
  308. * 函数名称:
  309. *   myVprojectDIB()
  310. *
  311. * 参数:
  312. *   LPSTR lpDIBBits    - 指向源DIB图像指针
  313. *   LONG  lWidth       - 源图像宽度(象素数)
  314. *   LONG  lHeight      - 源图像高度(象素数)
  315. *   INT*  iLeft        - 车牌左边缘
  316. *   INT*  iRight       - 车牌右边缘
  317. * 返回值:
  318. *   BOOL               - 成功返回TRUE,否则返回FALSE。
  319. *
  320. * 说明:
  321. *   该函数用于对含车牌图像进行垂直投影运算,求取车牌子图像的左右边缘位置
  322. *
  323. ************************************************************************/
  324. BOOL WINAPI myVprojectDIB(LPSTR lpDIB, LONG lWidth, LONG lHeight, 
  325.   int* iLeft, int* iRight) 
  326. {
  327. LPSTR lpDIBBits;                   //指向DIB的象素的指针
  328.     LONG lLineBytes;                   // 图像每行的字节数
  329. unsigned char * lpSrc;             //指向原图像象素点的指针
  330. unsigned char pixel; //像素值
  331. int i,j;
  332. // 计算结果
  333. INT* iResult;
  334. INT pzLeft,pzRight;
  335. bool findPZ=false;
  336. // 找到DIB图像象素起始位置
  337. lpDIBBits = ::FindDIBBits(lpDIB);
  338. // 计算图像每行的字节数
  339. lLineBytes = WIDTHBYTES(lWidth * 8);
  340. iResult=new INT[lWidth];
  341. for(i=0;i<lWidth;i++)
  342. iResult[i]=0;
  343. for(i=lWidth/5;i<lWidth*0.8;i++)
  344. {
  345. iResult[i]=0;
  346. for(j=0;j<lHeight;j++)
  347. {
  348. lpSrc=(unsigned char*)lpDIBBits+lLineBytes*j+i;
  349. pixel=(unsigned char)(*lpSrc);
  350. if(pixel==255)
  351. {
  352. iResult[i]++;
  353. }
  354. }
  355. if((!findPZ)&&iResult[i]>10)
  356. {
  357. pzLeft=i;
  358. findPZ=true;
  359. }
  360. pzRight=pzLeft+150;
  361. }
  362. *iLeft=pzLeft-10;
  363. *iRight=pzRight+10;
  364. return true;
  365. }
  366. /*************************************************************************
  367. *
  368. * 函数名称:
  369. *   MedianFilter()
  370. *
  371. * 参数:
  372. *   LPSTR lpDIBBits - 指向源DIB图像指针
  373. *   LONG  lWidth - 源图像宽度(象素数)
  374. *   LONG  lHeight - 源图像高度(象素数)
  375. *   int   iFilterH - 滤波器的高度
  376. *   int   iFilterW - 滤波器的宽度
  377. *   int   iFilterMX - 滤波器的中心元素X坐标
  378. *   int   iFilterMY - 滤波器的中心元素Y坐标
  379. *
  380. * 返回值:
  381. *   BOOL - 成功返回TRUE,否则返回FALSE。
  382. *
  383. * 说明:
  384. *   该函数对DIB图像进行中值滤波。
  385. *
  386. ************************************************************************/
  387. BOOL WINAPI myMedianFilter(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, 
  388.    int iFilterH, int iFilterW, 
  389.    int iFilterMX, int iFilterMY)
  390. {
  391. // 指向源图像的指针
  392. unsigned char* lpSrc;
  393. // 指向要复制区域的指针
  394. unsigned char* lpDst;
  395. // 指向复制图像的指针
  396. LPSTR lpNewDIBBits;
  397. HLOCAL hNewDIBBits;
  398. // 指向滤波器数组的指针
  399. unsigned char * aValue;
  400. HLOCAL hArray;
  401. // 循环变量
  402. LONG i;
  403. LONG j;
  404. LONG k;
  405. LONG l;
  406. // 图像每行的字节数
  407. LONG lLineBytes;
  408. // 计算图像每行的字节数
  409. lLineBytes = WIDTHBYTES(lWidth * 8);
  410. // 暂时分配内存,以保存新图像
  411. hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight);
  412. // 判断是否内存分配失败
  413. if (hNewDIBBits == NULL)
  414. {
  415. // 分配内存失败
  416. return FALSE;
  417. }
  418. // 锁定内存
  419. lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
  420. // 初始化图像为原始图像
  421. memcpy(lpNewDIBBits, lpDIBBits, lLineBytes * lHeight);
  422. // 暂时分配内存,以保存滤波器数组
  423. hArray = LocalAlloc(LHND, iFilterH * iFilterW);
  424. // 判断是否内存分配失败
  425. if (hArray == NULL)
  426. {
  427. // 释放内存
  428. LocalUnlock(hNewDIBBits);
  429. LocalFree(hNewDIBBits);
  430. // 分配内存失败
  431. return FALSE;
  432. }
  433. // 锁定内存
  434. aValue = (unsigned char * )LocalLock(hArray);
  435. // 开始中值滤波
  436. // 行(除去边缘几行)
  437. for(i = iFilterMY; i < lHeight - iFilterH + iFilterMY + 1; i++)
  438. {
  439. // 列(除去边缘几列)
  440. for(j = iFilterMX; j < lWidth - iFilterW + iFilterMX + 1; j++)
  441. {
  442. // 指向新DIB第i行,第j个象素的指针
  443. lpDst = (unsigned char*)lpNewDIBBits + lLineBytes * (lHeight - 1 - i) + j;
  444. // 读取滤波器数组
  445. for (k = 0; k < iFilterH; k++)
  446. {
  447. for (l = 0; l < iFilterW; l++)
  448. {
  449. // 指向DIB第i - iFilterMY + k行,第j - iFilterMX + l个象素的指针
  450. lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i + iFilterMY - k) + j - iFilterMX + l;
  451. // 保存象素值
  452. aValue[k * iFilterW + l] = *lpSrc;
  453. }
  454. }
  455. // 获取中值
  456. * lpDst = myGetMedianNum(aValue, iFilterH * iFilterW);
  457. }
  458. }
  459. // 复制变换后的图像
  460. memcpy(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight);
  461. // 释放内存
  462. LocalUnlock(hNewDIBBits);
  463. LocalFree(hNewDIBBits);
  464. LocalUnlock(hArray);
  465. LocalFree(hArray);
  466. // 返回
  467. return TRUE;
  468. }
  469. /*************************************************************************
  470. *
  471. * 函数名称:
  472. *   GetMedianNum()
  473. *
  474. * 参数:
  475. *   unsigned char * bpArray - 指向要获取中值的数组指针
  476. *   int   iFilterLen - 数组长度
  477. *
  478. * 返回值:
  479. *   unsigned char      - 返回指定数组的中值。
  480. *
  481. * 说明:
  482. *   该函数用冒泡法对一维数组进行排序,并返回数组元素的中值。
  483. *
  484. ************************************************************************/
  485. unsigned char WINAPI myGetMedianNum(unsigned char * bArray, int iFilterLen)
  486. {
  487. // 循环变量
  488. int i;
  489. int j;
  490. // 中间变量
  491. unsigned char bTemp;
  492. // 用冒泡法对数组进行排序
  493. for (j = 0; j < iFilterLen - 1; j ++)
  494. {
  495. for (i = 0; i < iFilterLen - j - 1; i ++)
  496. {
  497. if (bArray[i] > bArray[i + 1])
  498. {
  499. // 互换
  500. bTemp = bArray[i];
  501. bArray[i] = bArray[i + 1];
  502. bArray[i + 1] = bTemp;
  503. }
  504. }
  505. }
  506. // 计算中值
  507. if ((iFilterLen & 1) > 0)
  508. {
  509. // 数组有奇数个元素,返回中间一个元素
  510. bTemp = bArray[(iFilterLen + 1) / 2];
  511. }
  512. else
  513. {
  514. // 数组有偶数个元素,返回中间两个元素平均值
  515. bTemp = (bArray[iFilterLen / 2] + bArray[iFilterLen / 2 + 1]) / 2;
  516. }
  517. // 返回中值
  518. return bTemp;
  519. }
  520. /*************************************************************************
  521. *
  522. * 函数名称:
  523. *   InteEqualize()
  524. *
  525. * 参数:
  526. *   LPSTR lpDIBBits    - 指向源DIB图像指针
  527. *   LONG  lWidth       - 源图像宽度(象素数)
  528. *   LONG  lHeight      - 源图像高度(象素数)
  529. *
  530. * 返回值:
  531. *   BOOL               - 成功返回TRUE,否则返回FALSE。
  532. *
  533. * 说明:
  534. *   该函数用来对图像进行直方图均衡。
  535. *
  536. ************************************************************************/
  537. BOOL WINAPI InteEqualize(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
  538. {
  539. // 指向源图像的指针
  540. unsigned char* lpSrc;
  541. // 临时变量
  542. LONG lTemp;
  543. // 循环变量
  544. LONG i;
  545. LONG j;
  546. // 灰度映射表
  547. BYTE bMap[256];
  548. // 灰度映射表
  549. LONG lCount[256];
  550. // 图像每行的字节数
  551. LONG lLineBytes;
  552. // 计算图像每行的字节数
  553. lLineBytes = WIDTHBYTES(lWidth * 8);
  554. // 重置计数为0
  555. for (i = 0; i < 256; i ++)
  556. {
  557. // 清零
  558. lCount[i] = 0;
  559. }
  560. // 计算各个灰度值的计数
  561. for (i = 0; i < lHeight; i ++)
  562. {
  563. for (j = 0; j < lWidth; j ++)
  564. {
  565. lpSrc = (unsigned char *)lpDIBBits + lLineBytes * i + j;
  566. // 计数加1
  567. lCount[*(lpSrc)]++;
  568. }
  569. }
  570. // 计算灰度映射表
  571. for (i = 0; i < 256; i++)
  572. {
  573. // 初始为0
  574. lTemp = 0;
  575. for (j = 0; j <= i ; j++)
  576. {
  577. lTemp += lCount[j];
  578. }
  579. // 计算对应的新灰度值
  580. bMap[i] = (BYTE) (lTemp * 255 / lHeight / lWidth);
  581. }
  582. // 每行
  583. for(i = 0; i < lHeight; i++)
  584. {
  585. // 每列
  586. for(j = 0; j < lWidth; j++)
  587. {
  588. // 指向DIB第i行,第j个象素的指针
  589. lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
  590. // 计算新的灰度值
  591. *lpSrc = bMap[*lpSrc];
  592. }
  593. }
  594. // 返回
  595. return TRUE;
  596. }
  597. /*************************************************************************
  598. *
  599. * 函数名称:
  600. *   AddMinusDIB()
  601. *
  602. * 参数:
  603. *   LPSTR lpDIBBits    - 指向源DIB图像指针
  604. *   LPSTR lpDIBBitsBK  - 指向背景DIB图像指针
  605. *   LONG  lWidth       - 源图像宽度(象素数)
  606. *   LONG  lHeight      - 源图像高度(象素数)
  607. *  bool  bAddMinus - 为true时执行加运算,否则执行减运算。
  608. *
  609. * 返回值:
  610. *   BOOL               - 运算成功返回TRUE,否则返回FALSE。
  611. *
  612. * 说明:
  613. * 该函数用于对两幅图像进行加减运算。
  614. * 要求目标图像为255个灰度值的灰度图像。
  615. ************************************************************************/
  616. BOOL WINAPI AddMinusDIB(LPSTR lpDIBBits, LPSTR lpDIBBitsBK, LONG lWidth, LONG lHeight ,bool bAddMinus)
  617. {
  618. // 指向源图像的指针
  619. LPSTR lpSrc,lpSrcBK;
  620. // 指向缓存图像的指针
  621. LPSTR lpDst;
  622. // 指向缓存DIB图像的指针
  623. LPSTR lpNewDIBBits;
  624. HLOCAL hNewDIBBits;
  625. //循环变量
  626. long i;
  627. long j;
  628. //像素值
  629. unsigned char pixel,pixelBK;
  630. // 图像每行的字节数
  631. LONG lLineBytes;
  632. // 暂时分配内存,以保存新图像
  633. hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
  634. if (hNewDIBBits == NULL)
  635. {
  636. // 分配内存失败
  637. return FALSE;
  638. }
  639. // 锁定内存
  640. lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
  641. // 初始化新分配的内存,设定初始值为255
  642. lpDst = (char *)lpNewDIBBits;
  643. memset(lpDst, (BYTE)255, lWidth * lHeight);
  644. // 计算图像每行的字节数
  645. lLineBytes = WIDTHBYTES(lWidth * 8);
  646. for (j = 0;j < lHeight ;j++)
  647. {
  648. for(i = 0;i < lWidth ;i++)
  649. {
  650. // 指向源图像倒数第j行,第i个象素的指针
  651. lpSrc = (char *)lpDIBBits + lLineBytes * j + i;
  652. lpSrcBK = (char *)lpDIBBitsBK + lLineBytes * j + i;
  653. // 指向目标图像倒数第j行,第i个象素的指针
  654. lpDst = (char *)lpNewDIBBits + lLineBytes * j + i;
  655. pixel = (unsigned char)*lpSrc;
  656. pixelBK = (unsigned char)*lpSrcBK;
  657. if(bAddMinus)
  658. *lpDst = pixel + pixelBK > 255 ? 255 : pixel + pixelBK;
  659. else
  660. // *lpDst = pixel - pixelBK < 0 ? 0 : pixel - pixelBK;
  661. if(abs(pixel - pixelBK)<10)
  662. *lpDst=0;
  663. else
  664. *lpDst=pixel;
  665. }
  666. }
  667. // 复制腐蚀后的图像
  668. memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
  669. // 释放内存
  670. LocalUnlock(hNewDIBBits);
  671. LocalFree(hNewDIBBits);
  672. // 返回
  673. return TRUE;
  674. }
  675. /*************************************************************************
  676. *
  677. * 函数名称:
  678. *   myCropDIB()
  679. *
  680. * 参数:
  681. *   HDIB hDIB          - 指向源DIB图像句柄
  682. *   LPRECT lpRect      - 指向要剪裁的矩形区域
  683. *
  684. * 返回值:
  685. *   HDIB               - 返回裁剪后的矩形区域图像句柄。
  686. *
  687. * 说明:
  688. * 该函数用于对指定图像进行指定区域裁剪操作。
  689. * 要求目标图像为255个灰度值的灰度图像。
  690. ************************************************************************/
  691. HDIB WINAPI myCropDIB(HDIB hDIB, LPRECT lpRect)
  692. {
  693. LPBITMAPINFO lpbmi = NULL; 
  694.     LPBYTE       lpSourceBits, lpTargetBits, lpResult; 
  695.     HDC  hDC = NULL, hSourceDC, hTargetDC; 
  696.     HBITMAP      hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap; 
  697.     DWORD        dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize; 
  698. int  nWidth, nHeight;
  699. HDIB  hNewDIB;
  700. DWORD  dwSize;
  701. // Get DIB pointer
  702. if (! hDIB)
  703. {
  704. return NULL;
  705. }
  706. LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDIB);
  707. if (! lpSrcDIB)
  708. {
  709. return NULL;
  710. }
  711.     // Allocate and fill out a BITMAPINFO struct for the new DIB 
  712.     dwTargetHeaderSize = sizeof( BITMAPINFOHEADER ) + PaletteSize((LPSTR)lpSrcDIB); 
  713.     lpbmi = (LPBITMAPINFO)malloc( dwTargetHeaderSize ); 
  714. memcpy(lpbmi, lpSrcDIB, dwTargetHeaderSize);
  715. nWidth = RECTWIDTH(lpRect);
  716. nHeight = RECTHEIGHT(lpRect);
  717.     lpbmi->bmiHeader.biWidth = nWidth; 
  718.     lpbmi->bmiHeader.biHeight = nHeight; 
  719.     // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em 
  720. hDC = ::GetDC( NULL ); 
  721.     hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 ); 
  722.     hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 ); 
  723.     hSourceDC = CreateCompatibleDC( hDC ); 
  724.     hTargetDC = CreateCompatibleDC( hDC ); 
  725.     // Flip the bits on the source DIBSection to match the source DIB 
  726.     dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpSrcDIB->bmiHeader)); 
  727.     dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpbmi->bmiHeader)); 
  728.     memcpy( lpSourceBits, FindDIBBits((LPSTR)lpSrcDIB), dwSourceBitsSize ); 
  729.     lpbmi->bmiHeader.biSizeImage = dwTargetBitsSize; 
  730.     // Select DIBSections into DCs 
  731.     hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap ); 
  732.     hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap ); 
  733. // put old bitmap in new bitmap 
  734.     BitBlt(hTargetDC, 0, 0, nWidth, nHeight, hSourceDC, lpRect->left, lpRect->top, SRCCOPY); 
  735.     // Clean up and delete the DCs 
  736.     SelectObject( hSourceDC, hOldSourceBitmap ); 
  737.     SelectObject( hTargetDC, hOldTargetBitmap ); 
  738.     DeleteDC( hSourceDC ); 
  739.     DeleteDC( hTargetDC ); 
  740.     ::ReleaseDC( NULL, hDC ); 
  741.     // Flush the GDI batch, so we can play with the bits 
  742.     GdiFlush(); 
  743.     // Allocate enough memory for the new CF_DIB, and copy bits 
  744. dwSize = dwTargetHeaderSize + dwTargetBitsSize;
  745. hNewDIB =(HDIB)GlobalAlloc(GHND, dwSize);
  746.     lpResult = (LPBYTE)GlobalLock(hNewDIB);//malloc( dwTargetHeaderSize + dwTargetBitsSize ); 
  747.     memcpy( lpResult, lpbmi, dwTargetHeaderSize ); 
  748.     memcpy( FindDIBBits( (LPSTR)lpResult ), lpTargetBits, dwTargetBitsSize ); 
  749.     // final cleanup 
  750.     DeleteObject( hTargetBitmap ); 
  751.     DeleteObject( hSourceBitmap ); 
  752.     free( lpbmi ); 
  753. GlobalUnlock(hDIB);
  754. GlobalUnlock(hNewDIB);
  755.     return hNewDIB;
  756. }