Skip to content

Commit 63f1037

Browse files
committed
feat: work on spans instead of binary reader when decoding volumes
1 parent ddf3493 commit 63f1037

File tree

4 files changed

+51
-53
lines changed

4 files changed

+51
-53
lines changed

src/PiWeb.Volume/Block/BlockInfo.cs

+5-6
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,13 @@ internal readonly record struct BlockInfo( ushort ValueCount, bool IsFirstValueS
5555
#region methods
5656

5757
/// <summary>
58-
/// Reads the <see cref="BlockInfo"/> from the specified <paramref name="reader"/>.
58+
/// Reads the <see cref="BlockInfo"/> from the specified <paramref name="value"/>.
5959
/// </summary>
60-
public static BlockInfo Read( BinaryReader reader )
60+
public static BlockInfo Create( ushort value )
6161
{
62-
var resultLength = reader.ReadUInt16();
63-
var valueCount = resultLength & ValueCountMask;
64-
var isFirstValueShort = ( resultLength & IsFirstValueShortMask ) >> IsFirstValueShortOffset;
65-
var areOtherValuesShort = ( resultLength & AreOtherValuesShortMask ) >> AreOtherValuesShortOffset;
62+
var valueCount = value & ValueCountMask;
63+
var isFirstValueShort = ( value & IsFirstValueShortMask ) >> IsFirstValueShortOffset;
64+
var areOtherValuesShort = ( value & AreOtherValuesShortMask ) >> AreOtherValuesShortOffset;
6665

6766
return new BlockInfo( (ushort)valueCount, isFirstValueShort > 0, areOtherValuesShort > 0 );
6867
}

src/PiWeb.Volume/Block/BlockVolumeDecoder.cs

+21-26
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ namespace Zeiss.PiWeb.Volume.Block;
1515

1616
using System;
1717
using System.Buffers;
18-
using System.IO;
1918
using System.Runtime.InteropServices;
2019
using System.Runtime.Intrinsics;
2120
using System.Threading;
@@ -42,37 +41,49 @@ internal static void Decode( byte[] data,
4241
IProgress<VolumeSliceDefinition>? progress = null,
4342
CancellationToken ct = default )
4443
{
45-
var reader = new BinaryReader( new MemoryStream( data ) );
46-
var (_, sizeX, sizeY, sizeZ, quantization) = BlockVolumeMetaData.Read( reader );
44+
var header = BlockVolumeMetaData.Create( data );
45+
var (_, sizeX, sizeY, sizeZ, quantization) = header;
4746
var (bcx, bcy, bcz) = BlockVolume.GetBlockCount( sizeX, sizeY, sizeZ );
4847
var blockCount = bcx * bcy;
4948
var encodedBlockInfos = new EncodedBlockInfo[ blockCount ];
49+
var position = BlockVolumeMetaData.HeaderLength;
50+
var dataSpan = data.AsSpan();
51+
52+
Quantization.Invert( quantization );
5053

5154
for( ushort biz = 0; biz < bcz; biz++ )
5255
{
5356
ct.ThrowIfCancellationRequested();
5457

55-
var layerLength = reader.ReadInt32();
58+
var layerLength = MemoryMarshal.Read<int>( dataSpan.Slice( position, sizeof( int ) ) );
59+
position += sizeof( int );
5660
if( layerPredicate?.Invoke( biz ) is false )
5761
{
58-
reader.BaseStream.Seek( layerLength, SeekOrigin.Current );
62+
position += layerLength;
5963
continue;
6064
}
6165

62-
ReadBlockInfos( reader, blockCount, encodedBlockInfos );
66+
ReadLayer( dataSpan, position, blockCount, encodedBlockInfos );
6367
DecodeLayer( data, encodedBlockInfos, bcx, bcy, biz, quantization, blockPredicate, blockAction );
6468

6569
progress?.Report( new VolumeSliceDefinition( Direction.Z, (ushort)( biz * BlockVolume.N ) ) );
70+
71+
position += layerLength;
6672
}
6773
}
6874

69-
private static void ReadBlockInfos( BinaryReader reader, int blockCount, EncodedBlockInfo[] encodedBlockInfos )
75+
private static void ReadLayer( ReadOnlySpan<byte> dataSpan, int position, int blockCount, EncodedBlockInfo[] encodedBlockInfos )
7076
{
7177
for( var i = 0; i < blockCount; i++ )
7278
{
73-
var encodedBlockInfo = EncodedBlockInfo.Read( reader );
74-
reader.BaseStream.Seek( encodedBlockInfo.Info.Length, SeekOrigin.Current );
79+
var value = MemoryMarshal.Read<ushort>( dataSpan[ position.. ] );
80+
81+
position += sizeof( ushort );
82+
83+
var encodedBlockInfo = new EncodedBlockInfo( position, BlockInfo.Create( value ) );
7584
encodedBlockInfos[ i ] = encodedBlockInfo;
85+
86+
position += encodedBlockInfo.Info.Length;
7687
}
7788
}
7889

@@ -203,23 +214,7 @@ private static void ReadBlock( ReadOnlySpan<byte> data, EncodedBlockInfo blockIn
203214

204215
#endregion
205216

206-
private readonly record struct EncodedBlockInfo( int StartIndex, BlockInfo Info )
207-
{
208-
#region methods
209-
210-
/// <summary>
211-
/// Reads the encoded block info from the specified <paramref name="reader"/>
212-
/// </summary>
213-
public static EncodedBlockInfo Read( BinaryReader reader )
214-
{
215-
var info = BlockInfo.Read( reader );
216-
var startIndex = (int)reader.BaseStream.Position;
217-
218-
return new EncodedBlockInfo( startIndex, info );
219-
}
220-
221-
#endregion
222-
}
217+
private readonly record struct EncodedBlockInfo( int StartIndex, BlockInfo Info );
223218

224219
internal delegate void BlockAction( ReadOnlySpan<byte> data, BlockIndex index );
225220

src/PiWeb.Volume/Block/BlockVolumeMetaData.cs

+22-10
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@ namespace Zeiss.PiWeb.Volume.Block;
1414

1515
using System;
1616
using System.IO;
17+
using System.Runtime.InteropServices;
1718

1819
#endregion
1920

2021
/// <summary>
2122
/// Holds information that are needed to encode and decode a block volume.
2223
/// </summary>
23-
public readonly record struct BlockVolumeMetaData( uint Version, ushort SizeX, ushort SizeY, ushort SizeZ, double[] Quantization )
24+
public record BlockVolumeMetaData( uint Version, ushort SizeX, ushort SizeY, ushort SizeZ, double[] Quantization )
2425
{
2526
#region methods
2627

@@ -40,26 +41,37 @@ public void Write( BinaryWriter writer )
4041
}
4142

4243
/// <summary>
43-
/// Reads the metadata from the specified <paramref name="reader"/>
44+
/// Reads the metadata from the specified <paramref name="data"/>
4445
/// </summary>
45-
public static BlockVolumeMetaData Read( BinaryReader reader )
46+
public static BlockVolumeMetaData Create( ReadOnlySpan<byte> data )
4647
{
47-
var header = reader.ReadUInt32();
48+
var position = 0;
49+
var header = MemoryMarshal.Read<uint>( data[ position.. ] );
50+
position += sizeof( uint );
4851
if( header != BlockVolume.FileHeader )
4952
throw new FormatException( $"Encountered unexpected file header 0x{header:x8}, expected 0x{BlockVolume.FileHeader:x8}" );
5053

51-
var version = reader.ReadUInt32();
54+
var version = MemoryMarshal.Read<uint>( data[ position.. ] );
55+
position += sizeof( uint );
5256
if( version != BlockVolume.Version )
5357
throw new FormatException( $"Encountered unexpected file header '{version}', expected {BlockVolume.Version}" );
5458

55-
var sizeX = reader.ReadUInt16();
56-
var sizeY = reader.ReadUInt16();
57-
var sizeZ = reader.ReadUInt16();
59+
var sizeX = MemoryMarshal.Read<ushort>( data[ position.. ] );
60+
position += sizeof( ushort );
61+
var sizeY = MemoryMarshal.Read<ushort>( data[ position.. ] );
62+
position += sizeof( ushort );
63+
var sizeZ = MemoryMarshal.Read<ushort>( data[ position.. ] );
64+
position += sizeof( ushort );
5865

59-
var quantization = Block.Quantization.Read( reader, true );
66+
var quantization = MemoryMarshal.Cast<byte, double>( data.Slice( position, BlockVolume.N3 * sizeof( double ) ) );
6067

61-
return new BlockVolumeMetaData( version, sizeX, sizeY, sizeZ, quantization );
68+
return new BlockVolumeMetaData( version, sizeX, sizeY, sizeZ, quantization.ToArray() );
6269
}
6370

6471
#endregion
72+
73+
/// <summary>
74+
/// The number of bytes the header consists of.
75+
/// </summary>
76+
public static int HeaderLength => 2 * sizeof( uint ) + 3 * sizeof( ushort ) + BlockVolume.N3 * sizeof( double );
6577
}

src/PiWeb.Volume/Block/Quantization.cs

+3-11
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,12 @@ internal static class Quantization
3030
#region methods
3131

3232
/// <summary>
33-
/// Reads a quantization matrix from the specified <paramref name="reader"/>
33+
/// Invert a quantization matrix.
3434
/// </summary>
35-
public static double[] Read( BinaryReader reader, bool invert )
35+
public static void Invert( double[] quantization )
3636
{
37-
var values = new double[ BlockVolume.N3 ];
38-
_ = reader.Read( MemoryMarshal.Cast<double, byte>( values.AsSpan() ) );
39-
40-
if( !invert )
41-
return values;
42-
4337
for( var i = 0; i < BlockVolume.N3; i++ )
44-
values[ i ] = 1.0 / values[ i ];
45-
46-
return values;
38+
quantization[ i ] = 1.0 / quantization[ i ];
4739
}
4840

4941
/// <summary>

0 commit comments

Comments
 (0)