From 5fa756996028fc7ce6be943f3e47c10231dbed0d Mon Sep 17 00:00:00 2001 From: ubq323 Date: Sat, 6 Aug 2022 22:56:33 +0100 Subject: img --- img/better_disp.dat | 1 + img/better_disp.lua | 121 ++++++++++++++++++++++++++++++++++++++++++++++------ img/disp_common.lua | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++ img/driver.dat | 2 +- img/shitty_disp.dat | 1 + img/shitty_disp.lua | 116 ++----------------------------------------------- 6 files changed, 233 insertions(+), 127 deletions(-) create mode 100644 img/better_disp.dat create mode 100644 img/disp_common.lua create mode 100644 img/shitty_disp.dat (limited to 'img') 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] 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] 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} -- cgit v1.2.3