|
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 对象联系起来 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 视频函数来显示位图。
|