--//■■■■■■■■■■■■■■■■■■■■■■■■■
--//■ LEDデータ変換スクリプト - dLedSeqC用data出力 ■
--//■■■■■■■■■■■■■■■■■■■■■■■■■

--// * Fri Feb 27 21:11:43 JST 2015 Naoyuki Sawa
--// - 1st リリース。

--//輝度ビット数を定義します。
--// - 0=透明,1=消灯,2〜((2^DIMMER_BIT)-1)=点灯です。
--//   たとえば、「DIMMER_BIT=5」と定義した場合、以下のようになります:
--//
--//	DIMMER =   0 :      透明
--//	DIMMER =   1 :      消灯
--//	DIMMER =   2 :  1/30点灯
--//	DIMMER =   3 :  2/30点灯
--//	     〜     
--//	DIMMER =  30 : 29/30点灯
--//	DIMMER =  31 : 30/30点灯
--//
--// - LedConfig.luaで定義しても良かったのですが、頻繁に変更することは無いだろうと考え、LedConv.luaに含めました。
--//   LedConfig.luaで再定義して上書きしたり、「-e」オプションで変更することは可能です。
--//
DIMMER_BIT = 5

--//*************************************************************************
--//	最初に一度だけ呼び出される関数
--//*************************************************************************

function BEGIN()
	--//タブ区切りファイルから、LED定義を読み込む。
	LED = { }
	for line in io.lines(LED_FNAME) do
		local a = { }						--//┐
		for i in string.gmatch(line .. "\t", "(.-)" .. "\t") do	--//├タブ区切りでフィールド分割を行う。空フィールドも認める。
			table.insert(a, i)				--//│
		end							--//┘
		local vLed = { }
--//使わない	vLed.id     = assert(tonumber(a[1])) assert((vLed.id   >= 0) and (vLed.id <= (2^16)-1))	--//LED番号(0〜(2^16)-1))
		vLed.c      = assert(tonumber(a[2])) assert((vLed.c    == 1) or  (vLed.c  ==        3))	--//要素(1=単色LED,3=フルカラーLED)
--//使わない	vLed.name   = assert(tostring(a[3])) assert(#vLed.name ~= 0)				--//名称
		vLed.x      = assert(tonumber(a[4])) assert((vLed.x    >= 0) and (vLed.x  <= (2^16)-1))	--//取り込み矩形x
		vLed.y      = assert(tonumber(a[5])) assert((vLed.y    >= 0) and (vLed.y  <= (2^16)-1))	--//取り込み矩形y
		vLed.w      = assert(tonumber(a[6])) assert((vLed.w    >= 0) and (vLed.w  <= (2^16)-1))	--//取り込み矩形w
		vLed.h      = assert(tonumber(a[7])) assert((vLed.h    >= 0) and (vLed.h  <= (2^16)-1))	--//取り込み矩形h
--//使わない	vLed.symbol = assert(tostring(a[8]))	--//当スクリプトでは使用しない。これ以降は無視するので、何を書いても構わない。
		table.insert(LED, vLed)
	end
	--//輝度の最大値を求めます。
	assert((DIMMER_BIT >= 2) and (DIMMER_BIT <= 6))	--//7も可能ではあるが、LEDの特性上オーバースペックであろうから除外した。
	DIMMER_MAX = (2 ^ DIMMER_BIT) - 1
	--//出力ファイルを作成する。出力ファイルが指定されていなければ、標準出力へ出力する。
	if OUT_FNAME then
		OutFile = assert(io.open(OUT_FNAME, "w"))
	else
		OutFile = io.stdout
	end
end

--//*************************************************************************
--//	各フレームに対して、一度づつ呼び出される関数
--//*************************************************************************

function FRAME()
	local comma
	OutFile:write("data ")
	--//各LEDについて…
	for i, vLed in ipairs(LED) do
		--//輝度を取得する。
		local r, g, b = GetPixel(vLed.x + vLed.w / 2, vLed.y + vLed.h / 2)
		--//単色LEDならばc=1について,フルカラーLEDならばc=1,2,3について…
		for c = 1, vLed.c do
			local v = 0
			--///一要素でも0でなければ…
			if (r ~= 0) or (g ~= 0) or (b ~= 0) then
--//{{2015/11/12修正:単色LEDならばR,G,Bの内の最大輝度を取るべきところ、単純なミスでRの輝度を取ってしまっていた。修正した。
--//				    if (c == 1) then
--//					v = r
--//				elseif (c == 2) then
--//					v = g
--//				elseif (c == 3) then
--//					v = b
--//				else
--//					v = math.max(r, g, b)
--//				end
--//↓2015/11/12修正:単色LEDならばR,G,Bの内の最大輝度を取るべきところ、単純なミスでRの輝度を取ってしまっていた。修正した。
				if       (vLed.c == 3) then
					    if   (c == 1) then
						v = r
					elseif   (c == 2) then
						v = g
					else --//(c == 3)
						v = b
					end
				else --//(vLed.c == 1)
					v = math.max(r, g, b)
				end
--//}}2015/11/12修正:単色LEDならばR,G,Bの内の最大輝度を取るべきところ、単純なミスでRの輝度を取ってしまっていた。修正した。
				v = math.floor(v * DIMMER_MAX) + 1		--//[0,1]を[1,DIMMER_MAX]へ均等に変換する
				if v > DIMMER_MAX then v = DIMMER_MAX end	--//1が(DIMMER_MAX+1)に変換されるケースにのみ補正する
			end
			if (i ~= 1) or (c ~= 1) then
				OutFile:write(",")
			end
			    if DIMMER_MAX <=  9 then
				OutFile:write(string.format("%1d", v))
			elseif DIMMER_MAX <= 99 then
				OutFile:write(string.format("%2d", v))
			else
				OutFile:write(string.format("%3d", v))
			end
		end
	end
	OutFile:write("\n")
end

--//*************************************************************************
--//	最後に一度だけ呼び出される関数
--//*************************************************************************

function END()
	--//出力ファイルを閉じる。ただし、標準出力だった場合は閉じない。
	if OutFile ~= io.stdout then
		OutFile:close()
	end
end
