internal VolumeSliceRangeCollector(VolumeMetadata metaData, Direction direction, IReadOnlyCollection <VolumeSliceRangeDefinition> ranges, IProgress <VolumeSliceDefinition> progressNotifier = null, CancellationToken ct = default(CancellationToken))
        {
            if (direction != Direction.Z && ranges.Any(r => r.Direction != direction))
            {
                throw new ArgumentException("Collecting slices ranges for different directions than input is only allowed for z-directed input");
            }

            _Direction        = direction;
            _ProgressNotifier = progressNotifier;
            _Ct = ct;

            _X = metaData.SizeX;
            _Y = metaData.SizeY;
            _Z = metaData.SizeZ;

            foreach (var range in ranges)
            {
                var set = GetSlices(range.Direction);
                for (var i = range.First; i <= range.Last; i++)
                {
                    metaData.GetSliceSize(range.Direction, out var x, out var y);
                    set[i] = new byte[x * y];
                }
            }

            Interop = new InteropSliceWriter
            {
                WriteSlice = WriteSlice
            };
        }
Beispiel #2
0
        internal PreviewCreator(VolumeMetadata metadata, ushort minification, IProgress <VolumeSliceDefinition> progress = null, CancellationToken ct = default(CancellationToken))
        {
            _Metadata     = metadata ?? throw new ArgumentNullException(nameof(metadata));
            _Minification = minification;
            _Progress     = progress;
            _Ct           = ct;

            _PreviewSizeX = ( ushort )((metadata.SizeX - 1) / minification + 1);
            _PreviewSizeY = ( ushort )((metadata.SizeY - 1) / minification + 1);
            _PreviewSizeZ = ( ushort )((metadata.SizeZ - 1) / minification + 1);

            if (_PreviewSizeX < 2 || _PreviewSizeY < 2 || _PreviewSizeZ < 2)
            {
                throw new ArgumentOutOfRangeException(nameof(minification));
            }

            _PreviewData = new byte[_PreviewSizeZ][];
            long sliceSize = _PreviewSizeX * _PreviewSizeY;

            for (var z = 0; z < _PreviewSizeZ; z++)
            {
                _PreviewData[z] = new byte[sliceSize];
            }

            Interop = new InteropSliceWriter
            {
                WriteSlice = WriteSlice
            };
        }
        internal FullVolumeWriter(VolumeMetadata metadata, Direction direction, IProgress <ushort> progressNotifier = null, CancellationToken ct = default(CancellationToken))
        {
            if (metadata == null)
            {
                throw new ArgumentNullException(nameof(metadata));
            }
            _ProgressNotifier = progressNotifier;
            _Ct = ct;

            metadata.GetSliceSize(direction, out _SizeX, out _SizeY);

            _SizeZ = metadata.GetSize(direction);

            _Data = new byte[_SizeZ][];

            for (var z = 0; z < _SizeZ; z++)
            {
                _Data[z] = new byte[_SizeX * _SizeY];
            }

            Interop = new InteropSliceWriter
            {
                WriteSlice = WriteSlice
            };
        }
Beispiel #4
0
        /// <summary>
        /// Creates a new, decompressed volume from the specified data
        /// </summary>
        /// <param name="metadata">Holds additional information about a volume</param>
        /// <param name="stream">A stream to the slice data</param>
        /// <param name="options">Codec settings</param>
        /// <param name="progress">A progress indicator, which reports the current slice number.</param>
        /// <param name="ct"></param>
        /// <exception cref="VolumeException">Error during encoding</exception>
        public static Volume CreateCompressed(VolumeMetadata metadata, Stream stream, VolumeCompressionOptions options, IProgress <VolumeSliceDefinition> progress = null, CancellationToken ct = default(CancellationToken))
        {
            var compressedData = CompressStream(stream, Direction.Z, metadata, options, progress, ct);
            var dirctionMap    = new DirectionMap
            {
                [Direction.Z] = compressedData
            };

            return(new CompressedVolume(metadata, options, dirctionMap));
        }
Beispiel #5
0
        internal CompressedVolume(VolumeMetadata metadata, VolumeCompressionOptions options, DirectionMap compressedData) : base(metadata)
        {
            if (compressedData[Direction.Z] == null)
            {
                throw new NotSupportedException(Resources.GetResource <Volume>("CompressedDataMissing_ErrorText"));
            }

            _CompressedData    = compressedData;
            CompressionOptions = options;
        }
