/// <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> /// <returns>Awaitable <see cref="DicomFile"/> instance.</returns> public static async Task<DicomFile> OpenAsync(Stream stream, Encoding fallbackEncoding, Func<ParseState, bool> stop = null) { if (fallbackEncoding == null) { throw new ArgumentNullException("fallbackEncoding"); } var df = new DicomFile(); try { var source = new StreamByteSource(stream); 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: {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); } }
public static DicomFile Open(Stream stream, Encoding fallbackEncoding) { if (fallbackEncoding == null) { throw new ArgumentNullException("fallbackEncoding"); } var df = new DicomFile(); try { var source = new StreamByteSource(stream); var reader = new DicomFileReader(); reader.Read(source, new DicomDatasetReaderObserver(df.FileMetaInfo), new DicomDatasetReaderObserver(df.Dataset, fallbackEncoding)); df.Format = reader.FileFormat; df.Dataset.InternalTransferSyntax = reader.Syntax; return df; } catch (Exception e) { throw new DicomFileException(df, e.Message, e); } }
/// <summary> /// Process P-DATA-TF PDUs. /// </summary> /// <param name="pdu">PDU to process.</param> private async Task ProcessPDataTFAsync(PDataTF pdu) { try { foreach (var pdv in pdu.PDVs) { if (_dimse == null) { // create stream for receiving command if (_dimseStream == null) { _dimseStream = new MemoryStream(); _dimseStreamFile = null; } } else { // create stream for receiving dataset if (_dimseStream == null) { if (_dimse.Type == DicomCommandField.CStoreRequest) { var pc = Association.PresentationContexts.FirstOrDefault(x => x.ID == pdv.PCID); var file = new DicomFile(); file.FileMetaInfo.MediaStorageSOPClassUID = pc.AbstractSyntax; file.FileMetaInfo.MediaStorageSOPInstanceUID = _dimse.Command.Get<DicomUID>(DicomTag.AffectedSOPInstanceUID); file.FileMetaInfo.TransferSyntax = pc.AcceptedTransferSyntax; file.FileMetaInfo.ImplementationClassUID = Association.RemoteImplemetationClassUID; file.FileMetaInfo.ImplementationVersionName = Association.RemoteImplementationVersion; file.FileMetaInfo.SourceApplicationEntityTitle = Association.CallingAE; CreateCStoreReceiveStream(file); } else { _dimseStream = new MemoryStream(); _dimseStreamFile = null; } } } await this._dimseStream.WriteAsync(pdv.Value, 0, pdv.Value.Length).ConfigureAwait(false); if (pdv.IsLastFragment) { if (pdv.IsCommand) { _dimseStream.Seek(0, SeekOrigin.Begin); var command = new DicomDataset(); var reader = new DicomReader(); reader.IsExplicitVR = false; reader.Read(new StreamByteSource(_dimseStream), new DicomDatasetReaderObserver(command)); _dimseStream = null; _dimseStreamFile = null; var type = command.Get<DicomCommandField>(DicomTag.CommandField); switch (type) { case DicomCommandField.CStoreRequest: _dimse = new DicomCStoreRequest(command); break; case DicomCommandField.CStoreResponse: _dimse = new DicomCStoreResponse(command); break; case DicomCommandField.CFindRequest: _dimse = new DicomCFindRequest(command); break; case DicomCommandField.CFindResponse: _dimse = new DicomCFindResponse(command); break; case DicomCommandField.CMoveRequest: _dimse = new DicomCMoveRequest(command); break; case DicomCommandField.CMoveResponse: _dimse = new DicomCMoveResponse(command); break; case DicomCommandField.CEchoRequest: _dimse = new DicomCEchoRequest(command); break; case DicomCommandField.CEchoResponse: _dimse = new DicomCEchoResponse(command); break; case DicomCommandField.NActionRequest: _dimse = new DicomNActionRequest(command); break; case DicomCommandField.NActionResponse: _dimse = new DicomNActionResponse(command); break; case DicomCommandField.NCreateRequest: _dimse = new DicomNCreateRequest(command); break; case DicomCommandField.NCreateResponse: _dimse = new DicomNCreateResponse(command); break; case DicomCommandField.NDeleteRequest: _dimse = new DicomNDeleteRequest(command); break; case DicomCommandField.NDeleteResponse: _dimse = new DicomNDeleteResponse(command); break; case DicomCommandField.NEventReportRequest: _dimse = new DicomNEventReportRequest(command); break; case DicomCommandField.NEventReportResponse: _dimse = new DicomNEventReportResponse(command); break; case DicomCommandField.NGetRequest: _dimse = new DicomNGetRequest(command); break; case DicomCommandField.NGetResponse: _dimse = new DicomNGetResponse(command); break; case DicomCommandField.NSetRequest: _dimse = new DicomNSetRequest(command); break; case DicomCommandField.NSetResponse: _dimse = new DicomNSetResponse(command); break; default: _dimse = new DicomMessage(command); break; } _dimse.PresentationContext = Association.PresentationContexts.FirstOrDefault(x => x.ID == pdv.PCID); if (!_dimse.HasDataset) { this.PerformDimse(this._dimse); _dimse = null; return; } } else { if (_dimse.Type != DicomCommandField.CStoreRequest) { _dimseStream.Seek(0, SeekOrigin.Begin); var pc = Association.PresentationContexts.FirstOrDefault(x => x.ID == pdv.PCID); _dimse.Dataset = new DicomDataset(); _dimse.Dataset.InternalTransferSyntax = pc.AcceptedTransferSyntax; var source = new StreamByteSource(_dimseStream); source.Endian = pc.AcceptedTransferSyntax.Endian; var reader = new DicomReader(); reader.IsExplicitVR = pc.AcceptedTransferSyntax.IsExplicitVR; reader.Read(source, new DicomDatasetReaderObserver(_dimse.Dataset)); _dimseStream = null; _dimseStreamFile = null; } else { var request = _dimse as DicomCStoreRequest; try { var dicomFile = GetCStoreDicomFile(); _dimseStream = null; _dimseStreamFile = null; // NOTE: dicomFile will be valid with the default implementation of CreateCStoreReceiveStream() and // GetCStoreDicomFile(), but can be null if a child class overrides either method and changes behavior. // See documentation on CreateCStoreReceiveStream() and GetCStoreDicomFile() for information about why // this might be desired. request.File = dicomFile; if (request.File != null) { request.Dataset = request.File.Dataset; } } catch (Exception e) { // failed to parse received DICOM file; send error response instead of aborting connection SendResponse( new DicomCStoreResponse( request, new DicomStatus(DicomStatus.ProcessingFailure, e.Message))); Logger.Error("Error parsing C-Store dataset: {@error}", e); (this as IDicomCStoreProvider).OnCStoreRequestException( _dimseStreamFile != null ? _dimseStreamFile.Name : null, e); return; } } this.PerformDimse(this._dimse); _dimse = null; } } } } catch (Exception e) { SendAbort(DicomAbortSource.ServiceUser, DicomAbortReason.NotSpecified); Logger.Error("Exception processing P-Data-TF PDU: {@error}", e); } finally { SendNextMessage(); } }
private void ProcessPDataTF(object state) { var pdu = (PDataTF)state; try { foreach (var pdv in pdu.PDVs) { if (_dimse == null) { // create stream for receiving command if (_dimseStream == null) _dimseStream = new MemoryStream(); } else { // create stream for receiving dataset if (_dimseStream == null) { if (_dimse.Type == DicomCommandField.CStoreRequest) { var pc = Association.PresentationContexts.FirstOrDefault(x => x.ID == pdv.PCID); var file = new DicomFile(); file.FileMetaInfo.MediaStorageSOPClassUID = pc.AbstractSyntax; file.FileMetaInfo.MediaStorageSOPInstanceUID = _dimse.Command.Get<DicomUID>(DicomTag.AffectedSOPInstanceUID); file.FileMetaInfo.TransferSyntax = pc.AcceptedTransferSyntax; file.FileMetaInfo.ImplementationClassUID = Association.RemoteImplemetationClassUID; file.FileMetaInfo.ImplementationVersionName = Association.RemoteImplementationVersion; file.FileMetaInfo.SourceApplicationEntityTitle = Association.CallingAE; var fileName = TemporaryFile.Create(); file.Save(fileName); _dimseStream = File.OpenWrite(fileName); _dimseStream.Seek(0, SeekOrigin.End); } else { _dimseStream = new MemoryStream(); } } } _dimseStream.Write(pdv.Value, 0, pdv.Value.Length); if (pdv.IsLastFragment) { if (pdv.IsCommand) { _dimseStream.Seek(0, SeekOrigin.Begin); var command = new DicomDataset(); var reader = new DicomReader(); reader.IsExplicitVR = false; reader.Read(new StreamByteSource(_dimseStream), new DicomDatasetReaderObserver(command)); _dimseStream = null; var type = command.Get<DicomCommandField>(DicomTag.CommandField); switch (type) { case DicomCommandField.CStoreRequest: _dimse = new DicomCStoreRequest(command); break; case DicomCommandField.CStoreResponse: _dimse = new DicomCStoreResponse(command); break; case DicomCommandField.CFindRequest: _dimse = new DicomCFindRequest(command); break; case DicomCommandField.CFindResponse: _dimse = new DicomCFindResponse(command); break; case DicomCommandField.CMoveRequest: _dimse = new DicomCMoveRequest(command); break; case DicomCommandField.CMoveResponse: _dimse = new DicomCMoveResponse(command); break; case DicomCommandField.CEchoRequest: _dimse = new DicomCEchoRequest(command); break; case DicomCommandField.CEchoResponse: _dimse = new DicomCEchoResponse(command); break; case DicomCommandField.NActionRequest: _dimse = new DicomNActionRequest(command); break; case DicomCommandField.NActionResponse: _dimse = new DicomNActionResponse(command); break; case DicomCommandField.NCreateRequest: _dimse = new DicomNCreateRequest(command); break; case DicomCommandField.NCreateResponse: _dimse = new DicomNCreateResponse(command); break; case DicomCommandField.NDeleteRequest: _dimse = new DicomNDeleteRequest(command); break; case DicomCommandField.NDeleteResponse: _dimse = new DicomNDeleteResponse(command); break; case DicomCommandField.NEventReportRequest: _dimse = new DicomNEventReportRequest(command); break; case DicomCommandField.NEventReportResponse: _dimse = new DicomNEventReportResponse(command); break; case DicomCommandField.NGetRequest: _dimse = new DicomNGetRequest(command); break; case DicomCommandField.NGetResponse: _dimse = new DicomNGetResponse(command); break; case DicomCommandField.NSetRequest: _dimse = new DicomNSetRequest(command); break; case DicomCommandField.NSetResponse: _dimse = new DicomNSetResponse(command); break; default: _dimse = new DicomMessage(command); break; } if (!_dimse.HasDataset) { if (DicomMessage.IsRequest(_dimse.Type)) ThreadPool.QueueUserWorkItem(PerformDimseCallback, _dimse); else _processQueue.Queue((_dimse as DicomResponse).RequestMessageID, PerformDimseCallback, _dimse); _dimse = null; return; } } else { if (_dimse.Type != DicomCommandField.CStoreRequest) { _dimseStream.Seek(0, SeekOrigin.Begin); var pc = Association.PresentationContexts.FirstOrDefault(x => x.ID == pdv.PCID); _dimse.Dataset = new DicomDataset(); _dimse.Dataset.InternalTransferSyntax = pc.AcceptedTransferSyntax; var source = new StreamByteSource(_dimseStream); source.Endian = pc.AcceptedTransferSyntax.Endian; var reader = new DicomReader(); reader.IsExplicitVR = pc.AcceptedTransferSyntax.IsExplicitVR; reader.Read(source, new DicomDatasetReaderObserver(_dimse.Dataset)); _dimseStream = null; } else { var fileName = (_dimseStream as FileStream).Name; _dimseStream.Close(); _dimseStream = null; var request = _dimse as DicomCStoreRequest; try { request.File = DicomFile.Open(fileName); } catch (Exception e) { // failed to parse received DICOM file; send error response instead of aborting connection SendResponse(new DicomCStoreResponse(request, new DicomStatus(DicomStatus.ProcessingFailure, e.Message))); Logger.Error("Error parsing C-Store dataset: " + e.ToString()); (this as IDicomCStoreProvider).OnCStoreRequestException(fileName, e); return; } request.File.File.IsTempFile = true; request.Dataset = request.File.Dataset; } if (DicomMessage.IsRequest(_dimse.Type)) ThreadPool.QueueUserWorkItem(PerformDimseCallback, _dimse); else _processQueue.Queue((_dimse as DicomResponse).RequestMessageID, PerformDimseCallback, _dimse); _dimse = null; } } } } catch (Exception e) { SendAbort(DicomAbortSource.ServiceUser, DicomAbortReason.NotSpecified); Logger.Error("Exception processing P-Data-TF PDU: " + e.ToString()); } finally { SendNextMessage(); } }
public static DicomFile Open(Stream stream) { var df = new DicomFile(); try { var source = new StreamByteSource(stream); var reader = new DicomFileReader(); reader.Read(source, new DicomDatasetReaderObserver(df.FileMetaInfo), new DicomDatasetReaderObserver(df.Dataset)); df.Format = reader.FileFormat; df.Dataset.InternalTransferSyntax = reader.Syntax; return df; } catch (Exception e) { throw new DicomFileException(df, e.Message, e); } }
/// <summary> /// Asynchronously read DICOM Directory from stream. /// </summary> /// <param name="stream">Stream to read.</param> /// <param name="fallbackEncoding">Encoding to apply if it cannot be identified from DICOM directory.</param> /// <param name="stop">Stop criterion in dataset.</param> /// <returns>Awaitable <see cref="DicomDirectory"/> instance.</returns> public static new async Task<DicomDirectory> OpenAsync(Stream stream, Encoding fallbackEncoding, Func<ParseState, bool> stop = null) { if (fallbackEncoding == null) { throw new ArgumentNullException(nameof(fallbackEncoding)); } var df = new DicomDirectory(); try { var source = new StreamByteSource(stream); var reader = new DicomFileReader(); var dirObserver = new DicomDirectoryReaderObserver(df.Dataset); var result = await reader.ReadAsync( source, new DicomDatasetReaderObserver(df.FileMetaInfo), new DicomReaderMultiObserver( new DicomDatasetReaderObserver(df.Dataset, fallbackEncoding), dirObserver), stop).ConfigureAwait(false); return FinalizeDicomDirectoryLoad(df, reader, dirObserver, result); } catch (Exception e) { throw new DicomFileException(df, e.Message, e); } }