1. 程式人生 > >DIB點陣圖檔案的格式、讀取、儲存和顯示

DIB點陣圖檔案的格式、讀取、儲存和顯示

一、點陣圖檔案結構

點陣圖檔案由三部分組成:檔案頭 + 點陣圖資訊 + 點陣圖畫素資料

1、點陣圖檔案頭。點陣圖檔案頭主要用於識別點陣圖檔案。以下是點陣圖檔案頭結構的定義:

  1. typedefstruct tagBITMAPFILEHEADER { // bmfh 
  2.     WORD    bfType;   
  3.     DWORD   bfSize;   
  4.     WORD    bfReserved1;   
  5.     WORD    bfReserved2;   
  6.     DWORD   bfOffBits;   
  7. } BITMAPFILEHEADER;  

其中的bfType值應該是“BM”(0x4d42),標誌該檔案是點陣圖檔案。bfSize的值是點陣圖檔案的大小。

2、點陣圖資訊中所記錄的值用於分配記憶體,設定調色盤資訊,讀取畫素值等。
以下是點陣圖資訊結構的定義:

  1. typedefstruct tagBITMAPINFO {  
  2.     BITMAPINFOHEADER    bmiHeader;  
  3.     RGBQUAD             bmiColors[1];  
  4. } BITMAPINFO;  

可見點陣圖資訊也是由兩部分組成的:點陣圖資訊頭 + 顏色表

2.1點陣圖資訊頭。點陣圖資訊頭包含了單個畫素所用位元組數以及描述顏色的格式,此外還包括點陣圖的寬度、高度、目標裝置的位平面數、影象的壓縮格式。以下是點陣圖資訊頭結構的定義:

  1. typedefstruct tagBITMAPINFOHEADER{ // bmih 
  2.     DWORD  biSize;   
  3.     LONG   biWidth;   
  4.     LONG   biHeight;   
  5.     WORD   biPlanes;   
  6.     WORD   biBitCount   
  7.     DWORD  biCompression;   
  8.     DWORD  biSizeImage;   
  9.     LONG   biXPelsPerMeter;   
  10.     LONG   biYPelsPerMeter;   
  11.     DWORD
      biClrUsed;   
  12.     DWORD  biClrImportant;   
  13. } 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 帶調色盤和不帶調色盤點陣圖之間的區別

顏色表是由顏色表項組成的,顏色表項結構的定義如下:

  1. typedefstruct tagRGBQUAD { // rgbq 
  2.     BYTE    rgbBlue;   
  3.     BYTE    rgbGreen;   
  4.     BYTE    rgbRed;   
  5.     BYTE    rgbReserved;   
  6. } RGBQUAD;  

其中需要注意的問題是,RGBQUAD結構中的顏色順序是BGR,而不是平常的RGB。

3、點陣圖資料。最後,在點陣圖檔案頭、點陣圖資訊頭、點陣圖顏色表之後,便是點陣圖的主體部分:點陣圖資料。根據不同的點陣圖,點陣圖資料所佔據的位元組數也是不同的,比如,對於8位點陣圖,每個字

節代表了一個畫素,對於16位點陣圖,每兩個位元組代表了一個畫素,對於24位點陣圖,每三個位元組代表了一個畫素,對於32位點陣圖,每四個位元組代表了一個畫素

二、點陣圖檔案的讀取、儲存和顯示

標頭檔案中定義

  1. private:  
  2.  DWORD m_dwDibSize;  
  3.  CPalette m_Palette;  
  4.  int m_nPaletteEntries;  
  5.  RGBQUAD *m_pPalette;  
  6.  unsigned char *m_pDib, *m_pDibBits;  
  7.  BITMAPINFOHEADER *m_pBIH;  
  

1、讀取點陣圖

  1. //載入圖片
  2. void CImageDisposeDlg::OnBtnloadimage()   
  3. {  
  4.  // TODO: Add your control notification handler code here
  5.  //檔案路徑名稱
  6.  CString pszFilename;  
  7.  //瀏覽檔案對話方塊
  8.  CFileDialog hFileDlg(TRUE,"bmp",  
  9.     NULL,  
  10.     OFN_FILEMUSTEXIST|OFN_READONLY|OFN_PATHMUSTEXIST|OFN_NOCHANGEDIR,  
  11.     TEXT("BMP (*.bmp)|*.bmp|所有檔案(*.*)|*.*|"),  
  12.     NULL);  
  13.  if(hFileDlg.DoModal() == IDOK)  
  14.  {  
  15.     //獲得檔案路徑名稱
  16.     pszFilename=hFileDlg.GetPathName();   
  17.  }  
  18.  //檔案類
  19.  CFile cf;  
  20.  //檔案開啟失敗,程式返回
  21.  if( !cf.Open( pszFilename, CFile::modeRead ) )  
  22.  {  
  23.   return;  
  24.  }  
  25.  //獲得點陣圖資訊檔案大小
  26.  DWORD dwDibSize;  
  27.  dwDibSize = cf.GetLength() - sizeof( BITMAPFILEHEADER );  
  28.  //申請一塊記憶體存放點陣圖資訊
  29.  unsigned char *pDib;  
  30.  pDib = new unsigned char [dwDibSize];  
  31.  if( pDib == NULL )  
  32.  {  
  33.   return;  
  34.  }  
  35.  //點陣圖檔案頭
  36.  BITMAPFILEHEADER BFH;  
  37.  //從檔案讀取點陣圖檔案頭和點陣圖資料
  38.  try{  
  39.   // 判斷讀取點陣圖檔案頭是否成功
  40.   if( cf.Read( &BFH, sizeof( BITMAPFILEHEADER ) )  
  41.    != sizeof( BITMAPFILEHEADER ) ||  
  42.    // 判斷是否是點陣圖型別
  43.    BFH.bfType != 'MB' ||  
  44.    // 判斷讀取點陣圖資料是否成功
  45.    cf.Read( pDib, dwDibSize ) != dwDibSize ){  
  46.    //釋放點陣圖資料指標
  47.    delete [] pDib;  
  48.    //讀取失敗,程式返回
  49.    return;  
  50.    }  
  51.   }  
  52.  catch( CFileException *e ){  
  53.    e->Delete();  
  54.    delete [] pDib;  
  55.    return;  
  56.   }  
  57.  //重置全域性點陣圖資訊指標
  58.  if( m_pDib != NULL )  
  59.  {  
  60.   delete m_pDib;  
  61.  }  
  62.  //將點陣圖資訊指標和點陣圖資訊大小賦值給全域性變數
  63.  m_pDib = pDib;  
  64.  m_dwDibSize = dwDibSize;  
  65.  //獲取點陣圖資訊頭指標
  66.  m_pBIH = (BITMAPINFOHEADER *) m_pDib;  
  67.  //獲取點陣圖調色盤指標
  68.  m_pPalette =