当我们想仔细观察某个细微的东西时,一般都会使用放大镜。而要看清显示在计算机屏幕上的图片或文字时通常也可以借助于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);

}

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

  1. [Sciter系列] MFC下的Sciter–4.HTML与图片资源内置

    [Sciter系列] MFC下的Sciter–4.HTML与图片资源内置,防止代码泄露. 本系列文章的目的就是一步步构建出一个功能可用,接口基本完善的基于MFC框架的SciterFrame程序,以此作 ...

  2. Direct2D开发:MFC下从资源文件中加载位图

    转载请注明出处:http://www.cnblogs.com/ye-ming 0X01 概述: 相对于GDI处理界面,Direct2D有得天独厚的优势,下图就是Direct2D与GDI的效果对比,wi ...

  3. Caffe框架下的图像回归测试

    Caffe框架下的图像回归测试 参考资料: 1. http://stackoverflow.com/questions/33766689/caffe-hdf5-pre-processing 2. ht ...

  4. MFC下OpenGL入门(可以用)

    MFC下OpenGL入门 源文件 1, 建一工程文件,我这里命名为first,现在first工程里面我们没有添加任何东西,所有的东西都是MFC自动帮我们创建的. 2, 添加链接库.这一步很关键.打开菜 ...

  5. MFC下调用控制台和控制台下MFC库的支持

    1.MFC下调用控制台 在CWinApp的InitInstance中对话框的DoModal之前加入 AllocConsole(); // 开辟控制台 SetConsoleTitle(_T(" ...

  6. MFC下的各种字符串类型和相互转换

    MFC下的常用字符串数据类型表示的含义: L:Long  长 P:Point  指针 C:Const  常量 W:Wchar_t  宽字符 T:TCHAR  STR:String  字符串 在看看MF ...

  7. [Sciter系列] MFC下的Sciter–5.Sciter中GUI线程研究

    [Sciter系列] MFC下的Sciter–5.Sciter中GUI线程研究,目前MFC存在问题,win32没问题. 本系列文章的目的就是一步步构建出一个功能可用,接口基本完善的基于MFC框架的Sc ...

  8. [Sciter系列] MFC下的Sciter–3.Sciter脚本与底层交互

    [Sciter系列] MFC下的Sciter–3.Sciter脚本与底层交互,脚本调用底层自定义的方法函数. 本系列文章的目的就是一步步构建出一个功能可用,接口基本完善的基于MFC框架的SciterF ...

  9. [Sciter系列] MFC下的Sciter–2.Sciter中的事件,tiscript,语法

    [Sciter系列] MFC下的Sciter–2.Sciter中的事件,tiscript,CSS部分自觉学习,重点说明Tiscript部分的常见语法和事件用法. 本系列文章的目的就是一步步构建出一个功 ...

随机推荐

  1. Slack 开源替代品 Rocket.Chat(聊天,文件上传等等)

    Rocket.Chat 是特性最丰富的 Slack 开源替代品之一. 主要功能:群组聊天,直接通信,私聊群,桌面通知,媒体嵌入,链接预览,文件上传,语音/视频 聊天,截图等等. Rocket.Chat ...

  2. PASCAL的优越性:官方的说法(不需要Makefile,节约大量的时间)

    也许你认为为什么我选择pascal代替其他的语言,像C.或者您会拿FreePascal和其他的pascal编译器作比较,那么好,这里您看看FreePascal为什么好: 1.pascal是一个非常简洁 ...

  3. 《how to design programs》12章函数复合

    我们写代码时要学会适应辅助函数.作者提出了一个问题,如何对一个表排序.排序函数读取一个表,产生另一个表.排序函数的合约和用途如下: (sort empty) ;; expected value: em ...

  4. Amazon Redshift and Massively Parellel Processing

    Today, Yelp held a tech talk in Columbia University about the data warehouse adopted by Yelp. Yelp u ...

  5. 分治法求一个N个元素数组的逆序数

    背景  逆序数:也就是说,对于n个不同的元素,先规定各元素之间有一个标准次序(例如n个 不同的自然数,可规定从小到大为标准次序),于是在这n个元素的任一排列中,当某两个元素的先后次序与标准次序不同时, ...

  6. man/ls/clock/date/echo笔记

    login:    用户名:用户ID    认证机制:Authentication授权:Authorization审计:Audition (日志) prompt,命令提示符:命令:magic numb ...

  7. XMind快捷键可以自定义吗

    在使用快捷键的时候,不知你是否有过这样的疑问,为什么这个操作的快捷键一定要是这个呢,我为什么不能换成其他的按键呢.其实这些在XMind思维导图中都是可以更改的,用户可以根据自己的操作习惯来定义快捷键命 ...

  8. H5 视频直播相关技术

    一.移动视频直播发展 大家首先来看下面这张图: 可以看到,直播从 PC 到一直发展到移动端,越来越多的直播类 App 上线,同时移动直播进入了前所未有的爆发阶段,但是对于大多数移动直播来说,还是要以 ...

  9. ssh登录命令(转)

    转:http://blog.csdn.net/edward_qing_lee/article/details/23133331 常用格式:ssh [-l login_name] [-p port] [ ...

  10. C# 坦克大战学习总结

    1.学会用Resource管理资源 添加资源 在properties下的Resource.resx添加资源 使用资源 工程名.Properties.Resource.资源名 实际本质,是一个流. 2. ...