一种对图象进行局部放大的有效方法

附例:一种对图象进行局部放大的有效方法

  在实际工作中,对图象进行局部放大,以便更加清楚、细致的观察图象的某个部位,是经常遇到的问题。在Visual C++6.0中,巧妙、灵活的运用CDC类的StretchBlt()函数以及有效的完成对鼠标的消息映射等,就能实现这一目的;这里所实现的对图象进行局部放大的操作是:

(1)移动MOUSE鼠标,放大显示图象的不同部位。

(2)左击鼠标放大倍率。

(3)右击鼠标减少倍率。

实现结果:见以下图1和图2所示

              

1:原照片                 图2:局部放大后的照片

一、StretchBlt()函数

  CDC类定义设备环境对象类,其对象提供操作设备环境(如显示器或打印机等)的成员函数,以及操作与窗口客户区相关的显示描述表的成员函数。StrechBlt()就是CDC类中的一个函数,它将位图从源矩形和设备移进目的矩形,并为适应目的矩形框,还可能压缩或放大位图。StrechBlt函数原形如下:

BOOL StretchBlt(int x,int y,int nWidth,int nHeight,CDC *pSrcDC,int xSrc,int ySrc,int nSrcWidth,int nSrcHeight,DWORD dwRop);

其返回值是:若位图绘制成功,则返回非0值,否则返回值为0

参数:目标矩形左上角的逻辑x坐标;   y 目标矩形左上角的逻辑y坐标;

      nWidth 目标矩形的逻辑宽度;      nHeight 目标矩形的逻辑高度;

      pSrcDC 指定源设备环境;         XSrc 源矩形左上角的逻辑x坐标;

      YSrc 源矩形左上角的逻辑y坐标; nSrcWidth 源矩形的逻辑宽度;

      nSrcHeight 源矩形的逻辑高度;    dwRop 指定要执行的光栅操作;

说明:将位图从源矩形拷贝到目标矩形中,并按需要拉伸或压缩位图,使其适应目标矩形的大小。

二、实现过程:

1)建立一个单文档SDI应用程序,名为:图象放大镜

2)在视图类的View.hpublic中添加以下数据成员:

CSize m_sizeDest;

CSize m_sizeSource;

CBitmap *m_pBitmap;//位图类指针

CDC *m_pdcMem;//CDC类指针

int oldx,oldy,s,d;

bool recover;//布尔类型变量,即:真或假

long mana;

3)在资源中加入你自己喜欢的位图,并设ID为:IDB_BITMAP1

Insert->Resource->点黑BITMAP->New->Import->你找到一个你喜欢的位图图形,加到项目中。

4)在视图类的View.cpp的构造函数中,进行初始化数据成员

CMyView::CMyView()

{

// TODO: add construction code here

m_pdcMem=new CDC;//CDC

m_pBitmap=new CBitmap;//位图类

recover=true;//赋给布尔类型变量为真

s=30;  d=45;

mana=SRCCOPY;

}

5)在视图类的View.cpp的析构函数中,对用完后的数据成员进行释放

CMyView::~CMyView()

{

delete m_pdcMem;//释放为CDC类开辟的一片单元

delete m_pBitmap;//释放为位图类开辟的一片单元

}

注意:1、将主框架类MainFrm.h中的保护模式protected:下的

CStatusBar  m_wndStatusBar; 剪切到公共模式public:下

      2、在视图类执行文件CMyView.cpp,加入:#include “MainFrm.h”

6)在视图类的View.cpp的显示函数OnDraw()中编程:

void CMyView::OnDraw(CDC* pDC)

