实验一VC60下bmp位图的读取与显示.docx
《实验一VC60下bmp位图的读取与显示.docx》由会员分享,可在线阅读,更多相关《实验一VC60下bmp位图的读取与显示.docx(17页珍藏版)》请在冰豆网上搜索。
![实验一VC60下bmp位图的读取与显示.docx](https://file1.bdocx.com/fileroot1/2023-2/3/af4fce94-b6bc-4837-9079-9c83fa5c045c/af4fce94-b6bc-4837-9079-9c83fa5c045c1.gif)
实验一VC60下bmp位图的读取与显示
实验一、VC6.0下bmp位图的读取与显示
一、实验目的:
1、掌握windowsBMP格式位图文件的基本格式。
2、会使用VC++读取图像数据并显示。
二、实验内容:
1、在VC6.0环境下,生成MFC应用程序框架。
2、在已生成的应用程序中,加BMP位图读取与显示的代码,从已有文件中读取bmp格式文件并在视图中显示。
三、实验原理及步骤:
基本知识:
BMP位图文件格式
BMP位图文件中主要由4部分内容组成:
1、文件头BITMAPFILEHEADER为一STRUCTURE:
typedefstructtagBITMAPFILEHEADER{
WORDbfType;//文件类型,必须为“BM”或0x424d
DWORDbfSize;//文件大小
WORDbfReserved1;//保留
WORDbfReserved2;//保留
DWORDbfOffBits;//从文件头到实际位图数据的偏移字节数
}BITMAPFILEHEADER,FAR*LPBITMAPFILEHEADER,*PBITMAPFILEHEADER;
2、位图信息头BITMAPINFOHEADER,定义如下:
typedefstructtagBITMAPINFOHEADER{
DWORDbiSize;//structuresize
LONGbiWidth;//imagewidth
LONGbiHeight;//imageheight
WORDbiPlanes;//valueis1
WORDbiBitCount;//colorbits
DWORDbiCompression;//compressionornot
DWORDbiSizeImage;//Imagesize=width*height(其中width必须为4的倍数。
LONGbiXPelsPerMeter;//
LONGbiYPelsPerMeter;
DWORDbiClrUsed;//
DWORDbiClrImportant;
}BITMAPINFOHEADER,FAR*LPBITMAPINFOHEADER,*PBITMAPINFOHEADER;
3、调色板
typedefstructtagRGBQUAD{
BYTErgbBlue;
BYTErgbGreen;
BYTErgbRed;
BYTErgbReserved;
}RGBQUAD;用于存放图像的颜色。
4、图像的实际数据。
对于2色图,用1位表示像素的值。
对于16色图,用4位表示像素的值。
对于256色图,一个字节刚好表示1个像素。
对于用到调色板的位图,图像数据就是该像素颜色在调色板中索引值,对于真彩色,不用调色板,三个字节的数据分别代表图像的B、G、R。
具体实验步骤
1、生成一名为zhangyunxiang的基于MFC的应用程序框架:
选择file菜单new选项,在打开的窗口中选择project选项,选中MFCAppWizard(exe)。
并在projectname输入zhangyunxiang,选择存放project的位置。
如下图所示。
选择OK,进入下一步。
选择singledocument,如下图
最后CzhangyunxiangView类的基类中选择CscrollView,使应用程序视图具有滚动条。
如下图
点击Finish完成生成一名为zhangyunxiang的基于MFC的应用程序框架。
2、对class视图进行操作,添加成员变量跟成员函数到相应现在的zhangyunxiangview下
(1)在CzhangyunxiangView.h中加入如入变量:
具体步骤:
单击(右击)CzhangyunxiangView,在其中选中AddMenberVariable控件如下图:
然后左击它,接着就会出现如下图所示的对话框
在其中依次加入以下变量:
public:
intm_x;
HBITMAPm_Bmp;
LPVOIDm_ColorList;
LPBYTEm_Image;
LPBITMAPINFOHEADERm_DibHead;
enumallocate{None,crtallocate,heapallocate};
allocatem_nBmpallocate;
allocatem_nImageallocate;
DWORDm_ImageSize;
intm_nPalette;
HANDLEm_hFile;
HANDLEm_hMap;
LPVOIDm_lpvFile;
HPALETTEm_hPalette;
HGLOBALm_hGlob;
(2)在CzhangyunxiangView.h中加入如入变量:
具体步骤:
单击(右击)CzhangyunxiangView,在其中选中AddMenberFunction控件如下图:
然后左击它,接着就会出现如下图所示的对话框
利用ClassWizard向CzhangyunxiangView类中加入如下成员函数。
voidSetPaletteSize(intnBitCount);//设置调色板大小
voidClear();//清除
BOOLReadFile(CFile*pFile);//读取数据到内存
BOOLSetPalette();//当前位图颜色数大于256设置调色板
BOOLGetPalette();//创建颜色数不大于256的调色板
BOOLDibToDC(CDC*pDC,CSizesize);显示位图
BOOLMemToDib(LPVOIDlmem);//得到内存中位图象素位置
CSizeGetDibSize();//返回位图尺寸
完成以上操作后,在dipView.cpp中找到所添加函数的函数体,copy到自己建立的zhangyunxiangView.cpp中对应的函数名称的下面。
3、设计一个名为IDB_BITMAP1的位图
在resourc下单机右键,选择插入,单击Bitmap,选择新建,然后自己新建一个位图,保存。
4.修改OnDraw和OnInitialUpdate()函数设置滚动条的初始化图形和现实图像,如果不写OnDraw函数体的话图像将被保存在缓冲区而不显示出来
改后的程序为:
5.在Resource下双击Toolbar,打开工具栏编辑器,先对放大缩小工具图标进行绘制,绘制完成后在上面的工具栏中找到所设计的相应的图标,双击图标对图标进行ID的设置,之后在Menu下双击IDR_MAINFRAME进行类向导设计,类向导设计跟上学期的MFC实验中的类向导设计一样,然后添加放大缩小的函数内容到对应的函数下面
6、打开Menu资源,双击主菜单,打开菜单资源编辑器中打开选项,右键单击,选择类向导Class中选择Czhangyunxiangview,单击commond选择AddFunction单击OK,单击Editcode,拷贝Onfileopen函数中代码。
这样就可以打开相应的BMP格式图片。
如下图所示
7.利用资源编辑器,在主菜单中添加消息响应函数OnFileOpen(),并加入入下代码:
CFileDialogfiledlg(TRUE,"bmp","*.bmp");
if(filedlg.DoModal()!
=IDOK)
return;
CFilemyfile;
myfile.Open(filedlg.GetPathName(),CFile:
:
modeRead);
if(ReadFile(&myfile)==TRUE)
Invalidate();
SetPalette();
附录1:
读取bmp位图的函数代码。
CSizeCDipView:
:
GetDibSize()
{
if(m_DibHead==NULL)
returnCSize(0,0);
returnCSize((int)m_DibHead->biWidth,(int)m_DibHead->biHeight);
}
BOOLCDipView:
:
MemToDib(LPVOIDlmem)
{
Clear();
m_DibHead=(LPBITMAPINFOHEADER)lmem;
SetPaletteSize(m_DibHead->biBitCount);
m_Image=(LPBYTE)m_ColorList+sizeof(RGBQUAD)*m_nPalette;
GetPalette();
returnTRUE;
}
BOOLCDipView:
:
DibToDC(CDC*pDC,CSizesize)
{
if(m_DibHead==NULL)
returnFALSE;
if(m_hPalette!
=NULL)
{
HDChdc=pDC->GetSafeHdc();
:
:
SelectPalette(hdc,m_hPalette,TRUE);
}
pDC->SetStretchBltMode(COLORONCOLOR);
:
:
StretchDIBits(pDC->GetSafeHdc(),0,0,size.cx,size.cy,
0,0,m_DibHead->biWidth,m_DibHead->biHeight,
m_Image,(LPBITMAPINFO)m_DibHead,DIB_RGB_COLORS,
SRCCOPY);
returnTRUE;
}
BOOLCDipView:
:
GetPalette()
{
if(m_nPalette==0)
returnFALSE;
if(m_hPalette!
=NULL)
:
:
DeleteObject(m_hPalette);
LPLOGPALETTEpTempPalette=(LPLOGPALETTE)newchar[2*sizeof(WORD)+
m_nPalette*sizeof(PALETTEENTRY)];
pTempPalette->palVersion=0x30;
pTempPalette->palNumEntries=m_nPalette;
LPRGBQUADpRGBQuad=(LPRGBQUAD)m_ColorList;
for(inti=0;i{
pTempPalette->palPalEntry[i].peRed=pRGBQuad->rgbRed;
pTempPalette->palPalEntry[i].peGreen=pRGBQuad->rgbGreen;
pTempPalette->palPalEntry[i].peBlue=pRGBQuad->rgbBlue;
pTempPalette->palPalEntry[i].peFlags=0;
pRGBQuad++;
}
m_hPalette=:
:
CreatePalette(pTempPalette);
deletepTempPalette;
returnTRUE;
}
BOOLCDipView:
:
SetPalette()
{
if(m_nPalette!
=0)
returnFALSE;
CClientDCdc(this);
CDC*pDC=&dc;
m_hPalette=:
:
CreateHalftonePalette(pDC->GetSafeHdc());
returnTRUE;
}
BOOLCDipView:
:
ReadFile(CFile*pFile)
{
intnCount,nSize;
BITMAPFILEHEADERbmfh;
Clear();
try{
nCount=pFile->Read((LPVOID)&bmfh,sizeof(BITMAPFILEHEADER));
if(nCount!
=sizeof(BITMAPFILEHEADER)){
thrownewCException;
}
if(bmfh.bfType!
=0x4d42){
thrownewCException;
}
nSize=bmfh.bfOffBits-sizeof(BITMAPFILEHEADER);
m_DibHead=(LPBITMAPINFOHEADER)newchar[nSize];
m_nBmpallocate=m_nImageallocate=crtallocate;
nCount=pFile->Read(m_DibHead,nSize);
SetPaletteSize(m_DibHead->biBitCount);
GetPalette();
m_Image=(LPBYTE)newchar[m_ImageSize];
nCount=pFile->Read(m_Image,m_ImageSize);
}
catch(CException*tmpc){
AfxMessageBox("文件读取错误");
tmpc->Delete();
returnFALSE;
}
returnTRUE;
}
voidCDipView:
:
Clear()
{
if(m_hFile==NULL)return;
:
:
UnmapViewOfFile(m_lpvFile);
:
:
CloseHandle(m_hMap);
:
:
CloseHandle(m_hFile);
m_hFile=NULL;
if(m_nBmpallocate==crtallocate){
delete[]m_DibHead;
}
elseif(m_nBmpallocate==heapallocate){
:
:
GlobalUnlock(m_hGlob);
:
:
GlobalFree(m_hGlob);
}
if(m_nImageallocate==crtallocate)delete[]m_Image;
if(m_hPalette!
=NULL):
:
DeleteObject(m_hPalette);
if(m_Bmp!
=NULL):
:
DeleteObject(m_Bmp);
m_nBmpallocate=m_nImageallocate=None;
m_hGlob=NULL;
m_DibHead=NULL;
m_Image=NULL;
m_ColorList=NULL;
m_nPalette=0;
m_ImageSize=0;
m_lpvFile=NULL;
m_hMap=NULL;
m_hFile=NULL;
m_Bmp=NULL;
m_hPalette=NULL;
}
voidCDipView:
:
SetPaletteSize(intnBitCount)
{
if(m_DibHead->biSize!
=sizeof(BITMAPINFOHEADER)){
thrownewCException;
}
m_ImageSize=m_DibHead->biSizeImage;
if(m_ImageSize==0){
DWORDdwBytes=((DWORD)m_DibHead->biWidth*
m_DibHead->biBitCount)/32;
if(((DWORD)m_DibHead->biWidth*m_DibHead->biBitCount)%32)
{
dwBytes++;
}
dwBytes*=4;
m_ImageSize=dwBytes*m_DibHead->biHeight;
}
m_ColorList=(LPBYTE)m_DibHead+sizeof(BITMAPINFOHEADER);
if((m_DibHead==NULL)||(m_DibHead->biClrUsed==0)){
switch(nBitCount){
case1:
m_nPalette=2;
break;
case4:
m_nPalette=16;
break;
case8:
m_nPalette=256;
break;
case16:
case24:
case32:
m_nPalette=0;
break;
default:
ASSERT(FALSE);
}
}
else{
m_nPalette=m_DibHead->biClrUsed;
}
ASSERT((m_nPalette>=0)&&(m_nPalette<=256));
}
作业与思考:
分析上述代码,说明每一部分的功能。