基于MFC的图形图像处理方法.docx
- 文档编号:25357519
- 上传时间:2023-06-07
- 格式:DOCX
- 页数:19
- 大小:507.60KB
基于MFC的图形图像处理方法.docx
《基于MFC的图形图像处理方法.docx》由会员分享,可在线阅读,更多相关《基于MFC的图形图像处理方法.docx(19页珍藏版)》请在冰豆网上搜索。
基于MFC的图形图像处理方法
基于MFC的图形图像处理
李明(08.2)2008200698
§1MFC平台的简单应用
一用C语言中自带的函数画点。
其步骤如下:
1.建立一个工程:
“文件”__>“新建”__>选中“另几时idW")”-__>”
-「八冋:
”(在其中键入工程名称,女口“TEST1”)——>
位置[Q:
冋画像殛劉图像範理期耒晅’J/、”儿七口未仙十册如亠呈、“谥宀”
-(设置为自己想要存放的位置)——>确定——>
…兰二…罚”__>“完成”__>“确定”。
2.左击“”即可出现所见工程中的所有类。
若要实现画图功能,则必
须要在其中的“-'H>:
llVirw”类中的“5山小「仙「[1厂5【1门”函数中加入我们要
实现功能所需要执行的代码。
现在可以先后通过工具栏中的“籃”、“1”按钮进行编译执行。
其结果如下:
图一
图一为空白的,那是因为我们没有在“”函数中加任何代码。
(每次编译执行时,应把“图一”所示界面关闭,否者进行编译执行会出错。
)
3.利用C语言中自带的函数画一个点:
双击“”->在函数“voidCTEST1View:
:
OnDraw(CDCpDC)”提
示的地方加上所要执行的代码,这里为:
pDC->SetPixel(10,10,RGB(255,0,0));(该函数的前两个参数为所画点的位置坐标(x,y),第三个参数为其彩色值RGBE个分量各自的值)。
经“隘、、“J”后,其结果如下:
图二
可以看出所画此点极不清楚,我们可以自己编写一个画点函数。
二改进的画点函数。
此方法的思想是:
不只画出一个点P,同时也画出P附近的点。
在图像中可看做显示一个
像素及其领域中的像素。
在这里以画出所有离P点水平和垂直距离均小于等于5的点为例。
基
于此思想,首先按照上一部分所说的“步骤1”建立一个工程“TEST2',然后在
■”函数中添加如下代码:
for(inti=_5;i<=5;i++)
{
for(intj=-5;jv=5;j++)
{
pDC->SetPixel(10+i,10+j,RGB(255,0,0));
}
}
经编译执行后可得:
图三
图二与图三相比,后者清楚了许多。
这是因为图像是由许许多多的像素组成的,一个像素相对于整幅图来说是相当小的。
故图二所画的一个点似乎是看不到的。
三利用C语言中的函数直接画线。
如同前两部分,首先建立一个工程TEST3然后在“•0门5會刨CDCFDC]”函数中执行如下命令:
pDC->MoveTo(10,10);
pDC->LineTo(100,100);
经编译执行后就画出了一条从点(10,10)至点(100,100)的直线。
所画直线如下图所示:
图四
§2生成直线的扫描转换算法
一生成直线的DDA算法。
1.在计算机中画直线均是通过画离直线较近的整数点来实现的,如下图所示:
2.直线DDA算法描述:
设直线的解析式为y=mx+b即x=1y-b,且(x1,y1)和仪2,y2)分别为所求直线的起点
mm
和终点坐标•则可通过计算由x方向的增量△x引起y的改变来生成直线:
当Xjt=Xi1时,yyim。
(1-5)
为了减少误差积累,仅当|m|<1是采用(1-6)的方法。
当|m|_1时,
1
应用yiyi1时,Xid=Xi丄的方法。
(1-6)
m
3:
DDA算法的实现:
1建立工程TEST4
Classtype
>“NewClass”>””的
属性为“iGenericClass“;“也血”为“⑴门©”一一>“确定”。
3添加类Cline的成员:
右击“「CLinc”>”AddMemberVariable…”>”
VariableType:
"为“Cpoint”;“—”为“point1”;“…即应”—>“确
定”。
用同样的方法加一个成员变量point2。
4将Cline的数据成员初始化:
双击“・CLine[)”>通过“point1.x=0;
point1.y=0;”将point1初始化。
同样将point2初始化。
5添加类Cline的带参数的构造函数:
在上一步的构造函数下面加上
CLine:
:
CLine(intx1,inty1,intx2,inty2)
{
point1.x=x1;
point1.y=y1;
point2.x=x2;
point2.y=y2;
}
双击“花口“”>在“CLine();”后面加上“CLine(intx1,inty1,intx2,inty2);”
6在类Cline中增加函数voidCLine:
:
CLineddaplot(CDC*pDC):
右击“rCLinc”>“AddMemberFunction…”>“函数类型QJ:
”为“void”;
•CLineddaplot[CDC*pDC]”
“二匕也”为“CLineddaplot(CDC*pDC)”>”确定”>双击函数
添加基于DDA算法思想的画线函数代码。
”函数中的相应:
双击“「1:
、;1旳“”类中的
>在void
“TEST4View.cpp‘的前面加上#include"Line.h"
CTEST5View:
:
0nDraw(CDC*pD(提示的地方加入
CLineline(10,10,40,50);
line.CLineddaplot(pDC);
对TEST4编译执行,便可用DDA算法画出一条如下图所示的从点(10,10)到点(40,50)的直线:
图六
4:
DDA算法的优缺点:
算法简单,容易实现;(1-5)、(1-6)里面含有浮点运算,实行起来较慢;而且由于画点时的四舍五入,会存在误差积累。
二生成直线的Bresenham算法。
Bresenham算法是一种基于误差
在生成直线的算法中,Bresenham算法是最有效的算法之一判别式来生成直线的方法。
它可以克服DDA算法中的一些不足。
1:
直线Bresenham算法描述:
它也是采用递推步进的办法,令每次最大变化方向的坐标步进一个像素,同时另一个方向的坐标依据误差判别式的符号来决定是否也要步进一个像素。
且x1 从DDA直线算法可知这 我们首先讨论m=\y/△x,当Owmci些条件成立时,公式 当Xi1%1时,比1=y「m。 (1-5) i个像素点坐标为(Xi,yi),它 成立。 由于显示直线的像素只能取整数值坐标,可以假设直线上第 是直线上点(Xi,y)的最佳近似,如下图所示。 那么,直线上下一个像点的可能位置是(Xi*,yi) 或(X",%+1)。 图七 由图七可以知道,在x=Xi+1处,直线上点的y值是y=m(Xi+1)+b,该点离像素素点(Xi+1,yj 和象素点(xi+1,yi+1)的距离分别是d1和d2: (2- 3) (2 -4) d2=(yi+1)-y=(yi+1)-m(Xi+1)-b 这两个距离差是 d1-d2=2m(Xi+1)-2yi+2b-1 我们来分析公式(2-3): (1)当此值为正时,d1>d2,说明直线上理论点离(Xi+1,yi+1)像素较近,下一个像素点应取(Xi+1,yi+1)。 ⑵当此值为负时,d1 (Xi+1,yi)。 (3)当此值为零时,说明直线上理论点离上、下两个像素点的距离相等,取哪个点都行,假设算法规定这种情况下取(Xi+1,yi+1)作为下一个像素点。 这样正好与我们计算时采用四舍五入的思想相一致。 因此只要利用(d1-d2)的符号就可以决定下一个像素点的选择。 为此,我们进一步定义一个新的判别式: pi=△xx(d1-d2)=2△y•Xi-2△x•yi+c 式(2-4)中的△x=(x2-x1)>0,因此pi与(d1-d2)有相同的符号;这里△y=y2-y1,m=\y/△x;c=2Ay+△x(2b-1)。 下面对式(2-4)作进一步处理,以便得出误差判别递推公式并消除常数c。 将式(2-4)中的下标i改写成i+1,得到: Pi1=2^y•Xii-2△x•yii+c 将式(2-5)减去(2-4),并利用XiX1,可得: Pii=Pi+2Ay-2△x•(yii-yj 再假设直线的初始端点恰好是其像素点的坐标,即满足: y1=mx1+b 由式(2-4)和式(2-7)得到pi的初始值: p仁2^y-△x 这样,我们可利用误差判别变量,得到如下算法表示: 初始p仁2△y-△x (2- 5) (2- 6) (2-7) (2-8) 当Pi>0时: yiyi1, Xi厂人1 Pi1=Pi+2(△y-△x)(2 -9) 否则: yi1=yi Xi1=Xj1 Pi1=Pi+2Ay 从式(2-9)可以看出,第i+1步的判别变量Pi1仅与第i步的判别变量p「直线的两个端点坐标分量差厶x和厶y有关,运算中只含有整数相加和乘法运算,因此这个算法速度快并易于硬件实现。 当m不在{Owmci}里面是,直线可利用对称性画出。 2: Bresenham算法的实现: 建立一个工程TEST5并添加如DDA算法中所示的类CLine且对其增加成员变量、初始化、并添加构造函数等。 按照Bresenham算法的思想,在类Cline中增加函数voidCLine: : CLineBresenham(CDC*pDC)。 在在voidCTEST5View: : OnDraw(CDC*pDC)函数中响应 CLineline(10,10,40,50); line.CLineBresenham(pDC); 也可画一条从(10,10)到点(40,50)的直线: §3鼠标、菜单、工具栏、对话框的人机交互 一通过左鼠标按下、抬起点分别作为起、终点画线。 前面讲的画线方法都是指定起点和终点的坐标值,其实可以通过鼠标来确定直线的端点,不必 知道其坐标值。 例如可通过左鼠标按下、抬起点作为起点与终点来画线。 1建立工程TEST6 2.由于要保存左鼠标按下的点,故要在类“”中增加一个全局变量: 右击 ”——>“AddMemberVariable…”——>其中“”为 “CPoint”,”「;亡「»冋: ”为“point1”,为了保证数据的安全性“: ”――> 确定” 。 3.建立相应函数voidCTEST6View: : OnLButtonDown(UINTnFlags,CPointpoint): “查看” ――>“建立类向导”一一>“T冒石”中将其对话框中的属性设置如下: “皿、沙虫: 『”中的“閃顽鴉(因为要利用做鼠标点下的点作为 在函数voidCTEST4View: : OnLButtonDown(UINTnFlags,CPointpoint)中写入: point仁point;〃将鼠标点下的点存到point1中 便可建立响应函数voidCTEST4View: : OnLButtonUp(UINT nFlags,CPointpoint),在里面加入代码 CDC类的指针,以便调用里面的画点函 CDC*pDC=GetDC();〃此函数用来生成一个数pDC->SetPixel(); pDC->MoveTo(point1);pDC->LineTo(point); pDC->DeleteDC();〃为了保持内存,要将建立的指针删除掉 4.为了更好的人机交互,可在“•”函数中加入如下命令: pDC->TextOut(10,10,"通过左鼠标按下、抬起点分别作为起、终点画线"); 对TEST4编译、执行结果如下: 图九 二通过菜单建立人际交互(本部分操作均在工程TEST6内进行,并将前面建立的类CLine与 DDABresenham算法的函数都加在里面) 1建立菜单: 单击“錮%38别那”>双击“耳口Wnu”中的“” >在里面添加一个新的菜单“CLine”及子菜单“DDA与“Bresenham”。 2 更改菜单的属性: 右击“DDA'菜单——>”属性”——>将其ID设为 3为了使单击“DDA时,用DDA方法画线,单击“Bresenham”时用Bresenham方法画线。 可 以在类“一FCTEST6Vi匕w”中增加两个bool类型的变量m_bDD廁m_bBresenhan,并在函数“” “乍•CTESTEiYi±w[]|”中将此两个变量初始化(m_bDDA=false;m_bBresenham=false;)。 4 增加响应函数voidCTEST6View: : OnDDA(): 右击子菜单“DDA——>”建立类向导…”一 —设置为“T”――>双击“叩"门山… m_bDDA=true;m_bBresenham=false; Invalidate。 ;//重新调用画图函数OnDraw(CDC*pDC) 用类似的方法菜单“Bresenham”的建立响应函数。 但要在其中加入的代码是: m_bBresenham=true;m_bDDA=false; Invalidate。 ;//重新调用画图函数OnDraw(CDC*pDC) 5在函数“rm【\「w|门)厂*卩1山|”添加 CLineline(10,10,40,50); if(m_bDDA==true) { line.CLineddaplot(pDC); } elseif(m_bBresenham==true) {_ line.CLineBresenham(pDC); } 采用上述方法便可以实现单击“DDA时,用DDA方法画线,单击“Bresenham”时用Bresenham方法画线的功能。 三通过工具栏建立人机交互(本部分操作在工程TEST6内进行) ①添加工具按钮“星”: 单击“也*」■”——>双击⑴山沐”里面的 图十 四通过对话框建立人际交互(本部分操作在工程TEST6内进行) 上面的交互方式均不能画出在给定精确的起、终点坐标后的直线,但通过对画框便可以实现这种功能。 方法如下: ①添加对话框: 单击“-7"J一一>右击“』前口”——>“插入Dialog”一一>选中此对话框后 右击——“属性”——>将其ID设置为“IDD—LINEPARADLG”标题”设置为“LineParaDialog ——>选中“上子”中的“.||]”。 2 建立一个新的类CLinePARADIg 选中所建立的对话框后并右击一一>“建立类向导” >”皿me: ”为“CLinePARADig——>”OK——>”确定” 3 >在其“属性“中将“咁也口: ” 加入静态文字: 单击“控件”中的后即可在“对话框”中拖出一个静态文本 设置为“Inputtheendofline”。 类似的可在对话框中加入四个静态文本框、四个“编辑框”一—““并将其编辑框的ID分别设置为“IDC_XI”“IDC_Y1“IDC_X2'“IDC_Y2'。 ObjectIDs: 在函数中加入 CLinePARADiglineparadlg;lineparadlg.DoModal();intx1=lineparadlg.m_nX1;inty1=lineparadlg.m_nY1;intx2=lineparadlg.m_nX2;inty2=lineparadlg.m_nY2; CDC*pDC=GetDC();pDC->MoveTo(x1,y1);pDC->LineTo(x2,y2);pDC->DeleteDC(); 经编译执行(要在TEST6View.cpp中加入#include"LinePARADIg.h")之后,将出现如下图所示的对话框。 图十一 在对话框中填入直线的起始点坐标(X1,Y1)、(X2,Y2),点击确定后即可画出以(X1,Y1)为起点,以(X2,Y2)为重终点的直线。 如本例子将画出从(512,323)到(116,281)的直线。 图十二
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 MFC 图形图像 处理 方法
![提示](https://static.bdocx.com/images/bang_tan.gif)