VC下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 CpalettemmhBitmap - > Attach(hBitmap) / / 将该位图与一个CBitmap 对象联系起来
将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 CpalettemmhBitmap - > 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. 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 视频函数来显示位图。