当前位置:编程文档 >> VC++ >> VC下的BMP文件的显示方法
首页

VC下的BMP文件的显示方法

所属类别:VC++
推荐指数:★★★☆
文档人气:4350
本周人气:19
发布日期:2006-10-20

1  BMP 文件的结构
在进行图像处理程序设计时,常用到Windows 位图文件(即BMP 文件) 。Windows 位图
是映射到显示像素的位阵列,它有两种类型: GDI 位图和DIB。GDI 位图又称DDB ,是设备相
关的,其位的排列取决于显示设备,而DIB 是设备无关的,它具更强的灵活性与完整的图像数
据、压缩方式等定义,既可以存放在于内存也可以以文件形式保存在磁盘上(BMP 文件) 。对
于内存中DIB ,它包含两部分信息: (1) 位图信息(BITMAPINFO) ,包括位图信息头和颜色表;
(2) 位图数据,而对于BMP 文件则还要加上位图文件头。
BITMAPFIL EHEADER 结构中含有文件类型、文件长度和位图数据在文件内的起始位置
等信息,BITMAPINFOHEADER 结构包含位图高度和宽度、位平面数、每像素所占bit 数、颜
色表项数、位图压缩类型等信息,RGBQUAD 结构给出的颜色表是该位图图像使用的调色板,
并非所有BMP 位图都有颜色表,这可由BITMAPINFOHEADER 结构的biBitCount (每像素所
占bit 数) 成员来区别,biBitCount 为1 (黑白二色图) 、4 (16 色图) 、8 (256 色图) 时由颜色表项数
指出颜色表大小,biBitCount 为16 (16 位色图) 、24 (真彩色图) 、32 (32 位色图) 时没有颜色表。
这些信息正是在对位图处理和显示时所需的。
类库使用封装了Windows API 函数的设备相关类CDC 和GDI 对象类CBitmap 来操作位图,
但CBitmap 类必须在应用编译时将BMP 位图装入资源中,在应用运行时由其成员函数及
CDC 类的成员函数操作它。BMP 文件装入资源后被转换为DDB ,类Cbitmap 正是对一系列
DDB 操作的API 函数的封装。但将位图装入资源导致可执行文件增大且只能使用资源中有
限的位图,无法选取其它位图。为此,在图像处理程序设计时就必须直接操作BMP 位图文
件,这可通过VC 的MFC 和Windows API 函数实现:CFile 类的成员函数可打开BMP 文件并
读入内存; CPalette 类成员函数CreatePalette ( ) 创建调色板; Windows API 函数
CreateDIBSection() 创建兼容位图; CDC 类成员函数CreateCompatibleDC ( ) 、SelectObject ( ) 、
Select Palette () 、RealizePalette () 、和BitBlt () 分别是创建兼容设备描述表、将位图选进兼容DC、
选择调色板、及实现调色板及显示位图。
3  BMP 文件的几种显示方法
3. 1  直接写像素
Visual C + + 的CDC 类有一个成员函数Set Pixel ( int x , int y , COLORREF crColor ) 可以
直接在视区坐标(x ,y) 点设置成所要显示的颜色crColor 。只要在OnDraw ( ) 中加入循环写点
颜色代码即可,如:
for (x = 0 x < nWidth x + + )
  for (y = 0 y < nHeight y + + )
     pDC - > Set Pixel (x ,y ,nColor) 
