Advertisement
Guest User

Untitled

a guest
Nov 28th, 2024
214
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 28.32 KB | Source Code | 0 0
  1. local Stream = require("Stream")
  2. local Filters = require("Filter")
  3. local CRC32_Divisor = 4374732215 --CRC32 polynomial coefficents in decimal 4374732215
  4. local WindowSize = 16384 -- Max Deflate Window size for LZ77 is 32768
  5. local HashPrimes = {
  6. 3401963, 8034287, 9866071, 8987161, 2283571, 3562579, 104179, 629171, 1960789, 8242777, 513257, 9585769,
  7. 5199437, 8368433, 5819503, 6581321, 9861821, 9742217, 4044431, 9499669, 6340687, 1716241, 5263861, 420977, 394369, 3937537,
  8. 5556821, 3985243, 2307247, 1916279, 2093653, 6172577, 9951299, 9290329, 5454877, 758729, 8464133, 3400993, 1497347, 1715243,
  9. 9889849, 631471, 1221793, 1545179, 2839789, 5816047, 8199001, 6862727, 5928617, 9878929, 9351557, 6518657, 4504559, 875683,
  10. 2871049, 3684641, 8920943, 1262419, 1645691, 5939903, 1505737, 4718531, 9423277, 9868889, 3956647, 1617689, 6704377, 1126387,
  11. 5973571, 4302359, 6548947, 8009, 1427039, 5935393, 301153, 9189529, 2296363, 3353579, 3387691, 5152333, 7533793, 6834551, 7234753,
  12. 5569301, 7577279, 3170747, 6549727, 3215819, 5796487, 6569971, 4529957, 242419, 2574959, 7296301, 5485499, 5953939, 6158041, 8050873,
  13. 1770493, 4936951, 5865061, 3084451, 6086123, 1919881, 4622707, 8225201, 5648761, 2000753, 3916921, 8413519, 4252111, 8561909, 1081229,
  14. 6744139, 7749799, 5267173, 7913777, 1219487, 1653167, 218857, 1147043, 3011369, 1597157, 7615187, 1509961, 9868913, 7790477, 2968037, 4250591,
  15. 3406811, 3274841, 1350961, 3298579, 1256267, 2105969, 925697, 9698851, 1140239, 104651, 9670351, 5739821, 6623297, 6193799, 3054001, 2924827,
  16. 8540563, 6290497, 2286257, 1158569, 4884029, 237563, 7738457, 5409977, 7462277, 3698257, 3456863, 407503, 23929, 7025969, 4926941, 2593439, 9422927,
  17. 6764753, 4200769, 451667, 7167361, 2598971, 5236061, 8540237, 4198703, 5650769, 6816493, 8362649, 9495341, 3891383, 1370533, 4784687, 5674511, 87359,
  18. 5933467, 3833197, 6794539, 8717131, 6684089, 1753597, 4013197, 8171, 3120317, 7334441, 1125391, 840473, 7173863, 3005291, 316697, 3069421, 2634131, 3823319,
  19. 3069791, 8166317, 6201571, 2154707, 1545391, 4620101, 7707907, 4961531, 4624457, 2858393, 7834051, 6143519, 6676261, 4358531, 7572661, 7124977, 747839, 9957581,
  20. 7953107, 6957497, 3720877, 1660723, 6520223, 8838043, 6660391, 6869857, 8573207, 4806001, 6687463, 7846063, 3614041, 1978349, 4654217, 1213357, 778417, 494927,
  21. 2343329, 1581653, 1447217, 836317, 8163401, 9220847, 4251847, 34519, 7478717, 9845777, 6608737, 1789217, 405407, 6430799, 7344269, 5286839, 3699337, 715699,
  22. 4607593, 3542369, 1095541, 7886911, 28309
  23. }
  24. local CLCodeAlpabetOrder = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}
  25. local CLCodeExtraBits = {
  26.     [16] = {3, 2}, --min length, extrabits
  27.     [17] = {3, 3},
  28.     [18] = {11, 7}
  29. }
  30. local LengthCodes = {
  31.     --[[
  32.     the index is the code, the first value in table is the extra bits to read and add
  33.     onto the second value; the second value refers to the minimum length
  34.     ]]
  35.     [257] = {0, 3},
  36.     [258] = {0, 4},
  37.     [259] = {0, 5},
  38.     [260] = {0, 6},
  39.     [261] = {0, 7},
  40.     [262] = {0, 8},
  41.     [263] = {0, 9},
  42.     [264] = {0, 10},
  43.     [265] = {1, 11},
  44.     [266] = {1, 13},
  45.     [267] = {1, 15},
  46.     [268] = {1, 17},
  47.     [269] = {2, 19},
  48.     [270] = {2, 23},
  49.     [271] = {2, 27},
  50.     [272] = {2, 31},
  51.     [273] = {3, 35},
  52.     [274] = {3, 43},
  53.     [275] = {3, 51},
  54.     [276] = {3, 59},
  55.     [277] = {4, 67},
  56.     [278] = {4, 83},
  57.     [279] = {4, 99},
  58.     [280] = {4, 115},
  59.     [281] = {5, 131},
  60.     [282] = {5, 163},
  61.     [283] = {5, 195},
  62.     [284] = {5, 227},
  63.     [285] = {0, 258}
  64. }
  65. local DistanceCodes = {
  66.     [0] = {0, 1},
  67.     [1] = {0, 2},
  68.     [2] = {0, 3},
  69.     [3] = {0, 4},
  70.     [4] = {1, 5},
  71.     [5] = {1, 7},
  72.     [6] = {2, 9},
  73.     [7] = {2, 13},
  74.     [8] = {3, 17},
  75.     [9] = {3, 25},
  76.     [10] = {4, 33},
  77.     [11] = {4, 49},
  78.     [12] = {5, 65},
  79.     [13] = {5, 97},
  80.     [14] = {6, 129},
  81.     [15] = {6, 193},
  82.     [16] = {7, 257},
  83.     [17] = {7, 385},
  84.     [18] = {8, 513},
  85.     [19] = {8, 769},
  86.     [20] = {9, 1025},
  87.     [21] = {9, 1537},
  88.     [22] = {10, 2049},
  89.     [23] = {10, 3073},
  90.     [24] = {11, 4097},
  91.     [25] = {11, 6145},
  92.     [26] = {12, 8193},
  93.     [27] = {12, 12289},
  94.     [28] = {13, 16385},
  95.     [29] = {13, 24577},
  96. }
  97.  
  98. function GetCRC32(Bytes)
  99.     local Register = 0xFFFFFFFF --register is initialized to all 1s
  100.  
  101.     --extra bytes in place of final CRC
  102.     Bytes[#Bytes+1] = 0
  103.     Bytes[#Bytes+1] = 0
  104.     Bytes[#Bytes+1] = 0
  105.     Bytes[#Bytes+1] = 0
  106.  
  107.     --need to XOR in first 4 bytes since register doesn't start with all 0s
  108.     Register = Register ~ (Reverse8(Bytes[1]) << 24 | Reverse8(Bytes[2]) << 16 | Reverse8(Bytes[3]) << 8 | Reverse8(Bytes[4]))
  109.  
  110.     local CurrentByte = 5
  111.     local CurrentBit = 0
  112.  
  113.     while CurrentByte <= #Bytes or (Register >> 32) & 1 == 1 do
  114.         if (Register >> 32) & 1 == 1 then
  115.             Register = Register ~ CRC32_Divisor
  116.         else
  117.             Register = Register << 1 | ((Bytes[CurrentByte] >> CurrentBit) & 1)
  118.             CurrentBit = CurrentBit + 1
  119.  
  120.             if CurrentBit > 7 then
  121.                 CurrentBit = 0
  122.                 CurrentByte = CurrentByte + 1
  123.             end
  124.         end
  125.     end
  126.  
  127.     return Reverse32(Register ~ 0xFFFFFFFF) -- Register's ones complement is taken and flipped for final CRC
  128. end
  129.  
  130. function SwitchEndian16(Bytes)
  131.     return ((Bytes << 8) & 0xFF00) | ((Bytes >> 8) & 0xFF)
  132. end
  133.  
  134. function Reverse32(Num) -- reverses a 32 bit unsigned integer
  135.     Num = ((Num << 16) & 0xFFFF0000) | ((Num >> 16) & 0xFFFF)
  136.     Num = ((Num << 8) & 0xFF00FF00) | ((Num >> 8) & 0xFF00FF)
  137.     Num = ((Num << 4) & 0xF0F0F0F0) | ((Num >> 4) & 0xF0F0F0F)
  138.     Num = ((Num << 2) & 0xCCCCCCCC) | ((Num >> 2) & 0x33333333)
  139.     Num = ((Num << 1) & 0xAAAAAAAA) | ((Num >> 1) & 0x55555555)
  140.     return Num
  141. end
  142.  
  143. function Reverse8(Num)
  144.     Num = ((Num << 4) & 0xF0) | ((Num >> 4) & 0xF)
  145.     Num = ((Num << 2) & 0xCC) | ((Num >> 2) & 0x33)
  146.     Num = ((Num << 1) & 0xAA) | ((Num >> 1) & 0x55)
  147.     return Num
  148. end
  149.  
  150. function GetLenDistSymbols(Len, Dist)
  151.     local LenCode = nil
  152.     local DistCode = nil
  153.  
  154.     for i = 257, 285, 1 do
  155.         if Len >= LengthCodes[i][2] and (LengthCodes[i+1] == nil or Len < LengthCodes[i+1][2]) then
  156.             LenCode = i
  157.             break
  158.         end
  159.     end
  160.  
  161.     for i = 0, 29, 1 do
  162.         if Dist >= DistanceCodes[i][2] and (DistanceCodes[i+1] == nil or Dist < DistanceCodes[i+1][2]) then
  163.             DistCode = i
  164.             break
  165.         end
  166.     end
  167.  
  168.     return LenCode, Len - LengthCodes[LenCode][2], DistCode, Dist - DistanceCodes[DistCode][2]
  169. end
  170.  
  171. function GetAdler32(Bytes) --Checksum for Zlib footer as defined in the RFC 1950 spec
  172.     local s1 = 1
  173.     local s2 = 0
  174.     for i, byte in pairs(Bytes) do
  175.         s1 = (s1 + byte) % 65521
  176.         s2 = (s2 + s1) % 65521
  177.     end
  178.     return s2 * 65536 + s1
  179. end
  180.  
  181. function GenerateFixedCodes()
  182.     local PrefixCodes = {}
  183.  
  184.     for i = 0, 143, 1 do
  185.         PrefixCodes[i] = {48 + i, 8}
  186.     end
  187.     for i = 144, 255, 1 do
  188.         PrefixCodes[i] = {400 + (i-144), 9}
  189.     end
  190.     for i = 256, 279, 1 do
  191.         PrefixCodes[i] = {i - 256, 7}
  192.     end
  193.     for i = 280, 287, 1 do
  194.         PrefixCodes[i] = {192 + (i-280), 8}
  195.     end
  196.  
  197.     return PrefixCodes
  198. end
  199.  
  200. function Hash(n1, n2, n3, mod)
  201.     return (((n1+n3) * HashPrimes[(n3 & 0xFF) + 1]) - (n2 * HashPrimes[((n1-n3) & 0xFF) + 1]) + (n3 * HashPrimes[(n1 & 0xFF) + 1])) % mod
  202. end
  203.  
  204. function GenerateHashTable(ByteStream)
  205.     local HashTable = {}
  206.     local TableSize = #ByteStream * 5
  207.  
  208.     for i = 1, #ByteStream - 2, 1 do
  209.         local HashValue = Hash(ByteStream[i], ByteStream[i+1], ByteStream[i+2], TableSize)
  210.         if HashTable[HashValue] == nil then
  211.             HashTable[HashValue] = {i}
  212.         else
  213.             HashTable[HashValue][#HashTable[HashValue]+1] = i
  214.         end
  215.     end
  216.  
  217.     return HashTable
  218. end
  219.  
  220. function GetBounds(Indexes, Min, Max)
  221.     --doesnt converage exactly, off by 1-2 indexes
  222.  
  223.     local L1 = 1
  224.     local L2 = (#Indexes+1)//2
  225.     local L3 = #Indexes
  226.     local U1 = 1
  227.     local U2 = (#Indexes+1)//2
  228.     local U3 = #Indexes
  229.  
  230.     while (L3 - L2 > 1) or (U3 - U2 > 1) do
  231.         if Min > Indexes[L2] then
  232.             L1 = L2
  233.             L2 = (L1 + L3)//2
  234.         else
  235.             L3 = L2
  236.             L2 = (L1 + L3)//2
  237.         end
  238.  
  239.         if Max > Indexes[U2] then
  240.             U1 = U2
  241.             U2 = (U1 + U3)//2
  242.         else
  243.             U3 = U2
  244.             U2 = (U1 + U3)//2
  245.         end
  246.     end
  247.  
  248.     return L1, U3
  249. end
  250.  
  251. function ChooseMatch(ByteStream, StartIdx, PossibleIndexes)
  252.     local LongestMatch = 0
  253.     local MatchIdx = nil
  254.     local Min, Max = GetBounds(PossibleIndexes, StartIdx - WindowSize, StartIdx)
  255.     local MaxSearchDepth = 200
  256.  
  257.     for i = Max, Min, -1 do
  258.         local PossibleMatch = PossibleIndexes[i]
  259.         if PossibleMatch < StartIdx and StartIdx - WindowSize < PossibleMatch then
  260.             local MatchLen = 0 --starting at 0 incase of collisions in hashmap
  261.             while MatchLen < 258 do
  262.                 if ByteStream[PossibleMatch + MatchLen] == ByteStream[StartIdx + MatchLen] then
  263.                     MatchLen = MatchLen + 1
  264.                 else
  265.                     break
  266.                 end
  267.             end
  268.  
  269.             if MatchLen > LongestMatch and MatchLen >= 3 then
  270.                 LongestMatch = MatchLen
  271.                 MatchIdx = i
  272.             end
  273.  
  274.             if Max - i > MaxSearchDepth then break end --give up search after checking some possible matches
  275.  
  276.         end
  277.     end
  278.  
  279.     return MatchIdx, LongestMatch
  280. end
  281.  
  282. function LZ77(ByteStream)
  283.     local CompressedStream = {}
  284.     local HashTable = GenerateHashTable(ByteStream)
  285.     local HashMod = #ByteStream * 5
  286.     local CurrentIdx = 2 - WindowSize
  287.  
  288.     CompressedStream[1] = ByteStream[1]
  289.  
  290.     while CurrentIdx <= #ByteStream - WindowSize - 2 do
  291.         local StartIdx = CurrentIdx + WindowSize
  292.         local PossibleMatches = HashTable[Hash(ByteStream[StartIdx], ByteStream[StartIdx+1], ByteStream[StartIdx+2], HashMod)]
  293.         local BestMatch, Len = ChooseMatch(ByteStream, StartIdx, PossibleMatches)
  294.  
  295.         if ByteStream[StartIdx+3] ~= nil then
  296.             local NextPossibleMatches = HashTable[Hash(ByteStream[StartIdx+1], ByteStream[StartIdx+2], ByteStream[StartIdx+3], HashMod)]
  297.             local NextBestMatch, NextLen = ChooseMatch(ByteStream, StartIdx+1, NextPossibleMatches)
  298.             if NextLen - 1 > Len then
  299.                 CompressedStream[#CompressedStream+1] = ByteStream[StartIdx]
  300.                 BestMatch, Len = NextBestMatch, NextLen
  301.                 PossibleMatches = NextPossibleMatches
  302.                 StartIdx = StartIdx + 1
  303.                 CurrentIdx = CurrentIdx + 1
  304.             end
  305.         end
  306.  
  307.         CurrentIdx = CurrentIdx + Len + 1
  308.  
  309.         if Len ~= 0 then
  310.             CompressedStream[#CompressedStream+1] = {GetLenDistSymbols(Len, StartIdx - PossibleMatches[BestMatch])}
  311.             CurrentIdx = CurrentIdx - 1
  312.         else
  313.             CompressedStream[#CompressedStream+1] = ByteStream[StartIdx]
  314.         end
  315.     end
  316.  
  317.     for i = CurrentIdx + WindowSize, #ByteStream, 1 do
  318.         CompressedStream[#CompressedStream+1] = ByteStream[i]
  319.     end
  320.  
  321.     return CompressedStream
  322. end
  323.  
  324. function GetLiteralDistFrequencies(Symbols)
  325.     local Frequencies = {}
  326.     local DistFrequencies = {}
  327.  
  328.     for i, v in pairs(Symbols) do
  329.         if type(v) == "table" then
  330.             local LengthSymbol = v[1]
  331.             local DistSymbol = v[3]
  332.             if Frequencies[LengthSymbol] == nil then Frequencies[LengthSymbol] = 0 end
  333.             if DistFrequencies[DistSymbol] == nil then DistFrequencies[DistSymbol] = 0 end
  334.  
  335.             Frequencies[LengthSymbol] = Frequencies[LengthSymbol] + 1
  336.             DistFrequencies[DistSymbol] = DistFrequencies[DistSymbol] + 1
  337.         else
  338.             if Frequencies[v] == nil then Frequencies[v] = 0 end
  339.             Frequencies[v] = Frequencies[v] + 1
  340.         end
  341.     end
  342.  
  343.     return Frequencies, DistFrequencies
  344. end
  345.  
  346. function GetCLSymbolFrequncies(Symbols)
  347.     local Frequencies = {}
  348.  
  349.     for i, v in pairs(Symbols) do
  350.         if type(v) == "table" then
  351.             local Symbol = v[1]
  352.             if Frequencies[Symbol] == nil then Frequencies[Symbol] = 0 end
  353.             Frequencies[Symbol] = Frequencies[Symbol] + 1
  354.         else
  355.             if Frequencies[v] == nil then Frequencies[v] = 0 end
  356.             Frequencies[v] = Frequencies[v] + 1
  357.         end
  358.     end
  359.  
  360.     return Frequencies
  361. end
  362.  
  363. function SortProbabilities(Probabilities) --radix sort to sort frequencies
  364.     local SortedProbabilities = {}
  365.     local BitDepth = 1
  366.  
  367.     local Bin0 = {}
  368.     local Bin1 = {}
  369.  
  370.     SortedProbabilities[1] = Bin0
  371.     SortedProbabilities[2] = Bin1
  372.  
  373.     for i, v in pairs(Probabilities) do
  374.         if v[2] & 1 == 0 then
  375.             Bin0[#Bin0+1] = v
  376.         else
  377.             Bin1[#Bin1+1] = v
  378.         end
  379.     end
  380.  
  381.     while #Bin0 ~= #Probabilities do
  382.         local UpdatedBin0 = {}
  383.         local UpdatedBin1 = {}
  384.  
  385.         for j = 1, 2, 1 do
  386.             for i, v in pairs(SortedProbabilities[j]) do
  387.                 if v[2] >> BitDepth & 1 == 0 then
  388.                     UpdatedBin0[#UpdatedBin0+1] = v
  389.                 else
  390.                     UpdatedBin1[#UpdatedBin1+1] = v
  391.                 end
  392.             end
  393.         end
  394.  
  395.         Bin0 = UpdatedBin0
  396.         Bin1 = UpdatedBin1
  397.         SortedProbabilities = {Bin0, Bin1}
  398.         BitDepth = BitDepth + 1
  399.  
  400.     end
  401.  
  402.     SortedProbabilities = Bin0
  403.  
  404.     return SortedProbabilities
  405. end
  406.  
  407. function MergeSorted(Table1, Table2)
  408.     local MergedTable = {}
  409.     local P1 = 1
  410.     local P2 = 1
  411.  
  412.     while #MergedTable ~= #Table1 + #Table2 do
  413.         if Table2[P2] == nil or (Table1[P1] ~= nil and Table1[P1][2] < Table2[P2][2])  then
  414.             MergedTable[#MergedTable+1] = Table1[P1]
  415.             P1 = P1 + 1
  416.         else
  417.             MergedTable[#MergedTable+1] = Table2[P2]
  418.             P2 = P2 + 1
  419.         end
  420.     end
  421.  
  422.     return MergedTable
  423. end
  424.  
  425. function FlattenTable(Table)
  426.     local FlatTable = {}
  427.  
  428.     for i, v in pairs(Table) do
  429.         if type(v) == "table" then
  430.             local Items = FlattenTable(v)
  431.             for _, k in pairs(Items) do
  432.                 FlatTable[#FlatTable+1] = k
  433.             end
  434.         else
  435.             FlatTable[#FlatTable+1] = v
  436.         end
  437.     end
  438.  
  439.     return FlatTable
  440. end
  441.  
  442. function GetCodeLengths(Frequencies) --package merge algorithim for limited length huffman coding
  443.     local Probabilities = {}
  444.     local CodeLengths = {}
  445.     local TotalSymbols = 0
  446.  
  447.     for i, v in pairs(Frequencies) do
  448.         TotalSymbols = TotalSymbols + 1
  449.         Probabilities[#Probabilities+1] = {i, v}
  450.         CodeLengths[i] = 0
  451.     end
  452.  
  453.     Probabilities = SortProbabilities(Probabilities)
  454.     local MaxLen = math.ceil(math.log(TotalSymbols, 2))
  455.     local OriginalProbabilties = Probabilities
  456.  
  457.     for i = 1, MaxLen-1, 1 do
  458.         local MergedSymbols = {}
  459.         for j = 1, #Probabilities//2, 1 do
  460.             local Item1 = Probabilities[(j-1)*2 + 1]
  461.             local Item2 = Probabilities[(j-1)*2 + 2]
  462.  
  463.             MergedSymbols[#MergedSymbols+1] = {{Item1[1], Item2[1]}, Item1[2] + Item2[2]}
  464.         end
  465.         Probabilities = MergeSorted(OriginalProbabilties, MergedSymbols)
  466.     end
  467.  
  468.     local LenFrequencies = {}
  469.  
  470.     for i = 1, 2 * TotalSymbols - 2, 1 do
  471.         LenFrequencies[#LenFrequencies+1] = Probabilities[i][1]
  472.     end
  473.  
  474.     for i, v in pairs(FlattenTable(LenFrequencies)) do
  475.         CodeLengths[v] = CodeLengths[v] + 1
  476.     end
  477.  
  478.     local sum = 0
  479.  
  480.     for i, v in pairs(CodeLengths) do
  481.         sum = sum + 2^(-v)
  482.     end
  483.  
  484.     if sum > 1 then print("Error: Prefix code generation broke") return end
  485.  
  486.     return CodeLengths
  487. end
  488.  
  489. function GenerateCodesFromLengths(Lengths)
  490.     local LengthFrequencies = {}
  491.     local CurrentCodeAtLen = {}
  492.     local FinalCodes = {}
  493.     local MinLen = 16
  494.     local MaxLen = -1
  495.     local MaxSymbol = -1
  496.  
  497.     for i, v in pairs(Lengths) do
  498.         LengthFrequencies[v] = LengthFrequencies[v] ~= nil and LengthFrequencies[v] + 1 or 1
  499.         if v > MaxLen then MaxLen = v end
  500.         if v < MinLen then MinLen = v end
  501.         if i > MaxSymbol then MaxSymbol = i end
  502.     end
  503.  
  504.     CurrentCodeAtLen[MinLen] = 0
  505.     local PrevLen = MinLen
  506.  
  507.     for i = MinLen + 1, MaxLen, 1 do
  508.         if LengthFrequencies[i] ~= nil then
  509.             CurrentCodeAtLen[i] = (CurrentCodeAtLen[PrevLen] + LengthFrequencies[PrevLen]) << (i - PrevLen)
  510.             PrevLen = i
  511.         end
  512.     end
  513.  
  514.     for i = 0, MaxSymbol, 1 do --codes of same length are assigned in order
  515.         local Len = Lengths[i]
  516.         if Len ~= nil then
  517.             FinalCodes[i] = {CurrentCodeAtLen[Len], Len}
  518.             CurrentCodeAtLen[Len] = CurrentCodeAtLen[Len] + 1
  519.         else
  520.             FinalCodes[i] = {nil, 0} --symbol was not used
  521.         end
  522.     end
  523.  
  524.     return FinalCodes
  525. end
  526.  
  527. function FindRunLength(Table, Idx)
  528.     local InitalValue = Table[Idx]
  529.  
  530.     for i = Idx + 1, #Table, 1 do
  531.         if Table[i] ~= InitalValue then
  532.             return i - Idx
  533.         end
  534.     end
  535.  
  536.     return #Table - Idx
  537. end
  538.  
  539. function GetPrefixCodes(Freqencies)
  540.     local CodeLengths = GetCodeLengths(Freqencies)
  541.     local PrefixCodes = GenerateCodesFromLengths(CodeLengths)
  542.     return PrefixCodes
  543. end
  544.  
  545. function CompressHuffmanLengths(LLCodes, DistCodes)
  546.     local AllLengths = {} --The literal-length codes' lengths can continue into the distance codes' lengths
  547.     local CompressedLengths = {}
  548.  
  549.     for i = 0, #LLCodes, 1 do
  550.         AllLengths[#AllLengths+1] = LLCodes[i][2]
  551.     end
  552.  
  553.     for i = 0, #DistCodes, 1 do
  554.         AllLengths[#AllLengths+1] = DistCodes[i][2]
  555.     end
  556.  
  557.     local i = 1
  558.  
  559.     while i <= #AllLengths do
  560.         local RunLength = FindRunLength(AllLengths, i)
  561.  
  562.         if RunLength >= 4 then
  563.             local ExtraBits
  564.  
  565.             if AllLengths[i] ~= 0 then
  566.                 ExtraBits = math.min(6, RunLength - 1)
  567.                 CompressedLengths[#CompressedLengths+1] = AllLengths[i]
  568.                 CompressedLengths[#CompressedLengths+1] = {16, ExtraBits}
  569.                 i = i + 1 --adding one since we pushed a length and symbol here
  570.             elseif RunLength <= 10 then
  571.                 --Symbols 17 and 18 represent only 0s
  572.                 ExtraBits = math.min(10, RunLength)
  573.                 CompressedLengths[#CompressedLengths+1] = {17, ExtraBits}
  574.             else
  575.                 ExtraBits = math.min(138, RunLength)
  576.                 CompressedLengths[#CompressedLengths+1] = {18, ExtraBits}
  577.             end
  578.             i = i + ExtraBits
  579.         else
  580.             CompressedLengths[#CompressedLengths+1] = AllLengths[i]
  581.             i = i + 1
  582.         end
  583.     end
  584.  
  585.     return CompressedLengths
  586. end
  587.  
  588. function WriteRawData(Bytes, ByteStream, Final)
  589.  
  590.     if #Bytes > 0xFFFF then print("Block type 0 can only have 2^16 - 1 Bytes") return end
  591.  
  592.     local LEN = #Bytes
  593.     local NLEN = LEN ~ 0xFFFF
  594.  
  595.     ByteStream:PushBits(Final and 1 or 0, 1)
  596.     ByteStream:PushBits(0, 2)
  597.     ByteStream:PushBits(0, ByteStream.BitIndex ~= 0 and 8 - ByteStream.BitIndex or 0) -- padding until next byte
  598.  
  599.     ByteStream:PushNumber(LEN, 16)
  600.     ByteStream:PushNumber(NLEN, 16)
  601.  
  602.     for i, Byte in pairs(Bytes) do
  603.         ByteStream:PushNumber(Byte, 8)
  604.     end
  605. end
  606.  
  607. function CompressFixedDeflateBlock(Bytes, ByteStream, Final)
  608.     local PrefixCodes = GenerateFixedCodes()
  609.  
  610.     ByteStream:PushBits(Final and 1 or 0, 1)
  611.     ByteStream:PushNumber(1, 2)
  612.  
  613.     Bytes[#Bytes+1] = 256 --End of Block marker
  614.  
  615.     for i, Byte in pairs(Bytes) do
  616.         if type(Byte) == "number" then
  617.             local CodeInfo = PrefixCodes[Byte]
  618.             ByteStream:PushBits(CodeInfo[1], CodeInfo[2])
  619.         else
  620.             local LenBits = LengthCodes[Byte[1]][1]
  621.             local DistBits = DistanceCodes[Byte[3]][1]
  622.             local LenCodeInfo = PrefixCodes[Byte[1]]
  623.  
  624.             --distances have their own prefix codes!!! (the codes turn out to be just the number as 5 bits, but still pushed as a code)
  625.  
  626.             ByteStream:PushBits(LenCodeInfo[1], LenCodeInfo[2])
  627.             ByteStream:PushNumber(Byte[2], LenBits)
  628.             ByteStream:PushBits(Byte[3], 5)
  629.             ByteStream:PushNumber(Byte[4], DistBits)
  630.         end
  631.     end
  632.  
  633. end
  634.  
  635. function CompressDynamicDeflateBlock(Bytes, ByteStream, Final)
  636.  
  637.     ByteStream:PushBits(Final and 1 or 0, 1)
  638.     ByteStream:PushNumber(2, 2)
  639.  
  640.     Bytes[#Bytes+1] = 256
  641.  
  642.     --Generating all the huffman tables
  643.     local LLFreq, DistFreq = GetLiteralDistFrequencies(Bytes)
  644.     local LLCodes, DistCodes = GetPrefixCodes(LLFreq), GetPrefixCodes(DistFreq)
  645.     if DistCodes[0] == nil then DistCodes[0] = {nil, 0} end --need to push a single distance code in case distances arent used since HDIST is 5 bits (0-32) and we encode HDIST - 1 so decoder expects at least 1 distance code
  646.     local CompressedHuffmanLengths = CompressHuffmanLengths(LLCodes, DistCodes)
  647.     local CLCodeFreq = GetCLSymbolFrequncies(CompressedHuffmanLengths)
  648.     local CLCodePrefixCodes = GetPrefixCodes(CLCodeFreq)
  649.  
  650.     local CLCodesOrder = {}
  651.     local HCLEN = 0 --HCLEN is calculated from where the lengths appear in the weird order
  652.  
  653.     for i, v in pairs(CLCodeAlpabetOrder) do
  654.         if CLCodePrefixCodes[v] == nil then CLCodePrefixCodes[v] = {nil, 0} end
  655.         CLCodesOrder[i] = CLCodePrefixCodes[v]
  656.         if CLCodePrefixCodes[v][2] ~= 0 then
  657.             HCLEN = i
  658.         end
  659.     end
  660.  
  661.     local HLIT = #LLCodes - 257 + 1 -- note: # operator in Lua returns length from 1 to last non-nil element in order in a table, so +1 for code 0
  662.     local HDIST = #DistCodes - 1 + 1
  663.     HCLEN = HCLEN - 4
  664.  
  665.     ByteStream:PushNumber(HLIT, 5)
  666.     ByteStream:PushNumber(HDIST, 5)
  667.     ByteStream:PushNumber(HCLEN, 4)
  668.  
  669.     for i = 1, HCLEN + 4, 1 do
  670.         ByteStream:PushNumber(CLCodesOrder[i][2], 3)
  671.     end
  672.  
  673.     for i, v in pairs(CompressedHuffmanLengths) do
  674.         if type(v) == "table" then
  675.             local PrefixCodeInfo = CLCodePrefixCodes[v[1]]
  676.             local ExtraBitInfo = CLCodeExtraBits[v[1]]
  677.             ByteStream:PushBits(PrefixCodeInfo[1], PrefixCodeInfo[2])
  678.             ByteStream:PushNumber(v[2] - ExtraBitInfo[1], ExtraBitInfo[2])
  679.         else
  680.             local PrefixCodeInfo = CLCodePrefixCodes[v]
  681.             ByteStream:PushBits(PrefixCodeInfo[1], PrefixCodeInfo[2])
  682.         end
  683.     end
  684.  
  685.     for i, Byte in pairs(Bytes) do
  686.         if type(Byte) == "number" then
  687.             local CodeInfo = LLCodes[Byte]
  688.             ByteStream:PushBits(CodeInfo[1], CodeInfo[2])
  689.         else
  690.             local LenBits = LengthCodes[Byte[1]][1]
  691.             local DistBits = DistanceCodes[Byte[3]][1]
  692.             local LenCodeInfo = LLCodes[Byte[1]]
  693.             local DistCodeInfo = DistCodes[Byte[3]]
  694.  
  695.             ByteStream:PushBits(LenCodeInfo[1], LenCodeInfo[2])
  696.             ByteStream:PushNumber(Byte[2], LenBits)
  697.             ByteStream:PushBits(DistCodeInfo[1], DistCodeInfo[2])
  698.             ByteStream:PushNumber(Byte[4], DistBits)
  699.         end
  700.     end
  701.  
  702. end
  703.  
  704. function SplitIntoBlocks(Data) --Splitting into Deflate blocks of size 16384, this can be optimzed for better compression
  705.     local Blocks = {}
  706.  
  707.     for i = 1, math.ceil(#Data/16384), 1 do
  708.         Blocks[i] = {}
  709.         local Idx = (i-1) * 16384 + 1
  710.  
  711.         for j = 1, 16384, 1 do
  712.             Blocks[i][j] = Data[Idx]
  713.             Idx = Idx + 1
  714.         end
  715.     end
  716.  
  717.     return Blocks
  718. end
  719.  
  720. function Deflate(Data)
  721.     --Zlib header
  722.     local ByteStream = Stream.New()
  723.     local CMF = "00001000" --Compression Method (DEFLATE) and flags
  724.     local FLG = "00011101" --Compression and weird checksum such that (CMF * 256 + FLG) % 31 = 0
  725.  
  726.     ByteStream:PushNumber(tonumber(CMF, 2), 8) --I flippled the CMF and FLG so pushing reversed (like a number)
  727.     ByteStream:PushNumber(tonumber(FLG, 2), 8)
  728.  
  729.     local SqueezedData = LZ77(Data)
  730.     local Blocks = SplitIntoBlocks(SqueezedData)
  731.  
  732.     for i, Block in pairs(Blocks) do
  733.         if #Block > 8192 then
  734.             CompressDynamicDeflateBlock(Block, ByteStream, i == #Blocks)
  735.         else
  736.             CompressFixedDeflateBlock(Block, ByteStream, i == #Blocks)
  737.         end
  738.     end
  739.  
  740.     if ByteStream.BitIndex ~= 0 then --Stream padding to byte align is added before the adler32
  741.         ByteStream:PushBits(0, 8 - ByteStream.BitIndex)
  742.     end
  743.  
  744.     local Adler32 = GetAdler32(Data)
  745.  
  746.     ByteStream:PushNumber((Adler32 >> 24) & 0xFF, 8)
  747.     ByteStream:PushNumber((Adler32 >> 16) & 0xFF, 8)
  748.     ByteStream:PushNumber((Adler32 >> 8) & 0xFF, 8)
  749.     ByteStream:PushNumber(Adler32 & 0xFF, 8)
  750.  
  751.     return ByteStream.Bytes
  752. end
  753.  
  754. function AbsDiff(Data)
  755.     local Sum = 0
  756.  
  757.     for i, v in pairs(Data) do
  758.         Sum = Sum + (v < 128 and v or 256 - v)
  759.     end
  760.  
  761.     return math.abs(Sum)
  762. end
  763.  
  764. function FilterBytes(Bytes, BPP, FilterOn) --BPP (Bytes Per Pixel)
  765.     local FilteredBytes = {}
  766.  
  767.     if not FilterOn then
  768.         for i, row in pairs(Bytes) do
  769.             FilteredBytes[i] = Filters.None(row)
  770.         end
  771.         return FilteredBytes
  772.     end
  773.  
  774.     for i, row in pairs(Bytes) do
  775.         local MinSum = 999999999999999999
  776.  
  777.         local NoneResult = Filters.None(row)
  778.         local SubResult = Filters.Sub(row, BPP)
  779.         local UpResult = Filters.Up(row, Bytes[i-1], BPP)
  780.         local AvgResult = Filters.Average(row, Bytes[i-1], BPP)
  781.         local PaethResult = Filters.Paeth(row, Bytes[i-1], BPP)
  782.         local Results = {NoneResult, SubResult, UpResult, AvgResult, PaethResult}
  783.  
  784.         for j, v in pairs(Results) do
  785.             local RowSum = AbsDiff(v)
  786.             if RowSum < MinSum then
  787.                 MinSum = RowSum
  788.                 FilteredBytes[i] = v
  789.             end
  790.         end
  791.     end
  792.  
  793.     return Filters.Vectorize(FilteredBytes)
  794. end
  795.  
  796. function EncodePNG(FileName, Width, Height, Pixels, ColorType, FilterOn)
  797.     local Image = io.open(FileName, "wb")
  798.     local BinaryInfo = {}
  799.  
  800.     if not (ColorType == 2 or ColorType == 6) then print("Currently only colortypes 2 and 6 are valid") return end
  801.  
  802.     --PNG File Header bytes in decimal
  803.     BinaryInfo[1] = string.pack(">I1", 137)
  804.     BinaryInfo[2] = string.pack(">I1", 80)
  805.     BinaryInfo[3] = string.pack(">I1", 78)
  806.     BinaryInfo[4] = string.pack(">I1", 71)
  807.     BinaryInfo[5] = string.pack(">I1", 13)
  808.     BinaryInfo[6] = string.pack(">I1", 10)
  809.     BinaryInfo[7] = string.pack(">I1", 26)
  810.     BinaryInfo[8] = string.pack(">I1", 10)
  811.  
  812.     --IHDR Chunk
  813.     BinaryInfo[9] = string.pack(">I4", 13) -- chunk length
  814.  
  815.     local IHDR = {}
  816.     IHDR[1] = string.pack(">I4",  1229472850) -- chunk type
  817.     IHDR[2] = string.pack(">I4", Width)
  818.     IHDR[3] = string.pack(">I4", Height)
  819.     IHDR[4] = string.pack(">I1", 8) -- fixing bit depth at 8
  820.     IHDR[5] = string.pack(">I1", ColorType)
  821.     IHDR[6] = string.pack(">I1", 0) -- compression method is DEFLATE
  822.     IHDR[7] = string.pack(">I1", 0) -- filter method (only method 0 is defined)
  823.     IHDR[8] = string.pack(">I1", 0) -- interlace method 0 (no interlace), may implement later if needed
  824.     IHDR[9] = string.pack(">I4", GetCRC32({string.byte(table.concat(IHDR), 1, 17)})) -- IHDR CRC
  825.  
  826.     BinaryInfo[10] = table.concat(IHDR)
  827.  
  828.     Pixels = FilterBytes(Pixels, ColorType == 2 and 3 or 4, FilterOn)
  829.  
  830.     local CompressedByteStream = Deflate(Pixels)
  831.  
  832.     local IDATChunks = math.ceil(#CompressedByteStream/65536)
  833.  
  834.     for i = 1, IDATChunks, 1 do
  835.         local ByteIdx = (i-1)*65536
  836.         local ChunkLen = math.min(65536, #CompressedByteStream - (i-1)*65536)
  837.         BinaryInfo[#BinaryInfo+1] = string.pack(">I4", ChunkLen)
  838.  
  839.         local IDATChunk = {}
  840.         IDATChunk[1] = string.pack(">I1", 0x49)
  841.         IDATChunk[2] = string.pack(">I1", 0x44)
  842.         IDATChunk[3] = string.pack(">I1", 0x41)
  843.         IDATChunk[4] = string.pack(">I1", 0x54)
  844.  
  845.         for j = 1, ChunkLen, 1 do
  846.             IDATChunk[j + 4] = string.pack(">I1", CompressedByteStream[ByteIdx + j])
  847.         end
  848.  
  849.         IDATChunk[#IDATChunk+1] = string.pack(">I4", GetCRC32({string.byte(table.concat(IDATChunk), 1, #IDATChunk + 3)}))
  850.         BinaryInfo[#BinaryInfo+1] = table.concat(IDATChunk)
  851.     end
  852.  
  853.     BinaryInfo[#BinaryInfo+1] = string.pack(">I4", 0)
  854.  
  855.     local IEND = {}
  856.     IEND[1] = string.pack(">I1", 73)
  857.     IEND[2] = string.pack(">I1", 69)
  858.     IEND[3] = string.pack(">I1", 78)
  859.     IEND[4] = string.pack(">I1", 68)
  860.     IEND[5] = string.pack(">I4", GetCRC32({string.byte(table.concat(IEND), 1, 4)}))
  861.  
  862.     BinaryInfo[#BinaryInfo+1] = table.concat(IEND)
  863.     Image:write(table.concat(BinaryInfo))
  864.     io.close(Image)
  865. end
  866.  
  867. return EncodePNG
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement