local args = {...} local image = args[1] ---------------------------------------- Libraries ---------------------------------------- local bit32 = require("bit32") local advancedLua = require("advancedLua") local unicode = require("unicode") local fs = require("filesystem") local color = require("color") ------------------------------------------------------------------------------------------------------------ local module = {} local OCIFSignature = "OCIF" local encodingMethods = { load = {}, save = {} } ------------------------------------------------------------------------------------------------------------ local function writeByteArrayToFile(file, byteArray) for i = 1, #byteArray do file:write(string.char(byteArray[i])) end end local function readNumberFromFile(file, countOfBytes) local byteArray = {} for i = 1, countOfBytes do table.insert(byteArray, string.byte(file:read(1))) end return bit32.byteArrayToNumber(byteArray) end ---------------------------------------- Uncompressed OCIF1 encoding ---------------------------------------- encodingMethods.save[5] = function(file, picture) for i = 3, #picture, 4 do file:write(string.char(color.to8Bit(picture[i]))) file:write(string.char(color.to8Bit(picture[i + 1]))) file:write(string.char(math.floor(picture[i + 2] * 255))) writeByteArrayToFile(file, {string.byte(picture[i + 3], 1, 6)}) end end encodingMethods.load[5] = function(file, picture) table.insert(picture, readNumberFromFile(file, 2)) table.insert(picture, readNumberFromFile(file, 2)) for i = 1, image.getWidth(picture) * image.getHeight(picture) do table.insert(picture, color.to24Bit(string.byte(file:read(1)))) table.insert(picture, color.to24Bit(string.byte(file:read(1)))) table.insert(picture, string.byte(file:read(1)) / 255) table.insert(picture, string.readUnicodeChar(file)) end end ---------------------------------------- Grouped and compressed OCIF6 encoding ---------------------------------------- encodingMethods.save[6] = function(file, picture) -- Grouping picture by it's alphas, symbols and colors local groupedPicture = image.group(picture, true) -- Writing 1 byte for alphas array size file:write(string.char(table.size(groupedPicture))) for alpha in pairs(groupedPicture) do -- Writing 1 byte for current alpha value file:write(string.char(math.floor(alpha * 255))) -- Writing 2 bytes for symbols array size writeByteArrayToFile(file, bit32.numberToFixedSizeByteArray(table.size(groupedPicture[alpha]), 2)) for symbol in pairs(groupedPicture[alpha]) do -- Writing N bytes for current unicode symbol value writeByteArrayToFile(file, { string.byte(symbol, 1, 6) }) -- Writing 1 byte for backgrounds array size file:write(string.char(table.size(groupedPicture[alpha][symbol]))) for background in pairs(groupedPicture[alpha][symbol]) do -- Writing 1 byte for background color value (compressed by color) file:write(string.char(background)) -- Writing 1 byte for foregrounds array size file:write(string.char(table.size(groupedPicture[alpha][symbol][background]))) for foreground in pairs(groupedPicture[alpha][symbol][background]) do -- Writing 1 byte for foreground color value (compressed by color) file:write(string.char(foreground)) -- Writing 1 byte for y array size file:write(string.char(table.size(groupedPicture[alpha][symbol][background][foreground]))) for y in pairs(groupedPicture[alpha][symbol][background][foreground]) do -- Writing 1 byte for current y value file:write(string.char(y)) -- Writing 1 byte for x array size file:write(string.char(#groupedPicture[alpha][symbol][background][foreground][y])) for x = 1, #groupedPicture[alpha][symbol][background][foreground][y] do file:write(string.char(groupedPicture[alpha][symbol][background][foreground][y][x])) end end end end end end end encodingMethods.load[6] = function(file, picture) table.insert(picture, string.byte(file:read(1))) table.insert(picture, string.byte(file:read(1))) local currentAlpha, currentSymbol, currentBackground, currentForeground, currentY, currentX local alphaSize, symbolSize, backgroundSize, foregroundSize, ySize, xSize alphaSize = string.byte(file:read(1)) for alpha = 1, alphaSize do currentAlpha = string.byte(file:read(1)) / 255 symbolSize = readNumberFromFile(file, 2) for symbol = 1, symbolSize do currentSymbol = string.readUnicodeChar(file) backgroundSize = string.byte(file:read(1)) for background = 1, backgroundSize do currentBackground = color.to24Bit(string.byte(file:read(1))) foregroundSize = string.byte(file:read(1)) for foreground = 1, foregroundSize do currentForeground = color.to24Bit(string.byte(file:read(1))) ySize = string.byte(file:read(1)) for y = 1, ySize do currentY = string.byte(file:read(1)) xSize = string.byte(file:read(1)) for x = 1, xSize do currentX = string.byte(file:read(1)) image.set(picture, currentX, currentY, currentBackground, currentForeground, currentAlpha, currentSymbol) end end end end end end end ---------------------------------------- Public load&save methods of module ---------------------------------------- function module.load(path) local file, reason = io.open(path, "rb") if file then local readedSignature = file:read(#OCIFSignature) if readedSignature == OCIFSignature then local encodingMethod = string.byte(file:read(1)) if encodingMethods.load[encodingMethod] then local picture = {} encodingMethods.load[encodingMethod](file, picture) file:close() return picture else file:close() error("Failed to load OCIF image: encoding method \"" .. tostring(encodingMethod) .. "\" is not supported") end else file:close() error("Failed to load OCIF image: wrong signature (\"" .. tostring(readedSignature) .. "\")") end else error("Failed to open file \"" .. tostring(path) .. "\" for reading: " .. tostring(reason)) end end function module.save(path, picture, encodingMethod) encodingMethod = encodingMethod or 6 local file, reason = io.open(path, "wb") if file then if encodingMethods.save[encodingMethod] then -- Writing signature, encoding method, image width and height file:write(OCIFSignature, string.char(encodingMethod), string.char(picture[1]), string.char(picture[2])) -- Executing selected encoding method encodingMethods.save[encodingMethod](file, picture) file:close() else file:close() error("Failed to save file as OCIF image: encoding method \"" .. tostring(encodingMethod) .. "\" is not supported") end else error("Failed to open file for writing: " .. tostring(reason)) end end ------------------------------------------------------------------------------------------------------------ return module