ビットマップファイルの構造 その1

仕事で画像処理をしております。
大学でも画像処理なんて勉強したこと無くて、会社でも勉強会とか研修とか全然無くて思いっきりOJT(On the Job Training:要は仕事するうちに覚えろということw)。
なのにいつの間にか画像処理をそれなりに使えるようになってきた。
入社当初はプログラミングもほとんどわからなかったのにw
一度画像処理の基礎から勉強しなおそうと思い立って、自分で一から画像処理ライブラリを作りながらここにまとめていきます。
ホントに独学なので間違って覚えていることは突っ込んでもらおうと(笑)

画像処理をするにあたって

まずは、画像処理をするにあたって、画像ファイルをメモリ上で処理できる形にしなければならないです。
画像処理では主にDIB(Device Independent Bitmap:デバイス独立ビットマップ)の画像データ形式を扱います。情報が非圧縮で1画素ずつ順番に入ってるので処理に便利。
WindowsのBMPファイルはDIB形式のファイル。WindowsでプログラミングしてるのでBMPしか扱ったことがありませんがまぁほとんど一緒でしょう(ぉぃ)
ということでDIB形式についてのまとめ。

DIBの構造
DIBの構造図

DIBのファイルはファイルヘッダ・画像情報・(カラーテーブル)・画像データで構成されます(カラーテーブルがカッコで書かれているのは後述)。ファイル構造は上図参照。
VC++とかだと、これ専用の構造体が用意されていて、この構造体のサイズ分をファイルから順番に読み込んでいけば正しく読み込める!というわけで便利です。

各構成要素の解説
ファイルヘッダ

BITMAPFILEHEADER構造体で表現される。
ファイルの基本情報が詰め込まれています。どんなファイルなのか等 etc...
BITMAOPFILEHEADER構造体の中身は、

typedef struct tagBITMAPFILEHEADER {
	WORD	bfType;	// BMPファイルなら"BM"=0x4D42
	DWORD	bfSize;	// ファイルサイズ(単位:Byte)
	WORD	bfReserved1;// 予約領域
	WORD	bfReserved2;// 予約領域
	DWORD	bfOffBits;
	// ファイル先頭から画像データ先頭までのオフセット(Byte)
} BITMAPFILEHEADER;
bfType
ファイルタイプ
WindowsのBMPなら必ず"BM"となる。そうじゃなければビットマップファイルでない。
bfSize
ファイルサイズ(Byte)
このファイルのサイズを指定しておく。
bfReserved1
bfReserved2
予約領域
今現在使われてなく、0にすること。
bfOffBits
画像データまでのオフセット(Byte)
ビットマップファイルの先頭から画像データ領域までのオフセット数(Byte)。少し複雑なので詳しくは後述。

BITMAPFILEHEADER構造体の情報はファイルの基本情報なので画像を扱うには重要ではないですが、他のアプリケーションで扱う場合に(たとえばWindowsのペイントやWindows Picture and Fax Viewer、その他画像ビューワー、レタッチなどのための画像加工ソフトなど)このファイルヘッダの情報を扱っている場合があるのでなるべくきちんと処理するほうが良い。(と思われる(個人的見解

画像情報

BITMAPINFOHEADER構造体で表現される。
画像情報が詰め込まれています。画像サイズ、1ピクセルあたりのカラービット数、などなど。重要な情報です。
BITMAPINFOHEADER構造体の中身は、

typedef struct tagBITMAPINFOHEADER {
	DWORD	biSize;		// この構造体(BITMAPINFOHEADER)のサイズ
	DWORD	biWidth;	// 画像幅サイズ(px)
	DWORD	biHeight;	// 画像高さサイズ(px)
	WORD	biPlanes;	// プレーン数(???)
	WORD	biBitCount;	// 1ピクセルあたりのカラービットの数
	DWORD	biCompression;	// ビットマップの圧縮形式指定
	DWORD	biSizeImage;	// 画像データの全バイト数
	DWORD	biXPelsPerMeter;// 水平方向解像度(px/mm)
	DWORD	biYPelsPerMeter;// 垂直方向解像度(px/mm)
	DWORD	biClrUsed;	// カラーテーブルのエントリ数
	DWORD	biClrImportant;	// 表示用カラーテーブルのエントリ数
}BITMAPINFOHEADER;
biSize
この構造体のサイズ
BITMAOPINFOHEADERは40バイトなので常に40
biWidth
画像横サイズ。説明省略
biHeight
画像縦サイズ
biHeightが正のとき、ビットマップ画像は左下原点。画像データ列が左下から上に並べられていることになる。負のときは左上原点。
ちなみにビットマップ以外の多くの画像ファイルは左上原点の形式になっている。ディスプレイの画面も左上原点なのでビットマップを扱う場合はこの点に注意しなければならない。(何度苦しめられたことかw
biPlanes
プレーン数
よくわからないまま1にしています(汗)
biBitCount
1ピクセルあたりのカラービットの数
1,4,8,16,24,32 (bit) のみ使える。
biCompression
ビットマップの圧縮形式
ランレングスとかJPEGとか。ここでは画像処理のため圧縮は使用しない。圧縮画像の話はまた機会があれば。
biSizeImage
画像データの全バイト数
biXPelsPerMeter
biYPelsPerMeter
画像解像度(px/mm)
それぞれX,Y方向の画像解像度を示す。0を指定しても良い
biClrUsed
カラーテーブルのエントリ数
実際にビットマップファイルに組み込まれているテーブルの数。0を指定するとbiBitCountで指定した分使用できる最大数を持っていることになる
biClrImportant
表示用カラーテーブルのエントリ数
ビットマップを表示するのに必要な(重要な)カラーテーブル数。0を指定すると全ての色が重要になる。
カラーテーブル

カラーテーブルはRGBQUAD構造体で表現します
RGBQUAD構造体1つで1つの色を示す。
RGBQUAD構造体の中身は、

typedef struct tagRGBQUAD {
	BYTE	rgbBlue;	// 青チャンネルの輝度値(0~255)
	BYTE	rgbGreen;	// 緑チャンネルの輝度値(0~255)
	BYTE	rgbRed;		// 赤チャンネルの輝度値(0~255)
	BYTE	rgbReserved;	// 予約領域(常に0にする)
} RGBQUAD;

っと、説明はいらないでしょう(笑)

画像データ

ピクセルのデータが1つずつ順番に格納されています。もちろん一番多く一番重要なデータw
こちらもあまり説明はいらないでしょう。ただ後で少し注意点を。

参考

こちらを見る方が詳しいかも。。ここではわかりやすくしたつもりですがw

その2へ

DIBの構造は以上ですが注意点がいくつかあるのでそれは「その2」でw

関連記事