BMP

**BMP** 取自點陣圖 **B**it**m**a**p** 的縮寫，也稱為 **DIB**（與裝置無關的**點陣圖**），是一種獨立於監視器的點陣圖數位影像檔案格式。常見於微軟視窗和 OS/2 作業系統，Windows GDI API 內部使用的 DIB 資料結構與 BMP 檔案格式幾乎相同。

圖像通常儲存的顏色深度有 2（1 位）、16（4 位元）、256（8 位元）、65536（16 位元）和 1670 萬（24 位元）種顏色（其中位是表示每點所用的資料位）。8 位元圖像可以是索引彩色圖像外，也可以是灰階圖像。表示透明的 alpha 通道也可以儲存在一個類似於灰階圖像的獨立檔案中。帶有整合的 alpha 通道的 32 位元版本已經隨著 Windows XP 出現，它在 Windows 系統的登入介面和系統主題中都有使用。

## 儲存演算法

BMP 檔案通常是不壓縮的，所以它們通常比同一幅圖像的壓縮圖檔格式要大很多。例如，一個 800×600 的 24 位元幾乎占據 1.4MB 空間。因此它們通常不適合在網際網路或者其他低速或者有容量限制的媒介上進行傳輸。

根據顏色深度的不同，圖像上的一個像素可以用一個或者多個位元組表示，它由 **n/8** 所確定（n 是位深度，1 位元組包含 8 個資料位）。圖片瀏覽器等基於位元組的 ASCII 值計算像素的顏色，然後從調色盤中讀出相應的值。更為詳細的資訊請參閱下面關於點陣圖檔案的部份。

n 位 2n 種顏色的包含調色盤的點陣圖近似位元組數可以用下面的公式計算：

**BMP 檔案大小** $\approx 54+4\cdot 2^{n}+{\frac {{\rm {width}}\cdot {\rm {height}}\cdot n}{8}}$ ，其中高度（height）和寬度（width）都以像素為單位。

需要注意的是上面公式中的 **54** 是點陣圖檔案的檔案頭， $4\cdot 2^{n}$ 是彩色調色盤的大小。
如果點陣圖檔案不包含調色盤，如 24 位元，32 位元點陣圖，則點陣圖的近似位元組數可以用下面的公式計算：

**BMP 檔案大小** $\approx 54+{\frac {{\rm {width}}\cdot {\rm {height}}\cdot n}{8}}$ ，其中高度（height）和寬度（width）都以像素為單位。

另外需要注意的是這是一個近似值，對於 n 位的點陣圖圖像來說，儘管可能有最多 $2^{n}$ 種顏色，一個特定的圖像可能並不會使用這些所有的顏色。由於彩色調色盤僅僅定義了圖像所用的顏色，所以實際的彩色調色盤將小於 $4\cdot 2^{n}$ 。

如果想知道這些值是如何得到的，請參考下面檔案格式的部份。

由於儲存演算法本身決定的因素，根據幾個圖像參數的不同計算出的大小與實際的檔案大小將會有一些細小的差別。

## 檔案格式

點陣圖圖檔由若干大小固定（檔案頭）和大小可變的結構體按一定的順序構成。由於該檔案格式幾經演進，這些結構體的版本也很多。

點陣圖檔案由以下結構體依次構成：

下面的部份將會詳細地描述點陣圖檔案中儲存的資料。需要注意的是這是標準點陣圖的檔案格式，其他一些點陣圖圖像可能根據生成檔案的應用程式不同所使用格式可能會有細微的區別。

### 點陣圖檔案頭

這部份資料塊位於檔案開頭，用於進行檔案的辨識。典型的應用程式會首先普通讀取這部份資料以確保的確是點陣圖檔案並且沒有損壞。所有的整數值都以小端序存放（即最低有效位前置）。

### DIB 頭

這部份告訴應用程式圖像的詳細資訊，在螢幕上顯示圖像將會使用這些資訊，它從檔案的第 15 個位元組開始。

這部份資料塊對應了 Windows 和 OS/2 中的內部使用的頭結構以及其它一些版本的變體。但所有版本均以一個 DWORD 位（32 位元）開始，用以說明該資料區塊的大小，使得應用程式能夠根據這個大小來區分該圖像實際使用了哪種版本的 DIB 頭結構。

