/// <summary> /// Decodes truncated code item /// </summary> /// <param name="bitstream"></param> /// <param name="n"></param> /// <returns></returns> public static uint Decode(Bitstream bitstream, uint n) { uint k = CodecBase.BitsRequired(n); uint u = (1U << (int)k) - n; // u = number of unused codewords uint x = bitstream.Read(k - 1); if (x >= u) { // need another bit x = 2 * x + bitstream.Read(1); x -= u; } return(x); }
public static uint DecodeGamma(Bitstream bitstream) { uint n = 0, b; do { b = bitstream.Read(1); n++; } while (b != 1); n--; var t = bitstream.Read(n); return((1U << (int)n) + t); }
public static uint DecodeOmega(Bitstream bitstream) { uint n = 1, b; do { b = bitstream.Read(1); if (b != 0) { uint t = bitstream.Read(n); n = (1U << (int)n) + t; } } while (b != 0); return(n); }
public static uint DecodeDelta(Bitstream bitstream) { uint l = 0, b; do { b = bitstream.Read(1); l++; } while (b == 0); // get remaining l-1 digits of n, add back initial bit read in loop while determining L uint n = bitstream.Read(l - 1) + (1U << (int)(l - 1)); // read last n-1 bits of x, add back leading bit uint x = bitstream.Read(n - 1) + (1U << (int)(n - 1)); return(x); }
/// <summary> /// </summary> /// <returns></returns> public static uint Decode(Bitstream bitstream, uint k) { Trace.Assert(k > 1); uint v = bitstream.Read(k); while (true) { uint b = bitstream.Read(1); if (b == 0) // end of chain { return(bitstream.Read(v)); } v += k; v = (1U << (int)v) + bitstream.Read(v); } }
// read one bit, return 0 when out of bits uint ReadBit(Bitstream bitstream) { ++bitsRead; if (bitsRead < bitLength) { return(bitstream.Read(1)); } return(0); }
/// <summary> /// To decode an Even-Rodeh-coded integer: /// 1.Read 3 bits and store the value into N.If the first bit read was 0 then stop.The decoded number is N. /// If the first bit read was 1 then continue to step 2. /// 2.Examine the next bit. If the bit is 0 then read 1 bit and stop.The decoded number is N. /// If the bit is 1 then read N bits, store the value as the new value of N, and go back to step 2. /// </summary> /// <param name="bitstream"></param> /// <returns></returns> public static uint Decode(Bitstream bitstream) { uint n = bitstream.Read(3); if (n < 4) { return(n); } while (true) { uint nextBit = bitstream.Read(1); if (nextBit == 0) { return(n); } uint m = bitstream.Read(n - 1); n = m | (1U << (int)(n - 1)); } }
/// <summary> /// Copy in the given BitStream /// </summary> /// <param name="bitstream"></param> public void WriteStream(Bitstream bitstream) { var temp = bitstream.Position; bitstream.Position = 0; while (bitstream.Position < bitstream.Length) { Write(bitstream.Read(1), 1); } bitstream.Position = temp; }
/// <summary> /// Read the header for the compression algorithm /// Return number of symbols in stream if known, else 0 if not present /// </summary> /// <param name="bitstream"></param> /// <param name="headerFlags">Flags telling what to put in the header. Useful when embedding in other streams.</param> /// <returns></returns> public override uint ReadHeader(Bitstream bitstream, Header.HeaderFlags headerFlags) { decoderState = new DecoderState(); // read header values var header = Header.ReadUniversalHeader(bitstream, headerFlags); decoderState.SymbolCount = header.Item1; // get max distance occurring, used to encode tokens, very useful to users to know window needed size decoderState.ActualMaxDistance = UniversalCodec.Lomont.DecodeLomont1(bitstream, 10, 0); decoderState.ActualMinLength = UniversalCodec.Lomont.DecodeLomont1(bitstream, 2, 0); // see if decisions or decision runs if (bitstream.Read(1) == 0) { decoderState.DecisionDecoder = ReadItem(bitstream); } else { // read initial value decoderState.InitialValue = bitstream.Read(1); // read item decoderState.DecisionRunDecoder = ReadItem(bitstream); } // literals decoderState.LiteralDecoder = ReadItem(bitstream); // tokens or separate distance, length pairs if (bitstream.Read(1) == 0) { decoderState.TokenDecoder = ReadItem(bitstream); } else { decoderState.DistanceDecoder = ReadItem(bitstream); decoderState.LengthDecoder = ReadItem(bitstream); } return(decoderState.SymbolCount); }
public static uint Decode(Bitstream bitstream, uint m) { Trace.Assert(m > 0); var q = 0U; while (bitstream.Read(1) == 1) { ++q; } uint r = Truncated.Decode(bitstream, m); return(q * m + r); }
/// <summary> /// Decompress a symbol in the compression algorithm /// </summary> /// <param name="bitstream"></param> public override uint DecompressSymbol(Bitstream bitstream) { var output = decoderState.DecoderStream; // decode some if needed while (output.Count <= decoderState.DatumIndex) { if (bitstream.Read(1) == 0) { // literal uint symbol = bitstream.Read(decoderState.ActualBitsPerSymbol); if (Options.HasFlag(OptionFlags.DumpDebug)) { Write($"{output.Count}:[{symbol}] "); } output.Add(symbol); ++decoderState.DatumIndex; return(symbol); } // run uint token = bitstream.Read(decoderState.ActualBitsPerToken); // decode token uint length = token / (decoderState.ActualMaxDistance + 1) + decoderState.ActualMinLength; uint distance = token % (decoderState.ActualMaxDistance + 1); if (Options.HasFlag(OptionFlags.DumpDebug)) { Write($"[{distance},{length}] "); } // copy run for (uint i = 0; i < length; ++i) { output.Add(output[(int)(output.Count - distance - 1)]); } } return(output[decoderState.DatumIndex++]); }
public static uint DecodeExp(Bitstream bitstream, uint k) { if (k > 0) { // read value shifted by k uint high = DecodeExp(bitstream, 0); //read last k bits uint low = bitstream.Read(k); return((high << (int)k) | low); } uint n = 0, b; do { b = bitstream.Read(1); ++n; } while (b == 0); // b is high bit of value + 1 uint value = bitstream.Read(n - 1); value |= b << (int)(n - 1); return(value - 1); }
/// <summary> /// Decode lomont method 1 with the given chunksize /// </summary> /// <param name="bitstream"></param> /// <param name="chunkSize"></param> /// <param name="deltaChunk"></param> public static uint DecodeLomont1(Bitstream bitstream, int chunkSize, int deltaChunk) { uint value = 0, b; int shift = 0; do { b = bitstream.Read(1); // decision uint chunk = bitstream.Read((uint)chunkSize); value += chunk << shift; shift += chunkSize; if (deltaChunk != 0) { chunkSize += deltaChunk; if (chunkSize <= 0) { chunkSize = 1; } } } while (b != 0); return(value); }
/// <summary> /// /// </summary> /// <param name="bitstream"></param> /// <param name="universalDecoder">The same encoder/decoder pair used to encode this</param> /// <returns></returns> public static List <uint> BinaryAdaptiveSequentialDecode(Bitstream bitstream, Func <Bitstream, uint> universalDecoder) { var list = new List <uint>(); uint length = universalDecoder(bitstream) - 1; if (length == 0) { return(list); } uint b1 = universalDecoder(bitstream); uint xi = bitstream.Read(b1); list.Add(xi); while (list.Count < length) { var decision = bitstream.Read(1); if (decision == 0) { // bi is <= b(i-1), so enough bits xi = bitstream.Read(b1); } else { // bi is bigger than b(i-1), must increase it uint delta = 0; do { decision = bitstream.Read(1); delta++; } while (decision != 0); b1 += delta; xi = bitstream.Read(b1 - 1); // xi has implied leading 1 xi |= 1U << (int)(b1 - 1); } list.Add(xi); b1 = CodecBase.BitsRequired(xi); } return(list); }
// Get codec type, a bitstream for it, read the header, advance the bitstream // the codec, the bit length, and the bitstream Decoder ReadItem(Bitstream bitstream) { var decoder = new Decoder(); // save type uint type = bitstream.Read(2); if (type == 0) { decoder.Codec = new FixedSizeCodec(); } else if (type == 1) { decoder.Codec = new ArithmeticCodec(); } else if (type == 2) { decoder.Codec = new HuffmanCodec(); } else if (type == 3) { decoder.Codec = new GolombCodec(); } else { throw new NotImplementedException("Unknown compressor type"); } decoder.BitLength = UniversalCodec.Lomont.DecodeLomont1(bitstream, 6, 0); if (Options.HasFlag(OptionFlags.DumpDebug)) { WriteLine($"Compressor index {type}, length {decoder.BitLength}"); } // prepare a bitstream for the codec decoder.Bitstream = new Bitstream(); decoder.Bitstream.WriteStream(bitstream); decoder.Bitstream.Position = bitstream.Position; decoder.Codec.ReadHeader(decoder.Bitstream, internalFlags); bitstream.Position += decoder.BitLength; if (Options.HasFlag(OptionFlags.DumpDebug)) { WriteLine($"Post read item position {bitstream.Position}"); } return(decoder); }
/// <summary> /// Decompress a symbol in the compression algorithm /// </summary> /// <param name="bitstream"></param> public override uint DecompressSymbol(Bitstream bitstream) { return(bitstream.Read(BitsPerSymbol)); }
// lookup symbol and probability range using table decoding uint LookupLowMemoryCount(Bitstream bitstream, uint cumCount, out uint lowCount, out uint highCount) { // BASC encoded, decode with same process // todo - merge with BASC Codec version, make cleaner // swap bit positions to access table uint tempPosition = bitstream.Position; // save this bitstream.Position = tableStartBitPosition; lowCount = highCount = 0; uint symbol = 0; uint length = UniversalCodec.Lomont.DecodeLomont1(bitstream, 6, 0); if (length != 0) { uint b1 = UniversalCodec.Lomont.DecodeLomont1(bitstream, 6, 0); uint xi = bitstream.Read(b1); lowCount = 0; highCount = xi; symbol = symbolMin; uint i = symbolMin; while (highCount <= cumCount) { var decision = bitstream.Read(1); if (decision == 0) { // bi is <= b(i-1), so enough bits xi = bitstream.Read(b1); } else { // bi is bigger than b(i-1), must increase it uint delta = 0; do { decision = bitstream.Read(1); delta++; } while (decision != 0); b1 += delta; xi = bitstream.Read(b1 - 1); // xi has implied leading 1 xi |= 1U << (int)(b1 - 1); } b1 = BitsRequired(xi); lowCount = highCount; highCount += xi; ++i; if (xi != 0) { symbol = i; } } } // restore bit position bitstream.Position = tempPosition; return(symbol); }