CellView.cpp
上传用户:mjs2008
上传日期:2021-05-16
资源大小:5089k
文件大小:64k
源码类别:

生物技术

开发平台:

Visual C++

  1. // CellView.cpp : implementation of the CCellView class
  2. //
  3. #include "stdafx.h"
  4. #include "Cell.h"
  5. #include "CellDoc.h"
  6. #include "CellView.h"
  7. #include "HSI.h"
  8. #include "HSIDlg.h"
  9. #include "HistogramDlg.h"
  10. #include "Set.h"
  11. #include  <math.h>
  12. #ifdef _DEBUG
  13. #define new DEBUG_NEW
  14. #undef THIS_FILE
  15. static char THIS_FILE[] = __FILE__;
  16. #endif
  17. #define MAX_HOLE 625
  18. #define BITMAP_ID 0x4D42 // universal id for a bitmap
  19. #define DISTANCE(x0,y0,x1,y1) sqrt((x0-x1)*(x0-x1)+(y0-y1)*(y0-y1))
  20. /////////////////////////////
  21. // GLOBALS
  22. HBITMAP g_hBitmap=NULL;
  23. CString g_csFileName; // current open file name
  24. int g_nMapWidth=0;
  25. int g_nMapHeight=0;
  26. //bool g_bImgBufferChanged;
  27. RGB spec_rgb = { 0xff, 0x00, 0x00 }; // 标识色
  28. //RGB * g_pOrgImgBuffer; // 全局的原始图像数据
  29. RGB * g_pImgBuffer; // 全局的图像数据
  30. //RGB * g_pImgBufferBack; // 全局的图像数据 用于redo
  31. BYTE * g_pSobelResult; // Soble运算的结果
  32. HSI * g_pHSIBuffer; // 全局的HSI数据
  33. FLAGS * g_pFlags; // 全局的标志量
  34. FLAGS * g_pFlagsBack; // 全局的标志量
  35. bool g_bDir4Ero=false;
  36. bool g_bDir4Dil=false;
  37. long g_nCellCount=0;
  38. long g_nCellTotArea=0;
  39. /////////////////////////////////////////////////////////////////////////////
  40. // 用于某些特定函数中的全局
  41. CPoint scroll_lefttop; // scroll bar 左上角
  42. double huegap,intgap,satgap; // 在FindInVectorHSI中使用.提高效率
  43. long tot_area,tot_x,tot_y,max_radius; // 用于递归
  44. vector<CENTER_POINT> points_temp; // 用于临时存储CENTER_POINT
  45. int *qh; //queue handle
  46. int *qs, *qst, *qr; //queue save, start, read
  47. long qSz; //queue size (physical)
  48. int xt, yt; //temporary x and y locations
  49. /////////////////////////////////////////////////////////////////////////////
  50. // CCellView
  51. IMPLEMENT_DYNCREATE(CCellView, CScrollView)
  52. BEGIN_MESSAGE_MAP(CCellView, CScrollView)
  53. //{{AFX_MSG_MAP(CCellView)
  54. ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
  55. ON_WM_LBUTTONDOWN()
  56. ON_WM_MOUSEMOVE()
  57. ON_WM_LBUTTONUP()
  58. ON_COMMAND(ID_PROC_HSI, OnProcHsi)
  59. ON_WM_SETCURSOR()
  60. ON_COMMAND(ID_EDIT_UNDO, OnEditUndo)
  61. ON_COMMAND(ID_PROC_SOBEL, OnProcSobel)
  62. ON_COMMAND(ID_DISP_SOBEL, OnDispSobel)
  63. ON_COMMAND(ID_PROC_HISTOGRAM, OnProcHistogram)
  64. ON_COMMAND(ID_PROC_SPEC_COLOR, OnProcSpecColor)
  65. ON_COMMAND(ID_DISP_EDGE, OnDispEdge)
  66. ON_COMMAND(ID_DISP_REGION, OnDispRegion)
  67. ON_COMMAND(ID_PROC_RELOAD, OnProcReload)
  68. ON_COMMAND(ID_PROC_FINDCENTER, OnProcFindCenter)
  69. ON_COMMAND(ID_PROC_SOBEL_CORRECT, OnProcSobelCorrect)
  70. ON_COMMAND(ID_PROC_FORCE_KILL, OnProcForceKill)
  71. ON_COMMAND(ID_PROC_FORCE_SELE, OnProcForceSele)
  72. ON_COMMAND(ID_PROC_DILATION, OnProcDilation)
  73. ON_COMMAND(ID_PROC_EROSION, OnProcErosion)
  74. ON_COMMAND(ID_PROC_SMOOTH, OnProcSmooth)
  75. ON_COMMAND(ID_PROC_STAT, OnProcStat)
  76. ON_COMMAND(ID_PROC_FILLHOLE, FillHoles)
  77. //}}AFX_MSG_MAP
  78. // Standard printing commands
  79. ON_COMMAND(ID_FILE_PRINT, CScrollView::OnFilePrint)
  80. ON_COMMAND(ID_FILE_PRINT_DIRECT, CScrollView::OnFilePrint)
  81. ON_COMMAND(ID_FILE_PRINT_PREVIEW, CScrollView::OnFilePrintPreview)
  82. END_MESSAGE_MAP()
  83. /////////////////////////////////////////////////////////////////////////////
  84. // CCellView construction/destruction
  85. CCellView::CCellView()
  86. {
  87. // TODO: add construction code here
  88. m_DragRectSize.cx = 1;
  89. m_DragRectSize.cy = 1;
  90. g_csFileName = "";
  91. g_pImgBuffer = NULL;
  92. // g_pOrgImgBuffer = NULL;
  93. // g_pImgBufferBack = NULL;
  94. g_pHSIBuffer = NULL;
  95. g_pFlags = NULL;
  96. g_pFlagsBack = NULL;
  97. g_pSobelResult= NULL;
  98. // 所有布尔量初始化
  99. // g_bImgBufferChanged=false;
  100. m_bDrag=false;
  101. m_bProcHsi=false;
  102. m_bDispSobel=false;
  103. m_bIsDispEdge=false;
  104. m_bFullEdge=false;
  105. m_bForceKill=false;
  106. m_bForceAdd=false;
  107. CSize sz(g_nMapWidth,g_nMapHeight);
  108. SetScrollSizes(MM_TEXT, sz);
  109. }
  110. CCellView::~CCellView()
  111. {
  112. if(g_hBitmap)
  113. DeleteObject(g_hBitmap);
  114. if(g_pImgBuffer)
  115. delete[] g_pImgBuffer;
  116. // if (g_pOrgImgBuffer)
  117. // delete[] g_pOrgImgBuffer;
  118. // if (g_pImgBufferBack)
  119. // delete[] g_pImgBufferBack;
  120. if(g_pHSIBuffer)
  121. delete[] g_pHSIBuffer;
  122. if (g_pSobelResult)
  123. delete[] g_pSobelResult;
  124. if(g_pFlags)
  125. delete[] g_pFlags;
  126. if (g_pFlagsBack)
  127. delete[] g_pFlagsBack;
  128. }
  129. BOOL CCellView::PreCreateWindow(CREATESTRUCT& cs)
  130. {
  131. // TODO: Modify the Window class or styles here by modifying
  132. //  the CREATESTRUCT cs
  133. return CView::PreCreateWindow(cs);
  134. }
  135. /////////////////////////////////////////////////////////////////////////////
  136. // CCellView drawing
  137. void CCellView::OnDraw(CDC* pDC)
  138. {
  139. int x,y;
  140. CCellDoc* pDoc = GetDocument();
  141. ASSERT_VALID(pDoc);
  142. // TODO: add draw code for native data here
  143. if(g_hBitmap)
  144. {
  145. scroll_lefttop=GetScrollPosition();
  146. RECT rect;
  147. GetClientRect(&rect);
  148. int drawwd,drawht;
  149. if (g_nMapWidth>rect.right-rect.left)
  150. drawwd=rect.right-rect.left+1;
  151. else drawwd=g_nMapWidth;
  152. if (g_nMapHeight>rect.bottom-rect.top)
  153. drawht=rect.bottom-rect.top+1;
  154. else drawht=g_nMapHeight;
  155. BITMAPINFO bitmapinfo;
  156. CDC *pdc = GetDC();
  157. HDC dc = pdc->m_hDC;
  158. HDC memdc = ::CreateCompatibleDC(dc);
  159. ::SelectObject(memdc, g_hBitmap);
  160. if (m_bDispSobel) // 显示Sobel
  161. {
  162. BYTE *cur_pos=g_pSobelResult;
  163. for(y = 0; y < g_nMapHeight; y++)
  164. {
  165. for(x = 0; x < g_nMapWidth; x++)
  166. {
  167. if (x-scroll_lefttop.x>=0 && x-scroll_lefttop.x<=drawwd && y-scroll_lefttop.y>=0 && y-scroll_lefttop.y<=drawht)
  168. SetPixel(memdc,x,y,RGB(*cur_pos,*cur_pos,*cur_pos));
  169. cur_pos++;
  170. }
  171. }
  172. // g_bImgBufferChanged=false;
  173. }
  174. else
  175. {
  176. bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  177. bitmapinfo.bmiHeader.biWidth = g_nMapWidth;
  178. bitmapinfo.bmiHeader.biHeight = g_nMapHeight;
  179. bitmapinfo.bmiHeader.biPlanes = 1;
  180. bitmapinfo.bmiHeader.biBitCount = 24;
  181. bitmapinfo.bmiHeader.biCompression = BI_RGB;
  182. GetDIBits(memdc, g_hBitmap, 0, g_nMapHeight, NULL,
  183. &bitmapinfo, DIB_RGB_COLORS);
  184. FlipBitmapData(g_pImgBuffer); // flip it
  185. SetDIBits(memdc, g_hBitmap, 0, g_nMapHeight, g_pImgBuffer,
  186. &bitmapinfo, DIB_RGB_COLORS);
  187. FlipBitmapData(g_pImgBuffer); // flip back
  188. /* if (m_bIsDispEdge)
  189. {
  190. FlipBitmapData(g_pImgBuffer); // flip it
  191. SetDIBits(memdc, g_hBitmap, 0, g_nMapHeight, g_pImgBuffer,
  192. &bitmapinfo, DIB_RGB_COLORS);
  193. FlipBitmapData(g_pImgBuffer); // flip back
  194. }
  195. else
  196. {
  197. FlipBitmapData(g_pImgBuffer); // flip it
  198. SetDIBits(memdc, g_hBitmap, 0, g_nMapHeight, g_pImgBuffer,
  199. &bitmapinfo, DIB_RGB_COLORS);
  200. FlipBitmapData(g_pImgBuffer); // flip back
  201. }
  202. */ }
  203. ::BitBlt(dc, 0, 0, drawwd, drawht, memdc, scroll_lefttop.x, scroll_lefttop.y, SRCCOPY);
  204. FLAGS* cur_flag;
  205. if(m_bIsDispEdge)
  206. {
  207. for(y = 0; y < g_nMapHeight; y++)
  208. {
  209. cur_flag=&g_pFlags[y*g_nMapWidth];
  210. for(x = 0; x < g_nMapWidth; x++)
  211. {
  212. if(cur_flag->edged)
  213. if (x-scroll_lefttop.x>=0 && x-scroll_lefttop.x<=drawwd && y-scroll_lefttop.y>=0 && y-scroll_lefttop.y<=drawht)
  214. pdc->SetPixel(x-scroll_lefttop.x, y-scroll_lefttop.y, RGB(spec_rgb.r, spec_rgb.g, spec_rgb.b));
  215. cur_flag++;
  216. }
  217. }
  218. }
  219. else // region
  220. {
  221. for(y = 0; y < g_nMapHeight; y++)
  222. {
  223. cur_flag=&g_pFlags[y*g_nMapWidth];
  224. for(x = 0; x < g_nMapWidth; x++)
  225. {
  226. if(cur_flag->marked)
  227. if (x-scroll_lefttop.x>=0 && x-scroll_lefttop.x<=drawwd && y-scroll_lefttop.y>=0 && y-scroll_lefttop.y<=drawht)
  228. pdc->SetPixel(x-scroll_lefttop.x, y-scroll_lefttop.y, RGB(spec_rgb.r, spec_rgb.g, spec_rgb.b));
  229. cur_flag++;
  230. }
  231. }
  232. }
  233. CENTER_POINT centerp;
  234. CPen pen;
  235. pen.CreatePen(PS_SOLID, 1, RGB(spec_rgb.r, spec_rgb.g, spec_rgb.b));
  236. pdc->SelectObject(pen);
  237. for (int i=0;i<m_vCenterPoints.size();i++)
  238. {
  239. centerp=m_vCenterPoints.at(i);
  240. Arc(pdc->m_hDC,
  241. centerp.x-scroll_lefttop.x-centerp.radius,
  242. centerp.y-scroll_lefttop.y-centerp.radius,
  243. centerp.x-scroll_lefttop.x+centerp.radius,
  244. centerp.y-scroll_lefttop.y+centerp.radius,
  245. centerp.x-scroll_lefttop.x+centerp.radius,
  246. centerp.y-scroll_lefttop.y,
  247. centerp.x-scroll_lefttop.x+centerp.radius,
  248. centerp.y-scroll_lefttop.y
  249. );
  250. }
  251. DeleteObject(pen);
  252. ReleaseDC(pdc);
  253. ::DeleteDC(memdc);
  254. }
  255. }
  256. /////////////////////////////////////////////////////////////////////////////
  257. // CCellView printing
  258. BOOL CCellView::OnPreparePrinting(CPrintInfo* pInfo)
  259. {
  260. // default preparation
  261. return DoPreparePrinting(pInfo);
  262. }
  263. void CCellView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
  264. {
  265. // TODO: add extra initialization before printing
  266. }
  267. void CCellView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
  268. {
  269. // TODO: add cleanup after printing
  270. }
  271. /////////////////////////////////////////////////////////////////////////////
  272. // CCellView diagnostics
  273. #ifdef _DEBUG
  274. void CCellView::AssertValid() const
  275. {
  276. CView::AssertValid();
  277. }
  278. void CCellView::Dump(CDumpContext& dc) const
  279. {
  280. CView::Dump(dc);
  281. }
  282. CCellDoc* CCellView::GetDocument() // non-debug version is inline
  283. {
  284. ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CCellDoc)));
  285. return (CCellDoc*)m_pDocument;
  286. }
  287. #endif //_DEBUG
  288. /////////////////////////////////////////////////////////////////////////////
  289. // CCellView message handlers
  290. void CCellView::OnFileOpen() 
  291. {
  292. // 打开文件对话框
  293. char szFilter[] = "位图文件 (*.bmp)|*.bmp|所有文件(*.*)|*.*||";
  294. CString szFilename;
  295. BITMAP bmp;
  296. CFileDialog *FileDlg = new CFileDialog(TRUE, NULL, NULL, OFN_OVERWRITEPROMPT, szFilter, NULL);
  297. if(FileDlg->DoModal() == IDOK)
  298. {
  299. szFilename = FileDlg->GetPathName();
  300. if(!szFilename.IsEmpty())
  301. {
  302. HANDLE handle;
  303. handle = LoadImage(theApp.m_hInstance, szFilename, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
  304. if(handle)
  305. {
  306. if(g_hBitmap)
  307. DeleteObject(g_hBitmap);
  308. InvalidateRect(0, TRUE);
  309. g_hBitmap = (struct HBITMAP__ *) handle;
  310. g_csFileName = FileDlg->GetFileName();
  311. theApp.m_pMainWnd->SetWindowText((LPCTSTR) (g_csFileName + " - Cell"));
  312. }
  313. else
  314. {
  315. MessageBox("无法打开文件");
  316. return;
  317. }
  318. m_vAllSelected.clear();
  319. // 所有布尔量初始化
  320. m_bDrag=false;
  321. m_bProcHsi=false;
  322. m_bForceKill=false;
  323. m_bForceAdd=false;
  324. m_bDispSobel=false;
  325. AfxGetApp()->m_pMainWnd->GetMenu()->CheckMenuItem(ID_DISP_SOBEL, MF_UNCHECKED);
  326. m_bIsDispEdge=false;
  327. AfxGetApp()->m_pMainWnd->GetMenu()->CheckMenuItem(ID_DISP_REGION, MF_CHECKED);
  328. AfxGetApp()->m_pMainWnd->GetMenu()->CheckMenuItem(ID_DISP_EDGE, MF_UNCHECKED);
  329. m_vCenterPoints.clear(); // 清除!
  330. CDC *pdc = GetDC();
  331. HDC dc = pdc->m_hDC;
  332. HDC memdc = ::CreateCompatibleDC(dc);
  333. CBitmap::FromHandle(g_hBitmap)->GetBitmap(&bmp);
  334. ::SelectObject(memdc, g_hBitmap);
  335. g_nMapWidth=bmp.bmWidth;
  336. g_nMapHeight=bmp.bmHeight;
  337. // 设置滚动条
  338. CSize sz(g_nMapWidth,g_nMapHeight);
  339. SetScrollSizes(MM_TEXT, sz);
  340. // fill g_pImgBuffer
  341. if (LoadImageBuffer(memdc,(LPSTR)(LPCTSTR)g_csFileName)==0)
  342. return;
  343. // 初始化Flags
  344. if(g_pFlags)
  345. delete[] g_pFlags;
  346. g_pFlags = new FLAGS[g_nMapHeight * g_nMapWidth];
  347. memset(g_pFlags, 0, g_nMapHeight * g_nMapWidth * sizeof(FLAGS));
  348. if (g_pFlagsBack)
  349. delete[] g_pFlagsBack;
  350. g_pFlagsBack = new FLAGS[g_nMapHeight * g_nMapWidth];
  351. memset(g_pFlagsBack, 0, g_nMapHeight * g_nMapWidth * sizeof(FLAGS));
  352. GenHSIData();
  353. OnProcSobel(); // 预先生成Sobel信息
  354. ::BitBlt(dc, 0, 0, g_nMapWidth, g_nMapHeight, memdc, 0, 0, SRCCOPY);
  355. ReleaseDC(pdc);
  356. ::DeleteDC(memdc);
  357. }
  358. }
  359. delete FileDlg;
  360. }
  361. void CCellView::OnLButtonDown(UINT nFlags, CPoint point) 
  362. {
  363. m_LBDnPoint = point;
  364. m_LastPoint = point;
  365. m_bDrag = true;
  366. // draw selection box
  367. RECT currect;
  368. currect.top = m_LBDnPoint.y;
  369. currect.left = m_LBDnPoint.x;
  370. currect.right = point.x;
  371. currect.bottom = point.y;
  372. CDC *pdc = GetDC();
  373. pdc->DrawDragRect(&currect, m_DragRectSize, NULL, m_DragRectSize, NULL, NULL);
  374. ReleaseDC(pdc);
  375. CView::OnLButtonDown(nFlags, point);
  376. }
  377. void CCellView::OnMouseMove(UINT nFlags, CPoint point) 
  378. {
  379. if(m_bDrag)
  380. {
  381. RECT lastrect, currect;
  382. lastrect.top = m_LBDnPoint.y > m_LastPoint.y ? m_LastPoint.y : m_LBDnPoint.y;
  383. lastrect.left = m_LBDnPoint.x > m_LastPoint.x ? m_LastPoint.x : m_LBDnPoint.x;
  384. lastrect.right = m_LBDnPoint.x > m_LastPoint.x ? m_LBDnPoint.x : m_LastPoint.x;
  385. lastrect.bottom = m_LBDnPoint.y > m_LastPoint.y ? m_LBDnPoint.y : m_LastPoint.y;
  386. currect.top = m_LBDnPoint.y > point.y ? point.y : m_LBDnPoint.y;
  387. currect.left = m_LBDnPoint.x > point.x ? point.x : m_LBDnPoint.x;
  388. currect.right = m_LBDnPoint.x > point.x ? m_LBDnPoint.x : point.x;
  389. currect.bottom = m_LBDnPoint.y > point.y ? m_LBDnPoint.y : point.y;
  390. SIZE sz;
  391. sz.cx = 1;
  392. sz.cy = 1;
  393. CDC *pdc = GetDC();
  394. pdc->DrawDragRect(&currect, m_DragRectSize, &lastrect, m_DragRectSize, NULL, NULL);
  395. ReleaseDC(pdc);
  396. m_LastPoint = point;
  397. }
  398. CView::OnMouseMove(nFlags, point);
  399. }
  400. void CCellView::OnLButtonUp(UINT nFlags, CPoint point) 
  401. {
  402. if (!m_bDrag) // 安全措施
  403. {
  404. CView::OnLButtonUp(nFlags, point);
  405. return;
  406. }
  407. int exchange;
  408. m_bDrag = false;
  409. // 画选择框
  410. m_SelectedRect.left = m_LBDnPoint.x;
  411. m_SelectedRect.top = m_LBDnPoint.y;
  412. m_SelectedRect.right = point.x;
  413. m_SelectedRect.bottom = point.y;
  414. if(m_SelectedRect.left > m_SelectedRect.right)
  415. {
  416. exchange = m_SelectedRect.left;
  417. m_SelectedRect.left = m_SelectedRect.right;
  418. m_SelectedRect.right = exchange;
  419. }
  420. if(m_SelectedRect.top > m_SelectedRect.bottom)
  421. {
  422. exchange = m_SelectedRect.top;
  423. m_SelectedRect.top = m_SelectedRect.bottom;
  424. m_SelectedRect.bottom = exchange;
  425. }
  426. SIZE zero;
  427. zero.cx = 0;
  428. zero.cy = 0;
  429. CDC *pdc = GetDC();
  430. pdc->DrawDragRect(&m_SelectedRect, zero, &m_SelectedRect, m_DragRectSize, NULL, NULL);
  431. ReleaseDC(pdc);
  432. m_LastPoint.x = 0; // 设置为0
  433. if(g_hBitmap)
  434. {
  435. if(m_bProcHsi)
  436. {
  437. if(m_SelectedRect.left >= m_SelectedRect.right || m_SelectedRect.top >= m_SelectedRect.bottom)
  438. MessageBox("选择的范围不正确.请重新选择!");
  439. else
  440. {
  441. m_bProcHsi = false;
  442. CHSIDlg hsiDlg(&m_SelectedRect);
  443. if(hsiDlg.DoModal() == IDOK)
  444. ProcHSI(hsiDlg.m_bEx);
  445. }
  446. }
  447. else if (m_bForceKill)
  448. {
  449. if(m_SelectedRect.left >= m_SelectedRect.right || m_SelectedRect.top >= m_SelectedRect.bottom)
  450. MessageBox("选择的范围不正确.请重新选择!");
  451. else
  452. {
  453. m_bForceKill = false;
  454. m_SelectedRect.left+=scroll_lefttop.x;
  455. m_SelectedRect.right+=scroll_lefttop.x;
  456. m_SelectedRect.top+=scroll_lefttop.y;
  457. m_SelectedRect.bottom+=scroll_lefttop.y;
  458. for(int j = m_SelectedRect.top; j < m_SelectedRect.bottom; j++)
  459. {
  460. for(int i = m_SelectedRect.left; i < m_SelectedRect.right; i++)
  461. {
  462. if (i<0 || i>=g_nMapWidth || j<0 || j>=g_nMapHeight)
  463. continue;
  464. g_pFlags[INDEX(i, j)].marked=0;
  465. }
  466. }
  467. GenEdge();
  468. InvalidateRect(0,TRUE);
  469. }
  470. }
  471. else if (m_bForceAdd)
  472. {
  473. if(m_SelectedRect.left >= m_SelectedRect.right || m_SelectedRect.top >= m_SelectedRect.bottom)
  474. MessageBox("选择的范围不正确.请重新选择!");
  475. else
  476. {
  477. m_bForceAdd = false;
  478. m_SelectedRect.left+=scroll_lefttop.x;
  479. m_SelectedRect.right+=scroll_lefttop.x;
  480. m_SelectedRect.top+=scroll_lefttop.y;
  481. m_SelectedRect.bottom+=scroll_lefttop.y;
  482. for(int j = m_SelectedRect.top; j < m_SelectedRect.bottom; j++)
  483. {
  484. for(int i = m_SelectedRect.left; i < m_SelectedRect.right; i++)
  485. {
  486. if (i<0 || i>=g_nMapWidth || j<0 || j>=g_nMapHeight)
  487. continue;
  488. g_pFlags[INDEX(i, j)].marked=1;
  489. }
  490. }
  491. GenEdge();
  492. InvalidateRect(0,TRUE);
  493. }
  494. }
  495. }
  496. CView::OnLButtonUp(nFlags, point);
  497. }
  498. bool CCellView::LoadImageBuffer(HDC memdc,char *szFileName)
  499. {
  500. BITMAPFILEHEADER bitmapfileheader;
  501. BITMAPINFOHEADER bitmapinfoheader;
  502. BITMAPINFO  bitmapinfo;
  503. // this function opens a bitmap file and loads the data into bitmap
  504. int file_handle;  // the file handle
  505. OFSTRUCT file_data;          // the file data information
  506. // open the file if it exists
  507. if ((file_handle = OpenFile(szFileName,&file_data,OF_READ))==-1)
  508.    return 0;
  509. // now load the bitmap file header
  510. _lread(file_handle, &bitmapfileheader,sizeof(BITMAPFILEHEADER));
  511. // test if this is a bitmap file
  512. if (bitmapfileheader.bfType!=BITMAP_ID)
  513. {
  514. // close the file
  515. _lclose(file_handle);
  516. // return error
  517. return 0;
  518. } // end if
  519. // now we know this is a bitmap, so read in all the sections
  520. // first the bitmap infoheader
  521. // now load the bitmap file header
  522. _lread(file_handle, &bitmapinfoheader, sizeof(BITMAPINFOHEADER));
  523. if (bitmapinfoheader.biWidth%4 != 0) // 宽度不是4的倍数
  524. {
  525. MessageBox("文件宽度不是4的倍数");
  526. _lclose(file_handle);
  527. return 0;
  528. }
  529. if(g_pImgBuffer) // clear it if not null
  530. delete[] g_pImgBuffer;
  531. g_pImgBuffer = new RGB[g_nMapHeight * g_nMapWidth]; // make space
  532. // 申请备份buffer空间
  533. // if (g_pImgBufferBack)
  534. // delete[] g_pImgBufferBack;
  535. // g_pImgBufferBack=new RGB[g_nMapHeight * g_nMapWidth];
  536. // if (g_pOrgImgBuffer)
  537. // delete[] g_pOrgImgBuffer;
  538. // g_pOrgImgBuffer=new RGB[g_nMapHeight * g_nMapWidth];
  539. // now load the color palette if there is one
  540. if (bitmapinfoheader.biBitCount != 24)
  541. {
  542. // set bitmapinfo
  543. bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  544. bitmapinfo.bmiHeader.biWidth = g_nMapWidth;
  545. bitmapinfo.bmiHeader.biHeight = g_nMapHeight;
  546. bitmapinfo.bmiHeader.biPlanes = 1;
  547. bitmapinfo.bmiHeader.biBitCount = 24;
  548. bitmapinfo.bmiHeader.biCompression = BI_RGB;
  549. GetDIBits(memdc, g_hBitmap, 0, g_nMapHeight, NULL,
  550. &bitmapinfo, DIB_RGB_COLORS);
  551. GetDIBits(memdc, g_hBitmap, 0, g_nMapHeight, g_pImgBuffer,
  552. &bitmapinfo, DIB_RGB_COLORS);
  553. }
  554. else
  555. {
  556. _llseek(file_handle, bitmapfileheader.bfOffBits,FILE_BEGIN);
  557. _lread(file_handle, g_pImgBuffer, 3*g_nMapHeight*g_nMapWidth);
  558. }
  559. FlipBitmapData(g_pImgBuffer);
  560. // memcpy(g_pOrgImgBuffer,g_pImgBuffer,sizeof(RGB)*g_nMapWidth*g_nMapHeight);
  561. // close the file
  562. _lclose(file_handle);
  563. // return success
  564. return 1;
  565. }
  566. void CCellView::FlipBitmapData(RGB *buffer)
  567. {
  568. RGB *tempmem;
  569. int bytes_per_line=g_nMapWidth*sizeof(RGB);
  570. tempmem=new RGB[g_nMapWidth*g_nMapHeight];
  571. memcpy(tempmem,buffer,bytes_per_line*g_nMapHeight);
  572. for (int i=0;i<g_nMapHeight;i++)
  573.     memcpy(&buffer[((g_nMapHeight-1) - i)*g_nMapWidth],
  574. &tempmem[i*g_nMapWidth], bytes_per_line);
  575. delete[] tempmem;
  576. }
  577. void CCellView::OnProcHsi() 
  578. {
  579. if(g_hBitmap)
  580. {
  581. m_bProcHsi = true;
  582. MessageBox("请选择一块小区域作为颜色选取范围");
  583. }
  584. else
  585. MessageBox("请先打开图像文件!");
  586. }
  587. BOOL CCellView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
  588. {
  589. if(m_bProcHsi || m_bForceKill || m_bForceAdd)
  590. ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_CROSS));
  591. else
  592. ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
  593. return TRUE;
  594. }
  595. void CCellView::ProcHSI(bool bEx)
  596. {
  597. m_vHSI.clear();
  598. // fill vector
  599. HSI *hsi;
  600. huegap=256.0*g_nHueGap/100.0;
  601. if (huegap>5.12)
  602. huegap=5.12;
  603. huegap+=0.0001;
  604. intgap=g_nIntGap/100.0;
  605. if (intgap>0.02)
  606. intgap=0.02;
  607. intgap+=0.0001;
  608. satgap=g_nSatGap/100.0;
  609. if (satgap>0.02)
  610. satgap=0.02;
  611. satgap+=0.0001;
  612. m_SelectedRect.left+=scroll_lefttop.x;
  613. m_SelectedRect.right+=scroll_lefttop.x;
  614. m_SelectedRect.top+=scroll_lefttop.y;
  615. m_SelectedRect.bottom+=scroll_lefttop.y;
  616. for(int j = m_SelectedRect.top; j < m_SelectedRect.bottom; j++)
  617. {
  618. for(int i = m_SelectedRect.left; i < m_SelectedRect.right; i++)
  619. {
  620. if (i<0 || i>=g_nMapWidth || j<0 || j>=g_nMapHeight)
  621. continue;
  622. if(!g_pFlags[INDEX(i, j)].marked)
  623. {
  624. hsi=&g_pHSIBuffer[INDEX(i,j)];
  625. if(FindInVectorHSI(m_vHSI, *hsi) == false)
  626. {
  627. m_vHSI.push_back(*hsi);
  628. m_vAllSelected.push_back(*hsi);
  629. }
  630. }
  631. }
  632. }
  633. if(m_vHSI.size())
  634. {
  635. // backup
  636. // memcpy(g_pImgBufferBack,g_pImgBuffer,
  637. // sizeof(RGB)*g_nMapWidth*g_nMapHeight);
  638. memcpy(g_pFlagsBack,g_pFlags,
  639. sizeof(FLAGS)*g_nMapWidth*g_nMapHeight);
  640. // g_bImgBufferChanged=true;
  641. HsiProcess(bEx);
  642. // m_vHSI.clear();
  643. GenEdge();
  644. InvalidateRect(0, TRUE);
  645. }
  646. }
  647. void CCellView::GenHSIData()
  648. {
  649. int wd, ht;
  650. HSI tmp;
  651. RGB    *cur;
  652. if(g_pHSIBuffer)
  653. delete[] g_pHSIBuffer;
  654. g_pHSIBuffer = new HSI[g_nMapWidth * g_nMapHeight];
  655. memset(g_pHSIBuffer, 0, sizeof(HSI) * g_nMapWidth * g_nMapHeight);
  656. HSI *pHueBuffer = g_pHSIBuffer;
  657. cur = g_pImgBuffer;
  658. for(ht = 0; ht < g_nMapHeight; ht++)
  659. {
  660. for(wd = 0; wd < g_nMapWidth; wd++)
  661. {
  662. RgbToHsi(cur, &tmp);
  663. pHueBuffer->Hue = tmp.Hue*255.0/360.0;
  664. pHueBuffer->Intensity = tmp.Intensity;
  665. pHueBuffer->Saturation = tmp.Saturation;
  666. pHueBuffer++;
  667. cur++;
  668. }
  669. }
  670. }
  671. bool CCellView::FindInVectorHSI(vector<HSI> v, HSI c)
  672. {
  673. int size = v.size();
  674. for(int i = 0; i < size; i++)
  675. // if(c.Hue == v.at(i).Hue && c.Intensity == v.at(i).Intensity && c.Saturation == v.at(i).Saturation)
  676. if( fabs(c.Hue - v.at(i).Hue) < huegap &&
  677. fabs(c.Intensity - v.at(i).Intensity) < intgap && 
  678. fabs(c.Saturation - v.at(i).Saturation) < satgap )
  679. return true;
  680. return false;
  681. }
  682. void CCellView::HsiProcess(bool bEx)
  683. {
  684. RGB *cur=g_pImgBuffer;
  685. HSI *pHSI=g_pHSIBuffer;
  686. int size = m_vHSI.size();
  687. double sH, sS, sI, dH, dS, dI;
  688. HSI tmp, vtmp;
  689. int ht, wd;
  690. FLAGS *cur_flag = g_pFlags; // flag
  691. for(ht = 0; ht < g_nMapHeight; ht++)
  692. {
  693. for(wd = 0; wd < g_nMapWidth; wd++)
  694. {
  695. if(cur_flag->marked)
  696. {
  697. cur++;
  698. cur_flag++; // flag
  699. pHSI++;
  700. continue;
  701. }
  702. memcpy(&tmp,pHSI,sizeof(HSI));
  703. pHSI++;
  704. for(int i = 0; i < size; i++)
  705. {
  706. vtmp = m_vHSI.at(i);
  707. sH = vtmp.Hue;
  708. sS = vtmp.Saturation;
  709. sI = vtmp.Intensity;
  710. dH = tmp.Hue;
  711. dS = tmp.Saturation;
  712. dI = tmp.Intensity;
  713. if(!bEx) // 排除法
  714. {
  715. if
  716. (
  717. sH - dH >= 0 - g_nHueGap * 2.55
  718. && sH - dH <= g_nHueGap * 2.55
  719. && sS - dS >= 0 - g_nSatGap / 100.0
  720. && sS - dS <= g_nSatGap / 100.0
  721. && sI - dI >= 0 - g_nIntGap / 100.0
  722. && sI - dI <= g_nIntGap / 100.0
  723. )
  724. {
  725. cur_flag->marked = 1; // set marked
  726. // cur->r=cur->g=cur->b=0;
  727. continue;
  728. }
  729. }
  730. else
  731. {
  732. if
  733. (
  734. (sH - dH <= 0 - g_nHueGap * 2.55 || sH - dH >= g_nHueGap * 2.55)
  735. && (sS - dS <= 0 - g_nSatGap / 100.0 || sS - dS >= g_nSatGap / 100.0)
  736. && (sI - dI <= 0 - g_nIntGap / 100.0 || sI - dI >= g_nIntGap / 100.0)
  737. )
  738. {
  739. cur_flag->marked = 1; // set marked
  740. cur->r=cur->g=cur->b=0;
  741. continue;
  742. }
  743. }
  744. }
  745. cur++;
  746. cur_flag++; // flag
  747. }
  748. }
  749. }
  750. void CCellView::OnEditUndo() 
  751. {
  752. // TODO: Add your command handler code here
  753. // RGB *exch;
  754. FLAGS *exchf;
  755. if (g_pFlagsBack)
  756. {
  757. // exch=g_pImgBufferBack;
  758. // g_pImgBufferBack=g_pImgBuffer;
  759. // g_pImgBuffer=exch;
  760. // g_bImgBufferChanged=true;
  761. // 恢复
  762. if(g_pFlags && g_pFlagsBack)
  763. {
  764. exchf=g_pFlags;
  765. g_pFlags=g_pFlagsBack;
  766. g_pFlagsBack=exchf;
  767. }
  768. InvalidateRect(NULL,TRUE);
  769. }
  770. }
  771. void CCellView::OnProcSobel() 
  772. {
  773. if(!g_hBitmap)
  774. MessageBox("请先打开文件");
  775. else // here we go~
  776. {
  777. double SobelTemplateGx[9];
  778. double SobelTemplateGy[9];
  779. // -1 -2 -1
  780. //  0  0  0
  781. //  1  2  1
  782. SobelTemplateGx[0] = -1;
  783. SobelTemplateGx[1] = -2;
  784. SobelTemplateGx[2] = -1;
  785. SobelTemplateGx[3] = 0;
  786. SobelTemplateGx[4] = 0;
  787. SobelTemplateGx[5] = 0;
  788. SobelTemplateGx[6] = 1;
  789. SobelTemplateGx[7] = 2;
  790. SobelTemplateGx[8] = 1;
  791. // -1 0 1
  792. // -2 0 2
  793. // -1 0 1
  794. SobelTemplateGy[0] = -1;
  795. SobelTemplateGy[1] = 0;
  796. SobelTemplateGy[2] = 1;
  797. SobelTemplateGy[3] = -2;
  798. SobelTemplateGy[4] = 0;
  799. SobelTemplateGy[5] = 2;
  800. SobelTemplateGy[6] = -1;
  801. SobelTemplateGy[7] = 0;
  802. SobelTemplateGy[8] = 1;
  803. if(g_pSobelResult)
  804. delete[] g_pSobelResult;
  805. g_pSobelResult = new BYTE[g_nMapWidth * g_nMapHeight];
  806. if(!g_pSobelResult)
  807. {
  808. MessageBox("not enough memory");
  809. return;
  810. }
  811. RGB *got;
  812. double tempr, tempg, tempb;
  813. double multi;
  814. double result;
  815. int x, y;
  816. BYTE *cur_pos=g_pSobelResult;
  817. for(y = 0; y < g_nMapHeight; y++)
  818. {
  819. for(x = 0; x < g_nMapWidth; x++)
  820. {
  821. // 计算Gx方向
  822. tempr = tempg = tempb = 0;
  823. got = GetBit(x - 1, y - 1);
  824. if(got)
  825. {
  826. multi = SobelTemplateGx[0];
  827. tempr += multi * got->r;
  828. tempg += multi * got->g;
  829. tempb += multi * got->b;
  830. }
  831. got = GetBit(x, y - 1);
  832. if(got)
  833. {
  834. multi = SobelTemplateGx[1];
  835. tempr += multi * got->r;
  836. tempg += multi * got->g;
  837. tempb += multi * got->b;
  838. }
  839. got = GetBit(x + 1, y - 1);
  840. if(got)
  841. {
  842. multi = SobelTemplateGx[2];
  843. tempr += multi * got->r;
  844. tempg += multi * got->g;
  845. tempb += multi * got->b;
  846. }
  847. got = GetBit(x - 1, y);
  848. if(got)
  849. {
  850. multi = SobelTemplateGx[3];
  851. tempr += multi * got->r;
  852. tempg += multi * got->g;
  853. tempb += multi * got->b;
  854. }
  855. got = GetBit(x, y);
  856. if(got)
  857. {
  858. multi = SobelTemplateGx[4];
  859. tempr += multi * got->r;
  860. tempg += multi * got->g;
  861. tempb += multi * got->b;
  862. }
  863. got = GetBit(x + 1, y);
  864. if(got)
  865. {
  866. multi = SobelTemplateGx[5];
  867. tempr += multi * got->r;
  868. tempg += multi * got->g;
  869. tempb += multi * got->b;
  870. }
  871. got = GetBit(x - 1, y + 1);
  872. if(got)
  873. {
  874. multi = SobelTemplateGx[6];
  875. tempr += multi * got->r;
  876. tempg += multi * got->g;
  877. tempb += multi * got->b;
  878. }
  879. got = GetBit(x, y + 1);
  880. if(got)
  881. {
  882. multi = SobelTemplateGx[7];
  883. tempr += multi * got->r;
  884. tempg += multi * got->g;
  885. tempb += multi * got->b;
  886. }
  887. got = GetBit(x + 1, y + 1);
  888. if(got)
  889. {
  890. multi = SobelTemplateGx[8];
  891. tempr += multi * got->r;
  892. tempg += multi * got->g;
  893. tempb += multi * got->b;
  894. }
  895. result = fabs(tempr) + fabs(tempg) + fabs(tempb);
  896. // 计算Gy方向
  897. tempr = tempg = tempb = 0;
  898. got = GetBit(x - 1, y - 1);
  899. if(got)
  900. {
  901. multi = SobelTemplateGy[0];
  902. tempr += multi * got->r;
  903. tempg += multi * got->g;
  904. tempb += multi * got->b;
  905. }
  906. got = GetBit(x, y - 1);
  907. if(got)
  908. {
  909. multi = SobelTemplateGy[1];
  910. tempr += multi * got->r;
  911. tempg += multi * got->g;
  912. tempb += multi * got->b;
  913. }
  914. got = GetBit(x + 1, y - 1);
  915. if(got)
  916. {
  917. multi = SobelTemplateGy[2];
  918. tempr += multi * got->r;
  919. tempg += multi * got->g;
  920. tempb += multi * got->b;
  921. }
  922. got = GetBit(x - 1, y);
  923. if(got)
  924. {
  925. multi = SobelTemplateGy[3];
  926. tempr += multi * got->r;
  927. tempg += multi * got->g;
  928. tempb += multi * got->b;
  929. }
  930. got = GetBit(x, y);
  931. if(got)
  932. {
  933. multi = SobelTemplateGy[4];
  934. tempr += multi * got->r;
  935. tempg += multi * got->g;
  936. tempb += multi * got->b;
  937. }
  938. got = GetBit(x + 1, y);
  939. if(got)
  940. {
  941. multi = SobelTemplateGy[5];
  942. tempr += multi * got->r;
  943. tempg += multi * got->g;
  944. tempb += multi * got->b;
  945. }
  946. got = GetBit(x - 1, y + 1);
  947. if(got)
  948. {
  949. multi = SobelTemplateGy[6];
  950. tempr += multi * got->r;
  951. tempg += multi * got->g;
  952. tempb += multi * got->b;
  953. }
  954. got = GetBit(x, y + 1);
  955. if(got)
  956. {
  957. multi = SobelTemplateGy[7];
  958. tempr += multi * got->r;
  959. tempg += multi * got->g;
  960. tempb += multi * got->b;
  961. }
  962. got = GetBit(x + 1, y + 1);
  963. if(got)
  964. {
  965. multi = SobelTemplateGy[8];
  966. tempr += multi * got->r;
  967. tempg += multi * got->g;
  968. tempb += multi * got->b;
  969. }
  970. result += fabs(tempr) + fabs(tempg) + fabs(tempb);
  971. if(result > 255 * 8)
  972. *cur_pos++ = 255;
  973. else
  974. *cur_pos++ = result / 8;
  975. }
  976. }
  977. // m_bDispSobel = true;
  978. // AfxGetApp()->m_pMainWnd->GetMenu()->CheckMenuItem(ID_DISP_SOBEL, MF_CHECKED);
  979. // InvalidateRect(0, TRUE);
  980. }
  981. }
  982. RGB* CCellView::GetBit(int x, int y)
  983. {
  984. if(x < 0 || x >= g_nMapWidth || y < 0 || y >= g_nMapHeight)
  985. return 0;
  986. return (g_pImgBuffer + y * g_nMapWidth + x);
  987. }
  988. void CCellView::OnProcHistogram() 
  989. {
  990. if(g_hBitmap)
  991. {
  992. CHistogramDlg hDlg;
  993. if(hDlg.DoModal() == IDOK)
  994. {
  995. // backup
  996. // memcpy(g_pImgBufferBack,g_pImgBuffer,
  997. // sizeof(RGB)*g_nMapWidth*g_nMapHeight);
  998. memcpy(g_pFlagsBack,g_pFlags,
  999. sizeof(FLAGS)*g_nMapWidth*g_nMapHeight);
  1000. // g_bImgBufferChanged=true;
  1001. FLAGS *cur_flag = g_pFlags;
  1002. RGB *cur=g_pImgBuffer;
  1003. for(int j = 0; j < g_nMapHeight; j++)
  1004. {
  1005. for(int i = 0; i < g_nMapWidth; i++)
  1006. {
  1007. if(!(cur_flag->marked))
  1008. {
  1009. if ( (cur->b >= hDlg.m_Thresh_B && cur->b <= hDlg.m_Thresh_BMax)
  1010. && (cur->r >= hDlg.m_Thresh_R && cur->r <= hDlg.m_Thresh_RMax)
  1011. && (cur->g >= hDlg.m_Thresh_G && cur->g <= hDlg.m_Thresh_GMax))
  1012. {
  1013. cur_flag->marked = 1;
  1014. // cur->r=cur->g=cur->b=0; // 不改变了原图了!
  1015. }
  1016. }
  1017. cur_flag++;
  1018. cur++;
  1019. }
  1020. }
  1021. GenEdge();
  1022. InvalidateRect(0, TRUE);
  1023. }
  1024. }
  1025. else MessageBox("请先打开图像文件!");
  1026. }
  1027. void CCellView::GenEdge() // 八方向生成边界
  1028. {
  1029. FLAGS *cur = g_pFlags;
  1030. int width = g_nMapWidth;
  1031. int height = g_nMapHeight;
  1032. for(int j = 0; j < g_nMapHeight; j++)
  1033. {
  1034. for(int i = 0; i < g_nMapWidth; i++)
  1035. {
  1036. cur->edged = 0;
  1037. if(cur->marked)
  1038. {
  1039. if(j == 0 && i == 0) // left top
  1040. {
  1041. if(!((cur + 1)->marked && (cur + width)->marked && (cur + width + 1)->marked)) cur->edged = 1;
  1042. }
  1043. else if(j == 0 && i == width - 1) // right top
  1044. {
  1045. if(!((cur - 1)->marked && (cur + width)->marked && (cur + width - 1)->marked)) cur->edged = 1;
  1046. }
  1047. else if(j == height - 1 && i == 0) // bottom left
  1048. {
  1049. if(!((cur + 1)->marked && (cur - width)->marked && (cur - width + 1)->marked)) cur->edged = 1;
  1050. }
  1051. else if(j == height - 1 && i == width - 1) // bottom right
  1052. {
  1053. if(!((cur - 1)->marked && (cur - width)->marked && (cur - width - 1)->marked)) cur->edged = 1;
  1054. }
  1055. else if(j == 0) // top
  1056. {
  1057. if
  1058. (
  1059. !((cur - 1)->marked
  1060. && (cur + 1)->marked
  1061. && (cur + width - 1)->marked
  1062. && (cur + width + 1)->marked
  1063. && (cur + width)->marked
  1064. )
  1065. ) cur->edged = 1;
  1066. }
  1067. else if(i == 0) // left
  1068. {
  1069. if
  1070. (
  1071. !((cur - width)->marked
  1072. && (cur - width + 1)->marked
  1073. && (cur + 1)->marked
  1074. && (cur + width)->marked
  1075. && (cur + width + 1)->marked
  1076. )
  1077. ) cur->edged = 1;
  1078. }
  1079. else if(j == height - 1) // bottom
  1080. {
  1081. if
  1082. (
  1083. !((cur - 1)->marked
  1084. && (cur + 1)->marked
  1085. && (cur - width - 1)->marked
  1086. && (cur - width + 1)->marked
  1087. && (cur - width)->marked
  1088. )
  1089. ) cur->edged = 1;
  1090. }
  1091. else if(i == width - 1) // right
  1092. {
  1093. if
  1094. (
  1095. !((cur - width)->marked
  1096. && (cur - width - 1)->marked
  1097. && (cur - 1)->marked
  1098. && (cur + width)->marked
  1099. && (cur + width - 1)->marked
  1100. )
  1101. ) cur->edged = 1;
  1102. }
  1103. else // normal
  1104. {
  1105. if
  1106. (
  1107. !((cur - width - 1)->marked
  1108. && (cur - width)->marked
  1109. && (cur - width + 1)->marked
  1110. && (cur - 1)->marked
  1111. && (cur + 1)->marked
  1112. && (cur + width - 1)->marked
  1113. && (cur + width)->marked
  1114. && (cur + width + 1)->marked
  1115. )
  1116. ) cur->edged = 1;
  1117. }
  1118. }
  1119. cur++;
  1120. }
  1121. }
  1122. }
  1123. void CCellView::GenEdge4()// 四方向生成边界
  1124. {
  1125. FLAGS *cur = g_pFlags;
  1126. int width = g_nMapWidth;
  1127. int height = g_nMapHeight;
  1128. for(int j = 0; j < g_nMapHeight; j++)
  1129. {
  1130. for(int i = 0; i < g_nMapWidth; i++)
  1131. {
  1132. cur->edged = 0;
  1133. if(cur->marked)
  1134. {
  1135. if(j == 0 && i == 0) // left top
  1136. {
  1137. if(!((cur + 1)->marked && (cur + width)->marked && (cur + width + 1)->marked)) cur->edged = 1;
  1138. }
  1139. else if(j == 0 && i == width - 1) // right top
  1140. {
  1141. if(!((cur - 1)->marked && (cur + width)->marked && (cur + width - 1)->marked)) cur->edged = 1;
  1142. }
  1143. else if(j == height - 1 && i == 0) // bottom left
  1144. {
  1145. if(!((cur + 1)->marked && (cur - width)->marked && (cur - width + 1)->marked)) cur->edged = 1;
  1146. }
  1147. else if(j == height - 1 && i == width - 1) // bottom right
  1148. {
  1149. if(!((cur - 1)->marked && (cur - width)->marked && (cur - width - 1)->marked)) cur->edged = 1;
  1150. }
  1151. else if(j == 0) // top
  1152. {
  1153. if
  1154. (
  1155. !((cur - 1)->marked
  1156. && (cur + 1)->marked
  1157. && (cur + width - 1)->marked
  1158. && (cur + width + 1)->marked
  1159. && (cur + width)->marked
  1160. )
  1161. ) cur->edged = 1;
  1162. }
  1163. else if(i == 0) // left
  1164. {
  1165. if
  1166. (
  1167. !((cur - width)->marked
  1168. && (cur - width + 1)->marked
  1169. && (cur + 1)->marked
  1170. && (cur + width)->marked
  1171. && (cur + width + 1)->marked
  1172. )
  1173. ) cur->edged = 1;
  1174. }
  1175. else if(j == height - 1) // bottom
  1176. {
  1177. if
  1178. (
  1179. !((cur - 1)->marked
  1180. && (cur + 1)->marked
  1181. && (cur - width - 1)->marked
  1182. && (cur - width + 1)->marked
  1183. && (cur - width)->marked
  1184. )
  1185. ) cur->edged = 1;
  1186. }
  1187. else if(i == width - 1) // right
  1188. {
  1189. if
  1190. (
  1191. !((cur - width)->marked
  1192. && (cur - width - 1)->marked
  1193. && (cur - 1)->marked
  1194. && (cur + width)->marked
  1195. && (cur + width - 1)->marked
  1196. )
  1197. ) cur->edged = 1;
  1198. }
  1199. else // normal
  1200. {
  1201. if
  1202. (
  1203. !((cur - width)->marked
  1204. && (cur - 1)->marked
  1205. && (cur + 1)->marked
  1206. && (cur + width)->marked
  1207. )
  1208. ) cur->edged = 1;
  1209. }
  1210. }
  1211. cur++;
  1212. }
  1213. }
  1214. }
  1215. void CCellView::OnProcSpecColor() 
  1216. {
  1217. CColorDialog cDlg;
  1218. if(cDlg.DoModal() == IDOK)
  1219. {
  1220. COLORREF cr = cDlg.GetColor();
  1221. spec_rgb.b = cr >> 16 & 0xff;
  1222. spec_rgb.g = cr >> 8 & 0xff;
  1223. spec_rgb.r = cr & 0xff;
  1224. InvalidateRect(0, TRUE);
  1225. }
  1226. }
  1227. void CCellView::OnDispEdge() 
  1228. {
  1229. if (g_hBitmap)
  1230. {
  1231. if(!m_bIsDispEdge)
  1232. {
  1233. m_bIsDispEdge = true;
  1234. AfxGetApp()->m_pMainWnd->GetMenu()->CheckMenuItem(ID_DISP_EDGE, MF_CHECKED);
  1235. AfxGetApp()->m_pMainWnd->GetMenu()->CheckMenuItem(ID_DISP_REGION, MF_UNCHECKED);
  1236. InvalidateRect(0, TRUE);
  1237. }
  1238. }
  1239. else
  1240. MessageBox("请先打开文件");
  1241. }
  1242. void CCellView::OnDispRegion() 
  1243. {
  1244. if (g_hBitmap)
  1245. {
  1246. if(m_bIsDispEdge)
  1247. {
  1248. m_bIsDispEdge = false;
  1249. AfxGetApp()->m_pMainWnd->GetMenu()->CheckMenuItem(ID_DISP_REGION, MF_CHECKED);
  1250. AfxGetApp()->m_pMainWnd->GetMenu()->CheckMenuItem(ID_DISP_EDGE, MF_UNCHECKED);
  1251. InvalidateRect(0, TRUE);
  1252. }
  1253. }
  1254. else
  1255. MessageBox("请先打开文件");
  1256. }
  1257. void CCellView::OnDispSobel() 
  1258. {
  1259. if (!g_hBitmap)
  1260. {
  1261. MessageBox("请先打开文件");
  1262. return;
  1263. }
  1264. if (!g_pSobelResult)
  1265. {
  1266. MessageBox("请选择菜单[处理]-[显示→Sobel]来查看梯度信息");
  1267. return;
  1268. }
  1269. m_bDispSobel ^= 1;
  1270. if(m_bDispSobel)
  1271. AfxGetApp()->m_pMainWnd->GetMenu()->CheckMenuItem(ID_DISP_SOBEL, MF_CHECKED);
  1272. else
  1273. AfxGetApp()->m_pMainWnd->GetMenu()->CheckMenuItem(ID_DISP_SOBEL, MF_UNCHECKED);
  1274. // g_bImgBufferChanged=true;
  1275. InvalidateRect(0, TRUE);
  1276. }
  1277. void CCellView::OnProcReload() 
  1278. {
  1279. // TODO: Add your command handler code here
  1280. if (g_hBitmap)
  1281. {
  1282. // g_pFlags置0
  1283. memset(g_pFlags, 0, g_nMapHeight * g_nMapWidth * sizeof(FLAGS));
  1284. // memcpy(g_pImgBuffer,g_pOrgImgBuffer,sizeof(RGB)*g_nMapWidth*g_nMapHeight);
  1285. // g_bImgBufferChanged=true;
  1286. m_bProcHsi=false;
  1287. m_bDispSobel=false;
  1288. AfxGetApp()->m_pMainWnd->GetMenu()->CheckMenuItem(ID_DISP_SOBEL, MF_UNCHECKED);
  1289. m_bIsDispEdge=false;
  1290. AfxGetApp()->m_pMainWnd->GetMenu()->CheckMenuItem(ID_DISP_REGION, MF_CHECKED);
  1291. AfxGetApp()->m_pMainWnd->GetMenu()->CheckMenuItem(ID_DISP_EDGE, MF_UNCHECKED);
  1292. m_vCenterPoints.clear(); // 清除!
  1293. InvalidateRect(0,TRUE);
  1294. }
  1295. else
  1296. MessageBox("请先打开文件");
  1297. }
  1298. void CCellView::OnProcFindCenter() 
  1299. {
  1300. if(g_hBitmap)
  1301. {
  1302. // backup
  1303. memcpy(g_pFlagsBack,g_pFlags,
  1304. sizeof(FLAGS)*g_nMapWidth*g_nMapHeight);
  1305. int pre_shrink_count;
  1306. CSet setdlg;
  1307. if (IDOK==setdlg.DoModal()) // 对话框.输入腐蚀次数
  1308. {
  1309. pre_shrink_count=setdlg.m_nPreCount;
  1310. }
  1311. else return;
  1312. int i,j,x,y;
  1313. FLAGS *cur_flag;
  1314. // 先去掉pre_shrink_count层皮
  1315. GenEdge();
  1316. for (i=0;i<pre_shrink_count;i++)
  1317. {
  1318. cur_flag=g_pFlags;
  1319. for(y = 0; y < g_nMapHeight; y++)
  1320. for(x = 0; x < g_nMapWidth; x++)
  1321. {
  1322. // 去掉边界!
  1323. if (cur_flag->edged)
  1324. cur_flag->marked=0;
  1325. cur_flag++;
  1326. }
  1327. if (i==0)
  1328. GenEdge4();
  1329. else
  1330. GenEdge();
  1331. }
  1332. InvalidateRect(NULL,TRUE);
  1333. MessageBox("去掉了噪声");
  1334. cur_flag=g_pFlags; // 清除visited标志
  1335. for(y = 0; y < g_nMapHeight; y++)
  1336. for(x = 0; x < g_nMapWidth; x++)
  1337. {
  1338. cur_flag->visited=0;
  1339. cur_flag->center=0;
  1340. cur_flag++;
  1341. }
  1342. GenEdge();
  1343. CENTER_POINT pt;
  1344. points_temp.clear();
  1345. bool changed;
  1346. for (i=0;i<40;i++) // 标志中心点的腐蚀
  1347. {
  1348. changed=false;
  1349. // 清除visited标志
  1350. cur_flag=g_pFlags;
  1351. for(y = 0; y < g_nMapHeight; y++)
  1352. for(x = 0; x < g_nMapWidth; x++)
  1353. {
  1354. cur_flag->visited=0;
  1355. cur_flag++;
  1356. }
  1357. cur_flag=g_pFlags;
  1358. for(y = 0; y < g_nMapHeight; y++)
  1359. for(x = 0; x < g_nMapWidth; x++)
  1360. {
  1361. if (y>0 && y<g_nMapHeight-1 && x>0 && x<g_nMapWidth-1) // 最边上的不用处理
  1362. {
  1363. m_bFullEdge=true;
  1364. if (cur_flag->edged && !cur_flag->visited) // 没有访问过的边界
  1365. {
  1366. if ( !(cur_flag-1)->marked &&
  1367.  !(cur_flag+1)->marked &&
  1368.  !(cur_flag+g_nMapWidth)->marked &&
  1369.  !(cur_flag-g_nMapWidth)->marked )
  1370. //  !(cur_flag+g_nMapWidth-1)->marked &&
  1371. //  !(cur_flag+g_nMapWidth+1)->marked &&
  1372. //  !(cur_flag-g_nMapWidth-1)->marked &&
  1373. //  !(cur_flag-g_nMapWidth+1)->marked )
  1374. {
  1375. if (i==0) // 基本上这种是噪音
  1376. {
  1377. cur_flag++;
  1378. continue;
  1379. }
  1380. // 孤立的点
  1381. cur_flag->center=1;
  1382. // 保存一下CENTER_POINT信息
  1383. pt.x=x;
  1384. pt.y=y;
  1385. pt.radius=i+4+pre_shrink_count*2;
  1386. points_temp.push_back(pt);
  1387. cur_flag++;
  1388. continue;
  1389. }
  1390. else
  1391. MarkIt(x,y); // 判断是否需要保存
  1392. if (m_bFullEdge) // 需要保存!
  1393. SaveIt(x,y,i+6);
  1394. }
  1395. }
  1396. cur_flag++;
  1397. }
  1398. cur_flag=g_pFlags;
  1399. for(y = 0; y < g_nMapHeight; y++)
  1400. for(x = 0; x < g_nMapWidth; x++)
  1401. {
  1402. // 去掉边界!
  1403. if (cur_flag->edged)
  1404. {
  1405. changed=true;
  1406. cur_flag->marked=0;
  1407. }
  1408. cur_flag++;
  1409. }
  1410. if (i%2==0)
  1411. GenEdge4();
  1412. else
  1413. GenEdge();
  1414. if (!changed)
  1415. break;
  1416. }
  1417. // 清除visited标志
  1418. cur_flag=g_pFlags;
  1419. for(y = 0; y < g_nMapHeight; y++)
  1420. for(x = 0; x < g_nMapWidth; x++)
  1421. {
  1422. cur_flag->visited=0;
  1423. cur_flag++;
  1424. }
  1425. // 取平均值,获得中心点
  1426. vector<CENTER_POINT> points;
  1427. cur_flag=g_pFlags;
  1428. for(y = 0; y < g_nMapHeight; y++)
  1429. for(x = 0; x < g_nMapWidth; x++)
  1430. {
  1431. if (y>0 && y<g_nMapHeight-1 && x>0 && x<g_nMapWidth-1) // 最边上的不用处理
  1432. {
  1433. if (cur_flag->center)
  1434. {
  1435. if ( !(cur_flag-1)->center && !(cur_flag+1)->center &&
  1436.  !(cur_flag+g_nMapWidth)->center &&
  1437.  !(cur_flag-g_nMapWidth)->center &&
  1438.  !(cur_flag+g_nMapWidth-1)->center &&
  1439.  !(cur_flag+g_nMapWidth+1)->center &&
  1440.  !(cur_flag-g_nMapWidth-1)->center &&
  1441.  !(cur_flag-g_nMapWidth+1)->center )
  1442. {
  1443. // 孤立的点
  1444. pt.x=x;
  1445. pt.y=y;
  1446. points.push_back(pt);
  1447. cur_flag++;
  1448. continue;
  1449. }
  1450. else
  1451. {
  1452. tot_area=0;
  1453. max_radius=0;
  1454. tot_x=0;
  1455. tot_y=0;
  1456. CalcCenterArea(x,y);
  1457. pt.x=tot_x/tot_area;
  1458. pt.y=tot_y/tot_area;
  1459. pt.radius=max_radius;
  1460. g_pFlags[pt.y*g_nMapWidth+pt.x].center=1;
  1461. points.push_back(pt);
  1462. }
  1463. }
  1464. }
  1465. cur_flag++;
  1466. }
  1467. m_vCenterPoints.clear();
  1468. int x0,y0;
  1469. bool adj;
  1470. // 清除center标志
  1471. cur_flag=g_pFlags;
  1472. for(y = 0; y < g_nMapHeight; y++)
  1473. for(x = 0; x < g_nMapWidth; x++)
  1474. {
  1475. cur_flag->center=0;
  1476. cur_flag++;
  1477. }
  1478. // 平均化相近的中心点
  1479. for (i=0;i<points.size();i++)
  1480. {
  1481. x0=points.at(i).x;
  1482. y0=points.at(i).y;
  1483. adj=false;
  1484. for (j=i+1;j<points.size();j++)
  1485. {
  1486. x=points.at(j).x;
  1487. y=points.at(j).y;
  1488. if (abs(x0-x)+abs(y0-y)<10) // 相近
  1489. {
  1490. points.at(j).x=(x+x0)/2;
  1491. points.at(j).y=(y+y0)/2;
  1492. points.at(j).radius=points.at(i).radius;
  1493. points.erase(&points.at(j));
  1494. i--;
  1495. adj=true;
  1496. break;
  1497. }
  1498. }
  1499. if (!adj) // 非相近
  1500. {
  1501. if (points.at(i).radius>5)
  1502. {
  1503. m_vCenterPoints.push_back(points.at(i));
  1504. g_pFlags[points.at(i).y*g_nMapWidth+points.at(i).x].center=1;
  1505. }
  1506. }
  1507. }
  1508. double max_intensity=0.0;
  1509. double hue,inte;
  1510. double min_hue=255.0;
  1511. double max_hue=0.0;
  1512. double overmax;
  1513. double overmin;
  1514. if (m_vAllSelected.size()>0) // 保存着的选项
  1515. {
  1516. for (int i=0;i<m_vAllSelected.size();i++)
  1517. {
  1518. if (m_vAllSelected.at(i).Intensity>max_intensity)
  1519. max_intensity=m_vAllSelected.at(i).Intensity;
  1520. if (m_vAllSelected.at(i).Hue>max_hue)
  1521. max_hue=m_vAllSelected.at(i).Hue;
  1522. if (m_vAllSelected.at(i).Hue<min_hue)
  1523. min_hue=m_vAllSelected.at(i).Hue;
  1524. }
  1525. InvalidateRect(0,TRUE);
  1526. MessageBox("准备开始修正");
  1527. }
  1528. else
  1529. {
  1530. InvalidateRect(0,TRUE);
  1531. return;
  1532. }
  1533. max_hue+=max_hue*0.02;
  1534. min_hue-=min_hue*0.02;
  1535. overmax=max_hue*1.08;
  1536. overmin=min_hue*0.92;
  1537. int r0,r;
  1538. int tx,ty;
  1539. int area,toobad;
  1540. // 去掉被包含的圆
  1541. for (i=0;i<m_vCenterPoints.size();i++)
  1542. {
  1543. x0=m_vCenterPoints.at(i).x;
  1544. y0=m_vCenterPoints.at(i).y;
  1545. r0=m_vCenterPoints.at(i).radius;
  1546. for (j=i+1;j<m_vCenterPoints.size();j++)
  1547. {
  1548. x=m_vCenterPoints.at(j).x;
  1549. y=m_vCenterPoints.at(j).y;
  1550. r=m_vCenterPoints.at(j).radius;
  1551. if (DISTANCE(x0,y0,x,y)<abs(r0-r)+4) // 包含
  1552. {
  1553. CDC *pdc=GetDC();
  1554. CENTER_POINT centerp;
  1555. CPen pen;
  1556. pen.CreatePen(PS_DOT, 1, RGB(255,0,0));
  1557. pdc->SelectObject(pen);
  1558. if (r0>r) // 去掉r0
  1559. centerp=m_vCenterPoints.at(i);
  1560. else
  1561. centerp=m_vCenterPoints.at(j);
  1562. Arc(pdc->m_hDC,
  1563. centerp.x-scroll_lefttop.x-centerp.radius,
  1564. centerp.y-scroll_lefttop.y-centerp.radius,
  1565. centerp.x-scroll_lefttop.x+centerp.radius,
  1566. centerp.y-scroll_lefttop.y+centerp.radius,
  1567. centerp.x-scroll_lefttop.x+centerp.radius,
  1568. centerp.y-scroll_lefttop.y,
  1569. centerp.x-scroll_lefttop.x+centerp.radius,
  1570. centerp.y-scroll_lefttop.y
  1571. );
  1572. DeleteObject(pen);
  1573. if (r0>r) // 去掉r0
  1574. {
  1575. m_vCenterPoints.erase(&m_vCenterPoints.at(i));
  1576. i--;
  1577. }
  1578. else
  1579. m_vCenterPoints.erase(&m_vCenterPoints.at(j));
  1580. }
  1581. }
  1582. }
  1583. vector<CENTER_POINT> tocheck;
  1584. int n,size,total;
  1585. bool isok;
  1586. // 去掉潜在的错误(同两个圆相交,并且不相交的部分是噪声)
  1587. for (i=0;i<m_vCenterPoints.size();i++)
  1588. {
  1589. tocheck.clear();
  1590. x0=m_vCenterPoints.at(i).x;
  1591. y0=m_vCenterPoints.at(i).y;
  1592. r0=m_vCenterPoints.at(i).radius;
  1593. for (j=0;j<m_vCenterPoints.size();j++)
  1594. {
  1595. if (i==j)
  1596. continue;
  1597. x=m_vCenterPoints.at(j).x;
  1598. y=m_vCenterPoints.at(j).y;
  1599. r=m_vCenterPoints.at(j).radius;
  1600. if (DISTANCE(x0,y0,x,y)<abs(r0+r)) // 相交
  1601. {
  1602. pt.x=x; pt.y=y; pt.radius=r;
  1603. tocheck.push_back(pt);
  1604. }
  1605. }
  1606. size=tocheck.size();
  1607. if (size>1) // 同两个以上的圆相交
  1608. {
  1609. area=0;
  1610. total=0;
  1611. toobad=0;
  1612. for (tx=x0-r0;tx<x0+r0;tx++)
  1613. for (ty=y0-r0;ty<y0+r0;ty++)
  1614. {
  1615. if (DISTANCE(x0,y0,tx,ty)<r0) // 所有圆内部的点
  1616. {
  1617. if (tx<0 || tx>g_nMapWidth-1 || ty<0 || ty>g_nMapHeight-1)
  1618. continue;
  1619. isok=true;
  1620. for (n=0;n<size;n++)
  1621. {
  1622. pt=tocheck.at(n);// 取得
  1623. if (DISTANCE(tx,ty,pt.x,pt.y)<pt.radius)
  1624. {
  1625. isok=false;
  1626. break;
  1627. }
  1628. }
  1629. if (isok) // 同所有的圆都不相交的部分
  1630. {
  1631. total++;
  1632. hue=g_pHSIBuffer[ty*g_nMapWidth+tx].Hue;
  1633. inte=g_pHSIBuffer[ty*g_nMapWidth+tx].Intensity;
  1634. if (inte>max_intensity || hue > max_hue || hue < min_hue)
  1635. area++;
  1636. if (hue > overmax || hue < overmin)
  1637. toobad++;
  1638. }
  1639. }
  1640. }
  1641. if (total<r0*r0 || (total<r0*r0*1.5 && area>total*0.5) || toobad>total/6) // need adjust
  1642. {
  1643. CDC *pdc=GetDC();
  1644. CENTER_POINT centerp;
  1645. CPen pen;
  1646. if (total<r0*r0) // 红色 面积过小
  1647. pen.CreatePen(PS_SOLID, 2, RGB(255,0,0));
  1648. else if (toobad>total/6) // 绿色 错误点过多
  1649. pen.CreatePen(PS_SOLID, 2, RGB(0,255,0));
  1650. else // 浅蓝 误差过大
  1651. pen.CreatePen(PS_SOLID, 2, RGB(0,255,255));
  1652. pdc->SelectObject(pen);
  1653. centerp=m_vCenterPoints.at(i);
  1654. Arc(pdc->m_hDC,
  1655. centerp.x-scroll_lefttop.x-centerp.radius,
  1656. centerp.y-scroll_lefttop.y-centerp.radius,
  1657. centerp.x-scroll_lefttop.x+centerp.radius,
  1658. centerp.y-scroll_lefttop.y+centerp.radius,
  1659. centerp.x-scroll_lefttop.x+centerp.radius,
  1660. centerp.y-scroll_lefttop.y,
  1661. centerp.x-scroll_lefttop.x+centerp.radius,
  1662. centerp.y-scroll_lefttop.y
  1663. );
  1664. DeleteObject(pen);
  1665. m_vCenterPoints.erase(&m_vCenterPoints.at(i));
  1666. i--;
  1667. }
  1668. }
  1669. }
  1670. for (i=0;i<m_vCenterPoints.size();i++)
  1671. {
  1672. r0=m_vCenterPoints.at(i).radius;
  1673. if (r0<10)
  1674. {
  1675. x0=m_vCenterPoints.at(i).x;
  1676. y0=m_vCenterPoints.at(i).y;
  1677. area=0;
  1678. toobad=0;
  1679. for (tx=x0-r0;tx<x0+r0;tx++)
  1680. for (ty=y0-r0;ty<y0+r0;ty++)
  1681. if (sqrt((x0-tx)*(x0-tx)+(y0-ty)*(y0-ty))<r0)
  1682. {
  1683. if (tx<0 || tx>g_nMapWidth-1 || ty<0 || ty>g_nMapHeight-1)
  1684. continue;
  1685. hue=g_pHSIBuffer[ty*g_nMapWidth+tx].Hue;
  1686. if (hue > max_hue || hue < min_hue)
  1687. area++;
  1688. if (hue > overmax || hue < overmin)
  1689. toobad++;
  1690. }
  1691. if (area>r0*r0 || toobad>r0*r0/2) // need adjust
  1692. {
  1693. CDC *pdc=GetDC();
  1694. CENTER_POINT centerp;
  1695. CPen pen;
  1696. if (toobad>r0*r0/2)
  1697. pen.CreatePen(PS_DOT, 1, RGB(0,128,0));
  1698. else
  1699. pen.CreatePen(PS_DOT, 1, RGB(0,0,255));
  1700. pdc->SelectObject(pen);
  1701. centerp=m_vCenterPoints.at(i);
  1702. Arc(pdc->m_hDC,
  1703. centerp.x-scroll_lefttop.x-centerp.radius,
  1704. centerp.y-scroll_lefttop.y-centerp.radius,
  1705. centerp.x-scroll_lefttop.x+centerp.radius,
  1706. centerp.y-scroll_lefttop.y+centerp.radius,
  1707. centerp.x-scroll_lefttop.x+centerp.radius,
  1708. centerp.y-scroll_lefttop.y,
  1709. centerp.x-scroll_lefttop.x+centerp.radius,
  1710. centerp.y-scroll_lefttop.y
  1711. );
  1712. DeleteObject(pen);
  1713. m_vCenterPoints.erase(&m_vCenterPoints.at(i));
  1714. i--;
  1715. }
  1716. }
  1717. }
  1718. /* // 去掉潜在的错误(相交,并且包含许多色调范围外的象素)
  1719. for (i=0;i<m_vCenterPoints.size();i++)
  1720. {
  1721. x0=m_vCenterPoints.at(i).x;
  1722. y0=m_vCenterPoints.at(i).y;
  1723. r0=m_vCenterPoints.at(i).radius;
  1724. for (j=i+1;j<m_vCenterPoints.size();j++)
  1725. {
  1726. x=m_vCenterPoints.at(j).x;
  1727. y=m_vCenterPoints.at(j).y;
  1728. r=m_vCenterPoints.at(j).radius;
  1729. if (sqrt((x0-x)*(x0-x)+(y0-y)*(y0-y))<abs(r0+r)) // 相交
  1730. {
  1731. area=0;
  1732. toobad=0;
  1733. for (tx=x0-r0;tx<x0+r0;tx++)
  1734. for (ty=y0-r0;ty<y0+r0;ty++)
  1735. if (sqrt((x0-tx)*(x0-tx)+(y0-ty)*(y0-ty))<r0)
  1736. {
  1737. if (tx<0 || tx>g_nMapWidth-1 || ty<0 || ty>g_nMapHeight-1)
  1738. continue;
  1739. hue=g_pHSIBuffer[ty*g_nMapWidth+tx].Hue;
  1740. if (hue > max_hue || hue < min_hue)
  1741. area++;
  1742. if (hue > overmax || hue < overmin)
  1743. toobad++;
  1744. }
  1745. if (area>r0*r0 || toobad>r0*r0/2) // need adjust
  1746. {
  1747. InvalidateRect(0,TRUE);
  1748. {
  1749. CDC *pdc=GetDC();
  1750. CENTER_POINT centerp;
  1751. CPen pen;
  1752. if (toobad>r0*r0/6)
  1753. pen.CreatePen(PS_SOLID, 3, RGB(255,0,0));
  1754. else
  1755. pen.CreatePen(PS_SOLID, 3, RGB(0,0,0));
  1756. pdc->SelectObject(pen);
  1757. centerp=m_vCenterPoints.at(i);
  1758. Arc(pdc->m_hDC,
  1759. centerp.x-scroll_lefttop.x-centerp.radius,
  1760. centerp.y-scroll_lefttop.y-centerp.radius,
  1761. centerp.x-scroll_lefttop.x+centerp.radius,
  1762. centerp.y-scroll_lefttop.y+centerp.radius,
  1763. centerp.x-scroll_lefttop.x+centerp.radius,
  1764. centerp.y-scroll_lefttop.y,
  1765. centerp.x-scroll_lefttop.x+centerp.radius,
  1766. centerp.y-scroll_lefttop.y
  1767. );
  1768. DeleteObject(pen);
  1769. }
  1770. m_vCenterPoints.erase(&m_vCenterPoints.at(i));
  1771. i--;
  1772. Sleep(2000);
  1773. break;
  1774. }
  1775. }
  1776. }
  1777. }
  1778. */// Sleep(10000);
  1779. // InvalidateRect(0,TRUE);
  1780. }
  1781. else
  1782. MessageBox("请先打开图像文件!");
  1783. }
  1784. void CCellView::MarkIt(int i, int j)
  1785. {
  1786. // if (!m_bFullEdge)
  1787. // return; // 如果已经知道不是FullEdge了,那么不用做了!
  1788. if (i<1 || i>g_nMapWidth-2 || j<1 || j>g_nMapHeight-2)
  1789. {
  1790. return;
  1791. }
  1792. g_pFlags[j*g_nMapWidth+i].visited=1;
  1793. if ( !g_pFlags[j*g_nMapWidth+i-1].visited && // 没有访问过
  1794.   g_pFlags[j*g_nMapWidth+i-1].marked ) // 标志了
  1795. {
  1796. if (g_pFlags[j*g_nMapWidth+i-1].edged ) // 并且是边缘
  1797. MarkIt(i-1,j); // 左边
  1798. else
  1799. m_bFullEdge=false;
  1800. }
  1801. if ( !g_pFlags[j*g_nMapWidth+i+1].visited && // 没有访问过
  1802.   g_pFlags[j*g_nMapWidth+i+1].marked ) // 标志了
  1803. {
  1804. if (g_pFlags[j*g_nMapWidth+i+1].edged ) // 并且是边缘
  1805. MarkIt(i+1,j); // 右边
  1806. else
  1807. m_bFullEdge=false;
  1808. }
  1809. if ( !g_pFlags[(j-1)*g_nMapWidth+i].visited && // 没有访问过
  1810.   g_pFlags[(j-1)*g_nMapWidth+i].marked ) // 标志了
  1811. {
  1812. if (g_pFlags[(j-1)*g_nMapWidth+i].edged ) // 并且是边缘
  1813. MarkIt(i,j-1); // 上面
  1814. else
  1815. m_bFullEdge=false;
  1816. }
  1817. if ( !g_pFlags[(j+1)*g_nMapWidth+i].visited && // 没有访问过
  1818.   g_pFlags[(j+1)*g_nMapWidth+i].marked ) // 标志了
  1819. {
  1820. if (g_pFlags[(j+1)*g_nMapWidth+i].edged ) // 并且是边缘
  1821. MarkIt(i,j+1); // 下面
  1822. else
  1823. m_bFullEdge=false;
  1824. }
  1825. if ( !g_pFlags[(j-1)*g_nMapWidth+i-1].visited && // 没有访问过
  1826.   g_pFlags[(j-1)*g_nMapWidth+i-1].marked ) // 标志了
  1827. {
  1828. if (g_pFlags[(j-1)*g_nMapWidth+i-1].edged ) // 并且是边缘
  1829. MarkIt(i-1,j-1); // 左上
  1830. else
  1831. m_bFullEdge=false;
  1832. }
  1833. if ( !g_pFlags[(j+1)*g_nMapWidth+i-1].visited && // 没有访问过
  1834.   g_pFlags[(j+1)*g_nMapWidth+i-1].marked ) // 标志了
  1835. {
  1836. if (g_pFlags[(j+1)*g_nMapWidth+i-1].edged ) // 并且是边缘
  1837. MarkIt(i-1,j+1); // 左下
  1838. else
  1839. m_bFullEdge=false;
  1840. }
  1841. if ( !g_pFlags[(j-1)*g_nMapWidth+i+1].visited && // 没有访问过
  1842.   g_pFlags[(j-1)*g_nMapWidth+i+1].marked ) // 标志了
  1843. {
  1844. if (g_pFlags[(j-1)*g_nMapWidth+i+1].edged ) // 并且是边缘
  1845. MarkIt(i+1,j-1); // 右上
  1846. else
  1847. m_bFullEdge=false;
  1848. }
  1849. if ( !g_pFlags[(j+1)*g_nMapWidth+i+1].visited && // 没有访问过
  1850.   g_pFlags[(j+1)*g_nMapWidth+i+1].marked ) // 标志了
  1851. {
  1852. if (g_pFlags[(j+1)*g_nMapWidth+i+1].edged ) // 并且是边缘
  1853. MarkIt(i+1,j+1); // 右下
  1854. else
  1855. m_bFullEdge=false;
  1856. }
  1857. }
  1858. void CCellView::SaveIt(int i, int j, int radius)
  1859. {
  1860. if (i<1 || i>g_nMapWidth-2 || j<1 || j>g_nMapHeight-2)
  1861. {
  1862. return;
  1863. }
  1864. CENTER_POINT pt;
  1865. pt.x=i;
  1866. pt.y=j;
  1867. pt.radius=radius;
  1868. points_temp.push_back(pt);
  1869. // marke current point
  1870. g_pFlags[j*g_nMapWidth+i].center=1;
  1871. g_pFlags[j*g_nMapWidth+i].visited=0;
  1872. if ( g_pFlags[j*g_nMapWidth+i-1].visited )
  1873. {
  1874. SaveIt(i-1,j,radius);
  1875. }
  1876. if ( g_pFlags[j*g_nMapWidth+i+1].visited )
  1877. {
  1878. SaveIt(i+1,j,radius);
  1879. }
  1880. if ( g_pFlags[(j-1)*g_nMapWidth+i].visited )
  1881. {
  1882. SaveIt(i,j-1,radius);
  1883. }
  1884. if ( g_pFlags[(j+1)*g_nMapWidth+i].visited )
  1885. {
  1886. SaveIt(i,j+1,radius);
  1887. }
  1888. if ( g_pFlags[(j+1)*g_nMapWidth+i+1].visited )
  1889. {
  1890. SaveIt(i+1,j+1,radius);
  1891. }
  1892. if ( g_pFlags[(j+1)*g_nMapWidth+i-1].visited )
  1893. {
  1894. SaveIt(i-1,j+1,radius);
  1895. }
  1896. if ( g_pFlags[(j-1)*g_nMapWidth+i+1].visited )
  1897. {
  1898. SaveIt(i+1,j-1,radius);
  1899. }
  1900. if ( g_pFlags[(j-1)*g_nMapWidth+i-1].visited )
  1901. {
  1902. SaveIt(i-1,j-1,radius);
  1903. }
  1904. }
  1905. // 利用sobel信息进行修正
  1906. void CCellView::OnProcSobelCorrect() 
  1907. {
  1908. if (!g_hBitmap)
  1909. {
  1910. MessageBox("请先打开图片");
  1911. return;
  1912. }
  1913. // backup
  1914. memcpy(g_pFlagsBack,g_pFlags,
  1915. sizeof(FLAGS)*g_nMapWidth*g_nMapHeight);
  1916. double max_intensity=0.0;
  1917. double min_hue=255.0;
  1918. double max_hue=0.0;
  1919. if (m_vAllSelected.size()) // 还保存着啊!
  1920. for (int i=0;i<m_vAllSelected.size();i++)
  1921. {
  1922. if (m_vAllSelected.at(i).Intensity>max_intensity)
  1923. max_intensity=m_vAllSelected.at(i).Intensity;
  1924. if (m_vAllSelected.at(i).Hue>max_hue)
  1925. max_hue=m_vAllSelected.at(i).Hue;
  1926. if (m_vAllSelected.at(i).Hue<min_hue)
  1927. min_hue=m_vAllSelected.at(i).Hue;
  1928. }
  1929. max_hue-=max_hue*0.1;
  1930. min_hue+=min_hue*0.1;
  1931. int x,y;
  1932. FLAGS *cur_flag=g_pFlags;
  1933. BYTE  *cur_sobel=g_pSobelResult;
  1934. HSI   *cur_hsi=g_pHSIBuffer;
  1935. for(y = 0; y < g_nMapHeight; y++)
  1936. for(x = 0; x < g_nMapWidth; x++)
  1937. {
  1938. if ( cur_flag->marked )
  1939. {
  1940. if (*cur_sobel > 40) // 参数需要调整
  1941. {
  1942. if (max_intensity>0.01)
  1943. if (/*cur_hsi->Intensity>max_intensity &&*/ // 亮度大于最大值并且色调超出范围
  1944. (cur_hsi->Hue>max_hue || cur_hsi->Hue<min_hue) )
  1945. cur_flag->marked=0;
  1946. }
  1947. }
  1948. cur_hsi++;
  1949. cur_flag++;
  1950. cur_sobel++;
  1951. }
  1952. GenEdge();
  1953. InvalidateRect(0,TRUE);
  1954. }
  1955. void CCellView::CalcCenterArea(int i, int j)
  1956. {
  1957. if (i<1 || i>g_nMapWidth-2 || j<1 || j>g_nMapHeight-2)
  1958. {
  1959. return;
  1960. }
  1961. tot_area++;
  1962. tot_x+=i;
  1963. tot_y+=j;
  1964. g_pFlags[j*g_nMapWidth+i].center=0;
  1965. for ( int n=0; n<points_temp.size(); n++ )
  1966. {
  1967. if (points_temp.at(n).x==i && points_temp.at(n).y==j)
  1968. {
  1969. if (points_temp.at(n).radius>max_radius)
  1970. max_radius=points_temp.at(n).radius;
  1971. break;
  1972. }
  1973. }
  1974. if ( g_pFlags[j*g_nMapWidth+i-1].center )
  1975. {
  1976. CalcCenterArea(i-1,j);
  1977. }
  1978. if ( g_pFlags[j*g_nMapWidth+i+1].center )
  1979. {
  1980. CalcCenterArea(i+1,j);
  1981. }
  1982. if ( g_pFlags[(j-1)*g_nMapWidth+i].center )
  1983. {
  1984. CalcCenterArea(i,j-1);
  1985. }
  1986. if ( g_pFlags[(j+1)*g_nMapWidth+i].center )
  1987. {
  1988. CalcCenterArea(i,j+1);
  1989. }
  1990. if ( g_pFlags[(j+1)*g_nMapWidth+i+1].center )
  1991. {
  1992. CalcCenterArea(i+1,j+1);
  1993. }
  1994. if ( g_pFlags[(j+1)*g_nMapWidth+i-1].center )
  1995. {
  1996. CalcCenterArea(i-1,j+1);
  1997. }
  1998. if ( g_pFlags[(j-1)*g_nMapWidth+i+1].center )
  1999. {
  2000. CalcCenterArea(i+1,j-1);
  2001. }
  2002. if ( g_pFlags[(j-1)*g_nMapWidth+i-1].center )
  2003. {
  2004. CalcCenterArea(i-1,j-1);
  2005. }
  2006. }
  2007. void CCellView::OnProcForceKill() 
  2008. {
  2009. // TODO: Add your command handler code here
  2010. if(g_hBitmap)
  2011. {
  2012. m_bForceKill = true;
  2013. }
  2014. else
  2015. MessageBox("请先打开图像文件!");
  2016. }
  2017. void CCellView::OnProcForceSele() 
  2018. {
  2019. // TODO: Add your command handler code here
  2020. if(g_hBitmap)
  2021. {
  2022. m_bForceAdd = true;
  2023. }
  2024. else
  2025. MessageBox("请先打开图像文件!");
  2026. }
  2027. void CCellView::OnProcDilation() 
  2028. {
  2029. if (g_bDir4Dil)
  2030. g_bDir4Dil=false;
  2031. else g_bDir4Dil=true;
  2032. // backup
  2033. memcpy(g_pFlagsBack,g_pFlags,
  2034. sizeof(FLAGS)*g_nMapWidth*g_nMapHeight);
  2035. // 膨胀
  2036. RGB *cur=g_pImgBuffer;
  2037. FLAGS *cur_flag=g_pFlags;
  2038. vector<long> addr;
  2039. for (int ht=0;ht<g_nMapHeight;ht++)
  2040. for (int wd=0;wd<g_nMapWidth;wd++)
  2041. {
  2042. if (!cur_flag->marked)
  2043. {
  2044. if (ht==0 || wd==0 || ht==g_nMapHeight-1 || wd==g_nMapWidth-1)
  2045. {
  2046. cur++;
  2047. cur_flag++;
  2048. continue;
  2049. }
  2050. else if (g_bDir4Dil)
  2051. {
  2052. if (  (cur_flag-1)->marked || // left
  2053.   (cur_flag+1)->marked || // right
  2054.   (cur_flag-g_nMapWidth-1)->marked || // left up
  2055.   (cur_flag-g_nMapWidth+1)->marked || // right up
  2056.   (cur_flag+g_nMapWidth-1)->marked || // left down
  2057.   (cur_flag+g_nMapWidth+1)->marked || // right down
  2058.   (cur_flag-g_nMapWidth)->marked || // up
  2059.   (cur_flag+g_nMapWidth)->marked ) // down
  2060. addr.push_back((long)cur_flag);
  2061. }
  2062. else
  2063. {
  2064. if (  (cur_flag-1)->marked || // left
  2065.   (cur_flag+1)->marked || // right
  2066.   (cur_flag-g_nMapWidth)->marked || // up
  2067.   (cur_flag+g_nMapWidth)->marked ) // down
  2068. addr.push_back((long)cur_flag);
  2069. }
  2070. }
  2071. cur++;
  2072. cur_flag++;
  2073. }
  2074. int size=addr.size();
  2075. for (int i=0;i<size;i++)
  2076. ((FLAGS *)addr.at(i))->marked=1;
  2077. addr.clear();
  2078. GenEdge();
  2079. InvalidateRect(0,TRUE);
  2080. }
  2081. void CCellView::OnProcErosion() 
  2082. {
  2083. if (g_bDir4Ero)
  2084. g_bDir4Ero=false;
  2085. else g_bDir4Ero=true;
  2086. // backup
  2087. memcpy(g_pFlagsBack,g_pFlags,
  2088. sizeof(FLAGS)*g_nMapWidth*g_nMapHeight);
  2089. // 腐蚀
  2090. RGB *cur=g_pImgBuffer;
  2091. FLAGS *cur_flag=g_pFlags;
  2092. vector<long> addr;
  2093. for (int ht=0;ht<g_nMapHeight;ht++)
  2094. for (int wd=0;wd<g_nMapWidth;wd++)
  2095. {
  2096. if (cur_flag->marked)
  2097. {
  2098. if (ht==0 || wd==0 || ht==g_nMapHeight-1 || wd==g_nMapWidth-1)
  2099. {
  2100. cur_flag->marked=0;
  2101. cur++;
  2102. cur_flag++;
  2103. continue;
  2104. }
  2105. else if (g_bDir4Ero)
  2106. {
  2107. if (  !(cur_flag-1)->marked || // left
  2108.   !(cur_flag+1)->marked || // right
  2109.   !(cur_flag-g_nMapWidth-1)->marked || // left up
  2110.   !(cur_flag-g_nMapWidth+1)->marked || // right up
  2111.   !(cur_flag+g_nMapWidth-1)->marked || // left down
  2112.   !(cur_flag+g_nMapWidth+1)->marked || // right down
  2113.   !(cur_flag-g_nMapWidth)->marked || // up
  2114.   !(cur_flag+g_nMapWidth)->marked ) // down
  2115. addr.push_back((long)cur_flag);
  2116. }
  2117. else
  2118. {
  2119. if (  !(cur_flag-1)->marked || // left
  2120.   !(cur_flag+1)->marked || // right
  2121.   !(cur_flag-g_nMapWidth)->marked || // up
  2122.   !(cur_flag+g_nMapWidth)->marked ) // down
  2123. addr.push_back((long)cur_flag);
  2124. }
  2125. }
  2126. cur++;
  2127. cur_flag++;
  2128. }
  2129. int size=addr.size();
  2130. for (int i=0;i<size;i++)
  2131. ((FLAGS *)addr.at(i))->marked=0;
  2132. addr.clear();
  2133. GenEdge();
  2134. InvalidateRect(0,TRUE);
  2135. }
  2136. void CCellView::OnProcSmooth() 
  2137. {
  2138. int wd,ht;
  2139. if(g_hBitmap)
  2140. {
  2141. RGB *g_pTemp=new RGB[g_nMapWidth*g_nMapHeight];
  2142. RGB *ptemp=g_pTemp;
  2143. memset(g_pTemp,0,g_nMapWidth*g_nMapHeight*sizeof(RGB));
  2144. RGB *cur=g_pImgBuffer;
  2145. for (ht=0;ht<g_nMapHeight;ht++)
  2146. for (wd=0;wd<g_nMapWidth;wd++)
  2147. {
  2148. if (ht==0 || wd==0 || ht==g_nMapHeight-1 || wd==g_nMapWidth-1)
  2149. { }
  2150. else
  2151. {
  2152. ptemp->r=( (cur-g_nMapWidth-1)->r +
  2153.  (cur-g_nMapWidth  )->r +
  2154.  (cur-g_nMapWidth+1)->r +
  2155.  (cur-1)->r +
  2156.  cur->r +
  2157.  (cur+1)->r +
  2158.  (cur+g_nMapWidth-1)->r +
  2159.  (cur+g_nMapWidth  )->r +
  2160.  (cur+g_nMapWidth+1)->r )/9;
  2161. ptemp->g=( (cur-g_nMapWidth-1)->g +
  2162.  (cur-g_nMapWidth  )->g +
  2163.  (cur-g_nMapWidth+1)->g +
  2164.  (cur-1)->g +
  2165.  cur->g +
  2166.  (cur+1)->g +
  2167.  (cur+g_nMapWidth-1)->g +
  2168.  (cur+g_nMapWidth  )->g +
  2169.  (cur+g_nMapWidth+1)->g )/9;
  2170. ptemp->b=( (cur-g_nMapWidth-1)->b +
  2171.  (cur-g_nMapWidth  )->b +
  2172.  (cur-g_nMapWidth+1)->b +
  2173.  (cur-1)->b +
  2174.  cur->b +
  2175.  (cur+1)->b +
  2176.  (cur+g_nMapWidth-1)->b +
  2177.  (cur+g_nMapWidth  )->b +
  2178.  (cur+g_nMapWidth+1)->b )/9;
  2179. }
  2180. cur++;
  2181. ptemp++;
  2182. }
  2183. memcpy(g_pImgBuffer,g_pTemp,g_nMapWidth*g_nMapHeight*sizeof(RGB));
  2184. delete[] g_pTemp;
  2185. InvalidateRect(0,TRUE);
  2186. }
  2187. else
  2188. MessageBox("请先打开图像文件!");
  2189. }
  2190. void CCellView::CountSeeds()
  2191. {
  2192. int wd,ht;
  2193. FLAGS *cur_flag;
  2194. g_nCellCount=0;
  2195. g_nCellTotArea=0;
  2196. cur_flag=g_pFlags;
  2197. for (ht=0;ht<g_nMapHeight;ht++)
  2198. for (wd=0;wd<g_nMapWidth;wd++)
  2199. {
  2200. cur_flag->visited=0; // clear visited
  2201. cur_flag++;
  2202. }
  2203. cur_flag=g_pFlags;
  2204. for (ht=0;ht<g_nMapHeight;ht++)
  2205. for (wd=0;wd<g_nMapWidth;wd++)
  2206. {
  2207. if (cur_flag->marked && !cur_flag->visited)
  2208. {
  2209. g_nCellCount++;
  2210. ProcessCountSeeds(wd,ht,cur_flag);
  2211. }
  2212. cur_flag++;
  2213. }
  2214. InvalidateRect(0,TRUE);
  2215. char msg[256];
  2216. double avgarea=(double)g_nCellTotArea/(double)g_nCellCount;
  2217. sprintf(msg,"一共有%d个细胞,平均面积%d象素(大约%d*%d)",
  2218. g_nCellCount,(int)avgarea,(int)sqrt(avgarea),(int)sqrt(avgarea));
  2219. MessageBox(msg);
  2220. }
  2221. void CCellView::ProcessCountSeeds(int wd, int ht, FLAGS *curf)
  2222. {
  2223. if (wd<0 || wd>g_nMapWidth-1 || ht<0 || ht>g_nMapHeight-1)
  2224. return;
  2225. FLAGS *next;
  2226. g_nCellTotArea++;
  2227. curf->visited=1;
  2228. if (ht>0)
  2229. {
  2230. next=curf-g_nMapWidth;
  2231. if (next->marked && !next->visited)
  2232. ProcessCountSeeds(wd,ht-1,next); // up
  2233. }
  2234. if (ht<g_nMapHeight-1)
  2235. {
  2236. next=curf+g_nMapWidth;
  2237. if (next->marked && !next->visited)
  2238. ProcessCountSeeds(wd,ht+1,next); // down
  2239. }
  2240. if (wd>0)
  2241. {
  2242. next=curf-1;
  2243. if (next->marked && !next->visited)
  2244. ProcessCountSeeds(wd-1,ht,next); // left
  2245. }
  2246. if (wd<g_nMapWidth-1)
  2247. {
  2248. next=curf+1;
  2249. if (next->marked && !next->visited)
  2250. ProcessCountSeeds(wd+1,ht,next); // right
  2251. }
  2252. }
  2253. void CCellView::OnProcStat() 
  2254. {
  2255. int result;
  2256. result=MessageBox("是否使用中心点标注信息?",NULL,MB_YESNO);
  2257. if (result==IDYES)
  2258. {
  2259. CounterSeedsCenter();
  2260. }
  2261. else
  2262. {
  2263. CountSeeds();
  2264. }
  2265. }
  2266. void CCellView::CounterSeedsCenter()
  2267. {
  2268. if (m_vCenterPoints.size==0)
  2269. MessageBox("中心点数据似乎没有生成...");
  2270. else
  2271. {
  2272. long tota,totr;
  2273. tota=0; totr=0;
  2274. for (int i=0;i<m_vCenterPoints.size();i++)
  2275. {
  2276. tota+=m_vCenterPoints.at(i).radius*m_vCenterPoints.at(i).radius*3.14;
  2277. totr+=m_vCenterPoints.at(i).radius;
  2278. }
  2279. char msg[256];
  2280. sprintf(msg,"共有%d个细胞,平均半径%d,平均面积%d",
  2281. m_vCenterPoints.size(),
  2282. totr/m_vCenterPoints.size(),
  2283. tota/m_vCenterPoints.size());
  2284. MessageBox(msg);
  2285. }
  2286. }
  2287. void CCellView::FillHoles()
  2288. {
  2289. int wd,ht;
  2290. FLAGS *cur_flag=g_pFlags;
  2291. // backup
  2292. memcpy(g_pFlagsBack,g_pFlags,
  2293. sizeof(FLAGS)*g_nMapWidth*g_nMapHeight);
  2294. qSz=g_nMapWidth*g_nMapHeight*2;
  2295. qh=new int[qSz+1];
  2296. if(!qh) return;
  2297. for (ht=0;ht<g_nMapHeight;ht++)
  2298. for (wd=0;wd<g_nMapWidth;wd++)
  2299. {
  2300. cur_flag->visited=0; // clear visited
  2301. cur_flag++;
  2302. }
  2303. cur_flag=g_pFlags;
  2304. for (ht=0;ht<g_nMapHeight;ht++)
  2305. for (wd=0;wd<g_nMapWidth;wd++)
  2306. {
  2307. if (!cur_flag->marked && !cur_flag->visited)
  2308. {
  2309. g_nCellTotArea=0;
  2310. ProcessFillHoles(wd,ht);
  2311. if (g_nCellTotArea<MAX_HOLE && g_nCellTotArea>0)
  2312. FillTheHole(wd,ht);
  2313. // char msg[128];
  2314. // sprintf(msg,"%d",g_nCellTotArea);
  2315. // InvalidateRect(0,TRUE);
  2316. // MessageBox(msg);
  2317. }
  2318. cur_flag++;
  2319. }
  2320. delete[] qh;
  2321. GenEdge();
  2322. InvalidateRect(0,TRUE);
  2323. }
  2324. void CCellView::ProcessFillHoles(int wd, int ht)
  2325. {
  2326. if (wd<0 || wd>g_nMapWidth-1 || ht<0 || ht>g_nMapHeight-1)
  2327. return;
  2328. qst=qh;
  2329. memset(qst,0,qSz); //Clear the contents
  2330. qs=qr=qst;
  2331. *qs=xt=wd;
  2332. qs++;
  2333. *qs=yt=ht;
  2334. qs++;
  2335. g_pFlags[INDEX(xt,yt)].visited=1;
  2336. g_nCellTotArea++;
  2337. //Main queue loop
  2338. while(qr!=qs)
  2339. {
  2340. //Add new members to queue
  2341. //Above current pixel
  2342. if (yt>0)
  2343. if(!g_pFlags[(yt-1)*g_nMapWidth+xt].visited &&
  2344. !g_pFlags[(yt-1)*g_nMapWidth+xt].marked)
  2345. {
  2346. g_nCellTotArea++;
  2347. *qs=xt;
  2348. qs++;
  2349. *qs=yt-1;
  2350. qs++;
  2351. g_pFlags[(yt-1)*g_nMapWidth+xt].visited=1;
  2352. }
  2353. //Below current pixel
  2354. if (yt<g_nMapHeight-1)
  2355. if(!g_pFlags[(yt+1)*g_nMapWidth+xt].visited &&
  2356. !g_pFlags[(yt+1)*g_nMapWidth+xt].marked)
  2357. {
  2358. g_nCellTotArea++;
  2359. *qs=xt;
  2360. qs++;
  2361. *qs=yt+1;
  2362. qs++;
  2363. g_pFlags[(yt+1)*g_nMapWidth+xt].visited=1;
  2364. }
  2365. //Left of current pixel
  2366. if (xt>0)
  2367. if(!g_pFlags[yt*g_nMapWidth+xt-1].visited &&
  2368. !g_pFlags[yt*g_nMapWidth+xt-1].marked)
  2369. {
  2370. g_nCellTotArea++;
  2371. *qs=xt-1;
  2372. qs++;
  2373. *qs=yt;
  2374. qs++;
  2375. g_pFlags[yt*g_nMapWidth+xt-1].visited=1;
  2376. }
  2377. //Right of current pixel
  2378. if (yt<g_nMapWidth-1)
  2379. if(!g_pFlags[yt*g_nMapWidth+xt+1].visited &&
  2380. !g_pFlags[yt*g_nMapWidth+xt+1].marked)
  2381. {
  2382. g_nCellTotArea++;
  2383. *qs=xt+1;
  2384. qs++;
  2385. *qs=yt;
  2386. qs++;
  2387. g_pFlags[yt*g_nMapWidth+xt+1].visited=1;
  2388. }
  2389. //Retrieve current queue member
  2390. qr+=2;
  2391. xt=*qr;
  2392. yt=*(qr+1);
  2393. } //Back to beginning of loop
  2394. }
  2395. void CCellView::FillTheHole(int wd, int ht)
  2396. {
  2397. if (wd<0 || wd>g_nMapWidth-1 || ht<0 || ht>g_nMapHeight-1)
  2398. return;
  2399. g_nCellTotArea--;
  2400. if (g_nCellTotArea<0)
  2401. return;
  2402. qst=qh;
  2403. memset(qst,0,qSz); //Clear the contents
  2404. qs=qr=qst;
  2405. *qs=xt=wd;
  2406. qs++;
  2407. *qs=yt=ht;
  2408. qs++;
  2409. g_pFlags[INDEX(xt,yt)].marked=1;
  2410. //Main queue loop
  2411. while(qr!=qs)
  2412. {
  2413. //Add new members to queue
  2414. //Above current pixel
  2415. if (yt>0)
  2416. if(g_pFlags[(yt-1)*g_nMapWidth+xt].visited &&
  2417. !g_pFlags[(yt-1)*g_nMapWidth+xt].marked)
  2418. {
  2419. g_nCellTotArea--;
  2420. if (g_nCellTotArea<0)
  2421. return;
  2422. *qs=xt;
  2423. qs++;
  2424. *qs=yt-1;
  2425. qs++;
  2426. g_pFlags[(yt-1)*g_nMapWidth+xt].marked=1;
  2427. }
  2428. //Below current pixel
  2429. if (yt<g_nMapHeight-1)
  2430. if(g_pFlags[(yt+1)*g_nMapWidth+xt].visited &&
  2431. !g_pFlags[(yt+1)*g_nMapWidth+xt].marked)
  2432. {
  2433. g_nCellTotArea--;
  2434. if (g_nCellTotArea<0)
  2435. return;
  2436. *qs=xt;
  2437. qs++;
  2438. *qs=yt+1;
  2439. qs++;
  2440. g_pFlags[(yt+1)*g_nMapWidth+xt].marked=1;
  2441. }
  2442. //Left of current pixel
  2443. if (xt>0)
  2444. if(g_pFlags[yt*g_nMapWidth+xt-1].visited &&
  2445. !g_pFlags[yt*g_nMapWidth+xt-1].marked)
  2446. {
  2447. g_nCellTotArea--;
  2448. if (g_nCellTotArea<0)
  2449. return;
  2450. *qs=xt-1;
  2451. qs++;
  2452. *qs=yt;
  2453. qs++;
  2454. g_pFlags[yt*g_nMapWidth+xt-1].marked=1;
  2455. }
  2456. //Right of current pixel
  2457. if (yt<g_nMapWidth-1)
  2458. if(g_pFlags[yt*g_nMapWidth+xt+1].visited &&
  2459. !g_pFlags[yt*g_nMapWidth+xt+1].marked)
  2460. {
  2461. g_nCellTotArea--;
  2462. if (g_nCellTotArea<0)
  2463. return;
  2464. *qs=xt+1;
  2465. qs++;
  2466. *qs=yt;
  2467. qs++;
  2468. g_pFlags[yt*g_nMapWidth+xt+1].marked=1;
  2469. }
  2470. //Retrieve current queue member
  2471. qr+=2;
  2472. xt=*qr;
  2473. yt=*(qr+1);
  2474. } //Back to beginning of loop
  2475. }