{

CMyDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

static bool load;

if(!load)

{

BITMAP bm;

load = !load;

       m_pBitmap->LoadBitmap(IDB_BITMAP1); //位图类中的成员函数,

//从程序的可执行文件中调入指定的位图资源,并连接位图到对

//象,初始化对象,参数是:位图资源ID

m_pdcMem->CreateCompatibleDC(pDC); //CDC类成员函数,创建

//一个内存设备环境,以便位图在内存中保存下来,并与指定设备(窗口

//设备)环境相兼容,参数是:设备环境指针

m_pdcMem->SelectObject(m_pBitmap);//将位图对象选入内存设备环境中

//参数是:指向一个要选择的CBitmap对象的指针

m_pBitmap->GetObject(sizeof(bm),&bm);//sizeof是运算符,它的目的是返

//回操作数所占的内存空间大小(字节数),这里bm是数据类型,计算bm

//类型数据所占的字节数,&bmBITMAP对象bm的引用,即地址

m_sizeSource.cx=bm.bmWidth;

m_sizeSource.cy=bm.bmHeight;

m_sizeDest=m_sizeSource;

pDC->StretchBlt(0,0,m_sizeSource.cx,m_sizeSource.cy,

m_pdcMem,0,0,m_sizeSource.cx,m_sizeSource.cy,mana);

}

    else

{

pDC->StretchBlt(0,0,m_sizeSource.cx,m_sizeSource.cy,

               m_pdcMem,0,0,m_sizeSource.cx,m_sizeSource.cy,mana);

}

// TODO: add draw code for native data here

}

7)将鼠标移动消息WM_MOUSEMOVE映射到视图类中,并编程:

view->Clswizard->ClassName中找到WM_MOUSEMOVE点黑->Add Function

->Edit Code

void CMyView::OnMouseMove(UINT nFlags, CPoint point) 

{

// TODO: Add your message handler code here and/or call default

CString cord;

int dd;

CRect srect,drect,mrect;

CMainFrame *pFrame=(CMainFrame *)AfxGetApp()->m_pMainWnd;

CStatusBar *pStatus=&pFrame->m_wndStatusBar;

if(pStatus)

{

cord.Format("X=%d,Y=%d",point.x,point.y);

pStatus->SetPaneText(1,cord);

srect.left=point.x-s;

srect.top=point.y-s;

srect.right=point.x+s;

srect.bottom=point.y+s;

drect.left=point.x-d;

drect.top=point.y-d;

drect.right=point.x+d;

drect.bottom=point.y+d;

mrect.left=oldx-d;

mrect.top=oldy-d;

mrect.right=oldx+d;

mrect.bottom=oldy+d;

dd=2*d;

CDC *pDC=GetDC();

OnPrepareDC(pDC);

if(recover)

{

pDC->BitBlt(mrect.left,mrect.top,dd,dd,

m_pdcMem,mrect.left,mrect.top,mana);

}

pDC->StretchBlt(drect.left,drect.top,drect.Width(),

drect.Height(),m_pdcMem,srect.left,srect.top,

srect.Width(),srect.Height(),SRCCOPY);

//将位图从源矩形和设备移进目的矩形,为适应目的矩形框,

//可能压缩或放大位图。MFC类库大全353

oldx=point.x;

oldy=point.y;

ReleaseDC(pDC);

}

recover=true;

CView::OnMouseMove(nFlags, point);

}

8)将鼠标右键按下消息WM_RBUTTONDOWN映射到视图类中,并编程

view->Clswizard->ClassName中找到WM_RBUTTONDOWN点黑->

Add Function->Edit Code

void CMyView::OnRButtonDown(UINT nFlags, CPoint point) 

{

// TODO: Add your message handler code here and/or call default

if(d>5)

{

{ CDC *pDC=GetDC();

  pDC->StretchBlt(oldx-d,oldy-d,2*d,2*d,m_pdcMem,oldx-d,

oldy-d,2*d,2*d,mana);

  d-=10;

  ReleaseDC(pDC);

          CMyView::OnMouseMove(nFlags, point);

}

CView::OnRButtonDown(nFlags, point);

   } 

}

9)将鼠标左键按下消息WM_LBUTTONDOWN映射到视图类中,并编程

view->Clswizard->ClassName中找到WM_LBUTTONDOWN点黑->

Add Function->Edit Code

void CMyView::OnLButtonDown(UINT nFlags, CPoint point) 

{

// TODO: Add your message handler code here and/or call default

if(d<150)

{

d+=10;

       CMyView::OnMouseMove(nFlags, point);

}

CView::OnLButtonDown(nFlags, point);

}

(10)编译并运行,将鼠标放在图像某处,见某处有放大,再不停按鼠标左键,见逐渐放大,再按鼠标右键,见逐渐缩小。

在实际工作中,对图象进行局部放大,以便更加清楚、细致的观察图象的某个部位,是经常遇到的问题。在Visual C++6.0中,巧妙、灵活的运用CDC类的StretchBlt()函数以及有效的完成对鼠标的消息映射等,就能实现这一目的;这里所实现的对图象进行局部放大的操作是:

