/// <summary> /// Based on the given input, finds the best compression to use on it. /// </summary> /// <param name="input">assumed to be point data (x,x,x,x,x,x,x)</param> /// <returns></returns> internal byte GetBestDefHuff(int[] input) { if (input.Length < 3) { return(NoCompression); } DeltaDelta xfDelDel = new DeltaDelta(); int xfData = 0; int exData = 0; // Perform delta delta 2 times to set up the internal state of // delta delta transform xfDelDel.Transform(input[0], ref xfData, ref exData); xfDelDel.Transform(input[1], ref xfData, ref exData); double sumSq = 0.0; // Compute the variance of the delta delta uint n = 2; for (; n < input.Length; n++) { xfDelDel.Transform(input[n], ref xfData, ref exData); if (0 == exData) { sumSq += ((double)xfData * (double)xfData); } } sumSq *= (0.205625 / (n - 1.0)); int i = DefaultFirstSquareRoot.Length - 2; for (; i > 1; i--) { if (sumSq > DefaultFirstSquareRoot[i]) { break; } } byte retVal = (byte)(IndexedHuffman | (byte)(i + 1)); return(retVal); }
/// <summary> /// Based on the given input, finds the best compression to use on it. /// </summary> /// <param name="input">assumed to be point data (x,x,x,x,x,x,x)</param> /// <returns></returns> internal byte GetBestDefHuff(int[] input) { if (input.Length < 3) { return NoCompression; } DeltaDelta xfDelDel = new DeltaDelta(); int xfData = 0; int exData = 0; // Perform delta delta 2 times to set up the internal state of // delta delta transform xfDelDel.Transform(input[0], ref xfData, ref exData); xfDelDel.Transform(input[1], ref xfData, ref exData); double sumSq = 0.0; // Compute the variance of the delta delta uint n = 2; for(; n < input.Length; n++) { xfDelDel.Transform(input[n], ref xfData, ref exData); if (0 == exData) { sumSq += ((double)xfData * (double)xfData); } } sumSq *= (0.205625 / (n - 1.0)); int i = DefaultFirstSquareRoot.Length - 2; for(; i > 1; i--) { if(sumSq > DefaultFirstSquareRoot[i]) { break; } } byte retVal = (byte)(IndexedHuffman | (byte)(i + 1)); return retVal; }
/// <summary> /// Compress - compress the input[] into compressedData /// </summary> /// <param name="bitCount">The count of bits needed for all elements</param> /// <param name="input">input buffer</param> /// <param name="startInputIndex">offset into the input buffer</param> /// <param name="dtxf">data transform. can be null</param> /// <param name="compressedData">The list of bytes to write the compressed input to</param> internal void Compress(int bitCount, int[] input, int startInputIndex, DeltaDelta dtxf, List <byte> compressedData) { if (null == input || null == compressedData) { throw new ArgumentNullException(StrokeCollectionSerializer.ISFDebugMessage("input or compressed data was null in Compress")); } if (bitCount < 0) { throw new ArgumentOutOfRangeException("bitCount"); } if (bitCount == 0) { //adjust if the bitcount is 0 //(this makes bitCount 32) bitCount = (int)(Native.SizeOfInt << 3); } //have the writer adapt to the List<byte> passed in and write to it BitStreamWriter writer = new BitStreamWriter(compressedData); if (null != dtxf) { int xfData = 0; int xfExtra = 0; for (int i = startInputIndex; i < input.Length; i++) { dtxf.Transform(input[i], ref xfData, ref xfExtra); if (xfExtra != 0) { throw new InvalidOperationException(StrokeCollectionSerializer.ISFDebugMessage("Transform returned unexpected results")); } writer.Write((uint)xfData, bitCount); } } else { for (int i = startInputIndex; i < input.Length; i++) { writer.Write((uint)input[i], bitCount); } } }
/// <summary> /// FindPacketAlgoByte /// </summary> /// <param name="input">input stream to find the best compression for</param> /// <param name="testDelDel"></param> internal byte FindPacketAlgoByte(int[] input, bool testDelDel) { if (input == null) { throw new ArgumentNullException("input"); } // Check for the input item count if (0 == input.Length) { return 0; } // If the input count is less than 3, we cannot do del del testDelDel = testDelDel && (input.Length < 3); int minVal, maxVal; int minDelDel, maxDelDel; uint startIndex = 1; int xfData = 0, xfExtra = 0; DeltaDelta delDel = new DeltaDelta(); // Initialize all the max-min's to initial value minVal = maxVal = minDelDel = maxDelDel = input[0]; // Skip first two elements for del-del if (testDelDel) { delDel.Transform(input[0], ref xfData, ref xfExtra); delDel.Transform(input[1], ref xfData, ref xfExtra); // if we need extra bits, we cannot do del-del if (0 != xfExtra) { testDelDel = false; } } // Initialize DelDelMax/Min if we can do del-del if (testDelDel) { delDel.Transform(input[2], ref xfData, ref xfExtra); // Again, if nExtra is non-zero, we cannot do del-del if (0 != xfExtra) { testDelDel = false; } else { minDelDel = maxDelDel = xfData; // Update raw max/min for two elements UpdateMinMax(input[1], ref maxVal, ref minVal); UpdateMinMax(input[2], ref maxVal, ref minVal); // Following loop starts from 3 startIndex = 3; } } for (uint dataIndex = startIndex; dataIndex < input.Length; dataIndex++) { // Update the raw min-max first UpdateMinMax(input[dataIndex], ref maxVal, ref minVal); if (testDelDel) { // If we can do del-del, first do the transformation delDel.Transform(input[dataIndex], ref xfData, ref xfExtra); // again, cannot do del-del if xfExtra is non-zero // otherwise, update the del-del min/max if (0 != xfExtra) { testDelDel = false; } else { UpdateMinMax(xfData, ref maxDelDel, ref minDelDel); } } } // Find the absolute max for del-del uint ulAbsMaxDelDel = (uint)Math.Max(MathHelper.AbsNoThrow(minDelDel), MathHelper.AbsNoThrow(maxDelDel)); // Find the Math.Abs max for raw uint ulAbsMax = (uint)Math.Max(MathHelper.AbsNoThrow(minVal), MathHelper.AbsNoThrow(maxVal)); // If we could do del-del and Math.Abs max of del-del is at least twice smaller than // original, we do del-del, otherwise, we bitpack raw data if (testDelDel && ((ulAbsMaxDelDel >> 1) < ulAbsMax)) { ulAbsMax = ulAbsMaxDelDel; } else { testDelDel = false; } // Absolute bits int bitCount = 0; while ((0 != (ulAbsMax >> bitCount)) && (31 > bitCount)) { bitCount++; } // Sign bit bitCount++; // Return the algo data return (byte)((byte)(bitCount & 0x1F) | (testDelDel ? (byte)0x20 : (byte)0)); }
/// <summary> /// Compress - compress the input[] into compressedData /// </summary> /// <param name="bitCount">The count of bits needed for all elements</param> /// <param name="input">input buffer</param> /// <param name="startInputIndex">offset into the input buffer</param> /// <param name="dtxf">data transform. can be null</param> /// <param name="compressedData">The list of bytes to write the compressed input to</param> internal void Compress(int bitCount, int[] input, int startInputIndex, DeltaDelta dtxf, List<byte> compressedData) { if (null == input || null == compressedData) { throw new ArgumentNullException(StrokeCollectionSerializer.ISFDebugMessage("input or compressed data was null in Compress")); } if (bitCount < 0) { throw new ArgumentOutOfRangeException("bitCount"); } if (bitCount == 0) { //adjust if the bitcount is 0 //(this makes bitCount 32) bitCount = (int)(Native.SizeOfInt << 3); } //have the writer adapt to the List<byte> passed in and write to it BitStreamWriter writer = new BitStreamWriter(compressedData); if (null != dtxf) { int xfData = 0; int xfExtra = 0; for (int i = startInputIndex; i < input.Length; i++) { dtxf.Transform(input[i], ref xfData, ref xfExtra); if (xfExtra != 0) { throw new InvalidOperationException(StrokeCollectionSerializer.ISFDebugMessage("Transform returned unexpected results")); } writer.Write((uint)xfData, bitCount); } } else { for (int i = startInputIndex; i < input.Length; i++) { writer.Write((uint)input[i], bitCount); } } }
/// <summary> /// Compresses int[] packet data, returns it as a byte[] /// </summary> /// <param name="input">assumed to be point data (x,x,x,x,x,x,x)</param> /// <param name="compression">magic byte specifying the compression to use</param> /// <returns></returns> internal byte[] CompressPacketData(int[] input, byte compression) { if (input == null) { throw new ArgumentNullException("input"); } List <byte> compressedData = new List <byte>(); //leave room at the beginning of //compressedData for the compression header byte //which we will add at the end compressedData.Add((byte)0); if (DefaultCompression == (DefaultCompression & compression)) { compression = GetBestDefHuff(input); } if (IndexedHuffman == (DefaultCompression & compression)) { DataXform dtxf = this.HuffModule.FindDtXf(compression); HuffCodec huffCodec = this.HuffModule.FindCodec(compression); huffCodec.Compress(dtxf, input, compressedData); if (((compressedData.Count - 1 /*for the algo byte we just made room for*/) >> 2) > input.Length) { //recompress with no compression (gorilla) compression = NoCompression; //reset compressedData.Clear(); compressedData.Add((byte)0); } } if (NoCompression == (DefaultCompression & compression)) { bool testDelDel = ((compression & 0x20) != 0); compression = this.GorillaCodec.FindPacketAlgoByte(input, testDelDel); DeltaDelta dtxf = null; if ((compression & 0x20) != 0) { dtxf = this.DeltaDelta; } int inputIndex = 0; if (null != dtxf) { //multibyteencode the first two values int xfData = 0; int xfExtra = 0; dtxf.ResetState(); dtxf.Transform(input[0], ref xfData, ref xfExtra); this.MultiByteCodec.SignEncode(xfData, compressedData); dtxf.Transform(input[1], ref xfData, ref xfExtra); this.MultiByteCodec.SignEncode(xfData, compressedData); //advance to the third member, we've already read the first two inputIndex = 2; } //Gorllia time int bitCount = (compression & 0x1F); this.GorillaCodec.Compress(bitCount, //the max count of bits required for each int input, //the input array to compress inputIndex, //the index to start compressing at dtxf, //data transform to use when compressing, can be null compressedData); //a ref to the compressed data that will be written to } // compression / algo data always goes in index 0 compressedData[0] = compression; return(compressedData.ToArray()); }
/// <summary> /// FindPacketAlgoByte /// </summary> /// <param name="input">input stream to find the best compression for</param> /// <param name="testDelDel"></param> internal byte FindPacketAlgoByte(int[] input, bool testDelDel) { if (input == null) { throw new ArgumentNullException("input"); } // Check for the input item count if (0 == input.Length) { return(0); } // If the input count is less than 3, we cannot do del del testDelDel = testDelDel && (input.Length < 3); int minVal, maxVal; int minDelDel, maxDelDel; uint startIndex = 1; int xfData = 0, xfExtra = 0; DeltaDelta delDel = new DeltaDelta(); // Initialize all the max-min's to initial value minVal = maxVal = minDelDel = maxDelDel = input[0]; // Skip first two elements for del-del if (testDelDel) { delDel.Transform(input[0], ref xfData, ref xfExtra); delDel.Transform(input[1], ref xfData, ref xfExtra); // if we need extra bits, we cannot do del-del if (0 != xfExtra) { testDelDel = false; } } // Initialize DelDelMax/Min if we can do del-del if (testDelDel) { delDel.Transform(input[2], ref xfData, ref xfExtra); // Again, if nExtra is non-zero, we cannot do del-del if (0 != xfExtra) { testDelDel = false; } else { minDelDel = maxDelDel = xfData; // Update raw max/min for two elements UpdateMinMax(input[1], ref maxVal, ref minVal); UpdateMinMax(input[2], ref maxVal, ref minVal); // Following loop starts from 3 startIndex = 3; } } for (uint dataIndex = startIndex; dataIndex < input.Length; dataIndex++) { // Update the raw min-max first UpdateMinMax(input[dataIndex], ref maxVal, ref minVal); if (testDelDel) { // If we can do del-del, first do the transformation delDel.Transform(input[dataIndex], ref xfData, ref xfExtra); // again, cannot do del-del if xfExtra is non-zero // otherwise, update the del-del min/max if (0 != xfExtra) { testDelDel = false; } else { UpdateMinMax(xfData, ref maxDelDel, ref minDelDel); } } } // Find the absolute max for del-del uint ulAbsMaxDelDel = (uint)Math.Max(MathHelper.AbsNoThrow(minDelDel), MathHelper.AbsNoThrow(maxDelDel)); // Find the Math.Abs max for raw uint ulAbsMax = (uint)Math.Max(MathHelper.AbsNoThrow(minVal), MathHelper.AbsNoThrow(maxVal)); // If we could do del-del and Math.Abs max of del-del is at least twice smaller than // original, we do del-del, otherwise, we bitpack raw data if (testDelDel && ((ulAbsMaxDelDel >> 1) < ulAbsMax)) { ulAbsMax = ulAbsMaxDelDel; } else { testDelDel = false; } // Absolute bits int bitCount = 0; while ((0 != (ulAbsMax >> bitCount)) && (31 > bitCount)) { bitCount++; } // Sign bit bitCount++; // Return the algo data return((byte)((byte)(bitCount & 0x1F) | (testDelDel ? (byte)0x20 : (byte)0))); }