summaryrefslogtreecommitdiff
path: root/img/shitty_disp.lua
blob: 8bd1b610be74656b14ad750ea8db3d9e69bd750d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
-- bad displayment thing

local function color_dist(c1,c2)
	local total = 0
	for i=1,3 do total = total + (c1[i]-c2[i])^2 end
	return total
end

local function closest_palette_color(R,c)
	local closest = nil
	local closest_dist = 99999999
	for i=0,15 do
		local pc = {R.getPaletteColor(2^i)}
		local dist = color_dist(pc,c)
		if dist < closest_dist then
			closest = 2^i
			closest_dist = dist 
		end
	end
	return closest
end

local function average_color(pxlist)
	local count = #pxlist
	local tr,tg,tb = 0,0,0
	for _,px in ipairs(pxlist) do
		tr = tr + px[1]
		tg = tg + px[2]
		tb = tb + px[3]
	end
	return {tr/count,tg/count,tb/count}
end

local function sortby_r(pxlist) table.sort(pxlist,function(a,b) return a[1]<b[1] end) end
local function sortby_g(pxlist) table.sort(pxlist,function(a,b) return a[2]<b[2] end) end
local function sortby_b(pxlist) table.sort(pxlist,function(a,b) return a[3]<b[3] end) end

local function median_cut(pxlist,remaining)
	remaining = remaining or 4
	if remaining <= 0 then
		return {average_color(pxlist)}
	end
	local maxr,maxg,maxb = -1,-1,-1
	local minr,ming,minb = 999,999,999
	local max,min = math.max,math.min
	for _,px in ipairs(pxlist) do
		maxr = max(maxr,px[1])
		maxg = max(maxg,px[2])
		maxb = max(maxb,px[3])
		minr = min(minr,px[1])
		ming = min(ming,px[2])
		minb = min(minb,px[3])
	end
	local ranger,rangeg,rangeb = maxr-minr,maxg-ming,maxb-minb
	if ranger > rangeg then
		if ranger > rangeb then
			-- red
			sortby_r(pxlist)
		else
			-- blue
			sortby_b(pxlist)
		end
	else
		if rangeg > rangeb then
			-- green
			sortby_g(pxlist)
		else
			-- blue
			sortby_b(pxlist)
		end
	end
	local count = #pxlist
	local hcount = math.floor(count/2)

	local lhalf,uhalf = {},{}
	for i=1,hcount do
		lhalf[i] = pxlist[i]
	end
	for i=hcount+1,count do
		uhalf[i-hcount] = pxlist[i]
	end
	
	local lcols = median_cut(lhalf,remaining-1)
	local ucols = median_cut(uhalf,remaining-1)

	for i=1,#ucols do table.insert(lcols,ucols[i]) end
	return lcols
end

local function reset_palette(R)
	for i=0,15 do
		local cx = 2^i
		R.setPaletteColor(cx,term.nativePaletteColor(cx))
	end
end

local function improve_palette(R,img,w,h,imgx,imgy)
	local pxlist = {}
	local idx=1
	for px=imgx,imgx+w-1 do
		for py=imgy,imgy+h-1 do
			pxlist[idx] = img[py][px]
			idx = idx + 1
		end
	end
	local palette = median_cut(pxlist)
	assert(#palette==16,#palette.." doesn't equal 16")
	for i=0,15 do
		local pc = palette[i+1]
		R.setPaletteColor(2^i,table.unpack(pc))
	end
end
	


local function disp(R,img,scrx,scry,w,h,imgx,imgy)
	scrx = scrx or 1
	scry = scry or 1
	w = w or img.width
	h = h or img.height
	imgx = imgx or 1
	imgy = imgy or 1

	improve_palette(R,img,w,h,imgx,imgy)

	for offx=0,w-1 do
		for offy=0,h-1 do
			R.setCursorPos(scrx+offx,scry+offy)
			local icol = img[imgy+offy][imgx+offx]
			local pcol = closest_palette_color(R,icol)
			R.setBackgroundColor(pcol)
			R.write(" ")
		end
	end
end

return {disp=disp,color_dist=color_dist,closest_palette_color=closest_palette_color,reset_palette=reset_palette}