public void DecompressVoxelData( byte[] data, ushort[] result ) { BitStream stream; ushort DataBytes; DataBytes = BitConverter.ToUInt16( data, 0 ); if( DataBytes > 20 ) { MemoryStream initial_stream = new MemoryStream( data ); initial_stream.Seek( 2, SeekOrigin.Begin ); byte[] uncompressed_data = new byte[DataBytes]; GZipStream gz_stream = new GZipStream( initial_stream, CompressionMode.Decompress ); gz_stream.Read( uncompressed_data, 0, DataBytes ); stream = new BitStream( uncompressed_data ); } else { stream = new BitStream( data ); stream.Seek( 16 ); // seek by bit position } List<ushort> types = new List<ushort>(); byte bits; uint TypeCount; stream.Read( 8, out bits ); stream.Read( bits, out TypeCount ); TypeCount++; // always at least one. int n; for( n = 0; n < TypeCount; n++ ) { ushort val; stream.Read( 16, out val ); types.Add( val ); } int outpos = 0; do { ushort vox; uint val; uint count; stream.Read( 1, out val ); if( val == 0 ) { stream.Read( bits, out val ); vox = types[(int)val]; result[outpos++] = vox; } else { uint count_tmp; stream.Read( 6, out count_tmp ); count = count_tmp & 0x1F; if( ( count_tmp & 0x20 ) != 0 ) { count <<= 5; stream.Read( 6, out count_tmp ); count |= count_tmp & 0x1F; if( ( count_tmp & 0x20 ) != 0 ) { count <<= 5; stream.Read( 6, out count_tmp ); count |= count_tmp & 0x1F; } } count += 2; //stream.Read( 16, out count ); //Log.log( "Read count {0}", count ); stream.Read( bits, out val ); vox = types[(int)val]; for( n = 0; n < count; n++ ) result[outpos++] = vox; } } while( outpos < 32768 ); }
public void CompressVoxelData( ushort[] data, out byte[] result, out int bytes_used ) { BitStream stream = new BitStream(); int len = data.Length; int n; List<ushort> types = new List<ushort>(); for( n = 0; n < len; n++ ) { if( !types.Contains( data[n] ) ) types.Add( data[n] ); } int bits = BitStream.GetMinBitsNeededForValue( types.Count - 1 ); // 4 is 0,1,2,3; needs only 2 bits... //bits = (bits + 7 ) & 0xf8; stream.Seek( 16 ); // seek bit count stream.Write( (byte)bits, 8 ); stream.Write( (uint)types.Count-1, bits ); foreach( ushort type in types ) stream.Write( type, 16 ); ushort prior_cube = 0xFFFF, cube; uint index = 0; int count = 0; for( n = 0; n < len; n++ ) { cube = data[n]; if( prior_cube != cube ) { if( count > 0 ) WriteCubes( stream, bits, (uint)count, index ); index = (uint)types.IndexOf( cube ); prior_cube = cube; count = 1; } else count++; } WriteCubes( stream, bits, (uint)count, index ); stream.GetBytes( out result, out bytes_used ); result[0] = (byte)(( bytes_used ) & 0xFF); result[1] = (byte)( ( bytes_used ) >> 8); if( bytes_used < 20 ) return; MemoryStream final_stream = new MemoryStream(); final_stream.Seek( 2, SeekOrigin.Begin ); //DeflateStream gz_stream = new DeflateStream( final_stream, CompressionMode.Compress ); //GZipStream gz_stream = new GZipStream( final_stream, CompressionMode.Compress ); GZipStream gz_stream = new GZipStream( final_stream, CompressionLevel.Fastest ); //for( n = 2; n < bytes_used; n++ ) // gz_stream.WriteByte( result[n] ); gz_stream.Write( result, 2, bytes_used - 2 ); gz_stream.Close(); result = final_stream.ToArray();//.GetBuffer(); Log.log( "Compressed another {0}%", (float)( 100.0f * (float)( bytes_used - result.Length ) / ( bytes_used - 2 ) ) ); // store old length so we know how much to request decompressing. result[0] = (byte)( ( bytes_used ) & 0xFF ); result[1] = (byte)( ( bytes_used ) >> 8 ); bytes_used = result.Length;// (int)final_stream.Length; gz_stream.Dispose(); }