DlgMosaics.cpp
上传用户:piaozanzhu
上传日期:2008-02-14
资源大小:212k
文件大小:16k
源码类别:

图形图像处理

开发平台:

Visual C++

  1. // DlgMosaics.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "ImageProcessing.h"
  5. #include "DlgMosaics.h"
  6. #include "ImageProcessingDoc.h"
  7. #include "cdib.h"
  8. #include "CDib.h"
  9. #include "DlgMosaicRes.h"
  10. #include "GlobalApi.h"
  11. #ifdef _DEBUG
  12. #define new DEBUG_NEW
  13. #undef THIS_FILE
  14. static char THIS_FILE[] = __FILE__;
  15. #endif
  16. /////////////////////////////////////////////////////////////////////////////
  17. // CDlgMosaics dialog
  18. CDlgMosaics::CDlgMosaics(CWnd* pParent /*=NULL*/,CImageProcessingDoc* pDoc)
  19. : CDialog(CDlgMosaics::IDD, pParent)
  20. {
  21. //{{AFX_DATA_INIT(CDlgMosaics)
  22. // NOTE: the ClassWizard will add member initialization here
  23. //}}AFX_DATA_INIT
  24. m_pDoc = pDoc;
  25. // 设置计算图象位置标志位位FALSE
  26. m_bCalImgLoc = FALSE;
  27. // 设置基准图象为原始打开的图象
  28. m_pDibInit = pDoc->m_pDibInit;
  29. // 设置待配准图象
  30. m_pDibSamp = new CDib;
  31. left_starX=0;
  32. left_starY=0;
  33. left_endX=0;
  34. left_endY=0;
  35. right_starX=0;
  36. right_starY=0;
  37. right_endX=0;
  38. right_endY=0;
  39. }
  40. void CDlgMosaics::DoDataExchange(CDataExchange* pDX)
  41. {
  42. CDialog::DoDataExchange(pDX);
  43. //{{AFX_DATA_MAP(CDlgMosaics)
  44. // NOTE: the ClassWizard will add DDX and DDV calls here
  45. //}}AFX_DATA_MAP
  46. }
  47. BEGIN_MESSAGE_MAP(CDlgMosaics, CDialog)
  48. //{{AFX_MSG_MAP(CDlgMosaics)
  49. ON_WM_PAINT()
  50. ON_BN_CLICKED(IDC_OPEN, OnOpen)
  51. ON_BN_CLICKED(IDC_MOSAIC, OnMosaic)
  52. //}}AFX_MSG_MAP
  53. END_MESSAGE_MAP()
  54. /////////////////////////////////////////////////////////////////////////////
  55. // CDlgMosaics message handlers
  56. void CDlgMosaics::OnPaint() 
  57. {
  58. CPaintDC dc(this); // device context for painting
  59. // TODO: Add your message handler code here
  60. // 如果还没有计算图象的位置,则进行计算
  61. if(!m_bCalImgLoc){
  62. CalImageLocation();
  63. }
  64. CSize sizeDisplay;
  65. CPoint pointDisplay;
  66. // 显示基准图象
  67. if(!m_pDibInit->IsEmpty()){
  68. sizeDisplay.cx=m_pDibInit->m_lpBMIH->biWidth;
  69. sizeDisplay.cy=m_pDibInit->m_lpBMIH->biHeight;
  70. pointDisplay.x = m_rectInitImage.left;//基准图象
  71. pointDisplay.y = m_rectInitImage.top;
  72. m_pDibInit->Draw(&dc,pointDisplay,sizeDisplay);
  73. }
  74. // 显示待配准图象
  75. if(!m_pDibSamp->IsEmpty()){
  76. sizeDisplay.cx=m_pDibSamp->m_lpBMIH->biWidth;
  77. sizeDisplay.cy=m_pDibSamp->m_lpBMIH->biHeight;
  78. pointDisplay.x = m_rectResltImage.left;
  79. pointDisplay.y = m_rectResltImage.top;
  80. m_pDibSamp->Draw(&dc,pointDisplay,sizeDisplay);
  81. }
  82. // Do not call CDialog::OnPaint() for painting messages
  83. }
  84. void CDlgMosaics::CalImageLocation()
  85. {
  86. CWnd* pWnd=GetDlgItem(IDC_BMP1);//picture 控件的ID
  87. WINDOWPLACEMENT *winPlacement;
  88. winPlacement=new WINDOWPLACEMENT;
  89. pWnd->GetWindowPlacement(winPlacement);
  90. // 图象宽度
  91. int nImageWidth;
  92. nImageWidth = m_pDibInit->m_lpBMIH->biWidth;
  93. // 图象高度
  94. int nImageHeight;
  95. nImageHeight = m_pDibInit->m_lpBMIH->biHeight;
  96. // 调整控件IDC_BMP1的大小位置,并同时设置显示基准图象的位置
  97. if(nImageHeight > 352){
  98. winPlacement->rcNormalPosition.bottom = winPlacement->rcNormalPosition.top + nImageHeight;
  99. m_rectInitImage.bottom = winPlacement->rcNormalPosition.bottom;
  100. m_rectInitImage.top    = winPlacement->rcNormalPosition.top;
  101. }
  102. else{
  103. winPlacement->rcNormalPosition.bottom = winPlacement->rcNormalPosition.top + 352;
  104. m_rectInitImage.bottom = winPlacement->rcNormalPosition.top + 176 + nImageHeight/2;
  105. m_rectInitImage.top    = winPlacement->rcNormalPosition.top + 176 - nImageHeight/2;
  106. }
  107. if(nImageWidth > 288){
  108. winPlacement->rcNormalPosition.right = winPlacement->rcNormalPosition.left + nImageWidth;
  109. m_rectInitImage.right = winPlacement->rcNormalPosition.right;
  110. m_rectInitImage.left  = winPlacement->rcNormalPosition.left;
  111. }
  112. else{
  113. winPlacement->rcNormalPosition.right = winPlacement->rcNormalPosition.left + 288;
  114. m_rectInitImage.right = winPlacement->rcNormalPosition.left + 144 + nImageWidth/2;
  115. m_rectInitImage.left  = winPlacement->rcNormalPosition.left + 144 - nImageWidth/2;
  116. }
  117. // 设置IDC_BMP1控件的大小位置
  118. pWnd->SetWindowPlacement(winPlacement);
  119. // 获得显示基准图象控件的右边位置,以便确认显示待配准图象控件的位置
  120. int nIniImgRight;
  121. nIniImgRight = winPlacement->rcNormalPosition.right;
  122. int  nIniImgLeft;
  123. nIniImgLeft   = winPlacement->rcNormalPosition.left;
  124. // 获得IDC_BMP1控件的下边位置,以便调整其他控件的位置
  125. int nIniImgBottom;
  126. nIniImgBottom = winPlacement->rcNormalPosition.bottom;
  127. // 获得控件IDC_BMP2的句柄,并获得初始位置信息
  128. pWnd=GetDlgItem(IDC_BMP2);
  129. pWnd->GetWindowPlacement(winPlacement);
  130. // 如果还未打开待配准图象,则设置待配准图象大小和基准图象大小相等
  131. if(!m_pDibSamp->IsEmpty()){
  132. nImageWidth  = m_pDibSamp->m_lpBMIH->biWidth;
  133. nImageHeight = m_pDibSamp->m_lpBMIH->biHeight;
  134. }
  135. // 调整控件IDC_BMP2的大小位置,并同时设置显示待配准图象的位置
  136. // 先调整控件的左边位置,和IDC_BMP1控件相隔15个象素
  137. winPlacement->rcNormalPosition.left = nIniImgRight + 15;
  138. if(nImageHeight > 352){
  139. winPlacement->rcNormalPosition.bottom = winPlacement->rcNormalPosition.top + nImageHeight;
  140. m_rectResltImage.bottom = winPlacement->rcNormalPosition.bottom;
  141. m_rectResltImage.top    = winPlacement->rcNormalPosition.top;
  142. }
  143. else{
  144. winPlacement->rcNormalPosition.bottom = winPlacement->rcNormalPosition.top + 352;
  145. m_rectResltImage.bottom = winPlacement->rcNormalPosition.top + 176 + nImageHeight/2;
  146. m_rectResltImage.top    = winPlacement->rcNormalPosition.top + 176 - nImageHeight/2;
  147. }
  148. if(nImageWidth > 288){
  149. winPlacement->rcNormalPosition.right = winPlacement->rcNormalPosition.left + nImageWidth;
  150. m_rectResltImage.right = winPlacement->rcNormalPosition.right;
  151. m_rectResltImage.left  = winPlacement->rcNormalPosition.left;
  152. }
  153. else{
  154. winPlacement->rcNormalPosition.right = winPlacement->rcNormalPosition.left + 288;
  155. m_rectResltImage.right = winPlacement->rcNormalPosition.left + 144 + nImageWidth/2;
  156. m_rectResltImage.left  = winPlacement->rcNormalPosition.left + 144 - nImageWidth/2;
  157. }
  158. // 设置IDC_REG_BMP2控件的大小位置
  159. pWnd->SetWindowPlacement(winPlacement);
  160. if(nIniImgBottom < winPlacement->rcNormalPosition.bottom)
  161. nIniImgBottom = winPlacement->rcNormalPosition.bottom;
  162. nIniImgBottom = winPlacement->rcNormalPosition.bottom;
  163. nIniImgRight  = winPlacement->rcNormalPosition.right;
  164. // 设置控件IDOK的位置大小
  165. pWnd=GetDlgItem(IDOK);
  166. pWnd->GetWindowPlacement(winPlacement);
  167. winPlacement->rcNormalPosition.top = nIniImgBottom +15;
  168. winPlacement->rcNormalPosition.bottom = nIniImgBottom + 60;
  169. pWnd->SetWindowPlacement(winPlacement);
  170. // 设置控件IDCANCEL的位置大小
  171. pWnd=GetDlgItem(IDCANCEL);
  172. pWnd->GetWindowPlacement(winPlacement);
  173. winPlacement->rcNormalPosition.top = nIniImgBottom +15;
  174. winPlacement->rcNormalPosition.bottom = nIniImgBottom + 60;
  175. pWnd->SetWindowPlacement(winPlacement);
  176. // 设置控件IDC_OPEN的位置大小
  177. pWnd=GetDlgItem(IDC_OPEN);
  178. pWnd->GetWindowPlacement(winPlacement);
  179. winPlacement->rcNormalPosition.top = nIniImgBottom +15;
  180. winPlacement->rcNormalPosition.bottom = nIniImgBottom + 60;
  181. pWnd->SetWindowPlacement(winPlacement);
  182. // 设置控件IDC_MOSAIC的位置大小
  183. pWnd=GetDlgItem(IDC_MOSAIC);
  184. pWnd->GetWindowPlacement(winPlacement);
  185. winPlacement->rcNormalPosition.top = nIniImgBottom +15;
  186. winPlacement->rcNormalPosition.bottom = nIniImgBottom + 60;
  187. pWnd->SetWindowPlacement(winPlacement);
  188. /*
  189. // 设置控件IDC_REG_CHOSE_FEATUR的位置大小
  190. pWnd=GetDlgItem(IDC_REG_CHOSE_FEATURE);
  191. pWnd->GetWindowPlacement(winPlacement);
  192. winPlacement->rcNormalPosition.top = nIniImgBottom +15;
  193. winPlacement->rcNormalPosition.bottom = nIniImgBottom + 60;
  194. pWnd->SetWindowPlacement(winPlacement);
  195. */
  196. // 调整此对话框的大小
  197. //pWnd = GetDlgItem(IDD_DLG_REG);
  198. this->GetWindowPlacement(winPlacement);
  199. //winPlacement->rcNormalPosition.top = nIniImgBottom +15;
  200. winPlacement->rcNormalPosition.bottom = nIniImgBottom + 300;
  201. winPlacement->rcNormalPosition.left   = nIniImgLeft   - 20;
  202. winPlacement->rcNormalPosition.right  = nIniImgRight  + 20;
  203. this->SetWindowPlacement(winPlacement);
  204. // 释放已分配内存
  205. delete winPlacement;
  206. // 设置计算图象控件位置标志位为TRUE
  207. m_bCalImgLoc = TRUE;
  208. }
  209. void CDlgMosaics::OnOpen() 
  210. {
  211. // TODO: Add your control notification handler code here
  212. CFileDialog dlg(TRUE,"bmp","*.bmp");
  213. if(dlg.DoModal() == IDOK)
  214. {
  215.  
  216.   CFile file;
  217.  
  218.   CString strPathName;
  219.  
  220. strPathName = dlg.GetPathName();
  221.  
  222. // 打开文件
  223. if( !file.Open(strPathName, CFile::modeRead | CFile::shareDenyWrite))
  224. {
  225. // 返回
  226. return ;
  227. }
  228. // 读入模板图象
  229. if(!m_pDibSamp->Read(&file)){
  230. // 恢复光标形状
  231. EndWaitCursor();
  232. // 清空已分配内存
  233. m_pDibSamp->Empty();
  234. // 返回
  235.   return;
  236. }
  237. }
  238. // 判断是否是8-bpp位图(这里为了方便,只处理8-bpp位图的模板配准,其它的可以类推)
  239. if(m_pDibSamp->m_nColorTableEntries != 256)
  240. {
  241. // 提示用户
  242. MessageBox("目前只支持256色位图!", "系统提示" , MB_ICONINFORMATION | MB_OK);
  243. // 清空已分配内存
  244. m_pDibSamp->Empty();
  245. // 返回
  246. return;
  247. }
  248. // 如果打开新的待配准文件,将图象位置设置标志位设为FALSE,以便再次调整位置
  249. m_bCalImgLoc = FALSE;
  250. // 更新显示
  251. this->UpdateData();
  252. this->Invalidate();
  253. }
  254. void CDlgMosaics::OnMosaic() 
  255. {
  256. // TODO: Add your control notification handler code here
  257. SetComparDIB(m_pDibInit, m_pDibSamp);
  258. }
  259. /***********************************************************************************
  260.                     用于寻找两幅图象相同的部分
  261. ***********************************************************************************/
  262. BOOL CDlgMosaics::SetComparDIB(CDib *bmp1, CDib *bmp2)
  263. {
  264.    
  265. //最大面积
  266.     MAXarea=0;
  267.     //从第二幅图象的最左上角开始,从第一幅图象的最右上角开始,比点比列比块
  268. for(int rightbmp_h=0;rightbmp_h<bmp2->m_lpBMIH->biHeight/3;rightbmp_h++)
  269.     for(int leftbmp_w=bmp1->m_lpBMIH->biWidth;leftbmp_w>=bmp1->m_lpBMIH->biWidth/2;leftbmp_w--)
  270.     for(unsigned int leftbmp_h=0;leftbmp_h<bmp1->m_lpBMIH->biHeight;leftbmp_h++)
  271. {
  272. bmp2->Pix_X=0;                   
  273. bmp2->Pix_Y=rightbmp_h;
  274. bmp1->Pix_X=leftbmp_w;
  275. bmp1->Pix_Y=leftbmp_h;
  276. if(IsSamePix(bmp1,bmp2,bmp1->Pix_X,bmp1->Pix_Y,bmp2->Pix_X,bmp2->Pix_Y))
  277. if(IsSameCol(bmp1,bmp2,bmp1->Pix_X,bmp1->Pix_Y,bmp2->Pix_X,bmp2->Pix_Y))
  278. if(IsSameRect(bmp1,bmp2))
  279. break;
  280. else 
  281. continue;
  282. }
  283. //如果相同块的面积不为零则拼接
  284.      if(MAXarea!=0)
  285.  {
  286.  MergeDIB(bmp1,bmp2);
  287.  return TRUE;
  288.  }
  289.  else
  290.  {
  291.  MessageBox("没有找到合并点,不给予合并");
  292.  return FALSE;
  293.  }
  294. }
  295. /*******************************************************************************
  296. 用于计算点在图象中的位置
  297. *******************************************************************************/
  298. long CDlgMosaics::GetPixOffset(unsigned int X, unsigned int Y, CDib *bmp)
  299. {
  300.    //计算点在图象中的位置
  301. if((X>=0&&X<bmp->m_lpBMIH->biWidth)&&(Y>=0&&Y<bmp->m_lpBMIH->biHeight))
  302. return (Y*bmp->GetDibSaveDim().cx+X*(bmp->m_lpBMIH->biBitCount/8));//要在CDib中定义bmp_line_w和bmp_biBitCount
  303. return 0;
  304. }
  305. /********************************************************************************
  306. 用于判断是否是相同象素的点
  307. ********************************************************************************/
  308. BOOL CDlgMosaics::IsSamePix(CDib *bmp1, CDib *bmp2, int x1, int y1, int x2, int y2)
  309. {
  310. BYTE *p,*q;
  311. p=bmp1->m_lpImage+GetPixOffset(x1,y1,bmp1);
  312. q=bmp2->m_lpImage+GetPixOffset(x2,y2,bmp2);
  313. for(int i=0;i<bmp1->m_lpBMIH->biBitCount/8;i++)
  314. if(abs(p[i]-q[i])>50)
  315. return FALSE;
  316. else 
  317. return TRUE;
  318. }
  319. /************************************************************************************
  320. 用于判断是否是相同列
  321. ************************************************************************************/
  322. BOOL CDlgMosaics::IsSameCol(CDib *bmp1, CDib *bmp2, int x1, int y1, int x2, int y2)
  323. {
  324.     //计算当前象素点到图象1底部的高度
  325. unsigned int below_h1=bmp1->m_lpBMIH->biHeight-y1;
  326. //计算图象2当前象素点到底部的高度
  327. unsigned int below_h2=bmp2->m_lpBMIH->biHeight-y2;
  328. unsigned int h=(below_h1>below_h2)?below_h2:below_h1;
  329. for(unsigned int i=0;i<h;i++)
  330. {
  331. //判断是否是相同的象素点,如果是,则在同一列中往下比较
  332. if(!IsSamePix(bmp1,bmp2,x1,y1,x2,y2))
  333. return FALSE ;
  334. y1++;
  335. y2++;
  336. }
  337. return TRUE;
  338. }
  339. /*************************************************************************************
  340. 用语判断是否是相同的块
  341. *************************************************************************************/
  342. BOOL CDlgMosaics::IsSameRect(CDib *bmp1, CDib *bmp2)
  343. {
  344. unsigned int x1,y1,x2,y2;
  345. unsigned int w1=bmp1->m_lpBMIH->biWidth-bmp1->Pix_X;
  346. unsigned int w2=bmp2->m_lpBMIH->biWidth-bmp2->Pix_X;
  347. unsigned int w=(w1>w2)?w2:w1;
  348. x1=bmp1->Pix_X;y1=bmp1->Pix_Y;
  349. x2=bmp2->Pix_X;y2=bmp2->Pix_Y;
  350. for(unsigned int i=0;i<w;i++)
  351. {     
  352.  //判断是否是相同的列,如果是则向左移动继续比较是否是相同的块
  353. if(!IsSameCol(bmp1,bmp2,x1,y1,x2,y2))
  354. return FALSE;
  355. x1++;
  356. x2++;
  357. }
  358. unsigned int h=(bmp1->m_lpBMIH->biHeight-bmp1->Pix_Y)<(bmp2->m_lpBMIH->biHeight-bmp2->Pix_Y)?
  359. (bmp1->m_lpBMIH->biHeight-bmp1->Pix_Y):(bmp2->m_lpBMIH->biHeight-bmp2->Pix_Y);
  360.     //如果块的面积比先前的最大面积大,则取代之
  361. if(i*h>MAXarea)
  362. {
  363. MAXarea=i*h;
  364. left_starX=bmp1->Pix_X;
  365.     left_starY=bmp1->Pix_Y;
  366. left_endX=i+bmp1->Pix_X;
  367. left_endY=h+bmp1->Pix_Y;
  368. right_starX=bmp2->Pix_X;
  369. right_starY=bmp2->Pix_Y;
  370. right_endX=i+bmp2->Pix_X;
  371. right_endY=h+bmp2->Pix_Y;
  372. }
  373. return TRUE;
  374. }
  375. /*************************************************************************************
  376. 用于图象合并拼接
  377. *************************************************************************************/
  378. void CDlgMosaics::MergeDIB(CDib *bmp1, CDib *bmp2)
  379. {
  380.     
  381. BYTE* unitbuff;
  382. unitbuff=NULL;
  383. unsigned int w1=bmp1->m_lpBMIH->biHeight;
  384. unsigned int w2=bmp2->m_lpBMIH->biHeight;
  385. //新图象的宽
  386. unsigned int unit_w=bmp2->m_lpBMIH->biWidth+left_starX;
  387. //重叠部分的上部高度
  388. unsigned int unit_up=(left_starY>right_starY)?left_starY:right_starY;
  389. //重叠部分的下部高度
  390. unsigned int unit_down=((w1-left_endY)>(w2-right_endY))?(w1-left_endY):(w2-right_endY);
  391. //新图象的高
  392. unsigned int unit_h=unit_up+(left_endY-left_starY)/*重叠部分的高*/+unit_down;
  393. //得到每行实际占的字节数
  394. int byte_w=unit_w*(bmp1->m_lpBMIH->biBitCount/8);
  395. if(byte_w%4)
  396. byte_w=byte_w+(4-byte_w%4);
  397. //得到新图象的数据大小
  398. int imagedata=byte_w*unit_h;
  399. // 将此图象用CDib类封装
  400. m_pDibResult = new CDib(CSize(unit_w,unit_h), 8);
  401. // 计算结果图象的存储大小尺寸
  402. CSize sizeSaveResult;
  403. sizeSaveResult = m_pDibResult->GetDibSaveDim();
  404. // 拷贝调色板
  405. memcpy(m_pDibResult->m_lpvColorTable, m_pDibInit->m_lpvColorTable, m_pDibResult->m_nColorTableEntries*sizeof(RGBQUAD));
  406. // 应用调色板
  407. m_pDibResult->MakePalette();
  408. // 分配内存给合并后的图象
  409. LPBYTE lpImgResult;
  410. lpImgResult = (LPBYTE)new unsigned char[sizeSaveResult.cx * sizeSaveResult.cy];
  411. BYTE *p1,*p2,*p3;
  412. p1=bmp1->m_lpImage+left_starY*bmp1->GetDibSaveDim().cx;  //数据1起始地址
  413. p2=bmp2->m_lpImage+right_starY*bmp2->GetDibSaveDim().cx; //数据2起始地址
  414. p3=lpImgResult;
  415. //保存图象的数据,先把第一幅图象的第一行存进去,再存第二幅图象的第一行,然后再存
  416. //第一幅图象的第二行,再存第二幅图象的第二行,以次类推
  417. for(unsigned int i=0;i<unit_h;i++)
  418. {
  419. memcpy(p3,p1,left_starX*(bmp1->m_lpBMIH->biBitCount/8));
  420. p3+=left_starX*(bmp1->m_lpBMIH->biBitCount/8);
  421. p1+=bmp1->GetDibSaveDim().cx;
  422. memcpy(p3,p2,bmp2->m_lpBMIH->biWidth*(bmp2->m_lpBMIH->biBitCount/8));
  423. p3+=bmp2->m_lpBMIH->biWidth*(bmp2->m_lpBMIH->biBitCount/8);
  424. p2+=bmp2->GetDibSaveDim().cx;
  425.         //如果不是4的倍数则填满为4的倍数
  426. if((unsigned int)(p3-unitbuff)%4!=0)
  427. p3+=4-(unsigned int)((p3-unitbuff)%4);
  428. }
  429. // 将指针赋值给CDib类的数据
  430. m_pDibResult->m_lpImage = lpImgResult;
  431.     //创建显示拼接后图象的对话框
  432. CDlgMosaicRes* pDlg;
  433. pDlg = new CDlgMosaicRes(NULL,  m_pDibResult);
  434. pDlg->DoModal();
  435. // 删除对象
  436. delete pDlg;
  437. return ;
  438. }