Beispiel #6
0
        private static byte[] CompressStream(Stream stream, Direction direction, VolumeMetadata metadata, VolumeCompressionOptions options, IProgress <VolumeSliceDefinition> progress = null, CancellationToken ct = default(CancellationToken))
        {
            using (var outputStream = new MemoryStream())
            {
                GetEncodedSliceSize(metadata, direction, out var encodingSizeX, out var encodingSizeY);

                var inputStreamWrapper  = new SliceStreamReader(metadata, stream, progress, ct);
                var outputStreamWrapper = new StreamWrapper(outputStream);

                var error = ( VolumeError )CompressVolume(inputStreamWrapper.Interop, outputStreamWrapper.Interop, encodingSizeX, encodingSizeY, options.Encoder, options.PixelFormat, options.GetOptionsString(), options.Bitrate);

                if (error != VolumeError.Success)
                {
                    throw new VolumeException(error, Resources.FormatResource <Volume>("Compression_ErrorText", error));
                }

                return(outputStream.ToArray());
            }
        }
        internal SliceStreamReader(VolumeMetadata metadata, Stream stream, IProgress <VolumeSliceDefinition> progressNotifier = null, CancellationToken ct = default(CancellationToken))
        {
            _Stream = stream;

            _ProgressNotifier = progressNotifier;
            _Ct           = ct;
            _CurrentSlice = 0;

            _SizeX = metadata.SizeX;
            _SizeY = metadata.SizeY;
            _SizeZ = metadata.SizeZ;

            _Buffer = new byte[0];

            Interop = new InteropSliceReader
            {
                ReadSlice = ReadSlice
            };
        }
Beispiel #8
0
        internal SliceReader(VolumeMetadata metadata, byte[][] data, Direction readDirection = Direction.Z, IProgress <VolumeSliceDefinition> progressNotifier = null, CancellationToken ct = default(CancellationToken))
        {
            _Data             = data;
            _ReadDirection    = readDirection;
            _ProgressNotifier = progressNotifier;
            _Ct           = ct;
            _CurrentSlice = 0;

            _SizeX = metadata.SizeX;
            _SizeY = metadata.SizeY;
            _SizeZ = metadata.SizeZ;

            _Buffer = new byte[0];

            Interop = new InteropSliceReader
            {
                ReadSlice = ReadSlice
            };
        }
Beispiel #9
0
        /// <summary>
        /// Extracts the specified direction.
        /// </summary>
        /// <param name="direction">The direction.</param>
        /// <param name="index">The index.</param>
        /// <param name="volumeMetadata">The volume metadata.</param>
        /// <param name="data">The data.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentOutOfRangeException">direction - null</exception>
        internal static VolumeSlice Extract(Direction direction, ushort index, VolumeMetadata volumeMetadata, byte[][] data)
        {
            var sx = volumeMetadata.SizeX;
            var sy = volumeMetadata.SizeY;
            var sz = volumeMetadata.SizeZ;

            switch (direction)
            {
            case Direction.X:
            {
                var result = new byte[sy * sz];

                Parallel.For(0, sz, z =>
                    {
                        for (var y = 0; y < sy; y++)
                        {
                            result[z * sy + y] = data[z][y * sx + index];
                        }
                    });

                return(new VolumeSlice(direction, index, result));
            }

            case Direction.Y:
            {
                var result = new byte[sx * sz];

                Parallel.For(0, sz, z => { Array.Copy(data[z], index * sx, result, z * sx, sx); });

                return(new VolumeSlice(direction, index, result));
            }

            case Direction.Z:
            {
                var result = new byte[sx * sy];
                Array.Copy(data[index], 0, result, 0, sx * sy);
                return(new VolumeSlice(direction, index, result));
            }

            default:
                throw new ArgumentOutOfRangeException(nameof(direction), direction, null);
            }
        }
