202 lines
6.8 KiB
Lua
Executable File

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