(AHK)(AutiHotkey)(DIBの作り方、訂正とか修正とか最適化とか)

 前回の記事の → http://d.hatena.ne.jp/morakana/20090513/1242212019
訂正とか修正とか最適化とかです 笑)
まあ 黒色で作って リサイズした後 ToneDIB で 各輝度を持ち上げた方が やっぱ速くね? ということで ToneDIBを採用
指定色が黒色なら ToneDIBはスキップする仕様に
もし 「背景色は 圧倒的に白が多い!」というのなら 白で作って 各輝度を持ち下げてもいいかもね
;---------------------------------------------------------------------------------------------------------------------------------------------------------
; imgctl_NewDIB(NewWidth, NewHeight, R, G, B)     新規にDIBを作成して hDIBを返します
;---------------------------------------------------------------------------------------------------------------------------------------------------------
; 横:NewWidth 縦:NewHeight のサイズで 新規に DIBを生成します
; R G B に 輝度を設定する事で 塗りつぶす色を設定する事が出来ます
;
; BMPファイルのイメージを生成して MtoDIBに渡すことで DIBを生成しています
; 生成に成功すると DIBのハンドルが、 失敗すると 0が返ってきます
Imgctl_NewDIB(NewWidth, NewHeight, R = 0, G = 0, B = 0)
{
	BinDataImage := "0x42,0x4D,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"
	VarSetCapacity(buf, 58, 0x00)
	Loop Parse, BinDataImage, CSV
		NumPut((A_LoopField + 0), buf, (A_Index - 1), "UChar")
	If !(hNewDIB := Imgctl_MtoDIB(&buf, 58))
		Return 0
	If ( !R and !G and !B and Imgctl_ResizeDIB(hNewDIB, NewWidth, NewHeight) )
		Return hNewDIB
	If ( Imgctl_ResizeDIB(hNewDIB, NewWidth, NewHeight) and Imgctl_ToneDIB(hNewDIB, R, G, B) )
		Return hNewDIB
	Imgctl_DeleteDIB(hNewDIB)
	Return 0
}
;---------------------------------------------------------------------------------------------------------------------------------------------------------
; BOOL ToneDIB(HDIB hDIB, short rMove, short gMove, short bMove)
Imgctl_ToneDIB(hDIB, rMove, gMove, bMove)
{
	Return DllCall("imgctl.dll\ToneDIB", "UInt", hDIB, "Short", rMove, "Short", gMove, "Short", bMove, "Int")
}
;---------------------------------------------------------------------------------------------------------------------------------------------------------
; BOOL ResizeDIB(HDIB hDIB, long lWidth, long lHeight)
Imgctl_ResizeDIB(hDIB, NewWidth, NewHeight)
{
	Return DllCall("imgctl.dll\ResizeDIB", "UInt", hDIB, "Int", NewWidth, "Int", NewHeight, "Int")
}
;---------------------------------------------------------------------------------------------------------------------------------------------------------
; HDIB MtoDIB(const void *pBuffer, DWORD dwBufSize)
Imgctl_MtoDIB(pBuffer, BufSize)
{
	Return DllCall("imgctl.dll\MtoDIB", "UInt", pBuffer, "UInt", BufSize, "UInt")
}
;---------------------------------------------------------------------------------------------------------------------------------------------------------



 ついでに Imgctl_RepaintDIB関数も できるだけ最適化
ToneDIBともベンチ対決させたので 出来るだけ効率よくしてみました
;---------------------------------------------------------------------------------------------------------------------------------------------------------
; BOOL RepaintDIB(HDIB hDIB, const REPAINTINFO *repis, DWORD dwRepaintNum)
;
; 注意 : REPAINTINFO を 文字列で設定するように変更しました
;
; 白 を 黒 に 置き換える場合は "255,255,255-0,0,0" と書きます
; 16進数表記でも表記可能です "0xff,0xff,0xff-0x0,0x0,0x0"
; 
; 色の置き換えを複数個指定したい場合は | で区切ります
; 白 を 黒 に 黒 を 緑 に 赤 を 青 に 置き換える時は
; "255,255,255-0,0,0|0,0,0-0,255,0|255,0,0-0,0,255" と書きます
;
Imgctl_RepaintDIB(hDIB, RepaintInformation)
{
	Num := 0
	Arr := 0
	Loop, Parse, RepaintInformation, |
	{
		Num += 1
		Loop, Parse, A_LoopField, -
		{
			Loop, Parse, A_LoopField, CSV
			{
				Arr += 1
				[%Num%][%Arr%] := A_LoopField
			}
		}
		Arr := 0
	}
	VarSetCapacity(RI, (Num * 8), 0x00)
	Loop, %Num%
	{
		Offset := (A_Index - 1) * 8
		NumPut(([%A_Index%][6] << 48) + ([%A_Index%][5] << 40) + ([%A_Index%][4] << 32) + ([%A_Index%][3] << 16) + ([%A_Index%][2] << 8) + [%A_Index%][1], RI, Offset, "UInt64")
	}
	Return DllCall("imgctl.dll\RepaintDIB", "UInt", hDIB, "UInt", &RI, "UInt", Num, "Int")
}
;---------------------------------------------------------------------------------------------------------------------------------------------------------

 今回の ケースをシミュレートして UChar と UInt と UInt64 でも ベンチ対決させてみました
結果を言えば UInt64が一番早かったので それを採用
具体的には 「UCharで6回書き込み」「UIntで2回書き込み」「UInt64で1回書き込み」(結果は全て同じ)の3種を
10000回実行するのに掛かる時間を 5回とって それの 平均値を出しました
結果は UChar : UInt : UInt64 = 1 : 0.44 : 0.28 と 約3倍超えに!
まぁ ループしない限り 体感時間は変わりませんけどなにか? 笑)
	a := 0x11
	b := 0x22
	c := 0x33
	d := 0x44
	e := 0x55
	f := 0x66
	VarSetCapacity(buf, 8, 0x00)
	tt := 0
	Loop, 5
	{
		tc := DllCall("kernel32.dll\GetTickCount")
		Loop, 10000
		{
			NumPut(a, buf, 0, "UChar")
			NumPut(b, buf, 1, "UChar")
			NumPut(c, buf, 2, "UChar")
			NumPut(d, buf, 4, "UChar")
			NumPut(e, buf, 5, "UChar")
			NumPut(f, buf, 6, "UChar")
		}
		tt += (DllCall("kernel32.dll\GetTickCount") - tc)
	}
	MsgBox,% tt / 5
	tt := 0
	Loop, 5
	{
		tc := DllCall("kernel32.dll\GetTickCount")
		Loop, 10000
		{
			NumPut((c << 16) + (b << 8) + a, buf, 0, "UInt")
			NumPut((f << 16) + (e << 8) + d, buf, 4, "UInt")
		}
		tt += (DllCall("kernel32.dll\GetTickCount") - tc)
	}
	MsgBox,% tt / 5
	tt := 0
	Loop, 5
	{
		tc := DllCall("kernel32.dll\GetTickCount")
		Loop, 10000
		{
			NumPut( (f << 48) + (e << 40)  + (d << 32) + (c << 16) + (b << 8) + a, buf, 0, "UInt64")
		}
		tt += (DllCall("kernel32.dll\GetTickCount") - tc)
	}
	MsgBox,% tt / 5