实验一 图像的读取和显示.doc_第1页
实验一 图像的读取和显示.doc_第2页
实验一 图像的读取和显示.doc_第3页
实验一 图像的读取和显示.doc_第4页
实验一 图像的读取和显示.doc_第5页
已阅读5页,还剩12页未读 继续免费阅读

下载本文档

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

文档简介

实验一 图像文件的读取和显示一、 实验目的学习在Visual C+环境下对BMP文件的读取和显示,为读取各种类型的文件和后续进行图像处理打下基础。二、 实验内容利用Visual C+为用户提供的专门api函数从图像文件中读取图像数据、显示图像。三、 预备知识熟悉Visual C+的开发环境。四、 实验原理与步骤DIB(Device-indepentent bitmap)的与设备无关性主要体现在以下两个方面: DIB的颜色模式与设备无关。例如,一个256色的DIB即可以在真彩色显示模式下使用,也可以在16色模式下使用。 256色以下(包括256色)的DIB拥有自己的颜色表,像素的颜色独立于系统调色板。由于DIB不依赖于具体设备,因此可以用来永久性地保存图象。DIB一般是以*.BMP文件的形式保存在磁盘中的,有时也会保存在*.DIB文件中。运行在不同输出设备下的应用程序可以通过DIB来交换图象。DIB还可以用一种RLE算法来压缩图像数据,但一般来说DIB是不压缩的。1 DIB的结构Visual C+中未提供现成的类来封装DIB,用户要想使用DIB,首先应该了解DIB的结构。在内存中,一个完整的DIB由两部分组成:一个BITMAPINFO结构和一个存储像素阵列的数组。BITMAPINFO描述了位图的大小,颜色模式和调色板等各种属性,其定义为typedef struct tagBITMAPINFO BITMAPINFOHEADER bmiHeader;RGBQUAD bmiColors1; /颜色表 BITMAPINFO;RGBQUAD结构用来描述颜色,其定义为typedef struct tagRGBQUAD BYTE rgbBlue; /蓝色的强度BYTE rgbGreen; /绿色的强度BYTE rgbRed; /红色的强度BYTE rgbReserved; /保留字节,为0 RGBQUAD;注意,RGBQUAD结构中的颜色顺序是BGR,而不是平常的RGB。BITMAPINFOHEADER结构包含了DIB的各种信息,其定义为typedef struct tagBITMAPINFOHEADERDWORD biSize; /该结构的大小LONG biWidth; /位图的宽度(以像素为单位)LONG biHeight; /位图的高度(以像素为单位)WORD biPlanes; /必须为1WORD biBitCount /每个像素的位数(1、4、8、16、24或32)DWORD biCompression; /压缩方式,一般为0或BI_RGB (未压缩)DWORD biSizeImage; /以字节为单位的图象大小(仅用于压缩位图)LONG biXPelsPerMeter; /以目标设备每米的像素数来说明位图的水平分辨率LONG biYPelsPerMeter; /以目标设备每米的像素数来说明位图的垂直分辨率DWORD biClrUsed;DWORD biClrImportant; /重要颜色的数目,若该值为0则所有颜色都重要 BITMAPINFOHEADER;与DDB不同,DIB的字节数组是从图象的最下面一行开始的逐行向上存储的,也即等于把图象倒过来然后在逐行扫描。另外,字节数组中每个扫描行的字节数必需是4的倍数,如果不足要用0补齐。DIB可以存储在*.BMP或*.DIB文件中。DIB文件是以BITMAPFILEHEADER结构开头的,该结构的定义为typedef struct tagBITMAPFILEHEADER WORD bfType; /文件类型,必须为“BM”DWORD bfSize; /文件的大小WORD bfReserved1; /为0WORD bfReserved2; /为0DWORD bfOffBits; /存储的像素阵列相对于文件头的偏移量 BITMAPFILEHEADER;紧随该结构的是一个BITMAPINFOHEADER结构,然后是RGBQUAD结构组成的颜色表(如果有的话),文件最后存储的是DIB的像素阵列。DIB的颜色信息储存在自己的颜色表中,程序一般要根据颜色表为DIB创建逻辑调色板。在输出一幅DIB之前,程序应该将其逻辑调色板选入到相关的设备上下文中并实现到系统调色板中,然后再调用相关的GDI函数(如:SetDIBitsToDevice或:StretchDIBits)输出DIB。 在输出过程中,GDI函数会把DIB转换成DDB,这项工作主要包括以下两步:将DIB的颜色格式转换成与输出设备相同的颜色格式。例如,在真彩色的显示模式下要显示一个256色的DIB,则应该将其转换成24位的颜色格式。将DIB像素的逻辑颜色索引转换成系统调色板索引。2 实验具体步骤(1)利用工程中的MFC AppWizard(exe),建立一个多文档应用程序(假定工程名为ReadBMP),工程选项默认。(2)向工程中添加一个新建的DIBAPI.cpp文件和DIBAPI.h文件。将如下代码拷贝到DIBAPI.h文件,里面是空白的,把如下代码考入文件中:/DIBAPI.h#ifndef _INC_DIBAPI#define _INC_DIBAPIDECLARE_HANDLE(HDIB);#define PALVERSION 0x300#define IS_WIN30_DIB(lpbi) (*(LPDWORD)(lpbi)=sizeof(BITMAPINFOHEADER)#define RECTWIDTH(lpRect) (lpRect)-right-(lpRect)-left)#define RECTHEIGHT(lpRect) (lpRect)-bottom-(lpRect)-top)#define WIDTHBYTES(bits) (bits)+31)/32*4)#define DIB_HEADER_MARKER (WORD)(MbiClrUsed; if(dwClrUsed) return (WORD)dwClrUsed; if(IS_WIN30_DIB(lpbi) wBitCount=(LPBITMAPINFOHEADER)lpbi)-biBitCount; else wBitCount=(LPBITMAPCOREHEADER)lpbi)-bcBitCount; switch(wBitCount) case 1: return 2; case 4: return 16; case 8: return 256; default: return 0; WORD WINAPI PaletteSize(LPSTR lpbi) if(IS_WIN30_DIB(lpbi) return (WORD)(DIBNumColors(lpbi)*sizeof(RGBQUAD); else return (WORD)(DIBNumColors(lpbi)*sizeof(RGBTRIPLE);LPSTR WINAPI FindDIBBits(LPSTR lpbi) return (lpbi+*(LPDWORD)lpbi+:PaletteSize(lpbi);DWORD WINAPI DIBWidth(LPSTR lpDIB) LPBITMAPINFOHEADER lpbmi; LPBITMAPCOREHEADER lpbmc;lpbmi=(LPBITMAPINFOHEADER)lpDIB; lpbmc=(LPBITMAPCOREHEADER)lpDIB; if(IS_WIN30_DIB(lpDIB) return lpbmi-biWidth; else return (DWORD)lpbmc-bcWidth;DWORD WINAPI DIBHeight(LPSTR lpDIB) LPBITMAPINFOHEADER lpbmi; LPBITMAPCOREHEADER lpbmc; lpbmi=(LPBITMAPINFOHEADER)lpDIB; lpbmc=(LPBITMAPCOREHEADER)lpDIB; if(IS_WIN30_DIB(lpDIB) return lpbmi-biHeight; else return (DWORD)lpbmc-bcHeight;BOOL WINAPI PaintDIB(HDC hDC,LPRECT lpDCRect,HDIB hDIB,LPRECT lpDIBRect,CPalette* pPal) LPSTR lpDIBHdr; LPSTR lpDIBBits; BOOL bSuccess=FALSE; HPALETTE hPal=NULL; HPALETTE hOldPal=NULL; if(hDIB=NULL) return FALSE; lpDIBHdr=(LPSTR):GlobalLock(HGLOBAL)hDIB); lpDIBBits=FindDIBBits(lpDIBHdr); if(pPal!=NULL) hPal=(HPALETTE)pPal-m_hObject; hOldPal=:SelectPalette(hDC,hPal,TRUE); :SetStretchBltMode(hDC,COLORONCOLOR);if(RECTWIDTH(lpDCRect)=RECTWIDTH(lpDIBRect)&(RECTHEIGHT(lpDCRect)=RECTHEIGHT(lpDIBRect) bSuccess=:SetDIBitsToDevice(hDC,lpDCRect-left,lpDCRect-top,RECTWIDTH(lpDCRect),RECTHEIGHT(lpDCRect),lpDIBRect-left,(int)DIBHeight(lpDIBHdr)-lpDIBRect-top-RECTHEIGHT(lpDIBRect),0,(WORD)DIBHeight(lpDIBHdr), lpDIBBits,(LPBITMAPINFO)lpDIBHdr,DIB_RGB_COLORS); else bSuccess=:StretchDIBits(hDC,lpDCRect-left,lpDCRect-top,RECTWIDTH(lpDCRect),RECTHEIGHT(lpDCRect),lpDIBRect-left, lpDIBRect-top,RECTWIDTH(lpDIBRect),RECTHEIGHT(lpDIBRect), lpDIBBits,(LPBITMAPINFO)lpDIBHdr,DIB_RGB_COLORS,SRCCOPY); :GlobalUnlock(HGLOBAL)hDIB);if(hOldPal) :SelectPalette(hDC,hOldPal,TRUE);GlobalUnlock(hDIB);return bSuccess;BOOL WINAPI CreateDIBPalette(HDIB hDIB,CPalette* pPal) LPLOGPALETTE lpPal; HANDLE hLogPal; HPALETTE hPal=NULL; LPSTR lpbi; LPBITMAPINFO lpbmi; LPBITMAPCOREINFO lpbmc; BOOL bWinStyleDIB; int i; WORD wNumColors; BOOL bResult=FALSE; if(hDIB=NULL) return FALSE; lpbi=(LPSTR):GlobalLock(HGLOBAL)hDIB); lpbmi=(LPBITMAPINFO)lpbi;lpbmc=(LPBITMAPCOREINFO)lpbi;wNumColors=DIBNumColors(lpbi);bWinStyleDIB=IS_WIN30_DIB(lpbi);if(wNumColors!=0) hLogPal=:GlobalAlloc(GHND,sizeof(LOGPALETTE)+sizeof(PALETTEENTRY)*wNumColors); if(hLogPal=0) :GlobalUnlock(HGLOBAL)hDIB); return FALSE; lpPal=(LPLOGPALETTE):GlobalLock(hLogPal); lpPal-palVersion=PALVERSION; lpPal-palNumEntries=(WORD)wNumColors; bWinStyleDIB=IS_WIN30_DIB(lpbi); for(i=0;ipalPalEntryi.peRed=lpbmi-bmiColorsi.rgbRed; lpPal-palPalEntryi.peGreen=lpbmi-bmiColorsi.rgbGreen; lpPal-palPalEntryi.peBlue=lpbmi-bmiColorsi.rgbBlue; lpPal-palPalEntryi.peFlags=0; else lpPal-palPalEntryi.peRed=lpbmc-bmciColorsi.rgbtRed; lpPal-palPalEntryi.peGreen=lpbmc-bmciColorsi.rgbtGreen; lpPal-palPalEntryi.peBlue=lpbmc-bmciColorsi.rgbtBlue; lpPal-palPalEntryi.peFlags=0; bResult=pPal-CreatePalette(lpPal); :GlobalUnlock(HGLOBAL)hLogPal); :GlobalFree(HGLOBAL)hLogPal); :GlobalUnlock(HGLOBAL)hDIB); return bResult;HGLOBAL WINAPI CopyHandle(HGLOBAL h) if(h=NULL) return NULL; DWORD dwLen=:GlobalSize(HGLOBAL)h);HGLOBAL hCopy=:GlobalAlloc(GHND,dwLen); if(hCopy!=NULL) void* lpCopy=:GlobalLock(HGLOBAL)hCopy); void* lp=:GlobalLock(HGLOBAL)h); memcpy(lpCopy,lp,dwLen); :GlobalUnlock(hCopy); :GlobalUnlock(h); return hCopy;BOOL WINAPI SaveDIB(HDIB hDib,CFile& file) BITMAPFILEHEADER bmfHdr; LPBITMAPINFOHEADER lpBI; DWORD dwDIBSize; if(!hDib) return FALSE; lpBI=(LPBITMAPINFOHEADER):GlobalLock(HGLOBAL)hDib); if(lpBI=NULL) return FALSE; if(!IS_WIN30_DIB(lpBI) :GlobalUnlock(HGLOBAL)hDib); return FALSE; bmfHdr.bfType=DIB_HEADER_MARKER;dwDIBSize=*(LPDWORD)lpBI+:PaletteSize(LPSTR)lpBI); if(lpBI-biCompression=BI_RLE8)|(lpBI-biCompression=BI_RLE4) dwDIBSize+=lpBI-biSizeImage; else DWORD dwBmBitsSize;dwBmBitsSize=WIDTHBYTES(lpBI-biWidth)*(DWORD)lpBI-biBitCount)*lpBI-biHeight; dwDIBSize+=dwBmBitsSize; lpBI-biSizeImage=dwBmBitsSize; bmfHdr.bfSize=dwDIBSize+sizeof(BITMAPFILEHEADER); bmfHdr.bfReserved1=0; bmfHdr.bfReserved2=0;bmfHdr.bfOffBits=(DWORD)sizeof(BITMAPFILEHEADER)+lpBI-biSize+:PaletteSize(LPSTR)lpBI); TRY file.Write(LPSTR)&bmfHdr,sizeof(BITMAPFILEHEADER); file.WriteHuge(lpBI,dwDIBSize); CATCH(CFileException,e) :GlobalUnlock(HGLOBAL)hDib); THROW_LAST(); END_CATCH :GlobalUnlock(HGLOBAL)hDib); return TRUE;HDIB WINAPI ReadDIBFile(CFile& file) BITMAPFILEHEADER bmfHeader; DWORD dwBitsSize; HDIB hDIB; LPSTR pDIB; dwBitsSize=file.GetLength(); if(file.Read(LPSTR)&bmfHeader,sizeof(bmfHeader)!=sizeof(bmfHeader) return NULL; if(bmfHeader.bfType!=DIB_HEADER_MARKER) return NULL; hDIB=(HDIB):GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,dwBitsSize); if(hDIB=0) return NULL; pDIB=(LPSTR):GlobalLock(HGLOBAL)hDIB);if(file.ReadHuge(pDIB,dwBitsSize-sizeof(BITMAPFILEHEADER)!=dwBitsSize-sizeof(BITMAPFILEHEADER) :GlobalUnlock(HGLOBAL)hDIB); :GlobalFree(HGLOBAL)hDIB); return NULL; :GlobalUnlock(HGLOBAL)hDIB); return hDIB;/在此处输入自己的函数定义上面是DIBAPI.h头文件中声明的函数的定义,你将自己的函数定义加到“/在此处输入自己的函数定义”后面。(3)在CMyReadBMPDoc类中增加相应的成员函数、消息映射函数和成员变量,可以利用MFC ClassWizard对话框实现(Ctrl+W键)。具体内容如下表所示:类型名称类型访问类型消息映射函数OnOpenDocumentOnSaveDocument成员变量m_hDIBHDIBPublicm_nColorIndexintPublicm_refColorBKGCOLORREFPublicm_sizeDocCSizeProtectedm_palDIBCPalette*Protected成员函数InitDIBData()voidPublicReplaceHDIB(HDIB hDIB)voidPublic各个函数里面的代码如下:l 构造函数CMyReadBMPDoc:CMyReadBMPDoc()里的代码:m_refColorBKG=0x00808080; m_hDIB=NULL; m_palDIB=NULL; m_sizeDoc=CSize(1,1);l 析构函数CMyReadBMPDoc:CMyReadBMPDoc()里的代码:if(m_hDIB!=NULL) :GlobalFree(HGLOBAL)m_hDIB);if(m_palDIB!=NULL) delete m_palDIB;l 文档打开函数BOOL CMyReadBMPDoc:OnOpenDocument(LPCTSTR lpszPathName)里的代码:CFile file;CFileException fe;if(!file.Open(lpszPathName,CFile:modeRead|CFile:shareDenyWrite,&fe) ReportSaveLoadException(lpszPathName,&fe,FALSE,AFX_IDP_FAILED_TO_OPEN_DOC);return FALSE; DeleteContents();BeginWaitCursor();TRY m_hDIB=:ReadDIBFile(file); CATCH(CFileException,eLoad) file.Abort(); EndWaitCursor();ReportSaveLoadException(lpszPathName,eLoad,FALSE,AFX_IDP_FAILED_TO_OPEN_DOC);m_hDIB=NULL;return FALSE; END_CATCHInitDIBData();EndWaitCursor();if(m_hDIB=NULL) CString strMsg; strMsg=读取图像时出错!可能是不支持该类型的图像文件!; MessageBox(NULL,strMsg,NULL,MB_ICONINFORMATION|MB_OK); return FALSE; SetPathName(lpszPathName);SetModifiedFlag(FALSE);l 文档保存函数BOOL CMyReadBMPDoc:OnSaveDocument(LPCTSTR lpszPathName)里的代码:CFile file;CFileException fe;if(!file.Open(lpszPathName,CFile:modeCreate|CFile:modeReadWrite|CFile:shareExclusive,&fe) ReportSaveLoadException(lpszPathName,&fe,TRUE,AFX_IDP_INVALID_FILENAME);return FALSE; BOOL bSuccess=FALSE;TRY BeginWaitCursor(); bSuccess=:SaveDIB(m_hDIB,file); file.Close(); CATCH(CException,eSave) file.Abort(); EndWaitCursor();ReportSaveLoadException(lpszPathName,eSave,TRUE,AFX_IDP_FAILED_TO_SAVE_DOC); return FALSE; END_CATCHEndWaitCursor();SetModifiedFlag(FALSE);if(!bSuccess) CString strMsg; strMsg=无法保存BMP图像; MessageBox(NULL,strMsg,NULL,MB_ICONINFORMATION|MB_OK); l 成员函数InitDIBData()里的代码:if(m_palDIB!=NULL) delete m_palDIB; m_palDIB=NULL; 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); :GlobalFree(HGLOBAL)m_hDIB); m_hDIB=NULL; CString strMsg; strMsg=BMP图像太大!; MessageBox(NULL,strMsg,NULL,MB_ICONINFORMATION|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); m_hDIB=NULL; return; if(:CreateDIBPalette(m_hDIB,m_palDIB)=NULL) delete m_palDIB; m_palDIB=NULL; return; l 成员函数ReplaceHDIB(HDIB hDIB)里的代码:if(m_hDIB!=NULL) :GlobalFree(HGLOBAL)m_hDIB);m_hDIB=hDIB;l 在CMyReadBMPdoc.h的“/ Attributes”和“public:”后加入代码: HDIB GetHDIB() const return m_hDIB; CPalette* GetDocPalette() const return m_palDIB; CSize GetDocSize() const return m_sizeDoc

温馨提示

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

评论

0/150

提交评论