图像的缩放和旋转.docx

上传人:b****7 文档编号:10611754 上传时间:2023-02-21 格式:DOCX 页数:27 大小:1.08MB
下载 相关 举报
图像的缩放和旋转.docx_第1页
第1页 / 共27页
图像的缩放和旋转.docx_第2页
第2页 / 共27页
图像的缩放和旋转.docx_第3页
第3页 / 共27页
图像的缩放和旋转.docx_第4页
第4页 / 共27页
图像的缩放和旋转.docx_第5页
第5页 / 共27页
点击查看更多>>
下载资源
资源描述

图像的缩放和旋转.docx

《图像的缩放和旋转.docx》由会员分享,可在线阅读,更多相关《图像的缩放和旋转.docx(27页珍藏版)》请在冰豆网上搜索。

图像的缩放和旋转.docx

图像的缩放和旋转

 

面向对象程序设计

 

学号:

110081101001

专业:

控制理论与控制工程

学生所在学院:

信息工程学院

学生姓名:

户伟利

任课教师:

熊邦书

教师所在学院:

信息工程学院

 

2012年5月

 

2011级

图像的缩放和旋转原理

户伟利

南昌航空大学

摘要:

图像处理,是对图像进行分析、加工、和处理,使其满足视觉、心理以及其他要求的技术。

图像处理是信号处理在图像域上的一个应用。

目前大多数的图像是以数字形式存储,因而图像处理很多情况下指数字图像处理。

此外,基于光学理论的处理方法依然占有重要的地位。

图像处理是信号处理的子类,另外与计算机科学、人工智能等领域也有密切的关系。

传统的一维信号处理的方法和概念很多仍然可以直接应用在图像处理上,比如降噪、量化等。

然而,图像属于二维信号,和一维信号相比,它有自己特殊的一面,处理的方式和角度也有所不同。

本例通过GDI+类库,实现图像的缩放和旋转。

主要应用了GDI+的Graphics类的DrawImage方法和移动坐标系等技术。

通过移动坐标系的逆向思维,来达到移动图像的效果。

关键词:

图像处理;GDI+;信号;图像缩放;旋转

图像处理,是对图像进行分析、加工、和处理,使其满足视觉、心理以及其他要求的技术。

图像处理是信号处理在图像域上的一个应用。

目前大多数的图像是以数字形式存储,因而图像处理很多情况下指数字图像处理。

此外,基于光学理论的处理方法依然占有重要的地位。

图像处理是信号处理的子类,另外与计算机科学、人工智能等领域也有密切的关系。

传统的一维信号处理的方法和概念很多仍然可以直接应用在图像处理上,比如降噪、量化等。

然而,图像属于二维信号,和一维信号相比,它有自己特殊的一面,处理的方式和角度也有所不同。

本例通过GDI+类库,实现图像的缩放和旋转。

主要应用了GDI+的Graphics类的DrawImage方法和移动坐标系等技术。

通过移动坐标系的逆向思维,来达到移动图像的效果。

本例主要使用GDI+类库实现图像的缩放和旋转。

首先简要介绍GDI+类库。

一、GDI的定义

GDI是GraphicsDeviceInterface的缩写,含义是图形设备接口,它的主要任务是负责系统与绘图程序之间的信息交换,处理所有Windows程序的图形输出。

 在Windows操作系统下,绝大多数具备图形界面的应用程序都离不开GDI,我们利用GDI所提供的众多函数就可以方便的在屏幕、打印机及其它输出设备上输出图形,文本等操作。

GDI的出现使程序员无需要关心硬件设备及设备驱动,就可以将应用程序的输出转化为硬件设备上的输出,实现了程序开发者与硬件设备的隔离,大大方便了开发工作。

二、GDI+的定义

GDI+是WindowsXP中的一个子系统,它主要负责在显示屏幕和打印设备输出有关信息,它是一组通过C++类实现的应用程序编程接口。

顾名思义,GDI+是以前版本GDI的继承者,出于兼容性考虑,WindowsXP仍然支持以前版本的GDI,但是在开发新应用程序的时候,开发人员为了满足图形输出需要应该使用GDI+,因为GDI+对以前的Windows版本中GDI进行了优化,并添加了许多新的功能。

 作为图形设备接口的GDI+使得应用程序开发人员在输出屏幕和打印机信息的时候无需考虑具体显示设备的细节,他们只需调用GDI+库输出的类的一些方法即可完成图形操作,真正的绘图工作由这些方法交给特定的设备驱动程序来完成,GDI+使得图形硬件和应用程序相互隔离.从而使开发人员编写设备无关的应用程序变得非常容易。

(陈国建2010)

三、GDI+的使用和主要函数

3.1GDI+应用环境的搭建

要在程序中使用GDI+类库,必须先引入GDI+开发环境。

GDI+开发环境的搭建主要分为如下几步:

1)在网络上下载GDI+的开发包。

地址为:

2)将下载得到的GDI+开发包进行解压,放在系统的某个磁盘上。

解压后的GDI+包中的内容如下,笔者是将GDI+包解压到了E:

\GDI+目录下:

 

图1-1解压后GDI+包中的内容

3)在VisualC++6.0中包含GDI+包所包含的库文件和头文件路径,步骤为:

(1)打开VC6.0,在菜单栏上选择ToolsOptions菜单,如图所示:

图1-2打开VC6,选择Tools--Options菜单的效果

(2)在弹出的Options对话框中选择Directories选项卡,进入目录设置,如图所示:

图1-3,在Options对话框中选择Directories选项卡的效果

(3)在ShowDirectoriesFor:

下拉框中选择Includefiles,在Directories下拉框中新建一个子项,选择刚才解压到磁盘的GDI+包的头文件路径,笔者的是E:

\GDI+\Include如图所示。

并将该目录移动到顶层。

如图所示:

图1-4选择GDI+Include目录的效果

(4)在ShowDirectoriesFor下拉框中选择LibrariesFiles,同样在Diectories下拉框中新建一个子项,选中GDI+包中的库文件所在路径。

并将库文件路径移到顶层。

效果如下:

图1-5添加库文件所在路径

(5)在VC6.0中新建一个基于文档/视的工程,在最后一步的选项中,选择视图类的基类为CScrollView,这主要是为了当图片尺寸大于视图尺寸时,可以滚动显示,如图所示:

 

图1-6设置CMyView类的基类为ScrollView

(6)在stdafx.h中加入使用GDI+库所需要的头文件和库文件的声明语句,如下:

#ifndefULONG_PTR

#defineULONG_PTRunsignedlong*

#include"Gdiplus.h"

usingnamespaceGdiplus;

#pragmacomment(lib,"Gdiplus.lib")

#endif

第一二句确保定义ULONG_PTR为unsignedlong*类型。

三四五句包含头文件和库文件,并且声明使用名称空间。

(左飞2011)

使用名称空间的目的是为了避免和其他名称空间的同名变量相混淆。

具体效果如图所示:

图1-7在stdafx.h中加入使用GDI+头文件和库文件的声明语句

(7)在CXXXXApp:

:

InitInstance()函数中加入初始化GDI+的函数,

在CXXXApp:

:

ExitInstance()中,加入退出GDI+的函数。

其中ExitInstance()

并没有直接加入,需要手动加入。

结果如下:

BOOLCBianhuanDemoApp:

:

InitInstance()

{

AfxEnableControlContainer();

//………………………………

//此处省略设计器生成的若干代码

GdiplusStartup(&m_Token,&m_Input,NULL);

}

intCBianhuanDemoApp:

:

ExitInstance()

{

//TODO:

Addyourspecializedcodehereand/orcallthebaseclass

GdiplusShutdown(m_Token);

returnCWinApp:

:

ExitInstance();

}

(8)由于GDI+中的String类使用的是宽字符,所以我们还需要设置UNICODE字符集,方法如下:

单击Project--Settings菜单,打开Settings页,如图所示:

图1-8单击Settings菜单的效果

点开C++选项卡,将_MBCS改成_UNICODE,如图所示:

图1-9修改_MBCS为_UNICODE的效果

点开Link选项卡,在Category下拉菜单中选择Output选项,如图所示:

图1-10选择Output下拉选项的效果

在EntryPointSymbol文本框中填入wWinMainCRTStartup,表示将WinMain入口函数改成宽字符的。

至此,全部配置工作结束。

图1-11改变入口函数

3.2.GDI+相关函数

GDI+中的相关函数。

1)启动GDI+的函数,StatusGdiplusStartup(

__out  ULONG_PTRtoken*token,

__in   constGdiplusStartupInput*input,

__out  GdiplusStartupOutput*output

);

参数介绍:

token变量是ULONG_PTR类型的指针,表示GDI+的令牌。

input变量是GDI+的输入变量。

output变量是GDI+输出变量,这个变量一般不用,设置为NULL即可。

2)退出GDI+的函数,voidGdiplusShutdown(

__in  ULONG_PTRtoken

);

token变量与GdiplusStartup函数中的token变量意思相同。

3)图元类的构造函数:

Graphics(

[in]  HDChdc

);

因为Windows的GDI绘图都是在设备上下文上绘制的,若要转换到图元的GDI+绘制,则必须创建一个与当前设备上下文相联系的图元对象。

该构造函数提供了将HDC(当前设备上下文对象)转换为图元的功能,以便使用图元类进行绘图。

(刘锐宁2011)

4)GDI+绘图函数:

StatusDrawImage(

[in]  Image*image,

[in]  constPoint*destPoints,

[in]  INTcount,

[in]  INTsrcx,

[in]  INTsrcy,

[in]  INTsrcwidth,

[in]  INTsrcheight,

[in]  UnitsrcUnit,

[in]  ImageAttributes*imageAttributes,

[in]  DrawImageAbortcallback,

[in]  VOID*callbackData

);

该函数有多个重载版本,以上版本是参数最齐全的一个。

其中image参数表示要绘制的图形对象。

destPoints指针表示目标图形的位置及大小的点数组。

count为目标图形点数组中点的个数。

srcx表示源图形左上角的X位置。

srcy源图形左上角的Y位置。

srcwidth为源图形宽度。

srcheight为源图形高度。

srcUnit为像素格式。

imageAttributes为图形属性对象,相关参数请参见MSDN。

callback为绘图回调函数。

callbackData为回调函数数据。

5)矩阵类构造函数:

Matrix:

:

Matrix(

REALm11,REALm12,

REALm21,REALm22,

REALdx,REALdy);

此构造函数构造出的矩阵如下:

[m11m120]

m21m220

dxdy1

6)对图元进行缩放的函数:

StatusGraphics:

:

ScaleTransform(

REALsx,REALsy,

MatrixOrderorder);

其中sx为水平缩放细数。

sy为垂直缩放系数。

缩放的关系矩阵如下:

[X1Y11]=[XY1][sx00]=[sx·Xsy·Y1]

0sy0

001

7)对矩阵进行旋转的函数:

StatusGraphics:

:

RotateTransform(REALangle,

MatrixOrderorder);

其中angle表示旋转的角度,不是弧度。

order参数的含义请参见MSDN。

注意GDI+中的旋转变换全部是按照顺时针方向的。

四、使用GDI+实现图像的缩放和旋转

为了便于动态控制图像缩放的倍数和旋转的角度,本例引入了一个设置对话框。

1)设置对话框部分的实现

(1)在工程中添加一个对话框资源,ID为IDD_DIALOG1,并为该对话框资源关联变量为CSetDlg。

(2)CSetDlg对象的布局如下:

图2-1CSetDlg对象的布局

CSetDlg对象中的控件及属性如下:

资源类型

资源ID

关联变量类型

关联变量名称

静态控件

IDC_STATIC1

文本控件

IDC_EDIT1

float

m_value

CSetDlg类的头文件及CPP文件如下:

CSetDlg.h代码清单:

classCSetDlg:

publicCDialog

{

//Construction

public:

CSetDlg(CWnd*pParent=NULL);//standardconstructor

//DialogData

//{{AFX_DATA(CSetDlg)

enum{IDD=IDD_DIALOG1};

floatm_value;

//}}AFX_DATA

 

//Overrides

//ClassWizardgeneratedvirtualfunctionoverrides

//{{AFX_VIRTUAL(CSetDlg)

protected:

virtualvoidDoDataExchange(CDataExchange*pDX);//DDX/DDVsupport

//}}AFX_VIRTUAL

//Implementation

protected:

//Generatedmessagemapfunctions

//{{AFX_MSG(CSetDlg)

virtualBOOLOnInitDialog();

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

};

CSetDlg.cpp代码清单,省略部分设计器自动生成代码:

BOOLCSetDlg:

:

OnInitDialog()

