描画関連 - ソースコード
描画関連 - catsのホームページ
目次

ここには描画処理に関するプログラムのコードを載せています。

1 高速で使いやすいぼかし処理(平均化)
1.高速で使いやすいぼかし処理(平均化)
ソースコード

 現在のウィンドウのバッファにぼかし処理をかけます。標準命令のboxfと同じように使うことができます。ぼかし処理には平均化フィルタを使用し、処理部は高速化を図るために機械語で記述しました。機械語はC++で記述した平均化フィルタをコンパイルしたものです。C++内では、HSPから各種座標情報と、VRAMのアドレスを渡します。以下にC++のソースコードを書きます。

void AverageFilter(int bx, int by, int ex, int ey, unsigned char* vram, int wsx, int wsy)
{
	int bmp_w = (wsx * 3 + 3) / 4 * 4;
	int sum[3] = {0, 0, 0}, index, count, t;

	if (bx > ex) {
		t = bx;
		bx = ex;
		ex = t;
	}
	if (by > ey) {
		t = by;
		by = ey;
		ey = t;
	}
	if (bx < 0) bx = 0;
	if (by < 0) by = 0;
	if (ex > wsx) ex = wsx;
	if (ey > wsy) ey = wsy;

	for (int cy = by; cy < ey; cy++) {

		for (int cx = bx; cx < ex; cx++) {

			count = 0;
			for (int ccy = -1; ccy < 2; ccy++) {
				if (cy + ccy < 0 || cy + ccy >= wsy) continue;

				for (int ccx = -1; ccx < 2; ccx++) {
					if (cx + ccx < 0 || cx + ccx >= wsx) continue;

					index = (wsy - cy - ccy - 1) * bmp_w + (cx + ccx) * 3;
					for (int i = 0; i < 3; i++) {
						sum[i] += (int)*(vram + index + i);
					}

					count++;
				}

			}

			index = (wsy - cy - 1) * bmp_w + cx * 3;
			for (int i = 0; i < 3; i++) {
				*(vram + index + i) = (unsigned char)(sum[i] / count);
				sum[i] = 0;
			}

		}

	}
}

以下にHSPでのソースコードを書きます。

/*-------------------- ここからモジュール --------------------*/
#module mod_AF code
	#uselib "kernel32.dll"
		#func VirtualProtect "VirtualProtect" var, int, int, var
	// 機械語は一度だけ生成しておく
	#modinit local dummy
		dim code, 128
		VirtualProtect code, 512, 0x40, dummy
		code(0) = 0x83ec8b55, 0x456b34ec, 0xc083031c, 0xe2839903
		code(4) = 0xc1c20303, 0xe0c102f8, 0xd8458902, 0x00cc45c7
		code(8) = 0xc7000000, 0x0000d045, 0x45c70000, 0x000000d4
		code(12) = 0x08458b00, 0x7e10453b, 0x084d8b12, 0x8be44d89
		code(16) = 0x55891055, 0xe4458b08, 0x8b104589, 0x4d3b0c4d
		code(20) = 0x8b127e14, 0x55890c55, 0x14458be4, 0x8b0c4589
		code(24) = 0x4d89e44d, 0x087d8314, 0xc7077d00, 0x00000845
		code(28) = 0x7d830000, 0x077d000c, 0x000c45c7, 0x8b000000
		code(32) = 0x553b1055, 0x8b067e1c, 0x45891c45, 0x144d8b10
		code(36) = 0x7e204d3b, 0x20558b06, 0x8b145589, 0x45890c45
		code(40) = 0x8b09ebfc, 0xc183fc4d, 0xfc4d8901, 0x3bfc558b
		code(44) = 0x8d0f1455, 0x00000144, 0x8908458b, 0x09ebf845
		code(48) = 0x83f84d8b, 0x4d8901c1, 0xf8558bf8, 0x0f10553b
		code(52) = 0x0001228d, 0xe045c700, 0x00000000, 0xfff445c7
		code(56) = 0xebffffff, 0xf4458b09, 0x8901c083, 0x7d83f445
		code(60) = 0x8d0f02f4, 0x000000a8, 0x03fc4d8b, 0x0b78f44d
		code(64) = 0x03fc558b, 0x553bf455, 0xeb027c20, 0xf045c7d8
		code(68) = 0xffffffff, 0x458b09eb, 0x01c083f0, 0x83f04589
		code(72) = 0x7d02f07d, 0xf84d8b76, 0x78f04d03, 0xf8558b0b
		code(76) = 0x3bf05503, 0x027c1c55, 0x458bdceb, 0xfc452b20
		code(80) = 0x83f4452b, 0xaf0f01e8, 0x4d8bd845, 0xf04d03f8
		code(84) = 0x0303d16b, 0xdc4589c2, 0x00ec45c7, 0xeb000000
		code(88) = 0xec458b09, 0x8901c083, 0x7d83ec45, 0x1d7d03ec
		code(92) = 0x03184d8b, 0x558bdc4d, 0x04b60fec, 0xec4d8b11
		code(96) = 0xcc8d4403, 0x89ec558b, 0xebcc9544, 0xe0458bd4
		code(100) = 0x8901c083, 0x7be9e045, 0xe9ffffff, 0xffffff45
		code(104) = 0x2b204d8b, 0xe983fc4d, 0x4daf0f01, 0xf8556bd8
		code(108) = 0x89ca0303, 0x45c7dc4d, 0x000000e8, 0x8b09eb00
		code(112) = 0xc083e845, 0xe8458901, 0x03e87d83, 0x4d8b247d
		code(116) = 0x8d448be8, 0x7df799cc, 0x18558be0, 0x8bdc5503
		code(120) = 0x0488e84d, 0xe8558b0a, 0xcc9544c7, 0x00000000
		code(124) = 0xc9e9cdeb, 0xe9fffffe, 0xfffffea7, 0xc35de58b
	return
	
	// AverageFilter
	//    p1, p2 : 開始座標(X, Y)
	//    p3, p4 : 終端座標(X, Y)
	#modfunc AverageFilter int bx, int by, int ex, int ey, local dummy
		mref vram, 66
		mref bmscr, 67
		scr_w = bmscr(1)
		scr_h = bmscr(2)
		
		dim prm, 7
		prm = bx, by, ex, ey, varptr(vram), scr_w, scr_h
		
	return callfunc(prm, varptr(code), 7)
#global
/*-------------------- ここまでモジュール --------------------*/

	// モジュールを使用
	newmod af, mod_af

	screen 0, 640, 480, 4
		// 通常描画
		font "arial", 32
		color 128
		repeat 10
			mes "The Quick Brown Fox Jumps Over The Lazy Dog."
		loop
		
		// ぼかし処理
		repeat 5	; ぼかしレベル
			AverageFilter af, 128, 128, 320, 320
		loop
	
	// 再描画を忘れないこと
	redraw 1
stop

ぼかし処理を完了したあとは、redrawにより再描画することに注意してください。 また、高速化しているとはいえ、ループ内で何回も呼び出すのはナンセンスです。 あらかじめフィルタにかけたバッファを描画するようにしまあしょう。 なお、この関数では機械語内部で入力値のエラーをチェックしています。 描画できない領域が渡された場合、その領域はスキップされます。

参考文献

平均化フィルタを作る - [物理のかぎしっぽ]