由於工作需要,研究了一下點陣圖的檔案格式。發現網路上的資料大多不夠齊全,或者範例太含糊。我將所有找到的資料消化/整理/翻譯之後如下,希望對需要的人有幫助:

《簡介》

點陣圖(bitmap)格式是 Windows 採用的圖像檔案儲存格式,在 Windows 環境下運行的所有圖像處理軟件都支持這種格式。Windows 3.0 以前的 BMP 格式與顯示設備有關,因此稱為設備相關點陣圖(Device-Dependent Bitmap, DDB)格式。Windows 3.0 以後的 BMP 格式則與顯示設備無關(Device-Independent Bitmap, DIB),目的是為了讓 Windows 能夠在任何類型的顯示設備上顯示點陣圖檔案。點陣圖檔案的預設副檔名是 BMP 或 bmp。

*******************************************
《點陣圖檔案結構》

點陣圖檔案由四個部份組成:

  1. Bitmap File Header
  2. Bitmap Info Header
  3. Color Table (Palette)
  4. 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)

【註4】未知的功能...永遠被設為 1

【註5】16 及 32 位元點陣圖是否使用調色盤必須由 Compression 欄位的數值決定
    請參考 Bitfields 的解說。

【註6】點陣圖壓縮方式有以下四種:BI_RGBBI_RLE8BI_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)。
    例如:
    1. Bit_Per_Pixel = 16, Compression = BI_RGB(無壓縮),
      則每個像素的 16 位元之中:
      最低 5 位元表示藍色分量,
      中間 5 位元表示綠色分量,
      接著的高 5 位元則是紅色分量,
      最高的 1 位元保留不使用。
      此格式即為 RGB555 格式。
    2. Bit_Per_Pixel = 16, Compression = BI_BITFIELDS,
      紅、綠、藍的 mask 分別為 0xF800, 0x07E0, 0x001F,
      則每個像素的 16 位元之中:
      最低 5 位元表示藍色分量,
      中間 6 位元表示綠色分量,
      最高 5 位元則是紅色分量,
      此格式即為 RGB565 格式。

【註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 欄位為負值),則掃描方向則是由上而下。

 


整理 by chiapei@gmail.com

 

 

 

arrow
arrow
    全站熱搜

    瘋小貓 發表在 痞客邦 留言(57) 人氣()