存在多種版本的頭結構的原因是微軟對 DIB 格式進行過多次擴充。下表即為所有不同版本的 DIB 頭：

BITMAPCOREHEADER 之後的版本都只是在前一版本結構末尾追加欄位。

出於相容性的考量，大多數應用程式使用較舊版本的 DIB 頭儲存檔案。在不考慮 OS/2 的情況下，目前通用的格式為 BITMAPINFOHEADER 版本，內容在下表中列出。除非有特殊說明，其中所有值均為無符號整數。

注意：BI\_RGB 圖像的圖像大小欄位可以為 0。

壓縮方法欄位（位元組 #30-33）的有效值如下表：

注意：BI\_JPEG 和 BI\_PNG 僅對印表機驅動有效，不支援螢幕彩現。

除此之外，OS/2 的 BITMAPCOREHEADER 頭也不鮮見：

注意：OS/2 BITMAPCOREHEADER 的點陣圖都是未壓縮的，而且不能是 16 或 32 位元 / 像素。OS/2 BITMAPCOREHEADER 中的所有值均為無符號整數。

### 調色盤

這部份定義了圖像中所用的顏色。如上所述，點陣圖圖像一個像素接著一個像素儲存，每個像素使用一個或者多個位元組的值表示，所以調色盤的目的就是要告訴應用程式這些值所對應的實際顏色。

典型的點陣圖檔案使用 RGB 彩色模型。在這種模型中，每種顏色都是由不同強度（從 0 到最大強度）的紅色（R）、綠色（G）和藍色（B）組成的，也就是說，每種顏色都可以使用紅色、綠色和藍色的值所定義。

在點陣圖檔案的實現中，調色盤可以包含很多條目，條目個數就是圖像中所使用的顏色的個數。

每個條目用來描述一種顏色，包含 4 個位元組，其中三個表示藍色、綠色和紅色，第四個位元組沒有使用（大多數應用程式將它設為 0）；對於每個位元組，數值 0 表示該顏色分量在當前的顏色中沒有使用，而數值 255 表示這種顏色分量使用最大的強度。

### 像素儲存

表示點陣圖中像素的位元是以行為單位對齊儲存的，每一行的大小都向上取整為 4 位元組（32 位元 DWORD）的倍數。如果圖像的高度大於 1，多個經過填充實現對齊的行就形成了**像素陣列**。

完整儲存的一行像素所需的位元組數可以通過這個公式計算：

　
: ${\mbox{RowSize}}=\left\lfloor {\frac {{\mbox{BitsPerPixel}}\cdot {\mbox{ImageWidth}}+31}{32}}\right\rfloor \cdot 4,$

　
: _ImageWidth_ 以像素為單位

#### 像素陣列

這部份逐個像素表示圖像。每個像素使用一個或者多個位元組表示。

通常，像素是從下到上、從左到右儲存的。但如果使用的不是 BITMAPCOREHEADER，那麼未壓縮的 Windows 點陣圖還可以從上到下儲存，此時圖像高度為負值。

每一行的末尾通過填充若干個位元組的資料（並不一定為 0）使該行的長度為 4 位元組的倍數。像素陣列讀入記憶體後，每一行的起始位址必須為 4 的倍數。這個限制僅針對記憶體中的像素陣列，針對儲存時，僅要求每一行的大小為 4 位元組的倍數，對檔案的偏移沒有限制。

例如：對於 24 位元色的點陣圖，如果它的寬度為 1 像素，那麼除了每一行的資料（藍、綠、紅）需要占 3 位元組外，還會填充 1 位元組；而如果寬為 2 像素，則需要 2 位元組的填充；寬為 3 像素時，需要 3 位元組填充；寬為 4 像素時則不需要填充。

圖像相同的條件下，點陣圖圖檔通常比使用其它壓縮演算法的圖檔大很多。

#### 壓縮

索引色圖像可以使用 4 位元或 8 位元 RLE 或霍夫曼 1D 演算法壓縮。

OS/2 BITMAPCOREHEADER2 24 位元色圖像則可以使用 24 位元 RLE 演算法壓縮。

