public override int Read(IOfcNumberWriter writer, Block block, StreamBitReader reader) { // ReSharper disable once AssignmentInConditionalExpression if (block.OverrideGlobalNb = reader.ReadByte(1) > 0) { block.NeededBits = reader.ReadByte(Metadata.MaxNeededBitsNeededBitsNumber); } // ReSharper disable once AssignmentInConditionalExpression if (!Metadata.IsAbsolute) { if (block.AbsoluteSign = reader.ReadByte(1) > 0) { block.IsSignNegative = reader.ReadByte(1) > 0; } } var hasAbsoluteSign = block.AbsoluteSign || Metadata.IsAbsolute; var isNegative = block.AbsoluteSign && block.IsSignNegative || Metadata.IsAbsolute && Metadata.IsNegative; for (var i = 0; i < block.Length; i++) { var num = new OfcNumber(); if (!hasAbsoluteSign) { isNegative = reader.ReadByte(1) > 0; } num.Number = ((long)reader.Read(Metadata.MaxNeededBitsNumber)) * (isNegative ? -1 : 1); writer.Write(num); } return(block.Length); }
/// <summary> /// Reads the metadata in its binary form /// </summary> /// <param name="reader"></param> /// <returns></returns> public static BlockyMetadata FromBitStream(StreamBitReader reader) { var metadata = new BlockyMetadata { ValueCount = (int)reader.Read(31) }; // ReSharper disable once AssignmentInConditionalExpression if (metadata.IsAbsolute = reader.ReadByte(1) > 0) { metadata.IsNegative = reader.ReadByte(1) > 0; } metadata.MaxNeededBitsExponent = reader.ReadByte(4); metadata.MaxNeededBitsNumber = reader.ReadByte(6); metadata.MaxNeededBitsNeededBitsNumber = Utility.GetNeededBits(metadata.MaxNeededBitsNumber); metadata.LargestPossibleValue = Utility.GetMaxValue(metadata.MaxNeededBitsNumber); return(metadata); }
/// <summary> /// Reads a Single Value from its binary representation without the control bit (isBlock) /// </summary> /// <param name="reader"></param> /// <param name="metadata"></param> /// <returns></returns> public static OfcNumber ReadSingleValueWithoutControlBit(StreamBitReader reader, BlockyMetadata metadata) { var value = new OfcNumber(); if (!metadata.IsAbsolute) { value.IsNegative = reader.ReadByte(1) > 0; } else { value.IsNegative = metadata.IsNegative; } value.Number = (long)reader.Read(metadata.MaxNeededBitsNumber); var isExpNegative = reader.ReadByte(1) > 0; value.Exponent = (short)reader.Read(metadata.MaxNeededBitsExponent); // Bug: Potentually reading exp even though NoExp is set. Same in writing method! (Ineffizient) if (isExpNegative) { value.Exponent *= -1; } return(value); }
public override int Read(IOfcNumberWriter writer, Block block, StreamBitReader reader) { var val1 = ReadSingleValueWithoutControlBit(reader, Metadata); var val2 = ReadSingleValueWithoutControlBit(reader, Metadata); var ppLength = reader.ReadByte(8); var total = ppLength * block.Length; for (var i = 0; i < total; i++) { writer.Write(i % (ppLength * 2) >= ppLength ? val2 : val1); } return(total); }
/// <summary> /// Exclusive IsBlock /// </summary> /// <param name="reader"></param> /// <param name="metadata"></param> /// <returns></returns> public static Block ReadDefaultBlockHeader(StreamBitReader reader, BlockyMetadata metadata) { var block = new Block(); // ReSharper disable once AssignmentInConditionalExpression if (block.HasExponent = reader.ReadByte(1) > 0) { var negative = reader.ReadByte(1) > 0; block.Exponent = (short)reader.Read(metadata.MaxNeededBitsExponent); if (negative) { block.Exponent *= -1; } } // ReSharper disable once AssignmentInConditionalExpression if (block.HasPattern = reader.ReadByte(1) > 0) { block.Pattern = (Block.PatternType)reader.ReadByte(2); } block.Length = reader.ReadByte(8); return(block); }
protected BlockyDecompression([NotNull] Stream reader) { _bitReader = new StreamBitReader(reader); Metadata = BlockyMetadata.FromBitStream(_bitReader); _decompressionMethods[(int)Blockfinding.Blockfinding.Methods.PatternSame] = new PatternSameDecompression(Metadata); _decompressionMethods[(int)Blockfinding.Blockfinding.Methods.PatternPingPong] = new PatternPingPongDecompression(Metadata); _decompressionMethods[(int)Blockfinding.Blockfinding.Methods.FloatSimmilar] = new FloatSimmilarDecompression(Metadata); _decompressionMethods[(int)Blockfinding.Blockfinding.Methods.NumbersNoExp] = new NumbersNoExpDecompression(Metadata); _decompressionMethods[(int)Blockfinding.Blockfinding.Methods.PatternOffset] = new PatternOffsetDecompression(Metadata); if (_bitReader.ReadByte(1) > 0) // use huffman { throw new NotImplementedException(); } }
public void Decompress() { var valueCount = 0; while (valueCount < Metadata.ValueCount) { if (_bitReader.ReadByte(1) > 0) // isBlock { var block = DecompressionMethod.ReadDefaultBlockHeader(_bitReader, Metadata); var method = GetMethodForBlock(block); // Get decompressor class for block type valueCount += method.Read(_numberWriter, block, _bitReader); } else { _numberWriter.Write(DecompressionMethod.ReadSingleValueWithoutControlBit(_bitReader, Metadata)); valueCount++; } } _writer?.Flush(); }
public bool DecompressNext() { var blockLength = (int)_streamBitReader.Read(32); if (blockLength == 0) { return(false); // The compression will write 0 as int32 at the end - a block with 0 length = the end } var numbers = new char[blockLength][]; var numberLengths = new int[blockLength]; var expLengths = new int[blockLength]; var averageNumberLength = _streamBitReader.ReadByte(8); var averageExpLength = _streamBitReader.ReadByte(8); #region Reconstructing value lengths from bit mask and initializing numbers array for (var i = 0; i < blockLength; i++) { var isSmallerThanAvg = _streamBitReader.ReadByte(1) * -2 + 1; // * -2 + 1 transforms a 0 - 1 isNegative bool into a -1 or 1 multiplier ;) var diff = 0; while (_streamBitReader.ReadByte(1) == 0) { diff++; } numberLengths[i] = averageNumberLength + diff * isSmallerThanAvg; } for (var i = 0; i < blockLength; i++) { var isSmallerThanAvg = _streamBitReader.ReadByte(1) * -2 + 1; // * -2 + 1 transforms a 0 - 1 isNegative bool into a -1 or 1 multiplier ;) var diff = 0; while (_streamBitReader.ReadByte(1) == 0) { diff++; } expLengths[i] = averageExpLength + diff * isSmallerThanAvg; var thisNumLength = numberLengths[i]; if (expLengths[i] > 0) { thisNumLength += expLengths[i] + 1; } numbers[i] = new char[thisNumLength]; } #endregion var changed = true; for (var digitIndex = 0; changed; digitIndex++) { changed = false; for (var i = 0; i < blockLength; i++) { if (numberLengths[i] > digitIndex) { changed = true; numbers[i][digitIndex] = (char)_stream.ReadByte(); } } } for (var i = 0; i < blockLength; i++) { if (expLengths[i] > 0) { numbers[i][numberLengths[i]] = 'e'; } } changed = true; for (var digitIndex = 0; changed; digitIndex++) { changed = false; for (var i = 0; i < blockLength; i++) { if (expLengths[i] > digitIndex) { changed = true; numbers[i][numberLengths[i] + 1 + digitIndex] = (char)_stream.ReadByte(); } } } for (var i = 0; i < numbers.Length; i++) { _output.Report(new string(numbers[i])); } return(true); }