Advertisement
Guest User

Untitled

a guest
Feb 19th, 2018
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.34 KB | None | 0 0
  1. local gpu = require("component").gpu
  2. local png = require("libPNGimage")
  3. local unicode = require("unicode")
  4. local computer = require("computer")
  5. local bit32 = require("bit32")
  6.  
  7. local util = {}
  8. function util.cached1arg(func, entries, pos)
  9. local cache = {}
  10. local count = 0
  11. return function(...)
  12. local arg = select(pos, ...)
  13. if cache[arg] then
  14. return cache[arg]
  15. else
  16. if count == entries then
  17. cache[next(cache)] = nil
  18. else
  19. count = count + 1
  20. end
  21. local out = func(...)
  22. cache[arg] = out
  23. return out
  24. end
  25. end
  26. end
  27.  
  28. do
  29. util.palette = {}
  30.  
  31. local extract = function(color)
  32. color = color % 0x1000000
  33. local r = math.floor(color / 0x10000)
  34. local g = math.floor((color - r * 0x10000) / 0x100)
  35. local b = color - r * 0x10000 - g * 0x100
  36. return r, g, b
  37. end
  38. util.palette.extract = extract
  39.  
  40. local function delta(color1, color2)
  41. local r1, g1, b1 = extract(color1)
  42. local r2, g2, b2 = extract(color2)
  43. local dr = r1 - r2
  44. local dg = g1 - g2
  45. local db = b1 - b2
  46. return (0.2126 * dr^2 +
  47. 0.7152 * dg^2 +
  48. 0.0722 * db^2)
  49. end
  50. util.palette.delta = delta
  51.  
  52. local function t1deflate(palette, color)
  53. for idx = 1, #palette, 1 do
  54. if palette[idx] == color then
  55. return idx - 1
  56. end
  57. end
  58.  
  59. local idx, minDelta
  60. for i = 1, #palette, 1 do
  61. local d = delta(palette[i], color)
  62. if not minDelta or d < minDelta then
  63. idx, minDelta = i, d
  64. end
  65. end
  66.  
  67. return idx - 1
  68. end
  69.  
  70. local function t1inflate(palette, index)
  71. return palette[index + 1]
  72. end
  73.  
  74. local function generateT1Palette(secondColor)
  75. local palette = {
  76. 0x000000,
  77. secondColor
  78. }
  79.  
  80. palette.deflate = util.cached1arg(t1deflate, 128, 2)
  81. palette.inflate = t1inflate
  82.  
  83. return palette
  84. end
  85.  
  86. util.palette.t1 = generateT1Palette()
  87.  
  88. local t2deflate = t1deflate
  89. local t2inflate = t1inflate
  90.  
  91. local function generateT2Palette()
  92. local palette = {0xFFFFFF, 0xFFCC33, 0xCC66CC, 0x6699FF,
  93. 0xFFFF33, 0x33CC33, 0xFF6699, 0x333333,
  94. 0xCCCCCC, 0x336699, 0x9933CC, 0x333399,
  95. 0x663300, 0x336600, 0xFF3333, 0x000000}
  96.  
  97. palette.deflate = util.cached1arg(t2deflate, 128, 2)
  98. palette.inflate = t2inflate
  99.  
  100. return palette
  101. end
  102.  
  103. util.palette.t2 = generateT2Palette()
  104.  
  105. local t3inflate = t2inflate
  106.  
  107. local RCOEF = (6 - 1) / 0xFF
  108. local GCOEF = (8 - 1) / 0xFF
  109. local BCOEF = (5 - 1) / 0xFF
  110.  
  111. local t3deflate = function(palette, color)
  112. local paletteIndex = palette.t2deflate(palette, color)
  113. for i = 1, #palette, 1 do
  114. if palette[i] == color then
  115. return paletteIndex
  116. end
  117. end
  118.  
  119. local r, g, b = extract(color)
  120. local idxR = math.floor(r * RCOEF + 0.5)
  121. local idxG = math.floor(g * RCOEF + 0.5)
  122. local idxB = math.floor(b * RCOEF + 0.5)
  123. local deflated = 16 + idxR * 40 + idxG * 5 + idxB
  124. if (delta(t3inflate(palette, deflated % 0x100), color) <
  125. delta(t3inflate(palette, paletteIndex % 0x100), color)) then
  126. return deflated
  127. else
  128. return paletteIndex
  129. end
  130. end
  131.  
  132. local function generateT3Palette()
  133. local palette = {}
  134.  
  135. for i = 1, 16, 1 do
  136. palette[i] = 0xFF * i / (16 + 1) * 0x10101
  137. end
  138.  
  139. for idx = 16, 255, 1 do
  140. local i = idx - 16
  141. local iB = i % 5
  142. local iG = math.floor(i / 5) % 8
  143. local iR = math.floor(i / 5 / 8) % 6
  144. local r = math.floor(iR * 0xFF / (6 - 1) + 0.5)
  145. local g = math.floor(iG * 0xFF / (8 - 1) + 0.5)
  146. local b = math.floor(iB * 0xFF / (5 - 1) + 0.5)
  147. palette[idx + 1] = r * 0x10000 + g * 0x100 + b
  148. end
  149.  
  150. palette.deflate = util.cached1arg(t3deflate, 128, 2)
  151. palette.t2deflate = util.cached1arg(t2deflate, 128, 2)
  152. palette.inflate = t3inflate
  153.  
  154. return palette
  155. end
  156.  
  157. util.palette.t3 = generateT3Palette()
  158. end
  159.  
  160. local dirty = {}
  161.  
  162. for i = 0, 16 * 5 - 1 do
  163. dirty[i] = true
  164. end
  165.  
  166. local function isDirty(idx)
  167. return not not dirty[idx]
  168. end
  169.  
  170. local function setDirty(idx)
  171. dirty[idx] = true
  172. end
  173.  
  174. local function clearDirty(idx)
  175. dirty[idx] = nil
  176. end
  177.  
  178. local function clearDirtyFull()
  179. dirty = {}
  180. end
  181.  
  182. local buffer = {}
  183.  
  184. for i = 1, 3 * 160 * 50, 3 do
  185. buffer[i] = util.palette.t3:deflate(0x000000)
  186. buffer[i + 1] = util.palette.t3:deflate(0xffffff)
  187. buffer[i + 2] = " "
  188. end
  189.  
  190. local function index(x, y)
  191. return 3 * x + 480 * y + 1
  192. end
  193.  
  194. local function set(x, y, bg, fg, char)
  195. local i = index(x, y)
  196. buffer[i] = util.palette.t3:deflate(bg)
  197. buffer[i + 1] = util.palette.t3:deflate(fg)
  198. buffer[i + 2] = char
  199. setDirty(math.floor(x / 10), math.floor(y / 10))
  200. end
  201.  
  202. local cbg = gpu.getBackground()
  203. local cfg = gpu.getForeground()
  204.  
  205. local function setBg(bg)
  206. if bg ~= cbg then
  207. gpu.setBackground(bg)
  208. cbg = bg
  209. end
  210. end
  211.  
  212. local function setFg(fg)
  213. if fg ~= cfg then
  214. gpu.setForeground(fg)
  215. cfg = fg
  216. end
  217. end
  218.  
  219.  
  220. local function flushline(lops, ops, bg, fg, cs, x, y)
  221. if #cs > 0 then
  222. local sp = bit32.lshift(y, 8) + x
  223. local t = {bit32.lshift(bg, 8) + fg, cs, sp}
  224. lops[sp + unicode.wlen(cs)] = t
  225. table.insert(ops, t)
  226. end
  227. end
  228.  
  229. local function flushrect(ops, bg, fg, c, x, y)
  230. table.insert(ops, {r = true, bit32.lshift(bg, 8) + fg, c, x, y})
  231. end
  232.  
  233. local function render()
  234. local lops = {}
  235. local ops = {}
  236.  
  237. for block = 0, 16 * 5 - 1 do
  238. local sx = block % 16 * 10
  239. local sy = math.floor(block / 16) * 10
  240.  
  241. if isDirty(block) then
  242. local head = index(sx, sy)
  243. local rbg, rfg, rc = buffer[head], buffer[head + 1], buffer[head + 2]
  244. local rect = true
  245. for x = sx, sx + 9 do
  246. for y = sy, sy + 9 do
  247. local i = index(x, y)
  248. local bg = buffer[i]
  249. local fg = buffer[i + 1]
  250. local c = buffer[i + 2]
  251.  
  252. if bg ~= rbg or fg ~= rfg or c ~= rc then
  253. rect = false
  254. break
  255. end
  256. end
  257. end
  258.  
  259. if rect then
  260. flushrect(ops, rbg, rfg, rc, sx, sy)
  261. else
  262. for y = sy, sy + 9 do
  263. local head = index(sx, y)
  264. local lx, lbg, lfg, lcs = sx, buffer[head], buffer[head + 1], ""
  265.  
  266. for x = sx, sx + 9 do
  267. local i = index(x, y)
  268. local bg = buffer[i]
  269. local fg = buffer[i + 1]
  270. local c = buffer[i + 2]
  271.  
  272. if bg == lbg and fg == lfg then
  273. lcs = lcs .. c
  274. else
  275. flushline(lops, ops, lbg, lfg, lcs, lx, y)
  276. lx, lbg, lfg, lcs = x, bg, fg, c
  277. end
  278. end
  279.  
  280. flushline(lops, ops, lbg, lfg, lcs, lx, y)
  281. end
  282. end
  283. end
  284. end
  285.  
  286. local out = {}
  287.  
  288. for i, op in ipairs(ops) do
  289. if not op.r then
  290. local prec = lops[op[3]]
  291. if prec and prec[1] == op[1] then
  292. local t = {op[1], prec[2] .. op[2], prec[3]}
  293. lops[op[3]] = nil
  294. lops[op[3] + unicode.wlen(op[2])] = t
  295. table.insert(out, t)
  296. else
  297. table.insert(out, op)
  298. end
  299. else
  300. table.insert(out, op)
  301. end
  302. end
  303.  
  304. table.sort(out, function(rhs, lhs) return lhs[1] < rhs[1] end)
  305.  
  306. for _, op in ipairs(out) do
  307. setBg(util.palette.t3:inflate(bit32.rshift(op[1], 8)))
  308. setFg(util.palette.t3:inflate(bit32.band(op[1], 0xff)))
  309.  
  310. if op.r then
  311. gpu.fill(op[3] + 1, op[4] + 1, 10, 10, op[2])
  312. else
  313. gpu.set(bit32.band(op[3], 0xff) + 1, bit32.rshift(op[3], 8) + 1, op[2])
  314. end
  315. end
  316. end
  317.  
  318. local lastYield = computer.uptime()
  319. local function tlwyGuard()
  320. if computer.uptime() - lastYield > 3 then
  321. os.sleep(0)
  322. end
  323. end
  324.  
  325. local image = png.newFromFile(...)
  326.  
  327. local r, g, b, bg, fg
  328. for x = 0, image.ihdr.width - 1 do
  329. for y = 0, image.ihdr.height - 1, 2 do
  330. r, g, b = image:getPixel(x, y)
  331. if not r or not g or not b then
  332. bg = 0x000000
  333. else
  334. bg = bit32.lshift(r, 16) + bit32.lshift(g, 8) + b
  335. end
  336.  
  337. r, g, b = image:getPixel(x, y + 1)
  338. if not r or not g or not b then
  339. fg = 0x000000
  340. else
  341. fg = bit32.lshift(r, 16) + bit32.lshift(g, 8) + b
  342. end
  343.  
  344. set(x, math.floor(y / 2), fg, bg, "▄")
  345. end
  346. tlwyGuard()
  347. end
  348.  
  349. local start = computer.uptime()
  350. render()
  351. local elapsed = computer.uptime() - start
  352. print("elapsed", elapsed)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement