public DataFile Compress(DataFile toCompress) { var ppmTables = new PPMTables(_maxOrder); var ac = new ArithmeticCoder(); for (int i = 0; i < toCompress.Length; i++) { if (i % _cleanUpLimit == 0) { ppmTables.CleanUp(); } var entry = new Entry(toCompress.GetByte(i), GetContextFromFile(toCompress, i)); ContextTable.ToEncode toEncode; EncodeInfo encodeInfo; while ((toEncode = ppmTables.LookUpAndUpdate(entry, out encodeInfo)) != ContextTable.ToEncode.EncodeSymbol) { if (toEncode == ContextTable.ToEncode.EncodeEscape) { ac.Encode(encodeInfo.Count, encodeInfo.CumulativeCount, encodeInfo.TotalCount); } entry.NextContext(); } ac.Encode(encodeInfo.Count, encodeInfo.CumulativeCount, encodeInfo.TotalCount); } ac.FinalizeInterval(); var output = ac.GetEncodedBitString().ToArray(); return(new DataFile(output)); }
/// <summary> /// Encodes <paramref name="symbol"/> using the <paramref name="coder"/> with /// the provided <paramref name="model"/>. /// </summary> public static void Encode <TSymbolType>(this ArithmeticCoder coder, TSymbolType symbol, IModel <TSymbolType> model, WriteBitDelegate bitWriter) where TSymbolType : struct { // cumulate frequencies Range count = model.GetRange(symbol); // encode symbol coder.Encode(count, model.TotalFrequencies, bitWriter); // update model model.Update(symbol); }
public void TestBasicArithmeticCodingRoundtrip2() { const string testString = "ユチエフ-8は素晴らしいです"; var data = Encoding.UTF8.GetBytes(testString); var frequencies = ArithmeticCoder.CalculateFrequencies(data); var encodedData = ArithmeticCoder.Encode(data, frequencies); var decodedData = ArithmeticCoder.Decode(encodedData, frequencies, data.Length); var resultString = Encoding.UTF8.GetString(decodedData); Console.WriteLine("{0} {1} {2}", data.Length, encodedData.Length, decodedData.Length); Console.WriteLine(encodedData.Aggregate("", (s, b) => s + ", " + b)); Console.WriteLine(testString); Console.WriteLine(resultString); Assert.LessOrEqual(encodedData.Length, data.Length); Assert.AreEqual(testString, resultString); }