Advertisement
Guest User

LZW Compression and Encoding

a guest
Feb 1st, 2016
1,031
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 3.65 KB | None | 0 0
  1. local LZW = {}
  2.  
  3. local encodeDict = {}
  4. local decodeDict = {}
  5.  
  6. local numericEncodingChars = {}
  7.  
  8. do
  9.     local c = 33
  10.     for i = 0, 99 do
  11.         if (c == string.byte("-")) then
  12.             c = c + 1 -- skip "-", it is allocated as a lzw encoding delimiter
  13.         end
  14.        
  15.         numericEncodingChars[i] = string.char(c)
  16.        
  17.         c = c + 1
  18.     end
  19. end
  20.  
  21. for i, c in pairs(numericEncodingChars) do
  22.     encodeDict[i] = c
  23.     decodeDict[c] = i
  24. end
  25.  
  26.  
  27. local function getdict(isEncode)
  28.     local dict = {}
  29.    
  30.     local s = " !#$%&'\"()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
  31.     local len = string.len(s)
  32.    
  33.     for i = 1, len do
  34.         if isEncode then
  35.             dict[string.sub(s, i, i)] = i      
  36.         else
  37.             dict[i] = string.sub(s, i, i)
  38.         end
  39.     end
  40.    
  41.     return dict, len
  42. end
  43.  
  44.  
  45. local function getEncodedDictCode(code)
  46.     local encodedDictCode = {}
  47.    
  48.     local nums = ""
  49.     for n in string.gmatch(tostring(code), "%d") do
  50.         local temp = nums .. n
  51.        
  52.         if ((string.sub(temp, 1, 1) ~= "0") and encodeDict[tonumber(temp)]) then
  53.             nums = temp
  54.         else
  55.             encodedDictCode[#encodedDictCode + 1] = encodeDict[tonumber(nums)]
  56.             nums = n
  57.         end
  58.     end
  59.     encodedDictCode[#encodedDictCode + 1] = encodeDict[tonumber(nums)]
  60.    
  61.     return table.concat(encodedDictCode)
  62. end
  63.  
  64. local function encodeDictCodes(codes)
  65.     local translated = {}
  66.    
  67.     for i, code in pairs(codes) do
  68.         translated[i] = getEncodedDictCode(code)
  69.     end
  70.    
  71.     return translated
  72. end
  73.  
  74. local function decodeDictCodes(codes)
  75.     local translated = {}
  76.    
  77.     for i, code in pairs(codes) do
  78.         translated[i] = ""
  79.        
  80.         for c in string.gmatch(code, ".") do
  81.             translated[i] = translated[i] .. decodeDict[c]
  82.         end
  83.        
  84.         translated[i] = tonumber(translated[i])
  85.     end
  86.    
  87.     return translated
  88. end
  89.  
  90.  
  91. function LZW:Compress(text, disableExtraEncoding)
  92.     local s = ""
  93.     local ch
  94.    
  95.     local data = text
  96.    
  97.     local dlen = string.len(data)
  98.     local result = {}
  99.    
  100.     local dict, len = getdict(true)
  101.     local temp
  102.        
  103.     for i = 1, dlen do
  104.         ch = string.sub(data, i, i)
  105.         temp = s .. ch
  106.         if dict[temp] then
  107.             s = temp
  108.         else
  109.             result[#result + 1] = dict[s]
  110.             len = len + 1
  111.             dict[temp] = len
  112.             s = ch
  113.         end
  114.     end
  115.    
  116.     result[#result + 1] = dict[s]
  117.    
  118.     if (not disableExtraEncoding) then
  119.         result = encodeDictCodes(result)
  120.     end
  121.    
  122.     return table.concat(result, "-")
  123. end
  124.  
  125. function LZW:Decompress(text, disableExtraEncoding)
  126.     local dict, len = getdict(false)
  127.    
  128.     local entry
  129.     local ch
  130.     local prevCode, currCode
  131.    
  132.     local result = {}
  133.    
  134.     local data = {}
  135.     for c in string.gmatch(text, '([^%-]+)') do
  136.         data[#data + 1] = c
  137.     end
  138.    
  139.     if (not disableExtraEncoding) then
  140.         data = decodeDictCodes(data)
  141.     end
  142.    
  143.     prevCode = data[1]
  144.     result[#result + 1] = dict[prevCode]
  145.    
  146.     for i = 2, #data do
  147.         currCode = data[i]
  148.         entry = dict[currCode]
  149.        
  150.         if entry then
  151.             ch = string.sub(entry, 1, 1)  
  152.             result[#result + 1] = entry
  153.         else  
  154.             ch = string.sub(dict[prevCode], 1, 1)
  155.             result[#result + 1] = dict[prevCode] .. ch
  156.         end
  157.        
  158.         dict[#dict + 1] = dict[prevCode] .. ch
  159.        
  160.         prevCode = currCode
  161.     end
  162.    
  163.     return table.concat(result)
  164. end
  165.  
  166.  
  167. return LZW
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement