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; }
/// <summary> /// Compresses the volume with the specified compression options. /// </summary> /// <param name="options"></param> /// <param name="multiDirection"></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 CompressedVolume Compress(VolumeCompressionOptions options, bool multiDirection = false, IProgress <VolumeSliceDefinition> progress = null, CancellationToken ct = default(CancellationToken)) { var directionMap = new DirectionMap { [Direction.Z] = CompressDirection(Direction.Z, options, progress, ct) }; if (multiDirection) { directionMap[Direction.X] = CompressDirection(Direction.X, options, progress, ct); directionMap[Direction.Y] = CompressDirection(Direction.Y, options, progress, ct); } return(new CompressedVolume(Metadata, options, directionMap)); }
/// <summary> /// Compresses the volume with the specified compression options. /// </summary> /// <param name="progress">A progress indicator, which reports the current slice number.</param> /// <param name="ct"></param> /// <param name="direction"></param> /// <param name="options">Codec settings</param> /// <exception cref="VolumeException">Error during encoding</exception> /// <exception cref="NotSupportedException">The volume has no decompressed data</exception> private byte[] CompressDirection(Direction direction, 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 SliceReader(Metadata, Data, direction, 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 static VolumeCompressionOptions Deserialize(Stream stream) { var settings = new XmlReaderSettings { IgnoreComments = true, IgnoreWhitespace = true, IgnoreProcessingInstructions = true, CloseInput = false, NameTable = new NameTable() }; using (var reader = XmlReader.Create(stream, settings)) { var result = new VolumeCompressionOptions(); reader.MoveToElement(); while (reader.Read()) { switch (reader.Name) { case "Encoder": result.Encoder = reader.ReadString(); break; case "EncoderOptions": result.EncoderOptions = OptionsFromString(reader.ReadString()); break; case "PixelFormat": result.PixelFormat = reader.ReadString(); break; case "Bitrate": result.Bitrate = int.Parse(reader.ReadString(), NumberStyles.Integer, CultureInfo.InvariantCulture); break; } } return(result); } }
/// <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> /// 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> /// 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)); }
/// <summary> /// Compresses and saves the volume in the specified stream. /// </summary> /// <param name="stream">The stream.</param> /// <param name="options">The options.</param> /// <param name="multiDirection">if set to <c>true</c> [multi direction].</param> /// <param name="progress">The progress.</param> /// <param name="ct">The ct.</param> public void Save(Stream stream, VolumeCompressionOptions options, bool multiDirection = false, IProgress <VolumeSliceDefinition> progress = null, CancellationToken ct = default(CancellationToken)) { var compressed = Compress(options, multiDirection, progress, ct); compressed.Save(stream); }