BMP画像形式の?
ホーム 上へ

New (2001/09/02)         

bullet大量のフロッピーに古い画像データ

大量に残っているDOS時代のデータやソフトのセットアップ用フロッピー整理していました。数年前に5インチフロッピーから3.5インチフロッピーに変換して、ダンボール2箱に保存していたものです。3分の1くらいは、CG作品の作業データ、部品データ、画像データのはずです。保存しているだけで、ほとんど開くこともなかったのですが、昨年秋からPOV-Rayで3DCGを再開したので、ふっと昔の画像を覗いてみたくなったのです。

bullet昔の画像はRGBベタ形式

1990年代の初めに使用していた3DCGソフトは、C-TRACEとその上位バージョンC-TRACE+というソフトで、その画像形式はRGBベタのイメージデータの先頭にこのソフト独自のヘッダーがついている形式です。データの互換性のために、C-TRACEの画像形式でファイル保存すると同時に、画像イメージ部分だけをRGBベタファイルとして取り出してファイル化し、ヘッダー部分に含まれる画像の幅・高さなどの情報をテキストファイルに取り出して保存していました。

RGBベタ形式と言うのは、画像の1ピクセル(ドット)をR(赤)の256階調、G(緑)の256階調、B(青)の256階調の3バイトで保存します。ピクセルをファイルへ保存するときの順序は、画像の左上をファイルの先頭にして、横方向に、画像の右下がファイルの最後になるような順序です。

bulletRGBベタ形式の画像を表示するソフトがない

フロッピーに入ったデータの大半ははテキストなのでエディターで読み出すことが出来ましたが、古いC-TRACEの独自形式の画像を読み出すソフトも、RGBベタ形式の画像を読み出すソフトもないことに気が付きました。

bullet画像ローダーを作ることにする

最も使い慣れた開発ツールDelphiで、画像を表示するプログラムを作ることにしました。
RGBベタファイルを1ピクセル分3バイトずつ読み出して、メモリ上にそのまま1バイトずつ書き込み、それをビットマップ画像を格納できるコンポーネント上に書き込むことで、表示するという方針です。

640*400ドットの画像の場合なら、模擬的に書くと、こんな具合。

for i:=0 to 399 do
begin
    for j:=0 to 639 do
    begin
        Seek( f, (640*i+j)*3 );
        BlockRead(f, Buf, SizeOf(Buf));
        Image^ := Buf[1];  inc(Image);
        Image^ := Buf[2];  inc(Image);
        Image^ := Buf[3];  inc(Image);
   end;
end;

bullet画像が上下反転?

ところが、表示してみると、画像の上下が反転している。うーん、一体どうなっているんだー。
いろいろ調べてみると、Windows標準のビットマップ形式(BMP形式=DIB形式)は、RGBベタ画像形式とは極端に異なるところがあるのが分かりました。

BMP形式とRGBベタ形式のイメージには次のような差があったのです。

RGBベタ・イメージ

つまり、RGBベタではイメージの左上を画像の始点として横方向にピクセルの並びを捉え、右下のピクセルがイメージの終点になります。ところが、BMP(DIB)形式では、左下を始点として、右上を終点として扱っているのです。

これが原因で、上下が反転してしまったのです。

早速次のように修正。

for i:=399 downto 0 do
begin
    for j:=0 to 639 do
    begin
        Seek( f, (640*i+j)*3 );
        BlockRead(f, Buf, SizeOf(Buf));
        Image^ := Buf[1];  inc(Image);
        Image^ := Buf[2];  inc(Image);
        Image^ := Buf[3];  inc(Image);
   end;
end;

これで、上下は正しく表示されました。

bullet色が変?

でも表示された画像の雰囲気がどこか変なのです。どうも色が不自然です。赤っぽいところが青っぽく、青く見えるはずのところが赤く見えているのです。どうも、赤と青の情報が 入れ替わっているようです。

またまた、調べてみると、BMP形式では、イメージ表示の際に、R(赤)G(緑)B(青)の3バイトの並びが、B(青)G(緑)R(赤)の並びであることが分かりました。

そこで再び修正。

for i:=399 downto 0 do
begin
    for j:=0 to 639 do
    begin
        Seek( f, (640*i+j)*3 );
        BlockRead(f, Buf, SizeOf(Buf));
        Image^ := Buf[3];  inc(Image);
        Image^ := Buf[2];  inc(Image);
        Image^ := Buf[1];  inc(Image);
   end;
end;

これで、色も正しく表示されるようになりました。

bulletBMP画像形式の不思議

ということで、Windows標準の画像形式(BMP形式=DIB形式)というのは、なんとも不可思議な形式であると言うことが分かりました。

戻る ホーム 上へ 進む