BMPファイルの自作



BMPファイルを出力するにはbmpsave命令があります。
しかしbmpsave命令が出力するのは常にフルカラービットマップなので、ファイルサイズを減らしたりしたいときに不便です。(減色ソフトはいっぱいあるけど)
256色以下に減色することが出来ればそれなりの軽量化が見込めます。
どうやって減色するかというと、結局自分でピクセルデータを作り、ファイルを作り出すしかないわけです。
BMPファイルの構造は以下のとおりです。

・BITMAPFILEHEADER構造体
 2バイト : "BM"という文字列
 4バイト : ファイルサイズ
 2バイト : 予約
 2バイト : 予約
 4バイト : ピクセルデータの開始位置

ビットマップファイルのヘッダ部です。14バイトという微妙な大きさ…。

・BITMAPINFOHEADER構造体
 4バイト : 構造体サイズ(40)
 4バイト : ビットマップの幅
 4バイト : ビットマップの高さ
 2バイト : 面の数(1)
 2バイト : 1ピクセルあたりのビット数
 4バイト : 圧縮形式(0)
 4バイト : 画像のバイト数(0)
 4バイト : 解像度x(0でいい?)
 4バイト : 解像度y(上に同じ)
 4バイト : カラーテーブルの数(0でいい)
 4バイト : 重要な色の数(0でいい)

ビットマップの情報を持つ構造体です。40バイトありますが殆ど0でいいみたいです。

・RGBQUAD構造体
 1バイト : 青成分の値(0〜255)
 1バイト : 緑成分の値(0〜255)
 1バイト : 赤成分の値(0〜255)
 1バイト : 予約

256色以下の場合のカラーテーブルです。これを色数分作っておきます。
フルカラーの場合は存在しません。

・ピクセルデータ

ピクセルデータはVRAMを基に作成します。フルカラーの場合(HSPウィンドウがフルカラーモード)はVRAM(mref命令で取得)をそのままコピーして使えます。
注意すべき点は、ピクセルデータ1走査線分(横一列)で使用するバイト数は4の倍数でなければなりません。
4バイト境界にない場合は、4バイト境界になるように少し付け足されます。この部分をパディングといいます。
このパディングが厄介で、ファイルサイズの計算をややこしくします。

以上の要素を全てつなぎ合わせたものを保存すればBMPファイルの出来上がりです。

これらの情報はここの引用です。

しかし減色処理は非常に厄介です。いきなり作り始めるとわかりにくいので、まずはbmpsaveと同じような命令を、 つまりフルカラーのBMPファイルを作成することから始めます。

以下がbmpsaveと同じような命令のソース。(フルカラーモードでしか動作しないためbmpsave命令以下だけど)

;フルカラーモード専用

#module

#deffunc bmpsave2 str
	mref filename,32
	mref vram,66

	bdsize=winx*24+31/32*4*winy	;ピクセルデータサイズ
	filesize=bdsize+54	;ファイルサイズ
	sdim date,filesize	;実際のファイル内容

	;BITMAPFILEHEADER構造体
	wpoke date,0,0x4D42	;"BM"という文字列
	memcpy date,filesize,4,2	;ファイルサイズ
	;予約が4バイト
	value=54 : memcpy date,value,4,10	;ピクセルデータの開始位置までのバイト数

	;BITMAPINFOHEADER構造体
	value=40 : memcpy date,value,4,14	;BITMAPINFOHEADER構造体サイズ
	value=winx : memcpy date,value,4,18	;ビットマップの幅
	value=winy : memcpy date,value,4,22	;ビットマップの高さ
	wpoke date,26,1	;カラープレーン
	wpoke date,28,24	;1ピクセルあたりのビット数
	;残りは0でOK

	;ピクセルデータ
	memcpy date,vram,bdsize,54

	;保存
	bsave filename,date
return

#global

順を追ってみていけばわかるはず。初めにBITMAPFILEHEADER構造体、次にBITMAPINFOHEADER構造体、ピクセルデータを変数に書き込んでいきます。 フルカラーの場合RGBQUAD構造体は存在しません。
最初のピクセルデータサイズの計算式はパディングを含めたサイズを計算する公式だと思ってください。ファイルサイズ計算の方の+54というのはBITMAPFILEHEADER構造体と BITMAPINFOHEADER構造体を足したサイズです。
2バイト書き込みの場合はwpoke命令が使えますが、4バイトになるとちょっときついですよね。 wpoke命令2回でがんばって書き込むことも出来ますが、簡単な方法としてmemcpy命令があります。 これなら4バイト書き込みは簡単なんですが、memcpy命令は変数同士でなければならないので、ここではダミー変数 valueを使用して書き込んでいます。
ピクセルデータですが、フルカラーの場合VRAMをそのまま読み出せばそのままでOKです。
そしてそれらを最後に保存…という手順で完成になります。

とりあえずここまではbmpsave命令以下なので何の意味もありません。
次に減色方法をやりますが、おそらく理解は難しいと思います。


戻る 次へ