public static List <LZNT1_Data> GenerateFromLZ77Match(byte[] arg, LZ77Match match, ref int processedBytes) { var result = new List <LZNT1_Data>(); int remainingLength = match.Length; while (remainingLength >= 3) { var compressedWord = new LZNT1_CompressedWord(); int displacementBits = GetDisplcaementBits(processedBytes); int maximumLength = GetMaximumLength(processedBytes); int length = Math.Min(remainingLength, maximumLength); compressedWord.Value = 0; compressedWord.Value |= (length - 3) & ((1 << (16 - displacementBits)) - 1); compressedWord.Value |= ((match.Distance - 1) & ((1 << displacementBits) - 1)) << (16 - displacementBits); result.Add(compressedWord); processedBytes += length; remainingLength -= length; } for (int i = 0; i < remainingLength; i++) { var literal = new LZNT1_Literal(); literal.Literal = arg[processedBytes - match.Distance]; result.Add(literal); processedBytes++; } return(result); }
/// <summary> /// Encode data into LZ77 symbols. /// </summary> /// <param name="data">Byte array containing data to be encoded.</param> /// <returns>Array containing LZ77 symbols.</returns> public List <LZ77Symbol> Encode(byte[] data) { var hash = new LZ77HashTable(); int i = 0; var result = new List <LZ77Symbol>(); while (i < data.Length) { LZ77Symbol symbol; int location = hash.Match(data, i); var distance = i - location; if (distance > 0 && distance <= MaximumMatchDistance) { int len = 0; int k = location; for (int j = i; j < data.Length; j++) { if (len > MaximumMatchLength) { break; } if (data[k] == data[j]) { hash.Match(data, j); k++; len++; } else { break; } } symbol = new LZ77Match() { Length = len, Distance = distance }; i += len; } else { symbol = new LZ77Literal() { Literal = data[i] }; i++; } result.Add(symbol); } var eof = new LZ77EOF(); result.Add(eof); return(result); }
private byte[] EncodeSymbols(List <LZ77Symbol> input) { var header = getHeader(); /* * Write the 256-byte table of symbol bit lengths * While there are more literals or matches to encode * If the next thing is a literal * WriteBits(SymbolLength[LiteralValue], SymbolCode[LiteralValue]) * Else // the next thing is a match * Extract the length and distance of the match * MatchSymbolValue = 256 + min(Length - 3, 15) + (16 * GetHighBit(Distance)) * WriteBits(SymbolLength[MatchSymbolValue], SymbolCode[MatchSymbolValue]) * If (Length – 3) >= 15 * WriteByte(min(Length – 3 – 15, 255)) * If (Length – 3 – 15) >= 255 * WriteTwoBytes(Length – 3) * WriteBits(GetHighBit(Distance), Distance – (1 << GetHighBit(Distance))) * WriteBits(SymbolLength[256], SymbolCode[256]) * FlushBits() */ var stream = new HuffmanBitStreamWriter(header); foreach (var symbol in input) { if (symbol is LZ77Literal) { stream.WriteBits(code[symbol.Encode()].Length, code[symbol.Encode()].Code); } else if (symbol is LZ77Match) { stream.WriteBits(code[symbol.Encode()].Length, code[symbol.Encode()].Code); var match = symbol as LZ77Match; int matchLength = match.Length; if (matchLength - 3 >= 15) { stream.WriteByte((byte)Math.Min(matchLength - 3 - 15, 255)); if (matchLength - 3 - 15 >= 255) { stream.WriteTwoBytes((ushort)(matchLength - 3)); } } int distance = match.Distance; stream.WriteBits(LZ77Match.GetHighBit(distance), distance - (1 << LZ77Match.GetHighBit(distance))); } else if (symbol is LZ77EOF) { stream.WriteBits(code[symbol.Encode()].Length, code[symbol.Encode()].Code); } } stream.FlushBits(); return(stream.GetBytes()); }
public override LZ77Symbol ParseToLZ77Symbol(ref int processedBytes) { var displacementBits = GetDisplcaementBits(processedBytes); int diplacement = (Value >> (16 - displacementBits)) + 1; int length = (Value & ((1 << (16 - displacementBits)) - 1)) + 3; var result = new LZ77Match() { Distance = diplacement, Length = length }; processedBytes += length; return(result); }