📄 chap11_4.htm
字号:
<html>
<head>
<title>11.4 与设备无关的位图(DIB)</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta name="GENERATOR" content="Microsoft FrontPage 3.0">
</head>
<body link="#3973DE" alink="#3973DE">
<font SIZE="5"><b><div align="center"><center>
<table border="0" width="615" cellspacing="0" cellpadding="0">
<tr>
</b><td><div align="center"><center><table border="0" width="615" cellpadding="0" cellspacing="0" height="20">
<tr>
<td width="377" bgcolor="#15397D" height="20"></td>
<td width="238" bgcolor="#000000" height="20"><p align="right"></font><span style="text-decoration: none"><a href="../../index.htm"><font color="#FFFFFF">电脑报Visual
C++网络教程</font></a></span></td>
</tr>
</table>
</center></div><b><font FACE="Times New Roman" SIZE="3"><p ALIGN="CENTER"></font></b><font color="#3973DE" FACE="Times New Roman" size="4">11.4 </font><font color="#3973DE" size="4">与设备无关的位图</font><font color="#3973DE" FACE="Times New Roman" size="4">(DIB)</font><font FACE="Times New Roman" size="4"></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY">DIB(Device-indepentent bitmap)</font><font SIZE="3">的与设备无关性主要体现在以下两个方面:</p>
<ul>
<li><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">DIB</font>的颜色模式与设备无关。例如,一个<font FACE="Times New Roman" SIZE="3">256</font>色的<font FACE="Times New Roman" SIZE="3">DIB</font>即可以在真彩色显示模式下使用,也可以在<font FACE="Times New Roman" SIZE="3">16</font>色模式下使用。</p>
</li>
<li><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">256</font>色以下<font FACE="Times New Roman" SIZE="3">(</font>包括<font FACE="Times New Roman" SIZE="3">256</font>色<font FACE="Times New Roman" SIZE="3">)</font>的<font FACE="Times New Roman" SIZE="3">DIB</font>拥有自己的颜色表,像素的颜色独立于系统调色板。</font></p>
</li>
</ul>
<p><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3">由于</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">不依赖于具体设备,因此可以用来永久性地保存图象。</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">一般是以</font><font FACE="Times New Roman" SIZE="3">*.BMP</font><font SIZE="3">文件的形式保存在磁盘中的,有时也会保存在</font><font FACE="Times New Roman" SIZE="3">*.DIB</font><font SIZE="3">文件中。运行在不同输出设备下的应用程序可以通过</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">来交换图象。</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY">DIB</font><font SIZE="3">还可以用一种</font><font FACE="Times New Roman" SIZE="3">RLE</font><font SIZE="3">算法来压缩图像数据,但一般来说</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">是不压缩的。</font><font FACE="Times New Roman" SIZE="3"></p>
<b><p ALIGN="JUSTIFY"></b></font><font color="#3973DE" FACE="Times New Roman" SIZE="3">11.4.1
DIB</font><font SIZE="3" color="#3973DE">的结构</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3">与</font><font FACE="Times New Roman" SIZE="3">Borland
C++</font><font SIZE="3">下的框架类库</font><font FACE="Times New Roman" SIZE="3">OWL</font><font SIZE="3">不同,</font><font FACE="Times New Roman" SIZE="3">MFC</font><font SIZE="3">未提供现成的类来封装</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">。尽管</font><font FACE="Times New Roman" SIZE="3">Microsoft</font><font SIZE="3">列出了一些理由,但没有</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">类确实给</font><font FACE="Times New Roman" SIZE="3">MFC</font><font SIZE="3">用户带来很多不便。用户要想使用</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">,首先应该了解</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">的结构。</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3">在内存中,一个完整的</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">由两部分组成:一个</font><font FACE="Times New Roman" SIZE="3">BITMAPINFO</font><font SIZE="3">结构和一个存储像素阵列的数组。</font><font FACE="Times New Roman" SIZE="3">BITMAPINFO</font><font SIZE="3">描述了位图的大小,颜色模式和调色板等各种属性,其定义为</p>
<blockquote>
</font><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">typedef struct
tagBITMAPINFO { </p>
<p ALIGN="JUSTIFY">BITMAPINFOHEADER bmiHeader; </p>
<p ALIGN="JUSTIFY">RGBQUAD bmiColors[1]; //</font><font SIZE="3">颜色表</p>
</font><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">} BITMAPINFO;</p>
</blockquote>
<p ALIGN="JUSTIFY">RGBQUAD</font><font SIZE="3">结构用来描述颜色,其定义为</p>
<blockquote>
</font><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">typedef struct tagRGBQUAD
{</p>
<p ALIGN="JUSTIFY">BYTE rgbBlue; //</font><font SIZE="3">蓝色的强度</p>
</font><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">BYTE rgbGreen; //</font><font SIZE="3">绿色的强度</p>
</font><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">BYTE rgbRed; //</font><font SIZE="3">红色的强度</p>
</font><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">BYTE rgbReserved; //</font><font SIZE="3">保留字节,为</font><font FACE="Times New Roman" SIZE="3">0</p>
<p ALIGN="JUSTIFY">} RGBQUAD;</p>
</blockquote>
<p ALIGN="JUSTIFY"></font><font SIZE="3">注意,</font><font FACE="Times New Roman" SIZE="3">RGBQUAD</font><font SIZE="3">结构中的颜色顺序是</font><font FACE="Times New Roman" SIZE="3">BGR</font><font SIZE="3">,而不是平常的</font><font FACE="Times New Roman" SIZE="3">RGB</font><font SIZE="3">。</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY">BITMAPINFOHEADER</font><font SIZE="3">结构包含了</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">的各种信息,其定义为</p>
<blockquote>
</font><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">typedef struct
tagBITMAPINFOHEADER{ </p>
<p ALIGN="JUSTIFY">DWORD biSize; //</font><font SIZE="3">该结构的大小</p>
</font><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">LONG biWidth; //</font><font SIZE="3">位图的宽度</font><font FACE="Times New Roman" SIZE="3">(</font><font SIZE="3">以像素为单位</font><font FACE="Times New Roman" SIZE="3">)</p>
<p ALIGN="JUSTIFY">LONG biHeight; //</font><font SIZE="3">位图的高度</font><font FACE="Times New Roman" SIZE="3">(</font><font SIZE="3">以像素为单位</font><font FACE="Times New Roman" SIZE="3">)</p>
<p ALIGN="JUSTIFY">WORD biPlanes; //</font><font SIZE="3">必须为</font><font FACE="Times New Roman" SIZE="3">1</p>
<p ALIGN="JUSTIFY">WORD biBitCount //</font><font SIZE="3">每个像素的位数</font><font FACE="Times New Roman" SIZE="3">(1</font><font SIZE="3">、</font><font FACE="Times New Roman" SIZE="3">4</font><font SIZE="3">、</font><font FACE="Times New Roman" SIZE="3">8</font><font SIZE="3">、</font><font FACE="Times New Roman" SIZE="3">16</font><font SIZE="3">、</font><font FACE="Times New Roman" SIZE="3">24</font><font SIZE="3">或</font><font FACE="Times New Roman" SIZE="3">32)</p>
<p ALIGN="JUSTIFY">DWORD biCompression; //</font><font SIZE="3">压缩方式,一般为</font><font FACE="Times New Roman" SIZE="3">0</font><font SIZE="3">或</font><font FACE="Times New Roman" SIZE="3">BI_RGB (</font><font SIZE="3">未压缩</font><font FACE="Times New Roman" SIZE="3">)</p>
<p ALIGN="JUSTIFY">DWORD biSizeImage; //</font><font SIZE="3">以字节为单位的图象大小</font><font FACE="Times New Roman" SIZE="3">(</font><font SIZE="3">仅用于压缩位图</font><font FACE="Times New Roman" SIZE="3">)</p>
<p ALIGN="JUSTIFY">LONG biXPelsPerMeter; //</font><font SIZE="3">以目标设备每米的像素数来说明位图的水平分辨率</p>
</font><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">LONG biYPelsPerMeter; //</font><font SIZE="3">以目标设备每米的像素数来说明位图的垂直分辨率</p>
<font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">DWORD biClrUsed; /*</font>颜色表的颜色数,若为<font FACE="Times New Roman" SIZE="3">0</font>则位图使用由<font FACE="Times New Roman" SIZE="3">biBitCount</font>指定的最大颜色数<font FACE="Times New Roman" SIZE="3">*/</p>
<p ALIGN="JUSTIFY">DWORD biClrImportant; //</font>重要颜色的数目,若该值为<font FACE="Times New Roman" SIZE="3">0</font>则所有颜色都重要</p>
<blockquote>
</font><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">} BITMAPINFOHEADER;</p>
</blockquote>
</blockquote>
<p ALIGN="JUSTIFY"></font><font SIZE="3">与</font><font FACE="Times New Roman" SIZE="3">DDB</font><font SIZE="3">不同,</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">的字节数组是从图象的最下面一行开始的逐行向上存储的,也即等于把图象倒过来然后在逐行扫描。另外,字节数组中每个扫描行的字节数必需是</font><font FACE="Times New Roman" SIZE="3">4</font><font SIZE="3">的倍数,如果不足要用</font><font FACE="Times New Roman" SIZE="3">0</font><font SIZE="3">补齐。</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY">DIB</font><font SIZE="3">可以存储在</font><font FACE="Times New Roman" SIZE="3">*.BMP</font><font SIZE="3">或</font><font FACE="Times New Roman" SIZE="3">*.DIB</font><font SIZE="3">文件中。</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">文件是以</font><font FACE="Times New Roman" SIZE="3">BITMAPFILEHEADER</font><font SIZE="3">结构开头的,该结构的定义为</p>
<blockquote>
</font><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">typedef struct
tagBITMAPFILEHEADER { </p>
<p ALIGN="JUSTIFY">WORD bfType; //</font><font SIZE="3">文件类型,必须为“</font><font FACE="Times New Roman" SIZE="3">BM</font><font SIZE="3">”</p>
</font><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">DWORD bfSize; //</font><font SIZE="3">文件的大小</p>
</font><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">WORD bfReserved1; //</font><font SIZE="3">为</font><font FACE="Times New Roman" SIZE="3">0</p>
<p ALIGN="JUSTIFY">WORD bfReserved2; //</font><font SIZE="3">为</font><font FACE="Times New Roman" SIZE="3">0</p>
<p ALIGN="JUSTIFY">DWORD bfOffBits; //</font><font SIZE="3">存储的像素阵列相对于文件头的偏移量</p>
</font><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">} BITMAPFILEHEADER;</p>
</blockquote>
<p ALIGN="JUSTIFY"></font><font SIZE="3">紧随该结构的是一个</font><font FACE="Times New Roman" SIZE="3">BITMAPINFOHEADER</font><font SIZE="3">结构,然后是</font><font FACE="Times New Roman" SIZE="3">RGBQUAD</font><font SIZE="3">结构组成的颜色表</font><font FACE="Times New Roman" SIZE="3">(</font><font SIZE="3">如果有的话</font><font FACE="Times New Roman" SIZE="3">)</font><font SIZE="3">,文件最后存储的是</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">的像素阵列。</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY">DIB</font><font SIZE="3">的颜色信息储存在自己的颜色表中,程序一般要根据颜色表为</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">创建逻辑调色板。在输出一幅</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">之前,程序应该将其逻辑调色板选入到相关的设备上下文中并实现到系统调色板中,然后再调用相关的</font><font FACE="Times New Roman" SIZE="3">GDI</font><font SIZE="3">函数</font><font FACE="Times New Roman" SIZE="3">(</font><font SIZE="3">如</font><font FACE="Times New Roman" SIZE="3">::SetDIBitsToDevice</font><font SIZE="3">或</font><font FACE="Times New Roman" SIZE="3">::StretchDIBits)</font><font SIZE="3">输出</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">。在输出过程中,</font><font FACE="Times New Roman" SIZE="3">GDI</font><font SIZE="3">函数会把</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">转换成</font><font FACE="Times New Roman" SIZE="3">DDB</font><font SIZE="3">,这项工作主要包括以下两步:</p>
<blockquote>
<blockquote>
<p ALIGN="JUSTIFY">将</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">的颜色格式转换成与输出设备相同的颜色格式。例如,在真彩色的显示模式下要显示一个</font><font FACE="Times New Roman" SIZE="3">256</font><font SIZE="3">色的</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">,则应该将其转换成</font><font FACE="Times New Roman" SIZE="3">24</font><font SIZE="3">位的颜色格式。</p>
<p ALIGN="JUSTIFY">将</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">像素的逻辑颜色索引转换成系统调色板索引。</p>
</font><font FACE="Times New Roman" SIZE="3">
</blockquote>
</blockquote>
<p></font><b><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font></b><font color="#3973DE" FACE="Times New Roman" SIZE="3">11.4.2
</font><font color="#3973DE"><font SIZE="3">编写</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">类</font></font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3">由于</font><font FACE="Times New Roman" SIZE="3">MFC</font><font SIZE="3">未提供</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">类,用户在使用</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">时将面临繁重的</font><font FACE="Times New Roman" SIZE="3">Windows API</font><font SIZE="3">编程任务。幸运的是,</font><font FACE="Times New Roman" SIZE="3">Visual
C++</font><font SIZE="3">提供了一个较高层次的</font><font FACE="Times New Roman" SIZE="3">API</font><font SIZE="3">,简化了</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">的使用。这些</font><font FACE="Times New Roman" SIZE="3">API</font><font SIZE="3">函数实际上是由</font><font FACE="Times New Roman" SIZE="3">MFC</font><font SIZE="3">的</font><font FACE="Times New Roman" SIZE="3">DibLook</font><font SIZE="3">例程提供的,它们位于</font><font FACE="Times New Roman" SIZE="3">DibLook</font><font SIZE="3">目录下的</font><font FACE="Times New Roman" SIZE="3">dibapi.cpp</font><font SIZE="3">、</font><font FACE="Times New Roman" SIZE="3">myfile.cpp</font><font SIZE="3">和</font><font FACE="Times New Roman" SIZE="3">dibapi.h</font><font SIZE="3">文件中,主要包括:</p>
<blockquote>
<blockquote>
</font><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">ReadDIBFile //</font><font SIZE="3">把</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">文件读入内存</p>
</font><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">SaveDIB //</font><font SIZE="3">把</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">保存到文件中</p>
</font><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">CreateDIBPalette //</font><font SIZE="3">从</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">中创建一个逻辑调色板</p>
</font><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">PaintDIB //</font><font SIZE="3">显示</font><font FACE="Times New Roman" SIZE="3">DIB</p>
<p ALIGN="JUSTIFY">DIBWidth //</font><font SIZE="3">返回</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">的宽度</p>
</font><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">DIBHeight //</font><font SIZE="3">返回</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">的高度</font></p>
</blockquote>
</blockquote>
<p><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3">如果读者对这些函数的内部细节感兴趣,那么可以研究一下</font><font FACE="Times New Roman" SIZE="3">dibapi.cpp</font><font SIZE="3">和</font><font FACE="Times New Roman" SIZE="3">myfile.cpp</font><font SIZE="3">文件,但要做好吃苦的准备。</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3">即使利用上述</font><font FACE="Times New Roman" SIZE="3">API</font><font SIZE="3">,编写使用</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">的程序仍然不是很轻松。为了满足读者的要求,笔者编写了一个名为</font><font FACE="Times New Roman" SIZE="3">CDib</font><font SIZE="3">的较简单的</font><font FACE="Times New Roman" SIZE="3">DIB</font><font SIZE="3">类,该类是基于上述</font><font FACE="Times New Roman" SIZE="3">API</font><font SIZE="3">的,它的主要成员函数包括:</p>
<blockquote>
<blockquote>
</font><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">BOOL Load(LPCTSTR
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -