Tips of VC++ >
ビットマップ >
ビットマップファイルの構造
★ 前へ戻る ★ 次へ進む ★
ビットマップファイルのフォーマットは 数多くのサイトでも紹介されているかと思いますが、 あえて、私のサイトでも。 MSDNを見たほうが最新の情報は詳しく載っているでしょう。 つーか、このサイトの情報は古いです。 使えるかもしれませんが、とにかく古いです。(笑
ファイルの情報 | BITMAPFILEHEADER構造体 |
ビットマップの情報 | BITMAPINFOHEADER構造体 |
カラーテーブル | RGBQUAD構造体の配列 |
画像ビット | 数字がちゃらちゃら(笑) |
まず、最初にBITMAPFILEHEADER構造体があります。
この構造体の値を確かめることにより
ファイルがビットマップか他のファイルか確かめることができます。
あと、リソースの場合は存在しません。
typedef struct tagBITMAPFILEHEADER { WORD bfType; DWORD bfSize; WORD bfReserved1; WORD bfReserved2; DWORD bfOffBits; } BITMAPFILEHEADER, *PBITMAPFILEHEADER;
bfType |
ファイルタイプを指定します。
ビットマップファイルの場合は"BM"、すなわち0x4D42を
そのまま代入してください。 この値が0x4D42でない場合は、ビットマップではない事が分かる。 |
bfSize | ビットマップファイルのサイズを指定する。 ファイルサイズはAPIを使った方が正確であるので、特に使う事はない。 |
bfReserved1 | 現在使われていない。0にしなければならない。 |
bfReserved2 | 現在使われていない。0にしなければならない。 |
bfOffBits | この構造体から画像ビットまでのバイト数を指定する。 これも使う必要はない。 |
BITMAPINFOHEADER構造体はBITMAPINFO構造体の一部ですが、 分けて考えた方が楽です。ビットマップの情報(幅・高さ・解像度など)が 入ってるので、重要です。
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;
biSize | 構造体のバイト数を指定する。 sizeof(BITMAPINFOHEADER)でよい。 |
biWidth | ビットマップの幅をピクセルで指定する。 biCompressionの値がBI_JPEGかBI_PNGだった場合は、 展開したときの幅である。ただし、圧縮に尽いては触れないことにする。 |
biHeight |
ビットマップの高さをピクセルで指定する。 この値が正のとき、ビットマップは"bottom-up DIB"。すなわち、 画像ビットが左下隅から上に向かって並べられていることを示す。 この値が負のときは"top-down DIB"。すなわち、 画像ビットは左上隅から下に向かって並べられていることを示す。 もし後者の場合、biCompressionはBI_RGBかBI_BITFIELDSの どちらかでなければならない。 "top-down DIB"は圧縮することができない。 さらに、biCompressionの値がBI_JPEGかBI_PNGだった場合は、 展開したときの幅である。ただし、圧縮に尽いては触れないことにする。 |
biPlanes | ターゲットデバイスのためのプレーン数を指定する。 この値は1でなければならない。 |
biBitCount | 1ピクセルあたりのビット数を指定する。 この値は0,1,4,8,16,24,32のいずれかの値を取る。 詳細に尽いては後で述べることにする。 |
biCompression | このメンバはBI_RGB,BI_RLE4,BI_RLE8, BI_BITFIELDS,BI_JPEG,BI_PNG のいずれかを取る。 詳細に尽いては後で述べることにする。 |
biSizeImage |
画像のサイズを指定する。
biCompressionがBI_RGB、つまり無圧縮の場合は
0でもよい。そのときは自分で計算する必要がある。 bi_CompressionがBI_JPEGかBI_PNGのときは このメンバはJPEG画像、PNG画像それぞれの イメージバッファのサイズが入る。 |
biXPelsPerMeter | ビットマップのターゲットデバイスの水平方向の解像度を 1メートルあたりのピクセル数で指定する。 アプリケーションはこの値を、 現在の(current)デバイスから最もよく合うリソースグループから ビットマップを選ぶのに使うことができる。 |
biYPelsPerMeter | ビットマップのターゲットデバイスの水平方向の解像度を 1メートルあたりのピクセル数で指定する。 |
biClrUsed | 実際にビットマップで使われている カラーテーブルのエントリ数を指定する。 この値が0ならば、ビットマップはbiBitCountの値で使用できる 最大のエントリ数を持っている。 |
biClrImportant | ビットマップを表示するのに必要な(required) カラーテーブルのエントリ数を指定する。 この値が0のときは、全ての色が必要である。 |
BITMAPINFO構造体は次のようになっていて、 前述のBITMAPINFOHEADER構造体とカラーテーブル(配列)が格納されます。
typedef struct tagBITMAPINFO { BITMAPINFOHEADER bmiHeader; RGBQUAD bmiColors[1]; } BITMAPINFO, *PBITMAPINFO;
RGBQUADの配列がカラーテーブルです。この構造体は単純です。 RGBそれぞれの明度が入っているわけです。 解説は要りませんね。rgbReservedは使われていません。
typedef struct tagRGBQUAD { BYTE rgbBlue; BYTE rgbGreen; BYTE rgbRed; BYTE rgbReserved; } RGBQUAD;
画像ビットはBITMAPINFOHEADER::biHeightの符号によって 変わってくるのですが、基本的には下から上に向かって並んでいます。 しかし順番が逆なわけではなく、ラインの並べる方向が逆なのです。 並べられた状態を図にしてみるとこんな感じ。
それだけでなく、ラインはlong境界に合わせる。 すなわち、1ラインのバイト数を4の倍数にしなければならないので、 それに満たない場合は0で埋められている。 例えば、幅が99ピクセルの8bpp画像は1ラインは99バイトにならずに 100バイトになる。つまり、幅が99ピクセルでも100ピクセルでも 画像のサイズは同じなのである。
ビットマップがカラーテーブルを持っている場合、 画像ビットはもちろんカラーテーブルのインデックス値を示す。 そうでないフルカラービットマップの場合は、BGR順の3バイトで 1ピクセルを表すことになる。RGB順ではない点に注意して欲しい。
次に、BITMAOINFOHEADERのbiBitCountについて詳細を述べる。 またMSDNからの転用であるが…。
Value | Meaning |
---|---|
0 | 1ピクセルあたりのビット数はJPEGフォーマットか、 PNGフォーマットによって指定されている。 |
1 | 白黒ビットマップである。 BITMAPINFO::bmiColorsは2つのエントリを保持している。 ビットマップ配列の互いのビットがピクセルで表現される。 もし、ビットがクリア(clear)ならば(おそらくOFFのときだろう)、 ピクセルはBITMAPINFO::bmiColorsの最初のエントリで表現される。 もし、ビットがセット(set)ならば(おそらくONのときだろう)、 ピクセルはBITMAPINFO::bmiColorsの2番目のエントリで表現される。 |
4 | ビットマップは最大で16色持つことができる。 BITMAPINFO::bmiColorsは16のエントリを保持している。 ビットマップの互いのピクセルは カラーテーブルへの4ビットのインデックスで表現される。 例えば、画像の最初のバイトが0x1fの場合は二つのピクセルを示しており、 最初のピクセルは2番目のカラーテーブル、二つ目のピクセルは 16番目のカラーテーブルのエントリを示している。 |
8 | ビットマップは最大で256色を保持できる。 BITMAPINFO::bmiColorsは256のエントリを持っている。 この場合、画像のそれぞれの1バイトは一つのピクセルを表している。 |
16 |
ビットマップは最大で2^16(65536)色を持っている。 もしbiCompressionがBI_RGBならばBITMAPINFO::bmiColorsはNULLである。 画像ビットのそれぞれ2バイト(WORD)が一つのピクセルを示す。 そして、5ビットでそれぞれ赤・緑・青の明度(intensity)を示す。 青の値は緑と赤の後に来て、末尾の5ビットで表される。 カラーテーブルはbiClrUsedによって指定されたエントリ数を 保持していなければならない。 もしbiCompressionがBI_BITFIELDSならば、 BITMAPINFO::bmiColorsは3つのDWORDでそれぞれ、赤・緑・青を構成している カラーマスク(color mask)を保持している。 しかし、システムは次に示す二つの16bppカラーマスクしか サポートしていない。すなわち、青のマスクが0x001Fで緑のマスクが0x03E0、 赤が0x7C00の"5-6-5 16-bit image"と青のマスクが0x001Fで 緑のマスクが0x07E0、赤が0xF800の"5-5-5 16-bit imageで"ある。 画像ビットの2バイト(WORD)で1ピクセルを表す。 |
24 | ビットマップは最大で2^24(16777216)色を保持できる。 BITMAPINFO::bmiColorsはNULLで、画像ビットのそれぞれ3バイトが 青・緑・赤の順番でそれぞれ明度(intensity)を示す。 |
32 | 4294967296
ビットマップは最大で2^32(4294967296)色を保持できる。 もし、biCompressionがBI_RGBならば、 BITMAPINFO::bmiColorsはNULLで、画像ビットのそれぞれ4バイト(DWORD)が 青・緑・赤の順番でそれぞれ明度(intensity)を示す。 DWORDの最上位バイト(high byte)は使われていない。 もしbiCompressionがBI_BITFIELDSならば、 BITMAPINFO::bmiColorsは3つのDWORDでそれぞれ、赤・緑・青を構成している カラーマスク(color mask)を保持している。 しかし、システムは次に示す32bppカラーマスクしか サポートしていない。すなわち、青のマスクが0x000000FFで 緑のマスクが0x0000FF00、赤が0x00FF0000 緑のマスクが0x07E0、赤が0xF800の"5-5-5 16-bit imageで"ある。 画像ビットの4バイト(DWORD)で1ピクセルを表す。 |
以上のことを分析すると、 カラーテーブルを持っているのは1,4,8bppのビットマップまでで、 他の16,24,32bppはフルカラービットマップである。 さらに、0,16,32bppのビットマップはbiCompressionの値が深く関ってきそうだ。
Value | Description |
---|---|
BI_RGB | 非圧縮ビットマップである。 |
BI_RLE4 | 4bppビットマップのためのランレングス(RLE)形式である。 ビットマップ圧縮についてはここでは述べない。 |
BI_RLE8 | 8bppビットマップのためのランレングス(RLE)形式である。 ビットマップ圧縮に尽いてはここでは述べない。 |
BI_BITFIELDS | ビットマップが非圧縮で、BITMAPINFO::bmiColorsが 三つのDWORD値から成立しているとき指定する。 これは16,32bppのとき使われる、 |
BI_JPEG | 画像ビットがJPEGであることを示す。 |
BI_PNG | 画像ビットがPNGであることを示す。 |
圧縮されたビットマップがあまり蔓延していないことを理由に
ランレングス形式の解説は端折らせていただきます。ごめんなさい。m(_ _)m
JPEG,PNGフォーマットも知りたいんですが、難しそう…。
他のサイトを見てくださいな。でも、リクエストがあれば調べますよ〜。
May 9, 2002