Advertisement
Guest User

Untitled

a guest
Feb 20th, 2018
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.44 KB | None | 0 0
  1. local gpu = require("component").gpu
  2. local png = require("png")
  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. local function writeFillInstruction(instructions, textdata, fills, x, y,
  220. bg, fg, char)
  221. if not instructions[bg] then
  222. instructions[bg] = {}
  223. textdata[bg] = {}
  224. end
  225.  
  226. if not instructions[bg][fg] then
  227. instructions[bg][fg] = {}
  228. textdata[bg][fg] = {}
  229. end
  230.  
  231. if not fills[bg] then
  232. fills[bg] = {}
  233. end
  234.  
  235. if not fills[bg][fg] then
  236. fills[bg][fg] = {}
  237. end
  238.  
  239. local i = #instructions[bg][fg] + 1
  240. instructions[bg][fg][i] = x * 0x100 + y
  241. textdata[bg][fg][i] = char
  242. fills[bg][fg][i] = true
  243. end
  244.  
  245. local function writeLineInstruction(instructions, textdata, lines,
  246. x, y, bg, fg, line)
  247. if not instructions[bg] then
  248. instructions[bg] = {}
  249. textdata[bg] = {}
  250. end
  251.  
  252. if not instructions[bg][fg] then
  253. instructions[bg][fg] = {}
  254. textdata[bg][fg] = {}
  255. end
  256.  
  257. local pos = x * 0x100 + y
  258. local bgfg = bg * 0x100 + fg
  259.  
  260. if lines[2 * pos] and lines[2 * pos] == bgfg then
  261. local i = lines[2 * pos + 1]
  262. textdata[bg][fg][i] = textdata[bg][fg][i] .. line
  263. lines[2 * pos] = nil
  264. lines[2 * pos + 1] = nil
  265. lines[2 * (pos + unicode.wlen(line))] = bgfg
  266. lines[2 * (pos + unicode.wlen(line)) + 1] = i
  267. else
  268. local i = #instructions[bg][fg] + 1
  269. instructions[bg][fg][i] = pos
  270. textdata[bg][fg][i] = line
  271. lines[2 * pos] = bgfg
  272. lines[2 * pos + 1] = i
  273. end
  274. end
  275.  
  276. local function render()
  277. local instructions = {}
  278. local textdata = {}
  279. local fills = {}
  280. local lines = {}
  281.  
  282. for block = 0, 16 * 5 - 1 do
  283. local sx = block % 16 * 10
  284. local sy = math.floor(block / 16) * 10
  285.  
  286. if not isDirty(block) then
  287. goto continue
  288. end
  289.  
  290. local head = index(sx, sy)
  291. local rbg, rfg, rc = buffer[head], buffer[head + 1], buffer[head + 2]
  292. local rect = true
  293. for x = sx, sx + 9 do
  294. for y = sy, sy + 9 do
  295. local i = index(x, y)
  296. local bg = buffer[i]
  297. local fg = buffer[i + 1]
  298. local c = buffer[i + 2]
  299.  
  300. if bg ~= rbg or fg ~= rfg or c ~= rc then
  301. rect = false
  302. break
  303. end
  304. end
  305. end
  306.  
  307. if rect then
  308. writeFillInstruction(instructions, textdata, fills, sx, sy, rbg, rfg, rc)
  309. goto continue
  310. end
  311.  
  312. for y = sy, sy + 9 do
  313. local head = index(sx, y)
  314. local linex, linebg, linefg, line = sx, buffer[head], buffer[head + 1], {}
  315.  
  316. for x = sx, sx + 9 do
  317. local i = index(x, y)
  318. local bg = buffer[i]
  319. local fg = buffer[i + 1]
  320. local c = buffer[i + 2]
  321.  
  322. if bg == linebg and (fg == linefg or c == " ") then
  323. table.insert(line, c)
  324. else
  325. writeLineInstruction(instructions, textdata, lines, linex, y,
  326. linebg, linefg, table.concat(line))
  327. linex, linebg, linefg, line = x, bg, fg, {c}
  328. end
  329. end
  330.  
  331. if #line > 0 then
  332. writeLineInstruction(instructions, textdata, lines, linex, y,
  333. linebg, linefg, table.concat(line))
  334. end
  335. end
  336.  
  337. ::continue::
  338. end
  339.  
  340. for background, foregrounds in pairs(instructions) do
  341. setBg(util.palette.t3:inflate(background))
  342.  
  343. for foreground, chain in pairs(foregrounds) do
  344. setFg(util.palette.t3:inflate(foreground))
  345.  
  346. for i, pos in ipairs(chain) do
  347. local text = textdata[background][foreground][i]
  348. local x = bit32.rshift(pos, 8)
  349. local y = bit32.band(pos, 0xff)
  350.  
  351. if fills[background] and fills[background][foreground]
  352. and fills[background][foreground][i] then
  353. gpu.fill(x, y, 10, 10, text)
  354. else
  355. gpu.set(x, y, text)
  356. end
  357. end
  358. end
  359. end
  360. end
  361.  
  362. local lastYield = computer.uptime()
  363. local function tlwyGuard()
  364. if computer.uptime() - lastYield > 3 then
  365. os.sleep(0)
  366. end
  367. end
  368.  
  369. local old, bg, fg = {}
  370. local image = png(select(1, ...), function(y, _, pixels)
  371. if y % 2 == 0 then
  372. for x, a in ipairs(old) do
  373. local b = pixels[x]
  374. bg = bit32.lshift(a.R, 16) + bit32.lshift(a.G, 8) + a.B
  375. fg = bit32.lshift(b.R, 16) + bit32.lshift(b.G, 8) + a.B
  376. set(x - 1, math.floor((y - 1) / 2), fg, bg, "▄")
  377. end
  378. else
  379. old = pixels
  380. end
  381. end)
  382.  
  383. local start = computer.uptime()
  384. render()
  385. local elapsed = computer.uptime() - start
  386. require("event").pull("key_down")
  387. setBg(0x000000)
  388. setFg(0xffffff)
  389. require("term").clear()
  390. print("elapsed", elapsed)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement