KaychenHH

Image.lua

Mar 22nd, 2022 (edited)
19
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 11.43 KB | None | 0 0
  1. local computer = require("computer")
  2. local color = require("color")
  3. local unicode = require("unicode")
  4. local fs = require("filesystem")
  5. local gpu = require("component").gpu
  6.  
  7. -------------------------------------------------------------------------------
  8.  
  9. local image = {formatModules = {}}
  10.  
  11. -------------------------------------------------------------------------------
  12.  
  13. function image.getIndex(x, y, width)
  14.     return width * (y - 1) + x
  15. end
  16.  
  17. function image.group(picture, compressColors)
  18.     local groupedPicture, x, y, background, foreground = {}, 1, 1
  19.  
  20.     for i = 1, #picture[3] do
  21.         if compressColors then
  22.             background, foreground = color.to8Bit(picture[3][i]), color.to8Bit(picture[4][i])
  23.             if i % 603 == 0 then
  24.                 computer.pullSignal(0)
  25.             end
  26.         else
  27.             background, foreground = picture[3][i], picture[4][i]
  28.         end
  29.  
  30.         groupedPicture[picture[5][i]] = groupedPicture[picture[5][i]] or {}
  31.         groupedPicture[picture[5][i]][picture[6][i]] = groupedPicture[picture[5][i]][picture[6][i]] or {}
  32.         groupedPicture[picture[5][i]][picture[6][i]][background] = groupedPicture[picture[5][i]][picture[6][i]][background] or {}
  33.         groupedPicture[picture[5][i]][picture[6][i]][background][foreground] = groupedPicture[picture[5][i]][picture[6][i]][background][foreground] or {}
  34.         groupedPicture[picture[5][i]][picture[6][i]][background][foreground][y] = groupedPicture[picture[5][i]][picture[6][i]][background][foreground][y] or {}
  35.  
  36.         table.insert(groupedPicture[picture[5][i]][picture[6][i]][background][foreground][y], x)
  37.  
  38.         x = x + 1
  39.         if x > picture[1] then
  40.             x, y = 1, y + 1
  41.         end
  42.     end
  43.  
  44.     return groupedPicture
  45. end
  46.  
  47. function image.draw(x, y, picture)
  48.     local groupedPicture = image.group(picture)
  49.     local _, _, currentBackground, currentForeground, gpuGetBackground, imageX, imageY
  50.  
  51.     for alpha in pairs(groupedPicture) do
  52.         for symbol in pairs(groupedPicture[alpha]) do
  53.            
  54.             if not (symbol == " " and alpha == 1) then
  55.                 for background in pairs(groupedPicture[alpha][symbol]) do
  56.                    
  57.                     if background ~= currentBackground then
  58.                         currentBackground = background
  59.                         gpu.setBackground(background)
  60.                     end
  61.  
  62.                     for foreground in pairs(groupedPicture[alpha][symbol][background]) do
  63.                        
  64.                         if foreground ~= currentForeground and symbol ~= " " then
  65.                             currentForeground = foreground
  66.                             gpu.setForeground(foreground)
  67.                         end
  68.                        
  69.                         for yPos in pairs(groupedPicture[alpha][symbol][background][foreground]) do
  70.                             for xPos = 1, #groupedPicture[alpha][symbol][background][foreground][yPos] do
  71.                                 imageX, imageY = x + groupedPicture[alpha][symbol][background][foreground][yPos][xPos] - 1, y + yPos - 1
  72.  
  73.                                 if alpha > 0 then
  74.                                     _, _, gpuGetBackground = gpu.get(imageX, imageY)
  75.                                    
  76.                                     if alpha == 1 then
  77.                                         currentBackground = gpuGetBackground
  78.                                         gpu.setBackground(currentBackground)
  79.                                     else
  80.                                         currentBackground = color.blend(gpuGetBackground, background, alpha)
  81.                                         gpu.setBackground(currentBackground)
  82.                                     end
  83.                                 end
  84.  
  85.                                 gpu.set(imageX, imageY, symbol)
  86.                             end
  87.                         end
  88.                     end
  89.                 end
  90.             end
  91.         end
  92.     end
  93. end
  94.  
  95. function image.create(width, height, background, foreground, alpha, symbol, random)
  96.     local picture = {width, height, {}, {}, {}, {}}
  97.  
  98.     for i = 1, width * height do
  99.         table.insert(picture[3], random and math.random(0x0, 0xFFFFFF) or (background or 0x0))
  100.         table.insert(picture[4], random and math.random(0x0, 0xFFFFFF) or (foreground or 0x0))
  101.         table.insert(picture[5], alpha or 0x0)
  102.         table.insert(picture[6], random and string.char(math.random(65, 90)) or (symbol or " "))
  103.     end
  104.  
  105.     return picture
  106. end
  107.  
  108. function image.copy(picture)
  109.     local newPicture = {picture[1], picture[2], {}, {}, {}, {}}
  110.    
  111.     for i = 1, #picture[3] do
  112.         newPicture[3][i] = picture[3][i]
  113.         newPicture[4][i] = picture[4][i]
  114.         newPicture[5][i] = picture[5][i]
  115.         newPicture[6][i] = picture[6][i]
  116.     end
  117.  
  118.     return newPicture
  119. end
  120.  
  121. -------------------------------------------------------------------------------
  122.  
  123. function image.loadFormatModule(path, extension)
  124.     local success, result = loadfile(path)
  125.     if success then
  126.         success, result = pcall(success, image)
  127.         if success then
  128.             image.formatModules[extension] = result
  129.         else
  130.             error("Failed to execute image format module: " .. tostring(result))
  131.         end
  132.     else
  133.         error("Failed to load image format module: " .. tostring(result))
  134.     end
  135. end
  136.  
  137. local function loadOrSave(methodName, path, ...)
  138.     local extension = fs.extension(path)
  139.     if image.formatModules[extension] then
  140.         local success, result = pcall(image.formatModules[extension][methodName], path, ...)
  141.         if success then
  142.             return result
  143.         else
  144.             return false, "Failed to " .. methodName .. " image file: " .. tostring(result)
  145.         end
  146.     else
  147.         return false, "Failed to " .. methodName .. " image file: format module for extension \"" .. tostring(extension) .. "\" is not loaded"
  148.     end
  149. end
  150.  
  151. function image.save(path, picture, encodingMethod)
  152.     return loadOrSave("save", path, picture, encodingMethod)
  153. end
  154.  
  155. function image.load(path)
  156.     return loadOrSave("load", path)
  157. end
  158.  
  159. -------------------------------------------------------------------------------
  160.  
  161. function image.toString(picture)
  162.     local charArray = {
  163.         string.format("%02X", picture[1]),
  164.         string.format("%02X", picture[2])
  165.     }
  166.    
  167.     for i = 1, #picture[3] do
  168.         table.insert(charArray, string.format("%02X", color.to8Bit(picture[3][i])))
  169.         table.insert(charArray, string.format("%02X", color.to8Bit(picture[4][i])))
  170.         table.insert(charArray, string.format("%02X", math.floor(picture[5][i] * 255)))
  171.         table.insert(charArray, picture[6][i])
  172.  
  173.         if i % 603 == 0 then
  174.             computer.pullSignal(0)
  175.         end
  176.     end
  177.  
  178.     return table.concat(charArray)
  179. end
  180.  
  181. function image.fromString(pictureString)
  182.     local picture = {
  183.         tonumber("0x" .. unicode.sub(pictureString, 1, 2)),
  184.         tonumber("0x" .. unicode.sub(pictureString, 3, 4)),
  185.         {}, {}, {}, {}
  186.     }
  187.  
  188.     for i = 5, unicode.len(pictureString), 7 do
  189.         table.insert(picture[3], color.to24Bit(tonumber("0x" .. unicode.sub(pictureString, i, i + 1))))
  190.         table.insert(picture[4], color.to24Bit(tonumber("0x" .. unicode.sub(pictureString, i + 2, i + 3))))
  191.         table.insert(picture[5], tonumber("0x" .. unicode.sub(pictureString, i + 4, i + 5)) / 255)
  192.         table.insert(picture[6], unicode.sub(pictureString, i + 6, i + 6))
  193.     end
  194.  
  195.     return picture
  196. end
  197.  
  198. -------------------------------------------------------------------------------
  199.  
  200. function image.set(picture, x, y, background, foreground, alpha, symbol)
  201.     local index = image.getIndex(x, y, picture[1])
  202.     picture[3][index], picture[4][index], picture[5][index], picture[6][index] = background, foreground, alpha, symbol
  203.  
  204.     return picture
  205. end
  206.  
  207. function image.get(picture, x, y)
  208.     local index = image.getIndex(x, y, picture[1])
  209.     return picture[3][index], picture[4][index], picture[5][index], picture[6][index]
  210. end
  211.  
  212. function image.getSize(picture)
  213.     return picture[1], picture[2]
  214. end
  215.  
  216. function image.getWidth(picture)
  217.     return picture[1]
  218. end
  219.  
  220. function image.getHeight(picture)
  221.     return picture[2]
  222. end
  223.  
  224. function image.transform(picture, newWidth, newHeight)
  225.     local newPicture, stepWidth, stepHeight, background, foreground, alpha, symbol = {newWidth, newHeight, {}, {}, {}, {}}, picture[1] / newWidth, picture[2] / newHeight
  226.    
  227.     local x, y = 1, 1
  228.     for j = 1, newHeight do
  229.         for i = 1, newWidth do
  230.             background, foreground, alpha, symbol = image.get(picture, math.floor(x), math.floor(y))
  231.             table.insert(newPicture[3], background)
  232.             table.insert(newPicture[4], foreground)
  233.             table.insert(newPicture[5], alpha)
  234.             table.insert(newPicture[6], symbol)
  235.  
  236.             x = x + stepWidth
  237.         end
  238.  
  239.         x, y = 1, y + stepHeight
  240.     end
  241.  
  242.     return newPicture
  243. end
  244.  
  245. function image.crop(picture, fromX, fromY, width, height)
  246.     if fromX >= 1 and fromY >= 1 and fromX + width - 1 <= picture[1] and fromY + height - 1 <= picture[2] then
  247.         local newPicture, background, foreground, alpha, symbol = {width, height, {}, {}, {}, {}}
  248.        
  249.         for y = fromY, fromY + height - 1 do
  250.             for x = fromX, fromX + width - 1 do
  251.                 background, foreground, alpha, symbol = image.get(picture, x, y)
  252.                 table.insert(newPicture[3], background)
  253.                 table.insert(newPicture[4], foreground)
  254.                 table.insert(newPicture[5], alpha)
  255.                 table.insert(newPicture[6], symbol)
  256.             end
  257.         end
  258.  
  259.         return newPicture
  260.     else
  261.         return false, "Failed to crop image: target coordinates are out of source range"
  262.     end
  263. end
  264.  
  265. function image.flipHorizontally(picture)
  266.     local newPicture, background, foreground, alpha, symbol = {picture[1], picture[2], {}, {}, {}, {}}
  267.    
  268.     for y = 1, picture[2] do
  269.         for x = picture[1], 1, -1 do
  270.             background, foreground, alpha, symbol = image.get(picture, x, y)
  271.             table.insert(newPicture[3], background)
  272.             table.insert(newPicture[4], foreground)
  273.             table.insert(newPicture[5], alpha)
  274.             table.insert(newPicture[6], symbol)
  275.         end
  276.     end
  277.  
  278.     return newPicture
  279. end
  280.  
  281. function image.flipVertically(picture)
  282.     local newPicture, background, foreground, alpha, symbol = {picture[1], picture[2], {}, {}, {}, {}}
  283.    
  284.     for y = picture[2], 1, -1 do
  285.         for x = 1, picture[1] do
  286.             background, foreground, alpha, symbol = image.get(picture, x, y)
  287.             table.insert(newPicture[3], background)
  288.             table.insert(newPicture[4], foreground)
  289.             table.insert(newPicture[5], alpha)
  290.             table.insert(newPicture[6], symbol)
  291.         end
  292.     end
  293.  
  294.     return newPicture
  295. end
  296.  
  297. function image.expand(picture, fromTop, fromBottom, fromLeft, fromRight, background, foreground, alpha, symbol)
  298.     local newPicture = image.create(picture[1] + fromRight + fromLeft, picture[2] + fromTop + fromBottom, background, foreground, alpha, symbol)
  299.  
  300.     for y = 1, picture[2] do
  301.         for x = 1, picture[1] do
  302.             image.set(newPicture, x + fromLeft, y + fromTop, image.get(picture, x, y))
  303.         end
  304.     end
  305.  
  306.     return newPicture
  307. end
  308.  
  309. function image.blend(picture, blendColor, transparency)
  310.     local newPicture = {picture[1], picture[2], {}, {}, {}, {}}
  311.  
  312.     for i = 1, #picture[3] do
  313.         table.insert(newPicture[3], color.blend(picture[3][i], blendColor, transparency))
  314.         table.insert(newPicture[4], color.blend(picture[4][i], blendColor, transparency))
  315.         table.insert(newPicture[5], picture[5][i])
  316.         table.insert(newPicture[6], picture[6][i])
  317.     end
  318.  
  319.     return newPicture
  320. end
  321.  
  322. function image.rotate(picture, angle)
  323.     local radAngle = math.rad(angle)
  324.     local sin, cos = math.sin(radAngle), math.cos(radAngle)
  325.     local pixMap = {}
  326.  
  327.     local xCenter, yCenter = picture[1] / 2, picture[2] / 2
  328.     local xMin, xMax, yMin, yMax = math.huge, -math.huge, math.huge, -math.huge
  329.     for y = 1, picture[2] do
  330.         for x = 1, picture[1] do
  331.             local xNew = math.round(xCenter + (x - xCenter) * cos - (y - yCenter) * sin)
  332.             local yNew = math.round(yCenter + (y - yCenter) * cos + (x - xCenter) * sin)
  333.  
  334.             xMin, xMax, yMin, yMax = math.min(xMin, xNew), math.max(xMax, xNew), math.min(yMin, yNew), math.max(yMax, yNew)
  335.  
  336.             pixMap[yNew] = pixMap[yNew] or {}
  337.             pixMap[yNew][xNew] = {image.get(picture, x, y)}
  338.         end
  339.     end
  340.  
  341.     local newPicture = image.create(xMax - xMin + 1, yMax - yMin + 1, 0xFF0000, 0x0, 0x0, "#")
  342.     for y in pairs(pixMap) do
  343.         for x in pairs(pixMap[y]) do
  344.             image.set(newPicture, x - xMin + 1, y - yMin + 1, pixMap[y][x][1], pixMap[y][x][2], pixMap[y][x][3], pixMap[y][x][4])
  345.         end
  346.     end
  347.  
  348.     return newPicture
  349. end
  350.  
  351. -------------------------------------------------------------------------------
  352.  
  353. image.loadFormatModule("/lib/FormatModules/OCIF.lua", ".pic")
  354.  
  355. -------------------------------------------------------------------------------
  356.  
  357. return image
Add Comment
Please, Sign In to add comment