📄 csdn_文档中心_bmp位图文件结构及vc操作.htm
字号:
<TR>
<TD align=middle height=10></TD>
<TD height=10></TD></TR></TBODY></TABLE><!--文章说明信息结束//-->
<TABLE border=0 width=600>
<TBODY>
<TR>
<TD align=left><BR>
<DIV align=center><FONT size=2><B><FONT
size=3></FONT></B></FONT> </DIV>
<DIV align=right> </DIV><BR>
<DIV><!--jcstart-->浙江工业大学 朱永辉<BR><BR>----
用普通方法显示BMP位图,占内存大,速度慢,在图形缩小时,失真严重,在低颜色位数的设备上显示高颜色位数的图形图形时失真大。本文采用视频函数显示BMP位图,可以消除以上的缺点。
<BR><BR>---- 一、BMP文件结构 <BR><BR>---- 1. BMP文件组成 <BR><BR>----
BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。 <BR><BR>---- 2. BMP文件头 <BR><BR>----
BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息。 <BR><BR>---- 其结构定义如下:
<BR><BR>typedef struct tagBITMAPFILEHEADER<BR>{<BR>WORDbfType; //
位图文件的类型,必须为BM<BR>DWORD bfSize; // 位图文件的大小,以字节为单位<BR>WORDbfReserved1;
// 位图文件保留字,必须为0<BR>WORDbfReserved2; // 位图文件保留字,必须为0<BR>DWORD
bfOffBits; // 位图数据的起始位置,以相对于位图<BR>// 文件头的偏移量表示,以字节为单位<BR>}
BITMAPFILEHEADER;<BR><BR>---- 3. 位图信息头
<BR><BR>BMP位图信息头数据用于说明位图的尺寸等信息。<BR>typedef struct
tagBITMAPINFOHEADER{<BR>DWORD biSize; // 本结构所占用字节数<BR>LONGbiWidth;
// 位图的宽度,以像素为单位<BR>LONGbiHeight; // 位图的高度,以像素为单位<BR>WORD biPlanes;
// 目标设备的级别,必须为1<BR>WORD biBitCount// 每个像素所需的位数,必须是1(双色),<BR>//
4(16色),8(256色)或24(真彩色)之一<BR>DWORD biCompression; // 位图压缩类型,必须是
0(不压缩),<BR>// 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一<BR>DWORD biSizeImage;
// 位图的大小,以字节为单位<BR>LONGbiXPelsPerMeter; //
位图水平分辨率,每米像素数<BR>LONGbiYPelsPerMeter; // 位图垂直分辨率,每米像素数<BR>DWORD
biClrUsed;// 位图实际使用的颜色表中的颜色数<BR>DWORD biClrImportant;//
位图显示过程中重要的颜色数<BR>} BITMAPINFOHEADER;<BR><BR>---- 4. 颜色表 <BR><BR>----
颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下:
<BR><BR>typedef struct tagRGBQUAD {<BR>BYTErgbBlue;//
蓝色的亮度(值范围为0-255)<BR>BYTErgbGreen; // 绿色的亮度(值范围为0-255)<BR>BYTErgbRed;
// 红色的亮度(值范围为0-255)<BR>BYTErgbReserved;// 保留,必须为0<BR>}
RGBQUAD;<BR>颜色表中RGBQUAD结构数据的个数有biBitCount来确定:<BR>当biBitCount=1,4,8时,分别有2,16,256个表项;<BR>当biBitCount=24时,没有颜色表项。<BR>位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下:<BR>typedef
struct tagBITMAPINFO {<BR>BITMAPINFOHEADER bmiHeader; //
位图信息头<BR>RGBQUAD bmiColors[1]; // 颜色表<BR>} BITMAPINFO;<BR><BR>----
5. 位图数据 <BR><BR>----
位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。位图的一个像素值所占的字节数:
<BR><BR>当biBitCount=1时,8个像素占1个字节;<BR>当biBitCount=4时,2个像素占1个字节;<BR>当biBitCount=8时,1个像素占1个字节;<BR>当biBitCount=24时,1个像素占3个字节;<BR><BR>Windows规定一个扫描行所占的字节数必须是
4的倍数(即以long为单位),不足的以0填充, <BR><BR>一个扫描行所占的字节数计算方法: DataSizePerLine=
(biWidth* biBitCount+31)/8; <BR><BR>// 一个扫描行所占的字节数 DataSizePerLine=
DataSizePerLine/4*4; // 字节数必须是4的倍数 <BR><BR>位图数据的大小(不压缩情况下):
DataSize= DataSizePerLine* biHeight; <BR><BR>---- 二、BMP位图一般显示方法
<BR><BR>---- 1. 申请内存空间用于存放位图文件 <BR><BR>----
GlobalAlloc(GHND,FileLength); <BR><BR>---- 2. 位图文件读入所申请内存空间中
<BR><BR>---- LoadFileToMemory( mpBitsSrc,mFileName); <BR><BR>---- 3.
在OnPaint等函数中用创建显示用位图 <BR><BR>----
用CreateDIBitmap()创建显示用位图,用CreateCompatibleDC()创建兼容DC, <BR><BR>----
用SelectBitmap()选择显示位图。 <BR><BR>---- 4. 用BitBlt或StretchBlt等函数显示位图
<BR><BR>---- 5. 用DeleteObject()删除所创建的位图 <BR><BR>---- 以上方法的缺点是:
1)显示速度慢; 2) 内存占用大; 3) 位图在缩小显示时图形失真大,(可通过安装字体平滑软件来解决); 4)
在低颜色位数的设备上(如256显示模式)显示高颜色位数的图形(如真彩色)图形失真严重。 <BR><BR>---- 三、BMP位图缩放显示
<BR><BR>---- 用DrawDib视频函数来显示位图,内存占用少,速度快,而且还可以对图形进行淡化(Dithering
)处理。淡化处理是一种图形算法,可以用来在一个支持比图像所用颜色要少的设备上显示彩色图像。BMP位图显示方法如下:
<BR><BR>---- 1. 打开视频函数DrawDibOpen(),一般放在在构造函数中 <BR><BR>---- 2.
申请内存空间用于存放位图文件 <BR><BR>---- GlobalAlloc(GHND,FileLength);
<BR><BR>---- 3. 位图文件读入所申请内存空间中 <BR><BR>---- LoadFileToMemory(
mpBitsSrc,mFileName); <BR><BR>---- 4.
在OnPaint等函数中用DrawDibRealize(),DrawDibDraw()显示位图 <BR><BR>---- 5.
关闭视频函数DrawDibClose(),一般放在在析构函数中 <BR><BR>---- 以上方法的优点是: 1)显示速度快; 2)
内存占用少; 3) 缩放显示时图形失真小,4) 在低颜色位数的设备上显示高颜色位数的图形图形时失真小; 5)
通过直接处理位图数据,可以制作简单动画。 <BR><BR>---- 四、CViewBimap类编程要点 <BR><BR>---- 1.
在CViewBimap类中添加视频函数等成员 <BR><BR>HDRAWDIB m_hDrawDib; //
视频函数<BR>HANDLEmhBitsSrc; // 位图文件句柄(内存)<BR>LPSTR mpBitsSrc; //
位图文件地址(内存)<BR>BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头<BR><BR>----
2. 在CViewBimap类构造函数中添加打开视频函数 <BR><BR>---- m_hDrawDib= DrawDibOpen();
<BR><BR>---- 3. 在CViewBimap类析构函数中添加关闭视频函数 <BR><BR>if( m_hDrawDib !=
NULL)<BR>{<BR>DrawDibClose( m_hDrawDib);<BR>m_hDrawDib =
NULL;<BR>}<BR>---- 4. 在CViewBimap类图形显示函数OnPaint中添加GraphicDraw()
<BR>voidCViewBitmap::OnPaint()<BR>{<BR>CPaintDC dc(this); // device
context for painting<BR>GraphicDraw(
);<BR>}<BR><BR>voidCViewBitmap::GraphicDraw( void
)<BR>{<BR>CClientDC dc(this); // device context for
painting<BR>BITMAPFILEHEADER *pBitmapFileHeader;<BR>ULONG bfoffBits=
0;<BR>CPoint Wid;<BR><BR>// 图形文件名有效 (=0 BMP)<BR>if( mBitmapFileType
< ID_BITMAP_BMP ) return;<BR><BR>// 图形文件名有效 (=0 BMP)<BR>//
准备显示真彩位图<BR>pBitmapFileHeader= (BITMAPFILEHEADER *)
mpBitsSrc;<BR>bfoffBits= pBitmapFileHeader->bfOffBits;<BR><BR>//
使用普通函数显示位图<BR><BR>if( m_hDrawDib == NULL || mDispMethod ==
0)<BR>{<BR>HBITMAP
hBitmap=::CreateDIBitmap(dc.m_hDC,<BR>mpBitmapInfo, CBM_INIT,
mpBitsSrc+bfoffBits,<BR>(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);
<BR>// 建立位图<BR>HDC hMemDC=::CreateCompatibleDC(dc.m_hDC);//
建立内存<BR>HBITMAP hBitmapOld= SelectBitmap(hMemDC, hBitmap); //
选择对象<BR>// 成员CRect mDispR用于指示图形显示区域的大小.<BR>// 成员CPoint
mPos用于指示图形显示起始位置坐标.<BR>if( mPos.x > (mpBitmapInfo- >biWidth -
mDispR.Width() ))<BR>mPos.x= mpBitmapInfo->biWidth -
mDispR.Width() ;<BR>if( mPos.y > (mpBitmapInfo- >biHeight-
mDispR.Height()))<BR>mPos.y= mpBitmapInfo- >biHeight-
mDispR.Height();<BR>if( mPos.x < 0 ) mPos.x= 0;<BR>if( mPos.y
< 0 ) mPos.y= 0;<BR><BR>if( mFullViewTog == 0)<BR>{<BR>//
显示真彩位图<BR>::BitBlt(dc.m_hDC,0,0, mDispR.Width(), mDispR.Height(),
<BR>hMemDC,mPos.x,mPos.y, SRCCOPY);<BR>} else
{<BR>::StretchBlt(dc.m_hDC,0,0, mDispR.Width(),
mDispR.Height(),<BR>hMemDC,0,0, mpBitmapInfo- >biWidth,
mpBitmapInfo- <BR>>biHeight, SRCCOPY);<BR>}<BR>//
结束显示真彩位图<BR>::DeleteObject(SelectObject(hMemDC,hBitmapOld)); <BR>//
删 除 位 图<BR>} else {<BR><BR>// 使用视频函数显示位图<BR><BR>if( mPos.x >
(mpBitmapInfo- >biWidth - mDispR.Width() ))<BR>mPos.x=
mpBitmapInfo- >biWidth - mDispR.Width() ;<BR>if( mPos.y >
(mpBitmapInfo- >biHeight- mDispR.Height()))<BR>mPos.y=
mpBitmapInfo- >biHeight- mDispR.Height();<BR>if( mPos.x < 0 )
mPos.x= 0;<BR>if( mPos.y < 0 ) mPos.y= 0;<BR><BR>//
显示真彩位图<BR>DrawDibRealize( m_hDrawDib, dc.GetSafeHdc(),
TRUE);<BR><BR>if( mFullViewTog == 0)<BR>{<BR>Wid.x=
mDispR.Width();<BR>Wid.y= mDispR.Height();<BR>// 1:1 显示时,
不能大于图形大小<BR>if( Wid.x > mpBitmapInfo- >biWidth ) <BR>Wid.x =
mpBitmapInfo- >biWidth;<BR>if( Wid.y > mpBitmapInfo-
>biHeight) <BR>Wid.y = mpBitmapInfo-
>biHeight;<BR><BR>DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()<BR>,
0, 0, Wid.x, Wid.y,<BR>mpBitmapInfo, (LPVOID)
(mpBitsSrc+bfoffBits),<BR>mPos.x, mPos.y, Wid.x, Wid.y,
DDF_BACKGROUNDPAL);<BR>} else {<BR>DrawDibDraw( m_hDrawDib,
dc.GetSafeHdc(),<BR>0, 0, mDispR.Width(),
mDispR.Height(),<BR>mpBitmapInfo, (LPVOID)
(mpBitsSrc+bfoffBits),<BR>0, 0, mpBitmapInfo- >biWidth,
mpBitmapInfo-
>biHeight,<BR>DDF_BACKGROUNDPAL);<BR>}<BR>}<BR>return;<BR>}<BR><BR>----
五、使用CViewBimap类显示BMP位图 <BR><BR>---- 1. 在Visual
C++5.0中新建一个名称为mymap工程文件,类型为MFC
AppWizard[exe]。在编译运行通过后,在WorkSpace(如被关闭,用Alt_0打开)点击ResourceView,点击Menu左侧的+符号展开Menu
条目,双击IDR_MAINFRAME条目,进入菜单资源编辑,在'“查看(V)”下拉式菜单(英文版为View下拉式菜单)的尾部添加“ViewBitmap”条目,其ID为ID_VIEW_BITMAP。
<BR><BR>---- 2. 在Visual C++5.0中点击下拉式菜单Project- >Add To project-
>Files...,将Bitmap0.h 和Bitmap0.cpp添加到工程文件中。 <BR><BR>---- 3.
在Visual C++5.0中按Ctrl_W进入MFC ClassWizard,选择类名称为CMainFrame,ObjectIDs:
ID_VIEW_BITMAP,Messages选择Command,然后点击Add
Fucction按钮,然后输入函数名为OnViewBima p。在添加OnViewBimap后,在Member functions:
中点击OnViewBimap条目,点击Edit Code按钮编辑程序代码。代码如下: <BR><BR>void
CMainFrame::OnViewBitmap()<BR>{<BR>// TODO: Add your command handler
code here<BR>CViewBitmap *pViewBitmap= NULL;<BR><BR>pViewBitmap= new
CViewBitmap( "BITMAP.BMP", this);<BR>pViewBitmap- >ShowWindow(
TRUE);<BR>}<BR><BR>---- 并在该程序的头部添加#include "bitmap0.h",然后编译运行。
<BR><BR>---- 4. 找一个大一点的真彩色的BMP位图,将它拷贝到BITMAP.BMP中。 <BR><BR>---- 5.
运行时,点击下拉式菜单“查看(V)- >ViewBitmap”(英文版为View- >
ViewBitmap)即可显示BITMAP.BMP位图。 <BR><BR>---- 六、CViewBimap类功能说明
<BR><BR>---- 1.
在客户区中带有水平和垂直滚动条。在位图大小大于显示客户区时,可以使用滚动条;在位图大小小于显示客户区或全屏显示时,滚动条无效。
<BR><BR>---- 2.
在客户区中底部带有状态条。状态条中的第一格为位图信息,第二格为位图显示方法,可以是使用普通函数或使用视频函数。在第二格区域内点击鼠标,可在两者之间接换。第三格为位图显示比例,可以是1;1显示或全屏显示。在第三格区域内点击鼠标,可在两者之间接换。在全屏显示时,如果位图比客户区小,则对位图放大;
如果位图比客户区大,则对位图缩小。 <BR><BR>---- 3.
支持文件拖放功能。可以从资源管理器中拖动一个位图文件到客户区,就可以显示该位图。 <BR><BR>----
程序调试通过后,可以找一个较大的真彩色位图或调整客户区比位图小,在全屏显示方式下,比较使用普通函数与使用视频函数的差别。可以看出,位图放大时两者差别不大,但在位图缩小时,两者差别明显;
使用视频函数时位图失真小,显示速度快。 <BR><BR>----
还可以从控制面板中将屏幕显示方式从真彩色显示模式切换到256色显示模式,再比较使用普通函数与使用视频函数显示同一个真彩色位图的差别。现在可以体会到使用视频函数的优越性了吧。
<BR><BR>---- 在全屏显示时,位图的xy方向比例不相同,如要保持相同比例,可在显示程序中加以适当调整即可,读者可自行完成。
<BR><BR>朱永辉 zyonghui@21cn.com
<BR><!--jcend--></DIV><BR></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR>
<TABLE align=center bgColor=#006699 border=0 cellPadding=0 cellSpacing=0
width=770>
<TBODY>
<TR bgColor=#006699>
<TD align=middle bgColor=#006699 id=white><FONT
color=#ffffff>对该文的评论</FONT></TD>
<TD align=middle>
<SCRIPT src="CSDN_文档中心_BMP位图文件结构及VC操作.files/readnum.htm"></SCRIPT>
</TD></TR></TBODY></TABLE><BR>
<DIV align=center>
<TABLE align=center bgColor=#cccccc border=0 cellPadding=2 cellSpacing=1
width=770>
<TBODY>
<TR>
<TH bgColor=#006699 id=white><FONT
color=#ffffff>我要评论</FONT></TH></TR></TBODY></TABLE></DIV>
<DIV align=center>
<TABLE border=0 width=770>
<TBODY>
<TR>
<TD>你没有登陆,无法发表评论。 请先<A
href="http://www.csdn.net/member/login.asp?from=/Develop/read_article.asp?id=2103">登陆</A>
<A
href="http://www.csdn.net/expert/zc.asp">我要注册</A><BR></TD></TR></TBODY></TABLE></DIV><BR>
<HR noShade SIZE=1 width=770>
<TABLE border=0 cellPadding=0 cellSpacing=0 width=500>
<TBODY>
<TR align=middle>
<TD height=10 vAlign=bottom><A
href="http://www.csdn.net/intro/intro.asp?id=2">网站简介</A> - <A
href="http://www.csdn.net/intro/intro.asp?id=5">广告服务</A> - <A
href="http://www.csdn.net/map/map.shtm">网站地图</A> - <A
href="http://www.csdn.net/help/help.asp">帮助信息</A> - <A
href="http://www.csdn.net/intro/intro.asp?id=2">联系方式</A> - <A
href="http://www.csdn.net/english">English</A> </TD>
<TD align=middle rowSpan=3><A
href="http://www.hd315.gov.cn/beian/view.asp?bianhao=010202001032100010"><IMG
border=0 height=48 src="CSDN_文档中心_BMP位图文件结构及VC操作.files/biaoshi.gif"
width=40></A></TD></TR>
<TR align=middle>
<TD vAlign=top>百联美达美公司 版权所有 京ICP证020026号</TD></TR>
<TR align=middle>
<TD vAlign=top><FONT face=Verdana>Copyright © CSDN.net, Inc. All rights
reserved</FONT></TD></TR>
<TR>
<TD height=15></TD>
<TD></TD></TR></TBODY></TABLE></DIV>
<DIV></DIV><!--内容结束//--><!--结束//--></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -