Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local buffer = require("doubleBuffering")
- local bit32 = require("bit32")
- local args={...}
- local constants = {
- OCIFSignature = "OCIF",
- OCIF2Elements = {
- alphaStart = "A",
- symbolStart = "S",
- backgroundStart = "B",
- foregroundStart = "F",
- },
- elementCount = 4,
- byteSize = 8,
- nullChar = 0,
- rawImageLoadStep = 19,
- compressedFileFormat = ".pic",
- pngFileFormat = ".png",
- }
- local palette = {
- 0x000000, 0x000040, 0x000080, 0x0000BF, 0x0000FF, 0x002400, 0x002440, 0x002480, 0x0024BF, 0x0024FF, 0x004900, 0x004940, 0x004980, 0x0049BF, 0x0049FF, 0x006D00,
- 0x006D40, 0x006D80, 0x006DBF, 0x006DFF, 0x009200, 0x009240, 0x009280, 0x0092BF, 0x0092FF, 0x00B600, 0x00B640, 0x00B680, 0x00B6BF, 0x00B6FF, 0x00DB00, 0x00DB40,
- 0x00DB80, 0x00DBBF, 0x00DBFF, 0x00FF00, 0x00FF40, 0x00FF80, 0x00FFBF, 0x00FFFF, 0x0F0F0F, 0x1E1E1E, 0x2D2D2D, 0x330000, 0x330040, 0x330080, 0x3300BF, 0x3300FF,
- 0x332400, 0x332440, 0x332480, 0x3324BF, 0x3324FF, 0x334900, 0x334940, 0x334980, 0x3349BF, 0x3349FF, 0x336D00, 0x336D40, 0x336D80, 0x336DBF, 0x336DFF, 0x339200,
- 0x339240, 0x339280, 0x3392BF, 0x3392FF, 0x33B600, 0x33B640, 0x33B680, 0x33B6BF, 0x33B6FF, 0x33DB00, 0x33DB40, 0x33DB80, 0x33DBBF, 0x33DBFF, 0x33FF00, 0x33FF40,
- 0x33FF80, 0x33FFBF, 0x33FFFF, 0x3C3C3C, 0x4B4B4B, 0x5A5A5A, 0x660000, 0x660040, 0x660080, 0x6600BF, 0x6600FF, 0x662400, 0x662440, 0x662480, 0x6624BF, 0x6624FF,
- 0x664900, 0x664940, 0x664980, 0x6649BF, 0x6649FF, 0x666D00, 0x666D40, 0x666D80, 0x666DBF, 0x666DFF, 0x669200, 0x669240, 0x669280, 0x6692BF, 0x6692FF, 0x66B600,
- 0x66B640, 0x66B680, 0x66B6BF, 0x66B6FF, 0x66DB00, 0x66DB40, 0x66DB80, 0x66DBBF, 0x66DBFF, 0x66FF00, 0x66FF40, 0x66FF80, 0x66FFBF, 0x66FFFF, 0x696969, 0x787878,
- 0x878787, 0x969696, 0x990000, 0x990040, 0x990080, 0x9900BF, 0x9900FF, 0x992400, 0x992440, 0x992480, 0x9924BF, 0x9924FF, 0x994900, 0x994940, 0x994980, 0x9949BF,
- 0x9949FF, 0x996D00, 0x996D40, 0x996D80, 0x996DBF, 0x996DFF, 0x999200, 0x999240, 0x999280, 0x9992BF, 0x9992FF, 0x99B600, 0x99B640, 0x99B680, 0x99B6BF, 0x99B6FF,
- 0x99DB00, 0x99DB40, 0x99DB80, 0x99DBBF, 0x99DBFF, 0x99FF00, 0x99FF40, 0x99FF80, 0x99FFBF, 0x99FFFF, 0xA5A5A5, 0xB4B4B4, 0xC3C3C3, 0xCC0000, 0xCC0040, 0xCC0080,
- 0xCC00BF, 0xCC00FF, 0xCC2400, 0xCC2440, 0xCC2480, 0xCC24BF, 0xCC24FF, 0xCC4900, 0xCC4940, 0xCC4980, 0xCC49BF, 0xCC49FF, 0xCC6D00, 0xCC6D40, 0xCC6D80, 0xCC6DBF,
- 0xCC6DFF, 0xCC9200, 0xCC9240, 0xCC9280, 0xCC92BF, 0xCC92FF, 0xCCB600, 0xCCB640, 0xCCB680, 0xCCB6BF, 0xCCB6FF, 0xCCDB00, 0xCCDB40, 0xCCDB80, 0xCCDBBF, 0xCCDBFF,
- 0xCCFF00, 0xCCFF40, 0xCCFF80, 0xCCFFBF, 0xCCFFFF, 0xD2D2D2, 0xE1E1E1, 0xF0F0F0, 0xFF0000, 0xFF0040, 0xFF0080, 0xFF00BF, 0xFF00FF, 0xFF2400, 0xFF2440, 0xFF2480,
- 0xFF24BF, 0xFF24FF, 0xFF4900, 0xFF4940, 0xFF4980, 0xFF49BF, 0xFF49FF, 0xFF6D00, 0xFF6D40, 0xFF6D80, 0xFF6DBF, 0xFF6DFF, 0xFF9200, 0xFF9240, 0xFF9280, 0xFF92BF,
- 0xFF92FF, 0xFFB600, 0xFFB640, 0xFFB680, 0xFFB6BF, 0xFFB6FF, 0xFFDB00, 0xFFDB40, 0xFFDB80, 0xFFDBBF, 0xFFDBFF, 0xFFFF00, 0xFFFF40, 0xFFFF80, 0xFFFFBF, 0xFFFFFF,
- }
- function HEXtoRGB(color)
- return bit32.rshift(color, 16), bit32.band(bit32.rshift(color, 8), 0xFF), bit32.band(color, 0xFF)
- end
- function RGBtoHEX(rr, gg, bb)
- return bit32.lshift(rr, 16) + bit32.lshift(gg, 8) + bb
- end
- local function mergeBytesToNumber(...)
- local bytes = {...}
- local finalNumber = bytes[1]
- for i = 2, #bytes do
- finalNumber = bit32.bor(bit32.lshift(finalNumber, 8), bytes[i])
- end
- return finalNumber
- end
- -- Сконвертировать все переданные байты в строку
- local function convertBytesToString(...)
- local bytes = {...}
- for i = 1, #bytes do
- bytes[i] = string.char(bytes[i])
- end
- return table.concat(bytes)
- end
- --Выделить бит-терминатор в первом байте UTF-8 символа: 1100 0010 --> 0010 0000
- local function selectTerminateBit_l()
- local prevByte = nil
- local prevTerminateBit = nil
- return function( byte )
- local x, terminateBit = nil
- if ( prevByte == byte ) then
- return prevTerminateBit
- end
- x = bit32.band( bit32.bnot(byte), 0x000000FF )
- x = bit32.bor( x, bit32.rshift(x, 1) )
- x = bit32.bor( x, bit32.rshift(x, 2) )
- x = bit32.bor( x, bit32.rshift(x, 4) )
- x = bit32.bor( x, bit32.rshift(x, 8) )
- x = bit32.bor( x, bit32.rshift(x, 16) )
- terminateBit = x - bit32.rshift(x, 1)
- prevByte = byte
- prevTerminateBit = terminateBit
- return terminateBit
- end
- end
- local selectTerminateBit = selectTerminateBit_l()
- --Прочитать n байтов из файла, возвращает прочитанные байты как число, если не удалось прочитать, то возвращает 0
- local function readBytes(file, count)
- local readedBytes = file:read(count)
- return mergeBytesToNumber(string.byte(readedBytes, 1, count))
- end
- --Подготавливает цвета и символ для записи в файл сжатого формата
- local function encodePixel(background, foreground, alpha, char)
- --Расхерачиваем жирные цвета в компактные цвета
- local ascii_background1, ascii_background2, ascii_background3 = HEXtoRGB(background)
- local ascii_foreground1, ascii_foreground2, ascii_foreground3 = HEXtoRGB(foreground)
- --Расхерачиваем жирный код юникод-символа в несколько миленьких ascii-кодов
- local ascii_char1, ascii_char2, ascii_char3, ascii_char4, ascii_char5, ascii_char6 = string.byte( char, 1, 6 )
- ascii_char1 = ascii_char1 or constants.nullChar
- --Возвращаем все расхераченное
- return ascii_background1, ascii_background2, ascii_background3, ascii_foreground1, ascii_foreground2, ascii_foreground3, alpha, ascii_char1, ascii_char2, ascii_char3, ascii_char4, ascii_char5, ascii_char6
- end
- --Декодирование UTF-8 символа
- local function decodeChar(file)
- local first_byte = readBytes(file, 1)
- local charcode_array = {first_byte}
- local len = 1
- local middle = selectTerminateBit(first_byte)
- if ( middle == 32 ) then
- len = 2
- elseif ( middle == 16 ) then
- len = 3
- elseif ( middle == 8 ) then
- len = 4
- elseif ( middle == 4 ) then
- len = 5
- elseif ( middle == 2 ) then
- len = 6
- end
- for i = 1, len-1 do
- table.insert( charcode_array, readBytes(file, 1) )
- end
- return string.char( table.unpack( charcode_array ) )
- end
- local function convert8BitTo24Bit(hex8)
- return palette[hex8 + 1]
- end
- local function convertCoordsToIndex(x, y, width)
- return (width * (y - 1) + x) * constants.elementCount - constants.elementCount + 1
- end
- local function optimize(picture)
- local i1, i2, i3 = 0, 0, 0
- for i = 1, #picture, constants.elementCount do
- --Уменьшаем нагрузку на ЦОПЕ
- i1, i2, i3 = i + 1, i + 2, i + 3
- --Если цвет фона равен цвету текста, и используется псевдографические полупиксели
- if picture[i] == picture[i1] and (picture[i3] == "▄" or picture[i3] == "▀") then
- picture[i3] = " "
- end
- --Если символ равен пролбелу, т.е. цвет текста не учитывается
- if picture[i3] == " " then
- picture[i1] = 0x000000
- end
- end
- return picture
- end
- local function loadOCIF2(file, decompressColors, useOCIF4)
- local picture = {}
- --Читаем размер изображения
- local readedWidth = string.byte(file:read(1))
- local readedHeight = string.byte(file:read(1))
- local readednum = string.byte(file:read(1))
- picture.width = readedWidth
- picture.height = readedHeight
- picture.num = readednum
- local header, alpha, symbol, foreground, background, y, alphaSize, symbolSize, foregroundSize, backgroundSize, ySize = ""
- while true do
- header = file:read(1)
- if not header or header == "C" then break end
- -- print("----------------------")
- -- print("Заголовок: " .. header)
- if header == "A" then
- local countOfBytesForArraySize = string.byte(file:read(1))
- alphaSize = string.byte(file:read(countOfBytesForArraySize))
- alpha = string.byte(file:read(1))
- -- print("Количество байт под размер массива символов: " .. countOfBytesForArraySize)
- -- print("Размер массива символов: " .. alphaSize)
- -- print("Альфа: " .. alpha)
- elseif header == "S" then
- if decompressColors then
- symbolSize = string.byte(file:read(1))
- else
- symbolSize = mergeBytesToNumber(string.byte(file:read(3), 1, 3))
- end
- symbol = decodeChar(file)
- -- print("Размер массива цвета текста: " .. symbolSize)
- -- print("Символ: \"" .. symbol .. "\"")
- elseif header == "F" then
- if decompressColors then
- foregroundSize = string.byte(file:read(1))
- foreground = convert8BitTo24Bit(string.byte(file:read(1)))
- else
- foregroundSize = mergeBytesToNumber(string.byte(file:read(3), 1, 3))
- foreground = mergeBytesToNumber(string.byte(file:read(3), 1, 3))
- end
- -- print("Размер массива цвета фона: " .. foregroundSize)
- -- print("Цвет текста: " .. foreground)
- elseif header == "B" then
- backgroundSize = mergeBytesToNumber(string.byte(file:read(2), 1, 2))
- if decompressColors then
- background = convert8BitTo24Bit(string.byte(file:read(1)))
- else
- background = mergeBytesToNumber(string.byte(file:read(3), 1, 3))
- end
- -- print("Размер массива координат: " .. backgroundSize)
- -- print("Цвет фона: " .. background)
- --Поддержка загрузки формата OCIF3
- if not useOCIF4 then
- --Читаем координаты
- for i = 1, backgroundSize, 2 do
- local x = string.byte(file:read(1))
- local y = string.byte(file:read(1))
- local index = convertCoordsToIndex(x, y, readedWidth)
- -- print("Координата: " .. x .. "x" .. y .. ", индекс: "..index)
- picture[index] = background
- picture[index + 1] = foreground
- picture[index + 2] = alpha
- picture[index + 3] = symbol
- end
- end
- --Новый формат OCIF4
- elseif header == "Y" and useOCIF4 then
- ySize = string.byte(file:read(1))
- y = string.byte(file:read(1))
- -- print("Размер массива Y: " .. ySize)
- -- print("Текущий Y: " .. y)
- for i = 1, ySize do
- local x = string.byte(file:read(1))
- local index = convertCoordsToIndex(x, y, readedWidth)
- -- print("Координата: " .. x .. "x" .. y .. ", индекс: "..index)
- picture[index] = background
- picture[index + 1] = foreground
- picture[index + 2] = alpha
- picture[index + 3] = symbol
- end
- else
- error("Error while reading OCIFM format: unknown Header type (" .. header .. ")")
- end
- end
- return picture
- end
- local file = io.open(args[1],"rb")
- if file:read(5) ~= "OCIFM" then
- error("ЭТОТ ФОРМАТ НЕ ПОДДЕРЖИВАЕТСЯ!!!")
- end
- buffer.start()
- while true do
- local chto=file:read(1)
- if chto == "O" then
- local imgdata=optimize(loadOCIF2(file, true, true))
- buffer.image(1, 1, imgdata)
- buffer.draw()
- os.sleep(0)
- elseif not chto then
- break
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement