プログラミング/BMPファイル仕様/バイナリ構造 のバックアップソース(No.6)

BMPファイルのバイナリ構造の解説。

#contents

*概要 [#about]

BMPファイルのバイナリ構造は、データの先頭から順に以下のような構成要素を持つ。

+[[ファイルヘッダ>#file-header]]
+[[情報ヘッダ>#info-header]]
+[[ビットフィールド>#bitfields]]
+[[カラーパレット>#palette]]
+[[イメージデータ>#image-data]]

このうち、[[ビットフィールド>#bitfields]]と[[カラーパレット>#palette]]については[[情報ヘッダ>#info-header]]の内容次第で存在しないことがある。~
また、[[イメージデータ>#image-data]]は[[情報ヘッダ>#info-header]]の内容によって形式が大きく変わる。

なお、BMPバイナリ中にある2バイト及び4バイトの整数値データのバイトオーダは[[リトルエンディアン>e-words:リトルエンディアン]]であり、符号付き整数値の場合は最上位ビットを符号ビットとする2の補数表現を用いる。~
Windows環境しか考慮しないのであればバイトオーダを気にする必要はないが、プラットフォームに依存しないコードを記述する際には留意すること((説明文中でもリトルエンディアンを前提とした記述をしている箇所がある。))。

*ファイルヘッダ [#file-header]

@dfn{ファイルヘッダ};はBMPファイルのバイナリ構造において最初に現れる必要があり、以下の構成要素を持つ。

|~要素|~バイト数|h
|LEFT:|RIGHT:|c
|[[ファイルタイプ>#file-header-filetype]]|2|
|[[ファイルサイズ>#file-header-filesize]]|4|
|[[予約1>#file-header-reserved1]]|2|
|[[予約2>#file-header-reserved2]]|2|
|[[イメージデータオフセット>#file-header-offset]]|4|

以下に各構成要素の詳細を述べる。

:@aname(file-header-filetype){ファイルタイプ};(2バイト)|ファイルがBMPファイルであることを示すもので、1バイト目が @code{'B'}; 、2バイト目が @code{'M'}; となる。~
エンコーダは必ずこの値を格納するべきで、デコーダはこの値であるかをチェックするべきである。
:@aname(file-header-filesize){ファイルサイズ};(4バイト)|BMPファイル全体のバイト単位でのサイズが符号無し整数値で入る。~
ただし、厳密でないエンコーダはこの値を計算せずに @code{0}; を格納しても構わない。~
デコーダはこの値を利用する必要はなく、また信用するべきでもない。
:@aname(file-header-reserved1){予約1};(2バイト)&br;@aname(file-header-reserved2){予約2};(2バイト)|これら2要素は将来の拡張用に予約されており、エンコーダは @code{0}; を格納するべきである。~
デコーダはこれらの値を無視して構わない。
:@aname(file-header-offset){イメージデータオフセット};(4バイト)|BMPファイルの最初から[[イメージデータ>#image-data]]の先頭までのバイト単位でのオフセットが符号無し整数値で入る。~
ただし、厳密でないエンコーダは @code{0}; を格納しても構わない。~
デコーダは、この値が @code{0}; 以外であった場合は信用するべきである。

Win32 SDK環境では、これらの構成を定義した @code{[[BITMAPFILEHEADER>http://msdn.microsoft.com/en-us/library/ms532321(VS.85).aspx]]}; 構造体が存在する。

#code(c){{
typedef struct tagBITMAPFILEHEADER { 
  WORD    bfType; 
  DWORD   bfSize; 
  WORD    bfReserved1; 
  WORD    bfReserved2; 
  DWORD   bfOffBits; 
} BITMAPFILEHEADER, *PBITMAPFILEHEADER;
}}

*情報ヘッダ [#info-header]

@dfn{情報ヘッダ};は[[ファイルヘッダ>#file-header]]のすぐ後に続いて現れる必要があり、以下の4種類が存在する。

-[[COREタイプ>#info-header-core]](12バイト)
-[[INFOタイプ>#info-header-info]](40バイト)
-[[V4タイプ>#info-header-v4]](40〜108バイト)
-[[V5タイプ>#info-header-v5]](40〜124バイト)

これらのうち、現在一般的なBMPファイルに使われているのは[[INFOタイプ>#info-header-info]]である。~
エンコーダはこのタイプさえ書き出せるならば問題はなく、デコーダは最低でもこのタイプに対応する必要がある。

どの情報ヘッダタイプにおいても最初の4バイトは必ずヘッダサイズとなる。~
よって複数のタイプに対応するデコーダは、まず最初の4バイトを読み取り、その数値で情報ヘッダタイプを判別する。

**COREタイプ [#info-header-core]

@dfn{COREタイプ};は[[OS/2>Wikipedia:OS/2]]で使われていた情報ヘッダ形式で、以下の構成要素を持つ。

|~要素|~バイト数|h
|LEFT:|RIGHT:|c
|[[ヘッダサイズ>#info-header-core-size]]|4|
|[[幅>#info-header-core-width]]|2|
|[[高さ>#info-header-core-height]]|2|
|[[プレーン数>#info-header-core-plane]]|2|
|[[ピクセル毎のビット数>#info-header-core-bitcount]]|2|

以下に各構成要素の詳細を述べる。

:@aname(info-header-core-size){ヘッダサイズ};(4バイト)|情報ヘッダのバイト単位でのサイズが符号無し整数値で入る。~
COREタイプでは必ず @code{12}; となる。~
エンコーダは必ずこの値を格納するべきで、デコーダはこの値を用いて情報ヘッダを判別する。
:@aname(info-header-core-width){幅};(2バイト)&br;@aname(info-header-core-height){高さ};(2バイト)|イメージのピクセル単位での幅と高さが符号無し整数値で入る。~
値は @code{1}; 以上でなければならない。
:@aname(info-header-core-plane){プレーン数};(2バイト)|イメージのプレーン数(チャンネル数)が符号無し整数値で入る。~
BMPファイルでは必ず @code{1}; となる。~
エンコーダは必ずこの値を格納するべきで、厳密でないデコーダはこの値を無視しても構わない。
:@aname(info-header-core-bitcount){ピクセル毎のビット数};(2バイト)|[[イメージデータ>#image-data]]において1ピクセルを表現するのに必要なビット数が符号無し整数値で入る。~
COREタイプでは @code{1}; 、 @code{4}; 、 @code{8}; 、 @code{24}; のいずれかとなる。~
他のタイプと違い、 @code{0}; 、 @code{16}; 、 @code{32}; は無効である。

Win32 SDK環境では、これらの構成を定義した @code{[[BITMAPCOREHEADER>http://msdn.microsoft.com/en-us/library/ms532335(VS.85).aspx]]}; 構造体が存在する。

#code(c){{
typedef struct tagBITMAPCOREHEADER {
  DWORD   bcSize; 
  WORD    bcWidth; 
  WORD    bcHeight; 
  WORD    bcPlanes; 
  WORD    bcBitCount; 
} BITMAPCOREHEADER, *PBITMAPCOREHEADER;
}}

**INFOタイプ [#info-header-info]

@dfn{INFOタイプ};は最も標準的な情報ヘッダ形式で、以下の構成要素を持つ。~
なお、INFOタイプは[[V4タイプ>#info-header-v4]]及び[[V5タイプ>#info-header-v5]]に内包されているため、これらのタイプに対応するデコーダはINFOタイプについて考慮する必要はない。

|~要素|~バイト数|h
|LEFT:|RIGHT:|c
|[[ヘッダサイズ>#info-header-info-size]]|4|
|[[幅>#info-header-info-width]]|4|
|[[高さ>#info-header-info-height]]|4|
|[[プレーン数>#info-header-info-plane]]|2|
|[[ピクセル毎のビット数>#info-header-info-bitcount]]|2|
|[[圧縮タイプ>#info-header-info-compression]]|4|
|[[イメージデータサイズ>#info-header-info-imagesize]]|4|
|[[水平解像度>#info-header-info-xppm]]|4|
|[[垂直解像度>#info-header-info-yppm]]|4|
|[[カラーインデックス数>#info-header-info-clrused]]|4|
|[[重要インデックス数>#info-header-info-clrimp]]|4|

以下に各構成要素の詳細を述べる。

:@aname(info-header-info-size){ヘッダサイズ};(4バイト)|情報ヘッダのバイト単位でのサイズが符号無し整数値で入る。~
INFOタイプでは必ず @code{40}; となる。~
エンコーダは必ずこの値を格納するべきで、デコーダはこの値を用いて情報ヘッダを判別する。
:@aname(info-header-info-width){幅};(4バイト)|イメージのピクセル単位での幅が符号付き整数値で入る。~
値は @code{1}; 以上でなければならない。
:@aname(info-header-info-height){高さ};(4バイト)|イメージのピクセル単位での高さが符号付き整数値で入る。~
値は @code{0}; であってはならない。~
また、トップダウン形式の場合は高さの値にマイナスの符号を付ける。
:@aname(info-header-info-plane){プレーン数};(2バイト)|イメージのプレーン数(チャンネル数)が符号無し整数値で入る。~
BMPファイルでは必ず @code{1}; となる。~
エンコーダは必ずこの値を格納するべきで、厳密でないデコーダはこの値を無視しても構わない。
:@aname(info-header-info-bitcount){ピクセル毎のビット数};(2バイト)|[[イメージデータ>#image-data]]において1ピクセルを表現するのに必要なビット数が符号無し整数値で入る。~
値は @code{0}; 、 @code{1}; 、 @code{4}; 、 @code{8}; 、 @code{16}; 、 @code{24}; 、 @code{32}; のいずれかとなり、この値によって[[圧縮タイプ>#info-header-info-compression]]の取りうる値が変わる。
:@aname(info-header-info-compression){圧縮タイプ};(4バイト)|[[イメージデータ>#image-data]]の形式を表す符号無し整数値で、以下のいずれかの値が入る。
:: @code{0}; (Win32 SDK環境では定数 @code{BI_RGB}; と同値)|標準の非圧縮形式であることを示す。~
[[ピクセル毎のビット数>#info-header-info-bitcount]]は @code{0}; であってはならない。
:: @code{1}; (Win32 SDK環境では定数 @code{BI_RLE8}; と同値)|8ビットのRLE形式であることを示す。~
[[ピクセル毎のビット数>#info-header-info-bitcount]]は @code{8}; でなければならない。
:: @code{2}; (Win32 SDK環境では定数 @code{BI_RLE4}; と同値)|4ビットのRLE形式であることを示す。~
[[ピクセル毎のビット数>#info-header-info-bitcount]]は @code{4}; でなければならない。
:: @code{3}; (Win32 SDK環境では定数 @code{BI_BITFIELDS}; と同値)|[[ビットフィールド>#bitfields]]を持つ非圧縮形式であることを示す。~
[[ピクセル毎のビット数>#info-header-info-bitcount]]は @code{16}; か @code{32}; でなければならない。
:: @code{4}; (Win32 SDK環境では定数 @code{BI_JPEG}; と同値)|JPEG形式であることを示す。~
[[ピクセル毎のビット数>#info-header-info-bitcount]]は @code{0}; でなければならない。
:: @code{5}; (Win32 SDK環境では定数 @code{BI_PNG}; と同値)|PNG形式であることを示す。~
[[ピクセル毎のビット数>#info-header-info-bitcount]]は @code{0}; でなければならない。
:@aname(info-header-info-imagesize){イメージデータサイズ};(4バイト)|[[イメージデータ>#image-data]]のバイト単位でのサイズが符号無し整数値で入る。~
エンコーダは、[[圧縮タイプ>#info-header-info-compression]]が @code{0}; か @code{3}; である場合、この値を @code{0}; にしても構わない。~
デコーダはこの値を利用する必要はなく、また信用するべきでもない。
:@aname(info-header-info-xppm){水平解像度};(4バイト)&br;@aname(info-header-info-yppm){垂直解像度};(4バイト)|イメージの横方向及び縦方向の1メートル当たりのピクセル数が符号無し整数値で入る。~
エンコーダはこれらの情報が不要ならば @code{0}; を格納しても構わず、厳密でないデコーダはこれらの値を無視しても構わない。
:@aname(info-header-info-clrused){カラーインデックス数};(4バイト)|[[カラーパレット>#palette]]に格納される色数が符号無し整数値で入る。~
この値が @code{0}; で[[ピクセル毎のビット数>#info-header-info-bitcount]]が @code{8}; 以下の場合、色数は2を[[ピクセル毎のビット数>#info-header-info-bitcount]]の値で累乗した数になる。~
すなわち1ビットならば2色、4ビットならば16色、8ビットならば256色となる。
:@aname(info-header-info-clrimp){重要インデックス数};(4バイト)|[[カラーパレット>#palette]]に格納されている色のうち、正確に表示すべき重要色の数が符号無し整数値で入る。~
先頭から数えてこの値の分の色が重要色として定義される。~
この値が @code{0}; である場合、全ての色が重要色となる。~
厳密でないデコーダはこの値を無視しても構わない。

Win32 SDK環境では、これらの構成を定義した @code{[[BITMAPINFOHEADER>http://msdn.microsoft.com/en-us/library/ms532290(VS.85).aspx]]}; 構造体が存在する。

#code(c){{
typedef struct tagBITMAPINFOHEADER{
  DWORD  biSize; 
  LONG   biWidth; 
  LONG   biHeight; 
  WORD   biPlanes; 
  WORD   biBitCount; 
  DWORD  biCompression; 
  DWORD  biSizeImage; 
  LONG   biXPelsPerMeter; 
  LONG   biYPelsPerMeter; 
  DWORD  biClrUsed; 
  DWORD  biClrImportant; 
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;
}}

**V4タイプ [#info-header-v4]

@dfn{V4タイプ};は[[INFOタイプ>#info-header-info]]を拡張した情報ヘッダ形式で、以下の構成要素を持つ。~
なお、V4タイプは[[V5タイプ>#info-header-v5]]に内包されているため、[[V5タイプ>#info-header-v5]]に対応するデコーダはV4タイプについて考慮する必要はない。

|~要素|~バイト数|h
|LEFT:|RIGHT:|c
|[[ヘッダサイズ>#info-header-v4-size]]|4|
|[[幅>#info-header-v4-width]]|4|
|[[高さ>#info-header-v4-height]]|4|
|[[プレーン数>#info-header-v4-plane]]|2|
|[[ピクセル毎のビット数>#info-header-v4-bitcount]]|2|
|[[圧縮タイプ>#info-header-v4-compression]]|4|
|[[イメージデータサイズ>#info-header-v4-imagesize]]|4|
|[[水平解像度>#info-header-v4-xppm]]|4|
|[[垂直解像度>#info-header-v4-yppm]]|4|
|[[カラーインデックス数>#info-header-v4-clrused]]|4|
|[[重要インデックス数>#info-header-v4-clrimp]]|4|
|[[赤成分のカラーマスク>#info-header-v4-rmask]]|4|
|[[緑成分のカラーマスク>#info-header-v4-gmask]]|4|
|[[青成分のカラーマスク>#info-header-v4-bmask]]|4|
|[[α成分のカラーマスク>#info-header-v4-amask]]|4|
|[[色空間タイプ>#info-header-v4-cstype]]|4|
|[[赤成分に対するCIEXYZのX座標>#info-header-v4-rciex]]|4|
|[[赤成分に対するCIEXYZのY座標>#info-header-v4-rciey]]|4|
|[[赤成分に対するCIEXYZのZ座標>#info-header-v4-rciez]]|4|
|[[緑成分に対するCIEXYZのX座標>#info-header-v4-gciex]]|4|
|[[緑成分に対するCIEXYZのY座標>#info-header-v4-gciey]]|4|
|[[緑成分に対するCIEXYZのZ座標>#info-header-v4-gciez]]|4|
|[[青成分に対するCIEXYZのX座標>#info-header-v4-bciex]]|4|
|[[青成分に対するCIEXYZのY座標>#info-header-v4-bciey]]|4|
|[[青成分に対するCIEXYZのZ座標>#info-header-v4-bciez]]|4|
|[[赤成分に対するガンマ値>#info-header-v4-rgamma]]|4|
|[[緑成分に対するガンマ値>#info-header-v4-ggamma]]|4|
|[[青成分に対するガンマ値>#info-header-v4-bgamma]]|4|

以下に各構成要素の詳細を述べる。

:@aname(info-header-v4-size){ヘッダサイズ};(4バイト)|情報ヘッダのバイト単位でのサイズが符号無し整数値で入る。~
V4タイプでは @code{40}; 、 @code{52}; 、 @code{56}; 、 @code{60}; 、 @code{96}; 、 @code{108}; のいずれかの値となり、 @code{108}; よりも小さい場合は情報ヘッダの後半部分が切り捨てられる。~
ただし、エンコーダはこの値を @code{108}; として全構成要素を書き出すことが望ましいと思われる。~
デコーダはこの値を用いて情報ヘッダを判別し、この値のサイズ分だけデータを読み込んで解析するようにする。
:@aname(info-header-v4-width){幅};(4バイト)&br;@aname(info-header-v4-height){高さ};(4バイト)&br;@aname(info-header-v4-plane){プレーン数};(2バイト)&br;@aname(info-header-v4-bitcount){ピクセル毎のビット数};(2バイト)&br;@aname(info-header-v4-compression){圧縮タイプ};(4バイト)&br;@aname(info-header-v4-imagesize){イメージデータサイズ};(4バイト)&br;@aname(info-header-v4-xppm){水平解像度};(4バイト)&br;@aname(info-header-v4-yppm){垂直解像度};(4バイト)&br;@aname(info-header-v4-clrused){カラーインデックス数};(4バイト)&br;@aname(info-header-v4-clrimp){重要インデックス数};(4バイト)|これらの値は[[INFOタイプ>#info-header-info]]の対応する値と同様の意味を持つ。~
詳しくは[[INFOタイプ>#info-header-info]]を参照のこと。
:@aname(info-header-v4-rmask){赤成分のカラーマスク};(4バイト)&br;@aname(info-header-v4-gmask){緑成分のカラーマスク};(4バイト)&br;@aname(info-header-v4-bmask){青成分のカラーマスク};(4バイト)|これらの値は[[圧縮タイプ>#info-header-v4-compression]]が @code{3}; の場合のみ意味を持ち、各色成分のカラーマスク値が入る。~
データの意味は[[ビットフィールド>#bitfields]]と同様であるため、詳しくはそちらを参照のこと。
:@aname(info-header-v4-amask){α成分のカラーマスク};(4バイト)|α成分(透明度情報)のカラーマスク値が入る。~
データの意味は[[ビットフィールド>#bitfields]]と同様であるため、詳しくはそちらを参照のこと。~
α成分自体は値が小さいほど透明度が上がり、 @code{0}; で完全に背景を透過する。~
透明度情報を扱わないデコーダはこの値を無視しても構わない。
:@aname(info-header-v4-cstype){色空間タイプ};(4バイト)|色空間タイプを示す定数が符号無し整数値で入る。~
V4タイプの場合、この値は必ず @code{0}; (Win32 SDK環境では定数 @code{LCS_CALIBRATED_RGB}; と同値)となる。~
この値が @code{0}; 以外であった場合、この情報ヘッダは[[V5タイプ>#info-header-v5]]である可能性がある。
:@aname(info-header-v4-rciex){赤成分に対するCIEXYZのX座標};(4バイト)&br;@aname(info-header-v4-rciey){赤成分に対するCIEXYZのY座標};(4バイト)&br;@aname(info-header-v4-rciez){赤成分に対するCIEXYZのZ座標};(4バイト)&br;@aname(info-header-v4-gciex){緑成分に対するCIEXYZのX座標};(4バイト)&br;@aname(info-header-v4-gciey){緑成分に対するCIEXYZのY座標};(4バイト)&br;@aname(info-header-v4-gciez){緑成分に対するCIEXYZのZ座標};(4バイト)&br;@aname(info-header-v4-bciex){青成分に対するCIEXYZのX座標};(4バイト)&br;@aname(info-header-v4-bciey){青成分に対するCIEXYZのY座標};(4バイト)&br;@aname(info-header-v4-bciez){青成分に対するCIEXYZのZ座標};(4バイト)|これらの値は[[色空間タイプ>#info-header-v4-cstype]]の値が @code{0}; の場合のみ意味を持ち、各色成分に対応したCIEXYZカラーモデルの各座標(三刺激値)が符号付き整数値で入る。~
出力デバイス(ディスプレイ等)にRGB値を渡す際に、これらの値を用いることができる。~
よって、デバイスに依存しないデコーダはこれらの値を無視して構わない。~
:|CIEXYZカラーモデルについての詳細は[[Adobe SystemsによるCIEXYZカラーモデルの解説>http://www.adobe.com/jp/support/techguides/color/colormodels/ciexyz.html]]等を参照のこと。~
X, Y, Z の各値を X, Y, Z の合計値で割ることで、色度座標 x, y, z を求めることができる。~
Win32 SDKにおける実装に関しては[[MASAPICO'S Page>http://nienie.com/%7Emasapico/]]の[[Color Management のメモ書き>http://nienie.com/%7Emasapico/cmmemo.txt]]等が参考になる。
:@aname(info-header-v4-rgamma){赤成分に対するガンマ値};(4バイト)&br;@aname(info-header-v4-ggamma){緑成分に対するガンマ値};(4バイト)&br;@aname(info-header-v4-bgamma){青成分に対するガンマ値};(4バイト)|これらの値は[[色空間タイプ>#info-header-v4-cstype]]の値が @code{0}; の場合のみ意味を持ち、各色成分に対応したガンマ値が入る。~
データの形式はMSDN Libraryの [[@code{LOGCOLORSPACE};>http://msdn.microsoft.com/en-us/library/ms536841(VS.85).aspx]]  構造体の解説によると、8〜15ビットが整数部、16〜23ビットが小数部の固定小数点数とのこと((このことから、 [[BITMAPV4HEADER>http://msdn.microsoft.com/en-us/library/ms532300(VS.85).aspx]] 構造体の解説にある @q(BITMAPV4HEADER - MSDN Library){16^16 format}; という説明は、整数部16ビット、小数部16ビットの固定小数点数という意味であると考えられる。))。~
CIEのxyY色度空間における Y を表しており、最小値は 0.0 、最大値は 100.0 と思われるが、正確な情報は不明。~
デバイスに依存しないデコーダはこれらの値を無視して構わない。

Win32 SDK環境では、これらの構成を定義した @code{[[BITMAPV4HEADER>http://msdn.microsoft.com/en-us/library/ms532300(VS.85).aspx]]}; 構造体が存在する。

#code(c){{
typedef struct {
  DWORD        bV4Size;
  LONG         bV4Width;
  LONG         bV4Height;
  WORD         bV4Planes;
  WORD         bV4BitCount;
  DWORD        bV4V4Compression;
  DWORD        bV4SizeImage;
  LONG         bV4XPelsPerMeter;
  LONG         bV4YPelsPerMeter;
  DWORD        bV4ClrUsed;
  DWORD        bV4ClrImportant;
  DWORD        bV4RedMask;
  DWORD        bV4GreenMask;
  DWORD        bV4BlueMask;
  DWORD        bV4AlphaMask;
  DWORD        bV4CSType;
  CIEXYZTRIPLE bV4Endpoints;
  DWORD        bV4GammaRed;
  DWORD        bV4GammaGreen;
  DWORD        bV4GammaBlue;
} BITMAPV4HEADER, *PBITMAPV4HEADER;
}}

**V5タイプ [#info-header-v5]

@dfn{V5タイプ};は[[V4タイプ>#info-header-v4]]を更に拡張した情報ヘッダ形式で、以下の構成要素を持つ。~
なお、V5タイプに対応することで[[INFOタイプ>#info-header-info]]及び[[V4タイプ>#info-header-v4]]にも対応できる。

|~要素|~バイト数|h
|LEFT:|RIGHT:|c
|[[ヘッダサイズ>#info-header-v5-size]]|4|
|[[幅>#info-header-v5-width]]|4|
|[[高さ>#info-header-v5-height]]|4|
|[[プレーン数>#info-header-v5-plane]]|2|
|[[ピクセル毎のビット数>#info-header-v5-bitcount]]|2|
|[[圧縮タイプ>#info-header-v5-compression]]|4|
|[[イメージデータサイズ>#info-header-v5-imagesize]]|4|
|[[水平解像度>#info-header-v5-xppm]]|4|
|[[垂直解像度>#info-header-v5-yppm]]|4|
|[[カラーインデックス数>#info-header-v5-clrused]]|4|
|[[重要インデックス数>#info-header-v5-clrimp]]|4|
|[[赤成分のカラーマスク>#info-header-v5-rmask]]|4|
|[[緑成分のカラーマスク>#info-header-v5-gmask]]|4|
|[[青成分のカラーマスク>#info-header-v5-bmask]]|4|
|[[α成分のカラーマスク>#info-header-v5-amask]]|4|
|[[色空間タイプ>#info-header-v5-cstype]]|4|
|[[赤成分に対するCIEXYZのX座標>#info-header-v5-rciex]]|4|
|[[赤成分に対するCIEXYZのY座標>#info-header-v5-rciey]]|4|
|[[赤成分に対するCIEXYZのZ座標>#info-header-v5-rciez]]|4|
|[[緑成分に対するCIEXYZのX座標>#info-header-v5-gciex]]|4|
|[[緑成分に対するCIEXYZのY座標>#info-header-v5-gciey]]|4|
|[[緑成分に対するCIEXYZのZ座標>#info-header-v5-gciez]]|4|
|[[青成分に対するCIEXYZのX座標>#info-header-v5-bciex]]|4|
|[[青成分に対するCIEXYZのY座標>#info-header-v5-bciey]]|4|
|[[青成分に対するCIEXYZのZ座標>#info-header-v5-bciez]]|4|
|[[赤成分に対するガンマ値>#info-header-v5-rgamma]]|4|
|[[緑成分に対するガンマ値>#info-header-v5-ggamma]]|4|
|[[青成分に対するガンマ値>#info-header-v5-bgamma]]|4|
|[[sRGB色空間タイプ>#info-header-v5-srgb]]|4|
|[[色空間プロフィールオフセット>#info-header-v5-cspoffset]]|4|
|[[色空間プロフィールサイズ>#info-header-v5-cspsize]]|4|
|[[予約>#info-header-v5-reserved]]|4|

以下に各構成要素の詳細を述べる。

:@aname(info-header-v5-size){ヘッダサイズ};(4バイト)|情報ヘッダのバイト単位でのサイズが符号無し整数値で入る。~
V5タイプでは @code{40}; 、 @code{52}; 、 @code{56}; 、 @code{60}; 、 @code{96}; 、 @code{108}; 、 @code{112}; 、 @code{120}; 、 @code{124}; のいずれかの値となり、 @code{124}; よりも小さい場合は情報ヘッダの後半部分が切り捨てられる。~
ただし、エンコーダはこの値を @code{124}; として全構成要素を書き出すことが望ましいと思われる。~
デコーダはこの値を用いて情報ヘッダを判別し、この値のサイズ分だけデータを読み込んで解析するようにする。
:@aname(info-header-v5-width){幅};(4バイト)&br;@aname(info-header-v5-height){高さ};(4バイト)&br;@aname(info-header-v5-plane){プレーン数};(2バイト)&br;@aname(info-header-v5-bitcount){ピクセル毎のビット数};(2バイト)&br;@aname(info-header-v5-compression){圧縮タイプ};(4バイト)&br;@aname(info-header-v5-imagesize){イメージデータサイズ};(4バイト)&br;@aname(info-header-v5-xppm){水平解像度};(4バイト)&br;@aname(info-header-v5-yppm){垂直解像度};(4バイト)&br;@aname(info-header-v5-clrused){カラーインデックス数};(4バイト)&br;@aname(info-header-v5-clrimp){重要インデックス数};(4バイト)|これらの値は[[INFOタイプ>#info-header-info]]の対応する値と同様の意味を持つ。~
詳しくは[[INFOタイプ>#info-header-info]]を参照のこと。
:@aname(info-header-v5-rmask){赤成分のカラーマスク};(4バイト)&br;@aname(info-header-v5-gmask){緑成分のカラーマスク};(4バイト)&br;@aname(info-header-v5-bmask){青成分のカラーマスク};(4バイト)&br;@aname(info-header-v5-amask){α成分のカラーマスク};(4バイト)|これらの値は[[V4タイプ>#info-header-v4]]の対応する値と同様の意味を持つ。~
詳しくは[[V4タイプ>#info-header-v4]]を参照のこと。
:@aname(info-header-v5-cstype){色空間タイプ};(4バイト)|色空間タイプを示す符号無し整数値で、以下のいずれかの値が入る。
:: @code{0}; (Win32 SDK環境では定数 @code{LCS_CALIBRATED_RGB}; と同値)|[[V4タイプ>#info-header-v4]]と同様の色空間情報を持つことを示す。
:: @code{0x73524742}; または @code{'sRGB'}; (Win32 SDK環境では定数 @code{LCS_sRGB}; と同値)|sRGB色空間情報を持つことを示す。
:: @code{0x57696E20}; または @code{'Win '}; (Win32 SDK環境では定数 @code{LCS_WINDOWS_COLOR_SPACE}; と同値)|Windows標準の色空間であることを示す。
:: @code{0x4C494E4B}; または @code{'LINK'}; (Win32 SDK環境では定数 @code{PROFILE_LINKED}; と同値)|色空間プロフィールファイルのパスがBMPファイル中に含まれていることを示す。
:: @code{0x4D424544}; または @code{'MBED'}; (Win32 SDK環境では定数 @code{PROFILE_EMBEDDED}; と同値)|色空間プロフィールがBMPファイル中に含まれていることを示す。
:@aname(info-header-v5-rciex){赤成分に対するCIEXYZのX座標};(4バイト)&br;@aname(info-header-v5-rciey){赤成分に対するCIEXYZのY座標};(4バイト)&br;@aname(info-header-v5-rciez){赤成分に対するCIEXYZのZ座標};(4バイト)&br;@aname(info-header-v5-gciex){緑成分に対するCIEXYZのX座標};(4バイト)&br;@aname(info-header-v5-gciey){緑成分に対するCIEXYZのY座標};(4バイト)&br;@aname(info-header-v5-gciez){緑成分に対するCIEXYZのZ座標};(4バイト)&br;@aname(info-header-v5-bciex){青成分に対するCIEXYZのX座標};(4バイト)&br;@aname(info-header-v5-bciey){青成分に対するCIEXYZのY座標};(4バイト)&br;@aname(info-header-v5-bciez){青成分に対するCIEXYZのZ座標};(4バイト)&br;@aname(info-header-v5-rgamma){赤成分に対するガンマ値};(4バイト)&br;@aname(info-header-v5-ggamma){緑成分に対するガンマ値};(4バイト)&br;@aname(info-header-v5-bgamma){青成分に対するガンマ値};(4バイト)|これらの値は、[[色空間タイプ>#info-header-v5-cstype]]の値が @code{0}; の場合のみ、[[V4タイプ>#info-header-v4]]の対応する値と同様の意味を持つ。~
詳しくは[[V4タイプ>#info-header-v4]]を参照のこと。
:@aname(info-header-v5-srgb){sRGB色空間タイプ};(4バイト)|sRGB色空間を示す符号無し整数値で、以下のいずれかの値が入る。~
これらの値は全て[[ICC>http://www.color.org/]]によって定義された[[国際色彩協会標準(ICC32)>http://www.color.org/icc32.pdf]]に基づいている。~
厳密でないデコーダはこの値を無視しても構わない。
:: @code{1}; (Win32 SDK環境では定数 @code{LCS_GM_BUSINESS}; と同値)|例えば図やグラフといった、色相や明度の保存に重点を置いたイメージであることを示す。~
国際色彩協会標準の対応する名称は"Saturation"である。
:: @code{2}; (Win32 SDK環境では定数 @code{LCS_GM_GRAPHICS}; と同値)|例えばロゴやデザイン画といった、カラーアピアランスの一致に重点を置いたイメージであることを示す。~
国際色彩協会標準の対応する名称は"Relative Colorimetric"である。
:: @code{4}; (Win32 SDK環境では定数 @code{LCS_GM_IMAGES}; と同値)|例えば写真や風景画といった、比色分析の正確さに重点を置いたイメージであることを示す。~
国際色彩協会標準の対応する名称は"Perceptual"である。
:: @code{8}; (Win32 SDK環境では定数 @code{LCS_GM_ABS_COLORIMETRIC}; と同値)|例えばプレビューといった、比色の絶対値の保存が必要なイメージであることを示す。~
国際色彩協会標準の対応する名称は"Absolute Colorimetric"である。
:@aname(info-header-v5-cspoffset){色空間プロフィールオフセット};(4バイト)|この値は[[色空間タイプ>#info-header-v5-cstype]]の値が @code{'LINK'}; あるいは @code{'MBED'}; の場合のみ意味を持ち、色空間プロフィールデータの格納位置が情報ヘッダの先頭からのバイト単位でのオフセットとして符号無し整数値で入る。~
各色空間タイプにおける色空間プロフィールデータの内容を以下に示す。~
厳密でないデコーダはこの値を無視しても構わない。
::色空間タイプが @code{'LINK'}; の場合|プロフィールデータは色空間プロフィールファイルのパスを表す @code{'\0'}; (ヌル文字)で終わる文字列である。
::色空間タイプが @code{'MBED'}; の場合|プロフィールデータは[[色空間プロフィールサイズ>#info-header-v5-cspsize]]分の埋め込みデータである。
:@aname(info-header-v5-cspsize){色空間プロフィールサイズ};(4バイト)|この値は[[色空間タイプ>#info-header-v5-cstype]]の値が @code{'LINK'}; あるいは @code{'MBED'}; の場合のみ意味を持ち、色空間プロフィールデータのバイト単位でのサイズが符号無し整数値で入る。~
色空間プロフィールデータを利用しないデコーダはこの値を無視して構わない。
:@aname(info-header-v5-reserved){予約};(4バイト)|将来の拡張用に予約されており、エンコーダは @code{0}; を格納するべきである。~
デコーダはこの値を無視して構わない。

Win32 SDK環境では、これらの構成を定義した @code{[[BITMAPV5HEADER>http://msdn.microsoft.com/en-us/library/ms532331(VS.85).aspx]]}; 構造体が存在する。

#code(c){{
typedef struct { 
  DWORD        bV5Size; 
  LONG         bV5Width; 
  LONG         bV5Height; 
  WORD         bV5Planes; 
  WORD         bV5BitCount; 
  DWORD        bV5Compression; 
  DWORD        bV5SizeImage; 
  LONG         bV5XPelsPerMeter; 
  LONG         bV5YPelsPerMeter; 
  DWORD        bV5ClrUsed; 
  DWORD        bV5ClrImportant; 
  DWORD        bV5RedMask; 
  DWORD        bV5GreenMask; 
  DWORD        bV5BlueMask; 
  DWORD        bV5AlphaMask; 
  DWORD        bV5CSType; 
  CIEXYZTRIPLE bV5Endpoints; 
  DWORD        bV5GammaRed; 
  DWORD        bV5GammaGreen; 
  DWORD        bV5GammaBlue; 
  DWORD        bV5Intent; 
  DWORD        bV5ProfileData; 
  DWORD        bV5ProfileSize; 
  DWORD        bV5Reserved; 
} BITMAPV5HEADER, *PBITMAPV5HEADER;
}}

*ビットフィールド [#bitfields]

@dfn{ビットフィールド};は、以下の条件を''すべて満たす場合のみ''存在する。

-[[情報ヘッダ>#info-header]]が[[INFOタイプ>#info-header-info]]、[[V4タイプ>#info-header-v4]]、[[V5タイプ>#info-header-v5]]のいずれかである。
-ヘッダサイズが @code{40}; である。
-[[ピクセル毎のビット数>#info-header-info-bitcount]]が @code{16}; または @code{32}; である。
-[[圧縮タイプ>#info-header-info-compression]]が @code{3}; である。

なお、[[V4タイプ>#info-header-v4]]及び[[V5タイプ>#info-header-v5]]においてヘッダサイズが @code{52}; 以上の場合、ビットフィールドは[[情報ヘッダ>#info-header]]に内包される。

ビットフィールドは、存在するならば[[情報ヘッダ>#info-header]]のすぐ後に続いて現れる必要があり、以下の構成要素を持つ。

|~要素|~バイト数|h
|LEFT:|RIGHT:|c
|赤成分のカラーマスク|4|
|緑成分のカラーマスク|4|
|青成分のカラーマスク|4|

なお、[[ピクセル毎のビット数>#info-header-info-bitcount]]が @code{16}; または @code{32}; ではあるが[[圧縮タイプ>#info-header-info-compression]]が @code{0}; でありビットフィールドが存在しない場合、デコーダは以下の値を既定のビットフィールドとして読み込みを続ける。~
エンコーダは、以下の値をビットフィールドとして用いる場合、[[圧縮タイプ>#info-header-info-compression]]を @code{0}; としてビットフィールドを省略できる。

:[[ピクセル毎のビット数>#info-header-info-bitcount]]が @code{16}; の場合|
|~要素|~値|h
|LEFT:|RIGHT:|c
|~赤成分のカラーマスク| @code{0x00007C00}; |
|~緑成分のカラーマスク| @code{0x000003E0}; |
|~青成分のカラーマスク| @code{0x0000001F}; |
なお、この値を持つビットフィールドを@dfn{RGB555};と呼ぶ。
:[[ピクセル毎のビット数>#info-header-info-bitcount]]が @code{32}; の場合|
|~要素|~値|h
|LEFT:|RIGHT:|c
|~赤成分のカラーマスク| @code{0x00FF0000}; |
|~緑成分のカラーマスク| @code{0x0000FF00}; |
|~青成分のカラーマスク| @code{0x000000FF}; |
なお、この値を持つビットフィールドを@dfn{RGB888};と呼ぶ。

値の詳細については、[[ビットフィールド>../ビットフィールド]]のページを参照のこと。

*カラーパレット [#palette]

@dfn{カラーパレット};は、以下の条件の''片方、もしくは両方を満たす場合のみ''存在する。

-[[情報ヘッダ>#info-header]]のピクセル毎のビット数が @code{1}; 、 @code{4}; 、 @code{8}; のいずれかの値である場合。
-[[INFOタイプ>#info-header-info]]、[[V4タイプ>#info-header-v4]]、[[V5タイプ>#info-header-v5]]の[[カラーインデックス数>#info-header-info-clrused]]が @code{1}; 以上である場合。

ピクセル毎のビット数が @code{16}; 以上であっても[[カラーインデックス数>#info-header-info-clrused]]が @code{1}; 以上ならばカラーパレットは存在することに注意すること。~
その場合のカラーパレットは主に減色時の色の指針をデコーダに与えるものであるが、定義はされておらず、デコーダはその内容を無視しても構わない。

カラーパレットは、存在するならば[[情報ヘッダ>#info-header]]のすぐ後に続いて現れる必要があり、[[情報ヘッダ>#info-header]]のタイプによって以下の2種類のどちらかが''色数分だけ列挙される''。~
なお、[[ビットフィールド>#bitfields]]が存在する場合、[[情報ヘッダ>#info-header]]ではなく[[ビットフィールド>#bitfields]]のすぐ後に続いて現れる必要がある。

:TRIPLEタイプ|[[情報ヘッダ>#info-header]]が[[COREタイプ>#info-header-core]]の場合の形式で、以下の構成要素が列挙される。
|~要素|~バイト数|h
|LEFT:|RIGHT:|c
|青成分値|1|
|緑成分値|1|
|赤成分値|1|
Win32 SDK環境では、これらの構成を定義した @code{[[RGBTRIPLE>http://msdn.microsoft.com/en-us/library/ms532318(VS.85).aspx]]}; 構造体が存在する。
#code(c){{
typedef struct tagRGBTRIPLE { 
  BYTE rgbtBlue; 
  BYTE rgbtGreen; 
  BYTE rgbtRed; 
} RGBTRIPLE;
}}
:QUADタイプ|[[情報ヘッダ>#info-header]]が[[INFOタイプ>#info-header-info]]、[[V4タイプ>#info-header-v4]]、[[V5タイプ>#info-header-v5]]の場合の形式で、以下の構成要素が列挙される。
|~要素|~バイト数|h
|LEFT:|RIGHT:|c
|青成分値|1|
|緑成分値|1|
|赤成分値|1|
|予約|1|
Win32 SDK環境では、これらの構成を定義した @code{[[RGBQUAD>http://msdn.microsoft.com/en-us/library/ms532316(VS.85).aspx]]}; 構造体が存在する。
#code(c){{
typedef struct tagRGBQUAD {
  BYTE    rgbBlue; 
  BYTE    rgbGreen; 
  BYTE    rgbRed; 
  BYTE    rgbReserved; 
} RGBQUAD;
}}

列挙なので、例えばQUADタイプの場合は次の図のようなバイト並びになる。

#ref(QUADタイプ列挙.png,left,nolink,|青|緑|赤|予|青|緑|赤|予|青|緑|赤|予|青|緑…)

色数は、[[情報ヘッダ>#info-header]]が[[INFOタイプ>#info-header-info]]、[[V4タイプ>#info-header-v4]]、[[V5タイプ>#info-header-v5]]で、かつ[[カラーインデックス数>#info-header-info-clrused]]が @code{1}; 以上ならばその値分の数になる。~
そうでなければ、2をピクセル毎のビット数で乗算した数になる。~
すなわち、ピクセル毎のビット数が @code{1}; ならば2色、 @code{4}; ならば16色、 @code{8}; ならば256色になる。

構成要素である各色成分値は @code{0}; から @code{255}; までの値をとり、その色要素がどれだけ強いかを表す。~
これら色要素は光の三原色を表し、全てが @code{0}; ならば黒、全てが @code{255}; ならば白となる。

QUADタイプの予約要素には通常 @code{0}; が入るが、この値をα成分値(透明度情報)として利用するデコーダも存在する。

*イメージデータ [#image-data]

@dfn{イメージデータ};は、[[ファイルヘッダ>#file-header]]の[[イメージデータオフセット>#file-header-offset]]が @code{0}; の場合は上述した構成要素群のすぐ後に続いて現れる必要があり、 @code{1}; 以上の場合はその値に従った位置に現れる必要がある。~
ただし、[[イメージデータオフセット>#file-header-offset]]の示す位置が上述の構成要素群の格納位置と被る場合、厳密なデコーダは例外として扱い、厳密でないデコーダはその値が @code{0}; であるものとして扱う。

イメージデータは、[[情報ヘッダ>#info-header]]が[[INFOタイプ>#info-header-info]]、[[V4タイプ>#info-header-v4]]、[[V5タイプ>#info-header-v5]]のいずれかで、[[圧縮タイプ>#info-header-info-compression]]が @code{1}; または @code{2}; である場合、RLEを用いて圧縮されている。~
その場合のイメージデータの内容は[[RLEによる圧縮>../RLEによる圧縮]]のページを参照のこと。~
また、[[圧縮タイプ>#info-header-info-compression]]が @code{4}; または @code{5}; である場合、イメージデータはJPEG形式及びPNG形式のデータそのものである。~
JPEG形式及びPNG形式の詳細については本文書の範疇を超えるため解説しない。~
このセクションでは、[[圧縮タイプ>#info-header-info-compression]]が @code{0}; または @code{3}; の非圧縮イメージデータについて解説する。

イメージデータは[[行データ>#image-data-line]]の羅列から成り、[[行データ>#image-data-line]]は[[ピクセルデータ>#image-data-pixel]]の羅列から成る。~
そして各々の[[ピクセルデータ>#image-data-pixel]]は、[[情報ヘッダ>#info-header]]のピクセル毎のビット数が示すビット単位のサイズになる。

イメージデータ内における[[行データ>#image-data-line]]の整列順は、イメージ表示時に下に来る行ほど最初に格納されるボトムアップ形式である。~
例えば、次のイメージの様に表示されるBMPファイルがあるとする。

#ref(最上行が白、最下行が黒.png,left,nolink,(最上行の白から最下行の黒へグラデーションしている絵))

この時、行データの格納順は、最下行の黒が一番最初になり、最上行の白が一番最後になる。~
ただし、[[情報ヘッダ>#info-header]]が[[INFOタイプ>#info-header-info]]、[[V4タイプ>#info-header-v4]]、[[V5タイプ>#info-header-v5]]のいずれかで、その[[高さ>#info-header-info-height]]の値がマイナスである場合、イメージの高さはその値の絶対値となり、[[行データ>#image-data-line]]の整列順は上に来る行ほど先に格納されるトップダウン形式となる。

[[行データ>#image-data-line]]及び[[ピクセルデータ>#image-data-pixel]]の詳細を以下に述べる。

**行データ [#image-data-line]

@dfn{行データ};は、文字通りイメージの横1行を表すデータで、上述の通り[[ピクセルデータ>#image-data-pixel]]の羅列である。

更に、行データは必ず4バイトの整数倍のサイズでなければならない。~
エンコーダは、行内の全[[ピクセルデータ>#image-data-pixel]]の合計サイズが4バイトの整数倍サイズではない場合、4バイトの整数倍サイズになるように0を追加する必要がある。~
例えば、幅が5ピクセルの8ビットBMP(1ピクセルが1バイト)の場合、行内の全[[ピクセルデータ>#image-data-pixel]]の合計サイズは5バイトであるため、4バイトの整数倍である8バイトにするために、次の図のようにする必要がある。

#ref(幅5ピクセルの8ビットBMP.png,left,nolink,|P|P|P|P|P|0|0|0| (P=ピクセルデータ))

[[情報ヘッダ>#info-header]]の幅の値が @var{Width}; 、ピクセル毎のビット数の値が @var{BitCount}; のとき、行データのサイズ @var{LineSize}; は次の式により求まる。~
なお、この式中の @code{[]}; は[[ガウス記号>ZDNet:ガウス記号]]であり、 @code{[N]}; は @var{N}; を超えない最大の整数を表す。

 LineSize=[(Width×BitCount+31)÷32]×4

この式により求まった @var{LineSize}; に[[情報ヘッダ>#info-header]]の高さの値の絶対値を掛けることでイメージデータのサイズが求まる。~
デコーダはそのようにして求めたイメージデータのサイズを信用して読み込み用のメモリを確保すべきである。

**ピクセルデータ [#image-data-pixel]

@dfn{ピクセルデータ};は、イメージ中の1ピクセル(別の言い方をするなら1ドット)を表すデータで、[[情報ヘッダ>#info-header]]のピクセル毎のビット数によって以下の形式が存在する。

:パレットタイプ|ピクセル毎のビット数が @code{1}; 、 @code{4}; 、 @code{8}; のいずれかの場合の形式。~
ピクセルデータは、[[カラーパレット>#palette]]内の1色を指し示す、0から始まるインデックス値となる。
:ビットフィールドタイプ|ピクセル毎のビット数が @code{16}; または @code{32}; の場合の形式。~
ピクセルデータは[[ビットフィールド>#bitfields]]の各カラーマスク値を基に算出された色となる。~
[[情報ヘッダ>#info-header]]が[[V4タイプ>#info-header-v4]]または[[V5タイプ>#info-header-v5]]の場合、[[α成分のカラーマスク>#info-header-v4-amask]]も考慮する。~
算出方法の詳細については[[ビットフィールド>../ビットフィールド]]のページを参照のこと。
:カラータイプ|ピクセル毎のビット数が @code{24}; の場合の形式で、ピクセルデータは以下の構成になる。
|~要素|~バイト数|h
|LEFT:|RIGHT:|c
|青成分値|1|
|緑成分値|1|
|赤成分値|1|
各色成分値のとりうる値とその意味は、[[カラーパレット>#palette]]の各色成分値と同義である。