用普通方法顯示BMP位圖,占記憶體大,速度慢,在圖形縮小時,失真嚴重,在低顔色位數的裝置上顯示高顔色位數的圖形圖形時失真大。本文采用視訊函數顯示BMP位圖,可以消除以上的缺點。
一、BMP檔案結構
1. BMP檔案組成
BMP檔案由檔案頭、位圖資訊頭、顔色資訊和圖形資料四部分組成。
2. BMP檔案頭
BMP檔案頭資料結構含有BMP檔案的類型、檔案大小和位圖起始位置等資訊。
其結構定義如下:
typedef struct tagBITMAPFILEHEADER
{
WORDbfType; // 位圖檔案的類型,必須為BM
DWORD bfSize; // 位圖檔案的大小,以位元組為機關
WORDbfReserved1; // 位圖檔案保留字,必須為0
WORDbfReserved2; // 位圖檔案保留字,必須為0
DWORD bfOffBits; // 位圖資料的起始位置,以相對于位圖
// 檔案頭的偏移量表示,以位元組為機關
} BITMAPFILEHEADER;
3. 位圖資訊頭
BMP位圖資訊頭資料用于說明位圖的尺寸等資訊。
typedef struct tagBITMAPINFOHEADER{
DWORD biSize; // 本結構所占用位元組數
LONGbiWidth; // 位圖的寬度,以像素為機關
LONGbiHeight; // 位圖的高度,以像素為機關
WORD biPlanes; // 目标裝置的級别,必須為1
WORD biBitCount// 每個像素所需的位數,必須是1(雙色),
// 4(16色),8(256色)或24(真彩色)之一
DWORD biCompression; // 位圖壓縮類型,必須是 0(不壓縮),
// 1(BI_RLE8壓縮類型)或2(BI_RLE4壓縮類型)之一
DWORD biSizeImage; // 位圖的大小,以位元組為機關
LONGbiXPelsPerMeter; // 位圖水準分辨率,每米像素數
LONGbiYPelsPerMeter; // 位圖垂直分辨率,每米像素數
DWORD biClrUsed;// 位圖實際使用的顔色表中的顔色數
DWORD biClrImportant;// 位圖顯示過程中重要的顔色數
} BITMAPINFOHEADER;
4. 顔色表
顔色表用于說明位圖中的顔色,它有若幹個表項,每一個表項是一個RGBQUAD類型的結構,定義一種顔色。RGBQUAD結構的定義如下:
typedef struct tagRGBQUAD {
BYTErgbBlue;// 藍色的亮度(值範圍為0-255)
BYTErgbGreen; // 綠色的亮度(值範圍為0-255)
BYTErgbRed; // 紅色的亮度(值範圍為0-255)
BYTErgbReserved;// 保留,必須為0
} RGBQUAD;
顔色表中RGBQUAD結構資料的個數有biBitCount來确定:
當biBitCount=1,4,8時,分别有2,16,256個表項;
當biBitCount=24時,沒有顔色表項。
位圖資訊頭和顔色表組成位圖資訊,BITMAPINFO結構定義如下:
typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader; // 位圖資訊頭
RGBQUAD bmiColors[1]; // 顔色表
} BITMAPINFO;
5. 位圖資料
位圖資料記錄了位圖的每一個像素值,記錄順序是在掃描行内是從左到右,掃描行之間是從下到上。位圖的一個像素值所占的位元組數:
當biBitCount=1時,8個像素占1個位元組;
當biBitCount=4時,2個像素占1個位元組;
當biBitCount=8時,1個像素占1個位元組;
當biBitCount=24時,1個像素占3個位元組;
Windows規定一個掃描行所占的位元組數必須是4的倍數(即以long為機關),寫入位圖檔案中時也要求這樣,不足的以0填充,一個掃描行所占的位元組數計算方法:
DataSizePerline= (biWidth* biBitCount+31)/8;
// 一個掃描行所占的位元組數
DataSizePerLine= DataSizePerLine/4*4; // 位元組數必須是4的倍數
位圖資料的大小(不壓縮情況下):
DataSize= DataSizePerLine* biHeight;
二、BMP位圖一般顯示方法
1. 申請記憶體空間用于存放位圖檔案
GlobalAlloc(GHND,FileLength);
2. 位圖檔案讀入所申請記憶體空間中
LoadFileToMemory( mPBitsSrc,mFileName);
3. 在OnPaint等函數中用建立顯示用位圖
用CreateDIBitmap()建立顯示用位圖,用CreateCompatibleDC()建立相容DC,
用SelectBitmap()選擇顯示位圖。
4. 用BitBlt或StretchBlt等函數顯示位圖
5. 用DeleteObject()删除所建立的位圖
以上方法的缺點是: 1)顯示速度慢; 2) 記憶體占用大; 3) 位圖在縮小顯示時圖形失真大,(可通過安裝字型平滑軟體來解決); 4) 在低顔色位數的裝置上(如256顯示模式)顯示高顔色位數的圖形(如真彩色)圖形失真嚴重。