当前位置:文档之家› 计算机图形学 实验二要点

计算机图形学 实验二要点

计算机科学系实验报告课程名称计算机图形学班级12网络2实验名称VC存取BMP图像及其几何变换教导教师吴志攀姓名李文森学号1214080613213 日期2014 .11.21一、实验目的1. 掌握VC中BMP图像的存取方法;2. 掌握BMP图像平移、旋转、变比等几何变换。

二、实验设备与环境TC2.0,Windows XP三、实验内容、程序清单及运行结果1.打开VC++ 6.0,选择File|New进入界面。

在Projects中选择MFC AppWinzard(exe),在Project name中输入项目名称,本例为ReadBMP,在Location中输入项目要保存的文件夹。

点击“OK”进入下一步。

如下图2-1所示。

图2-12.选择文档类型。

在本例中使用的是单文档视图结构,所以这里选择Singledocument。

其余部分设置使用VC++ 6.0的默认设置,点击“Finish”完成项目创建。

如下图2-2所示:图2-23.为了将BMP中的数据读入到内存中,在项目中导入专门处理BMP文件头和数据的文件:DIBAPI.H和DIBAPI.CPP,在其中实现对BMP文件的大部分处理。

在工作区“FileView”选项卡的“Header Files”中点右键,在“添加文件到目录”添加“DIBAPI.H”文件。

如下图2-3所示:图2-3在工作区“FileView”选项卡的“Source Files”中点右键,在“添加文件到目录”添加“DIBAPI.CPP”文件。

并在“ReadBMPDoc.h”添加头文件"dibapi.h",如下所示:#include "dibapi.h"4.在CReadBMPDoc类中添加保护成员变量CPalette* m_palDIB,HDIB m_hDIB和CSize m_sizeDoc。

m_hDIB用于保存当前BMP图像句柄,m_palDIB用于指向BMP图像对应的调色板。

protected:HDIB m_hDIB;CPalette* m_palDIB;CSize m_sizeDoc;5.为了取得保存在当前文档中的HDIB和Palette数据,在“ReadBMPDoc.h”的CReadBMPDoc类中添加方法:GetHDIB,GetDocPalette和GDocSize。

如下所示:// Attributespublic:HDIB GetHDIB() const{ return m_hDIB; }CPalette* GetDocPalette() const{ return m_palDIB; }CSize GetDocSize() const{ return m_sizeDoc; }在CReadBMPDoc.cpp的构造函数中初始化:// 初始化变量m_hDIB = NULL;m_palDIB = NULL;m_sizeDoc = CSize(1,1);6.响应类CReadBMPDoc OnOpenDocument事件,以实现打开文件的操作。

从View|ClassWizard进入MFC ClassWizard界面,在Message Maps选项中完成消息映射。

