/// <summary> /// DecompressPacketData - given a compressed byte[], uncompress it to the outputBuffer /// </summary> /// <param name="input">compressed byte from the ISF stream</param> /// <param name="outputBuffer">prealloc'd buffer to write to</param> /// <returns></returns> internal uint DecompressPacketData(byte[] input, int[] outputBuffer) { if (input == null) { throw new ArgumentNullException("input"); } if (input.Length < 2) { throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Input buffer passed was shorter than expected")); } if (outputBuffer == null) { throw new ArgumentNullException("outputBuffer"); } if (outputBuffer.Length == 0) { throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("output buffer length was zero")); } byte compression = input[0]; uint totalBytesRead = 1; //we just read one int inputIndex = 1; switch (compression & 0xC0) { case 0x80: //IndexedHuffman { DataXform dtxf = this.HuffModule.FindDtXf(compression); HuffCodec huffCodec = this.HuffModule.FindCodec(compression); totalBytesRead += huffCodec.Uncompress(dtxf, input, inputIndex, outputBuffer); return(totalBytesRead); } case 0x00: //NoCompression { int outputBufferIndex = 0; DeltaDelta dtxf = null; if ((compression & 0x20) != 0) { dtxf = this.DeltaDelta; } int bitCount = 0; if ((compression & 0x1F) == 0) { bitCount = Native.BitsPerInt; //32 } else { bitCount = (compression & 0x1F); } if (null != dtxf) { //must have at least two more bytes besides the //initial algo byte if (input.Length < 3) { throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Input buffer was too short (must be at least 3 bytes)")); } //multibyteencode the first two values int xfData = 0; int xfExtra = 0; dtxf.ResetState(); uint bytesRead = this.MultiByteCodec.SignDecode(input, inputIndex, ref xfData); //advance our index inputIndex += (int)bytesRead; totalBytesRead += bytesRead; int result = dtxf.InverseTransform(xfData, xfExtra); Debug.Assert(outputBufferIndex < outputBuffer.Length); outputBuffer[outputBufferIndex++] = result; bytesRead = this.MultiByteCodec.SignDecode(input, inputIndex, ref xfData); //advance our index inputIndex += (int)bytesRead; totalBytesRead += bytesRead; result = dtxf.InverseTransform(xfData, xfExtra); Debug.Assert(outputBufferIndex < outputBuffer.Length); outputBuffer[outputBufferIndex++] = result; } totalBytesRead += this.GorillaCodec.Uncompress(bitCount, //the max count of bits required for each int input, //the input array to uncompress inputIndex, //the index to start uncompressing at dtxf, //data transform to use when compressing, can be null outputBuffer, //a ref to the output buffer to write to outputBufferIndex); //the index of the output buffer to write to return(totalBytesRead); } default: { throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Invalid decompression algo byte")); } } }
/// <summary> /// Uncompress - uncompress a byte[] into an int[] of point data (x,x,x,x,x) /// </summary> /// <param name="bitCount">The number of bits each element uses in input</param> /// <param name="input">compressed data</param> /// <param name="inputIndex">index to begin decoding at</param> /// <param name="dtxf">data xf, can be null</param> /// <param name="outputBuffer">output buffer that is prealloc'd to write to</param> /// <param name="outputBufferIndex">the index of the output buffer to write to</param> internal uint Uncompress(int bitCount, byte[] input, int inputIndex, DeltaDelta dtxf, int[] outputBuffer, int outputBufferIndex) { if (null == input) { throw new ArgumentNullException("input"); } if (inputIndex >= input.Length) { throw new ArgumentOutOfRangeException("inputIndex"); } if (null == outputBuffer) { throw new ArgumentNullException("outputBuffer"); } if (outputBufferIndex >= outputBuffer.Length) { throw new ArgumentOutOfRangeException("outputBufferIndex"); } if (bitCount < 0) { throw new ArgumentOutOfRangeException("bitCount"); } // Adjust bit count if 0 passed in if (bitCount == 0) { //adjust if the bitcount is 0 //(this makes bitCount 32) bitCount = (int)(Native.SizeOfInt << 3); } // Test whether the items are signed. For unsigned number, we don't need mask // If we are trying to compress signed long values with bit count = 5 // The mask will be 1111 1111 1111 0000. The way it is done is, if the 5th // bit is 1, the number is negative numbe, othrwise it's positive. Testing // will be non-zero, ONLY if the 5th bit is 1, in which case we OR with the mask // otherwise we leave the number as it is. uint bitMask = (unchecked((uint)~0) << (bitCount - 1)); uint bitData = 0; BitStreamReader reader = new BitStreamReader(input, inputIndex); if(dtxf != null) { while (!reader.EndOfStream) { bitData = reader.ReadUInt32(bitCount); // Construct the item bitData = ((bitData & bitMask) != 0) ? bitMask | bitData : bitData; int result = dtxf.InverseTransform((int)bitData, 0); Debug.Assert(outputBufferIndex < outputBuffer.Length); outputBuffer[outputBufferIndex++] = result; if (outputBufferIndex == outputBuffer.Length) { //only write as much as the outputbuffer can hold //this is assumed by calling code break; } } } else { while (!reader.EndOfStream) { bitData = reader.ReadUInt32(bitCount); // Construct the item bitData = ((bitData & bitMask) != 0) ? bitMask | bitData : bitData; Debug.Assert(outputBufferIndex < outputBuffer.Length); outputBuffer[outputBufferIndex++] = (int)bitData; if (outputBufferIndex == outputBuffer.Length) { //only write as much as the outputbuffer can hold //this is assumed by calling code break; } } } // Calculate how many bytes were read from input buffer return (uint)((outputBuffer.Length * bitCount + 7) >> 3); }
/// <summary> /// Uncompress - uncompress a byte[] into an int[] of point data (x,x,x,x,x) /// </summary> /// <param name="bitCount">The number of bits each element uses in input</param> /// <param name="input">compressed data</param> /// <param name="inputIndex">index to begin decoding at</param> /// <param name="dtxf">data xf, can be null</param> /// <param name="outputBuffer">output buffer that is prealloc'd to write to</param> /// <param name="outputBufferIndex">the index of the output buffer to write to</param> internal uint Uncompress(int bitCount, byte[] input, int inputIndex, DeltaDelta dtxf, int[] outputBuffer, int outputBufferIndex) { if (null == input) { throw new ArgumentNullException("input"); } if (inputIndex >= input.Length) { throw new ArgumentOutOfRangeException("inputIndex"); } if (null == outputBuffer) { throw new ArgumentNullException("outputBuffer"); } if (outputBufferIndex >= outputBuffer.Length) { throw new ArgumentOutOfRangeException("outputBufferIndex"); } if (bitCount < 0) { throw new ArgumentOutOfRangeException("bitCount"); } // Adjust bit count if 0 passed in if (bitCount == 0) { //adjust if the bitcount is 0 //(this makes bitCount 32) bitCount = (int)(Native.SizeOfInt << 3); } // Test whether the items are signed. For unsigned number, we don't need mask // If we are trying to compress signed long values with bit count = 5 // The mask will be 1111 1111 1111 0000. The way it is done is, if the 5th // bit is 1, the number is negative numbe, othrwise it's positive. Testing // will be non-zero, ONLY if the 5th bit is 1, in which case we OR with the mask // otherwise we leave the number as it is. uint bitMask = (unchecked ((uint)~0) << (bitCount - 1)); uint bitData = 0; BitStreamReader reader = new BitStreamReader(input, inputIndex); if (dtxf != null) { while (!reader.EndOfStream) { bitData = reader.ReadUInt32(bitCount); // Construct the item bitData = ((bitData & bitMask) != 0) ? bitMask | bitData : bitData; int result = dtxf.InverseTransform((int)bitData, 0); Debug.Assert(outputBufferIndex < outputBuffer.Length); outputBuffer[outputBufferIndex++] = result; if (outputBufferIndex == outputBuffer.Length) { //only write as much as the outputbuffer can hold //this is assumed by calling code break; } } } else { while (!reader.EndOfStream) { bitData = reader.ReadUInt32(bitCount); // Construct the item bitData = ((bitData & bitMask) != 0) ? bitMask | bitData : bitData; Debug.Assert(outputBufferIndex < outputBuffer.Length); outputBuffer[outputBufferIndex++] = (int)bitData; if (outputBufferIndex == outputBuffer.Length) { //only write as much as the outputbuffer can hold //this is assumed by calling code break; } } } // Calculate how many bytes were read from input buffer return((uint)((outputBuffer.Length * bitCount + 7) >> 3)); }