/// <summary> /// Returns a newly created instance of a stream byte source class. /// The actual class depends on the stream capabilities. /// </summary> /// <param name="stream">Stream to read from.</param> /// <param name="readOption">Defines the handling of large tags.</param> /// <param name="largeObjectSize">Custom limit of what are large values and what are not. /// If 0 is passed, then the default of 64k is used.</param> public static IByteSource Create(Stream stream, FileReadOption readOption = FileReadOption.Default, int largeObjectSize = 0) { if (stream.CanSeek) { return(new StreamByteSource(stream, readOption, largeObjectSize)); } return(new UnseekableStreamByteSource(stream, readOption, largeObjectSize)); }
//======================================= //関数 //======================================= /// <summary> /// /// </summary> public FileBuilder( IFileWriter <T> writer, IFileParser <T> parser, FileReadOption readOption = FileReadOption.None, FileWriteOption writeOption = FileWriteOption.None ) { Writer = writer; Parser = parser; ReadOption = readOption; WriteOption = writeOption; }
/// <summary> /// Initializes a new instance of <see cref="StreamByteSource"/>. /// </summary> /// <param name="stream">Stream to read from.</param> public StreamByteSource(Stream stream, FileReadOption readOption = FileReadOption.Default) { _stream = stream; _endian = Endian.LocalMachine; _reader = EndianBinaryReader.Create(_stream, _endian); _mark = 0; // here the mapping of the default option is applied - may be extracted into some GlobalSettings class or similar _readOption = (readOption == FileReadOption.Default) ? FileReadOption.ReadLargeOnDemand : readOption; LargeObjectSize = 64 * 1024; _milestones = new Stack <long>(); _lock = new object(); }
/// <summary> /// Initializes an instance of <see cref="FileByteSource"/>. /// </summary> /// <param name="file">File to read from.</param> /// <param name="readOption">Option how to deal with large values, if they should be loaded directly into memory or lazy loaded on demand</param> /// <param name="largeObjectSize">Custom limit of what are large values and what are not. If 0 is passend, then the default of 64k is used.</param> public FileByteSource(IFileReference file, FileReadOption readOption, int largeObjectSize) { _file = file; _stream = _file.OpenRead(); _endian = Endian.LocalMachine; _reader = EndianBinaryReader.Create(_stream, _endian); Marker = 0; // here the mapping of the default option is applied - may be extracted into some GlobalSettings class or similar _readOption = (readOption == FileReadOption.Default) ? FileReadOption.ReadLargeOnDemand : readOption; LargeObjectSize = largeObjectSize <= 0 ? 64 * 1024 : largeObjectSize; _milestones = new Stack <long>(); _lock = new object(); _disposed = false; }
/// <summary> /// Interrogates directory tree for dicom files and produces series info and individual file info /// </summary> /// <param name="options"></param> /// <param name="fileSystemOptions"></param> /// <param name="seriesMessageProducerModel"></param> /// <param name="fileMessageProducerModel"></param> /// <param name="fs">File system to use</param> public TagReaderBase(DicomTagReaderOptions options, FileSystemOptions fileSystemOptions, IProducerModel seriesMessageProducerModel, IProducerModel fileMessageProducerModel, IFileSystem fs) { Logger = LogManager.GetLogger(GetType().Name); _filesystemRoot = fileSystemOptions.FileSystemRoot; NackIfAnyFileErrors = options.NackIfAnyFileErrors; _searchPattern = fileSystemOptions.DicomSearchPattern; _fileReadOption = options.GetReadOption(); Logger.Debug($"FileReadOption is: {_fileReadOption}"); _seriesMessageProducerModel = seriesMessageProducerModel; _fileMessageProducerModel = fileMessageProducerModel; _fs = fs; Logger.Info($"Stopwatch implementation - IsHighResolution: {Stopwatch.IsHighResolution}. Frequency: {Stopwatch.Frequency} ticks/s"); }
/// <summary> /// Initializes a new instance of <see cref="UnseekableStreamByteSource"/>. /// </summary> /// <param name="stream">Stream to read from.</param> /// <param name="readOption">Defines the handling of large tags.</param> /// <param name="largeObjectSize">Custom limit of what are large values and what are not. /// If 0 is passed, then the default of 64k is used.</param> public UnseekableStreamByteSource(Stream stream, FileReadOption readOption = FileReadOption.Default, int largeObjectSize = 0) { if (readOption == FileReadOption.Default || readOption == FileReadOption.ReadLargeOnDemand) { var logger = Setup.ServiceProvider.GetRequiredService <ILogManager>().GetLogger("FellowOakDicom.IO"); logger.Warn("Reading large files on demand is not possible with unseekable streams, reading all tags immediately instead."); readOption = FileReadOption.ReadAll; } _byteSource = new StreamByteSource(stream, readOption, largeObjectSize); _buffer = new MemoryStream(); _bufferReader = EndianBinaryReader.Create(_buffer, Endian.LocalMachine); _bufferWriter = EndianBinaryWriter.Create(_buffer, Endian.LocalMachine); _bufferState = BufferState.Unused; // we cannot use the milestones of the stream byte source, as these don't // account for the buffer _milestones = new Stack <long>(); }
/// <summary> /// Reads the specified filename and returns a DicomFile object. Note that the values for large /// DICOM elements (e.g. PixelData) are read in "on demand" to conserve memory. Large DICOM elements /// are determined by their size in bytes - see the default value for this in the FileByteSource._largeObjectSize /// </summary> /// <param name="fileName">The filename of the DICOM file</param> /// <param name="fallbackEncoding">Encoding to apply when attribute Specific Character Set is not available.</param> /// <param name="stop">Stop criterion in dataset.</param> /// <returns>DicomFile instance</returns> public static DicomFile Open(string fileName, Encoding fallbackEncoding, Func <ParseState, bool> stop = null, FileReadOption readOption = FileReadOption.Default) { if (fallbackEncoding == null) { throw new ArgumentNullException(nameof(fallbackEncoding)); } DicomFile df = new DicomFile(); try { df.File = IOManager.CreateFileReference(fileName); using (var source = new FileByteSource(df.File, readOption)) { var reader = new DicomFileReader(); var result = reader.Read( source, new DicomDatasetReaderObserver(df.FileMetaInfo), new DicomDatasetReaderObserver(df.Dataset, fallbackEncoding), stop); if (result == DicomReaderResult.Processing) { throw new DicomFileException(df, "Invalid read return state: {state}", result); } if (result == DicomReaderResult.Error) { return(null); } df.IsPartial = result == DicomReaderResult.Stopped || result == DicomReaderResult.Suspended; df.Format = reader.FileFormat; df.Dataset.InternalTransferSyntax = reader.Syntax; return(df); } } catch (Exception e) { throw new DicomFileException(df, e.Message, e); } }
/// <summary> /// Reads the specified filename and returns a DicomFile object. Note that the values for large /// DICOM elements (e.g. PixelData) are read in "on demand" to conserve memory. Large DICOM elements /// are determined by their size in bytes - see the default value for this in the FileByteSource._largeObjectSize /// </summary> /// <param name="fileName">The filename of the DICOM file</param> /// <param name="readOption">An option how to deal with large dicom tags like pixel data.</param> /// <returns>DicomFile instance</returns> public static DicomFile Open(string fileName, FileReadOption readOption = FileReadOption.Default) { return(Open(fileName, DicomEncoding.Default, readOption: readOption)); }
/// <summary> /// Read a DICOM file from stream. /// </summary> /// <param name="stream">Stream to read.</param> /// <param name="readOption">The option how to deal with large DICOM tags like pixel data.</param> /// <returns>Read <see cref="DicomFile"/>.</returns> public static DicomFile Open(Stream stream, FileReadOption readOption = FileReadOption.Default) { return(Open(stream, DicomEncoding.Default, readOption: readOption)); }
/// <summary> /// Reads the specified file and returns a DicomFile object. Note that the values for large /// DICOM elements (e.g. PixelData) are read in "on demand" to conserve memory. Large DICOM elements /// are determined by their size in bytes - see the default value for this in the FileByteSource._largeObjectSize /// </summary> /// <param name="file">The file reference of the DICOM file</param> /// <param name="fallbackEncoding">Encoding to apply when attribute Specific Character Set is not available.</param> /// <param name="readOption">Option how to deal with large values, if they should be loaded directly into memory or lazy loaded on demand</param> /// <param name="largeObjectSize">Custom limit of what are large values and what are not. If 0 is passend, then the default of 64k is used.</param> /// <returns>DicomFile instance</returns> internal static DicomFile Open(IFileReference file, Encoding fallbackEncoding, FileReadOption readOption = FileReadOption.Default, int largeObjectSize = 0) { if (fallbackEncoding == null) { throw new ArgumentNullException(nameof(fallbackEncoding)); } var df = new DicomFile(); try { df.File = file; using var source = new FileByteSource(file, readOption, largeObjectSize); using var unvalidated = new UnvalidatedScope(df.Dataset); var reader = new DicomFileReader(); var result = reader.Read( source, new DicomDatasetReaderObserver(df.FileMetaInfo), new DicomDatasetReaderObserver(df.Dataset, fallbackEncoding)); HandleOpenError(df, result); df.IsPartial = result == DicomReaderResult.Stopped || result == DicomReaderResult.Suspended; df.Format = reader.FileFormat; df.Dataset.InternalTransferSyntax = reader.Syntax; return(df); } catch (Exception e) { throw new DicomFileException(df, e.Message, e); } }
/// <summary> /// Asynchronously read a DICOM file from stream. /// </summary> /// <param name="stream">Stream to read.</param> /// <param name="readOption">The option how to deal with large DICOM tags like pixel data.</param> /// <param name="largeObjectSize">Custom limit of what are large values and what are not. If 0 is passend, then the default of 64k is used.</param> /// <returns>Awaitable <see cref="DicomFile"/> instance.</returns> public static Task <DicomFile> OpenAsync(Stream stream, FileReadOption readOption = FileReadOption.Default, int largeObjectSize = 0) => OpenAsync(stream, DicomEncoding.Default, readOption: readOption, largeObjectSize: largeObjectSize);
/// <summary> /// Asynchronously read a DICOM file from stream. /// </summary> /// <param name="stream">Stream to read.</param> /// <param name="fallbackEncoding">Encoding to use if encoding cannot be obtained from DICOM file.</param> /// <param name="stop">Stop criterion in dataset.</param> /// <param name="readOption">The option how to deal with large DICOM tags like pixel data.</param> /// <param name="largeObjectSize">Custom limit of what are large values and what are not. If 0 is passend, then the default of 64k is used.</param> /// <returns>Awaitable <see cref="DicomFile"/> instance.</returns> public static async Task <DicomFile> OpenAsync(Stream stream, Encoding fallbackEncoding, Func <ParseState, bool> stop = null, FileReadOption readOption = FileReadOption.Default, int largeObjectSize = 0) { if (fallbackEncoding == null) { throw new ArgumentNullException(nameof(fallbackEncoding)); } var df = new DicomFile(); try { var source = StreamByteSourceFactory.Create(stream, readOption, largeObjectSize); using var unvalidated = new UnvalidatedScope(df.Dataset); var reader = new DicomFileReader(); var result = await reader.ReadAsync( source, new DicomDatasetReaderObserver(df.FileMetaInfo), new DicomDatasetReaderObserver(df.Dataset, fallbackEncoding), stop).ConfigureAwait(false); HandleOpenError(df, result); df.IsPartial = result == DicomReaderResult.Stopped || result == DicomReaderResult.Suspended; df.Format = reader.FileFormat; df.Dataset.InternalTransferSyntax = reader.Syntax; return(df); } catch (Exception e) { throw new DicomFileException(df, e.Message, e); } }
/// <summary> /// Reads the specified filename and returns a DicomFile object. Note that the values for large /// DICOM elements (e.g. PixelData) are read in "on demand" to conserve memory. Large DICOM elements /// are determined by their size in bytes - see the default value for this in the FileByteSource._largeObjectSize /// </summary> /// <param name="fileName">The filename of the DICOM file</param> /// <param name="readOption">An option how to deal with large dicom tags like pixel data.</param> /// <param name="largeObjectSize">Custom limit of what are large values and what are not. If 0 is passend, then the default of 64k is used.</param> /// <returns>DicomFile instance</returns> public static DicomFile Open(string fileName, FileReadOption readOption = FileReadOption.Default, int largeObjectSize = 0) => Open(fileName, DicomEncoding.Default, readOption: readOption, largeObjectSize: largeObjectSize);
/// <summary> /// Asynchronously reads the specified filename and returns a DicomFile object. Note that the values for large /// DICOM elements (e.g. PixelData) are read in "on demand" to conserve memory. Large DICOM elements /// are determined by their size in bytes - see the default value for this in the FileByteSource._largeObjectSize /// </summary> /// <param name="fileName">The filename of the DICOM file</param> /// <param name="readOption">The option how to deal with large dicom tags like pixel data.</param> /// <returns>Awaitable <see cref="DicomFile"/> instance.</returns> public static Task <DicomFile> OpenAsync(string fileName, FileReadOption readOption = FileReadOption.Default) { return(OpenAsync(fileName, DicomEncoding.Default, readOption: readOption)); }
/// <summary> /// Reads the specified file and returns a DicomFile object. Note that the values for large /// DICOM elements (e.g. PixelData) are read in "on demand" to conserve memory. Large DICOM elements /// are determined by their size in bytes - see the default value for this in the FileByteSource._largeObjectSize /// </summary> /// <param name="file">The file reference of the DICOM file</param> /// <param name="fallbackEncoding">Encoding to apply when attribute Specific Character Set is not available.</param> /// <returns>DicomFile instance</returns> internal static DicomFile Open(IFileReference file, Encoding fallbackEncoding, FileReadOption readOption = FileReadOption.Default) { if (fallbackEncoding == null) { throw new ArgumentNullException(nameof(fallbackEncoding)); } DicomFile df = new DicomFile(); try { df.File = file; using (var source = new FileByteSource(file, readOption)) using (var unvalidated = new UnvalidatedScope(df.Dataset)) { DicomFileReader reader = new DicomFileReader(); var result = reader.Read( source, new DicomDatasetReaderObserver(df.FileMetaInfo), new DicomDatasetReaderObserver(df.Dataset, fallbackEncoding)); if (result == DicomReaderResult.Processing) { throw new DicomFileException(df, $"Invalid read return state: {result}"); } if (result == DicomReaderResult.Error) { return(null); } df.IsPartial = result == DicomReaderResult.Stopped || result == DicomReaderResult.Suspended; df.Format = reader.FileFormat; df.Dataset.InternalTransferSyntax = reader.Syntax; return(df); } } catch (Exception e) { throw new DicomFileException(df, e.Message, e); } }
/// <summary> /// Asynchronously read a DICOM file from stream. /// </summary> /// <param name="stream">Stream to read.</param> /// <param name="fallbackEncoding">Encoding to use if encoding cannot be obtained from DICOM file.</param> /// <param name="stop">Stop criterion in dataset.</param> /// <param name="readOption">The option how to deal with large DICOM tags like pixel data.</param> /// <returns>Awaitable <see cref="DicomFile"/> instance.</returns> public static async Task <DicomFile> OpenAsync(Stream stream, Encoding fallbackEncoding, Func <ParseState, bool> stop = null, FileReadOption readOption = FileReadOption.Default) { if (fallbackEncoding == null) { throw new ArgumentNullException(nameof(fallbackEncoding)); } var df = new DicomFile(); try { var source = new StreamByteSource(stream, readOption); using (var unvalidated = new UnvalidatedScope(df.Dataset)) { var reader = new DicomFileReader(); var result = await reader.ReadAsync( source, new DicomDatasetReaderObserver(df.FileMetaInfo), new DicomDatasetReaderObserver(df.Dataset, fallbackEncoding), stop).ConfigureAwait(false); if (result == DicomReaderResult.Processing) { throw new DicomFileException(df, $"Invalid read return state: {result}"); } if (result == DicomReaderResult.Error) { return(null); } df.IsPartial = result == DicomReaderResult.Stopped || result == DicomReaderResult.Suspended; df.Format = reader.FileFormat; df.Dataset.InternalTransferSyntax = reader.Syntax; return(df); } } catch (Exception e) { throw new DicomFileException(df, e.Message, e); } }
/// <summary> /// Asynchronously read a DICOM file from stream. /// </summary> /// <param name="stream">Stream to read.</param> /// <param name="readOption">The option how to deal with large DICOM tags like pixel data.</param> /// <returns>Awaitable <see cref="DicomFile"/> instance.</returns> public static Task <DicomFile> OpenAsync(Stream stream, FileReadOption readOption = FileReadOption.Default) { return(OpenAsync(stream, DicomEncoding.Default, readOption: readOption)); }