下图2-4所示:图2-4在BOOL CReadBMPDoc::OnOpenDocument(LPCTSTR lpszPathName)函数中添加如下代码://if (!CDocument::OnOpenDocument(lpszPathName))//return FALSE;// TODO: Add your specialized creation code here//return TRUE;CFile file;CFileException fe;// 打开文件if (!file.Open(lpszPathName, CFile::modeRead | CFile::shareDenyWrite, &fe)){// 失败ReportSaveLoadException(lpszPathName, &fe,FALSE, AFX_IDP_FAILED_TO_OPEN_DOC);// 返回FALSEreturn FALSE;}DeleteContents();// 更改光标形状BeginWaitCursor();// 尝试调用ReadDIBFile()读取图像TRY{m_hDIB = ::ReadDIBFile(file);}CA TCH (CFileException, eLoad){// 读取失败file.Abort();// 恢复光标形状EndWaitCursor();// 报告失败ReportSaveLoadException(lpszPathName, eLoad,FALSE, AFX_IDP_FAILED_TO_OPEN_DOC);// 设置DIB为空m_hDIB = NULL;// 返回FALSEreturn FALSE;}END_CATCH// 初始化DIBInitDIBData();// 恢复光标形状EndWaitCursor();// 判断读取文件是否成功if (m_hDIB == NULL){// 失败,可能非BMP格式CString strMsg;strMsg = "读取图像时出错!可能是不支持该类型的图像文件!";// 提示出错MessageBox(NULL, strMsg, "系统提示", MB_ICONINFORMA TION | MB_OK);// 返回FALSEreturn FALSE;}// 设置文件名称SetPathName(lpszPathName);// 初始化胀标记为FALSESetModifiedFlag(FALSE);// 返回TRUEreturn TRUE;并在ReadBMPDoc.cpp添加Public成员函数InitDIBData,并添加如下程序:void CReadBMPDoc::InitDIBData(){// 初始化DIB对象// 判断调色板是否为空if (m_palDIB != NULL){// 删除调色板对象delete m_palDIB;// 重置调色板为空m_palDIB = NULL;}// 如果DIB对象为空,直接返回if (m_hDIB == NULL){// 返回return;}LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);// 判断图像是否过大if (::DIBWidth(lpDIB) > INT_MAX ||::DIBHeight(lpDIB) > INT_MAX){::GlobalUnlock((HGLOBAL) m_hDIB);// 释放DIB对象::GlobalFree((HGLOBAL) m_hDIB);// 设置DIB为空m_hDIB = NULL;CString strMsg;strMsg = "BMP图像太大!";// 提示用户MessageBox(NULL, strMsg, "系统提示", MB_ICONINFORMA TION | MB_OK);// 返回return;}// 设置文档大小m_sizeDoc = CSize((int) ::DIBWidth(lpDIB), (int) ::DIBHeight(lpDIB));::GlobalUnlock((HGLOBAL) m_hDIB);// 创建新调色板m_palDIB = new CPalette;// 判断是否创建成功if (m_palDIB == NULL){// 失败,可能是内存不足::GlobalFree((HGLOBAL) m_hDIB);// 设置DIB对象为空m_hDIB = NULL;// 返回return;}// 调用CreateDIBPalette来创建调色板if (::CreateDIBPalette(m_hDIB, m_palDIB) == NULL){// 返回空,可能该DIB对象没有调色板// 删除delete m_palDIB;// 设置为空m_palDIB = NULL;// 返回return;}}// 调用CreateDIBPalette来创建调色板if (::CreateDIBPalette(m_hDIB, m_palDIB) == NULL){// 返回空,可能该DIB对象没有调色板// 删除delete m_palDIB;// 设置为空m_palDIB = NULL;// 返回return;}7.完成图片的打开操作之后,图片的数据就已经被保存在程序中,为了将图片显示出来还需要响应类CReadBMPView的OnDraw事件,在其中完成图像显示。

void CReadBMPView::OnDraw(CDC* pDC){//CReadBMPDoc* pDoc = GetDocument();//ASSERT_V ALID(pDoc);// TODO: add draw code for native data here// 显示等待光标BeginWaitCursor();// 获取文档CReadBMPDoc* pDoc = GetDocument();ASSERT_V ALID(pDoc);// 获取DIBHDIB hDIB = pDoc->GetHDIB();// 判断DIB是否为空if (hDIB != NULL){LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);// 获取DIB宽度int cxDIB = (int) ::DIBWidth(lpDIB);// 获取DIB高度int cyDIB = (int) ::DIBHeight(lpDIB);::GlobalUnlock((HGLOBAL) hDIB);CRect rcDIB;rcDIB.top = rcDIB.left = 0;rcDIB.right = cxDIB;rcDIB.bottom = cyDIB;CRect rcDest;// 判断是否是打印if (pDC->IsPrinting()){// 是打印,计算输出图像的位置和大小,以便符合页面// 获取打印页面的水平宽度(象素)int cxPage = pDC->GetDeviceCaps(HORZRES);// 获取打印页面的垂直高度(象素)int cyPage = pDC->GetDeviceCaps(VERTRES);// 获取打印机每英寸象素数int cxInch = pDC->GetDeviceCaps(LOGPIXELSX);int cyInch = pDC->GetDeviceCaps(LOGPIXELSY);// 计算打印图像大小(缩放,根据页面宽度调整图像大小)rcDest.top = rcDest.left = 0;rcDest.bottom = (int)(((double)cyDIB * cxPage * cyInch)/ ((double)cxDIB * cxInch));rcDest.right = cxPage;// 计算打印图像位置(垂直居中)int temp = cyPage - (rcDest.bottom - rcDest.top);rcDest.bottom += temp/2;rcDest.top += temp/2;}else// 非打印{// 不必缩放图像rcDest = rcDIB;}// 输出DIB::PaintDIB(pDC->m_hDC, &rcDest, pDoc->GetHDIB(),&rcDIB, pDoc->GetDocPalette());}// 恢复正常光标EndWaitCursor();}8.编译、调试并运行程序,自此一个用于打开BMP图像的单文档视图结构的程序就完成了。

相关主题