在MFC下实现图像放大镜

当我们想仔细观察某个细微的东西时,一般都会使用放大镜。而要看清显示在计算机屏幕上的图片或文字时通常也可以借助于Windows操作系统附带的放大程序来实现。但该程序只能以固定的放大倍数去进行观看,有时并不能满足我们的需要。本文就通过MFC基本类库提供的StretchBlt函数来实现对屏幕图象的局部放大,并且可以随意放大、缩小,选取到合适的放大倍数来对图像的细节进行观察。

设计与实现

本程序主要用来对图像的局部进行可调倍数的放大,应当具有以下主要功能:

1. 移动MOUSE放大显示图像的不同部位

2. 左击增加放大倍率、右击减少放大倍率。

从光学角度来看,对物体的放大成像是通过把较小的真实物体显示成尺寸较大的虚像来实现的。因此我们可以用类似的原理,把图像中待放大的区间从较小的显示范围拉伸到一个比较大的显示范围即可达到图像放大的效果,两个区间的比值也就是图像的放大倍率。可以通过缩小源区间的范围或扩大放大区间的范围来实现放大倍率的调整。在MFC基本类库中提供有CDC类的StretchBlt函数可以将一幅位图从一个源矩形以一定的光栅操作拷贝到另外一个不同大小的目标矩形中去,因此可以用此函数来实现图象放大的功能,其函数原形声明如下:

BOOL StretchBlt( int x, int y, //目标矩形的坐标原点

int nWidth, int nHeight, //目标矩形的长度和宽度

CDC* pSrcDC, //源设备环境句柄

int xSrc, int ySrc, //源矩形的坐标原点

int nSrcWidth, int nSrcHeight, //源矩形的长度和宽度

DWORD dwRop ); //光栅操作标志

当指定的源和目标矩形的宽度或高度不一样时,StretchBlt函数将创建一个位图的镜像。如果是宽度有变化,就沿x轴创建镜像;如果是高度上有变化就沿y轴创建镜像。而且该函数可以在内存中对源图象做拉伸或压缩处理后再拷贝到目标矩形中去。

要放大图像首先要把图像显示出来,一般可以从文件动态装载或者直接从资源中用LoadBitMap读取位图资源。下面的代码放在视类的OnDraw函数中,用以在第一次调用时将位图装载并显示出来,以后再被调用只是负责重画:

……

static bool load;

if (!load)

{

BITMAP bm;

load = !load;

//装载位图到 m_pBitmap

m_pBitmap->LoadBitmap(IDB_BITMAP1);

//创建相关的设备环境

m_pdcMem->CreateCompatibleDC(pDC);

//将位图从m_ pBitmap中装载到m_pdcMem中

m_pdcMem->SelectObject(m_pBitmap);

m_pBitmap->GetObject(sizeof(bm),&bm);

m_sizeSource.cx = bm.bmWidth;

m_sizeSource.cy = bm.bmHeight;

m_sizeDest = m_sizeSource;

//把位图从m_pdcMem中装载到当前正在使用的设备环境中

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);

SetCursor(NULL);//隐藏鼠标

}

要实现前面提到的第一个功能:移动MOUSE放大显示图像的不同部位,显然首先要在WM_MOUSEMOVE消息的响应函数里编写代码。以整形变量s和d来分别表示所选取的源和目标区域的大小,再通过消息响应函数OnMouseMove的入口参数point来确定当前的鼠标位置就可以计算出我们要选取的源和目标区域在图像的位置。放大的工作只需通过StretchBlt函数将源区域中所在的图像拉伸到目标矩形那么大,并拷贝给目标区域即可实现所选区域的放大效果,下面是部分主要代码:

……

//确定目标区域、源区域的坐标位置

CRect srect,drect,mrect;

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);

}

//隐藏鼠标

SetCursor(NULL);

//拉伸放大

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;

……

为了实现第二个功能:左击增加放大倍率、右击减少放大倍率,可以分别在消息WM_LBUTTONDOWN和消息WM_RBUTTONDOWN中添加改变选取区域大小的代码来实现。如果选取源矩形不变而改变目标矩形的大小会随着放大倍数的增大,显示区域也不断增大,当放大到一定程度的时候会另人无法忍受,因此选取通过缩放源矩形大小来控制放大倍数的方案:

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

{

if (s < 60)

{

SetCursor(NULL);

s+=3;

OnMouseMove(nFlags, point);

}

CView::OnRButtonDown(nFlags, point);

}

……

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

{

if(s>5)

{

s-=3;

SetCursor(NULL);

OnMouseMove(nFlags, point);

}

CView::OnLButtonDown(nFlags, point);

}

时间: 2024-07-31 07:51:29

在MFC下实现图像放大镜的相关文章

mfc-VS2010 MFC 下如何调整状态栏高度

问题描述 VS2010 MFC 下如何调整状态栏高度 小弟最近在vs2010下 mfc多文档开发的过程中,需要调整界面上状态栏的高度,但是系统不提供GetStatusBarCtrl()或直接函数改变其高度,求大神告诉解决方法,深表感谢! ps:应该可以新建类继承CMFCStatusBar,但是具体怎么实现呢?

MFC下如何快速找到界面的方法对应的代码????

问题描述 MFC下如何快速找到界面的方法对应的代码???? MFC下如何快速找到界面的方法对应的代码,大神们请指教!!! 解决方案 再资源中,双击界面上的按钮等,就可以自动定位到编译器中的按钮代码 解决方案二: 用classwizard,或者直接双击对话框设计器中的控件.

列举出字体信息,MFC下拉框列举字体

问题描述 列举出字体信息,MFC下拉框列举字体 MFC下拉框列举字体,用的是EnumFomt么?群高手告诉我是这样的,但是查了百度没有COMBOX的 解决方案 你是不是想太多了?你看看这个可以解决你的问题吗:http://www.cnblogs.com/kzloser/archive/2012/11/21/2780246.html

串口通信-如何在Vs2010基于MFC下,编写代码,强行占用【串口】

问题描述 如何在Vs2010基于MFC下,编写代码,强行占用[串口] 自己编写了一个程序,需要USB串口与程序相连接.可是如果在程序运行过程中,不小心动了 USB线的话,程序就卡了,提示[串口被占用],需要把USB线拔下来再插一遍才能解决问题,所以问有没有什么代码能直接解决问题?求大侠指导!

定时器-mfc下编写的滚动字幕信息不流畅

问题描述 mfc下编写的滚动字幕信息不流畅 我用mfc编写滚动信息,SetTimer定时器改变DrawText函数每次绘画的位置,信息能够实现滚动,但是不流畅. 解决方案 SetTimer 时间时隔 显示的实现可能有问题,可以看看显示,即刷新滚动占用的时间与 SetTimer 时间的大小关系 滚动每次移动的位移,也可能导致你所说的现象 解决方案二: SetTimer的精度不是很高,差不多是50ms左右. 解决方案三: SetTimer的间隔进行一下调整优化.选择一个合适的更新间隔

chtmlview-网页的 BeforeUnload 消息在IE 内核的mfc下怎么截获

问题描述 网页的 BeforeUnload 消息在IE 内核的mfc下怎么截获 能在 COleControlSite 中的STDMETHOD(ShowMessage) 截获网页的alter 窗口, 但是 beforunload消息弹出框无法进入这个函数,有人知道怎么直接截获这个网页关闭 时候的这个消息吗? 解决方案 这个最好是注入Javascript去获取,然后由Javascript·通知外面的窗口

(DirectX系列07)DirectShow MFC下Filter编码分析

    MFC下Filter的编写和Win32下Filter的编写极其相似,但又存在很多不同点,在Win32中需要去实现CreateInstance函数,而在MFC直接用NEW 动态产生,不过这并不代表不需要去维护Filter对象计数,因此在MFC 下Filter中依然需要调用AddRef函数来维护这个平衡:其它还不需要实现注册表注册等功能,如下代码: ////////////////////////////////////////////////////////////////////////

图片-matlab下跑图像的代码时出现错误

问题描述 matlab下跑图像的代码时出现错误 运行了run时跑出以下错误 重命名试了也不行,找了整个程序里貌似也没有与他重命名的文件,不知道是哪里出了问题,望各位帮忙解决

关于mfc下的一个接受udp/ts视频流的实时播放器

问题描述 关于mfc下的一个接受udp/ts视频流的实时播放器 RT,初次接触播放器开发, 对这些东西不是很懂,请求大牛可以告诉我,总体框架应该如何设计,应该用什么库来进行解码(ffmpeg?),什么库来进行播放(sdl? directshow?),或者说有什么现成的东西可以应用.跪谢!!!! 解决方案 您能说详细点么?我懂得不太多.wmp怎么播放网络流文件解码? 解决方案二: http://bbs.csdn.net/topics/390129795 解决方案三: 没人懂么?求解!!!!!!!!