DIB點陣圖檔案的格式、讀取、儲存和顯示
一、點陣圖檔案結構
點陣圖檔案由三部分組成:檔案頭 + 點陣圖資訊 + 點陣圖畫素資料
1、點陣圖檔案頭。點陣圖檔案頭主要用於識別點陣圖檔案。以下是點陣圖檔案頭結構的定義:
- typedefstruct tagBITMAPFILEHEADER { // bmfh
- WORD bfType;
- DWORD bfSize;
- WORD bfReserved1;
- WORD bfReserved2;
- DWORD bfOffBits;
-
} BITMAPFILEHEADER;
其中的bfType值應該是“BM”(0x4d42),標誌該檔案是點陣圖檔案。bfSize的值是點陣圖檔案的大小。
2、點陣圖資訊中所記錄的值用於分配記憶體,設定調色盤資訊,讀取畫素值等。
以下是點陣圖資訊結構的定義:
- typedefstruct tagBITMAPINFO {
- BITMAPINFOHEADER bmiHeader;
- RGBQUAD bmiColors[1];
- } BITMAPINFO;
可見點陣圖資訊也是由兩部分組成的:點陣圖資訊頭 + 顏色表
2.1點陣圖資訊頭。點陣圖資訊頭包含了單個畫素所用位元組數以及描述顏色的格式,此外還包括點陣圖的寬度、高度、目標裝置的位平面數、影象的壓縮格式。以下是點陣圖資訊頭結構的定義:
- typedefstruct tagBITMAPINFOHEADER{ // bmih
- DWORD biSize;
- LONG biWidth;
- LONG biHeight;
- WORD biPlanes;
- WORD biBitCount
- DWORD biCompression;
- DWORD biSizeImage;
- LONG biXPelsPerMeter;
- LONG biYPelsPerMeter;
-
DWORD
- DWORD biClrImportant;
- } BITMAPINFOHEADER;
下表是對結構體當中各個成員的說明:
結構成員
說 明
biSize 結構BITMAPINFOHEADER的位元組數,即sizeof(BITMAPINFOHEADER)*
biWidth
以畫素為單位的影象寬度*
biHeight
以畫素為單位的影象長度*
biplanes
目標裝置的位平面數
biBitCount
每個畫素的位數*(1)
biCompression
影象的壓縮格式(這個值幾乎總是為0)
biSizeImage
以位元組為單位的影象資料的大小(對BI_RGB壓縮方式而言)
biXPelsPermeter
水平方向上的每米的畫素個數
biYpelsPerMeter
垂直方向上的每米的畫素個數
biClrused
調色盤中實際使用的顏色數(2)
biClrImportant
現實點陣圖時必須的顏色數(3)
說明:*是需要加以注意的部分,因為它們是我們在進行點陣圖操作時經常參考的變數
(1)對於每個畫素的位元組數,分別有一下意義:
0,用在JPEG格式中
1,單色圖,調色盤中含有兩種顏色,也就是我們通常說的黑白圖片
4,16色圖
8,256色圖,通常說的灰度圖
16,64K圖,一般沒有調色盤,影象資料中每兩個位元組表示一個畫素,5個或6個位表示一個RGB分量
24,16M真彩色圖,一般沒有調色盤,影象資料中每3個位元組表示一個畫素,每個位元組表示一個RGB分量
32,4G真彩色,一般沒有調色盤,每4個位元組表示一個畫素,相對24位真彩圖而言,加入了一個透明度,即RGBA模式
(2)這個值通常為0,表示使用biBitCount確定的全部顏色,例外是使用的顏色數目小於制定的顏色深度的顏色數目的最大值。
(3)這個值通常為0,表示所有的顏色都是必需的
2.2顏色表。顏色表一般是針對16位一下的影象而設定的,對於16位和16位以上的影象,由於其點陣圖畫素資料中直接對對應畫素的RGB(A)顏色進行描述,因而省卻了調色盤。而對於16位一下的
影象,由於其點陣圖畫素資料中記錄的只是調色盤索引值,因而需要根據這個索引到調色盤去取得相應的RGB(A)顏色。顏色表的作用就是建立調色盤。
下圖是帶調色盤和不帶調色盤的點陣圖的簡單示意圖
圖1 帶調色盤和不帶調色盤點陣圖之間的區別
顏色表是由顏色表項組成的,顏色表項結構的定義如下:
- typedefstruct tagRGBQUAD { // rgbq
- BYTE rgbBlue;
- BYTE rgbGreen;
- BYTE rgbRed;
- BYTE rgbReserved;
- } RGBQUAD;
其中需要注意的問題是,RGBQUAD結構中的顏色順序是BGR,而不是平常的RGB。
3、點陣圖資料。最後,在點陣圖檔案頭、點陣圖資訊頭、點陣圖顏色表之後,便是點陣圖的主體部分:點陣圖資料。根據不同的點陣圖,點陣圖資料所佔據的位元組數也是不同的,比如,對於8位點陣圖,每個字
節代表了一個畫素,對於16位點陣圖,每兩個位元組代表了一個畫素,對於24位點陣圖,每三個位元組代表了一個畫素,對於32位點陣圖,每四個位元組代表了一個畫素
二、點陣圖檔案的讀取、儲存和顯示
標頭檔案中定義
- private:
- DWORD m_dwDibSize;
- CPalette m_Palette;
- int m_nPaletteEntries;
- RGBQUAD *m_pPalette;
- unsigned char *m_pDib, *m_pDibBits;
- BITMAPINFOHEADER *m_pBIH;
1、讀取點陣圖
- //載入圖片
- void CImageDisposeDlg::OnBtnloadimage()
- {
- // TODO: Add your control notification handler code here
- //檔案路徑名稱
- CString pszFilename;
- //瀏覽檔案對話方塊
- CFileDialog hFileDlg(TRUE,"bmp",
- NULL,
- OFN_FILEMUSTEXIST|OFN_READONLY|OFN_PATHMUSTEXIST|OFN_NOCHANGEDIR,
- TEXT("BMP (*.bmp)|*.bmp|所有檔案(*.*)|*.*|"),
- NULL);
- if(hFileDlg.DoModal() == IDOK)
- {
- //獲得檔案路徑名稱
- pszFilename=hFileDlg.GetPathName();
- }
- //檔案類
- CFile cf;
- //檔案開啟失敗,程式返回
- if( !cf.Open( pszFilename, CFile::modeRead ) )
- {
- return;
- }
- //獲得點陣圖資訊檔案大小
- DWORD dwDibSize;
- dwDibSize = cf.GetLength() - sizeof( BITMAPFILEHEADER );
- //申請一塊記憶體存放點陣圖資訊
- unsigned char *pDib;
- pDib = new unsigned char [dwDibSize];
- if( pDib == NULL )
- {
- return;
- }
- //點陣圖檔案頭
- BITMAPFILEHEADER BFH;
- //從檔案讀取點陣圖檔案頭和點陣圖資料
- try{
- // 判斷讀取點陣圖檔案頭是否成功
- if( cf.Read( &BFH, sizeof( BITMAPFILEHEADER ) )
- != sizeof( BITMAPFILEHEADER ) ||
- // 判斷是否是點陣圖型別
- BFH.bfType != 'MB' ||
- // 判斷讀取點陣圖資料是否成功
- cf.Read( pDib, dwDibSize ) != dwDibSize ){
- //釋放點陣圖資料指標
- delete [] pDib;
- //讀取失敗,程式返回
- return;
- }
- }
- catch( CFileException *e ){
- e->Delete();
- delete [] pDib;
- return;
- }
- //重置全域性點陣圖資訊指標
- if( m_pDib != NULL )
- {
- delete m_pDib;
- }
- //將點陣圖資訊指標和點陣圖資訊大小賦值給全域性變數
- m_pDib = pDib;
- m_dwDibSize = dwDibSize;
- //獲取點陣圖資訊頭指標
- m_pBIH = (BITMAPINFOHEADER *) m_pDib;
- //獲取點陣圖調色盤指標
- m_pPalette =