1、DIBAPI.H和DIBAPI.CPP,在其中实现对BMP文件的大部分处理。在工作区“FileView”选项卡的“Header Files”中点右键,在“添加文件到目录”添加“DIBAPI.H”文件。如下图23所示:图23在工作区“FileView”选项卡的“Source Files”中点右键,在“添加文件到目录”添加“DIBAPI.CPP”文件。并在“ReadBMPDoc.h”添加头文件dibapi.h,如下所示:#include 4在CReadBMPDoc类中添加保护成员变量CPalette* m_palDIB,HDIB m_hDIB和CSize m_sizeDoc。m_hDIB用于保存当
2、前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; CS
3、ize 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选项中完成消息映射。下图24所示:图24在BOOL CReadBMPDoc:OnOpenDocument(LPCTSTR lpszPathName)
4、函数中添加如下代码: /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, A
5、FX_IDP_FAILED_TO_OPEN_DOC); / 返回FALSE return FALSE; DeleteContents(); / 更改光标形状 BeginWaitCursor(); / 尝试调用ReadDIBFile()读取图像 TRY m_hDIB = :ReadDIBFile(file); CATCH (CFileException, eLoad) / 读取失败 file.Abort(); / 恢复光标形状 EndWaitCursor(); / 报告失败 ReportSaveLoadException(lpszPathName, eLoad, / 设置DIB为空 m_hDIB
6、 = NULL; END_CATCH / 初始化DIB InitDIBData(); / 恢复光标形状 EndWaitCursor(); / 判断读取文件是否成功 if (m_hDIB = NULL) / 失败,可能非BMP格式 CString strMsg; strMsg = 读取图像时出错!可能是不支持该类型的图像文件!; / 提示出错 MessageBox(NULL, strMsg, 系统提示, MB_ICONINFORMATION | MB_OK); / 设置文件名称 SetPathName(lpszPathName); / 初始化胀标记为FALSE SetModifiedFlag(F
7、ALSE); / 返回TRUE return TRUE;并在ReadBMPDoc.cpp添加Public成员函数InitDIBData,并添加如下程序:void CReadBMPDoc:InitDIBData() / 初始化DIB对象 / 判断调色板是否为空 if (m_palDIB != NULL) / 删除调色板对象 delete m_palDIB; / 重置调色板为空 m_palDIB = NULL; / 如果DIB对象为空,直接返回 / 返回 return; LPSTR lpDIB = (LPSTR) :GlobalLock(HGLOBAL) m_hDIB); / 判断图像是否过大 i
8、f (:DIBWidth(lpDIB) INT_MAX |:DIBHeight(lpDIB) INT_MAX) :GlobalUnlock(HGLOBAL) m_hDIB); / 释放DIB对象GlobalFree(HGLOBAL) m_hDIB);BMP图像太大! / 提示用户 / 设置文档大小 m_sizeDoc = CSize(int) :DIBWidth(lpDIB), (int) :DIBHeight(lpDIB); : / 创建新调色板 m_palDIB = new CPalette; / 判断是否创建成功 if (m_palDIB = NULL) / 失败,可能是内存不足 / 设
9、置DIB对象为空 / 调用CreateDIBPalette来创建调色板CreateDIBPalette(m_hDIB, m_palDIB) = NULL) / 返回空,可能该DIB对象没有调色板 / 删除 / 设置为空 7.完成图片的打开操作之后,图片的数据就已经被保存在程序中,为了将图片显示出来还需要响应类CReadBMPView的OnDraw事件,在其中完成图像显示。void CReadBMPView:OnDraw(CDC* pDC) /CReadBMPDoc* pDoc = GetDocument(); /ASSERT_VALID(pDoc); add draw code for nat
10、ive data here / 显示等待光标 / 获取文档 CReadBMPDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); / 获取DIB HDIB hDIB = pDoc-GetHDIB(); / 判断DIB是否为空 if (hDIB ! LPSTR lpDIB = (LPSTR) :GlobalLock(HGLOBAL) hDIB); / 获取DIB宽度 int cxDIB = (int) :DIBWidth(lpDIB); / 获取DIB高度 int cyDIB = (int) :DIBHeight(lpDIB);GlobalUnlock(H
11、GLOBAL) 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); / 获取打印机每英寸象素
12、数 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.bot
13、tom - rcDest.top); rcDest.bottom += temp/2; rcDest.top += temp/2; else / 非打印 / 不必缩放图像 rcDest = rcDIB; / 输出DIBPaintDIB(pDC-m_hDC, &rcDest, pDoc-GetHDIB(), &rcDIB, pDoc-GetDocPalette(); / 恢复正常光标8.编译、调试并运行程序,自此一个用于打开BMP图像的单文档视图结构的程序就完成了。通过修改当前位图句柄m_hDIB中存放像素的数据就可以对图像进行改变了。 9. 在项目中导入专门处理BMP几何变换的文件:GeoTr
14、ans.H和GeoTrans.CPP。并在ReadBMPView.cpp文件中添加:GeoTrans.h打开“Resource View”对菜单进行修改,添加“几何变换”菜单项。添加“图像平移”子菜单,ID为“ID_Geo_Trans”。在“CReadBMPView”中建立名为“OnGeoTrans”的“OnCommand”函数。OnGeoTrans() Add your command handler code here / 平移位图 /CCh1_1Doc* pDoc = GetDocument(); / 指向DIB的指针 LPSTR lpDIB; / 指向DIB象素指针 LPSTR lpD
15、IBBits; / 锁定DIB lpDIB = (LPSTR) :GlobalLock(HGLOBAL) pDoc-GetHDIB(); / 判断是否是8-bpp位图(这里为了方便,只处理8-bpp位图的平移,其它的可以类推)DIBNumColors(lpDIB) != 256) MessageBox(目前只支持256色位图的平移!, , MB_ICONINFORMATION | MB_OK); / 解除锁定GlobalUnlock(HGLOBAL) pDoc- LONG lXOffset; LONG lYOffset; / 创建对话框 /CDlgGeoTran dlgPara; / 初始化变
16、量值 /dlgPara.m_XOffset = 100; /dlgPara.m_YOffset = 100; / 显示对话框,提示用户设定平移量 /if (dlgPara.DoModal() != IDOK) / /return; / / 获取用户设定的平移量 lXOffset = 100; lYOffset = 100; / 删除对话框 /delete dlgPara; / 找到DIB图像象素起始位置 lpDIBBits = :FindDIBBits(lpDIB); / 调用TranslationDIB()函数平移DIB if (TranslationDIB1(lpDIBBits, :DIB
17、Width(lpDIB), :DIBHeight(lpDIB), lXOffset, lYOffset) / 设置脏标记 pDoc-SetModifiedFlag(TRUE); / 更新视图UpdateAllViews(NULL); else分配内存失败! / 解除锁定 / 恢复光标10. 在“几何变换”菜单项中添加“垂直镜像”子菜单,ID为“ID_Geo_MirV”。在“CReadBMPView”中建立名为“OnGeoMirV”的“OnCommand”函数。 void CReadBMPView:OnGeoMirV() / 垂直镜像 / 判断是否是8-bpp位图(这里为了方便,只处理8-bpp
18、位图的垂直镜像,其它的可以类推)目前只支持256色位图的垂直镜像! / 调用MirrorDIB()函数垂直镜像DIB if (MirrorDIB(lpDIBBits, :DIBHeight(lpDIB), FALSE)11. 在“几何变换”菜单项中添加“水平镜像”子菜单,ID为“ID_Geo_MirH”。在“CReadBMPView”中建立名为“OnGeoMirH”的“OnCommand”函数。OnGeoMirH() / 水平镜像 / 判断是否是8-bpp位图(这里为了方便,只处理8-bpp位图的水平镜像,其它的可以类推)目前只支持256色位图的水平镜像! / 调用MirrorDIB()函数水平镜像DIBDIBHeight(lpDIB), TRUE)12. 在“几何变换”菜单项中添加“图像转置”子菜单,ID为“ID_Geo_Transpose”。在“CReadBMPView”中建立名为“OnGeoTranspose”的“OnCommand”函数。OnGeoTranspose() / TOD
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1