{

CDialog:

:

OnInitDialog();

//TODO:

Addextrainitializationhere

CBianhuanDemoView*view=(CBianhuanDemoView*)((CMainFrame*)AfxGetMainWnd())->GetActiveView();

if(view->nset==1)

{

SetWindowText(L"请输入旋转参数");

GetDlgItem(IDC_STATIC1)->SetWindowText(L"请输入旋转角度:

");

}

elseif(view->nset==2)

{

SetWindowText(L"请输入缩放参数");

GetDlgItem(IDC_STATIC1)->SetWindowText(L"请输入缩放比例:

");

}

returnTRUE;//returnTRUEunlessyousetthefocustoacontrol

//EXCEPTION:

OCXPropertyPagesshouldreturnFALSE

}

在CSetDlg类的OnInitDialog()函数中先判断CXXXView类中的nset参数是1还是2,如果是1,表示处于旋转状态,分别设置窗口标题和静态文本控件标题。

若为2,则为缩放状态,也设置相应标题。

2)旋转和缩放图形的实现

下面重点看下CXXXView类处理图形缩放和旋转的代码:

CBianhuanDemoView.h代码清单:

classCBianhuanDemoView:

publicCView

{

protected:

//createfromserializationonly

CBianhuanDemoView();

DECLARE_DYNCREATE(CBianhuanDemoView)

//Attributes

public:

CBianhuanDemoDoc*GetDocument();

enumBianhuan

{

SCALE,

ROTATE

};

Bianhuanbianhuan;

CStringfileName;

intnset;

floatm_value;

//Operations

public:

//Overrides

//ClassWizardgeneratedvirtualfunctionoverrides

//{{AFX_VIRTUAL(CBianhuanDemoView)

public:

virtualvoidOnDraw(CDC*pDC);//overriddentodrawthisview

virtualBOOLPreCreateWindow(CREATESTRUCT&cs);

protected:

virtualBOOLOnPreparePrinting(CPrintInfo*pInfo);

virtualvoidOnBeginPrinting(CDC*pDC,CPrintInfo*pInfo);

virtualvoidOnEndPrinting(CDC*pDC,CPrintInfo*pInfo);

//}}AFX_VIRTUAL

//Implementation

public:

voidShowRotateImage(CDC*pDC,Image&image,REALx,REALy,REALangle);

virtual~CBianhuanDemoView();

#ifdef_DEBUG

virtualvoidAssertValid()const;

virtualvoidDump(CDumpContext&dc)const;

#endif

protected:

//Generatedmessagemapfunctions

protected:

//{{AFX_MSG(CBianhuanDemoView)

afx_msgvoidOnRotate();

afx_msgvoidOnScale();

afx_msgvoidOnFileOpen();

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

};

其中定义了一个枚举类型的变量,名称叫做变换,用来控制操作类型。

其中枚举值分别为SCALE=0缩放,ROTATE=1旋转。

代码如下:

enumBianhuan

{

SCALE,

ROTATE

};

Bianhuanbianhuan;

这个变量将会在OnDraw函数和菜单的响应函数中被用到。

CBianhuanDemoView.cpp文件代码清单:

该清单省略了设计器自动生成的部分代码:

#include"SetDlg.h"

CBianhuanDemoView:

:

CBianhuanDemoView():

m_value

(2)

{

//TODO:

addconstructioncodehere

}

第一句包含设置对话框头文件,以便在源文件中进行使用。

第二句构造函数将m_value变量置为2。

voidCBianhuanDemoView:

:

OnDraw(CDC*pDC)

{

CBianhuanDemoDoc*pDoc=GetDocument();

ASSERT_VALID(pDoc);

//TODO:

adddrawcodefornativedatahere

switch(bianhuan)

{

caseROTATE:

//旋转

{

Bitmapimage1(fileName);

ShowRotateImage(pDC,image1,276,276,m_value);

}

break;

caseSCALE:

//缩放

{

Graphicsgrph(pDC->GetSafeHdc());

Bitmapimage(fileName);

RectFrect(16,16,image.GetWidth(),image.GetHeight());

if(m_value>2)

{

MessageBox(L"缩放比例过大,将按2倍大小处理!

");

m_value=2;

}

REALsx=m_value;

REALsy=m_value;

//grph.DrawImage(&image,rect);

grph.ScaleTransform(sx,sy);

grph.DrawImage(&image,rect);

}

break;

}

}

OnDraw函数中根据枚举值bianhuan的不同值,进行不同类型的绘图。

voidCBianhuanDemoView:

:

OnRotate()

{

//TODO:

Addyourcommandhandlercodehere

if(fileName.IsEmpty())

{

MessageBox(L"请先选择图像!

");

return;

}

nset=1;

CSetDlgdlg;

dlg.m_value=m_value;

if(dlg.DoModal()==IDCANCEL)

{

return;

}

this->m_value=dlg.m_value;

this->bianhuan=ROTATE;

this->Invalidate(TRUE);

}

voidCBianhuanDemoView:

:

OnScale()

{

//TODO:

Addyourcommandhandlercodehere

if(fileName.IsEmpty())

{

MessageBox(L"请先选择图像!

");

return;

}

nset=2;

CSetDlgdlg;

dlg.m_value=m_value;

if(dlg.DoModal()==IDCANCEL)

{

return;

}

this->m_value=dlg.m_value;

this->bianhuan=SCALE;

this->Invalidate(TRUE);

}

旋转

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 英语

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1