減色保存



前回でBMPファイルを作成することは出来ました。
さてここからが問題。前回のようなただの保存ではまったく意味がないので、減色して保存してみましょう。
減色方法として近似色検索でピクセルデータを作っていく方法がありますが、これは非常に時間がかかり、かつ複雑なスクリプトになります。
一般的なのはこの近似色検索だそうですが、HSPでこんなのをやってるととても遅くなります。
これくらいは仕方がないことなのですが、もう少し高速化する方法はあります。
とりあえず私の方法は、1ドット1ドット走査してカラーテーブルを作りながら同時にピクセルデータを作成していく方法です。 こうすると近似色検索ではなく同色検索になり、かつ検索回数が減ります。
つまりはこういう過程になります。

1.1ピクセルの色を取得
2.カラーテーブルに同じ色が存在しなければカラーテーブルにその色を追加
3.その色のカラーテーブルの番号をピクセルデータとして書き込み
※繰り返し

という流れになります。
かなり大まかにしか書いてませんが、実際このひとつの処理がめちゃめちゃ難しかったりします。
これ以上は言葉では解説できませんので、ソースとコメントを見て理解してみてください。

;フルカラーモード専用

#module

#deffunc bmpsave2 str,int
	mref filename,32
	mref bit,1
	mref vram,66

	rast=winx*bit+31/32*4	;1走査線のバイト数
	bdsize=rast*winy	;ピクセルデータサイズ
	if bit<=8 : rq=1<<bit : else : rq=0	;RGBQUAD構造体の数
	bdstart=rq*4+54
	filesize=bdsize+(rq*4)+54	;ファイルサイズ
	sdim date,filesize	;実際のファイル内容

	;BITMAPFILEHEADER構造体
	wpoke date,0,0x4D42	;"BM"という文字列
	memcpy date,filesize,4,2	;ファイルサイズ
	;予約が4バイト
	memcpy date,bdstart,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,bit	;1ピクセルあたりのビット数
	;残りは0でOK

	;ピクセルデータ
	if rq {	;8ビット以下
		dim rgbquad,256	;RGBQUAD構造体配列
		bytetimes=8/bit	;1バイトに書き込む回数
		colnum=0	;カラーテーブルに登録された色数
		repeat winy
			cnt3=cnt
			bytecnt=0	;1バイトに書き込んだ回数
			bytedate=0	;1バイトの値
			writepoint=rast*cnt+bdstart	;書き込む場所
			repeat winx
				cnt2=cnt
				memcpy col,vram,3,0,cnt3*rast+cnt*3	;RGB値をコピー
				repeat colnum+1
					ct=cnt	;色の番号
					if cnt=colnum {	;同じ色が見つからなかった場合
						if colnum!=(1<<bit) {
							rgbquad.colnum=col	;色を登録
							colnum++
						}
						break
					}
					if col=rgbquad.cnt : break	;同じ色があった場合
				loop
				bytedate=ct<<(bytetimes-bytecnt-1*bit)|bytedate	;色番号をbitビット書き込む
				bytecnt++
				if bytecnt=bytetimes {	;1バイト分たまったら
					poke date,writepoint,bytedate	;書き込む
					bytedate=0	;1バイトの値を初期化
					bytecnt=0	;1バイトに書き込んだ回数を初期化
					writepoint++	;書き込みアドレスを1バイト進める
				}
			loop
			if bytecnt {	;1バイトたまらないまま1走査線終了してしまったとき
				poke date,writepoint,bytedate	;中途半端でも書き込む
			}
		loop
		memcpy date,rgbquad,rq*4,54	;カラーテーブル書き込み
	} else {	;フルカラー
		memcpy date,vram,bdsize,54	;VRAM直コピー
	}

	;保存
	bsave filename,date
return

#global

通常のbmpsave命令に加え、第2引数にビット数を指定することで減色保存することが出来ます。
24を指定するとフルカラー、8で256色、4で16色、2で4色、1でモノクロ(2色)で保存絵できるはずです。(たぶん)
ただこの方法だと限界色数以上の色を使っている場合、走査中に色数を超えたところから先は画像が崩れることを覚悟してください。
こういう場合は近似色検索で出すとまともになったりします。


前へ 戻る