Skip to content

Instantly share code, notes, and snippets.

@visy
Created July 2, 2023 13:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save visy/9eb16a207c5e9394846519fecd905887 to your computer and use it in GitHub Desktop.
Save visy/9eb16a207c5e9394846519fecd905887 to your computer and use it in GitHub Desktop.
TIC-80 LZW graphics compression
pixal="abcdefghijklmnop"
function compressLZW(input)
local dictionary = {}
local result = {}
local dictSize = 256
local p = ""
for i = 0, 255 do
dictionary[string.char(i)] = i
end
local inputLen = #input
local i = 1
while i <= inputLen do
local c = input:sub(i, i)
local pc = p .. c
if dictionary[pc] then
p = pc
else
table.insert(result, dictionary[p])
dictionary[pc] = dictSize
dictSize = dictSize + 1
p = c
end
i = i + 1
end
if p ~= "" then
table.insert(result, dictionary[p])
end
return result
end
function decompressLZW(input)
local dictionary = {}
local result = {}
local dictSize = 256
for i = 0, 255 do
dictionary[i] = string.char(i)
end
local inputLen = #input
local i = 1
local p = dictionary[input[i]]
table.insert(result, p)
i = i + 1
while i <= inputLen do
local code = input[i]
local entry
if dictionary[code] then
entry = dictionary[code]
elseif code == dictSize then
entry = p .. p:sub(1, 1)
else
return nil, "Invalid compressed data"
end
table.insert(result, entry)
dictionary[dictSize] = p .. entry:sub(1, 1)
dictSize = dictSize + 1
p = entry
i = i + 1
end
return table.concat(result)
end
function sget(x,y)
local addr=0x4000+(x//8+y//8*16)*32
return peek4(addr*2+x%8+y%8*8)
end
function sput(x,y,c)
local addr=0x4000+(x//8+y//8*16)*32
return poke4(addr*2+x%8+y%8*8,c)
end
-- Test the compress and decompress functions
local input = ""
for y = 0, 256 do
for x = 0, 128 do
local c = sget(x,y)
c=math.floor(c)
input = input .. string.sub(pixal,c,c)
end
end
trace("Input len: "..#input,0,0)
local compressed = compressLZW(input)
trace("Compressed len: " .. #compressed,0,7)
# compressed data
# local gfxdata = {54,256,257,258,259,54,... etc.
local compressed = gfxdata
local decompressed = decompressLZW(compressed)
function decomp()
-- print("please wait, LZW decompressing")
local i = 1
for y=0,255 do
for x=0,128 do
local cc = string.sub(decompressed,i,i)
local c = 15
if cc == "0" then
c = 0
end
if cc == "1" then
c = 1
end
if cc == "2" then
c = 2
end
if cc == "3" then
c = 3
end
if cc == "4" then
c = 4
end
if cc == "5" then
c = 5
end
if cc == "6" then
c = 6
end
if cc == "7" then
c = 7
end
if cc == "8" then
c = 8
end
if cc == "9" then
c = 9
end
if cc == "A" then
c = 10
end
if cc == "B" then
c = 11
end
if cc == "C" then
c = 12
end
if cc == "D" then
c = 13
end
if cc == "E" then
c = 14
end
if cc == "F" then
c = 15
end
sput(x,y,c)
i = i + 1
end
end
end
trace("Decompressed len: " .. #decompressed .. "",0,14)
trace(string.format("Size diff: %.2f", 100-((#compressed)/(#input)*100)) .. "%",0,22)
trace("compressed data: '" .. table.concat(compressed, ",") .. "'")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment