示例#1
0
        public void OnElement_SmallObject_ReturnValueTrue()
        {
            const string expected = "STEREOTACTIC";

            var e = new ManualResetEventSlim(false);
            var element = new DicomCodeString(DicomTag.ApplicatorType, expected);

            using (var stream = new MemoryStream())
            {
                var target = new StreamByteTarget(stream);
                var writer = new DicomWriter(
                    DicomTransferSyntax.ExplicitVRLittleEndian,
                    new DicomWriteOptions { LargeObjectSize = 14 },
                    target);
                writer.OnBeginWalk();
                Assert.True(writer.OnElement(element));

                e.Wait(100);

                stream.Seek(8, SeekOrigin.Begin);
                using (var reader = new StreamReader(stream))
                {
                    var actual = reader.ReadToEnd().Trim();
                    Assert.Equal(expected, actual);
                }
            }
        }
示例#2
0
		private void OnCompletePreamble(IByteTarget target, object state) {
			// recalculate FMI group length as required by standard
			_fileMetaInfo.RecalculateGroupLengths();

			DicomWriter writer = new DicomWriter(DicomTransferSyntax.ExplicitVRLittleEndian, _options, _target);
			DicomDatasetWalker walker = new DicomDatasetWalker(_fileMetaInfo);
			walker.BeginWalk(writer, OnCompleteFileMetaInfo, walker);
		}
    private DicomDataset DeepClone_(DicomDataset dataset)
    {
      var ms = new MemoryStream();
      var target = new StreamByteTarget(ms);
      var writer = new DicomWriter(DicomTransferSyntax.ImplicitVRLittleEndian, DicomWriteOptions.Default, target);
      var walker = new DicomDatasetWalker(dataset);
      walker.Walk(writer);

      var clone = new DicomDataset();
      var reader = new DicomReader { IsExplicitVR = false };
      var byteSource = new ByteBufferByteSource(
        new MemoryByteBuffer(ms.ToArray()));
      reader.Read(byteSource, new DicomDatasetReaderObserver(clone));
      return clone;
    }
示例#4
0
        private void SendNextMessage()
        {
            while (true)
            {
                DicomMessage msg;

                lock (_lock)
                {
                    if (_msgQueue.Count == 0)
                    {
                        if (_pending.Count == 0) OnSendQueueEmpty();
                        return;
                    }

                    if (_sending) return;

                    if (Association.MaxAsyncOpsInvoked > 0 && _pending.Count >= Association.MaxAsyncOpsInvoked) return;

                    _sending = true;

                    msg = _msgQueue.Dequeue();
                }

                if (msg is DicomRequest) _pending.Add(msg as DicomRequest);

                DicomPresentationContext pc = null;
                if (msg is DicomCStoreRequest)
                {
                    pc =
                        Association.PresentationContexts.FirstOrDefault(
                            x =>
                                x.Result == DicomPresentationContextResult.Accept && x.AbstractSyntax == msg.SOPClassUID
                                && x.AcceptedTransferSyntax == (msg as DicomCStoreRequest).TransferSyntax);
                    if (pc == null)
                        pc =
                            Association.PresentationContexts.FirstOrDefault(
                                x =>
                                    x.Result == DicomPresentationContextResult.Accept &&
                                    x.AbstractSyntax == msg.SOPClassUID);
                }
                else
                {
                    pc =
                        Association.PresentationContexts.FirstOrDefault(
                            x =>
                                x.Result == DicomPresentationContextResult.Accept && x.AbstractSyntax == msg.SOPClassUID);
                }

                if (pc == null)
                {
                    pc = msg.PresentationContext;
                }

                if (pc == null)
                {
                    _pending.Remove(msg as DicomRequest);

                    try
                    {
                        if (msg is DicomCStoreRequest)
                            (msg as DicomCStoreRequest).PostResponse(
                                this,
                                new DicomCStoreResponse(msg as DicomCStoreRequest, DicomStatus.SOPClassNotSupported));
                        else if (msg is DicomCEchoRequest)
                            (msg as DicomCEchoRequest).PostResponse(
                                this,
                                new DicomCEchoResponse(msg as DicomCEchoRequest, DicomStatus.SOPClassNotSupported));
                        else if (msg is DicomCFindRequest)
                            (msg as DicomCFindRequest).PostResponse(
                                this,
                                new DicomCFindResponse(msg as DicomCFindRequest, DicomStatus.SOPClassNotSupported));
                        else if (msg is DicomCMoveRequest)
                            (msg as DicomCMoveRequest).PostResponse(
                                this,
                                new DicomCMoveResponse(
                                    msg as DicomCMoveRequest,
                                    DicomStatus.SOPClassNotSupported));

                        //TODO: add N services
                    }
                    catch
                    {
                    }

                    Logger.Error(
                        "No accepted presentation context found for abstract syntax: {sopClassUid}",
                        msg.SOPClassUID);
                }
                else
                {
                    var dimse = new Dimse
                    {
                        Message = msg,
                        PresentationContext = pc
                    };

                    // force calculation of command group length as required by standard
                    msg.Command.RecalculateGroupLengths();

                    if (msg.HasDataset)
                    {
                        // remove group lengths as recommended in PS 3.5 7.2
                        //
                        //	2. It is recommended that Group Length elements be removed during storage or transfer 
                        //	   in order to avoid the risk of inconsistencies arising during coercion of data 
                        //	   element values and changes in transfer syntax.
                        msg.Dataset.RemoveGroupLengths();

                        if (msg.Dataset.InternalTransferSyntax != dimse.PresentationContext.AcceptedTransferSyntax)
                            msg.Dataset =
                                msg.Dataset.ChangeTransferSyntax(dimse.PresentationContext.AcceptedTransferSyntax);
                    }

                    Logger.Info("{logId} -> {dicomMessage}", LogID, msg.ToString(Options.LogDimseDatasets));

                    try
                    {
                        dimse.Stream = new PDataTFStream(this, pc.ID, Association.MaximumPDULength);

                        var writer = new DicomWriter(
                            DicomTransferSyntax.ImplicitVRLittleEndian,
                            DicomWriteOptions.Default,
                            new StreamByteTarget(dimse.Stream));

                        dimse.Walker = new DicomDatasetWalker(msg.Command);
                        dimse.Walker.Walk(writer);

                        if (dimse.Message.HasDataset)
                        {
                            dimse.Stream.IsCommand = false;

                            writer = new DicomWriter(
                                dimse.PresentationContext.AcceptedTransferSyntax,
                                DicomWriteOptions.Default,
                                new StreamByteTarget(dimse.Stream));

                            dimse.Walker = new DicomDatasetWalker(dimse.Message.Dataset);
                            dimse.Walker.Walk(writer);
                        }
                    }
                    catch (Exception e)
                    {
                        Logger.Error("Exception sending DIMSE: {@error}", e);
                    }
                    finally
                    {
                        dimse.Stream.Flush(true).Wait();
                        dimse.Stream.Dispose();
                    }
                }

                lock (_lock) _sending = false;
            }
        }
示例#5
0
        private void OnCompleteFileMetaInfo(IAsyncResult result)
        {
            try
            {
                DicomDatasetWalker walker;

                if (result != null)
                {
                    walker = result.AsyncState as DicomDatasetWalker;
                    walker.EndWalk(result);
                }

                DicomTransferSyntax syntax = _fileMetaInfo.TransferSyntax;

                if (_options.KeepGroupLengths)
                {
                    // update transfer syntax and recalculate existing group lengths
                    _dataset.InternalTransferSyntax = syntax;
                    _dataset.RecalculateGroupLengths(false);
                }
                else
                {
                    // remove group lengths as suggested in PS 3.5 7.2
                    //
                    //	2. It is recommended that Group Length elements be removed during storage or transfer
                    //	   in order to avoid the risk of inconsistencies arising during coercion of data
                    //	   element values and changes in transfer syntax.
                    _dataset.RemoveGroupLengths();
                }

                DicomWriter writer = new DicomWriter(syntax, _options, _target);
                walker = new DicomDatasetWalker(_dataset);
                walker.BeginWalk(writer, OnCompleteDataset, walker);
            }
            catch (Exception e)
            {
                _exception = e;
                _async.Set();
            }
        }
示例#6
0
		private void OnEndSendCommand(IAsyncResult result) {
			var dimse = result.AsyncState as Dimse;
			try {
				dimse.Walker.EndWalk(result);

				dimse.Stream.IsCommand = false;

				var writer = new DicomWriter(dimse.PresentationContext.AcceptedTransferSyntax, DicomWriteOptions.Default, new StreamByteTarget(dimse.Stream));

				dimse.Walker = new DicomDatasetWalker(dimse.Message.Dataset);
				dimse.Walker.BeginWalk(writer, OnEndSendMessage, dimse);
			} catch (Exception e) {
				Logger.Error("Exception sending DIMSE: {@error}", e);
			} finally {
				if (!dimse.Message.HasDataset) {
					lock (_lock)
						_sending = false;
					SendNextMessage();
				}
			}
		}
示例#7
0
		private void SendNextMessage() {
			DicomMessage msg;

			lock (_lock) {
				if (_msgQueue.Count == 0) {
					if (_pending.Count == 0)
						OnSendQueueEmpty();
					return;
				}

				if (_sending)
					return;

				if (Association.MaxAsyncOpsInvoked > 0 && _pending.Count >= Association.MaxAsyncOpsInvoked)
					return;

				_sending = true;

				msg = _msgQueue.Dequeue();
			}

			if (msg is DicomRequest)
				_pending.Add(msg as DicomRequest);

			DicomPresentationContext pc = null;
			if (msg is DicomCStoreRequest) {
				pc = Association.PresentationContexts.FirstOrDefault(x => x.Result == DicomPresentationContextResult.Accept && x.AbstractSyntax == msg.SOPClassUID && x.AcceptedTransferSyntax == (msg as DicomCStoreRequest).TransferSyntax);
				if (pc == null)
					pc = Association.PresentationContexts.FirstOrDefault(x => x.Result == DicomPresentationContextResult.Accept && x.AbstractSyntax == msg.SOPClassUID);
			} else {
				pc = Association.PresentationContexts.FirstOrDefault(x => x.Result == DicomPresentationContextResult.Accept && x.AbstractSyntax == msg.SOPClassUID);
			}

			if (pc == null) {
				Logger.Error("No accepted presentation context found for abstract syntax: {0}", msg.SOPClassUID);
				lock (_lock)
					_sending = false;
				SendNextMessage();
				return;
			}

			var dimse = new Dimse();
			dimse.Message = msg;
			dimse.PresentationContext = pc;

			// force calculation of command group length as required by standard
			msg.Command.RecalculateGroupLengths();

			if (msg.HasDataset) {
				// remove group lengths as recommended in PS 3.5 7.2
				//
				//	2. It is recommended that Group Length elements be removed during storage or transfer 
				//	   in order to avoid the risk of inconsistencies arising during coercion of data 
				//	   element values and changes in transfer syntax.
				msg.Dataset.RemoveGroupLengths();

				if (msg.Dataset.InternalTransferSyntax != dimse.PresentationContext.AcceptedTransferSyntax)
					msg.Dataset = msg.Dataset.ChangeTransferSyntax(dimse.PresentationContext.AcceptedTransferSyntax);
			}

			Logger.Info("{0} -> {1}", LogID, msg.ToString(Options.LogDimseDatasets));

			dimse.Stream = new PDataTFStream(this, pc.ID, Association.MaximumPDULength);

			var writer = new DicomWriter(DicomTransferSyntax.ImplicitVRLittleEndian, DicomWriteOptions.Default, new StreamByteTarget(dimse.Stream));

			dimse.Walker = new DicomDatasetWalker(msg.Command);

			if (dimse.Message.HasDataset)
				dimse.Walker.BeginWalk(writer, OnEndSendCommand, dimse);
			else
				dimse.Walker.BeginWalk(writer, OnEndSendMessage, dimse);
		}
示例#8
0
        /// <summary>
        /// Write DICOM file meta information.
        /// </summary>
        /// <param name="target">Byte target subject to writing.</param>
        /// <param name="fileMetaInfo">File meta information.</param>
        /// <param name="options">Writer options.</param>
        private static void WriteFileMetaInfo(
            IByteTarget target,
            DicomDataset fileMetaInfo,
            DicomWriteOptions options)
        {
            // recalculate FMI group length as required by standard
            fileMetaInfo.RecalculateGroupLengths();

            var writer = new DicomWriter(DicomTransferSyntax.ExplicitVRLittleEndian, options, target);
            var walker = new DicomDatasetWalker(fileMetaInfo);
            walker.Walk(writer);
        }
示例#9
0
        /// <summary>
        /// Write DICOM dataset.
        /// </summary>
        /// <param name="target">Byte target subject to writing.</param>
        /// <param name="syntax">Transfer syntax applicable to dataset.</param>
        /// <param name="dataset">Dataset.</param>
        /// <param name="options">Writer options.</param>
        private static Task WriteDatasetAsync(
            IByteTarget target,
            DicomTransferSyntax syntax,
            DicomDataset dataset,
            DicomWriteOptions options)
        {
            UpdateDatasetGroupLengths(syntax, dataset, options);

            var writer = new DicomWriter(syntax, options, target);
            var walker = new DicomDatasetWalker(dataset);
            return walker.WalkAsync(writer);
        }
示例#10
0
 private void OnCompletePreamble(IByteTarget target, object state)
 {
     DicomWriter writer = new DicomWriter(DicomTransferSyntax.ExplicitVRLittleEndian, _options, _target);
     DicomDatasetWalker walker = new DicomDatasetWalker(_fileMetaInfo);
     walker.BeginWalk(writer, OnCompleteFileMetaInfo, walker);
 }
示例#11
0
        private void OnCompleteFileMetaInfo(IAsyncResult result)
        {
            try {
                DicomDatasetWalker walker;

                if (result != null) {
                    walker = result.AsyncState as DicomDatasetWalker;
                    walker.EndWalk(result);
                }

                DicomTransferSyntax syntax = _fileMetaInfo.TransferSyntax;

                DicomWriter writer = new DicomWriter(syntax, _options, _target);
                walker = new DicomDatasetWalker(_dataset);
                walker.BeginWalk(writer, OnCompleteDataset, walker);
            } catch (Exception e) {
                _exception = e;
                _async.Set();
            }
        }
示例#12
0
 private static void WalkDataset(
     IByteTarget target,
     DicomTransferSyntax syntax,
     DicomDataset dataset,
     DicomWriteOptions options)
 {
     var writer = new DicomWriter(syntax, options, target);
     var walker = new DicomDatasetWalker(dataset);
     walker.Walk(writer);
 }
示例#13
0
        private void SendNextMessage()
        {
            while (true)
            {
                DicomMessage msg;

                lock (_lock)
                {
                    if (_sending)
                    {
                        return;
                    }

                    if (_msgQueue.Count == 0)
                    {
                        if (_pending.Count == 0) OnSendQueueEmpty();
                        return;
                    }

                    if (!Options.IgnoreAsyncOps && Association.MaxAsyncOpsInvoked > 0
                        && _pending.Count >= Association.MaxAsyncOpsInvoked)
                    {
                        Logger.Debug("Cannot send messages since pending: {pending} would exceed max async ops invoked: {invoked}",
                            _pending.Count,
                            Association.MaxAsyncOpsInvoked);
                        return;
                        // Cannot easily recover from this unwanted state, so better to throw.
                        throw new DicomNetworkException(
                            "Cannot send messages since pending: {0} would exceed max async ops invoked: {1}",
                            _pending.Count,
                            Association.MaxAsyncOpsInvoked);
                    }

                    _sending = true;

                    msg = _msgQueue.Dequeue();

                    if (msg is DicomRequest)
                    {
                        _pending.Add(msg as DicomRequest);
                    }
                }

                DicomPresentationContext pc = null;
                if (msg is DicomCStoreRequest)
                {
                    pc =
                        Association.PresentationContexts.FirstOrDefault(
                            x =>
                                x.Result == DicomPresentationContextResult.Accept && x.AbstractSyntax == msg.SOPClassUID
                                && x.AcceptedTransferSyntax == (msg as DicomCStoreRequest).TransferSyntax);
                    if (pc == null)
                        pc =
                            Association.PresentationContexts.FirstOrDefault(
                                x =>
                                    x.Result == DicomPresentationContextResult.Accept &&
                                    x.AbstractSyntax == msg.SOPClassUID);
                }
                else if (msg is DicomResponse)
                {
                    //the presentation context should be set already from the request object
                    pc = msg.PresentationContext;

                    //fail safe if no presentation context is already assigned to the response (is this going to happen)
                    if (pc == null)
                    {
                        pc = this.Association.PresentationContexts.FirstOrDefault<DicomPresentationContext>(x => (x.Result == DicomPresentationContextResult.Accept) && (x.AbstractSyntax == msg.SOPClassUID));
                    }

                }
                else
                {
                    pc =
                        Association.PresentationContexts.FirstOrDefault(
                            x =>
                                x.Result == DicomPresentationContextResult.Accept && x.AbstractSyntax == msg.SOPClassUID);
                }

                if (pc == null)
                {
                    pc = msg.PresentationContext;
                }

                if (pc == null)
                {
                    lock (_lock)
                    {
                        _pending.Remove(msg as DicomRequest);
                    }

                    try
                    {
                        if (msg is DicomCStoreRequest)
                            (msg as DicomCStoreRequest).PostResponse(
                                this,
                                new DicomCStoreResponse(msg as DicomCStoreRequest, DicomStatus.SOPClassNotSupported));
                        else if (msg is DicomCEchoRequest)
                            (msg as DicomCEchoRequest).PostResponse(
                                this,
                                new DicomCEchoResponse(msg as DicomCEchoRequest, DicomStatus.SOPClassNotSupported));
                        else if (msg is DicomCFindRequest)
                            (msg as DicomCFindRequest).PostResponse(
                                this,
                                new DicomCFindResponse(
                                    msg as DicomCFindRequest,
                                    DicomStatus.SOPClassNotSupported));
                        else if (msg is DicomCGetRequest)
                            (msg as DicomCGetRequest).PostResponse(
                                this,
                                new DicomCGetResponse(
                                    msg as DicomCGetRequest,
                                    DicomStatus.SOPClassNotSupported));
                        else if (msg is DicomCMoveRequest)
                            (msg as DicomCMoveRequest).PostResponse(
                                this,
                                new DicomCMoveResponse(
                                    msg as DicomCMoveRequest,
                                    DicomStatus.SOPClassNotSupported));
                        else if (msg is DicomNActionRequest)
                            (msg as DicomNActionRequest).PostResponse(
                                this,
                                new DicomNActionResponse(
                                    msg as DicomNActionRequest,
                                    DicomStatus.SOPClassNotSupported));
                        else if (msg is DicomNCreateRequest)
                            (msg as DicomNCreateRequest).PostResponse(
                                this,
                                new DicomNCreateResponse(
                                    msg as DicomNCreateRequest,
                                    DicomStatus.SOPClassNotSupported));
                        else if (msg is DicomNDeleteRequest)
                            (msg as DicomNDeleteRequest).PostResponse(
                                this,
                                new DicomNDeleteResponse(
                                    msg as DicomNDeleteRequest,
                                    DicomStatus.SOPClassNotSupported));
                        else if (msg is DicomNEventReportRequest)
                            (msg as DicomNEventReportRequest).PostResponse(
                                this,
                                new DicomNEventReportResponse(
                                    msg as DicomNEventReportRequest,
                                    DicomStatus.SOPClassNotSupported));
                        else if (msg is DicomNGetRequest)
                            (msg as DicomNGetRequest).PostResponse(
                                this,
                                new DicomNGetResponse(
                                    msg as DicomNGetRequest,
                                    DicomStatus.SOPClassNotSupported));
                        else if (msg is DicomNSetRequest)
                            (msg as DicomNSetRequest).PostResponse(
                                this,
                                new DicomNSetResponse(
                                    msg as DicomNSetRequest,
                                    DicomStatus.SOPClassNotSupported));
                        else
                        {
                            Logger.Warn("Unknown message type: {type}", msg.Type);
                        }
                    }
                    catch
                    {
                    }

                    Logger.Error(
                        "No accepted presentation context found for abstract syntax: {sopClassUid}",
                        msg.SOPClassUID);
                }
                else
                {
                    var dimse = new Dimse
                    {
                        Message = msg,
                        PresentationContext = pc
                    };

                    // force calculation of command group length as required by standard
                    msg.Command.RecalculateGroupLengths();

                    if (msg.HasDataset)
                    {
                        // remove group lengths as recommended in PS 3.5 7.2
                        //
                        //	2. It is recommended that Group Length elements be removed during storage or transfer 
                        //	   in order to avoid the risk of inconsistencies arising during coercion of data 
                        //	   element values and changes in transfer syntax.
                        msg.Dataset.RemoveGroupLengths();

                        if (msg.Dataset.InternalTransferSyntax != dimse.PresentationContext.AcceptedTransferSyntax)
                        {
                            Logger.Debug("{logId} Changing Transfer Syntax from {0} to {1}", LogID, msg.Dataset.InternalTransferSyntax, dimse.PresentationContext.AcceptedTransferSyntax);
                            msg.Dataset =
                                msg.Dataset.Clone(dimse.PresentationContext.AcceptedTransferSyntax);
                        }
                    }

                    Logger.Info("{logId} -> {dicomMessage}", LogID, msg.ToString(Options.LogDimseDatasets));

                    try
                    {
                        dimse.Stream = new PDataTFStream(this, pc.ID, Association.MaximumPDULength);

                        var writer = new DicomWriter(
                            DicomTransferSyntax.ImplicitVRLittleEndian,
                            DicomWriteOptions.Default,
                            new StreamByteTarget(dimse.Stream));

                        dimse.Walker = new DicomDatasetWalker(msg.Command);
                        dimse.Walker.Walk(writer);

                        if (dimse.Message.HasDataset)
                        {
                            dimse.Stream.SetIsCommandAsync(false).Wait();

                            writer = new DicomWriter(
                                dimse.PresentationContext.AcceptedTransferSyntax,
                                DicomWriteOptions.Default,
                                new StreamByteTarget(dimse.Stream));

                            dimse.Walker = new DicomDatasetWalker(dimse.Message.Dataset);
                            dimse.Walker.Walk(writer);
                        }
                    }
                    catch (Exception e)
                    {
                        Logger.Error("Exception sending DIMSE: {@error}", e);
                    }
                    finally
                    {
                        dimse.Stream.FlushAsync(true).Wait();
                        dimse.Stream.Dispose();
                    }
                }

                lock (_lock) _sending = false;
            }
        }
示例#14
0
        public void OnFragmentItem_LargeBuffer_ReturnValueTrue()
        {
            var expected = Enumerable.Range(0, 256).Select(i => (byte)i).ToArray();

            var e = new ManualResetEventSlim(false);

            using (var stream = new MemoryStream())
            {
                var target = new StreamByteTarget(stream);
                var writer = new DicomWriter(
                    DicomTransferSyntax.ExplicitVRLittleEndian,
                    new DicomWriteOptions { LargeObjectSize = 200 },
                    target);
                writer.OnBeginWalk();
                Assert.True(writer.OnFragmentItem(new MemoryByteBuffer(expected)));

                e.Wait(100);

                var actual = new byte[expected.Length];
                stream.Seek(8, SeekOrigin.Begin);
                stream.Read(actual, 0, actual.Length);
                Assert.Equal(expected, actual);
            }
        }