由於工作需要,研究了一下點陣圖的檔案格式。發現網路上的資料大多不夠齊全,或者範例太含糊。我將所有找到的資料消化/整理/翻譯之後如下,希望對需要的人有幫助:
《簡介》
點陣圖(bitmap)格式是 Windows 採用的圖像檔案儲存格式,在 Windows 環境下運行的所有圖像處理軟件都支持這種格式。Windows 3.0 以前的 BMP 格式與顯示設備有關,因此稱為設備相關點陣圖(Device-Dependent Bitmap, DDB)格式。Windows 3.0 以後的 BMP 格式則與顯示設備無關(Device-Independent Bitmap, DIB),目的是為了讓 Windows 能夠在任何類型的顯示設備上顯示點陣圖檔案。點陣圖檔案的預設副檔名是 BMP 或 bmp。
*******************************************
《點陣圖檔案結構》
點陣圖檔案由四個部份組成:
- Bitmap File Header
- Bitmap Info Header
- Color Table (Palette)
- Bitmap Array
Note: 以下欄位資料皆為 little-endian! Little-Endian 的意思是:若某個欄位值為 0x1234,當你將BMP檔案用 UltraEdit 之類的純文字編輯器打開時,則你看到的值會是 0x3412,這是 Intel 制定的儲存方式,把值小的位元組(0x34)存在前面;詳情可參考 Big Endian 和 Little Endian 架構的說明
Shift | Name | Size (bytes) |
Content | |
Bitmap File Header |
0000h | Identifier (ID) | 2 | 'BM'【註1】 |
0002h | File Size | 4 | 整個點陣圖檔案的大小(單位:byte) | |
0006h | Reserved | 4 | 保留欄位 | |
000Ah | Bitmap Data Offset | 4 | 點陣圖資料開始之前的偏移量(單位:byte) | |
Bitmap Info Header |
000Eh | Bitmap Header Size | 4 | Bitmap Info Header 的長度【註2】 |
0012h | Width | 4 | 點陣圖的寬度,以像素(pixel)為單位 | |
0016h | Height | 4 | 點陣圖的高度,以像素(pixel)為單位【註3】 | |
001Ah | Planes | 2 | 點陣圖的位元圖層數【註4】 | |
001Ch | Bits Per Pixel | 2 | 每個像素的位元數 1:單色點陣圖(使用 2 色調色盤) 4:4 位元點陣圖(使用 16 色調色盤) 8:8 位元點陣圖(使用 256 色調色盤) 16:16 位元高彩點陣圖(不一定使用調色盤) 24:24 位元全彩點陣圖(不使用調色盤) 32:32 位元全彩點陣圖(不一定使用調色盤) 【註5】 |
|
001Eh | Compression | 4 | 壓縮方式【註6】: 0:未壓縮 1:RLE 8-bit/pixel 2:RLE 4-bit/pixel 3:Bitfields |
|
0022h | Bitmap Data Size | 4 | 點陣圖資料的大小(單位:byte)【註7】。 | |
0026h | H-Resolution | 4 | 水平解析度(單位:像素/公尺)【註8】 | |
002Ah | V-Resolution | 4 | 垂直解析度(單位:像素/公尺) | |
002Eh | Used Colors | 4 | 點陣圖使用的調色盤顏色數【註9】 | |
0032h | Important Colors | 4 | 重要的顏色數【註10】 | |
Palette | 0036h | Palette | N*4 | 調色盤資料。 每個索引值指定一種顏色:0x00RRGGBB 其中最高位元組保留為零 |
Bitmap Array |
- | Bitmap Data | - | 點陣圖資料【註11】 |
【註1】此欄原本有多種識別碼,用來識別點陣圖的類型:
'BM' - Windows 3.1x, 95, NT, ...
'BA' - OS/2 Bitmap Array
'CI' - OS/2 Color Icon
'CP' - OS/2 Color Pointer
'IC' - OS/2 Icon
'PT' - OS/2 Pointer
不過既然 OS/2 並不普及,目前皆在 Windows 上作業,因此 ID 全都是 'BM'。
【註2】此欄原本有多種數值,依作業系統種類而定:
28h - Windows 3.1x, 95, NT, ...
0Ch - OS/2 1.x
F0h - OS/2 2.x
以目前 Windows 常用的點陣圖來說,此欄位數值通常是 28h。
但因為微軟已經制定出了新的點陣圖格式,其中的 Bitmap Info Header 結構變化較大,長度加長,所以最好不要直接使用常數 28h,而是應該從實際檔案中讀取這個數值,才能確保程式相容性。
【註3】高度可能為負值,負值表示掃瞄方向由上而下。
但若高度是負值時,此點陣圖將不能被壓縮!(也就是說 Compression 欄位總是為 0)
【註5】16 及 32 位元點陣圖是否使用調色盤必須由 Compression 欄位的數值決定,
請參考 Bitfields 的解說。
【註6】點陣圖壓縮方式有以下四種:BI_RGB,BI_RLE8,BI_RLE4,以及BI_BITFIELDS。
- None (BI_RGB)
表示此點陣圖資料沒有壓縮,不使用調色盤。 - RLE 8bpp (BI_RLE8)
每個像素為 8 bit 的 RLE 壓縮編碼(Run-Length Encoding)(總共可使用 256 色)。
有「編碼模式」(Encoded Mode)和「絕對模式」(Absolute Mode)兩種方法,
可在同一幅圖檔中的任何地方交錯使用。
「編碼模式」:由兩個位元組(byte)組成。
第一個位元組指定 "Length"(使用相同顏色的像素數目),
第二個位元組指定 "Run"(此像素使用的調色盤索引)。
若第一個位元組為零,則表示特殊意義:
0x0000 - 表示此列結束
0x0001 - 表示此點陣圖檔案結束
0x0002 - 表示其後的兩位元組分別表示
下個像素位置與目前像素位置的水平/垂直偏移量。
0x000x - 表示絕對模式。
「絕對模式」:第一個位元組為 0x00,第二個位元組為 0x03 ~ 0xFF 之間的數值。
其中第二個位元組表示後續資料的長度(單位為 byte),
後續資料的每個位元組都表示單一像素的調色盤索引值。
每一模式的編碼長度都必須與字邊界對齊(word-aligned),也就是 2 的倍數。
使用「編碼模式」時,由於每組編碼皆為兩個位元組,所以毋需多加處理;
但是使用「絕對模式」時,則必須在最後補上適當的 0x00 以使資料長度對齊 2 的倍數。
下面是一個 BI_RLE8 的例子:
03 01 05 02 00 03 00 01 02 00 02 01 00 02 05 01 02 03 00 00 09 02 00 01
這些資料可解讀為:
壓縮資料 解壓縮之後的資料 03 01 01 01 01 05 02 02 02 02 02 02 00 03 00 01 02 00 00 01 02(最後的 00 是為了 word-aligned 才補上的) 02 01 01 01 00 02 05 01 從目前位置右移 5 像素之後,向下移一列 02 03 03 03 00 00 此列結束 09 02 02 02 02 02 02 02 02 02 02 00 01 此點陣圖結束 上述資料的圖形如下:
- RLE 4bpp (BI_RLE4)
每個像素為 4-bit 的 RLE 壓縮編碼(總共可使用 16 色)。
同樣也有「編碼模式」與「絕對模式」,且可以在同一圖檔中任何地方使用任一模式。
「編碼模式」:由兩個位元組組成。
第一個位元組指定像素數目,
第二個位元組包含兩個調色盤索引:
第一個像素使用高 4 位元的索引值、
第二個像素使用低 4 位元的索引值、
第三個像素又使用高 4 位元的索引值,以此類推。
若第一個位元組為零,則表示特殊意義:
0x0000 - 表示此列結束
0x0001 - 表示此點陣圖檔案結束
0x0002 - 表示其後的兩位元組分別表示
下個像素位置與目前像素位置的水平/垂直偏移量。
0x000x - 表示絕對模式。
「絕對模式」:第一個位元組為 0x00,第二個位元組表示後續資料的長度(單位為 byte)。
後續資料的每個位元組都含有兩個調色盤索引值(高 4 及低 4 位元),
每個索引值對應一個像素。
每一模式的編碼長度仍然必須與字邊界對齊(word-aligned)。
使用「編碼模式」時,由於每組編碼皆為兩個位元組,所以毋需多加處理;
但是使用「絕對模式」時,則必須在最後補上適當的 0 以使資料長度對齊 2 的倍數。
下面是一個 BI_RLE4 的例子:
03 11 05 02 00 05 01 23 10 00 02 22 00 02 05 01 02 13 00 00 09 10 00 01
這些資料可解讀為:
壓縮資料 解壓縮之後的資料 03 11 1 1 1 05 02 0 2 0 2 0 00 05 01 23 10 00 0 1 2 3 1(最後的 0 00 是為了 word-aligned 才補上的) 02 22 2 2 00 02 05 01 從目前位置右移 5 像素之後,向下移一列 02 13 1 3 00 00 此列結束 09 10 1 0 1 0 1 0 1 0 1 00 01 此點陣圖結束 上述資料的圖形如下:
- Bitfileds (BI_BITFIELDS)
只有當「Bit Per Pixel」欄位的數值為 16 或 32 時,才會使用 BI_BITFIELDS 這種格式。
使用 BI_BITFIELDS 時,點陣圖檔中原本的調色盤位置會被三個 DWORD 佔據,
分別代表 R、G、B 三個顏色分量的遮罩(mask)。
例如:- Bit_Per_Pixel = 16, Compression = BI_RGB(無壓縮),
則每個像素的 16 位元之中:
最低 5 位元表示藍色分量,
中間 5 位元表示綠色分量,
接著的高 5 位元則是紅色分量,
最高的 1 位元保留不使用。
此格式即為 RGB555 格式。 - Bit_Per_Pixel = 16, Compression = BI_BITFIELDS,
紅、綠、藍的 mask 分別為 0xF800, 0x07E0, 0x001F,
則每個像素的 16 位元之中:
最低 5 位元表示藍色分量,
中間 6 位元表示綠色分量,
最高 5 位元則是紅色分量,
此格式即為 RGB565 格式。
- Bit_Per_Pixel = 16, Compression = BI_RGB(無壓縮),
【註7】若沒有壓縮(Compression 欄位為 0),則此欄數值可設為 0。
(我發現許多繪圖軟體根本不看此欄數值,隨便填寫也無所謂,圖檔仍可正常開啟)
【註8】若要換算為 dpi,則將此欄數值要除以39.37(吋/公尺)
例如,此欄數值若為 2834 (pixels per meter),
則 2834 ÷ 39.37 = 72 (pixels per inch) = 72 dpi
【註9】此欄表示圖檔實際使用的顏色數目,若數值為 0,表示使用所有調色盤顏色。
如果此欄數值並非「可用顏色的最大值」或者「零」,則需注意調色盤尺寸的計算。
例如,在 4 bpp bitmap 中,調色盤預設尺寸應是 16*4 bytes,
但若 Used Color 欄位數值並非 16 或 0,則調色盤尺寸應是 Used_Color_Number * 4 (bytes)。
【註10】當此欄的值等於「顏色數」或者為 0 時,表示所有顏色都一樣重要。
【註11】緊跟在調色盤之後的就是點陣圖資料陣列。
每一掃描列的長度取決於圖檔的寬度及顏色深度(Color Depth),
但是每一掃描列的長度必需是 4 byte 的倍數(DWORD-aligned)!
正常的點陣圖掃描列是由底向上儲存的:
陣列中的第一個 byte 表示全圖左下角的像素,而最後一個 byte 則表示全圖右上角的像素。
但如果是正向掃描(Height 欄位為負值),則掃描方向則是由上而下。
留言列表