(1)移动MOUSE鼠标,放大显示图象的不同部位。(2)左击鼠标放大倍率。

(3)右击鼠标减少倍率。

实现结果:见以下图1和图2所示:

            

1:原图象                 图2:局部放大后的图象

一、StretchBlt()函数

    CDC类定义设备环境对象类,其对象提供操作设备环境(如显示器或打印机

等)的成员函数,以及操作与窗口客户区相关的显示描述表的成员函数。StrechBlt()就是CDC类中的一个函数,它将位图从源矩形和设备移进目的矩形,并为适应目的矩形框,还可能压缩或放大位图。StrechBlt函数原形如下:

BOOL StretchBlt(int x,int y,int nWidth,int nHeight,CDC *pSrcDC,int xSrc,int ySrc,int nSrcWidth,int nSrcHeight,DWORD dwRop);

其返回值是:若位图绘制成功,则返回非0值,否则返回值为0。

参数:x 目标矩形左上角的逻辑x坐标;   y 目标矩形左上角的逻辑y坐标;

      nWidth 目标矩形的逻辑宽度;      nHeight 目标矩形的逻辑高度;

      pSrcDC 指定源设备环境;         XSrc 源矩形左上角的逻辑x坐标;

      YSrc 源矩形左上角的逻辑y坐标; nSrcWidth 源矩形的逻辑宽度;

      nSrcHeight 源矩形的逻辑高度;    dwRop 指定要执行的光栅操作;

说明:将位图从源矩形拷贝到目标矩形中,并按需要拉伸或压缩位图,使其适应目标矩形的大小。

二、制作图象放大镜的程序设计过程:

(1)建立一个单文档SDI应用程序,名为:放大镜

(2)在视图类的View.h的public中添加以下数据成员:

CSize m_sizeDest;

CSize m_sizeSource;

CBitmap *m_pBitmap;//位图类指针

CDC *m_pdcMem;//CDC类指针

int oldx,oldy,s,d;

bool recover;//布尔类型变量,即:真或假

long mana;

(3)在资源中加入你自己喜欢的位图,并设ID为:IDB_BITMAP1

Insert->Resource->点黑BITMAP->New->Import->找到一个你喜欢的位图图形,加到项目中。

(4)在视图类的View.cpp的构造函数中,进行初始化数据成员

CMyView::CMyView()

{

// TODO: add construction code here

m_pdcMem=new CDC;//CDC类

m_pBitmap=new CBitmap;//位图类

recover=true;//赋给布尔类型变量为真

s=30;  d=45;

mana=SRCCOPY;

}

(5)在视图类的View.cpp的析构函数中,对用完后的数据成员进行释放

CMyView::~CMyView()

{

delete m_pdcMem;//释放为CDC类开辟的一片单元

delete m_pBitmap;//释放为位图类开辟的一片单元

}

注意:1、将主框架类MainFrm.h中的保护模式protected:下的

CStatusBar  m_wndStatusBar; 剪切到公共模式public:下

      2、在视图类执行文件CMyView.cpp中,加入:#include “MainFrm.h”

(6)在视图类的View.cpp的显示函数OnDraw()中编程:

void CMyView::OnDraw(CDC* pDC)

{

CMyDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

static bool load;

if(!load)

{

BITMAP bm;

load = !load;

   m_pBitmap->LoadBitmap(IDB_BITMAP1); //位图类中的成员函数,

//从程序的可执行文件中调入指定的位图资源,并连接位图到对象,

//初始化对象,参数是:位图资源ID号

m_pdcMem->CreateCompatibleDC(pDC); //CDC类成员函数,创建一个

//内存设备环境,以便位图在内存中保存下来,并与指定设备(窗口设备)

//环境相兼容,参数是:设备环境指针

m_pdcMem->SelectObject(m_pBitmap);//将位图对象选入内存设备环境中,

//参数是:指向一个要选择的CBitmap对象的指针。

m_pBitmap->GetObject(sizeof(bm),&bm);//sizeof是运算符,它的目的是返

//回操作数所占的内存空间大小(字节数),这里bm是数据类型,计算bm

//类型数据所占的字节数,&bm是BITMAP对象bm的引用,即地址

m_sizeSource.cx=bm.bmWidth;

m_sizeSource.cy=bm.bmHeight;

m_sizeDest=m_sizeSource;

pDC->StretchBlt(0,0,m_sizeSource.cx,m_sizeSource.cy,

m_pdcMem,0,0,m_sizeSource.cx,m_sizeSource.cy,mana);

}

   else

{

 pDC->StretchBlt(0,0,m_sizeSource.cx,m_sizeSource.cy,

   m_pdcMem,0,0,m_sizeSource.cx,m_sizeSource.cy,mana);

}

// TODO: add draw code for native data here

}

(7)将鼠标移动消息WM_MOUSEMOVE映射到视图类中,并编程:

view->Clswizard->在ClassName中找到WM_MOUSEMOVE点黑->

Add Function->Edit Code

void CMyView::OnMouseMove(UINT nFlags, CPoint point) 

{

// TODO: Add your message handler code here and/or call default

CString cord;

int dd;

CRect srect,drect,mrect;

CMainFrame *pFrame=(CMainFrame *)AfxGetApp()->m_pMainWnd;

CStatusBar *pStatus=&pFrame->m_wndStatusBar;

if(pStatus)

{

cord.Format("X=%d,Y=%d",point.x,point.y);

pStatus->SetPaneText(1,cord);

srect.left=point.x-s;

srect.top=point.y-s;

srect.right=point.x+s;

srect.bottom=point.y+s;

drect.left=point.x-d;

drect.top=point.y-d;

drect.right=point.x+d;

drect.bottom=point.y+d;

mrect.left=oldx-d;

mrect.top=oldy-d;

mrect.right=oldx+d;

mrect.bottom=oldy+d;

dd=2*d;

CDC *pDC=GetDC();

OnPrepareDC(pDC);

if(recover)

{

pDC->BitBlt(mrect.left,mrect.top,dd,dd,

m_pdcMem,mrect.left,mrect.top,mana);

}

pDC->StretchBlt(drect.left,drect.top,drect.Width(),

  drect.Height(),m_pdcMem,srect.left,srect.top,

  srect.Width(),srect.Height(),SRCCOPY);

//将位图从源矩形和设备移进目的矩形,为适应目的矩形框,

//可能压缩或放大位图。

oldx=point.x;

oldy=point.y;

ReleaseDC(pDC);

}

recover=true;

CView::OnMouseMove(nFlags, point);

}

(8)将鼠标右键按下消息WM_RBUTTONDOWN映射到视图类中,并编程

view->Clswizard->在ClassName中找到WM_RBUTTONDOWN点黑->

Add Function->Edit Code

void CMyView::OnRButtonDown(UINT nFlags, CPoint point) 

{

// TODO: Add your message handler code here and/or call default

if(d>5)

{

{ CDC *pDC=GetDC();

  pDC->StretchBlt(oldx-d,oldy-d,2*d,2*d,m_pdcMem,oldx-d,

  oldy-d,2*d,2*d,mana);

  d-=10;

  ReleaseDC(pDC);

     CMyView::OnMouseMove(nFlags, point);

 }

  CView::OnRButtonDown(nFlags, point);

   } 

}

(9)将鼠标左键按下消息WM_LBUTTONDOWN映射到视图类中,并编程

view->Clswizard->在ClassName中找到WM_LBUTTONDOWN点黑->

Add Function->Edit Code

void CMyView::OnLButtonDown(UINT nFlags, CPoint point) 

{

// TODO: Add your message handler code here and/or call default

if(d<150)

{

 d+=10;

    CMyView::OnMouseMove(nFlags, point);

}

CView::OnLButtonDown(nFlags, point);

}

(10)编译并运行,将鼠标放在图像某处,见某处有放大,再不停按鼠标左键,见逐渐放大,再按鼠标右键,见逐渐缩小。

三、小结

Visual C++6.0有很强的图形图象设计功能,而其CDC类的StretchBlt函数对

位图操作又有拉伸与压缩的独特功能;因而用Visual C++6.0进行图形局部放大处理极为方便。该方法的实现,使我们对Visual C++的技术内涵又有了进一步的了解。相信以后通过不断学习与运用,能掌握更多的技巧,为教学、生产与科研服务。  

你可能感兴趣的:(一种对图象进行局部放大的有效方法)