PageRenderTime 49ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/DICOM/DicomDatasetWalker.cs

https://github.com/petnet/fo-dicom
C# | 197 lines | 167 code | 30 blank | 0 comment | 33 complexity | f3992c420a1b8d7249a954853cfd40bd MD5 | raw file
Possible License(s): BSD-3-Clause
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading;
  6. using Dicom.IO.Buffer;
  7. namespace Dicom {
  8. public delegate void DicomDatasetWalkerCallback();
  9. public interface IDicomDatasetWalker {
  10. void OnBeginWalk(DicomDatasetWalker walker, DicomDatasetWalkerCallback callback);
  11. bool OnElement(DicomElement element);
  12. bool OnBeginSequence(DicomSequence sequence);
  13. bool OnBeginSequenceItem(DicomDataset dataset);
  14. bool OnEndSequenceItem();
  15. bool OnEndSequence();
  16. bool OnBeginFragment(DicomFragmentSequence fragment);
  17. bool OnFragmentItem(IByteBuffer item);
  18. bool OnEndFragment();
  19. void OnEndWalk();
  20. }
  21. public class DicomDatasetWalker {
  22. #region State Items
  23. private class BeginDicomSequenceItem : DicomItem {
  24. public BeginDicomSequenceItem(DicomDataset item) : base(DicomTag.Unknown) {
  25. Dataset = item;
  26. }
  27. public DicomDataset Dataset {
  28. get;
  29. private set;
  30. }
  31. public override DicomVR ValueRepresentation {
  32. get { return DicomVR.NONE; }
  33. }
  34. }
  35. private class EndDicomSequenceItem : DicomItem {
  36. public EndDicomSequenceItem() : base(DicomTag.Unknown) { }
  37. public override DicomVR ValueRepresentation {
  38. get { return DicomVR.NONE; }
  39. }
  40. }
  41. private class EndDicomSequence : DicomItem {
  42. public EndDicomSequence() : base(DicomTag.Unknown) { }
  43. public override DicomVR ValueRepresentation {
  44. get { return DicomVR.NONE; }
  45. }
  46. }
  47. private class DicomFragmentItem : DicomItem {
  48. public DicomFragmentItem(IByteBuffer buffer) : base(DicomTag.Unknown) {
  49. Buffer = buffer;
  50. }
  51. public IByteBuffer Buffer {
  52. get;
  53. private set;
  54. }
  55. public override DicomVR ValueRepresentation {
  56. get { return DicomVR.NONE; }
  57. }
  58. }
  59. private class EndDicomFragment : DicomItem {
  60. public EndDicomFragment() : base(DicomTag.Unknown) { }
  61. public override DicomVR ValueRepresentation {
  62. get { return DicomVR.NONE; }
  63. }
  64. }
  65. #endregion
  66. private IEnumerable<DicomItem> _dataset;
  67. private Queue<DicomItem> _items;
  68. private IDicomDatasetWalker _walker;
  69. private EventAsyncResult _async;
  70. private Exception _exception;
  71. public DicomDatasetWalker(IEnumerable<DicomItem> dataset) {
  72. _dataset = dataset;
  73. }
  74. public void Walk(IDicomDatasetWalker walker) {
  75. EndWalk(BeginWalk(walker, null, null));
  76. }
  77. public IAsyncResult BeginWalk(IDicomDatasetWalker walker, AsyncCallback callback, object state) {
  78. _walker = walker;
  79. _exception = null;
  80. _async = new EventAsyncResult(callback, state);
  81. ThreadPool.QueueUserWorkItem(Walk, null);
  82. return _async;
  83. }
  84. public void EndWalk(IAsyncResult result) {
  85. result.AsyncWaitHandle.WaitOne();
  86. if (_exception != null)
  87. throw _exception;
  88. }
  89. private void NextWalkItem() {
  90. _items.Dequeue();
  91. ThreadPool.QueueUserWorkItem(Walk, null);
  92. }
  93. private void BuildWalkQueue(IEnumerable<DicomItem> dataset) {
  94. foreach (DicomItem item in dataset) {
  95. if (item is DicomElement) {
  96. _items.Enqueue(item);
  97. } else if (item is DicomFragmentSequence) {
  98. DicomFragmentSequence sq = item as DicomFragmentSequence;
  99. _items.Enqueue(item);
  100. foreach (IByteBuffer fragment in sq) {
  101. _items.Enqueue(new DicomFragmentItem(fragment));
  102. }
  103. _items.Enqueue(new EndDicomFragment());
  104. } else if (item is DicomSequence) {
  105. DicomSequence sq = item as DicomSequence;
  106. _items.Enqueue(item);
  107. foreach (DicomDataset sqi in sq) {
  108. _items.Enqueue(new BeginDicomSequenceItem(sqi));
  109. BuildWalkQueue(sqi);
  110. _items.Enqueue(new EndDicomSequenceItem());
  111. }
  112. _items.Enqueue(new EndDicomSequence());
  113. }
  114. }
  115. }
  116. private void Walk(object state) {
  117. try {
  118. if (_items == null) {
  119. _items = new Queue<DicomItem>();
  120. BuildWalkQueue(_dataset);
  121. _walker.OnBeginWalk(this, NextWalkItem);
  122. }
  123. DicomItem item = null;
  124. while (_items.Count > 0) {
  125. item = _items.Peek();
  126. if (item is DicomElement) {
  127. if (!_walker.OnElement(item as DicomElement))
  128. return;
  129. } else if (item is DicomFragmentSequence) {
  130. if (!_walker.OnBeginFragment(item as DicomFragmentSequence))
  131. return;
  132. } else if (item is DicomFragmentItem) {
  133. if (!_walker.OnFragmentItem((item as DicomFragmentItem).Buffer))
  134. return;
  135. } else if (item is EndDicomFragment) {
  136. if (!_walker.OnEndFragment())
  137. return;
  138. } else if (item is DicomSequence) {
  139. if (!_walker.OnBeginSequence(item as DicomSequence))
  140. return;
  141. } else if (item is BeginDicomSequenceItem) {
  142. if (!_walker.OnBeginSequenceItem((item as BeginDicomSequenceItem).Dataset))
  143. return;
  144. } else if (item is EndDicomSequenceItem) {
  145. if (!_walker.OnEndSequenceItem())
  146. return;
  147. } else if (item is EndDicomSequence) {
  148. if (!_walker.OnEndSequence())
  149. return;
  150. }
  151. _items.Dequeue();
  152. }
  153. _walker.OnEndWalk();
  154. _items = null;
  155. _async.Set();
  156. } catch (Exception e) {
  157. try {
  158. _walker.OnEndWalk();
  159. } catch {
  160. }
  161. _exception = e;
  162. _items = null;
  163. _async.Set();
  164. }
  165. }
  166. }
  167. }