Omsigames

grapes/Image.lua

Dec 25th, 2024
13
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 20.42 KB | None | 0 0
  1. local color = require("grapes.Color")
  2. local Filesystem = require("grapes.Filesystem")
  3. local unicode = require("unicode")
  4. local bit32 = require("bit32")
  5.  
  6. -- Grapes filesystem initialization
  7.  
  8. local component = require("component")
  9. local bootFilesystemProxy = component.proxy(component.invoke(component.list("eeprom")(), "getData"))
  10. Filesystem.setProxy(bootFilesystemProxy)
  11.  
  12. --------------------------------------------------------------------------------
  13.  
  14. local image = {}
  15.  
  16. local OCIFSignature = "OCIF"
  17. local encodingMethodsRead = {}
  18. local encodingMethodsReadMetadata = {}
  19. local encodingMethodsWrite = {}
  20.  
  21. --------------------------------------------------------------------------------
  22.  
  23. local function group(picture, compressColors)
  24.     local groupedPicture, x, y, background, foreground = {}, 1, 1
  25.  
  26.     for i = 3, #picture, 4 do
  27.         if compressColors then
  28.             background, foreground = color.to8Bit(picture[i]), color.to8Bit(picture[i + 1])
  29.  
  30.             if i % 603 == 0 then
  31.                 computer.pullSignal(0)
  32.             end
  33.         else
  34.             background, foreground = picture[i], picture[i + 1]
  35.         end
  36.  
  37.         groupedPicture[picture[i + 2]] = groupedPicture[picture[i + 2]] or {}
  38.         groupedPicture[picture[i + 2]][picture[i + 3]] = groupedPicture[picture[i + 2]][picture[i + 3]] or {}
  39.         groupedPicture[picture[i + 2]][picture[i + 3]][background] = groupedPicture[picture[i + 2]][picture[i + 3]][background] or {}
  40.         groupedPicture[picture[i + 2]][picture[i + 3]][background][foreground] = groupedPicture[picture[i + 2]][picture[i + 3]][background][foreground] or {}
  41.         groupedPicture[picture[i + 2]][picture[i + 3]][background][foreground][y] = groupedPicture[picture[i + 2]][picture[i + 3]][background][foreground][y] or {}
  42.  
  43.         table.insert(groupedPicture[picture[i + 2]][picture[i + 3]][background][foreground][y], x)
  44.  
  45.         x = x + 1
  46.  
  47.         if x > picture[1] then
  48.             x, y = 1, y + 1
  49.         end
  50.     end
  51.  
  52.     return groupedPicture
  53. end
  54.  
  55. -- 5
  56. encodingMethodsWrite[5] = function(file, picture)
  57.     file:writeBytes(
  58.         bit32.rshift(picture[1], 8),
  59.         bit32.band(picture[1], 0xFF)
  60.     )
  61.  
  62.     file:writeBytes(
  63.         bit32.rshift(picture[2], 8),
  64.         bit32.band(picture[2], 0xFF)
  65.     )
  66.  
  67.     for i = 3, #picture, 4 do
  68.         file:writeBytes(
  69.             color.to8Bit(picture[i]),
  70.             color.to8Bit(picture[i + 1]),
  71.             math.floor(picture[i + 2] * 255)
  72.         )
  73.  
  74.         file:write(picture[i + 3])
  75.     end
  76. end
  77.  
  78. encodingMethodsReadMetadata[5] = function(file)
  79.     return
  80.         file:readBytes(2),
  81.         file:readBytes(2)
  82. end
  83.  
  84. encodingMethodsRead[5] = function(file, picture, width, height)
  85.     picture[1] = width
  86.     picture[2] = height
  87.  
  88.     for i = 1, width * height do
  89.         table.insert(picture, color.to24Bit(file:readBytes(1)))
  90.         table.insert(picture, color.to24Bit(file:readBytes(1)))
  91.         table.insert(picture, file:readBytes(1) / 255)
  92.         table.insert(picture, file:readUnicodeChar())
  93.     end
  94. end
  95.  
  96. local function readMetadata678(file, is7, is8)
  97.     return
  98.         file:readBytes(1) + is8,
  99.         file:readBytes(1) + is8
  100. end
  101.  
  102. local function read678(file, picture, width, height, is7, is8)
  103.     picture[1] = width
  104.     picture[2] = height
  105.  
  106.     local currentAlpha, currentSymbol, currentBackground, currentForeground, currentY
  107.  
  108.     for alpha = 1, file:readBytes(1) + is7 do
  109.         currentAlpha = file:readBytes(1) / 255
  110.        
  111.         for symbol = 1, file:readBytes(2) + is7 do
  112.             currentSymbol = file:readUnicodeChar()
  113.            
  114.             for background = 1, file:readBytes(1) + is7 do
  115.                 currentBackground = color.to24Bit(file:readBytes(1))
  116.                
  117.                 for foreground = 1, file:readBytes(1) + is7 do
  118.                     currentForeground = color.to24Bit(file:readBytes(1))
  119.                    
  120.                     for y = 1, file:readBytes(1) + is7 do
  121.                         currentY = file:readBytes(1)
  122.                        
  123.                         for x = 1, file:readBytes(1) + is7 do
  124.                             image.set(
  125.                                 picture,
  126.                                 file:readBytes(1) + is8,
  127.                                 currentY + is8,
  128.                                 currentBackground,
  129.                                 currentForeground,
  130.                                 currentAlpha,
  131.                                 currentSymbol
  132.                             )
  133.                         end
  134.                     end
  135.                 end
  136.             end
  137.         end
  138.     end
  139. end
  140.  
  141. local function saveOCIF678(file, picture, is7, is8)
  142.     local function getGroupSize(t)
  143.         local size = -is7
  144.        
  145.         for key in pairs(t) do
  146.             size = size + 1
  147.         end
  148.    
  149.         return size
  150.     end
  151.    
  152.     -- Grouping picture by it's alphas, symbols and colors
  153.     local groupedPicture = group(picture, true)
  154.  
  155.     -- Writing 1 byte per image width and height
  156.     file:writeBytes(
  157.         picture[1] - is8,
  158.         picture[2] - is8
  159.     )
  160.  
  161.     -- Writing 1 byte for alphas array size
  162.     file:writeBytes(getGroupSize(groupedPicture))
  163.  
  164.     local symbolsSize
  165.  
  166.     for alpha in pairs(groupedPicture) do
  167.         symbolsSize = getGroupSize(groupedPicture[alpha])
  168.  
  169.         file:writeBytes(
  170.             -- Writing 1 byte for current alpha value
  171.             math.floor(alpha * 255),
  172.             -- Writing 2 bytes for symbols array size
  173.             bit32.rshift(symbolsSize, 8),
  174.             bit32.band(symbolsSize, 0xFF)
  175.         )
  176.  
  177.         for symbol in pairs(groupedPicture[alpha]) do
  178.             -- Writing current unicode symbol value
  179.             file:write(symbol)
  180.             -- Writing 1 byte for backgrounds array size
  181.             file:writeBytes(getGroupSize(groupedPicture[alpha][symbol]))
  182.  
  183.             for background in pairs(groupedPicture[alpha][symbol]) do
  184.                 file:writeBytes(
  185.                     -- Writing 1 byte for background color value (compressed by color)
  186.                     background,
  187.                     -- Writing 1 byte for foregrounds array size
  188.                     getGroupSize(groupedPicture[alpha][symbol][background])
  189.                 )
  190.  
  191.                 for foreground in pairs(groupedPicture[alpha][symbol][background]) do
  192.                     file:writeBytes(
  193.                         -- Writing 1 byte for foreground color value (compressed by color)
  194.                         foreground,
  195.                         -- Writing 1 byte for y array size
  196.                         getGroupSize(groupedPicture[alpha][symbol][background][foreground])
  197.                     )
  198.                    
  199.                     for y in pairs(groupedPicture[alpha][symbol][background][foreground]) do
  200.                         file:writeBytes(
  201.                             -- Writing 1 byte for current y value
  202.                             y - is8,
  203.                             -- Writing 1 byte for x array size
  204.                             #groupedPicture[alpha][symbol][background][foreground][y] - is7
  205.                         )
  206.  
  207.                         for x = 1, #groupedPicture[alpha][symbol][background][foreground][y] do
  208.                             -- Wrting 1 byte for current x value
  209.                             file:writeBytes(groupedPicture[alpha][symbol][background][foreground][y][x] - is8)
  210.                         end
  211.                     end
  212.                 end
  213.             end
  214.         end
  215.     end
  216. end
  217.  
  218. -- 6
  219. encodingMethodsReadMetadata[6] = function(file)
  220.     return readMetadata678(file, 0, 0)
  221. end
  222.  
  223. encodingMethodsRead[6] = function(file, picture, width, height)
  224.     read678(file, picture, width, height, 0, 0)
  225. end
  226.  
  227. encodingMethodsWrite[6] = function(file, picture)
  228.     saveOCIF678(file, picture, 0, 0)
  229. end
  230.  
  231. -- 7
  232. encodingMethodsReadMetadata[7] = function(file)
  233.     return readMetadata678(file, 1, 0)
  234. end
  235.  
  236. encodingMethodsRead[7] = function(file, picture, width, height)
  237.     read678(file, picture, width, height, 1, 0)
  238. end
  239.  
  240. encodingMethodsWrite[7] = function(file, picture)
  241.     saveOCIF678(file, picture, 1, 0)
  242. end
  243.  
  244. -- 8
  245. encodingMethodsReadMetadata[8] = function(file)
  246.     return readMetadata678(file, 1, 1)
  247. end
  248.  
  249. encodingMethodsRead[8] = function(file, picture, width, height)
  250.     read678(file, picture, width, height, 1, 1)
  251. end
  252.  
  253. encodingMethodsWrite[8] = function(file, picture)
  254.     saveOCIF678(file, picture, 1, 1)
  255. end
  256.  
  257. --------------------------------------------------------------------------------
  258.  
  259. function image.getIndex(x, y, width)
  260.     return 4 * (width * (y - 1) + x) - 1
  261. end
  262.  
  263. function image.create(width, height, background, foreground, alpha, symbol, random)
  264.     local picture = {width, height}
  265.  
  266.     for i = 1, width * height do
  267.         table.insert(picture, random and math.random(0x0, 0xFFFFFF) or (background or 0x0))
  268.         table.insert(picture, random and math.random(0x0, 0xFFFFFF) or (foreground or 0x0))
  269.         table.insert(picture, alpha or 0x0)
  270.         table.insert(picture, random and string.char(math.random(65, 90)) or (symbol or " "))
  271.     end
  272.  
  273.     return picture
  274. end
  275.  
  276. function image.copy(picture)
  277.     local newPicture = {}
  278.    
  279.     for i = 1, #picture do
  280.         newPicture[i] = picture[i]
  281.     end
  282.  
  283.     return newPicture
  284. end
  285.  
  286. function image.save(path, picture, encodingMethod)
  287.     encodingMethod = encodingMethod or 6
  288.    
  289.     local file, reason = Filesystem.open(path, "wb")
  290.    
  291.     if file then   
  292.         if encodingMethodsWrite[encodingMethod] then
  293.             file:write(OCIFSignature, string.char(encodingMethod))
  294.  
  295.             local result, reason = xpcall(encodingMethodsWrite[encodingMethod], debug.traceback, file, picture)
  296.            
  297.             file:close()
  298.  
  299.             if result then
  300.                 return true
  301.             else
  302.                 return false, "Failed to save OCIF image: " .. tostring(reason)
  303.             end
  304.         else
  305.             file:close()
  306.            
  307.             return false, "Failed to save OCIF image: encoding method \"" .. tostring(encodingMethod) .. "\" is not supported"
  308.         end
  309.     else
  310.         return false, "Failed to open file for writing: " .. tostring(reason)
  311.     end
  312. end
  313.  
  314. function image.readMetadata(file)
  315.     local signature = file:readString(#OCIFSignature)
  316.        
  317.     if signature == OCIFSignature then
  318.         local encodingMethod = file:readBytes(1)
  319.        
  320.         if encodingMethodsReadMetadata[encodingMethod] then
  321.             local result, widthOrReason, height = xpcall(encodingMethodsReadMetadata[encodingMethod], debug.traceback, file, picture)
  322.            
  323.             if result then
  324.                 return signature, encodingMethod, widthOrReason, height
  325.             else
  326.                 file:close()
  327.  
  328.                 return false, "Failed to read OCIF metadata: " .. tostring(widthOrReason)
  329.             end
  330.         else
  331.             file:close()
  332.        
  333.             return false, "Failed to read OCIF metadata: encoding method \"" .. tostring(encodingMethod) .. "\" is not supported"
  334.         end
  335.     else
  336.         file:close()
  337.        
  338.         return false, "Failed to read OCIF metadata: binary signature \"" .. tostring(signature) .. "\" is not valid"
  339.     end
  340. end
  341.  
  342. function image.readPixelData(file, encodingMethod, width, height)
  343.     local picture = {}
  344.     local result, reason = xpcall(encodingMethodsRead[encodingMethod], debug.traceback, file, picture, width, height)
  345.     file:close()
  346.  
  347.     if result then
  348.         return picture
  349.     else
  350.         return false, "Failed to read OCIF pixel data: " .. tostring(reason)
  351.     end
  352. end
  353.  
  354. function image.load(path)
  355.     local file, reason = Filesystem.open(path, "rb")
  356.    
  357.     if file then
  358.         local signature, encodingMethod, width, height = image.readMetadata(file)
  359.  
  360.         if signature then
  361.             return image.readPixelData(file, encodingMethod, width, height)
  362.         else
  363.             return false, encodingMethod
  364.         end
  365.     else
  366.         return false, "Failed to open file \"" .. tostring(path) .. "\" for reading: " .. tostring(reason)
  367.     end
  368. end
  369.  
  370. -------------------------------------------------------------------------------
  371.  
  372. function image.toString(picture)
  373.     local charArray = {
  374.         string.format("%02X", picture[1]),
  375.         string.format("%02X", picture[2])
  376.     }
  377.    
  378.     for i = 3, #picture, 4 do
  379.         table.insert(charArray, string.format("%02X", color.to8Bit(picture[i])))
  380.         table.insert(charArray, string.format("%02X", color.to8Bit(picture[i + 1])))
  381.         table.insert(charArray, string.format("%02X", math.floor(picture[i + 2] * 255)))
  382.         table.insert(charArray, picture[i + 3])
  383.  
  384.         if i % 603 == 0 then
  385.             computer.pullSignal(0)
  386.         end
  387.     end
  388.  
  389.     return table.concat(charArray)
  390. end
  391.  
  392. function image.fromString(pictureString)
  393.     local picture = {
  394.         tonumber("0x" .. unicode.sub(pictureString, 1, 2)),
  395.         tonumber("0x" .. unicode.sub(pictureString, 3, 4)),
  396.     }
  397.  
  398.     for i = 5, unicode.len(pictureString), 7 do
  399.         table.insert(picture, color.to24Bit(tonumber("0x" .. unicode.sub(pictureString, i, i + 1))))
  400.         table.insert(picture, color.to24Bit(tonumber("0x" .. unicode.sub(pictureString, i + 2, i + 3))))
  401.         table.insert(picture, tonumber("0x" .. unicode.sub(pictureString, i + 4, i + 5)) / 255)
  402.         table.insert(picture, unicode.sub(pictureString, i + 6, i + 6))
  403.     end
  404.  
  405.     return picture
  406. end
  407.  
  408. --------------------------------------------------------------------------------
  409.  
  410. function image.set(picture, x, y, background, foreground, alpha, symbol)
  411.     local index = image.getIndex(x, y, picture[1])
  412.     picture[index], picture[index + 1], picture[index + 2], picture[index + 3] = background, foreground, alpha, symbol
  413.  
  414.     return picture
  415. end
  416.  
  417. function image.get(picture, x, y)
  418.     local index = image.getIndex(x, y, picture[1])
  419.     return picture[index], picture[index + 1], picture[index + 2], picture[index + 3]
  420. end
  421.  
  422. function image.getSize(picture)
  423.     return picture[1], picture[2]
  424. end
  425.  
  426. function image.getWidth(picture)
  427.     return picture[1]
  428. end
  429.  
  430. function image.getHeight(picture)
  431.     return picture[2]
  432. end
  433.  
  434. function image.transform(picture, newWidth, newHeight)
  435.     local newPicture, stepWidth, stepHeight, background, foreground, alpha, symbol = {newWidth, newHeight}, picture[1] / newWidth, picture[2] / newHeight
  436.    
  437.     local x, y = 1, 1
  438.     for j = 1, newHeight do
  439.         for i = 1, newWidth do
  440.             background, foreground, alpha, symbol = image.get(picture, math.floor(x), math.floor(y))
  441.             table.insert(newPicture, background)
  442.             table.insert(newPicture, foreground)
  443.             table.insert(newPicture, alpha)
  444.             table.insert(newPicture, symbol)
  445.  
  446.             x = x + stepWidth
  447.         end
  448.  
  449.         x, y = 1, y + stepHeight
  450.     end
  451.  
  452.     return newPicture
  453. end
  454.  
  455. function image.crop(picture, fromX, fromY, width, height)
  456.     if fromX >= 1 and fromY >= 1 and fromX + width - 1 <= picture[1] and fromY + height - 1 <= picture[2] then
  457.         local newPicture, background, foreground, alpha, symbol = {width, height}
  458.        
  459.         for y = fromY, fromY + height - 1 do
  460.             for x = fromX, fromX + width - 1 do
  461.                 background, foreground, alpha, symbol = image.get(picture, x, y)
  462.                 table.insert(newPicture, background)
  463.                 table.insert(newPicture, foreground)
  464.                 table.insert(newPicture, alpha)
  465.                 table.insert(newPicture, symbol)
  466.             end
  467.         end
  468.  
  469.         return newPicture
  470.     else
  471.         return false, "Failed to crop image: target coordinates are out of source range"
  472.     end
  473. end
  474.  
  475. function image.flipHorizontally(picture)
  476.     local newPicture, background, foreground, alpha, symbol = {picture[1], picture[2]}
  477.    
  478.     for y = 1, picture[2] do
  479.         for x = picture[1], 1, -1 do
  480.             background, foreground, alpha, symbol = image.get(picture, x, y)
  481.             table.insert(newPicture, background)
  482.             table.insert(newPicture, foreground)
  483.             table.insert(newPicture, alpha)
  484.             table.insert(newPicture, symbol)
  485.         end
  486.     end
  487.  
  488.     return newPicture
  489. end
  490.  
  491. function image.flipVertically(picture)
  492.     local newPicture, background, foreground, alpha, symbol = {picture[1], picture[2]}
  493.    
  494.     for y = picture[2], 1, -1 do
  495.         for x = 1, picture[1] do
  496.             background, foreground, alpha, symbol = image.get(picture, x, y)
  497.             table.insert(newPicture, background)
  498.             table.insert(newPicture, foreground)
  499.             table.insert(newPicture, alpha)
  500.             table.insert(newPicture, symbol)
  501.         end
  502.     end
  503.  
  504.     return newPicture
  505. end
  506.  
  507. function image.expand(picture, fromTop, fromBottom, fromLeft, fromRight, background, foreground, alpha, symbol)
  508.     local newPicture = image.create(picture[1] + fromRight + fromLeft, picture[2] + fromTop + fromBottom, background, foreground, alpha, symbol)
  509.  
  510.     for y = 1, picture[2] do
  511.         for x = 1, picture[1] do
  512.             image.set(newPicture, x + fromLeft, y + fromTop, image.get(picture, x, y))
  513.         end
  514.     end
  515.  
  516.     return newPicture
  517. end
  518.  
  519. function image.blend(picture, blendColor, transparency)
  520.     local newPicture = {picture[1], picture[2]}
  521.  
  522.     for i = 3, #picture, 4 do
  523.         table.insert(newPicture, color.blend(picture[i], blendColor, transparency))
  524.         table.insert(newPicture, color.blend(picture[i + 1], blendColor, transparency))
  525.         table.insert(newPicture, picture[i + 2])
  526.         table.insert(newPicture, picture[i + 3])
  527.     end
  528.  
  529.     return newPicture
  530. end
  531.  
  532. function image.rotate(picture, angle)
  533.     local function copyPixel(newPic, oldPic, index)
  534.         table.insert(newPic, oldPic[index])
  535.         table.insert(newPic, oldPic[index + 1])
  536.         table.insert(newPic, oldPic[index + 2])
  537.         table.insert(newPic, oldPic[index + 3])
  538.     end
  539.  
  540.     if angle == 90 then
  541.         local newPicture = {picture[2], picture[1]}
  542.        
  543.         for i = 1, picture[2] do
  544.             for j = picture[1], 1, -1 do
  545.                 copyPixel(newPicture, picture, image.getIndex(i, j, picture[2]))
  546.             end
  547.         end
  548.  
  549.         return newPicture
  550.     elseif angle == 180 then
  551.         local newPicture = {picture[1], picture[2]}
  552.        
  553.         for j = picture[1], 1, -1 do
  554.             for i = picture[2], 1, -1 do
  555.                 copyPixel(newPicture, picture, image.getIndex(i, j, picture[2]))
  556.             end
  557.         end
  558.  
  559.         return newPicture
  560.     elseif angle == 270 then
  561.         local newPicture = {picture[2], picture[1]}
  562.        
  563.         for i = picture[2], 1, -1 do
  564.             for j = 1, picture[1] do
  565.                 copyPixel(newPicture, picture, image.getIndex(i, j, picture[2]))
  566.             end
  567.         end
  568.  
  569.         return newPicture
  570.     else
  571.         error("Can't rotate image: angle must be 90, 180 or 270 degrees.")
  572.     end
  573. end
  574.  
  575. function image.hueSaturationBrightness(picture, hue, saturation, brightness)
  576.     local function calculate(c)
  577.         local h, s, b = color.integerToHSB(c)
  578.        
  579.         b = b + brightness; if b < 0 then b = 0 elseif b > 1 then b = 1 end
  580.         s = s + saturation; if s < 0 then s = 0 elseif s > 1 then s = 1 end
  581.         h = h + hue; if h < 0 then h = 0 elseif h > 360 then h = 360 end
  582.  
  583.         return color.HSBToInteger(h, s, b)
  584.     end
  585.  
  586.     for i = 3, #picture, 4 do
  587.         picture[i] = calculate(picture[i])
  588.         picture[i + 1] = calculate(picture[i + 1])
  589.     end
  590.  
  591.     return picture
  592. end
  593.  
  594. function image.hue(picture, hue)
  595.     return image.hueSaturationBrightness(picture, hue, 0, 0)
  596. end
  597.  
  598. function image.saturation(picture, saturation)
  599.     return image.hueSaturationBrightness(picture, 0, saturation, 0)
  600. end
  601.  
  602. function image.brightness(picture, brightness)
  603.     return image.hueSaturationBrightness(picture, 0, 0, brightness)
  604. end
  605.  
  606. function image.blackAndWhite(picture)
  607.     return image.hueSaturationBrightness(picture, 0, -1, 0)
  608. end
  609.  
  610. function image.colorBalance(picture, r, g, b)
  611.     local function calculate(c)
  612.         local rr, gg, bb = color.integerToRGB(c)
  613.  
  614.         rr = rr + r
  615.         gg = gg + g
  616.         bb = bb + b
  617.        
  618.         if rr < 0 then rr = 0 elseif rr > 255 then rr = 255 end
  619.         if gg < 0 then gg = 0 elseif gg > 255 then gg = 255 end
  620.         if bb < 0 then bb = 0 elseif bb > 255 then bb = 255 end
  621.  
  622.         return color.RGBToInteger(rr, gg, bb)
  623.     end
  624.  
  625.     for i = 3, #picture, 4 do
  626.         picture[i] = calculate(picture[i])
  627.         picture[i + 1] = calculate(picture[i + 1])
  628.     end
  629.  
  630.     return picture
  631. end
  632.  
  633. function image.invert(picture)
  634.     for i = 3, #picture, 4 do
  635.         picture[i] = 0xffffff - picture[i]
  636.         picture[i + 1] = 0xffffff - picture[i + 1]
  637.     end
  638.  
  639.     return picture
  640. end
  641.  
  642. function image.getGaussianBlurKernel(radius, weight)
  643.     local size, index, sum, weightSquared2, value =
  644.         radius * 2 + 1,
  645.         2,
  646.         0,
  647.         2 * weight * weight
  648.  
  649.     local kernel, constant =
  650.         {size},
  651.         1 / (math.pi * weightSquared2)
  652.    
  653.     -- Filling convolution matrix
  654.     for y = -radius, radius do
  655.         for x = -radius, radius do
  656.             value = constant * math.exp(-((y * y) + (x * x)) / weightSquared2);
  657.             kernel[index] = value
  658.             sum = sum + value;
  659.  
  660.             index = index + 1
  661.         end
  662.     end
  663.  
  664.     index = 2
  665.  
  666.     for y = 1, size do
  667.         for x = 1, size do
  668.             kernel[index] = kernel[index] * 1 / sum;
  669.  
  670.             index = index + 1
  671.         end
  672.     end
  673.  
  674.     return kernel;
  675. end
  676.  
  677. function image.convolve(picture, kernel)
  678.     -- Processing
  679.     local
  680.         pictureWidth,
  681.         pictureHeight,
  682.         kernelSize,
  683.         pictureIndex,
  684.         kernelIndex,
  685.         kernelValue,
  686.         rAcc,
  687.         gAcc,
  688.         bAcc,
  689.         r,
  690.         g,
  691.         b,
  692.         x,
  693.         y = picture[1], picture[2], kernel[1], 3
  694.  
  695.     local newPicture, kernelRadius =
  696.         { pictureWidth, pictureHeight },
  697.         math.floor(kernelSize / 2)
  698.  
  699.     for pictureY = 1, pictureHeight do
  700.         for pictureX = 1, pictureWidth do
  701.             rAcc, gAcc, bAcc, kernelIndex = 0, 0, 0, 2
  702.  
  703.             -- Summing
  704.             for kernelY = -kernelRadius, kernelRadius do
  705.                 y = pictureY + kernelY
  706.  
  707.                 if y >= 1 and y <= pictureHeight then
  708.                     for kernelX = -kernelRadius, kernelRadius do
  709.                         x = pictureX + kernelX
  710.  
  711.                         if x >= 1 and x <= pictureWidth then
  712.                             kernelValue = kernel[kernelIndex]
  713.                             r, g, b = color.integerToRGB(picture[4 * (pictureWidth * (y - 1) + x) - 1])
  714.  
  715.                             rAcc, gAcc, bAcc = rAcc + r * kernelValue, gAcc + g * kernelValue, bAcc + b * kernelValue
  716.                         end
  717.  
  718.                         kernelIndex = kernelIndex + 1
  719.                     end
  720.                 else
  721.                     kernelIndex = kernelIndex + kernelSize
  722.                 end
  723.             end
  724.  
  725.             -- Setting pixel values on new picture
  726.             if rAcc > 255 then
  727.                 rAcc =  255
  728.             elseif rAcc < 0 then
  729.                 rAcc = 0
  730.             else
  731.                 rAcc = rAcc - rAcc % 1
  732.             end
  733.  
  734.             if gAcc > 255 then
  735.                 gAcc =  255
  736.             elseif gAcc < 0 then
  737.                 gAcc = 0
  738.             else
  739.                 gAcc = gAcc - gAcc % 1
  740.             end
  741.  
  742.             if bAcc > 255 then
  743.                 bAcc =  255
  744.             elseif bAcc < 0 then
  745.                 bAcc = 0
  746.             else
  747.                 bAcc = bAcc - bAcc % 1
  748.             end
  749.  
  750.             newPicture[pictureIndex] = color.RGBToInteger(rAcc, gAcc, bAcc)
  751.             pictureIndex = pictureIndex + 1
  752.  
  753.             newPicture[pictureIndex] = 0x0
  754.             pictureIndex = pictureIndex + 1
  755.  
  756.             newPicture[pictureIndex] = picture[pictureIndex]
  757.             pictureIndex = pictureIndex + 1
  758.  
  759.             newPicture[pictureIndex] = " "
  760.             pictureIndex = pictureIndex + 1
  761.         end
  762.     end
  763.  
  764.     return newPicture
  765. end
  766.  
  767. --------------------------------------------------------------------------------
  768.  
  769. return image
  770.  
Tags: ORMS
Add Comment
Please, Sign In to add comment