Beispiel #10
0
        internal static void GetEncodedSliceSize(VolumeMetadata metadata, Direction direction, out ushort x, out ushort y)
        {
            switch (direction)
            {
            case Direction.X:
                x = ( ushort )Math.Max((metadata.SizeY + Constants.EncodingBlockSize - 1) / Constants.EncodingBlockSize * Constants.EncodingBlockSize, Constants.MinimumEncodingSize);
                y = ( ushort )Math.Max((metadata.SizeZ + Constants.EncodingBlockSize - 1) / Constants.EncodingBlockSize * Constants.EncodingBlockSize, Constants.MinimumEncodingSize);
                break;

            case Direction.Y:
                x = ( ushort )Math.Max((metadata.SizeX + Constants.EncodingBlockSize - 1) / Constants.EncodingBlockSize * Constants.EncodingBlockSize, Constants.MinimumEncodingSize);
                y = ( ushort )Math.Max((metadata.SizeZ + Constants.EncodingBlockSize - 1) / Constants.EncodingBlockSize * Constants.EncodingBlockSize, Constants.MinimumEncodingSize);
                break;

            case Direction.Z:
                x = ( ushort )Math.Max((metadata.SizeX + Constants.EncodingBlockSize - 1) / Constants.EncodingBlockSize * Constants.EncodingBlockSize, Constants.MinimumEncodingSize);
                y = ( ushort )Math.Max((metadata.SizeY + Constants.EncodingBlockSize - 1) / Constants.EncodingBlockSize * Constants.EncodingBlockSize, Constants.MinimumEncodingSize);
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(direction), direction, null);
            }
        }
Beispiel #11
0
        internal static UncompressedVolume CreatePreview(byte[][] data, VolumeMetadata metadata, ushort minification)
        {
            var sizeX        = metadata.SizeX;
            var sizeY        = metadata.SizeY;
            var sizeZ        = metadata.SizeZ;
            var previewSizeX = ( ushort )((metadata.SizeX - 1) / minification + 1);
            var previewSizeY = ( ushort )((metadata.SizeY - 1) / minification + 1);
            var previewSizeZ = ( ushort )((metadata.SizeZ - 1) / minification + 1);

            if (previewSizeX < 2 || previewSizeY < 2 || previewSizeZ < 2)
            {
                throw new ArgumentOutOfRangeException(nameof(minification));
            }

            var  result    = new byte[previewSizeZ][];
            long sliceSize = previewSizeX * previewSizeY;

            for (var z = 0; z < previewSizeZ; z++)
            {
                result[z] = new byte[sliceSize];
            }

            for (ushort z = 0, oz = 0; z < previewSizeZ && oz < sizeZ; z++, oz += minification)
            {
                var position = 0;

                for (ushort y = 0, oy = 0; y < previewSizeY && oy < sizeY; y++, oy += minification)
                {
                    for (ushort x = 0, ox = 0; x < previewSizeX && ox < sizeX; x++, ox += minification)
                    {
                        result[z][position++] = data[oz][oy * sizeX + ox];
                    }
                }
            }

            return(Volume.CreateUncompressed(new VolumeMetadata(previewSizeX, previewSizeY, previewSizeZ, metadata.ResolutionX * minification, metadata.ResolutionY * minification, metadata.ResolutionZ * minification), result));
        }
Beispiel #12
0
 internal Volume(VolumeMetadata metadata)
 {
     Metadata = metadata;
 }
