第二章 BMP位图类的创建与MFC单文档视图类的显示.doc_第1页
第二章 BMP位图类的创建与MFC单文档视图类的显示.doc_第2页
第二章 BMP位图类的创建与MFC单文档视图类的显示.doc_第3页
第二章 BMP位图类的创建与MFC单文档视图类的显示.doc_第4页
免费预览已结束,剩余1页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

BMP位图文件的4个组成部分bmp文件大体上分成四个部分。位图文件头BITMAPFILEHEADER 、位图信息头BITMAPINFOHEADER 、调色板Palette 、实际的位图数据ImageDate第1部分为位图文件头BITMAPFILEHEADER,是一个结构体类型,该结构的长度是固定的,为14个字节。其定义如下:typedef struct tagBITMAPFILEHEADER WORD bfType; DWORD bfSize; WORD bfReserved1; WORD bfReserved2; DWORD bfOffBits; BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;1.文件头信息块0000-0001 :文件标识,为字母ASCII码“BM”。0002-0005 :文件大小。0006-0009 :保留,每字节以“00”填写。000A-000D :记录图像数据区的起始位置。各字节的信息含义依次为:文件头信息块大小,图像描述信息块的大小,图像颜色表的大小,保留(为01)。第2部分为位图信息头BITMAPINFOHEADER,也是一个结构体类型的数据结构,该结构的长度也是固定的,为40个字节(WORD为无符号16位整数,DWORD为无符号32位整数,LONG为32位整数)。其定义如下:typedef struct tagBITMAPINFOHEADER DWORD biSize; 图像描述信息块的大小,常为28H。 LONG biWidth; LONG biHeight; WORD biPlanes; =1 WORD biBitCount;记录像素的位数 DWORD biCompression; 数据压缩方式 DWORD biSizeImage; 图像区数据的大小 LONG biXPelsPerMeter; 指定目标设备的水平分辨率,单位是像素/米 LONG biYPelsPerMeter; DWORD biClrUsed; 位图实际用到的颜色数 DWORD biClrImportant;位图显示过程中重要的颜色数,如果该值为零,则认为所有的颜色都是重要的。 BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;2.图像描述信息块000E-0011:图像描述信息块的大小,常为28H。0012-0015:图像宽度。0016-0019:图像高度。001A-001B:图像的plane总数(恒为1)。001C-001D:记录像素的位数,很重要的数值,图像的颜色数由该值决定。001E-0021:数据压缩方式(数值位0:不压缩;1:8位压缩;2:4位压缩)。0022-0025:图像区数据的大小。0026-0029:水平每米有多少像素,在设备无关位图(.DIB)中,每字节以00H填写。002A-002D:垂直每米有多少像素,在设备无关位图(.DIB)中,每字节以00H填写。002E-0031:此图像所用的颜色数,如值为0,表示所有颜色一样重要。第3部分为颜色表。颜色表实际上是一个RGBQUAD结构的数组,数组的长度由biClrUsed指定(如果该值为零,则由biBitCount指定,即2的biBitCount次幂个元素)。RGBQUAD结构是一个结构体类型,占4个字节,其定义如下:typedef struct tagRGBQUAD BYTE rgbBlue; BYTE rgbGreen; BYTE rgbRed; BYTE rgbReserved;RGBQUAD;3.颜色表颜色表的大小根据所使用的颜色模式而定:2色图像为8字节;16色图像位64字节;256色图像为1024字节。其中,每4字节表示一种颜色,并以B(蓝色)、G(绿色)、R(红色)、alpha(32位位图的透明度值,一般不需要)。即首先4字节表示颜色号0的颜色,接下来表示颜色号1的颜色,依此类推。第4部分是位图数据,即图像数据,其紧跟在位图文件头、位图信息头和颜色表(如果有颜色表的话)之后,记录了图像的每一个像素值。对于有颜色表的位图,位图数据就是该像素颜色在调色板中的索引值;对于真彩色图,位图数据就是实际的R、G、B值(三个分量的存储顺序是B、G、R)。下面分别就2色、16色、256色和真彩色位图的位图数据进行说明: 对于2色位图,用1位就可以表示该像素的颜色,所以1个字节能存储8个像素的颜色值。 对于16色位图,用4位可以表示一个像素的颜色。所以一个字节可以存储2个像素的颜色值。 对于256色位图,1个字节刚好存储1个像素的颜色值。 对于真彩色位图,3个字节才能表示1个像素的颜色值。需要注意两点:第一,Windows规定一个扫描行所占的字节数必须是4的倍数,不足4的倍数则要对其进行扩充。假设图像的宽为biWidth个像素、每像素biBitCount个比特,其一个扫描行所占的真实字节数的计算公式如下:DataSizePerLine = (biWidth * biBitCount /8+ 3) / 4*4那么,不压缩情况下位图数据的大小(BITMAPINFOHEADER结构中的biSizeImage成员)计算如下:biSizeImage = DataSizePerLine * biHeight第二,一般来说,BMP文件的数据是从图像的左下角开始逐行扫描图像的,即从下到上、从左到右,将图像的像素值一一记录下来,因此图像坐标零点在图像左下角。CDIB类的建立class CDibpublic: LPRGBQUAD m_lpRgbQuad;/颜色表指针 LPBYTE m_lpData; /位图数据指针 UINT m_numberOfColors;/颜色数BOOL m_bValid;/位图是否有效BOOL m_bHasRgbQuad;/是否有颜色表HPALETTE m_hPalette; /调色板句柄 LPBITMAPFILEHEADER m_lpBmpFileHeader; /位图文件头指针 LPBITMAPINFOHEADER m_lpBmpInfoHeader;/位图信息头指针 LPBITMAPINFO m_lpBmpInfo; /位图信息指针LPBYTE m_lpDib;/位图指针,包含除位图文件头的所有内容、需要动态分配和释放DWORD size;public: char m_fileName256; LPCTSTR GetFileName();BOOL LoadFile(LPCTSTR dibFileName);BOOL SaveFile(LPCTSTR filename);LPCTSTR GetFileName(); LONG GetWidth(); LONG GetHeight(); DWORD GetSize();/获取位图大小 WORD GetBitCount();/获取单个像素所占的位数 UINT GetLineByte();/获取每行像素所占字节数 UINT GetNumOfColor();/获取位图颜色数 LPRGBQUAD GetRgbQuad();/获取位图颜色表 LPBYTE GetData(); /获取位图数据 BOOL Draw(CDC* pDC,BYTE *,CPoint origin,CSize size);/显示位图 BOOL HasRgbQuad();/判断是否有颜色表? BITMAPINFO* GetInfo(); BOOL IsGrade();/判断是否为灰度图像WORD PaletteSize(LPBYTE lpDIB);WORD DIBNumColors(LPBYTE lpDIB); BOOL IsValid();/判断位图是否有效?protected:DWORD CalcRgbQuadLength();/计算位图颜色表的长度BOOL MakePalette();/根据颜色表生成调色板void Empty(BOOL bFlag=TRUE);/清理空间 public:CDib(void);CDib(void); ;主要成员函数:/函数功能:从文件加载位图/输入参数:LPCTSTR dibFileName表示待加载位图文件路径/返回值:加载是否成功/BOOL CDib:LoadFile(LPCTSTR dibFileName)strcpy(m_fileName,dibFileName);/记录位图文件名CFile dibFile;/选择读模式定义文件对象if(!dibFile.Open(LPCTSTR)m_fileName, CFile:modeRead|CFile:shareDenyWrite)return FALSE;Empty(FALSE);/为位图文件头指针分配空间,并初始化为m_lpBmpFileHeader=(LPBITMAPFILEHEADER)new BYTEsizeof(BITMAPFILEHEADER);memset(m_lpBmpFileHeader,0,sizeof(BITMAPFILEHEADER);/读取位图文件头int nCount=dibFile.Read(m_lpBmpFileHeader,sizeof(BITMAPFILEHEADER);/读bmp文件头信息到指针m_lpBmpfileHeaderif(nCount!=sizeof(BITMAPFILEHEADER)return FALSE;if (m_lpBmpFileHeader-bfType = 0x4d42)/判断是否是bmp文件DWORD fileLength = dibFile.GetLength(); /获取文件长度信息size = fileLength -sizeof(BITMAPFILEHEADER);/文件数据区大小=文件长度-文件头大小m_lpDib=new BYTEsize;memset(m_lpDib,0,size);dibFile.Read(void*)m_lpDib, size);/读除bmp文件头外的所有数据到指针m_lpDibdibFile.Close();/关闭文件m_lpBmpInfo = (LPBITMAPINFO) m_lpDib;/获取bmp文件的信息m_lpBmpInfoHeader = (LPBITMAPINFOHEADER) m_lpDib;/获取文件信息头地址m_lpRgbQuad = (LPRGBQUAD)(m_lpDib +m_lpBmpInfoHeader-biSize); /颜色表地址=pDib +m_lpBmpInfoHeader-biSize;int m_numberOfColors =GetNumOfColor();/颜色数if (m_lpBmpInfoHeader-biClrUsed = 0)/m_lpBmpInfoHeader-biClrUsed =m_numberOfColors;/颜色表的大小CalcRgbQuadLength()return m_numberOfColors *sizeof(RGBQUAD)DWORD colorTableSize =CalcRgbQuadLength();/位图数据区地址m_lpData =m_lpDib + m_lpBmpInfoHeader-biSize+ colorTableSize;if (m_lpRgbQuad = (LPRGBQUAD)m_lpData) / No color tablem_lpRgbQuad = NULL;m_lpBmpInfoHeader-biSizeImage = GetSize();m_bValid = TRUE;return TRUE; elsem_bValid = FALSE;AfxMessageBox(This isnt a bitmap file!);return FALSE;/将位图保存到文件/LPCTSTR filename表示位图文件保存路径文件名/返回值,TRUE-表示成功/BOOL CDib:SaveFile(LPCTSTR filename)CFile dibFile;/以写模式打开文件if(!dibFile.Open(LPCTSTR)filename, CFile:modeCreate|CFile:modeWrite|CFile:shareExclusive)return FALSE;strcpy(m_fileName,filename);dibFile.Write(m_lpBmpFileHeader,sizeof(BITMAPFILEHEADER);/将位图文件头结构写进文件dibFile.Write(m_lpBmpInfoHeader,sizeof(BITMAPINFOHEADER);/将位图信息头结构写进文件DWORD dwRgbQuandLength=CalcRgbQuadLength();/计算颜色表长度if(dwRgbQuandLength!=0)dibFile.Write(m_lpRgbQuad,dwRgbQuandLength);/若存在颜色表,则将颜色表写进位图文件DWORD dwDataSize=GetLineByte()*GetHeight();dibFile.Write(m_lpData,dwDataSize);/将位图数据写进位图文件dibFile.Close();/关闭文件return TRUE;/根据颜色表生成调色板/BOOL CDib:MakePalette()DWORD dwRgbQuadLength=CalcRgbQuadLength();if(dwRgbQuadLength=0)return FALSE;/为表示图像为真彩色图像,没有调色板if(m_hPalette!=NULL)/删除旧的调色板对象DeleteObject(m_hPalette);m_hPalette=NULL;/申请缓冲器,初始化为/*调色板编程见到这样两个结构: typedef struct tagPALETTEENTRY BYTE peRed; BYTE peGreen; BYTE peBlue; BYTE peFlags; PALETTEENTRY; typedef struct tagLOGPALETTE WORD palVersion; WORD palNumEntries; PALETTEENTRY palPalEntry1; / LOGPALETTE;*/DWORD dwNumOfColor=GetNumOfColor();DWORD dwSize=2*sizeof(WORD)+dwNumOfColor*sizeof(PALETTEENTRY);LPLOGPALETTE lpLongPalette=(LPLOGPALETTE)new BYTEdwSize;memset(lpLongPalette,0,dwSize);/生成逻辑调色板lpLongPalette-palVersion=0x300;lpLongPalette-palNumEntries=dwNumOfColor;LPRGBQUAD lpRgbQuad =(LPRGBQUAD)m_lpRgbQuad;/ m_lpRgbQuad位图文件颜色表地址for (int i=0;ipalPalEntryi.peRed=lpRgbQuad-rgbRed;lpLongPalette-palPalEntryi.peGreen=lpRgbQuad-rgbGreen;lpLongPalette-palPalEntryi.peBlue=lpRgbQuad-rgbBlue;lpLongPalette-palPalEntryi.peFlags=0;lpRgbQuad+;m_hPalette=CreatePalette(lpLongPalette);/创建逻辑调色板delete lpLongPalette;return TRUE;LPCTSTR CDib:GetFileName()return m_fileName;LONG CDib:GetWidth()return m_lpBmpInfoHeader-biWidth;LONG CDib:GetHeight()return m_lpBmpInfoHeader-biHeight;DWORD CDib:GetSize()if (m_lpBmpInfoHeader-biSizeImage!=0)return m_lpBmpInfoHeader-biSizeImage; elsereturn GetWidth()*GetHeight();WORD CDib:GetBitCount()return m_lpBmpInfoHeader-biBitCount;UINT CDib:GetLineByte()return (GetWidth()*GetBitCount()/8+3)/4*4;/获取图像使用的颜色数/UINT CDib:GetNumOfColor()UINT dwNumOfColor;/m_lpBmpInfoHeader-biClrUsed图像中使用的颜色数,m_lpBmpInfoHeader-biBitCount像素位数,if(m_lpBmpInfoHeader-biClrUsed=0)&(m_lpBmpInfoHeader-biBitCountbiBitCount)case 1:dwNumOfColor=2;break;case 4:dwNumOfColor=16;break;case 8:dwNumOfColor=256;elsedwNumOfColor=m_lpBmpInfoHeader-biClrUsed;return dwNumOfColor;DWORD CDib:CalcRgbQuadLength()DWORD dwNumOfColor=GetNumOfColor();if (dwNumOfColor256)dwNumOfColor=0;return dwNumOfColor*sizeof(RGBQUAD);/获取颜色表/返回颜色表指针/LPRGBQUAD CDib:GetRgbQuad()return m_lpRgbQuad;/获取位图数据区指针/LPBYTE CDib:GetData()return m_lpData;/函数功能:显示位图/CDC *pDC表示设备环境指针/CPoint origin 表示显示矩形区域的左上角/CSize size表示显示矩形区域的大小/BOOL CDib:Draw(CDC* pDC,BYTE * lpData,CPoint origin,CSize size)if(!IsValid()return FALSE;if(m_lpDib=NULL) return FALSE;HPALETTE hOldPalette=NULL;if(m_hPalette!=NULL)/如果位图有调色板则选进设备环境中hOldPalette=SelectPalette(pDC-GetSafeHdc(),m_hPalette,TRUE);pDC-SetStretchBltMode(COLORONCOLOR);/设置位图伸缩模式/将位图在pDC所指向的设备上进行显示StretchDIBits(pDC-GetSafeHdc(),origin.x,origin.y,size.cx,size.cy,0,0,GetWidth(),GetHeight(),lpData,m_lpBmpInfo,DIB_RGB_COLORS,SRCCOPY);if(hOldPalette!=NULL)SelectPalette(pDC-GetSafeHdc(),hOldPalette,TRUE);/恢复旧的调试板return TRUE;BOOL CDib:HasRgbQuad()return m_bHasRgbQuad;BOOL CDib:IsValid()return m_bValid;BOOL CDib:IsGrade()return (GetBitCount()0);void CDib:Empty(BOOL bFlag)/清理空间if(bFlag) strcpy(m_fileName,);if(m_lpBmpFileHeader!=NULL)delete m_lpBmpFileHeader;m_lpBmpFileHeader=NULL;if (m_lpDib!=NULL)delete m_lpDib;m_lpDib=NULL;m_lpBmpInfo=NULL;m_lpBmpInfoHeader=NULL;m_lpRgbQuad=NULL;m_lpData=NULL;if (m_hPalette!=NULL)DeleteObject(m_hPalette);m_hPalette=NULL;m_bHasRgbQuad=FALSE;m_bValid=FALSE;MFC单文档中图像的显示与操作一、创建MFC单文档工程:DIPAX二、在DIPAX工程添加CDib类的定义及其实现。三、在DIPAX工程MFC单文档中创建两个视图类,左右分开1、首先创建类:class CDynSplitterWnd :public CSplitterWndpublic:CDynSplitterWnd(void);CDynSplitterWnd(void);在CMainFrame中包含上述类的头文件,重写CMainFrame类的方法virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext);2、在重写类之前,创建新的视图类class CDynSplitView : public CView /第一个视图类:CdipaxView以及在CMainFrame里创建上述窗口分割类的对象CDynSplitterWnd m_wndSplitter;3、现在可以重写上述OnCreateClient()方法了:BOOL CMainFrame:OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)/ TODO: 在此添加专用代码和/或调用基类if (!m_wndSplitter.CreateStatic(this, 1, 2)TRACE0(Failed to Splitter windown);return FALSE;/ add the first splitter pane - the default view in column 0if (!m_wndSplitter.CreateView(0, 0,pContext-m_pNewViewClass, CSize(275, 150), pContext)TRACE0(Failed to create first panen);return FALSE;/ add the second splitter pane - an input view in column 1if (!m_wndSplitter.CreateView(0, 1,RUNTIME_CLASS(CDynSplitView), CSize(0, 0), pContext)TRACE0(Failed to create second panen);return FALSE;/ activate the input viewSetActiveView(CView*)m_wndSplitter.GetPane(0,1);return TRUE;/return CFrameWnd:OnCreateClient(lpcs, pContext);4、运行效果四、在视图类CdipaxView中显示位图1.在CdipaxDoc文档类中添加:(1)添加头文件#include DIB.h(2)添加成员变量:CDib Cdib;CString filename;int statedoc;(3)添加OnFileOpen()事件函数: OnFileOpen()void CdipaxDoc:OnFileOpen()/ TODO: 在此添加命令处理程序代码CFileDialog dlg(TRUE,_T(BMP),_T(*.BMP),OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,_T(位图文件(*.BMP)|*.BMP|);if(IDOK=dlg.DoModal ()filename.Format (%s,dlg.GetPathName() ); Cdib.LoadFile(filename);statedoc=1;(4)在构造函数中添加:CdipaxDoc:CdipaxDoc()/ TODO: 在此添加一次性构造代码statedoc=0;2、在CdipaxView视图类中添加:(1)在CdipaxView.h中添加成员变量public:CString filename;int state1;(2)在构造函数中添加:CdipaxView:CdipaxView()/ TODO: 在此处添加构造代码state1=0;(3)改写菜单项:(4)改写工具栏:(5)在CdipaxView中为菜单ID_ORIGINIMAGE添加事件处理程序:void CdipaxView:OnOriginimage()/ TODO: 在此添加命令处理程序代码CdipaxDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);filename=pDoc-filename;state1=1;Invalidate();(6)重写OnDraw函数:void CdipaxView:OnDraw(CDC* pDC)CdipaxDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);/ TODO: 在此处为本机数据添加绘制代码if(state1=1) pDoc-Cdib.Draw(pDC,pDoc-Cdib.m_lpData,CPoint(0,0),CSize(pDoc-Cdib.GetWidth(),pDoc-Cdib.G

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论