BMP

BMP取自位圖Bitmap的縮寫，也稱為DIB（與設備無關的位圖），是一種獨立於顯示器的位圖數字圖像文件格式。常見於微軟視窗和OS/2作業系統，Windows GDI API內部使用的DIB數據結構與 BMP 文件格式幾乎相同。

圖像通常保存的顏色深度有2（1位）、16（4位）、256（8位）、65536（16位）和約1677萬（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$。

如果想知道這些值是如何得到的，請參考下面文件格式的部分。

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

## 文件格式

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

位圖文件由以下結構體依次構成：

結構體名稱｜可選｜大小｜用途｜備註

位圖文件頭｜否｜14位元組｜存儲位圖文件通用資訊｜僅在讀取文件時有用

DIB頭｜否｜固定（存在7種不同版本）｜存儲位圖詳細資訊及像素格式｜緊接在位圖文件頭後

附加位掩碼｜是｜3或4 DWORD（12或16位元組）｜定義像素格式｜僅在DIB頭是BITMAPINFOHEADER時存在

調色板｜見備註｜可變｜定義圖像數據（像素陣列）所用顏色｜色深≤ 8時不能省略

填充區A｜是｜可變｜結構體對齊｜位圖文件頭中像素陣列偏移量的產物

像素陣列｜否｜可變｜定義實際的像素數值｜像素數據在DIB頭和附加位掩碼中定義。像素陣列中每行均以4位元組對齊

填充區B｜是｜可變｜結構體對齊｜DIB頭中ICC色彩特性數據偏移量的產物

ICC色彩特性數據｜是｜可變｜定義色彩特性｜可以包含外部文件路徑，由該文件來定義色彩特性

下面的部分將會詳細地描述位圖文件中保存的數據。需要注意的是這是標準位圖的文件格式，其他一些位圖圖像可能根據生成文件的應用程式不同所使用格式可能會有細微的區別。

### 位圖文件頭

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

偏移量｜大小｜用途

0000h｜2位元組｜用於標識BMP和DIB文件的魔數，一般為0x42 0x4D，即ASCII的BM。以下為可能的取值：、BM – Windows 3.1x, 95, NT, ... etc.、BA – OS/2 struct Bitmap Array、CI – OS/2 struct Color Icon、CP – OS/2 const Color Pointer、IC – OS/2 struct Icon、PT – OS/2 Pointer

0002h｜4位元組｜BMP文件的大小（單位為字節）

0006h｜2位元組｜保留；實際值因創建程序而異

0008h｜2位元組｜保留；實際值因創建程序而異

000Ah｜4位元組｜位圖數據（像素陣列）的地址偏移，也就是起始地址。

### DIB頭

這部分告訴應用程式圖像的詳細資訊，在螢幕上顯示圖像將會使用這些資訊，它從文件的第15個字節開始。

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

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

大小｜結構名稱｜作業系統支援｜所加特性

12｜BITMAPCOREHEADEROS21XBITMAPHEADER｜OS/2和3.0版本以來的Windows

64｜BITMAPCOREHEADER2OS22XBITMAPHEADER｜OS/2｜添加半調網屏；添加RLE及霍夫曼1D壓縮。

40｜BITMAPINFOHEADER｜Windows 3.0及更高版本｜刪除RLE-24及霍夫曼1D壓縮；添加16/32位像素格式；添加可選的RGB位掩碼。

52｜BITMAPV2INFOHEADER｜Undocumented｜刪除可選的RGB位掩碼；添加必選的RGB位掩碼。Adobe Photoshop

56｜BITMAPV3INFOHEADER｜Not officially documented｜添加必選的Alpha通道位掩碼。Adobe Photoshop

108｜BITMAPV4HEADER｜Windows 95/NT4及更高版本｜添加色彩空間類型和伽瑪校正。

124｜BITMAPV5HEADER｜Windows 98/2000及更高版本｜添加ICC色彩特性。

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

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

偏移量｜大小（位元組）｜用途

0Eh｜4｜該頭結構的大小（40位元組）

12h｜4｜位圖寬度，單位為像素（有符號整數）

16h｜4｜位圖高度，單位為像素（有符號整數）

1Ah｜2｜色彩平面數；只有1為有效值

1Ch｜2｜每個像素所占位數，即圖像的色深。典型值為1、4、8、16、24和32

1Eh｜4｜所使用的壓縮方法，可取值見下表。

22h｜4｜圖像大小。指原始位圖數據的大小（詳見後文），與文件大小不是同一個概念。

26h｜4｜圖像的橫向解析度，單位為像素每米（有符號整數）

2Ah｜4｜圖像的縱向解析度，單位為像素每米（有符號整數）

2Eh｜4｜調色板的顏色數，為0時表示顏色數為默認的2色深個

32h｜4｜重要顏色數，為0時表示所有顏色都是重要的；通常不使用本項

注意：BI_RGB圖像的圖像大小欄位可以為0。

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

值｜標識｜壓縮方法｜備註

0｜BI_RGB｜無｜最常見

1｜BI_RLE8｜RLE 8位/像素｜只能用於格式為8位/像素的位圖

2｜BI_RLE4｜RLE 4位/像素｜只能用於格式為4位/像素的位圖

3｜BI_BITFIELDS｜位欄位或者霍夫曼1D壓縮（BITMAPCOREHEADER2）｜像素格式由位掩碼指定，或位圖經過霍夫曼1D壓縮（BITMAPCOREHEADER2）

4｜BI_JPEG｜JPEG或RLE-24壓縮（BITMAPCOREHEADER2）｜位圖包含JPEG圖像或經過RLE-24壓縮（BITMAPCOREHEADER2）

5｜BI_PNG｜PNG｜位圖包含PNG圖像

6｜BI_ALPHABITFIELDS｜位欄位｜針對Windows CE .NET 4.0及之後版本

注意：BI_JPEG和BI_PNG僅對印表機驅動有效，不支持螢幕渲染。

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

偏移量｜大小（位元組）｜用途

0Eh｜4｜該頭結構的大小（12位元組）

12h｜2｜位圖寬度，單位為像素

14h｜2｜位圖高度，單位為像素

16h｜2｜色彩平面數；只有1為有效值

18h｜2｜每個像素所占位數。典型值為1、4、8和24

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

### 調色板

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

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

在位圖文件的實現中，調色板可以包含很多條目，條目個數就是圖像中所使用的顏色的個數。

```c
typedef struct tagRGBQUAD {
    BYTE rgbBlue;
    BYTE rgbGreen;
    BYTE rgbRed;
    BYTE rgbReserved;
}   RGBQUAD;
```

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

### 像素存儲

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

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

$$\mbox{RowSize} = \left\lfloor\frac { \mbox{BitsPerPixel} \cdot \mbox{ImageWidth}+31 <pre> }{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

## 基本資料

- 日語原文：Windows位圖
- 擴展名：`.bmp`, `.dib`
- mime：`image/bmp`、`image/x-bmp`
- _nomimecode：y
- type code：`'BMP '`、`'BMPf'`、`'BMPp'`
- 統一類型標識：com.microsoft.bmp
- 類型：位圖
- 啟用：WMF的OSP
- 開發者：微軟