Added completely new image format - it's extremely small and fast. Plus, added some improvements to rendering algorythms.

This commit is contained in:
Igor Timofeev 2015-08-29 00:22:41 +03:00
parent 574ca986cb
commit 09cc715fc8

View File

@ -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