summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--img/better_disp.dat1
-rw-r--r--img/better_disp.lua121
-rw-r--r--img/disp_common.lua119
-rw-r--r--img/driver.dat2
-rw-r--r--img/shitty_disp.dat1
-rw-r--r--img/shitty_disp.lua116
6 files changed, 233 insertions, 127 deletions
diff --git a/img/better_disp.dat b/img/better_disp.dat
new file mode 100644
index 0000000..797cd18
--- /dev/null
+++ b/img/better_disp.dat
@@ -0,0 +1 @@
+dep img/disp_common
diff --git a/img/better_disp.lua b/img/better_disp.lua
index d7b59c1..1d36f7a 100644
--- a/img/better_disp.lua
+++ b/img/better_disp.lua
@@ -1,3 +1,5 @@
+local disp_common = require("disp_common")
+
-- a vlorb consists of six gromlings[A
-- 1 2
-- 4 8
@@ -22,10 +24,102 @@ local function vlorb(onc,offc, g1,g2,g3,g4,g5,g6)
return textc,bgc,string.char(vlorbchar)
end
-local function should_be_on(col)
- return col[1]+col[2]+col[3] > 1.5
+local function all_palette_distances(R)
+ local out = {}
+ for a=0,15 do
+ for b = 0,15 do
+ local ia=2^a
+ local ib=2^b
+ local ca = R.getPaletteColor(ia)
+ local cb = R.getPaletteColor(ib)
+ local dist = disp_common.color_dist(ca,cb)
+ out[ia][ib] = dist
+ end
+ end
+ return out
+end
+
+local function list_contains(list,val)
+ for _,v in ipairs(list) do
+ if v == val then return true end
+ end
+ return false
end
+-- R, lPx_gromlings, l_pdists -> lCx_gromlings
+local function adjust_to_2_colors(R,gromlings,pdists)
+ -- gromlings goes 1 2 3 4 5 6
+ -- compress the 6 pixels to just 2 colors
+ -- return the list of cidxs
+ local gromling_colors = {}
+ for i,c in ipairs(gromlings) do
+ gromling_colors[i] = disp_common.closest_palette_color(R,c)
+ end
+
+ local all_current_colors = {}
+ local ncolors = 0
+ for _,cidx in ipairs(gromling_colors) do
+ all_current_colors[cidx] = true
+ ncolors = ncolors+1
+ end
+
+ while ncolors > 2 do
+ -- merge closest two colors until there are only 2 distinct ones left
+ local best_dist = 9999
+ local best_a = nil
+ local best_b = nil
+ for a in pairs(all_current_colors) do
+ for b in pairs(all_current_colors) do
+ if a ~= b then
+ local dist = pdists[a][b]
+ if dist < best_dist then
+ best_dist = dist
+ best_a = a
+ best_b = b
+ end
+ end
+ end
+ end
+
+ -- todo: be cleverer when deciding whether to merge a into b, or b into a
+ -- currently just merge b into a
+ assert(best_a and best_b and best_a ~= best_b)
+ all_current_colors[best_b] = false
+ ncolors=ncolors-1
+ for gidx,col in ipairs(gromling_colors) do
+ if col == best_b then gromling_colors[gidx] = best_a end
+ end
+ end
+
+ return gromling_colors
+end
+
+local function gromling_list_to_vlorb(gromling_colors)
+ -- takes list of cidxs
+ local ca = nil
+ local cb = nil
+ local gs = {}
+ for i,col in ipairs(gromling_colors) do
+ if col == ca then
+ gs[i] = true
+ elseif col == cb then
+ gs[i] = false
+ else
+ if not ca then
+ ca = col
+ gs[i] = true
+ elseif not cb then
+ cb = col
+ gs[i] = false
+ else
+ error("third gromling color in vlorb")
+ end
+ end
+ end
+ return ca,cb,table.unpack(gs)
+end
+
+
-- todo: refactor common stuff into a common file
local function disp(R,img,scrx,scry,w,h,imgx,imgy)
-- w and h are image coords
@@ -36,6 +130,9 @@ local function disp(R,img,scrx,scry,w,h,imgx,imgy)
imgx = imgx or 1
imgy = imgy or 1
+ disp_common.improve_palette(R,img,w,h,imgx,imgy)
+ local pdists=all_palette_distances(R)
+
local sw = math.ceil(w/2)
local sh = math.ceil(h/3)
@@ -44,23 +141,21 @@ local function disp(R,img,scrx,scry,w,h,imgx,imgy)
local ioffx=soffx*2
local ioffy=soffy*3
R.setCursorPos(scrx+soffx,scry+soffy)
- local gs = {}
+ local lPx_gromlings = {}
for goffy=0,2 do
for goffx=0,1 do
- local ic = img[imgy+ioffy+goffy][imgx+ioffx+goffx] or {0,0,0}
- table.insert(gs,should_be_on(ic))
+ local px = img[imgy+ioffy+goffy][imgx+ioffx+goffx] or {0,0,0}
+ table.insert(lPx_gromlings,px)
end
end
- local tc,bc,ch = vlorb(colors.white,colors.black,table.unpack(gs))
- R.setTextColor(tc)
- R.setBackgroundColor(bc)
- R.write(ch)
+
+ local lCx_gromlings = adjust_to_2_colors(lPx_gromlings)
+ local textc,bgc,vlorbchar = vlorb(gromling_list_to_vlorb(lCx_gromlings))
+ R.setTextColor(textc)
+ R.setBackgroundColor(bgc)
+ R.write(vlorbchar)
end
end
end
-
-
-
-
return {vlorb=vlorb,disp=disp}
diff --git a/img/disp_common.lua b/img/disp_common.lua
new file mode 100644
index 0000000..5c46b94
--- /dev/null
+++ b/img/disp_common.lua
@@ -0,0 +1,119 @@
+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
+
+return {
+ color_dist=color_dist,
+ closest_palette_color=closest_palette_color,
+ average_color=average_color,
+ median_cut=median_cut,
+ reset_palette=reset_palette,
+ improve_palette=improve_palette,
+}
diff --git a/img/driver.dat b/img/driver.dat
index d1e4787..27e1798 100644
--- a/img/driver.dat
+++ b/img/driver.dat
@@ -1,2 +1,2 @@
-dep util img/shitty_disp img/load_pnm
+dep util img/shitty_disp img/load_pnm img/better_disp
file img/driver.lua img/walter.pnm
diff --git a/img/shitty_disp.dat b/img/shitty_disp.dat
new file mode 100644
index 0000000..797cd18
--- /dev/null
+++ b/img/shitty_disp.dat
@@ -0,0 +1 @@
+dep img/disp_common
diff --git a/img/shitty_disp.lua b/img/shitty_disp.lua
index 8bd1b61..ea9681b 100644
--- a/img/shitty_disp.lua
+++ b/img/shitty_disp.lua
@@ -1,116 +1,6 @@
-- 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 disp_common = require("disp_common")
+local improve_palette,closest_palette_color = disp_common.improve_palette,disp_common.closest_palette_color
local function disp(R,img,scrx,scry,w,h,imgx,imgy)
@@ -134,4 +24,4 @@ local function disp(R,img,scrx,scry,w,h,imgx,imgy)
end
end
-return {disp=disp,color_dist=color_dist,closest_palette_color=closest_palette_color,reset_palette=reset_palette}
+return {disp=disp}