/// <summary> /// Calculates the metadata from the given values /// </summary> /// <param name="values"></param> /// <returns></returns> public static BlockyMetadata FromData(List <OfcNumber> values) { if (values.Count == 0) { throw new InvalidOperationException("Cannot gather compression metadata with 0 values!"); } var metadata = new BlockyMetadata() { IsNegative = values.First().IsNegative, IsAbsolute = true, ValueCount = values.Count }; foreach (var ofcNumber in values) { if (ofcNumber.NeededBitsNumber > metadata.MaxNeededBitsNumber) { metadata.MaxNeededBitsNumber = ofcNumber.NeededBitsNumber; metadata.LargestPossibleValue = Utility.GetMaxValue(ofcNumber.NeededBitsNumber); } if (ofcNumber.NeededBitsExponent > metadata.MaxNeededBitsExponent) { metadata.MaxNeededBitsExponent = ofcNumber.NeededBitsExponent; //Todo: this is redundant af, we should be able to calculate it from the huffman creator } if (metadata.IsAbsolute && ofcNumber.IsNegative != metadata.IsNegative) { metadata.IsAbsolute = false; } if (metadata.NoExponent && ofcNumber.Exponent != 0) { metadata.NoExponent = false; } } return(metadata); }
protected BlockyDecompression([NotNull] Stream reader) { _bitReader = new StreamBitReader(reader); Metadata = BlockyMetadata.FromBitStream(_bitReader); _decompressionMethods[(int)Methods.PatternSame] = new PatternSameDecompression(Metadata); _decompressionMethods[(int)Methods.PatternPingPong] = new PatternPingPongDecompression(Metadata); _decompressionMethods[(int)Methods.FloatSimmilar] = new FloatSimmilarDecompression(Metadata); _decompressionMethods[(int)Methods.NumbersNoExp] = new NumbersNoExpDecompression(Metadata); _decompressionMethods[(int)Methods.PatternOffset] = new PatternOffsetDecompression(Metadata); if (_bitReader.ReadByte(1) > 0) // use huffman { throw new NotImplementedException(); } }
/// <summary> /// Will calculate everything and make it ready for writing /// </summary> public void Finish() { if (Values.Count == 0) { return; } Metadata = BlockyMetadata.FromData(Values); Metadata.MaxNeededBitsNeededBitsNumber = Utility.GetNeededBits(Metadata.MaxNeededBitsNumber); _blockfinding = new Blockfinding.Blockfinding(Values, Metadata); Blocks = _blockfinding.FindAllBlocks(); PostCompressionOptimisation(); //Todo: make optional Write(); }
/// <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); }
/// <remarks>This will set OverrideGlobalNb but not the NeededBits</remarks> /// <param name="metadata"></param> /// <param name="newNb"></param> /// <returns>The bit difference that would occur when changing the NeededBits in the header to newNb</returns> public int DifferenceWithNb(BlockyMetadata metadata, ref byte newNb) //Bug: wrong calculatons if nb > maxNb ? { if (metadata.MaxNeededBitsNeededBitsNumber < (metadata.MaxNeededBitsNumber - newNb) * Length) // If the space we'd save in the header by not overriding the nb is smaller than the space we'd save at the values because of the overriden nb # TL;DR: If it's worth to override the nb in the header { if (!OverrideGlobalNb) { OverrideGlobalNb = true; return((NeededBits - newNb) * Length - metadata.MaxNeededBitsNeededBitsNumber); // The bits we'll save with the header change - the bits we'll waste by overriding the nb in the header (adds some overhead ...) } } else if (OverrideGlobalNb) // If the nb are overriden but it's not worth to override them (which is why we got to 'else' ...) { OverrideGlobalNb = false; newNb = metadata.MaxNeededBitsNumber; // Bug: moved this from the if above. Not sure if i have missed something or fixed a bug :S return((NeededBits - newNb) * Length + metadata.MaxNeededBitsNeededBitsNumber); // The bits we'll save with the header change + the bits we'll save by not overriding the nb in the header (removes some overhead ...) } return((NeededBits - newNb) * Length); // the bits we'll save if the nb were already overriden and have changed value }
public bool ShouldOverrideNb(BlockyMetadata metadata) { return(metadata.MaxNeededBitsNeededBitsNumber < (metadata.MaxNeededBitsNumber - NeededBits) * Length && !HasPattern); }