Beispiel #13
0
        /// <summary>
        /// Loads volume data from the specified data stream.
        /// </summary>
        /// <param name="stream">The stream.</param>
        /// <returns></returns>
        /// <exception cref="VolumeException">Error during decoding</exception>
        /// <exception cref="NotSupportedException">The volume has no compressed data</exception>
        /// <exception cref="InvalidOperationException">One or more entries are missing in the archive.</exception>
        public static CompressedVolume Load(Stream stream)
        {
            if (!stream.CanSeek)
            {
                stream = new MemoryStream(stream.StreamToArray());
            }

            VolumeMetadata           metaData;
            DirectionMap             directionMap = new DirectionMap();
            VolumeCompressionOptions compressionOptions;

            using (var archive = new ZipArchive(stream))
            {
                #region Metadata

                var metaDataEntry = archive.GetEntry("Metadata.xml");
                if (metaDataEntry == null)
                {
                    throw new InvalidOperationException(Resources.FormatResource <Volume>("InvalidFormatMissingFile_ErrorText", "Metadata.xml"));
                }

                using (var entryStream = metaDataEntry.Open())
                {
                    metaData = VolumeMetadata.Deserialize(entryStream);
                    if (metaData.FileVersion > FileVersion)
                    {
                        throw new InvalidOperationException(Resources.FormatResource <Volume>("FileVersionError_Text", metaData.FileVersion, FileVersion));
                    }
                }

                #endregion

                #region CompressionOptions

                var compressionOptionsEntry = archive.GetEntry("CompressionOptions.xml");

                if (compressionOptionsEntry != null)
                {
                    using (var entryStream = compressionOptionsEntry.Open())
                    {
                        compressionOptions = VolumeCompressionOptions.Deserialize(entryStream);
                    }
                }
                else
                {
                    compressionOptions = null;
                }

                #endregion

                #region Voxels

                var dataEntry = archive.GetEntry("Voxels.dat");
                if (dataEntry == null)
                {
                    dataEntry = archive.GetEntry("VoxelsZ.dat");
                    if (dataEntry == null)
                    {
                        throw new InvalidOperationException(Resources.FormatResource <Volume>("InvalidFormatMissingFile_ErrorText", "Voxels.dat"));
                    }

                    using (var entryStream = dataEntry.Open())
                    {
                        directionMap[Direction.Z] = entryStream.StreamToArray();
                    }

                    dataEntry = archive.GetEntry("VoxelsY.dat");
                    if (dataEntry != null)
                    {
                        using (var entryStream = dataEntry.Open())
                        {
                            directionMap[Direction.Y] = entryStream.StreamToArray();
                        }
                    }

                    dataEntry = archive.GetEntry("VoxelsX.dat");
                    if (dataEntry != null)
                    {
                        using (var entryStream = dataEntry.Open())
                        {
                            directionMap[Direction.X] = entryStream.StreamToArray();
                        }
                    }
                }
                else
                {
                    using (var entryStream = dataEntry.Open())
                    {
                        directionMap[Direction.Z] = entryStream.StreamToArray();
                    }
                }

                #endregion
            }

            return(new CompressedVolume(metaData, compressionOptions, directionMap));
        }
        /// <summary>
        /// Extracts the specified definition.
        /// </summary>
        /// <param name="definition">The definition.</param>
        /// <param name="volumeMetadata">The volume metadata.</param>
        /// <param name="data">The data.</param>
        /// <returns></returns>
        internal static VolumeSliceRange Extract(VolumeSliceRangeDefinition definition, VolumeMetadata volumeMetadata, byte[][] data)
        {
            var slices = new List <VolumeSlice>();

            for (var i = definition.First; i <= definition.Last; i++)
            {
                slices.Add(VolumeSlice.Extract(definition.Direction, i, volumeMetadata, data));
            }

            return(new VolumeSliceRange(definition, slices));
        }
Beispiel #15
0
 /// <summary>
 /// Creates a new, decompressed volume from the specified data
 /// </summary>
 /// <param name="metadata">Describes the volumes size and resolution</param>
 /// <param name="data">The decompressed volume as 8-Bit grayscale values. The array dimensions must match the specified <paramref name="metadata"/> (byte[z][x*y]).</param>
 /// <exception cref="IndexOutOfRangeException">The specified data did not match the dimensions of the specified <paramref name="metadata"/>.</exception>
 public static UncompressedVolume CreateUncompressed(VolumeMetadata metadata, byte[][] data)
 {
     return(new UncompressedVolume(metadata, data));
 }
Beispiel #16
0
        /// <summary>
        /// Creates a new, decompressed volume from the specified data
        /// </summary>
        /// <param name="metadata">Describes the volumes size and resolution</param>
        /// <param name="data">The decompressed volume as 8-Bit grayscale values. The array dimensions must match the specified <paramref name="metadata"/> (byte[z][x*y]).</param>
        /// <param name="multiDirection"></param>
        /// <param name="progress">A progress indicator, which reports the current slice number.</param>
        /// <param name="options">Codec settings</param>
        /// <param name="ct"></param>
        /// <exception cref="IndexOutOfRangeException">The specified data did not match the dimensions of the specified <paramref name="metadata"/>.</exception>
        /// <exception cref="VolumeException">Error during encoding</exception>
        public static CompressedVolume CreateCompressed(VolumeMetadata metadata, byte[][] data, VolumeCompressionOptions options, bool multiDirection = false, IProgress <VolumeSliceDefinition> progress = null, CancellationToken ct = default(CancellationToken))
        {
            var volume = new UncompressedVolume(metadata, data);

            return(volume.Compress(options, multiDirection, progress, ct));
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="UncompressedVolume" /> class.
        /// </summary>
        /// <param name="metadata">The metadata.</param>
        /// <param name="data">The grayscale slice data.</param>
        public UncompressedVolume(VolumeMetadata metadata, byte[][] data) : base(metadata)
        {
            Data = data;

            CheckForIntegrity();
        }