DIB.cpp
上传用户:yipeng6868
上传日期:2013-02-16
资源大小:222k
文件大小:47k
源码类别:

书籍源码

开发平台:

Visual C++

  1. // DIB.cpp: implementation of the DIB class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "DIB.h"
  6. #include"math.h"
  7. #define WIDTHBYTES(bits)  ((bits+31)/32*4)
  8. #define RECTWIDTH(x) (x->right-x->left)
  9. #define RECTHEIGHT(x) (x->bottom-x->top)
  10. #define THRESHOLDCONTRAST  40
  11. #ifdef _DEBUG
  12. #undef THIS_FILE
  13. static char THIS_FILE[]=__FILE__;
  14. #define new DEBUG_NEW
  15. #endif
  16. #define PI 3.1415926
  17. extern int locax,locay;
  18. #define m_WIDTH 600
  19. #define m_HEIGHT 600
  20. //////////////////////////////////////////////////////////////////////
  21. // Construction/Destruction
  22. /////////////////////////////////////////////////////////////////////
  23. HDIB DIB::ReadDIBFile(HANDLE hFile)
  24. {
  25. BITMAPFILEHEADER bmfHeader;
  26. DWORD dwBitsSize;
  27. HANDLE hDIB;
  28. HANDLE hDIBtmp;
  29. LPBITMAPINFOHEADER lpbi;
  30. DWORD dwRead;
  31.     //得到文件大小
  32. dwBitsSize = GetFileSize(hFile,NULL);
  33. hDIB =  GlobalAlloc(GMEM_MOVEABLE,(DWORD)(sizeof(BITMAPINFOHEADER)));
  34. if(!hDIB)
  35. return NULL;
  36. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  37. if(!lpbi)
  38. {
  39. GlobalFree(hDIB);
  40. return NULL;
  41. }
  42. if(!ReadFile(hFile,(LPBYTE)&bmfHeader,sizeof(BITMAPFILEHEADER),&dwRead,NULL))
  43. goto ErrExit;
  44. if(sizeof(BITMAPFILEHEADER)!=dwRead)//读取文件出错
  45. goto ErrExit;
  46. if(bmfHeader.bfType != 0x4d42)//文件类型不匹配
  47. goto ErrExit;
  48. if(!ReadFile(hFile,(LPBYTE)lpbi,sizeof(BITMAPINFOHEADER),&dwRead,NULL))
  49. goto ErrExit;
  50. if(sizeof(BITMAPINFOHEADER)!= dwRead)//读取数据出错
  51. goto ErrExit;
  52. GlobalUnlock(hDIB);
  53. if(lpbi->biSizeImage==0)
  54. lpbi->biSizeImage = (this->BytePerLine(hDIB))*lpbi->biHeight;
  55. hDIBtmp = GlobalReAlloc(hDIB,lpbi->biSize+lpbi->biSizeImage,0);
  56. if(!hDIBtmp)
  57. goto ErrExitNoUnlock;
  58. else
  59. hDIB = hDIBtmp;
  60. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  61. //根据情况设定文件指针
  62. if(bmfHeader.bfOffBits != 0L)
  63. SetFilePointer(hFile,bmfHeader.bfOffBits,NULL,FILE_BEGIN);
  64.     //读取文件的象素颜色数据
  65. if(ReadFile(hFile,(LPBYTE)lpbi+lpbi->biSize,lpbi->biSizeImage,&dwRead,NULL))
  66. goto OKExit;
  67. ErrExit:
  68. GlobalUnlock(hDIB);
  69. ErrExitNoUnlock:
  70. GlobalFree(hDIB); //释放内存
  71. return NULL;
  72. OKExit:
  73. GlobalUnlock(hDIB);
  74. return hDIB;
  75. }
  76. HDIB DIB::LoadDIB(LPCTSTR lpFileName)
  77. {
  78. HANDLE hDIB;
  79. HANDLE hFile;
  80. //创建文件句柄
  81. if((hFile = CreateFile(lpFileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN,NULL))!= INVALID_HANDLE_VALUE)
  82. {  
  83. //读取数据
  84. hDIB = ReadDIBFile(hFile);
  85. //关闭文件句柄
  86. CloseHandle(hFile);
  87. return hDIB;
  88. }
  89. return NULL;
  90. }
  91. BOOL DIB::PaintDIBTrue(HDC hDC,LPRECT lpDCRect,HANDLE hDIB,LPRECT lpDIBRect ,DWORD dwRop)
  92. {
  93. LPBYTE lpDIBHdr;
  94. LPBYTE lpDIBBits;
  95. BOOL bSuccess = FALSE;
  96. if(!hDIB)
  97. return FALSE;
  98. lpDIBHdr = (LPBYTE)GlobalLock(hDIB);
  99. lpDIBBits = lpDIBHdr + sizeof(BITMAPINFOHEADER);
  100. bSuccess = StretchDIBits(hDC,lpDCRect->left,
  101.  lpDCRect->top,
  102.  RECTWIDTH(lpDCRect),
  103.  RECTHEIGHT(lpDCRect),
  104.  lpDIBRect->left,
  105.  ((LPBITMAPINFOHEADER)lpDIBHdr)->biHeight-lpDIBRect->top-RECTHEIGHT(lpDIBRect),
  106.  RECTWIDTH(lpDIBRect),
  107.  RECTHEIGHT(lpDIBRect),
  108.  lpDIBBits,
  109.  (LPBITMAPINFO)lpDIBHdr,
  110.  DIB_RGB_COLORS,
  111.  SRCCOPY);
  112. GlobalUnlock(hDIB);
  113. return bSuccess;
  114. }
  115. WORD DIB::BytePerLine(HANDLE hDIB)
  116. {
  117. WORD i;
  118. LPBITMAPINFOHEADER lpbi;
  119. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  120. i = WIDTHBYTES((lpbi->biWidth)*24);
  121. GlobalUnlock(hDIB);
  122. return i;
  123. }
  124. //函数实现图片从彩色到黑白的转换
  125. HDIB DIB::ToGray(HANDLE hDIB)
  126. {
  127. HDIB hNewDIB = NULL;
  128. LPBITMAPINFOHEADER lpSrc,lpDest;
  129. LPBYTE lpS,lpD;
  130. DWORD dwBytesPerLine;
  131. DWORD dwImgSize;
  132. WORD wBytesPerLine;
  133. unsigned i ,j,height,width;
  134. if(!hDIB)
  135. return NULL;
  136. lpSrc = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  137. dwBytesPerLine = WIDTHBYTES(24*(lpSrc->biWidth));
  138. dwImgSize = lpSrc->biHeight * dwBytesPerLine;
  139. //申请新的内存,大小等于原来图象的大小
  140. hNewDIB = GlobalAlloc(GHND,sizeof(BITMAPINFOHEADER)+dwImgSize);
  141. lpDest = (LPBITMAPINFOHEADER)GlobalLock(hNewDIB);
  142. //保存图片的长宽、颜色深度等信息
  143. memcpy((void*)lpDest,(void*)lpSrc,sizeof(BITMAPINFOHEADER));
  144. DWORD dwSBytesPerLine;
  145. dwSBytesPerLine = (24*(lpSrc->biWidth)+31)/32*4;
  146. height = lpDest->biHeight;
  147. width = lpDest->biWidth;
  148. lpS = (LPBYTE)lpSrc;
  149. wBytesPerLine = this->BytePerLine(hDIB);
  150. lpD = (LPBYTE)lpDest;
  151. lpS = lpS + sizeof(BITMAPINFOHEADER);
  152. lpD = lpD + sizeof(BITMAPINFOHEADER);
  153. unsigned  r , g ,b,gray ;
  154. //扫描整个图片,实现灰度化
  155. for(i = 0 ;i<height; i++)
  156. {
  157. for(j = 0 ;j<(unsigned )lpDest->biWidth;j++)
  158. {
  159.         //获得原来图片的颜色值
  160. r = *(lpS++);
  161. g = *(lpS++);
  162. b  = *(lpS++);
  163. //计算灰度值
  164. gray = (g*50+r*39+b*11)/100;
  165. //保存灰度值到目标图片
  166. *(lpD++)=gray;
  167. *(lpD++) = gray;
  168. *(lpD++) = gray;
  169. }
  170. //处理四字节对齐问题
  171. unsigned  k ;
  172. for(k=0;k<dwSBytesPerLine-lpSrc->biWidth*3;k++)
  173. {
  174. lpS++;
  175. lpD++;
  176. }
  177. }
  178. GlobalUnlock(hDIB);
  179. GlobalUnlock(hNewDIB);
  180.     return hNewDIB;
  181. }
  182. LPBYTE  DIB::FindDIBBits(HANDLE hDIB)
  183. {
  184. LPBYTE lpDIB,lpDIBtmp;
  185. LPBITMAPINFOHEADER lpbi;
  186. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  187. lpDIBtmp = (LPBYTE)lpbi;
  188. lpDIB = lpDIBtmp + sizeof(BITMAPINFOHEADER);
  189. GlobalUnlock(hDIB);
  190. return lpDIB;
  191. }
  192. long DIB::PixelOffset(int i,int j,WORD wBytePerLine)
  193. {
  194. long   Offset;
  195. Offset = i*wBytePerLine + j*3;
  196. return Offset;
  197. }
  198. int DIB::BOUND(int a ,int b ,int rgb)
  199. {
  200. if(rgb<0)
  201. return BOUND(a,b,abs(rgb));
  202. if(rgb>b)
  203. return b;
  204. return rgb;
  205. }
  206. //实现图片的黑白二值化
  207. void DIB::WhiteBlack(HANDLE hDIB,unsigned n)
  208. {
  209. LPBITMAPINFOHEADER  lpbi;
  210. LPBYTE lpS;
  211. int width,height;
  212. long lOffset;
  213. WORD                wBytesPerLine;
  214. if(!hDIB)
  215. return ;
  216. wBytesPerLine = this->BytePerLine(hDIB);
  217. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  218.     //得到图片的长宽信息
  219. width = lpbi->biWidth;
  220. height = lpbi->biHeight;
  221. lpS = (LPBYTE)lpbi;
  222. //lps指向数据区
  223. lpS = lpS + sizeof(BITMAPINFOHEADER);
  224.    //扫描整个图片,实现二值化
  225. for(int i = 0;i<height;i++)
  226. for(int j = 0 ;j<width;j++)
  227. {   //得到象素数据在数据区中的偏移
  228. lOffset = this->PixelOffset(i,j,wBytesPerLine);
  229. if(*(lpS+lOffset)<n)//象素值小于临界值
  230. {   //把象素填充为黑色
  231. *(lpS+lOffset++) = 0;
  232. *(lpS+lOffset++) = 0;
  233. *(lpS+lOffset)   = 0;
  234. }
  235. else //象素值大于临界值
  236. {   
  237. //把象素填充为白色
  238. *(lpS+lOffset++) = 255;
  239. *(lpS+lOffset++) = 255;
  240. *(lpS+lOffset)   = 255;
  241. }
  242. }
  243. GlobalUnlock(hDIB);
  244. }
  245. DIB::DIB()
  246. {
  247. for(int i=0;i<ImgRange; i++)
  248. for (int j=0; j<ImgRange; j++)
  249. this->lab[i][j] = false;
  250. }
  251. DIB::~DIB()
  252. {
  253. }
  254. BOOL DIB:: SaveDIB(HANDLE hDib, CFile& file)
  255. {
  256. // Bitmap文件头
  257. BITMAPFILEHEADER bmfHdr;
  258. // 指向BITMAPINFOHEADER的指针
  259. LPBITMAPINFOHEADER lpBI;
  260. // DIB大小
  261. DWORD dwDIBSize =0;
  262. if (hDib == NULL)
  263. {
  264. // 如果DIB为空,返回FALSE
  265. return FALSE;
  266. }
  267. // 读取BITMAPINFO结构,并锁定
  268. lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib);
  269. if (lpBI == NULL)
  270. {
  271. // 为空,返回FALSE
  272. return FALSE;
  273. }
  274. // 判断是否是WIN3.0 DIB
  275. // if (!IS_WIN30_DIB(lpBI))
  276. // {
  277. // 不支持其它类型的DIB保存
  278. // 解除锁定
  279. // ::GlobalUnlock((HGLOBAL) hDib);
  280. // 返回FALSE
  281. // return FALSE;
  282. // }
  283. // 填充文件头
  284. // 文件类型"BM"
  285. bmfHdr.bfType =  0x4d42; //DIB_HEADER_MARKER;
  286. // 计算DIB大小时,最简单的方法是调用GlobalSize()函数。但是全局内存大小并
  287. // 不是DIB真正的大小,它总是多几个字节。这样就需要计算一下DIB的真实大小。
  288. // 文件头大小+颜色表大小
  289. // (BITMAPINFOHEADER和BITMAPCOREHEADER结构的第一个DWORD都是该结构的大小)
  290. // dwDIBSize = *(LPDWORD)lpBI; //+ ::PaletteSize((LPSTR)lpBI);
  291. dwDIBSize = sizeof(BITMAPINFOHEADER);//+lpBI->biSizeImage;
  292. // 计算图像大小
  293. if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))
  294. {
  295. // 对于RLE位图,没法计算大小,只能信任biSizeImage内的值
  296. dwDIBSize += lpBI->biSizeImage;
  297. }
  298. else
  299. {
  300. // 象素的大小
  301. DWORD dwBmBitsSize;
  302. // 大小为Width * Height
  303. dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*24) * lpBI->biHeight;
  304. // 计算出DIB真正的大小
  305. dwDIBSize += dwBmBitsSize;
  306. // 更新biSizeImage(很多BMP文件头中biSizeImage的值是错误的)
  307. lpBI->biSizeImage = dwBmBitsSize;
  308. }
  309. // 计算文件大小:DIB大小+BITMAPFILEHEADER结构大小
  310. bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
  311. // 两个保留字
  312. bmfHdr.bfReserved1 = 0;
  313. bmfHdr.bfReserved2 = 0;
  314. // 计算偏移量bfOffBits,它的大小为Bitmap文件头大小+DIB头大小+颜色表大小
  315. bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize;
  316.  // + PaletteSize((LPSTR)lpBI);
  317. // 尝试写文件
  318. // TRY
  319. {
  320. // 写文件头
  321. file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
  322. // 写DIB头和象素
  323. file.WriteHuge(lpBI, dwDIBSize);
  324. }
  325. // CATCH (CFileException, e)
  326. // {
  327. // 解除锁定
  328. // ::GlobalUnlock((HGLOBAL) hDib);
  329. // 抛出异常
  330. /// THROW_LAST();
  331. // }
  332. // END_CATCH
  333. // 解除锁定
  334. ::GlobalUnlock((HGLOBAL) hDib);
  335. // 返回TRUE
  336. return TRUE;
  337. }
  338. HANDLE DIB::CopyHandle( HANDLE hSrc)
  339. {
  340. HANDLE hDst;
  341. LPBITMAPINFOHEADER lpbi;
  342. int width,height;
  343. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hSrc);
  344. width = lpbi->biWidth;
  345. height = lpbi->biHeight;
  346. hDst = GlobalAlloc(GMEM_MOVEABLE,lpbi->biSize+lpbi->biSizeImage);
  347. if(!hDst)
  348. return NULL;
  349. LPBYTE lpDest;
  350. lpDest = (LPBYTE)GlobalLock(hDst);
  351. memcpy(lpDest,(LPBYTE)lpbi,lpbi->biSize+lpbi->biSizeImage);
  352. GlobalUnlock(hSrc);
  353. GlobalUnlock(hDst);
  354. return hDst;
  355. }
  356. //函数寻找图片中的特征区域的中心点
  357. #define THRESHOLD (RADIUS*2+1)*(RADIUS*2+1)*15
  358. //函数在一幅图片中寻找匹配的中心点
  359. BOOL DIB::MatchImportantPoint(HANDLE hDIB,int CharaterInfo[RADIUS*2+1][RADIUS*2+1][3],CPoint *ImPoint)
  360. {
  361. LPBITMAPINFOHEADER lpbi;
  362. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  363. int width = lpbi->biWidth;
  364. int height = lpbi->biHeight;
  365. LPBYTE lpData = this->FindDIBBits(hDIB);
  366.     WORD wBytesPerLine = this->BytePerLine(hDIB);
  367. long lOffset;
  368. long sum =100000,tempsum;
  369. //扫描整个图片(边缘点)除外
  370. for(int i=RADIUS ;i<height-RADIUS;i++)
  371. for(int j=RADIUS;j<width-RADIUS;j++)
  372. {
  373. tempsum =0;
  374. //扫描以RADIUS*2+1为边长的正方形区域
  375. for(int k=-RADIUS;k<=RADIUS;k++)
  376. for(int kk=-RADIUS;kk<=RADIUS;kk++)
  377. {
  378. //计算当前正方形和已知特征区域的颜色差值
  379. lOffset = this->PixelOffset(i+k,j+kk,wBytesPerLine);
  380. int colorblue = abs(*(lpData+lOffset++)-CharaterInfo[k+RADIUS][kk+RADIUS][0]);
  381. int colorgreen = abs(*(lpData+lOffset++)-CharaterInfo[k+RADIUS][kk+RADIUS][1]);
  382. int colorred = abs(*(lpData+lOffset++)-CharaterInfo[k+RADIUS][kk+RADIUS][2]);
  383. tempsum +=colorgreen+colorblue+colorred;
  384. }
  385. if(tempsum<sum)
  386. {  //更新差值
  387. sum = tempsum;
  388. //更改特征坐标点
  389. ImPoint->x = j;
  390. ImPoint->y = i;
  391. }
  392. }
  393. if(sum <THRESHOLD){//找到满足条件的区域
  394. //下面的代码把找到的区域的边框设置成为白色
  395. for(i =-RADIUS;i<=RADIUS;i++)
  396. {
  397. lOffset = this->PixelOffset(ImPoint->y-RADIUS,ImPoint->x+i,wBytesPerLine);
  398. *(lpData+lOffset++) = 255;
  399. *(lpData+lOffset++) = 255;
  400. *(lpData+lOffset++) = 255;
  401. }
  402. for(i =-RADIUS;i<=RADIUS;i++)
  403. {
  404. lOffset = this->PixelOffset(ImPoint->y+RADIUS,ImPoint->x+i,wBytesPerLine);
  405. *(lpData+lOffset++) = 255;
  406. *(lpData+lOffset++) = 255;
  407. *(lpData+lOffset++) = 255;
  408. }
  409. for(i =-RADIUS;i<=RADIUS;i++)
  410. {
  411. lOffset = this->PixelOffset(ImPoint->y+i,ImPoint->x+RADIUS,wBytesPerLine);
  412. *(lpData+lOffset++) = 255;
  413. *(lpData+lOffset++) = 255;
  414. *(lpData+lOffset++) = 255;
  415. }
  416. for(i =-RADIUS;i<=RADIUS;i++)
  417. {
  418. lOffset = this->PixelOffset(ImPoint->y+i,ImPoint->x-RADIUS,wBytesPerLine);
  419. *(lpData+lOffset++) = 255;
  420. *(lpData+lOffset++) = 255;
  421. *(lpData+lOffset++) = 255;
  422. }
  423. GlobalUnlock(hDIB);
  424. return true;
  425. }
  426. else AfxMessageBox("Can't find the corresponding point!");
  427. GlobalUnlock(hDIB);
  428. return false;
  429. }
  430. //比较两张图片的相似度
  431. BOOL DIB::IsScaterPoint(int x, int y, int width, int height, LPBYTE lpData,WORD wBytesPerLine,  int threshold,bool lab[m_HEIGHT][m_WIDTH])
  432. {
  433. long lOffset;
  434. //得到数据的偏移
  435. lOffset = this->PixelOffset(y,x,wBytesPerLine);
  436. //判断该点是否为白色以及是否计算过了
  437. if(*(lpData+lOffset) == 255 && lab[y][x] == false)
  438. {
  439. //链长度加一
  440. this->lenth++;
  441. //更改标志位
  442. lab[y][x] = true;
  443. //如果链长度达到临界值则返回真
  444. if(this->lenth >= threshold)
  445. return true;
  446. //对右边点的边界判断以及标志位判断
  447. if(x+1<width && lab[y][x+1] == false)
  448. {
  449. //递归调用本函数,对右边的点进行判断
  450. IsScaterPoint(x+1,y,width,height,lpData,wBytesPerLine,threshold,lab);
  451. if(this->lenth>=threshold)
  452. return true;
  453. }
  454. //处理左边的点
  455. if(x-1>=0 && lab[y][x-1] == false)
  456. {
  457. (IsScaterPoint(x-1,y,width,height,lpData,wBytesPerLine,threshold,lab));
  458. if(this->lenth>=threshold)
  459. return true;
  460. }
  461. //处理上面的点
  462. if(y-1>=0 && lab[y-1][x]==false)
  463. {
  464. (IsScaterPoint(x,y-1,width,height,lpData,wBytesPerLine,threshold,lab));
  465. if(this->lenth>=threshold)
  466. return true;
  467. }
  468. //处理下面的点
  469. if(y+1<height && lab[y+1][x]==false)
  470. { (IsScaterPoint(x,y+1,width,height,lpData,wBytesPerLine,threshold,lab));
  471. if(this->lenth>=threshold)
  472. return true;
  473. }
  474. //处理右下的点
  475. if(y+1<height  && x+1 <width && lab[y+1][x+1]==false)
  476. { (IsScaterPoint(x+1,y+1,width,height,lpData,wBytesPerLine,threshold,lab));
  477. if(this->lenth>=threshold)
  478. return true;
  479. }
  480. //处理左下的点
  481. if(y+1<height && x-1 >=0 && lab[y+1][x-1]==false)
  482. { (IsScaterPoint(x-1,y+1,width,height,lpData,wBytesPerLine,threshold,lab));
  483. if(this->lenth>=threshold)
  484. return true;
  485. }
  486. //处理左上的点
  487. if(y-1>=0 && x-1 >=0 &&lab[y-1][x-1]==false)
  488. { (IsScaterPoint(x-1,y-1,width,height,lpData,wBytesPerLine,threshold,lab));
  489. if(this->lenth>=threshold)
  490. return true;
  491. }
  492. //处理右上的点
  493. if(y-1<height && x+1<width && lab[y+1][x]==false)
  494. { (IsScaterPoint(x+1,y-1,width,height,lpData,wBytesPerLine,threshold,lab));
  495. if(this->lenth>=threshold)
  496. return true;
  497. }
  498. }
  499. //如果递归结束,长度达不到临界值,返回假
  500. return false;
  501. }
  502. BOOL DIB::LightingCompensate(HANDLE hDIB)
  503. {
  504. if(!hDIB)
  505. return FALSE;
  506. LPBITMAPINFOHEADER lpbi;
  507. int width,height;
  508. LPBYTE lpData;
  509. WORD wBytesPerLine;
  510. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  511. //得到图片宽和高
  512. width = lpbi->biWidth;
  513. height = lpbi->biHeight;
  514. //得到图片数据区
  515. lpData = this->FindDIBBits(hDIB);
  516. //得到图片每行的象素所占字节个数
  517. wBytesPerLine = this->BytePerLine(hDIB);
  518. //比例系数
  519. const float thresholdco = 0.05;
  520. //象素个数的临界常数
  521. const int thresholdnum = 100;
  522. //灰度级数组
  523. int histogram[256];
  524. for(int i =0;i<256;i++)
  525. histogram[i] = 0;
  526. //对于过于小的图片的判断
  527. if(width*height*thresholdco < thresholdnum)
  528. return false;
  529. int colorr,colorg,colorb;
  530. long lOffset;
  531. //考察整个图片
  532. for( i=0;i<height;i++)
  533. for(int j=0;j<width;j++)
  534. {
  535. //得到象素数据的偏移
  536. lOffset = this->PixelOffset(i,j,wBytesPerLine);
  537. //得到rgb值
  538. colorb = *(lpData+lOffset++);
  539. colorg = *(lpData+lOffset++);
  540. colorr = *(lpData+lOffset++);
  541. //计算灰度值
  542. int gray = (colorr * 299 + colorg * 587 + colorb * 114)/1000;
  543. histogram[gray]++;
  544. }
  545. int calnum =0;
  546. int total = width*height;
  547. int num;
  548. //下面的循环得到满足系数thresholdco的临界灰度级
  549. for(i =0;i<256;i++)
  550. {
  551. if((float)calnum/total < thresholdco)
  552. {
  553. calnum+= histogram[255-i];
  554. num = i;
  555. }
  556. else
  557. break;
  558. }
  559. int averagegray = 0;
  560. calnum =0;
  561. //得到满足条件的象素总的灰度值
  562. for(i = 255;i>=255-num;i--)
  563. {
  564. averagegray += histogram[i]*i;
  565. calnum += histogram[i];
  566. }
  567. averagegray /=calnum;
  568. //得到光线补偿的系数
  569. float co = 255.0/(float)averagegray;
  570. //下面的循环对图象进行光线补偿
  571. for(i =0;i<height;i++)
  572. for(int j=0;j<width;j++)
  573. {
  574. //得到数据便宜
  575. lOffset = this->PixelOffset(i,j,wBytesPerLine);
  576. //得到蓝色分量
  577. colorb = *(lpData+lOffset);
  578. //调整
  579. colorb *=co;
  580. //临界判断
  581. if(colorb >255)
  582. colorb = 255;
  583. //保存
  584. *(lpData+lOffset) = colorb;
  585. //绿色分量
  586. colorb = *(lpData+lOffset+1);
  587. colorb *=co;
  588. if(colorb >255)
  589. colorb = 255;
  590. *(lpData+lOffset+1) = colorb;
  591. //红色分量
  592. colorb = *(lpData+lOffset+2);
  593. colorb *=co;
  594. if(colorb >255)
  595. colorb = 255;
  596. *(lpData+lOffset+2) = colorb;
  597. }
  598. return TRUE;
  599. }
  600. BOOL DIB::FaceModeling(int Cr,int Cb)
  601. {
  602. //Cb的系数常量
  603. const float cx = 114.38;
  604. //cr的系数常量
  605. const float cy = 160.02;
  606. //角度常量
  607. const float theta = 2.53;
  608. //x轴线和y轴线的两个常量
  609. const float ecx = 1.60;
  610. const float ecy = 2.41;
  611. //长轴
  612. const float a = 25.39;
  613. //短轴
  614. const float b = 14.03;
  615. //相似度常量
  616. const float judge = 0.5;
  617. //计算得到x轴数值
  618. float  x = cos(theta)*(Cb-cx)+sin(theta)*(Cr-cy);
  619. //y轴数值
  620. float  y = -sin(theta)*(Cb -cx)+cos(theta)*(Cr-cy);
  621. //计算离心率
  622. float temp = pow(x-ecx,2)/pow(a,2)+pow(y-ecy,2)/pow(b,2);
  623. //如果满足要求返回真,否则假
  624. if(fabs(temp-1.0)<judge)
  625. return TRUE;
  626. else
  627. return FALSE;
  628. }
  629. LPBYTE DIB::YcctoRgb(LPBYTE lpYcc,WORD wBytesPerLine,int height,int width)
  630. {
  631. LPBYTE lpRGB;
  632. //申请内存
  633. lpRGB = new BYTE[wBytesPerLine*height];
  634. //检查内容分配
  635. if(lpRGB == NULL)
  636. {
  637. AfxMessageBox("not enought memory");
  638. return NULL;
  639. }
  640. long lOffset;
  641. //下面的循环实现从ycc到rgb的转换
  642. for(int i=0;i<height;i++)
  643. for(int j=0;j<width;j++)
  644. {
  645. //得到数据便宜
  646. lOffset = PixelOffset(i,j,wBytesPerLine);
  647. //得到y,Cr,Cb的数值
  648. int Y = *(lpYcc+lOffset);
  649. int Cr = *(lpYcc+lOffset+1);
  650. int Cb = *(lpYcc+lOffset+2);
  651. //利用公式进行计算,并把结果保存到动态数组里面
  652. *(lpRGB+lOffset+2) = (1164*(Y-16)+1596*(Cr-128))/1000;
  653. *(lpRGB+lOffset+1) = (1164*(Y-16) - 813*(Cr-128) - 392*(Cb-128))/1000;
  654. *(lpRGB+lOffset)   = (1164*(Y-16) +2017*(Cb-128))/1000;
  655. }
  656. return lpRGB;
  657. }
  658. int DIB::_Cb(int Y)
  659. {
  660. int Cb;
  661. //如果亮度很小的情况
  662. if(Y<Kl)
  663. Cb = 108 + ((Kl-Y)*10)/(Kl-Ymin);
  664. //亮度很大的情况
  665. else if(Y>Kh)
  666. Cb = 108 + ((Y-Kh)*10)/(Ymax - Kh);
  667. else 
  668. Cb = -1;
  669. return Cb;
  670. }
  671. int DIB::_Cr(int Y)
  672. {
  673. int Cr;
  674. //亮度很小的情况
  675. if(Y<Kl)
  676. Cr = 154 - ((Kl-Y)*10)/(Kl-Ymin);
  677. //亮度很大的情况
  678. else if(Y>Kh)
  679. Cr = 154 - ((Y-Kh)*22)/(Ymax - Kh);
  680. else
  681. Cr = -1;
  682. return Cr;
  683. }
  684. int DIB::_WCr(int Y)
  685. {
  686. int WCr;
  687. if(Y<Kl)
  688. //亮度很小的情况
  689. WCr = WLcr + ((Y-Ymin)*(Wcr-WLcr))/(Kl-Ymin);
  690. else if(Y>Kh)
  691. //亮度很大的情况
  692. WCr = WHcr + ((Ymax-Y)*(Wcr-WHcr))/(Ymax-Kh);
  693. else WCr = -1;
  694. return WCr;
  695. }
  696. int DIB:: _WCb(int Y)
  697. {
  698. int WCb;
  699. if(Y<Kl)
  700. //亮度很小的情况
  701. WCb = WLcb + ((Y-Ymin)*(Wcb-WLcb))/(Kl-Ymin);
  702. else if(Y>Kh)
  703. //亮度很大的情况
  704. WCb = WHcb + ((Ymax-Y)*(Wcb-WHcb))/(Ymax-Kh);
  705. else WCb = -1;
  706. return WCb;
  707. }
  708. void DIB::YccTransform(LPBYTE lpYcc,WORD wBytesPerLine,int height,int width)
  709. {
  710. int Y,Cr,Cb;
  711. long lOffset;
  712. //下面的循环实现ycc色彩空间的非线性转换
  713. for(int i=0;i<height;i++)
  714. for(int j=0;j<width;j++)
  715. {
  716. //得到数据偏移
  717. lOffset = PixelOffset(i,j,wBytesPerLine);
  718. //得到y,Cr,Cb数值
  719. Y = *(lpYcc+lOffset);
  720. Cr = *(lpYcc+lOffset+1);
  721. Cb = *(lpYcc+lOffset+2);
  722. //如果y数值在两个临界值之间,保持不变
  723. if(Y>=Kl && Y<=Kh)
  724. continue;
  725. //调用非线性转换函数调整Cr,Cb的数值
  726. Cr = (Cr-_Cr(Y))*(Wcr/_WCr(Y))+_Cr(Kh);
  727. Cb = (Cb-_Cb(Y))*(Wcb/_WCb(Y))+_Cb(Kh);
  728. *(lpYcc+lOffset+1) = Cr;
  729. *(lpYcc+lOffset+2) = Cb;
  730. }
  731. }
  732. void DIB::faceear(LPBYTE lpYcc, WORD wBytesPerLine, int height,int width, bool flag[ImgRange][ImgRange])
  733. {
  734. //初始化标志位
  735. for (int i=0; i<ImgRange; i++)
  736. for (int j=0; j<ImgRange; j++)
  737. {
  738. flag[i][j] = false;
  739. }
  740. long lOffset;
  741. int Cr;
  742. int Cb;
  743. for (i=0; i<height; i++)
  744. for (int j=0; j<width; j++)
  745. {
  746. //得到偏移
  747. lOffset = PixelOffset(i,j,wBytesPerLine);
  748. //得到Cr,Cb数值
  749. Cr = *(lpYcc+lOffset+1);
  750. Cb = *(lpYcc+lOffset+2);
  751. //人脸颜色建模
  752. if(FaceModeling(Cr,Cb))
  753. {
  754. //修改标志位
  755. flag[i][j] = true;
  756. }
  757. }
  758. }
  759. void  DIB::FaceLocate(HANDLE hDIB, CRect faceLocation[10], int &faceNum)
  760. {
  761. HANDLE hDIBTemp;
  762. //保存当前数据
  763. hDIBTemp = this->CopyHandle(hDIB);
  764. LPBITMAPINFOHEADER lpbi;
  765. LPBYTE lpData;
  766. WORD wBytesPerLine;
  767. int height;
  768. int width;
  769. long lOffset;
  770. //得到图象的基本信息
  771. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  772. height = lpbi->biHeight;
  773. width  = lpbi->biWidth;
  774. lpData = FindDIBBits(hDIB);
  775. wBytesPerLine = BytePerLine(hDIB);
  776. //人脸数目初始化为0
  777. faceNum =0;
  778. for(int k=0; k<10; k++)
  779. {
  780. //初始化区域
  781. faceLocation[k].bottom = -1;
  782. faceLocation[k].top = height;
  783. faceLocation[k].right = -1;
  784. faceLocation[k].left = width;
  785. }
  786. for(int i=0; i<height; i++)
  787. for (int j=0; j<width; j++)
  788. {
  789. //偏移
  790. lOffset = PixelOffset(i,j,wBytesPerLine);
  791. int num;
  792. //当前点的数值
  793. num = *(lpData + lOffset);
  794. if (num !=0)//不是黑色
  795. {
  796. //递归计算
  797. RecursiveLocateRect(lpData, wBytesPerLine, i, j, num, faceLocation[faceNum]);
  798. faceNum++;
  799. }
  800. }
  801. GlobalUnlock(hDIB);
  802. GlobalFree(hDIB);
  803. //数值还原
  804. hDIB = this->CopyHandle(hDIBTemp);
  805. lpData = FindDIBBits(hDIB);
  806. wBytesPerLine = BytePerLine(hDIB);
  807. for (i=0; i<faceNum; i++)
  808. for (int j=faceLocation[i].top; j<faceLocation[i].bottom; j++)
  809. {
  810. //把得到的人脸区域用绿色矩形标注,处理竖直的两条边
  811. lOffset = this->PixelOffset(j, faceLocation[i].left, wBytesPerLine);
  812. *(lpData + lOffset++) = 0;
  813. *(lpData + lOffset++) = 255;
  814. *(lpData + lOffset++) = 0;
  815. lOffset = this->PixelOffset(j, faceLocation[i].right, wBytesPerLine);
  816. *(lpData + lOffset++) = 0;
  817. *(lpData + lOffset++) = 255;
  818. *(lpData + lOffset++) = 0;
  819. }
  820. for (i=0; i<faceNum; i++)
  821. for (int j=faceLocation[i].left; j<faceLocation[i].right; j++)
  822. {
  823. //处理水平的两天矩形边
  824. lOffset = this->PixelOffset(faceLocation[i].top, j, wBytesPerLine);
  825. *(lpData + lOffset++) = 0;
  826. *(lpData + lOffset++) = 255;
  827. *(lpData + lOffset++) = 0;
  828. lOffset = this->PixelOffset(faceLocation[i].bottom, j, wBytesPerLine);
  829. *(lpData + lOffset++) = 0;
  830. *(lpData + lOffset++) = 255;
  831. *(lpData + lOffset++) = 0;
  832. }
  833. GlobalFree(hDIBTemp);
  834. GlobalUnlock(hDIB);
  835. }
  836. void DIB::RecursiveLocateRect(LPBYTE lpData,WORD wBytesPerLine, int y, int x, int num, CRect &faceRect)
  837. {
  838. long lOffset;
  839. //得到偏移
  840. lOffset = PixelOffset(y,x,wBytesPerLine);
  841. //数值判断
  842. if(*(lpData + lOffset) == num)
  843. {
  844. //更改颜色为黑色
  845. *(lpData + lOffset++) = 0;
  846. *(lpData + lOffset++) = 0;
  847. *(lpData + lOffset++) = 0;
  848. //修改矩形的上下左右四个点位置
  849. if(faceRect.bottom < y)
  850. {
  851. faceRect.bottom = y;
  852. }
  853. if(faceRect.top > y)
  854. {
  855. faceRect.top = y;
  856. }
  857. if(faceRect.right < x)
  858. {
  859. faceRect.right = x;
  860. }
  861. if(faceRect.left > x)
  862. {
  863. faceRect.left = x;
  864. }
  865. //上下左右调用本函数进行区域判定
  866. RecursiveLocateRect(lpData, wBytesPerLine, y-1, x, num,faceRect);
  867. RecursiveLocateRect(lpData, wBytesPerLine, y+1, x, num, faceRect);
  868. RecursiveLocateRect(lpData, wBytesPerLine, y, x-1, num, faceRect);
  869. RecursiveLocateRect(lpData, wBytesPerLine, y, x+1, num, faceRect);
  870. }
  871. }
  872. void DIB::EyeMapC(LPBYTE lpRgb, const LPBYTE lpYcc,  WORD wBytesPerLine, CRect faceLocation)
  873. {
  874. long lOffset;
  875. int cr;
  876. int cb;
  877. //根据传进来的矩形区域进行眼睛的色度匹配
  878. for(int i=faceLocation.top; i<=faceLocation.bottom; i++)
  879. for (int j=faceLocation.left; j<=faceLocation.right; j++)
  880. {
  881. //得到Cr,Cb数值
  882. lOffset = PixelOffset(i, j, wBytesPerLine);
  883. cr = *(lpYcc + lOffset +1);
  884. cb = *(lpYcc + lOffset +2);
  885. //标志
  886. bool lab;
  887. //判断Cb分量的数值,并修改标志
  888. int cmap = cb -116 ;
  889. if(cmap >-1 && cmap <4)
  890. lab = true;
  891. else
  892. lab = false;
  893. //判断Cr分量的数值,并修改标志
  894.  cmap =  cr- 144  ;
  895. if(cmap <=-2 || cmap>= 2)
  896. {
  897. lab = false;
  898. }
  899. //根据标志设定图像颜色
  900. if(lab)
  901. cmap = 255;
  902. else
  903. cmap = 0;
  904. //保存图象颜色
  905. *(lpRgb + lOffset++) = cmap;
  906. *(lpRgb + lOffset++) = cmap;
  907. *(lpRgb + lOffset++) = cmap;
  908. }
  909. }
  910. void DIB::EyeMapb(LPBYTE lpRgb, const LPBYTE lpYcc,  WORD wBytesPerLine, CRect faceLocation)
  911. {
  912. long lOffset;
  913. int cr;
  914. int cb;
  915. for(int i=faceLocation.top; i<=faceLocation.bottom; i++)
  916. for (int j=faceLocation.left; j<=faceLocation.right; j++)
  917. {
  918. lOffset = PixelOffset(i, j, wBytesPerLine);
  919. cb = *(lpYcc + lOffset +2);
  920. *(lpRgb + lOffset++) = cb;
  921. *(lpRgb + lOffset++) = cb;
  922. *(lpRgb + lOffset++) = cb;
  923. }
  924. }
  925. void DIB::EyeMapR(LPBYTE lpRgb, const LPBYTE lpYcc,  WORD wBytesPerLine, CRect faceLocation)
  926. {
  927. long lOffset;
  928. int cr;
  929. int cb;
  930. for(int i=faceLocation.top; i<=faceLocation.bottom; i++)
  931. for (int j=faceLocation.left; j<=faceLocation.right; j++)
  932. {
  933. lOffset = PixelOffset(i, j, wBytesPerLine);
  934. cr = *(lpYcc + lOffset +1);
  935. cb = *(lpYcc + lOffset +2);
  936. *(lpRgb + lOffset++) = cr;
  937. *(lpRgb + lOffset++) = cr;
  938. *(lpRgb + lOffset++) = cr;
  939. }
  940. }
  941. void DIB::ErasionFalseArea(HANDLE hDIB)
  942. {
  943. int PixelNum[255];
  944. LPBITMAPINFOHEADER lpbi;
  945. int width;
  946. int height;
  947. LPBYTE lpData;
  948. WORD wBytesPerLine;
  949. long lOffset;
  950. //得到长宽信息
  951. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  952. height = lpbi->biHeight;
  953. width  = lpbi->biWidth;
  954. //得到数据区指针和每行字节数
  955. lpData = FindDIBBits(hDIB);
  956. wBytesPerLine = BytePerLine(hDIB);
  957. //初始化象素累计数组
  958. for (int i=0; i<255; i++)
  959. {
  960. PixelNum[i] = 0;
  961. }
  962. int calNum =1;
  963. for (i=0; i<height; i++)
  964. for (int j=0; j<width; j++)
  965. {
  966. lOffset = PixelOffset(i,j,wBytesPerLine);
  967. //如果象素为白色
  968. if (*(lpData + lOffset)==255)
  969. {
  970. //递归统计该区域连续的白色点象素点个数
  971. RecursiveCal(lpData, i,j,wBytesPerLine, PixelNum[calNum],calNum);
  972. calNum++;
  973. }
  974. }
  975. for (i=0; i<calNum; i++)
  976. {
  977. //如果象素点个数小于一定数目则把这个标志设置为0
  978. if (PixelNum[i] < AREAPIXEL)
  979. {
  980. PixelNum[i] = 0;
  981. }
  982. }
  983. //下面的循环根据标志数组来最终设定图象的颜色
  984. for(i=0; i<height; i++)
  985. for (int j=0; j<width; j++)
  986. {
  987. lOffset = PixelOffset( i,j,wBytesPerLine);
  988. int num = *(lpData + lOffset);
  989. //如果当前点不是黑色点
  990. if(num != 0)
  991. {
  992. //如果标志数组为0,则设置为黑色
  993. if(PixelNum[num] == 0)
  994. {
  995. *(lpData+lOffset++) =0;
  996. *(lpData+lOffset++) =0;
  997. *(lpData+lOffset++) =0;
  998. }
  999. //否则设置为白色
  1000. else
  1001. {
  1002. *(lpData+lOffset++) =255;
  1003. *(lpData+lOffset++) =255;
  1004. *(lpData+lOffset++) =255;
  1005. }
  1006. }
  1007. }
  1008. }
  1009. void DIB::RecursiveCal(LPBYTE lpData, int y, int x, WORD wBytesPerLine, int &pixelNum, int num)
  1010. {
  1011. long lOffset;
  1012. lOffset = PixelOffset(y,x,wBytesPerLine);
  1013. //如果当前点为白色点
  1014. if(*(lpData+lOffset) == 255)
  1015. {
  1016. //把当前点大小设置成为序号值
  1017. *(lpData+lOffset++) = num;
  1018. *(lpData+lOffset++) = num;
  1019. *(lpData+lOffset++) = num;
  1020. //象素个数加一
  1021. pixelNum++;
  1022. int tempx;
  1023. int tempy;
  1024. //递归当前点上面的点
  1025. tempy = y-1;
  1026. tempx = x;
  1027. RecursiveCal(lpData,tempy,tempx,wBytesPerLine,pixelNum,num);
  1028. //下面的点
  1029. tempy = y+1;
  1030. tempx = x;
  1031. RecursiveCal(lpData,tempy,tempx,wBytesPerLine,pixelNum,num);
  1032. //左边的点
  1033. tempy = y;
  1034. tempx = x-1;
  1035. RecursiveCal(lpData,tempy,tempx,wBytesPerLine,pixelNum,num);
  1036. //右边的点
  1037. tempy = y;
  1038. tempx = x+1;
  1039. RecursiveCal(lpData,tempy,tempx,wBytesPerLine,pixelNum,num);
  1040. }
  1041. }
  1042. void DIB::eyeMap(LPBYTE lpResult, bool eyemapc[][ImgRange], bool eyemapl[][ImgRange], bool lab[][ImgRange], WORD wBytesPerLine, CRect faceLocation)
  1043. {
  1044. long lOffset;
  1045. //根据得到的亮度和色度信息对眼睛进行综合匹配
  1046. for(int i=faceLocation.top; i<=faceLocation.bottom; i++)
  1047. for (int j=faceLocation.left; j<faceLocation.right; j++)
  1048. {
  1049. lOffset = PixelOffset(i, j, wBytesPerLine);
  1050. //如果当前点的亮度和色度匹配都为真,并且在人脸区域内
  1051. //就设置为白色,否则设置为黑色
  1052. if((eyemapc[i][j]) && (eyemapl[i][j]) && lab[i][j])
  1053. {
  1054. *(lpResult + lOffset++) = 255;
  1055. *(lpResult + lOffset++) = 255;
  1056. *(lpResult + lOffset++) = 255;
  1057. }
  1058. else
  1059. {
  1060. *(lpResult + lOffset++) = 0;
  1061. *(lpResult + lOffset++) = 0;
  1062. *(lpResult + lOffset++) = 0;
  1063. }
  1064. }
  1065. }
  1066. void DIB::EyeMapL(LPBYTE lpRgb, WORD wBytesPerLine, CRect faceLocation)
  1067. {
  1068. int r;
  1069. int g;
  1070. int b;
  1071. int gray ;
  1072. long lOffset;
  1073. //下面的循环实现眼睛的亮度匹配
  1074. for (int i=faceLocation.top; i<=faceLocation.bottom; i++)
  1075. for (int j=faceLocation.left; j<=faceLocation.right; j++)
  1076. {
  1077. lOffset = PixelOffset(i, j, wBytesPerLine);
  1078. //得到rgb值
  1079. b = *(lpRgb + lOffset);
  1080. g = *(lpRgb + lOffset+1);
  1081. r = *(lpRgb + lOffset+2);
  1082. //计算得到灰度
  1083. gray = (r*10+g*30+b*60)/100;
  1084. //根据眼睛的亮度区域来设定图象的数值
  1085. if(100<gray && 125>gray)
  1086. gray =255;
  1087. else
  1088. gray = 0;
  1089. *(lpRgb + lOffset++) = gray;
  1090. *(lpRgb + lOffset++) = gray;
  1091. *(lpRgb + lOffset++) = gray;
  1092. }
  1093. }
  1094. void  DIB::RgbtoYcb(HANDLE hDIB, LPBYTE lpYcb)
  1095. {
  1096. LPBITMAPINFOHEADER lpbi;
  1097. int width,height;
  1098. WORD wBytesPerLine;
  1099. LPBYTE lpData;
  1100. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  1101. //得到图象的基本信息
  1102. width = lpbi->biWidth;
  1103. height = lpbi->biHeight;
  1104. lpData = FindDIBBits(hDIB);
  1105. wBytesPerLine = BytePerLine(hDIB);
  1106. long lOffset;
  1107. //下面的循环实现从rgb到ycc的转化
  1108. for(int i=0;i<height;i++)
  1109. for(int j=0;j<width;j++)
  1110. {
  1111. lOffset = PixelOffset(i,j,wBytesPerLine);
  1112. //得到rgb数值
  1113. int b = *(lpData + lOffset);
  1114. int g = *(lpData + lOffset+1);
  1115. int r = *(lpData + lOffset+2);
  1116. //计算得到y,cr,cb的数值
  1117. int Y = (257*r+504*g+98*b)/1000+16;
  1118. int Cr = (439*r-368*g-71*b)/1000+128;
  1119. int Cb = (-148*r-291*g+439*b)/1000+128;
  1120. //保存计算得到的数值
  1121. *(lpYcb+lOffset++) = Y;
  1122. *(lpYcb+lOffset++) = Cr;
  1123. *(lpYcb+lOffset++) = Cb;
  1124. }
  1125. GlobalUnlock(hDIB);
  1126. }
  1127. void DIB::Erasion(HANDLE hDIB)
  1128. {
  1129. LPBITMAPINFOHEADER lpbi;
  1130. LPBYTE lpData;
  1131. WORD wBytesPerLine;
  1132. long lOffset;
  1133. long lOffsetJudge;
  1134. int height;
  1135. int width;
  1136. //得到基本数据
  1137. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  1138. height = lpbi->biHeight;
  1139. width = lpbi->biWidth;
  1140. wBytesPerLine = BytePerLine(hDIB);
  1141. lpData = FindDIBBits(hDIB);
  1142. HANDLE hTempDIB;
  1143. LPBYTE lpTemp;
  1144. //申请同样大小的内存
  1145. hTempDIB =   GlobalAlloc(GMEM_MOVEABLE,(DWORD)(sizeof(BITMAPINFOHEADER) + wBytesPerLine*height));
  1146. //判断内存情况
  1147. if(!hTempDIB)
  1148. {
  1149. GlobalFree(hTempDIB);
  1150. GlobalFree(hDIB);
  1151. return;
  1152. }
  1153. lpTemp = (LPBYTE)GlobalLock(hTempDIB);
  1154. lpTemp+= sizeof(BITMAPINFOHEADER);
  1155. //下面的循环实现腐蚀功能
  1156. for (int i=1; i<height-1; i++)
  1157. for (int j=1; j<width-1; j++)
  1158. {
  1159. lOffset = PixelOffset(i,j,wBytesPerLine);
  1160. //如果为白色点
  1161. if (*(lpData+lOffset) == 255)
  1162. {
  1163. //考察上面的点
  1164. lOffsetJudge = PixelOffset(i-1, j, wBytesPerLine);
  1165. //如果是黑色就把原来的点设置为黑色,并接着循环
  1166. if (*(lpData + lOffsetJudge) ==0)
  1167. {
  1168. *(lpTemp + lOffset++) = 0;
  1169. *(lpTemp + lOffset++) = 0;
  1170. *(lpTemp + lOffset++) = 0;
  1171. continue;
  1172. }
  1173. //考察下面的点
  1174. lOffsetJudge = PixelOffset(i+1, j, wBytesPerLine);
  1175. if (*(lpData + lOffsetJudge) ==0)
  1176. {
  1177. *(lpTemp + lOffset++) = 0;
  1178. *(lpTemp + lOffset++) = 0;
  1179. *(lpTemp + lOffset++) = 0;
  1180. continue;
  1181. }
  1182. //左面的点
  1183. lOffsetJudge = PixelOffset(i, j-1, wBytesPerLine);
  1184. if (*(lpData + lOffsetJudge) ==0)
  1185. {
  1186. *(lpTemp + lOffset++) = 0;
  1187. *(lpTemp + lOffset++) = 0;
  1188. *(lpTemp + lOffset++) = 0;
  1189. continue;
  1190. }
  1191. //右面的点
  1192. lOffsetJudge = PixelOffset(i, j+1, wBytesPerLine);
  1193. if (*(lpData + lOffsetJudge) ==0)
  1194. {
  1195. *(lpTemp + lOffset++) = 0;
  1196. *(lpTemp + lOffset++) = 0;
  1197. *(lpTemp + lOffset++) = 0;
  1198. continue;
  1199. }
  1200. //如果上下左右四个点都是白色,则设置为白色
  1201. lOffset = this->PixelOffset(i, j, wBytesPerLine);
  1202. *(lpTemp + lOffset)   = 255;
  1203. *(lpTemp + lOffset+1) = 255;
  1204. *(lpTemp + lOffset+2) = 255;
  1205. }
  1206. //如果当前点为黑色,则在暂时的目标区域中设置为黑色
  1207. else
  1208. {
  1209. *(lpTemp + lOffset)   = 0;
  1210. *(lpTemp + lOffset+1) = 0;
  1211. *(lpTemp + lOffset+2) = 0;
  1212. }
  1213. }
  1214. //把图象周边的点全部设置为黑色
  1215. for(i=0; i<height; i++)
  1216. {
  1217. lOffset = PixelOffset(i, 0, wBytesPerLine);
  1218. *(lpTemp + lOffset)   = 0;
  1219. *(lpTemp + lOffset+1) = 0;
  1220. *(lpTemp + lOffset+2) = 0;
  1221. }
  1222. for(i=0; i<height; i++)
  1223. {
  1224. lOffset = PixelOffset(i, width-1, wBytesPerLine);
  1225. *(lpTemp + lOffset)   = 0;
  1226. *(lpTemp + lOffset+1) = 0;
  1227. *(lpTemp + lOffset+2) = 0;
  1228. }
  1229. for (i=0; i<width; i++)
  1230. {
  1231. lOffset = PixelOffset(0, i, wBytesPerLine);
  1232. *(lpTemp + lOffset)   = 0;
  1233. *(lpTemp + lOffset+1) = 0;
  1234. *(lpTemp + lOffset+2) = 0;
  1235. }
  1236. for (i=0; i<width; i++)
  1237. {
  1238. lOffset = PixelOffset(height-1, i, wBytesPerLine);
  1239. *(lpTemp + lOffset)   = 0;
  1240. *(lpTemp + lOffset+1) = 0;
  1241. *(lpTemp + lOffset+2) = 0;
  1242. }
  1243. //把暂时区域的数值拷贝到原来的句柄下面
  1244. memcpy(lpData,lpTemp,wBytesPerLine*height);
  1245. GlobalUnlock(hDIB);
  1246. GlobalUnlock(hTempDIB);
  1247. GlobalFree(hTempDIB);
  1248. }
  1249. void DIB::Erasion2(HANDLE hDIB)
  1250. {
  1251. LPBITMAPINFOHEADER lpbi;
  1252. LPBYTE lpData;
  1253. WORD wBytesPerLine;
  1254. long lOffset;
  1255. long lOffsetJudge;
  1256. int height;
  1257. int width;
  1258. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  1259. height = lpbi->biHeight;
  1260. width = lpbi->biWidth;
  1261. wBytesPerLine = BytePerLine(hDIB);
  1262. lpData = FindDIBBits(hDIB);
  1263. HANDLE hTempDIB;
  1264. LPBYTE lpTemp;
  1265. //申请相同大小的内存
  1266. hTempDIB =   GlobalAlloc(GMEM_MOVEABLE,(DWORD)(sizeof(BITMAPINFOHEADER) + wBytesPerLine*height));
  1267. if(!hTempDIB)
  1268. {
  1269. GlobalFree(hTempDIB);
  1270. GlobalFree(hDIB);
  1271. return;
  1272. }
  1273. lpTemp = (LPBYTE)GlobalLock(hTempDIB);
  1274. lpTemp+= sizeof(BITMAPINFOHEADER);
  1275. //下面的代码实现腐蚀功能
  1276. for (int i=1; i<height-1; i++)
  1277. for (int j=1; j<width-1; j++)
  1278. {
  1279. //如果当前点为白色
  1280. lOffset = PixelOffset(i,j,wBytesPerLine);
  1281. if (*(lpData+lOffset) == 255)
  1282. {
  1283. //判断左边的带你,如果是黑色的就把暂时区域中的对应点设置为黑色
  1284. lOffsetJudge = PixelOffset(i, j-1, wBytesPerLine);
  1285. if (*(lpData + lOffsetJudge) ==0)
  1286. {
  1287. *(lpTemp + lOffset++) = 0;
  1288. *(lpTemp + lOffset++) = 0;
  1289. *(lpTemp + lOffset++) = 0;
  1290. continue;
  1291. }
  1292. //考察右边的点
  1293. lOffsetJudge = PixelOffset(i, j+1, wBytesPerLine);
  1294. if (*(lpData + lOffsetJudge) ==0)
  1295. {
  1296. *(lpTemp + lOffset++) = 0;
  1297. *(lpTemp + lOffset++) = 0;
  1298. *(lpTemp + lOffset++) = 0;
  1299. continue;
  1300. }
  1301. //如果左右两边的点都是白色把点设置为白色
  1302. lOffset = this->PixelOffset(i, j, wBytesPerLine);
  1303. *(lpTemp + lOffset)   = 255;
  1304. *(lpTemp + lOffset+1) = 255;
  1305. *(lpTemp + lOffset+2) = 255;
  1306. }
  1307. //如果当前点为黑色,则把暂时区域中对应点设置为黑色
  1308. else
  1309. {
  1310. *(lpTemp + lOffset)   = 0;
  1311. *(lpTemp + lOffset+1) = 0;
  1312. *(lpTemp + lOffset+2) = 0;
  1313. }
  1314. }
  1315. //把图象四周的点设置为黑色
  1316. for(i=0; i<height; i++)
  1317. {
  1318. lOffset = PixelOffset(i, 0, wBytesPerLine);
  1319. *(lpTemp + lOffset)   = 0;
  1320. *(lpTemp + lOffset+1) = 0;
  1321. *(lpTemp + lOffset+2) = 0;
  1322. }
  1323. for(i=0; i<height; i++)
  1324. {
  1325. lOffset = PixelOffset(i, width-1, wBytesPerLine);
  1326. *(lpTemp + lOffset)   = 0;
  1327. *(lpTemp + lOffset+1) = 0;
  1328. *(lpTemp + lOffset+2) = 0;
  1329. }
  1330. for (i=0; i<width; i++)
  1331. {
  1332. lOffset = PixelOffset(0, i, wBytesPerLine);
  1333. *(lpTemp + lOffset)   = 0;
  1334. *(lpTemp + lOffset+1) = 0;
  1335. *(lpTemp + lOffset+2) = 0;
  1336. }
  1337. for (i=0; i<width; i++)
  1338. {
  1339. lOffset = PixelOffset(height-1, i, wBytesPerLine);
  1340. *(lpTemp + lOffset)   = 0;
  1341. *(lpTemp + lOffset+1) = 0;
  1342. *(lpTemp + lOffset+2) = 0;
  1343. }
  1344. //把暂时区域的点拷贝到原句柄下
  1345. memcpy(lpData,lpTemp,wBytesPerLine*height);
  1346. GlobalUnlock(hDIB);
  1347. GlobalUnlock(hTempDIB);
  1348. GlobalFree(hTempDIB);
  1349. }
  1350. void DIB::Dilation(HANDLE hDIB)
  1351. {
  1352. LPBITMAPINFOHEADER lpbi;
  1353. int height;
  1354. int width;
  1355. WORD wBytesPerLine;
  1356. LPBYTE lpData;
  1357. LPBYTE lpTemp;
  1358. long lOffset;
  1359. //得到图象的基本信息
  1360. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  1361. height = lpbi->biHeight;
  1362. width = lpbi->biWidth;
  1363. wBytesPerLine = this->BytePerLine(hDIB);
  1364. lpData = this->FindDIBBits(hDIB);
  1365. //申请一块和数据区大小相同的内存
  1366. lpTemp = (LPBYTE) new BYTE[wBytesPerLine * height];
  1367. long lOffsetJudge;
  1368. for (int i=1; i<height-1; i++)
  1369. for (int j=1; j<width-1; j++)
  1370. {
  1371. lOffset = this->PixelOffset(i, j, wBytesPerLine);
  1372. //如果当前点为白色,接着循环
  1373. if(*(lpData + lOffset) == 255)
  1374. {
  1375. *(lpTemp + lOffset++) = 255;
  1376. *(lpTemp + lOffset++) = 255;
  1377. *(lpTemp + lOffset++) = 255;
  1378. continue;
  1379. }
  1380. //否则考察上下左右四个点
  1381. else
  1382. {
  1383. lOffsetJudge = this->PixelOffset(i-1, j, wBytesPerLine);
  1384. //如果上面的点为白色
  1385. if(*(lpData + lOffsetJudge) == 255)
  1386. { //设置为白色,并继续循环
  1387. *(lpTemp + lOffset++) = 255;
  1388. *(lpTemp + lOffset++) = 255;
  1389. *(lpTemp + lOffset++) = 255;
  1390. continue;
  1391. }
  1392. //考察下面的点
  1393. lOffsetJudge = this->PixelOffset(i+1,j, wBytesPerLine);
  1394. if(*(lpData + lOffsetJudge) == 255)
  1395. {
  1396. *(lpTemp + lOffset++) = 255;
  1397. *(lpTemp + lOffset++) = 255;
  1398. *(lpTemp + lOffset++) = 255;
  1399. continue;
  1400. }
  1401. //考察左边的点
  1402. lOffsetJudge = this->PixelOffset(i,j-1, wBytesPerLine);
  1403. if(*(lpData + lOffsetJudge) == 255)
  1404. {
  1405. *(lpTemp + lOffset++) = 255;
  1406. *(lpTemp + lOffset++) = 255;
  1407. *(lpTemp + lOffset++) = 255;
  1408. continue;
  1409. }
  1410. //考察右边的点
  1411. lOffsetJudge = this->PixelOffset(i,j+1, wBytesPerLine);
  1412. if(*(lpData + lOffsetJudge) == 255)
  1413. {
  1414. *(lpTemp + lOffset++) = 255;
  1415. *(lpTemp + lOffset++) = 255;
  1416. *(lpTemp + lOffset++) = 255;
  1417. continue;
  1418. }
  1419. //如果上下左右都是黑色点,则把暂时区域的点设置为黑色
  1420. lOffset = this->PixelOffset(i,j,wBytesPerLine);
  1421. *(lpTemp + lOffset++) = 0;
  1422. *(lpTemp + lOffset++) = 0;
  1423. *(lpTemp + lOffset++) = 0;
  1424. }
  1425. }
  1426. //处理图象四周的点,设置为黑色
  1427. for(i=0; i<height; i++)
  1428. {
  1429. lOffset = this->PixelOffset(i, 0, wBytesPerLine);
  1430. {
  1431. *(lpTemp + lOffset++) = 0;
  1432. *(lpTemp + lOffset++) = 0;
  1433. *(lpTemp + lOffset++) = 0;
  1434. }
  1435. }
  1436. for(i=0; i<height; i++)
  1437. {
  1438. lOffset = this->PixelOffset(i, width-1, wBytesPerLine);
  1439. {
  1440. *(lpTemp + lOffset++) = 0;
  1441. *(lpTemp + lOffset++) = 0;
  1442. *(lpTemp + lOffset++) = 0;
  1443. }
  1444. }
  1445. for(i=0; i<width; i++)
  1446. {
  1447. lOffset = this->PixelOffset(0, i, wBytesPerLine);
  1448. {
  1449. *(lpTemp + lOffset++) = 0;
  1450. *(lpTemp + lOffset++) = 0;
  1451. *(lpTemp + lOffset++) = 0;
  1452. }
  1453. }
  1454. for(i=0; i<width; i++)
  1455. {
  1456. lOffset = this->PixelOffset(height-1, i, wBytesPerLine);
  1457. {
  1458. *(lpTemp + lOffset++) = 0;
  1459. *(lpTemp + lOffset++) = 0;
  1460. *(lpTemp + lOffset++) = 0;
  1461. }
  1462. }
  1463. //把暂时区域的点拷贝到原句柄区域下面
  1464. memcpy(lpData, lpTemp, wBytesPerLine*height);
  1465. delete [] lpTemp;
  1466. GlobalUnlock(hDIB);
  1467. }
  1468. void DIB::DeleteFasleEye(HANDLE hDIB, CRect facelocation)
  1469. {
  1470. LPBYTE lpData;
  1471. LPBITMAPINFOHEADER lpbi;
  1472. int height;
  1473. int width;
  1474. long lOffset;
  1475. WORD wBytesPerLine;
  1476. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  1477. height = lpbi->biHeight;
  1478. width = lpbi->biWidth;
  1479. lpData = this->FindDIBBits(hDIB);
  1480. wBytesPerLine = this->BytePerLine(hDIB);
  1481. for (int i=0; i<height; i++)
  1482. for (int j=0; j<width; j++)
  1483. {
  1484. lOffset = this->PixelOffset(i, j, wBytesPerLine);
  1485. if(*(lpData + lOffset) == 255)
  1486. {
  1487. if(i<(facelocation.bottom+facelocation.top)/2)
  1488. {
  1489. *(lpData + lOffset++) = 0;
  1490. *(lpData + lOffset++) = 0;
  1491. *(lpData + lOffset++) = 0;
  1492. }
  1493. }
  1494. }
  1495. GlobalUnlock(hDIB);
  1496. }
  1497. void DIB::DeleteScatePoint(HANDLE hDIB)
  1498. {
  1499. LPBITMAPINFOHEADER lpbi;
  1500. int height;
  1501. int width;
  1502. LPBYTE lpData;
  1503. WORD wBytesPerLine;
  1504. long lOffset;
  1505. //得到图象的基本信息
  1506. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  1507. height = lpbi->biHeight;
  1508. width  = lpbi->biWidth;
  1509. wBytesPerLine = this->BytePerLine(hDIB);
  1510. lpData = this->FindDIBBits(hDIB);
  1511. for (int i=0; i<height; i++)
  1512. for(int j=0; j<width; j++)
  1513. {
  1514. //得到偏移
  1515. lOffset = this->PixelOffset(i, j, wBytesPerLine);
  1516. //如果当前点为白色点
  1517. if(*(lpData + lOffset) == 255)
  1518. {
  1519. //设定判断数组
  1520. for(int ii = 0;ii<ImgRange;ii++)
  1521. for (int jj=0; jj<ImgRange; jj++)
  1522. this->lab[ii][jj] = false;
  1523. //设定判断长度
  1524. this->lenth=0;
  1525. //判断是否为离散点
  1526. bool judge = this->IsScaterPoint(j, i, width,height,lpData,wBytesPerLine,3,this->lab);
  1527. if(!judge)
  1528. {
  1529. //是离散点则把该点设置为黑色
  1530. *(lpData + lOffset++) = 0;
  1531. *(lpData + lOffset++) = 0;
  1532. *(lpData + lOffset++) = 0;
  1533. }
  1534. }
  1535. }
  1536. GlobalUnlock(hDIB);
  1537. }
  1538. void  DIB::  MouseMap(LPBYTE lpRgb, const LPBYTE lpYcc,  WORD wBytesPerLine, CRect faceLocation)
  1539. {
  1540. //下面的循环在人脸的区域内实现嘴巴的匹配
  1541. for (int i=faceLocation.top; i<faceLocation.bottom; i++)
  1542. for (int j=faceLocation.left; j<faceLocation.right; j++)
  1543. {
  1544. //得到偏移
  1545. long lOffset = this->PixelOffset(i, j, wBytesPerLine);
  1546. //得到cr,cb的数值
  1547. int cr = *(lpYcc+lOffset+1);
  1548. int cb = *(lpYcc+lOffset+2);
  1549. //标志
  1550. bool lab;
  1551. int mapm;
  1552. //根据cr的数值设定标志
  1553. cr = cr-143;
  1554. if(cr <-5 || cr>5)
  1555. {
  1556. cr = 0;
  1557. }
  1558. cr *=cr;
  1559. if(cr>16)
  1560.  lab = true;
  1561. else
  1562. lab = false;
  1563. //根据cb的时值设定标志
  1564. cb= cb-120;
  1565. if(cb<-5 || cb >5)
  1566. {
  1567. cb = 0;
  1568. if(lab = true)
  1569. lab = false;
  1570. }
  1571. //如果cr,cb两项数值都在设定的范围之内,则设定颜色位白色,否则黑色
  1572. if(lab)
  1573. mapm = 255;
  1574. else
  1575. mapm = 0;
  1576.  
  1577. *(lpRgb + lOffset++) = mapm;
  1578. *(lpRgb + lOffset++) = mapm;
  1579. *(lpRgb + lOffset++) = mapm;
  1580. }
  1581. }
  1582. void DIB::MouthCenter(HANDLE hDIB, CRect faceLocation, CPoint &mouthLocation)
  1583. {
  1584. LPBITMAPINFOHEADER lpbi;
  1585. int height;
  1586. int width;
  1587. long lOffset;
  1588. WORD wBytesPerLine;
  1589. LPBYTE lpData;
  1590. //得到图象的基本信息
  1591. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  1592. height = lpbi->biHeight;
  1593. width  = lpbi->biWidth;
  1594. wBytesPerLine = this->BytePerLine(hDIB);
  1595. lpData = this->FindDIBBits(hDIB);
  1596. //下面的三个变量用来累计嘴巴区域的象素的x,y和象素点数
  1597. int xnum = 0 ;
  1598. int ynum = 0 ;
  1599. int count = 0;
  1600. for (int i=faceLocation.top; i<faceLocation.bottom; i++)
  1601. for (int j=faceLocation.left; j<faceLocation.right; j++)
  1602. {
  1603. lOffset = this->PixelOffset(i, j, wBytesPerLine);
  1604. //白色点
  1605. if(*(lpData + lOffset) == 255)
  1606. {
  1607. //x值加
  1608. xnum +=j;
  1609. //y值加
  1610. ynum +=i;
  1611. //点数加
  1612. count++;
  1613. }
  1614. }
  1615. //得到中心点位置
  1616. mouthLocation.x = xnum/count;
  1617. mouthLocation.y = ynum/count;
  1618. //把中心点设置位绿色
  1619. lOffset = this->PixelOffset(mouthLocation.y, mouthLocation.x, wBytesPerLine);
  1620. *(lpData + lOffset++) =0;
  1621. *(lpData + lOffset++) =255;
  1622. *(lpData + lOffset++) =0;
  1623. GlobalUnlock(hDIB);
  1624. }
  1625. void DIB::EyeCenter(HANDLE hDIB, CRect faceLocation, CPoint &eye1, CPoint &eye2)
  1626. {
  1627. LPBITMAPINFOHEADER lpbi;
  1628. LPBYTE lpData;
  1629. long lOffset;
  1630. WORD wBytesPerLine;
  1631. int height;
  1632. int width;
  1633. int pixelnum =0;
  1634. int num =0;
  1635. //得到图象基本信息
  1636. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  1637. height = lpbi->biHeight;
  1638. width  = lpbi->biWidth;
  1639. lpData = this->FindDIBBits(hDIB);
  1640. wBytesPerLine  = this->BytePerLine(hDIB);
  1641. //考察人脸区域
  1642. for(int i=faceLocation.top; i<faceLocation.bottom; i++)
  1643. for (int j=faceLocation.left; j<faceLocation.right; j++)
  1644. {
  1645. lOffset = this->PixelOffset(i, j, wBytesPerLine);
  1646. //白色点
  1647. if(*(lpData + lOffset) == 255)
  1648. //递归统计象素并修改象素值
  1649. this->RecursiveCal(lpData,i,j,wBytesPerLine,pixelnum,++num);
  1650. }
  1651. //初始化眼睛的坐标
  1652. eye1.x =0;
  1653. eye1.y =0;
  1654. eye2.x =0;
  1655. eye2.y =0;
  1656. //初始化象素点个数
  1657. int eye1count=0;
  1658. int eye2count =0;
  1659. for (i=faceLocation.top; i<faceLocation.bottom; i++)
  1660. for (int j=faceLocation.left; j<faceLocation.right; j++)
  1661. {
  1662. lOffset = this->PixelOffset(i, j, wBytesPerLine);
  1663. //如果象素点的数值为1
  1664. if(*(lpData + lOffset) == 1)
  1665. {
  1666. //眼睛1的横坐标和纵坐标加上当前点的坐标值
  1667. eye1.x +=j;
  1668. eye1.y +=i;
  1669. eye1count++;
  1670. //把当前点改成白色
  1671. *(lpData + lOffset++) = 255;
  1672. *(lpData + lOffset++) = 255;
  1673. *(lpData + lOffset++) = 255;
  1674. }
  1675. //如果当前象素的数值为2
  1676. else if(*(lpData + lOffset) == 2)
  1677. {
  1678. //眼睛2的横坐标和纵坐标加上当前点的坐标值
  1679. eye2.x +=j;
  1680. eye2.y +=i;
  1681. //象素点个数加一
  1682. eye2count++;
  1683. //把当前点设置为白色
  1684. *(lpData + lOffset++) = 255;
  1685. *(lpData + lOffset++) = 255;
  1686. *(lpData + lOffset++) = 255;
  1687. }
  1688. }
  1689. //计算眼睛的中心点坐标
  1690. eye1.x /=eye1count;
  1691. eye1.y /=eye1count;
  1692. eye2.x /=eye2count;
  1693. eye2.y /=eye2count;
  1694. //把中心点设置为绿色
  1695. lOffset = this->PixelOffset(eye1.y, eye1.x ,wBytesPerLine);
  1696. *(lpData + lOffset++) = 0;
  1697. *(lpData + lOffset++) = 255;
  1698. *(lpData + lOffset++) = 0;
  1699. lOffset = this->PixelOffset(eye2.y, eye2.x ,wBytesPerLine);
  1700. *(lpData + lOffset++) = 0;
  1701. *(lpData + lOffset++) = 255;
  1702. *(lpData + lOffset++) = 0;
  1703. GlobalUnlock(hDIB);
  1704. }
  1705. void DIB::EllipseFace(HANDLE hDIB, CPoint mouth, CPoint eye1, CPoint eye2)
  1706. {
  1707. LPBYTE lpData;
  1708. LPBITMAPINFOHEADER lpbi;
  1709. int width;
  1710. int height;
  1711. WORD wBytesPerLine;
  1712. long lOffset;
  1713. //得到图象的基本信息
  1714. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  1715. height = lpbi->biHeight;
  1716. width  = lpbi->biWidth;
  1717. lpData = this->FindDIBBits(hDIB);
  1718. wBytesPerLine = this->BytePerLine(hDIB);
  1719. //用dda算法画三角形
  1720. this->DdaLine(mouth,eye1,lpData,wBytesPerLine);
  1721. this->DdaLine(mouth,eye2,lpData,wBytesPerLine);
  1722. this->DdaLine(eye1,eye2,lpData,wBytesPerLine);
  1723. //椭圆的中心点和两个焦点坐标
  1724. int ellipsecenter_x;
  1725. int ellipsecenter_y;
  1726. int ellipseFocusTop_x;
  1727. int ellipseFocusTop_y;
  1728. int ellipseFocusBottom_x;
  1729. int ellipseFocusBottom_y;
  1730. //根据眼睛和嘴巴的坐标计算椭圆的中心点坐标
  1731. ellipsecenter_x = (eye1.x + eye2.x + mouth.x )/3;
  1732. ellipsecenter_y = (eye1.y + eye2.y)/2 -abs(eye2.x - eye1.x)/2;
  1733. //上面的焦点
  1734. ellipseFocusTop_x = ellipsecenter_x;
  1735. ellipseFocusBottom_x = ellipsecenter_x;
  1736. //下面的焦点
  1737. ellipseFocusTop_y =  ellipsecenter_y + (eye1.y +eye2.y)/2 -mouth.y;
  1738. ellipseFocusBottom_y = ellipsecenter_y - ((eye1.y +eye2.y)/2 -mouth.y)+2;
  1739. //长轴
  1740. int a = (eye1.x-eye2.x)*2-2;
  1741. for (int i=0; i<height; i++)
  1742. for (int j=0; j<width; j++)
  1743. {
  1744. //得到一个点到两个焦点的距离和
  1745. int lenth = sqrt(pow(j-ellipseFocusTop_x,2)+pow(i-ellipseFocusTop_y,2))
  1746. +sqrt(pow(j-ellipseFocusBottom_x,2)+ pow(i-ellipseFocusBottom_y,2));
  1747. //判断距离和与长轴的关系
  1748. if(lenth<2*a+2 && lenth >2*a-2)
  1749. {
  1750. //把点设置为绿色
  1751. lOffset = this->PixelOffset(i, j, wBytesPerLine);
  1752. *(lpData + lOffset++) = 0;
  1753. *(lpData + lOffset++) = 255;
  1754. *(lpData + lOffset++) = 0;
  1755. }
  1756. }
  1757. GlobalUnlock(hDIB);
  1758. }
  1759. void DIB::DdaLine(CPoint from, CPoint end, LPBYTE lpData, WORD wBytesPerLine)
  1760. {
  1761. //x,y的增量
  1762. float delta_x;
  1763. float delta_y;
  1764. //x,y的坐标
  1765. float x;
  1766. float y;
  1767. //x,y上的差值
  1768. int dx;
  1769. int dy;
  1770. //总的步长
  1771. int steps;
  1772. int k;
  1773. //得到x,y的差值
  1774. dx = end.x - from.x;
  1775. dy = end.y - from.y;
  1776. //判断x,y上的差值大小,确定步长
  1777. if(abs(dx) > abs(dy))
  1778. {
  1779. steps = abs(dx);
  1780. }
  1781. else
  1782. {
  1783. steps = abs(dy);
  1784. }
  1785. //得到每次增量的大小
  1786. delta_x = (float)dx / (float)steps;
  1787. delta_y = (float)dy / (float)steps;
  1788. //设定x,y的起点
  1789. x = (float)from.x;
  1790. y = (float)from.y;
  1791. //设定初始点的颜色为绿色
  1792. long lOffset = this->PixelOffset(y, x, wBytesPerLine);
  1793. *(lpData + lOffset++) = 0;
  1794. *(lpData + lOffset++) = 255;
  1795. *(lpData + lOffset++) = 0;
  1796. //根据计算得到的步长,把直线上的点填充成绿色
  1797. for (k=1;k<=steps; k++)
  1798. {
  1799. //x,y分别加上各自的增量
  1800. x+=delta_x;
  1801. y+=delta_y;
  1802. //设置点的颜色
  1803. lOffset = this->PixelOffset(y, x, wBytesPerLine);
  1804. *(lpData + lOffset++) = 0;
  1805. *(lpData + lOffset++) = 255;
  1806. *(lpData + lOffset++) = 0;
  1807. }
  1808. }