DlgMosaics.cpp
资源名称:FINAL.rar [点击查看]
上传用户:piaozanzhu
上传日期:2008-02-14
资源大小:212k
文件大小:16k
源码类别:
图形图像处理
开发平台:
Visual C++
- // DlgMosaics.cpp : implementation file
- //
- #include "stdafx.h"
- #include "ImageProcessing.h"
- #include "DlgMosaics.h"
- #include "ImageProcessingDoc.h"
- #include "cdib.h"
- #include "CDib.h"
- #include "DlgMosaicRes.h"
- #include "GlobalApi.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- /////////////////////////////////////////////////////////////////////////////
- // CDlgMosaics dialog
- CDlgMosaics::CDlgMosaics(CWnd* pParent /*=NULL*/,CImageProcessingDoc* pDoc)
- : CDialog(CDlgMosaics::IDD, pParent)
- {
- //{{AFX_DATA_INIT(CDlgMosaics)
- // NOTE: the ClassWizard will add member initialization here
- //}}AFX_DATA_INIT
- m_pDoc = pDoc;
- // 设置计算图象位置标志位位FALSE
- m_bCalImgLoc = FALSE;
- // 设置基准图象为原始打开的图象
- m_pDibInit = pDoc->m_pDibInit;
- // 设置待配准图象
- m_pDibSamp = new CDib;
- left_starX=0;
- left_starY=0;
- left_endX=0;
- left_endY=0;
- right_starX=0;
- right_starY=0;
- right_endX=0;
- right_endY=0;
- }
- void CDlgMosaics::DoDataExchange(CDataExchange* pDX)
- {
- CDialog::DoDataExchange(pDX);
- //{{AFX_DATA_MAP(CDlgMosaics)
- // NOTE: the ClassWizard will add DDX and DDV calls here
- //}}AFX_DATA_MAP
- }
- BEGIN_MESSAGE_MAP(CDlgMosaics, CDialog)
- //{{AFX_MSG_MAP(CDlgMosaics)
- ON_WM_PAINT()
- ON_BN_CLICKED(IDC_OPEN, OnOpen)
- ON_BN_CLICKED(IDC_MOSAIC, OnMosaic)
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
- /////////////////////////////////////////////////////////////////////////////
- // CDlgMosaics message handlers
- void CDlgMosaics::OnPaint()
- {
- CPaintDC dc(this); // device context for painting
- // TODO: Add your message handler code here
- // 如果还没有计算图象的位置,则进行计算
- if(!m_bCalImgLoc){
- CalImageLocation();
- }
- CSize sizeDisplay;
- CPoint pointDisplay;
- // 显示基准图象
- if(!m_pDibInit->IsEmpty()){
- sizeDisplay.cx=m_pDibInit->m_lpBMIH->biWidth;
- sizeDisplay.cy=m_pDibInit->m_lpBMIH->biHeight;
- pointDisplay.x = m_rectInitImage.left;//基准图象
- pointDisplay.y = m_rectInitImage.top;
- m_pDibInit->Draw(&dc,pointDisplay,sizeDisplay);
- }
- // 显示待配准图象
- if(!m_pDibSamp->IsEmpty()){
- sizeDisplay.cx=m_pDibSamp->m_lpBMIH->biWidth;
- sizeDisplay.cy=m_pDibSamp->m_lpBMIH->biHeight;
- pointDisplay.x = m_rectResltImage.left;
- pointDisplay.y = m_rectResltImage.top;
- m_pDibSamp->Draw(&dc,pointDisplay,sizeDisplay);
- }
- // Do not call CDialog::OnPaint() for painting messages
- }
- void CDlgMosaics::CalImageLocation()
- {
- CWnd* pWnd=GetDlgItem(IDC_BMP1);//picture 控件的ID
- WINDOWPLACEMENT *winPlacement;
- winPlacement=new WINDOWPLACEMENT;
- pWnd->GetWindowPlacement(winPlacement);
- // 图象宽度
- int nImageWidth;
- nImageWidth = m_pDibInit->m_lpBMIH->biWidth;
- // 图象高度
- int nImageHeight;
- nImageHeight = m_pDibInit->m_lpBMIH->biHeight;
- // 调整控件IDC_BMP1的大小位置,并同时设置显示基准图象的位置
- if(nImageHeight > 352){
- winPlacement->rcNormalPosition.bottom = winPlacement->rcNormalPosition.top + nImageHeight;
- m_rectInitImage.bottom = winPlacement->rcNormalPosition.bottom;
- m_rectInitImage.top = winPlacement->rcNormalPosition.top;
- }
- else{
- winPlacement->rcNormalPosition.bottom = winPlacement->rcNormalPosition.top + 352;
- m_rectInitImage.bottom = winPlacement->rcNormalPosition.top + 176 + nImageHeight/2;
- m_rectInitImage.top = winPlacement->rcNormalPosition.top + 176 - nImageHeight/2;
- }
- if(nImageWidth > 288){
- winPlacement->rcNormalPosition.right = winPlacement->rcNormalPosition.left + nImageWidth;
- m_rectInitImage.right = winPlacement->rcNormalPosition.right;
- m_rectInitImage.left = winPlacement->rcNormalPosition.left;
- }
- else{
- winPlacement->rcNormalPosition.right = winPlacement->rcNormalPosition.left + 288;
- m_rectInitImage.right = winPlacement->rcNormalPosition.left + 144 + nImageWidth/2;
- m_rectInitImage.left = winPlacement->rcNormalPosition.left + 144 - nImageWidth/2;
- }
- // 设置IDC_BMP1控件的大小位置
- pWnd->SetWindowPlacement(winPlacement);
- // 获得显示基准图象控件的右边位置,以便确认显示待配准图象控件的位置
- int nIniImgRight;
- nIniImgRight = winPlacement->rcNormalPosition.right;
- int nIniImgLeft;
- nIniImgLeft = winPlacement->rcNormalPosition.left;
- // 获得IDC_BMP1控件的下边位置,以便调整其他控件的位置
- int nIniImgBottom;
- nIniImgBottom = winPlacement->rcNormalPosition.bottom;
- // 获得控件IDC_BMP2的句柄,并获得初始位置信息
- pWnd=GetDlgItem(IDC_BMP2);
- pWnd->GetWindowPlacement(winPlacement);
- // 如果还未打开待配准图象,则设置待配准图象大小和基准图象大小相等
- if(!m_pDibSamp->IsEmpty()){
- nImageWidth = m_pDibSamp->m_lpBMIH->biWidth;
- nImageHeight = m_pDibSamp->m_lpBMIH->biHeight;
- }
- // 调整控件IDC_BMP2的大小位置,并同时设置显示待配准图象的位置
- // 先调整控件的左边位置,和IDC_BMP1控件相隔15个象素
- winPlacement->rcNormalPosition.left = nIniImgRight + 15;
- if(nImageHeight > 352){
- winPlacement->rcNormalPosition.bottom = winPlacement->rcNormalPosition.top + nImageHeight;
- m_rectResltImage.bottom = winPlacement->rcNormalPosition.bottom;
- m_rectResltImage.top = winPlacement->rcNormalPosition.top;
- }
- else{
- winPlacement->rcNormalPosition.bottom = winPlacement->rcNormalPosition.top + 352;
- m_rectResltImage.bottom = winPlacement->rcNormalPosition.top + 176 + nImageHeight/2;
- m_rectResltImage.top = winPlacement->rcNormalPosition.top + 176 - nImageHeight/2;
- }
- if(nImageWidth > 288){
- winPlacement->rcNormalPosition.right = winPlacement->rcNormalPosition.left + nImageWidth;
- m_rectResltImage.right = winPlacement->rcNormalPosition.right;
- m_rectResltImage.left = winPlacement->rcNormalPosition.left;
- }
- else{
- winPlacement->rcNormalPosition.right = winPlacement->rcNormalPosition.left + 288;
- m_rectResltImage.right = winPlacement->rcNormalPosition.left + 144 + nImageWidth/2;
- m_rectResltImage.left = winPlacement->rcNormalPosition.left + 144 - nImageWidth/2;
- }
- // 设置IDC_REG_BMP2控件的大小位置
- pWnd->SetWindowPlacement(winPlacement);
- if(nIniImgBottom < winPlacement->rcNormalPosition.bottom)
- nIniImgBottom = winPlacement->rcNormalPosition.bottom;
- nIniImgBottom = winPlacement->rcNormalPosition.bottom;
- nIniImgRight = winPlacement->rcNormalPosition.right;
- // 设置控件IDOK的位置大小
- pWnd=GetDlgItem(IDOK);
- pWnd->GetWindowPlacement(winPlacement);
- winPlacement->rcNormalPosition.top = nIniImgBottom +15;
- winPlacement->rcNormalPosition.bottom = nIniImgBottom + 60;
- pWnd->SetWindowPlacement(winPlacement);
- // 设置控件IDCANCEL的位置大小
- pWnd=GetDlgItem(IDCANCEL);
- pWnd->GetWindowPlacement(winPlacement);
- winPlacement->rcNormalPosition.top = nIniImgBottom +15;
- winPlacement->rcNormalPosition.bottom = nIniImgBottom + 60;
- pWnd->SetWindowPlacement(winPlacement);
- // 设置控件IDC_OPEN的位置大小
- pWnd=GetDlgItem(IDC_OPEN);
- pWnd->GetWindowPlacement(winPlacement);
- winPlacement->rcNormalPosition.top = nIniImgBottom +15;
- winPlacement->rcNormalPosition.bottom = nIniImgBottom + 60;
- pWnd->SetWindowPlacement(winPlacement);
- // 设置控件IDC_MOSAIC的位置大小
- pWnd=GetDlgItem(IDC_MOSAIC);
- pWnd->GetWindowPlacement(winPlacement);
- winPlacement->rcNormalPosition.top = nIniImgBottom +15;
- winPlacement->rcNormalPosition.bottom = nIniImgBottom + 60;
- pWnd->SetWindowPlacement(winPlacement);
- /*
- // 设置控件IDC_REG_CHOSE_FEATUR的位置大小
- pWnd=GetDlgItem(IDC_REG_CHOSE_FEATURE);
- pWnd->GetWindowPlacement(winPlacement);
- winPlacement->rcNormalPosition.top = nIniImgBottom +15;
- winPlacement->rcNormalPosition.bottom = nIniImgBottom + 60;
- pWnd->SetWindowPlacement(winPlacement);
- */
- // 调整此对话框的大小
- //pWnd = GetDlgItem(IDD_DLG_REG);
- this->GetWindowPlacement(winPlacement);
- //winPlacement->rcNormalPosition.top = nIniImgBottom +15;
- winPlacement->rcNormalPosition.bottom = nIniImgBottom + 300;
- winPlacement->rcNormalPosition.left = nIniImgLeft - 20;
- winPlacement->rcNormalPosition.right = nIniImgRight + 20;
- this->SetWindowPlacement(winPlacement);
- // 释放已分配内存
- delete winPlacement;
- // 设置计算图象控件位置标志位为TRUE
- m_bCalImgLoc = TRUE;
- }
- void CDlgMosaics::OnOpen()
- {
- // TODO: Add your control notification handler code here
- CFileDialog dlg(TRUE,"bmp","*.bmp");
- if(dlg.DoModal() == IDOK)
- {
- CFile file;
- CString strPathName;
- strPathName = dlg.GetPathName();
- // 打开文件
- if( !file.Open(strPathName, CFile::modeRead | CFile::shareDenyWrite))
- {
- // 返回
- return ;
- }
- // 读入模板图象
- if(!m_pDibSamp->Read(&file)){
- // 恢复光标形状
- EndWaitCursor();
- // 清空已分配内存
- m_pDibSamp->Empty();
- // 返回
- return;
- }
- }
- // 判断是否是8-bpp位图(这里为了方便,只处理8-bpp位图的模板配准,其它的可以类推)
- if(m_pDibSamp->m_nColorTableEntries != 256)
- {
- // 提示用户
- MessageBox("目前只支持256色位图!", "系统提示" , MB_ICONINFORMATION | MB_OK);
- // 清空已分配内存
- m_pDibSamp->Empty();
- // 返回
- return;
- }
- // 如果打开新的待配准文件,将图象位置设置标志位设为FALSE,以便再次调整位置
- m_bCalImgLoc = FALSE;
- // 更新显示
- this->UpdateData();
- this->Invalidate();
- }
- void CDlgMosaics::OnMosaic()
- {
- // TODO: Add your control notification handler code here
- SetComparDIB(m_pDibInit, m_pDibSamp);
- }
- /***********************************************************************************
- 用于寻找两幅图象相同的部分
- ***********************************************************************************/
- BOOL CDlgMosaics::SetComparDIB(CDib *bmp1, CDib *bmp2)
- {
- //最大面积
- MAXarea=0;
- //从第二幅图象的最左上角开始,从第一幅图象的最右上角开始,比点比列比块
- for(int rightbmp_h=0;rightbmp_h<bmp2->m_lpBMIH->biHeight/3;rightbmp_h++)
- for(int leftbmp_w=bmp1->m_lpBMIH->biWidth;leftbmp_w>=bmp1->m_lpBMIH->biWidth/2;leftbmp_w--)
- for(unsigned int leftbmp_h=0;leftbmp_h<bmp1->m_lpBMIH->biHeight;leftbmp_h++)
- {
- bmp2->Pix_X=0;
- bmp2->Pix_Y=rightbmp_h;
- bmp1->Pix_X=leftbmp_w;
- bmp1->Pix_Y=leftbmp_h;
- if(IsSamePix(bmp1,bmp2,bmp1->Pix_X,bmp1->Pix_Y,bmp2->Pix_X,bmp2->Pix_Y))
- if(IsSameCol(bmp1,bmp2,bmp1->Pix_X,bmp1->Pix_Y,bmp2->Pix_X,bmp2->Pix_Y))
- if(IsSameRect(bmp1,bmp2))
- break;
- else
- continue;
- }
- //如果相同块的面积不为零则拼接
- if(MAXarea!=0)
- {
- MergeDIB(bmp1,bmp2);
- return TRUE;
- }
- else
- {
- MessageBox("没有找到合并点,不给予合并");
- return FALSE;
- }
- }
- /*******************************************************************************
- 用于计算点在图象中的位置
- *******************************************************************************/
- long CDlgMosaics::GetPixOffset(unsigned int X, unsigned int Y, CDib *bmp)
- {
- //计算点在图象中的位置
- if((X>=0&&X<bmp->m_lpBMIH->biWidth)&&(Y>=0&&Y<bmp->m_lpBMIH->biHeight))
- return (Y*bmp->GetDibSaveDim().cx+X*(bmp->m_lpBMIH->biBitCount/8));//要在CDib中定义bmp_line_w和bmp_biBitCount
- return 0;
- }
- /********************************************************************************
- 用于判断是否是相同象素的点
- ********************************************************************************/
- BOOL CDlgMosaics::IsSamePix(CDib *bmp1, CDib *bmp2, int x1, int y1, int x2, int y2)
- {
- BYTE *p,*q;
- p=bmp1->m_lpImage+GetPixOffset(x1,y1,bmp1);
- q=bmp2->m_lpImage+GetPixOffset(x2,y2,bmp2);
- for(int i=0;i<bmp1->m_lpBMIH->biBitCount/8;i++)
- if(abs(p[i]-q[i])>50)
- return FALSE;
- else
- return TRUE;
- }
- /************************************************************************************
- 用于判断是否是相同列
- ************************************************************************************/
- BOOL CDlgMosaics::IsSameCol(CDib *bmp1, CDib *bmp2, int x1, int y1, int x2, int y2)
- {
- //计算当前象素点到图象1底部的高度
- unsigned int below_h1=bmp1->m_lpBMIH->biHeight-y1;
- //计算图象2当前象素点到底部的高度
- unsigned int below_h2=bmp2->m_lpBMIH->biHeight-y2;
- unsigned int h=(below_h1>below_h2)?below_h2:below_h1;
- for(unsigned int i=0;i<h;i++)
- {
- //判断是否是相同的象素点,如果是,则在同一列中往下比较
- if(!IsSamePix(bmp1,bmp2,x1,y1,x2,y2))
- return FALSE ;
- y1++;
- y2++;
- }
- return TRUE;
- }
- /*************************************************************************************
- 用语判断是否是相同的块
- *************************************************************************************/
- BOOL CDlgMosaics::IsSameRect(CDib *bmp1, CDib *bmp2)
- {
- unsigned int x1,y1,x2,y2;
- unsigned int w1=bmp1->m_lpBMIH->biWidth-bmp1->Pix_X;
- unsigned int w2=bmp2->m_lpBMIH->biWidth-bmp2->Pix_X;
- unsigned int w=(w1>w2)?w2:w1;
- x1=bmp1->Pix_X;y1=bmp1->Pix_Y;
- x2=bmp2->Pix_X;y2=bmp2->Pix_Y;
- for(unsigned int i=0;i<w;i++)
- {
- //判断是否是相同的列,如果是则向左移动继续比较是否是相同的块
- if(!IsSameCol(bmp1,bmp2,x1,y1,x2,y2))
- return FALSE;
- x1++;
- x2++;
- }
- unsigned int h=(bmp1->m_lpBMIH->biHeight-bmp1->Pix_Y)<(bmp2->m_lpBMIH->biHeight-bmp2->Pix_Y)?
- (bmp1->m_lpBMIH->biHeight-bmp1->Pix_Y):(bmp2->m_lpBMIH->biHeight-bmp2->Pix_Y);
- //如果块的面积比先前的最大面积大,则取代之
- if(i*h>MAXarea)
- {
- MAXarea=i*h;
- left_starX=bmp1->Pix_X;
- left_starY=bmp1->Pix_Y;
- left_endX=i+bmp1->Pix_X;
- left_endY=h+bmp1->Pix_Y;
- right_starX=bmp2->Pix_X;
- right_starY=bmp2->Pix_Y;
- right_endX=i+bmp2->Pix_X;
- right_endY=h+bmp2->Pix_Y;
- }
- return TRUE;
- }
- /*************************************************************************************
- 用于图象合并拼接
- *************************************************************************************/
- void CDlgMosaics::MergeDIB(CDib *bmp1, CDib *bmp2)
- {
- BYTE* unitbuff;
- unitbuff=NULL;
- unsigned int w1=bmp1->m_lpBMIH->biHeight;
- unsigned int w2=bmp2->m_lpBMIH->biHeight;
- //新图象的宽
- unsigned int unit_w=bmp2->m_lpBMIH->biWidth+left_starX;
- //重叠部分的上部高度
- unsigned int unit_up=(left_starY>right_starY)?left_starY:right_starY;
- //重叠部分的下部高度
- unsigned int unit_down=((w1-left_endY)>(w2-right_endY))?(w1-left_endY):(w2-right_endY);
- //新图象的高
- unsigned int unit_h=unit_up+(left_endY-left_starY)/*重叠部分的高*/+unit_down;
- //得到每行实际占的字节数
- int byte_w=unit_w*(bmp1->m_lpBMIH->biBitCount/8);
- if(byte_w%4)
- byte_w=byte_w+(4-byte_w%4);
- //得到新图象的数据大小
- int imagedata=byte_w*unit_h;
- // 将此图象用CDib类封装
- m_pDibResult = new CDib(CSize(unit_w,unit_h), 8);
- // 计算结果图象的存储大小尺寸
- CSize sizeSaveResult;
- sizeSaveResult = m_pDibResult->GetDibSaveDim();
- // 拷贝调色板
- memcpy(m_pDibResult->m_lpvColorTable, m_pDibInit->m_lpvColorTable, m_pDibResult->m_nColorTableEntries*sizeof(RGBQUAD));
- // 应用调色板
- m_pDibResult->MakePalette();
- // 分配内存给合并后的图象
- LPBYTE lpImgResult;
- lpImgResult = (LPBYTE)new unsigned char[sizeSaveResult.cx * sizeSaveResult.cy];
- BYTE *p1,*p2,*p3;
- p1=bmp1->m_lpImage+left_starY*bmp1->GetDibSaveDim().cx; //数据1起始地址
- p2=bmp2->m_lpImage+right_starY*bmp2->GetDibSaveDim().cx; //数据2起始地址
- p3=lpImgResult;
- //保存图象的数据,先把第一幅图象的第一行存进去,再存第二幅图象的第一行,然后再存
- //第一幅图象的第二行,再存第二幅图象的第二行,以次类推
- for(unsigned int i=0;i<unit_h;i++)
- {
- memcpy(p3,p1,left_starX*(bmp1->m_lpBMIH->biBitCount/8));
- p3+=left_starX*(bmp1->m_lpBMIH->biBitCount/8);
- p1+=bmp1->GetDibSaveDim().cx;
- memcpy(p3,p2,bmp2->m_lpBMIH->biWidth*(bmp2->m_lpBMIH->biBitCount/8));
- p3+=bmp2->m_lpBMIH->biWidth*(bmp2->m_lpBMIH->biBitCount/8);
- p2+=bmp2->GetDibSaveDim().cx;
- //如果不是4的倍数则填满为4的倍数
- if((unsigned int)(p3-unitbuff)%4!=0)
- p3+=4-(unsigned int)((p3-unitbuff)%4);
- }
- // 将指针赋值给CDib类的数据
- m_pDibResult->m_lpImage = lpImgResult;
- //创建显示拼接后图象的对话框
- CDlgMosaicRes* pDlg;
- pDlg = new CDlgMosaicRes(NULL, m_pDibResult);
- pDlg->DoModal();
- // 删除对象
- delete pDlg;
- return ;
- }