BMP 位图文件可在文档序列化过程中加载到内存并由其头部信息计算出位图宽度
nWidth 和高度nHeight 以及各像素点的颜色值nColor 。这种方法简单,不用涉及复杂的调色
板操作,但显示速度慢且可看出写点过程。
3. 2  从资源中装入位图
在VC 开发环境的资源编辑器里可将要显示的BMP 位图文件加载到资源中,并用资源
ID 来标识它,在应用的视类的成员函数OnDraw(CDC 3 pDC) 中显示,如:
CDC 3 hMemDC = new CDC;
Cbitmap 3 hBitmap = new Cbitmap 
hBitmap = LoadBitmap ( ID-BMPSOURCE)  / / ID-BMPSOURCE 为资源ID
hMemDC - > CreateCompatibleDC(pDC) 
hMemDC - > SelectObject (hBitmap) 
pDC - >BitBlt (0 ,0 ,nWidth ,nHeight ,hMemDC ,0 ,0 ,SRCCOPY) 
由于ID-BMPSOURCE 为资源ID ,BMP 位图文件不能在应用运行时装入。
3. 3  从BMP 文件装入位图
将BMP 文件读入内存,用Windows API 函数CreateDIBSection 创建了一个以兼容DC 为
基础的HBITMAP 句柄,并通过类CGdiObjec 成员函数Attach 与CBitmap 类对象关联起来。
然后将DIB 位图数据拷贝到由函数CreateDIBSection 创建的DIB 位的内存区域。
根据位图所用的颜色数,创建逻辑调色板了。超过256 色的位图是没有颜色表,简单地创
建一个和设备环境兼容的半色调调色板,BMP 文件显示的程序实现是:由Visual C + + 产生名为ShowBmp 的工程,在生成的CShowBmpDoc 类中添加成员:CFile 3 m-pBmp File CBitmap
3 mmhBitmap  CPalette 3 hPalette int nWidth ,nHeight ,nColors 并在其构造函数中初始化mpBmp
Fil、mmhBitmap 及hPalette 为NULL  在VC 的类向导中为该类添加消息响应函数
OnOpendocument.nbsp;在CshowBmpView 类的成员函数OnDraw 中加入显示代码。详细源程序
如下:
BOOL CShowBmpDoc : :OnOpendocument.nbsp(L PCTSTR lpszPathName)
{
if ( ! Cdocument.nbsp: :OnOpendocument.nbsp(lpszPathName) ) return FALSE;
m- pBmpFile = new CFile(lpszPathName , CFile : :modeRead | CFile : :typeBinary) 
if ( ! m- pBmpFile) { AfxMessageBox(”该文件打开错”)  return false }
UINT m- nFileLength = m- pBmpFile - > GetLength () 
BITMAPFIL EHEADER bf 
m- pBmpFile - > Read( &bf ,sizeof (BITMAPFIL EHEADER) ) 
if (bf . bf Type ! = ( (WORD) (’M’< < 8) | ’B’) ) {AfxMessageBox(”不是BMP 文件!”) return false }
UINT nBmp InfoLeng = (UINT) bf . bfOffBits - sizeof (BITMAPFIL EHEADER) 
L PBITMAPINFO lpBitmap = (L PBITMAPINFO) new BYTE[ nBmp InfoLen ] 
m- pBmpFile - > Read( (L PVOID) lpBitmap ,nBmp InfoLen) 
DWORD dwBitlen = bf . bfSize - bf . bfOffBits 
L PVOID lpBits = new BYTE[ dwBitlen ] 
HBITMAP hBitmap = : :CreateDIBSection(NULL , (BITMAPINFO 3 ) lpBitmap , \
DIB - RGB- COLORS , &lpBits ,NULL ,0) 
if ( hBitmap = = NULL ) {AfxMessageBox(”Cannot form a DIBSection”)  return false }
m- pBmpFile - > ReadHuge (lpBits ,dwBitlen) 
mmhBitmap = new Cbitmap hPalette = new Cpalette 
mmhBitmap - > Attach(hBitmap)  / / 将该位图与一个CBitmap 对象联系起来
nColors = lpBitmap - > bmiHeader. biClrUsed ? lpBitmap - > bmiHeader. biClrUsed \
:1 < < lpBitmap - > bmiHeader. biBitCount 
nWidth = lpBitmap - > bmiHeader. biWidth 
nHeight = lpBitmap - > bmiHeader. biHeight 
CDC dc 
if ( nColors > 256 ) / / 颜色数> 256
  hPalette - > CreateHalftonePalette( &dc ) 
else / / 颜色数< = 256
{
  RGBQUAD 3 prgb = new RGBQUAD[ nColors ] 
  CDC memdc 
  memdc. CreateCompatibleDC( &dc) 
  memdc. SelectObject ( &mmhBitmap ) 
  : : GetDIBColorTable( memdc , 0 , nColors , prgb ) 
  UINT nsize = sizeof (LOGPAL ETTE) + (sizeof (PAL ETTEENTRY) 3 nColors) 
  LOGPAL ETTE 3 plp = (LOGPAL ETTE 3 ) new byte[ nsize ] 
 plp - > palVersion = 0x300 
  plp - > palNumEntries = nColors 
  for ( int i = 0  i < nColors i + + )   {
    plp - > palPalEntry[i ] . peRed = prgb[i ] . rgbRed 
    plp - > palPalEntry[i ] . peGreen = prgb[i ] . rgbGreen 
    plp - > palPalEntry[i ] . peBlue = prgb[i ] . rgbBlue 
    plp - > palPalEntry[i ] . peFlags = 0 
  }
  hPalette - > CreatePalette( plp ) 
  delete plp delete prgb 
}
m- pBmpFile - > Close() delete m-pBmpFile m-pBmpFile = NULL 
return TRUE;
}
void CShowBmpView : :OnDraw(CDC 3 pDC)
{
CShowBmpDoc 3 pDoc = Getdocument.nbsp() 
ASSERT-VAL ID(pDoc) 
if ( ! pDoc - > mmhBitmap) return 
CDC memdc 
memdc. CreateCompatibleDC(pDC ) 
memdc. SelectObject ( pDoc - > mmhBitmap ) 
if (pDC - > GetDeviceCaps(RASTERCAPS) & RC- PAL ETTE & & \
pDoc - > hPalette - > m- hObject ! = NULL)
{
pDC - > Select Palette( pDoc - > hPalette , FALSE ) 
pDC - > RealizePalette() 
}
pDC - > BitBlt (0 , 0 , pDoc - > nWidth ,pDoc - > nHeight , &memdc , 0 , 0 ,SRCCOPY) 
}
4  结束语
本文只对未压缩的BMP 位图文件的显示给出Visual C + + 程序实现方法,按这些方法,
对压缩的BMP 文件及其它图像文件如(PCX ,J PG等) ,熟悉它们的文件结构和压缩算法后,同
样可对它们进行处理和显示。例外,Windows API 函数LoadImage () 可直接读取BMP 文件形
成HBITMAP 句柄,在用VC 进行动画程序设计时,为进一步提高显示速度,可用DrawDib 视
频函数来显示位图。

2  Visual C + + 中操作Windows 位图的类库和函数
Visual C + + 可通过MFC 类库或采用Windows API 接口来处理和显示BMP 位图。MFC

文档说明:

     

相关文档


读取评论列表……