mirror of
https://github.com/IgorTimofeev/MineOS.git
synced 2026-01-08 04:02:40 +01:00
Added completely new image format - it's extremely small and fast. Plus, added some improvements to rendering algorythms.
This commit is contained in:
parent
574ca986cb
commit
09cc715fc8
345
lib/image.lua
345
lib/image.lua
@ -4,11 +4,149 @@ local gpu = require("component").gpu
|
||||
|
||||
local image = {}
|
||||
|
||||
---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
local transparentSymbol = "#"
|
||||
|
||||
function image.load(path)
|
||||
--------------------Все, что касается сжатого формата изображений----------------------------------------------------------------------------------
|
||||
|
||||
--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 i > 1 then
|
||||
if image2[j][i - 1].bg ~= image2[j][i].bg then
|
||||
gpu.setBackground(image2[j][i].bg)
|
||||
end
|
||||
if image2[j][i - 1].fg ~= image2[j][i].fg then
|
||||
gpu.setBackground(image2[j][i].bg)
|
||||
end
|
||||
else
|
||||
gpu.setBackground(image2[j][i].bg)
|
||||
gpu.setForeground(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 = {}
|
||||
|
||||
@ -35,21 +173,216 @@ function image.load(path)
|
||||
return massiv
|
||||
end
|
||||
|
||||
function image.draw(x, y, massivSudaPihay)
|
||||
--Отрисовка ПНГ
|
||||
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
|
||||
gpu.setBackground(massivSudaPihay[j][i][1])
|
||||
gpu.setForeground(massivSudaPihay[j][i][2])
|
||||
|
||||
if i > 1 then
|
||||
if massivSudaPihay[j][i - 1][1] ~= massivSudaPihay[j][i][1] then
|
||||
gpu.setBackground(massivSudaPihay[j][i][1])
|
||||
end
|
||||
if massivSudaPihay[j][i - 1][2] ~= massivSudaPihay[j][i][2] then
|
||||
gpu.setForeground(massivSudaPihay[j][i][2])
|
||||
end
|
||||
else
|
||||
gpu.setBackground(massivSudaPihay[j][i][1])
|
||||
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,imageHeight do
|
||||
for i=1,imageWidth 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
|
||||
|
||||
-- Просканировать файловую систему на наличие .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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user