16 位元色與 32 位元色圖像始終為未壓縮資料。

如果需要，任何色深的圖像都可以以未壓縮形式儲存。

#### 像素格式

無論是磁碟上的點陣圖檔案還是記憶體中的點陣圖圖像，像素都由一組位（英語：bit）表示。

* 每像素占 1 位（色深為 1 位，1bpp）的格式支援 2 種不同顏色。像素值直接對應一個位的值，最左像素對應第一個位元組的最高位。使用該位的值用來對色表的索引：為 0 表示色表中的第一項，為 1 表示色表中的第二項（即最後一項）。
* 每像素占 2 位（色深為 2 位，2bpp）的格式支援 4 種不同顏色。每個位元組對應 4 個像素，最左像素為最高的兩位（僅在 Windows CE 中有效）。需要使用像素值來對一張含有 4 個顏色值的色表進行索引。
* 每像素占 4 位元（色深為 4 位元，4bpp）的格式支援 16 種不同的顏色。每個位元組對應 2 個像素，最左像素為最高的四位。需要使用像素值來對一張含有 16 個顏色值的色表進行索引。
* 每像素占 8 位元（色深為 8 位元，8bpp）的格式支援 256 種不同的顏色。每個位元組對應 1 個像素。需要使用像素值來對一張含有 256 個顏色值的色表進行索引。
* 每像素占 16 位元（色深為 16 位元，16bpp）的格式支援 65536 種不同的顏色，每 2 個位元組（byte）對應一個像素。該像素的不透明度（英語：alpha）、紅、綠、藍採樣值即儲存在該 2 個位元組中。
* 每像素占 24 位元（色深為 24 位元，24bpp）的格式支援 16777216 種不同的顏色，每 3 個位元組對應一個像素。
* 每像素占 32 位元（色深為 32 位元，32bpp）的格式支援 4294967296 種不同的顏色，每 4 個位元組對應一個像素。

為了區分一個顏色值中的哪些位表示哪種採樣值，DIB 頭給出了一套預設規則，同時也允許使用 BITFIELDS 將某組位指定為像素中的某個通道。

## 其他

儘管檔案大小比較大，但是點陣圖檔案的簡單性、在微軟視窗和其他地方的廣泛使用以及這種格式的優秀文件標準以及沒有專利約束，使得它成為其他作業系統圖像處理程式能夠讀寫的一種最為常用的格式。

X Window System 使用類似的**.XBM** 格式表示一位黑白圖像以及**.XPM**（**pixelmap**）表示彩色圖像。另外還有一種**.RAW** 格式，它除了儲存原始資料之外沒有任何其他資訊。其他還有 Portable Pixmap file format（**.PPM**）和 Truevision TGA（**.TGA**），但是它們用得很少或者只用於特殊目的。儘管其他格式也儲存為「點陣圖」（與向量圖不同），但是它們使用資料壓縮或者顏色索引，所以它們不是嚴格意義上的點陣圖。

由於包含有冗餘資訊，許多 BMP 檔案使用類似於 ZIP 這樣的無失真資料壓縮演算法能夠取得很好的壓縮效果。

## 參見

* 圖檔格式比較
* Windows Picture and Fax Viewer

## 參考文獻

* Feng Yuan：《Windows Graphics Programming——Win32 GDI and DirectDraw》，Prentice Hall PTR， 1st ed.，2000-12-1，ISBN: 0-13-086985-6, 1234 pages. Chapter 10: Bitmap Basics; Chapter 11:Advanced Bitmap Graphics; Chapter 12:Image Processing Using Windows Bitmaps;

## 外部連結

* Microsoft's MSDN page on Bitmaps（頁面存檔備份，存於網際網路檔案館）
* Bitmap Storage Explanation（頁面存檔備份，存於網際網路檔案館）
* Bitmap File Structure（頁面存檔備份，存於網際網路檔案館）
* An introduction to DIBs (Device Independent Bitmaps)（頁面存檔備份，存於網際網路檔案館）
* Example BMP images with various internal formats
* Turbo C++ 3.0 Code to open 16-color bitmaps in DOS
* 點陣圖（Bitmap）檔案格式 by chiapei（頁面存檔備份，存於網際網路檔案館）