mirror of
https://github.com/IgorTimofeev/MineOS.git
synced 2025-12-21 11:39:23 +01:00
404 lines
11 KiB
Lua
404 lines
11 KiB
Lua
local fs = require("filesystem")
|
||
local unicode = require("unicode")
|
||
local gpu = require("component").gpu
|
||
|
||
local image = {}
|
||
|
||
local transparentSymbol = "#"
|
||
|
||
--------------------Все, что касается сжатого формата изображений----------------------------------------------------------------------------------
|
||
|
||
--OC image format .ocif by Pirnogion
|
||
local ocif_signature1 = 0x896F6369
|
||
local ocif_signature2 = 0x00661A0A --7 bytes: 89 6F 63 69 66 1A 0A
|
||
local ocif_signature_expand = { string.char(0x89), string.char(0x6F), string.char(0x63), string.char(0x69), string.char(0x66), string.char(0x1A), string.char(0x0A) }
|
||
|
||
local BYTE = 8
|
||
local NULL_CHAR = 0
|
||
|
||
local imageAPI = {}
|
||
|
||
local function readBytes(file, bytes)
|
||
local readedByte = 0
|
||
local readedNumber = 0
|
||
for i = bytes, 1, -1 do
|
||
readedByte = string.byte( file:read(1) or NULL_CHAR )
|
||
readedNumber = readedNumber + bit32.lshift(readedByte, i*8-8)
|
||
end
|
||
|
||
return readedNumber
|
||
end
|
||
|
||
local function HEXtoRGB(color)
|
||
local rr = bit32.rshift( color, 16 )
|
||
local gg = bit32.rshift( bit32.band(color, 0x00ff00), 8 )
|
||
local bb = bit32.band(color, 0x0000ff)
|
||
|
||
return rr, gg, bb
|
||
end
|
||
|
||
local function encodePixel(hexcolor_fg, hexcolor_bg, char)
|
||
local rr_fg, gg_fg, bb_fg = HEXtoRGB( hexcolor_fg )
|
||
local rr_bg, gg_bg, bb_bg = HEXtoRGB( hexcolor_bg )
|
||
local ascii_char1, ascii_char2 = string.byte( char, 1, 2 )
|
||
|
||
ascii_char1 = ascii_char1 or NULL_CHAR
|
||
ascii_char2 = ascii_char2 or NULL_CHAR
|
||
|
||
return rr_fg, gg_fg, bb_fg, rr_bg, gg_bg, bb_bg, ascii_char1, ascii_char2
|
||
end
|
||
|
||
local function decodeChar(char1, char2)
|
||
if ( char1 ~= 0 and char2 ~= 0 ) then
|
||
return string.char( char1, char2 )
|
||
elseif ( char1 ~= 0) then
|
||
return string.char( char1 )
|
||
elseif ( char2 ~= 0 ) then
|
||
return string.char( char2 )
|
||
end
|
||
end
|
||
|
||
--Чтение сжатого формата
|
||
local function loadJPG(path)
|
||
local image = {}
|
||
local file = io.open(path, "rb")
|
||
|
||
local signature1, signature2 = readBytes(file, 4), readBytes(file, 3)
|
||
if ( signature1 ~= ocif_signature1 or signature2 ~= ocif_signature2 ) then
|
||
file:close()
|
||
return nil
|
||
end
|
||
|
||
image.width = readBytes(file, 1)
|
||
image.height = readBytes(file, 1)
|
||
image.depth = readBytes(file, 1)
|
||
|
||
for y = 1, image.height, 1 do
|
||
table.insert( image, {} )
|
||
for x = 1, image.width, 1 do
|
||
table.insert( image[y], {} )
|
||
image[y][x].fg = readBytes(file, 3)
|
||
image[y][x].bg = readBytes(file, 3)
|
||
image[y][x].char = decodeChar(readBytes(file, 1), readBytes(file, 1))
|
||
end
|
||
end
|
||
|
||
file:close()
|
||
|
||
return image
|
||
end
|
||
|
||
--Рисование сжатого формата
|
||
local function drawJPG(x, y, image2)
|
||
x = x - 1
|
||
y = y - 1
|
||
for j = 1, image2.height, 1 do
|
||
for i = 1, image2.width, 1 do
|
||
|
||
if image2[j][i].char ~= transparentSymbol then
|
||
|
||
if image2[j][i].bg ~= gpu.getBackground() then
|
||
gpu.setBackground(image2[j][i].bg)
|
||
end
|
||
|
||
if image2[j][i].fg ~= gpu.getForeground() then
|
||
gpu.setBackground(image2[j][i].fg)
|
||
end
|
||
|
||
gpu.set(x + i, y + j, image2[j][i].char)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
--Сохранение ДЖПГ в файл из существующего массива
|
||
function image.saveJPG(path, image)
|
||
|
||
-- Удаляем файл, если есть
|
||
-- И делаем папку к нему
|
||
fs.remove(path)
|
||
fs.makeDirectory(fs.path(path))
|
||
|
||
local file = io.open(path, "w")
|
||
|
||
--print("width = ", image.width)
|
||
|
||
file:write( table.unpack(ocif_signature_expand) )
|
||
file:write( string.char( image.width ) )
|
||
file:write( string.char( image.height ) )
|
||
file:write( string.char( image.depth ) )
|
||
|
||
for y = 1, image.height, 1 do
|
||
for x = 1, image.width, 1 do
|
||
local encodedPixel = { encodePixel( image[y][x].fg, image[y][x].bg, image[y][x].char ) }
|
||
for i = 1, #encodedPixel do
|
||
file:write( string.char( encodedPixel[i] ) )
|
||
end
|
||
end
|
||
end
|
||
|
||
file:close()
|
||
end
|
||
|
||
---------------------------Все, что касается несжатого формата-------------------------------------------------------
|
||
|
||
--Загрузка ПНГ
|
||
local function loadPNG(path)
|
||
local file = io.open(path, "r")
|
||
local massiv = {}
|
||
|
||
for line in file:lines() do
|
||
local dlinaStroki = unicode.len(line)
|
||
local lineNumber = #massiv + 1
|
||
|
||
if dlinaStroki > 14 then
|
||
local pixelCounter = 1
|
||
massiv[lineNumber] = {}
|
||
for i = 1, dlinaStroki, 16 do
|
||
local loadedBackground = unicode.sub(line, i, i + 5)
|
||
local loadedForeground = unicode.sub(line, i + 7, i + 12)
|
||
local loadedSymbol = unicode.sub(line, i + 14, i + 14)
|
||
|
||
massiv[lineNumber][pixelCounter] = { tonumber("0x" .. loadedBackground), tonumber("0x" .. loadedForeground), loadedSymbol }
|
||
|
||
pixelCounter = pixelCounter + 1
|
||
end
|
||
end
|
||
end
|
||
|
||
file:close()
|
||
return massiv
|
||
end
|
||
|
||
--Отрисовка ПНГ
|
||
local function drawPNG(x, y, massivSudaPihay)
|
||
x = x - 1
|
||
y = y - 1
|
||
for j = 1, #massivSudaPihay do
|
||
for i = 1, #massivSudaPihay[j] do
|
||
if massivSudaPihay[j][i][1] and massivSudaPihay[j][i][2] and massivSudaPihay[j][i][3] ~= transparentSymbol then
|
||
|
||
if massivSudaPihay[j][i][1] ~= gpu.getBackground() then
|
||
gpu.setBackground(massivSudaPihay[j][i][1])
|
||
end
|
||
|
||
if massivSudaPihay[j][i][2] ~= gpu.getForeground() then
|
||
gpu.setForeground(massivSudaPihay[j][i][2])
|
||
end
|
||
|
||
gpu.set(x + i, y + j, massivSudaPihay[j][i][3])
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
-- Сохранение существующего массива ПНГ в файл
|
||
function image.savePNG(path, MasterPixels)
|
||
-- Удаляем файл, если есть
|
||
-- И делаем папку к нему
|
||
fs.remove(path)
|
||
fs.makeDirectory(fs.path(path))
|
||
local f = io.open(path, "w")
|
||
|
||
for j=1, #MasterPixels do
|
||
for i=1,#MasterPixels[j] do
|
||
f:write(HEXtoSTRING(MasterPixels[j][i][1])," ",HEXtoSTRING(MasterPixels[j][i][2])," ",MasterPixels[j][i][3]," ")
|
||
end
|
||
f:write("\n")
|
||
end
|
||
|
||
f:close()
|
||
end
|
||
|
||
---------------------Глобальные функции отрисовки---------------------------------------------------------
|
||
|
||
--Конвертер из PNG в JPG
|
||
function image.PNGtoJPG(PNGMassiv)
|
||
local JPGMassiv = {}
|
||
local width, height = 0, 0
|
||
|
||
--Сохраняем пиксели
|
||
for j = 1, #PNGMassiv do
|
||
JPGMassiv[j] = {}
|
||
width = 0
|
||
for i = 1, #PNGMassiv[j] do
|
||
JPGMassiv[j][i] = {}
|
||
JPGMassiv[j][i]["bg"] = PNGMassiv[j][i][1]
|
||
JPGMassiv[j][i]["fg"] = PNGMassiv[j][i][2]
|
||
JPGMassiv[j][i]["char"] = PNGMassiv[j][i][3]
|
||
width = width + 1
|
||
end
|
||
height = height + 1
|
||
end
|
||
|
||
JPGMassiv["width"] = width
|
||
JPGMassiv["height"] = height
|
||
JPGMassiv["depth"] = 8
|
||
|
||
return JPGMassiv
|
||
end
|
||
|
||
--Конвертер из JPG в PNG
|
||
function image.JPGtoPNG(JPGMassiv)
|
||
local PNGMassiv = {}
|
||
local width, height = 0, 0
|
||
|
||
--Сохраняем пиксели
|
||
for j = 1, #JPGMassiv do
|
||
PNGMassiv[j] = {}
|
||
width = 0
|
||
for i = 1, #JPGMassiv[j] do
|
||
PNGMassiv[j][i] = {}
|
||
PNGMassiv[j][i][1] = JPGMassiv[j][i]["bg"]
|
||
PNGMassiv[j][i][2] = JPGMassiv[j][i]["fg"]
|
||
PNGMassiv[j][i][3] = JPGMassiv[j][i]["char"]
|
||
width = width + 1
|
||
end
|
||
height = height + 1
|
||
end
|
||
|
||
return PNGMassiv
|
||
end
|
||
|
||
-- Просканировать файловую систему на наличие .PNG
|
||
-- И сохранить рядом с ними аналогичную копию в формате .JPG
|
||
-- Осторожно, функция для дебага и знающих людей
|
||
-- С кривыми ручками сюда не лезь
|
||
function image.convertAllPNGtoJPG(path)
|
||
local list = ecs.getFileList(path)
|
||
for key, file in pairs(list) do
|
||
if fs.isDirectory(path.."/"..file) then
|
||
image.convertAllPNGtoJPG(path.."/"..file)
|
||
else
|
||
if ecs.getFileFormat(file) == ".png" or ecs.getFileFormat(file) == ".PNG" then
|
||
print("Найден .PNG в директории \""..path.."/"..file.."\"")
|
||
print("Загружаю этот файл...")
|
||
PNGFile = loadPNG(path.."/"..file)
|
||
print("Загрузка завершена!")
|
||
print("Конвертация в JPG начата...")
|
||
JPGFile = image.PNGtoJPG(PNGFile)
|
||
print("Ковертация завершена!")
|
||
print("Сохраняю .JPG в той же папке...")
|
||
image.saveJPG(path.."/"..ecs.hideFileFormat(file)..".jpg", JPGFile)
|
||
print("Сохранение завершено!")
|
||
print(" ")
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
--Загрузка любого изображения из доступных типов
|
||
function image.load(path)
|
||
|
||
local kartinka = {}
|
||
local fileFormat = ecs.getFileFormat(path)
|
||
|
||
if string.lower(fileFormat) == ".jpg" then
|
||
kartinka["format"] = ".jpg"
|
||
kartinka["image"] = loadJPG(path)
|
||
elseif string.lower(fileFormat) == ".png" then
|
||
kartinka["format"] = ".png"
|
||
kartinka["image"] = loadPNG(path)
|
||
else
|
||
ecs.error("Wrong file format! (not .png or .jpg)")
|
||
end
|
||
|
||
return kartinka
|
||
end
|
||
|
||
--Отрисовка этого изображения
|
||
function image.draw(x, y, kartinka)
|
||
if kartinka.format == ".jpg" then
|
||
drawJPG(x, y, kartinka["image"])
|
||
elseif kartinka.format == ".png" then
|
||
drawPNG(x, y, kartinka["image"])
|
||
end
|
||
end
|
||
|
||
---------------------------------------------------------------------------------------------------------------------
|
||
|
||
--image.convertAllPNGtoJPG("")
|
||
|
||
-- local test = image.load("System/OS/Icons/Love.jpg")
|
||
-- image.draw(2, 2, test)
|
||
|
||
-- local cyyyyka = image.load("1.png.png")
|
||
-- image.draw(2, 2, cyyyyka)
|
||
|
||
|
||
|
||
|
||
-- function imageAPI.initGlobal()
|
||
-- local prev = _G.global_images
|
||
-- _G.global_images = {}
|
||
|
||
-- return _G.global_images, prev
|
||
-- end
|
||
|
||
-- local test = {
|
||
-- ["format"] = ".jpg",
|
||
-- ["image"] ={
|
||
-- ["width"] = 8,
|
||
-- ["height"] = 4,
|
||
-- ["depth"] = 8,
|
||
-- {
|
||
-- {["fg"]=0x000000, ["bg"]=0xFFFFFF, ["char"]='1'},
|
||
-- {["fg"]=0x000000, ["bg"]=0xFFFFFF, ["char"]='0'},
|
||
-- {["fg"]=0x000000, ["bg"]=0xFFFFFF, ["char"]='1'},
|
||
-- {["fg"]=0x000000, ["bg"]=0xFFFFFF, ["char"]='0'},
|
||
-- {["fg"]=0x000000, ["bg"]=0xFFFFFF, ["char"]='1'},
|
||
-- {["fg"]=0x000000, ["bg"]=0x004980, ["char"]=' '},
|
||
-- {["fg"]=0x000000, ["bg"]=0x004980, ["char"]=' '},
|
||
-- {["fg"]=0x000000, ["bg"]=0x004980, ["char"]=' '}
|
||
-- },
|
||
-- {
|
||
-- {["fg"]=0x000000, ["bg"]=0x004980, ["char"]=' '},
|
||
-- {["fg"]=0x000000, ["bg"]=0xFFFFFF, ["char"]='1'},
|
||
-- {["fg"]=0x000000, ["bg"]=0xFFFFFF, ["char"]='0'},
|
||
-- {["fg"]=0x000000, ["bg"]=0xFFFFFF, ["char"]='1'},
|
||
-- {["fg"]=0x000000, ["bg"]=0xFFFFFF, ["char"]='0'},
|
||
-- {["fg"]=0x000000, ["bg"]=0xFFFFFF, ["char"]='1'},
|
||
-- {["fg"]=0x000000, ["bg"]=0x004980, ["char"]=' '},
|
||
-- {["fg"]=0x000000, ["bg"]=0x004980, ["char"]=' '}
|
||
-- },
|
||
-- {
|
||
-- {["fg"]=0x000000, ["bg"]=0x004980, ["char"]=' '},
|
||
-- {["fg"]=0x000000, ["bg"]=0x004980, ["char"]=' '},
|
||
-- {["fg"]=0x000000, ["bg"]=0xFFFFFF, ["char"]='1'},
|
||
-- {["fg"]=0x000000, ["bg"]=0xFFFFFF, ["char"]='0'},
|
||
-- {["fg"]=0x000000, ["bg"]=0xFFFFFF, ["char"]='1'},
|
||
-- {["fg"]=0x000000, ["bg"]=0xFFFFFF, ["char"]='0'},
|
||
-- {["fg"]=0x000000, ["bg"]=0xFFFFFF, ["char"]='1'},
|
||
-- {["fg"]=0x000000, ["bg"]=0x004980, ["char"]=' '}
|
||
-- },
|
||
-- {
|
||
-- {["fg"]=0x000000, ["bg"]=0xFFFFFF, ["char"]='P'},
|
||
-- {["fg"]=0x000000, ["bg"]=0xFFFFFF, ["char"]='A'},
|
||
-- {["fg"]=0x000000, ["bg"]=0xFFFFFF, ["char"]='S'},
|
||
-- {["fg"]=0x000000, ["bg"]=0xFFFFFF, ["char"]='T'},
|
||
-- {["fg"]=0x000000, ["bg"]=0xFFFFFF, ["char"]='Ж'},
|
||
-- {["fg"]=0x000000, ["bg"]=0xFFFFFF, ["char"]='B'},
|
||
-- {["fg"]=0x000000, ["bg"]=0xFFFFFF, ["char"]='I'},
|
||
-- {["fg"]=0x000000, ["bg"]=0xFFFFFF, ["char"]='N'}
|
||
-- },
|
||
-- }
|
||
-- }
|
||
|
||
-- image.draw(20, 2, test)
|
||
|
||
|
||
return image
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|