
■BMP形式(Windows DIB)
-- BMP形式入門 - BMPファイルの中身をちょっと覗いてみる --
間違い・誤字脱字を発見した場合はメールまたはBBSでお知らせください。
□ はじめに
□ BMP形式とは...
□ 全体の構造
□ ビットマップファイルヘッダ
□ ビットマップ情報ヘッダ
□ RGBQUAD構造体
□ ビット配列
□ 番外編 - ビットマップオブジェクト関連のWin32API関数
□ はじめに
デバイス独立ビットマップ(Device-Independent Bitmap)のフォーマットは情報ヘッダのちがいによってOS/2用とWindows用の2種類が
存在しますが、ここではWindows用のみ取り扱います。
また、16bit、32bitビットマップについては一般にあまり使われない形式なので省略しています。
圧縮形式(RLE形式:Run-Length Encoded)についても使う機会は少ないと思うので、これも省略します。
□ BMP形式とは...
Bitmapとは画像操作(移動、拡大縮小、回転、ペイントなど)を行なったり、
画像をディスクにファイルとして保存するためのグラフィックオブジェクトである。
Windows標準画像ファイル形式であるBMP形式は
Windows Device-Independent Bitmap(略してDIBと呼ばれる)を、
ファイルに保存したものである。
拡張子は.BMPである(拡張子.DIBもある)。
ランレングス法で圧縮されたビットマップはRLE(Run-Length Encoded)形式と呼ばれるが、
無圧縮で使用されることのほうが圧倒的に多い。
ビットマップにはDIBの他にGDIで使用されるデバイス依存ビットマップ(Device-Dependent Bitmap)がある。
初期のWindowsではDDBが開発者の扱える唯一のビットマップであった。
その後、技術が向上し表示デバイスが多様化するのに伴って、
デバイスに依存しないかたちで画像を扱えるDIBが開発され、
Windowsは3.0から採用している。
DIBはもともとIBMとMicrosoftが共同でOS開発を行なっていた頃に作られた画像ファイル形式なので、
WindowsDIBの他に情報ヘッダの異なるOS/2用のDIBも存在する。
DIBには、以下の情報が含まれる。
1.BMPファイル作成時に使用された表示装置のカラーフォーマット
2.BMPファイル作成時に使用された表示装置の解像度
3.BMPファイル作成時に使用された表示装置用のパレット
4.ピクセルを定義するビット配列
5.ファイルサイズを小さくするための圧縮方法
□ 全体の構造
ファイル全体の構造
| オフセット | サイズ | ファイル構造 |
| 00 (0) | (14) | ファイルヘッダ( BITMAPFILEHEADER構造体 ) |
| 0E (14) | biSize (40) | 情報ヘッダ( BITMAPINFOHEADER構造体 ) |
| 36 (54) | (注 1) | パレット(24bit、32bitBMPには存在しない) |
| bfOffBits | (注 2) | 画像データ( ビット配列 ) |
BMPファイルの構造は基本的に4つのセクションにわかれている。
ファイルヘッダ部には「ファイルタイプ」や「ファイルサイズ」など、
ファイル自体に関する情報が納められてる。
情報ヘッダ部は画像として取り扱われるのに必要な情報が格納されてる。
パレット部はRGBQUAD構造体の配列としてインデックスカラーが格納される。
また、2バイト以上のデータは[ 最下位バイト → 最上位バイト ]の順
(リトルエンディアン)で格納される。
4バイトの例) 0x12345678 ⇒ 78 56 34 12
(注 1)… パレットのサイズ
biClrUsedが0以外の時は、(biClrUsed * 4)で計算し、
biClrUsedが0のときは、(1ピクセルの階調数 * 4)で計算する。
1ピクセルの階調数 = 2の(biBitCount)乗
/* マクロで取得する場合 */
#define getpalsize(clrused, bitcount) ( ( (clrused != 0) ? ( clrused ) : (1 << bitcount) )*4)
(注 2)
ビット配列部のサイズ = ( bfSize - bfOffBits )
□ ビットマップファイルヘッダ
typedef struct tagBITMAPFILEHEADER {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER;
BITMAPFILEHEADER構造体
| オフセット | 構造体メンバ | サイズ(byte) | 内容 | 備考 |
| 00 (0) | bfType | 2 | ファイルタイプ | 常に 0x42,0x4D ("BM") |
| 02 (2) | bfSize | 4 | ファイルサイズ(byte) | |
| 06 (6) | bfReserved1 | 2 | 予約領域 | 使われていないので常に 0 |
| 08 (8) | bfReserved1 | 2 | 予約領域 | 使われていないので常に 0 |
| 0A (10) | bfOffBits | 4 | オフセット | ファイル先頭からビット配列先頭位置までのオフセット |
bfType
BMP形式として識別させるための識別子.
ここで扱う変数型について...
| | typedef unsigned short | WORD |
| | typedef unsigned long | DWORD |
| | typedef unsigned char | BYTE |
| | typedef long | LONG |
# その他の型については、Win32環境のC言語処理系ならwindef.hなどを参照
□ ビットマップ情報ヘッダ
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;
BITMAPINFOHEADER構造体
| オフセット | 構造体メンバ | サイズ(byte) | 内容 | 備考 |
| 0E (14) | biSize | 4 | 構造体のサイズ(byte) | 常に 0x28(40) (注1) |
| 12 (18) | biWidth | 4 | 画像の横幅(pixel) | |
| 16 (22) | biHeight | 4 | 画像の高さ(pixel) | 正の数ならビットマップの配列は下から上へ、負の数なら逆 |
| 1A (26) | biPlanes | 2 | プレーン | 常に1 |
| 1C (28) | biBitCount | 2 | 1ピクセルあたりの情報量 | (注2) |
| 1E (30) | biCompression | 4 | 圧縮形式 | 0: 無圧縮、1: 8bitRLE、2: 4bitRLE、3: ビットフィールド |
| 22 (34) | biSizeImage | 4 | ビット配列部のサイズ | byte単位 |
| 26 (38) | biXPixPerMeter | 4 | 水平方向解像度 | メートルあたりの解像度 - 0 の場合がある |
| 2A (42) | biYPixPerMeter | 4 | 垂直方向解像度 | メートルあたりの解像度 - 0 の場合がある |
| 2E (46) | biClrUsed | 4 | パレットの色数 | パレットが存在していても 0 になる事がある(注3) |
| 32 (50) | biClrImportant | 4 | 重要なパレットのインデックス | 0 になる事がある |
(注1)biSize … 構造体のサイズ
このbiSizeはBMPファイルに保存されている情報ヘッダのサイズである。
(注2)biBitCount … 1ピクセルで何色表現できるかを表す。
1 -- 2色(2階調ビットマップ)
2階調(モノクロ)画像で、2個のRGBQUAD構造体が含まれる。
ビット配列部分は0と1の配列で表され、それらが2つのRGBQUAD構造体にそれぞれ対応している。
4 -- 16色(4bitビットマップ)
16個のRGBQUAD構造体を含み、
ビット配列部分は、パレットの何番目に登録されている色かを示すインデックスの配列になる。
8 -- 256色(8bitビットマップ)
256色まで表現できる。
ビット配列部分は、インデックスの配列。
24 -- 16,777,216色(フルカラービットマップ)
RGBQUADを使わずにBGR順に並んだ3バイトで1ピクセルの色を表す。
ビット配列部分はBGRの配列である。
(注3)biClrUsed … インデックスカラーの色数。
biClrUsedが 0 の時はbiBitCountからパレットの色数を求める。
if(biClrUsed == 0){
colors = 1 << biBitCount;
}else{
colors = biClrUsed;
}
□ RGBQUAD構造体
typedef struct tagRGBQUAD {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;
RGBQUAD構造体
| オフセット | 構造体メンバ | サイズ(byte) | 内容 | 備考 |
| -- | rgbBlue | 1 | B 輝度 | |
| -- | rgbGreen | 1 | G 輝度 | |
| -- | rgbRed | 1 | R 輝度 | |
| -- | rgbReserved | 1 | 予約領域 | 常に 0 |
RGBQUAD構造体はパレット部で個々のインデックスカラーの定義に使われる。
□ ビット配列
ビット配列部でのデータ格納方式はbiBitCountによって異なる。
24bit Bitmap
RGBの個々の階調(256階調) * チャンネル数(R,G,Bの3つ) = 8bits * 3 = 24bits = biBitCount
24bit(フルカラービットマップ)の場合は、
ピクセルのRGB輝度が青→緑→赤の順に3バイト(24bit)の配列として並んで格納されている
(RGBQUADではない)。
biHeightが正の数値であれば、実際の画像の左下のピクセルを起点に画像上方に向かっていく配列(ボトムアップ方式)、
負の数値であれば左上のピクセルから始まって画像下方に向かう配列(トップダウン方式)になる。
BMPファイルを出力するアプリケーションはほとんどがボトムアップ方式(biHeightが正の数値)でピクセルの並びを記録している。
ピクセルRGB輝度は画像のピクセル総数(biWidth * abs( biHeight ) )と同じだけ繰り返される。
8bit Bitmap
最大256色のパレットを持つ、
パレットが存在する 8bit、4bit、1bitの場合、ビット配列部にはRGB輝度ではなく
パレットのインデックス(パレットで何番目の色が使われているか)が格納されている。
24bit, 8bit, 4bit, 1bitのすべてにおいて、画像の水平方向1行分のピクセルのデータサイズ(バイト)は
4バイトで割り切れるように調整されていなければならない。
1行分のデータのサイズを4で割って余りが出る場合、
4の倍数バイトになるように余分な 0 を詰める。
制 作 中 ...
□ 番外編 - ビットマップオブジェクトを扱うWin32API関数
BitBlt
CreateBitmap
CreateBitmapIndirect
CreateCompatibleBitmap
CreateDIBitmap
CreateDIBSection
CreateDiscardableBitmap
ExtFloodFill
FloodFill
GetBitmapBits
GetBitmapDimensionEx
GetDIBColorTable
GetDIBits
GetPixel
GetStretchBltMode
LoadBitmap
MaskBlt
PatBlt
PlgBlt
SetBitmapBits
SetBitmapDimension
SetDIBColorTable
SetDIBits
SetDIBitsToDevice
SetPixel
SetPixelV
SetStretchBltMode
StretchBlt
StretchDIBits
■ BitBlt ■
BitBlt関数は、ピクセル矩形に相当するカラーデータをコピー先のデバイスコンテキストからコピー元のデバイスコンテキストにビットブロック転送する関数である(要するにコピーです)。
BOOL BitBlt(
HDC hdcDest, // コピー先のデバイスコンテキスト.
int nXDest, // コピー先の矩形の左上頂点のX座標.
int nYDest, // コピー先の矩形の左上頂点のY座標.
int nWidth, // コピー元とコピー先の矩形共通の横幅.
int nHeight, // コピー元とコピー先の矩形共通の高さ.
HDC hdcSrc, // コピー元のデバイスコンテキスト.
int nXSrc, // コピー元の矩形の左上頂点のX座標.
int nYSrc, // コピー元の矩形の左上頂点のY座標.
DWORD dwRop // ラスタオペレーションコード.
);
ラスタオペレーションコード
コピー元のカラーデータとコピー先矩形のカラーデータをどのように合成するかを
定義するコードで、以下に列挙するコードを指定する.
# ラスタオペレーションコードはStretchDIBits関数などでも使用します.
| BLACKNESS |
物理パレットのインデックス0に関連付けされている色でコピー先の矩形を
塗り潰す(この色はデフォルトの物理パレットでは黒). |
| DSTINVERT |
コピー先矩形の色を反転 |
| MERGECOPY |
指定された模様とコピー元の矩形の色を論理積演算子(AND)で合成. |
| MERGEPAINT |
反転させたコピー元矩形の色とコピー先矩形の色を論理和演算子(OR)で合成. |
| NOTSRCCOPY |
色を反転させたコピー元矩形をコピー先の座標にコピー. |
| NOTSRCERASE |
論理和でコピー先とコピー元の矩形を結合してから、さらにその結果の色を反転. |
| PATCOPY |
指定された模様をコピー先のビットマップにコピー. |
| PATINVERT |
排他的論理和(XOR)で、指定された模様の色とコピー先矩形の色を結合. |
| PATPAINT |
指定した模様の色と反転したコピー元の色を論理和で結合し、さらにその結果を
コピー先矩形の色と論理和で結合させる. |
| SRCAND |
コピー元とコピー先を論理積で結合. |
| SRCCOPY |
コピー元の矩形をそのままコピー先にコピー. |
| SRCERASE |
反転させたコピー先の色とコピー元の色を論理積で結合. |
| SRCINVERT |
コピー元とコピー先を排他的論理和で結合. |
| SRCPAINT |
コピー元とコピー先を論理和で結合. |
| WHITENESS |
物理パレットのインデックス1に関連付けられた色で、コピー先矩形を
塗り潰す(この色はデフォルトの物理パレットでは白). |
戻り値
関数が成功した場合には非ゼロを返す.
失敗した場合はゼロを返す.拡張エラー情報を得るにはGetLastError関数を呼び出す事.
サンプルソースコード
サンプル その1( html )
いろいろな実行結果 - 画像
■ CreateBitmap ■
CreateBitmap関数は、指定された幅、高さ、カラーフォーマット(カラープレーンとピクセルあたりのビット数)からビットマップを作る.
HBITMAP CreateBitmap(
int nWidth, // ビットマップの横.
int nHeight, // ビットマップの高さ.
UINT cPlanes, // デバイスで使用されるカラープレーンの数.
UINT cBitsPerPel, // 1ピクセルの色を表すのに必要なビット数.
CONST VOID *lpvBits // ピクセル矩形に色をセットするために使うカラーデータ配列へのポインタ.
);
パラメータ
lpvBits
矩形中の1行ごとの配列はWORDアラインでなくてはならない(WORDアラインでない場合はゼロを詰める).
戻り値
関数が成功した場合はビットマップのハンドルを返す.
失敗した場合はNULLを返す.
備考
ビットマップが作成された後、SelectObject関数でデバイスコンテキストに選択できる.
CreateBitmapはモノクロビットマップを作成するのに使い、カラーのビットマップを作成するにはCreateCompatibleBitmapを使うこと.
以 下 制 作 中 ...
[ 文書作成 ]
Kalashnikov <kalashnikov-lj@infoseek.jp >
[ 参考文献 ]
Win32 Developer's References / Microsoft