private DicomDirectoryRecord ParseDirectoryRecord(uint offset, List <uint> notFoundOffsets)
        {
            DicomDirectoryRecord record = null;

            if (!_lookup.TryGetValue(offset, out var dataset))
            {
                if (offset != 0)
                {
                    notFoundOffsets.Add(offset);
                }
            }
            else
            {
                record = new DicomDirectoryRecord(dataset)
                {
                    Offset = offset
                };

                _lookup.Remove(offset);

                record.NextDirectoryRecord =
                    ParseDirectoryRecord(record.GetSingleValue <uint>(DicomTag.OffsetOfTheNextDirectoryRecord), notFoundOffsets);

                record.LowerLevelDirectoryRecord =
                    ParseDirectoryRecord(record.GetSingleValue <uint>(DicomTag.OffsetOfReferencedLowerLevelDirectoryEntity), notFoundOffsets);
            }

            return(record);
        }
Exemple #2
0
        public void Exact_Offsets_Should_All_Match()
        {
            var offsets = GenerateUniqueRandonmOffsets(155, 500000);
            var root    = new Container()
            {
                Sequence = new DicomDataset()
            };

            root.CreateChildren(offsets, 5, 3, 3, 2);

            var allChildren = root.AllContainer.Skip(1).ToArray();
            var sequence    = new DicomSequence(DicomTag.DirectoryRecordSequence);

            root.Sequence.AddOrUpdate(sequence);

            var byteSource = new TestByteSource();
            var observer   = new DicomDirectoryReaderObserver(root.Sequence);

            observer.OnBeginSequence(byteSource, DicomTag.DirectoryRecordSequence, 0);
            foreach (var container in allChildren)
            {
                sequence.Items.Add(container.Sequence);
                byteSource.Position = container.Offset + 8;
                observer.OnBeginSequenceItem(byteSource, 0);
                observer.OnEndSequenceItem();
            }
            observer.OnEndSequence();

            var rootRecord = new DicomDirectoryRecord
            {
                LowerLevelDirectoryRecord = observer.BuildDirectoryRecords(),
            };

            root.AssertRecord(rootRecord);
        }
        private DicomDirectoryRecord ParseDirectoryRecord(DicomDirectoryRecord record, uint offset, uint[] offsets)
        {
            if (record == null)
            {
                // Find the best matching existing offset for the given offset
                // The given offset should be in offsets and the following entry in that sorted array gives
                // us the next used offset. That's the upper bound for the search

                var index = Array.BinarySearch(offsets, offset);
                if (index < 0)
                {
                    return(null);
                }
                uint maxOffset;
                int  maxIndex = offsets.Length - 1;
                // Deal with the rare possibility that offsets can contain duplicates
                while (true)
                {
                    if (index >= maxIndex)
                    {
                        maxOffset = uint.MaxValue;
                        break;
                    }
                    maxOffset = offsets[++index];
                    if (maxOffset != offset)
                    {
                        break;
                    }
                }
                offset = _lookup.Keys.FirstOrDefault(key => key >= offset && key < maxOffset);
                if (!_lookup.TryGetValue(offset, out var dataset))
                {
                    return(null);
                }

                record = new DicomDirectoryRecord(dataset)
                {
                    Offset = offset
                };

                _lookup.Remove(offset);
            }

            var nextOffset = record.GetSingleValue <uint>(DicomTag.OffsetOfTheNextDirectoryRecord);

            if (nextOffset > 0)
            {
                record.NextDirectoryRecord = ParseDirectoryRecord(record.NextDirectoryRecord, nextOffset, offsets);
            }

            var lowerLevelOffset = record.GetSingleValue <uint>(DicomTag.OffsetOfReferencedLowerLevelDirectoryEntity);

            if (lowerLevelOffset > 0)
            {
                record.LowerLevelDirectoryRecord = ParseDirectoryRecord(record.LowerLevelDirectoryRecord, lowerLevelOffset, offsets);
            }

            return(record);
        }
		private DicomDirectoryRecord ParseDirectoryRecord(uint offset) {
			DicomDirectoryRecord record = null;
			if (_lookup.ContainsKey(offset)) {
				record = new DicomDirectoryRecord(_lookup[offset]);
				record.Offset = offset;

				record.NextDirectoryRecord = ParseDirectoryRecord(record.Get<uint>(DicomTag.OffsetOfTheNextDirectoryRecord));

				record.LowerLevelDirectoryRecord = ParseDirectoryRecord(record.Get<uint>(DicomTag.OffsetOfReferencedLowerLevelDirectoryEntity));
			}

			return record;
		}
Exemple #5
0
        public void Duplicate_Offsets_Should_Not_Throw()
        {
            var offsets = new List <uint>(GenerateUniqueRandonmOffsets(155, 100000).Select(o => o * 5));

            for (int i = 0; i < offsets.Count - 2; i += 2)
            {
                offsets[i + 1] = offsets[i];
            }

            var root = new Container()
            {
                Sequence = new DicomDataset()
            };

            root.CreateChildren(offsets, 5, 3, 3, 2);

            var allChildren = root.AllContainer.Skip(1).ToArray();
            var sequence    = new DicomSequence(DicomTag.DirectoryRecordSequence);

            root.Sequence.AddOrUpdate(sequence);

            var byteSource = new TestByteSource();
            var observer   = new DicomDirectoryReaderObserver(root.Sequence);

            observer.OnBeginSequence(byteSource, DicomTag.DirectoryRecordSequence, 0);
            uint lastPosition = 0;

            foreach (var container in allChildren)
            {
                sequence.Items.Add(container.Sequence);
                var position = container.Offset + 8;
                if (position == lastPosition)
                {
                    position += 1;
                }
                lastPosition = position;

                byteSource.Position = position;
                observer.OnBeginSequenceItem(byteSource, 0);
                observer.OnEndSequenceItem();
            }
            observer.OnEndSequence();

            var rootRecord = new DicomDirectoryRecord
            {
                LowerLevelDirectoryRecord = observer.BuildDirectoryRecords(),
            };

            // Cannot assert all records when duplicate offsets exist.
            // root.AssertRecord(rootRecord);
        }
        public DicomDirectoryRecord BuildDirectoryRecords()
        {
            var notFoundOffsets       = new List <uint>();
            var offset                = _dataset.GetSingleValue <uint>(DicomTag.OffsetOfTheFirstDirectoryRecordOfTheRootDirectoryEntity);
            DicomDirectoryRecord root = ParseDirectoryRecord(offset, notFoundOffsets);

            if (_lookup.Count > 0)
            {
                // There are unresolved sequences. Try to resolve them with non exact offset match
                root = ParseDirectoryRecordNotExact(root, offset, notFoundOffsets);
            }

            return(root);
        }
Exemple #7
0
        private DicomDirectoryRecord ParseDirectoryRecord(uint offset)
        {
            DicomDirectoryRecord record = null;

            if (_lookup.ContainsKey(offset))
            {
                record        = new DicomDirectoryRecord(_lookup[offset]);
                record.Offset = offset;

                record.NextDirectoryRecord = ParseDirectoryRecord(record.Get <uint>(DicomTag.OffsetOfTheNextDirectoryRecord));

                record.LowerLevelDirectoryRecord = ParseDirectoryRecord(record.Get <uint>(DicomTag.OffsetOfReferencedLowerLevelDirectoryEntity));
            }

            return(record);
        }
Exemple #8
0
            public void AssertRecord(DicomDirectoryRecord record)
            {
                if (Id != 0)
                {
                    Assert.Equal(Id.ToString(), record.GetSingleValue <string>(DicomTag.SOPInstanceUID));
                }

                DicomDirectoryRecord current = record.LowerLevelDirectoryRecord;

                foreach (var child in Children)
                {
                    Assert.NotNull(current);
                    child.AssertRecord(current);
                    current = current.NextDirectoryRecord;
                }
                Assert.Null(current);
            }
Exemple #9
0
        private void CreateImageRecord(
            DicomFileMetaInformation metaFileInfo,
            DicomDataset dataset,
            DicomDirectoryRecord seriesRecord,
            string referencedFileId)
        {
            var currentImage     = seriesRecord.LowerLevelDirectoryRecord;
            var imageInstanceUid = dataset.Get <string>(DicomTag.SOPInstanceUID);


            while (currentImage != null)
            {
                if (currentImage.Get <string>(DicomTag.ReferencedSOPInstanceUIDInFile) == imageInstanceUid)
                {
                    return;
                }

                if (currentImage.NextDirectoryRecord != null)
                {
                    currentImage = currentImage.NextDirectoryRecord;
                }
                else
                {
                    //no more patient records, break the loop
                    break;
                }
            }
            var newImage = CreateRecordSequenceItem(DicomDirectoryRecordType.Image, dataset);

            newImage.AddOrUpdate(DicomTag.ReferencedFileID, referencedFileId);
            newImage.AddOrUpdate(DicomTag.ReferencedSOPClassUIDInFile, metaFileInfo.MediaStorageSOPClassUID.UID);
            newImage.AddOrUpdate(DicomTag.ReferencedSOPInstanceUIDInFile, metaFileInfo.MediaStorageSOPInstanceUID.UID);
            newImage.AddOrUpdate(DicomTag.ReferencedTransferSyntaxUIDInFile, metaFileInfo.TransferSyntax.UID);

            if (currentImage != null)
            {
                //study not found under patient record
                currentImage.NextDirectoryRecord = newImage;
            }
            else
            {
                //no studies record found under patient record
                seriesRecord.LowerLevelDirectoryRecord = newImage;
            }
        }
Exemple #10
0
        private void AddDirectoryRecordsToSequenceItem(DicomDirectoryRecord recordItem)
        {
            if (recordItem == null)
            {
                return;
            }

            _directoryRecordSequence.Items.Add(recordItem);
            if (recordItem.LowerLevelDirectoryRecord != null)
            {
                AddDirectoryRecordsToSequenceItem(recordItem.LowerLevelDirectoryRecord);
            }

            if (recordItem.NextDirectoryRecord != null)
            {
                AddDirectoryRecordsToSequenceItem(recordItem.NextDirectoryRecord);
            }
        }
        private DicomDirectoryRecord ParseDirectoryRecordNotExact(DicomDirectoryRecord root, uint rootOffset, List <uint> offsets)
        {
            // Collect all used offsets, and sort them (they can contain duplicates)
            foreach (var dataset in _lookup.Values)
            {
                var offset = dataset.GetSingleValue <uint>(DicomTag.OffsetOfTheNextDirectoryRecord);
                if (offset > 0)
                {
                    offsets.Add(offset);
                }
                offset = dataset.GetSingleValue <uint>(DicomTag.OffsetOfReferencedLowerLevelDirectoryEntity);
                if (offset > 0)
                {
                    offsets.Add(offset);
                }
            }
            var offsetArray = offsets.ToArray();

            Array.Sort(offsetArray);

            return(ParseDirectoryRecord(root, rootOffset, offsetArray));
        }
Exemple #12
0
        private void SetOffsets(DicomDirectoryRecord record)
        {
            if (record.NextDirectoryRecord != null)
            {
                record.Add <uint>(DicomTag.OffsetOfTheNextDirectoryRecord, record.NextDirectoryRecord.Offset);
                SetOffsets(record.NextDirectoryRecord);
            }
            else
            {
                record.Add <uint>(DicomTag.OffsetOfTheNextDirectoryRecord, 0);
            }

            if (record.LowerLevelDirectoryRecord != null)
            {
                record.Add <uint>(DicomTag.OffsetOfReferencedLowerLevelDirectoryEntity, record.LowerLevelDirectoryRecord.Offset);
                SetOffsets(record.LowerLevelDirectoryRecord);
            }
            else
            {
                record.Add <uint>(DicomTag.OffsetOfReferencedLowerLevelDirectoryEntity, 0);
            }
        }
Exemple #13
0
        private DicomDirectoryRecord CreateSeriesRecord(DicomDataset dataset, DicomDirectoryRecord studyRecord)
        {
            var currentSeries     = studyRecord.LowerLevelDirectoryRecord;
            var seriesInstanceUid = dataset.Get <string>(DicomTag.SeriesInstanceUID);


            while (currentSeries != null)
            {
                if (currentSeries.Get <string>(DicomTag.SeriesInstanceUID) == seriesInstanceUid)
                {
                    return(currentSeries);
                }

                if (currentSeries.NextDirectoryRecord != null)
                {
                    currentSeries = currentSeries.NextDirectoryRecord;
                }
                else
                {
                    //no more patient records, break the loop
                    break;
                }
            }

            var newSeries = CreateRecordSequenceItem(DicomDirectoryRecordType.Series, dataset);

            if (currentSeries != null)
            {
                //series not found under study record
                currentSeries.NextDirectoryRecord = newSeries;
            }
            else
            {
                //no series record found under study record
                studyRecord.LowerLevelDirectoryRecord = newSeries;
            }
            return(newSeries);
        }
Exemple #14
0
        private DicomDirectoryRecord CreateStudyRecord(DicomDataset dataset, DicomDirectoryRecord patientRecord)
        {
            var currentStudy     = patientRecord.LowerLevelDirectoryRecord;
            var studyInstanceUid = dataset.Get <string>(DicomTag.StudyInstanceUID);


            while (currentStudy != null)
            {
                if (currentStudy.Get <string>(DicomTag.StudyInstanceUID) == studyInstanceUid)
                {
                    return(currentStudy);
                }

                if (currentStudy.NextDirectoryRecord != null)
                {
                    currentStudy = currentStudy.NextDirectoryRecord;
                }
                else
                {
                    //no more patient records, break the loop
                    break;
                }
            }
            var newStudy = CreateRecordSequenceItem(DicomDirectoryRecordType.Study, dataset);

            if (currentStudy != null)
            {
                //study not found under patient record
                currentStudy.NextDirectoryRecord = newStudy;
            }
            else
            {
                //no studies record found under patient record
                patientRecord.LowerLevelDirectoryRecord = newStudy;
            }
            return(newStudy);
        }
Exemple #15
0
        private DicomDirectoryRecord CreateRecordSequenceItem(DicomDirectoryRecordType recordType, DicomDataset dataset)
        {
            if (recordType == null)
            {
                throw new ArgumentNullException("recordType");
            }
            if (dataset == null)
            {
                throw new ArgumentNullException("dataset");
            }

            var sequenceItem = new DicomDirectoryRecord();

            //add record item attributes
            sequenceItem.Add <uint>(DicomTag.OffsetOfTheNextDirectoryRecord, 0);
            sequenceItem.Add <ushort>(DicomTag.RecordInUseFlag, 0xFFFF);
            sequenceItem.Add <uint>(DicomTag.OffsetOfReferencedLowerLevelDirectoryEntity, 0);
            sequenceItem.Add <string>(DicomTag.DirectoryRecordType, recordType.ToString());

            //copy the current dataset character set
            sequenceItem.Add(dataset.FirstOrDefault(d => d.Tag == DicomTag.SpecificCharacterSet));

            foreach (var tag in recordType.Tags)
            {
                if (dataset.Contains(tag))
                {
                    sequenceItem.Add(dataset.Get <DicomItem>(tag));
                }
                else
                {
                    System.Diagnostics.Debug.WriteLine("Cannot find tag {0} for record type {1}", tag, recordType);
                }
            }

            return(sequenceItem);
        }
Exemple #16
0
		private DicomDirectoryRecord CreateRecordSequenceItem(DicomDirectoryRecordType recordType, DicomDataset dataset) {
			if (recordType == null)
				throw new ArgumentNullException("recordType");
			if (dataset == null)
				throw new ArgumentNullException("dataset");

			var sequenceItem = new DicomDirectoryRecord();

			//add record item attributes
			sequenceItem.Add<uint>(DicomTag.OffsetOfTheNextDirectoryRecord, 0);
			sequenceItem.Add<ushort>(DicomTag.RecordInUseFlag, 0xFFFF);
			sequenceItem.Add<uint>(DicomTag.OffsetOfReferencedLowerLevelDirectoryEntity, 0);
			sequenceItem.Add<string>(DicomTag.DirectoryRecordType, recordType.ToString());

			//copy the current dataset character set
			sequenceItem.Add(dataset.FirstOrDefault(d => d.Tag == DicomTag.SpecificCharacterSet));

			foreach (var tag in recordType.Tags) {
				if (dataset.Contains(tag)) {
					sequenceItem.Add(dataset.Get<DicomItem>(tag));
				} else {
					System.Diagnostics.Debug.WriteLine("Cannot find tag {0} for record type {1}", tag, recordType);
				}
			}

			return sequenceItem;
		}
Exemple #17
0
		private DicomDirectoryRecord CreateStudyRecord(DicomDataset dataset, DicomDirectoryRecord patientRecord) {
			var currentStudy = patientRecord.LowerLevelDirectoryRecord;
			var studyInstanceUid = dataset.Get<string>(DicomTag.StudyInstanceUID);


			while (currentStudy != null) {
				if (currentStudy.Get<string>(DicomTag.StudyInstanceUID) == studyInstanceUid) {
					return currentStudy;
				}

				if (currentStudy.NextDirectoryRecord != null) {
					currentStudy = currentStudy.NextDirectoryRecord;
				} else {
					//no more patient records, break the loop
					break;
				}
			}
			var newStudy = CreateRecordSequenceItem(DicomDirectoryRecordType.Study, dataset);
			if (currentStudy != null) {
				//study not found under patient record
				currentStudy.NextDirectoryRecord = newStudy;
			} else {
				//no studies record found under patient record
				patientRecord.LowerLevelDirectoryRecord = newStudy;
			}
			return newStudy;
		}
Exemple #18
0
		private DicomDirectoryRecord CreateSeriesRecord(DicomDataset dataset, DicomDirectoryRecord studyRecord) {
			var currentSeries = studyRecord.LowerLevelDirectoryRecord;
			var seriesInstanceUid = dataset.Get<string>(DicomTag.SeriesInstanceUID);


			while (currentSeries != null) {
				if (currentSeries.Get<string>(DicomTag.SeriesInstanceUID) == seriesInstanceUid) {
					return currentSeries;
				}

				if (currentSeries.NextDirectoryRecord != null) {
					currentSeries = currentSeries.NextDirectoryRecord;
				} else {
					//no more patient records, break the loop
					break;
				}
			}

			var newSeries = CreateRecordSequenceItem(DicomDirectoryRecordType.Series, dataset);
			if (currentSeries != null) {
				//series not found under study record
				currentSeries.NextDirectoryRecord = newSeries;
			} else {
				//no series record found under study record
				studyRecord.LowerLevelDirectoryRecord = newSeries;
			}
			return newSeries;
		}
Exemple #19
0
		private void CreateImageRecord(DicomFileMetaInformation metaFileInfo, DicomDataset dataset, DicomDirectoryRecord seriesRecord, string referencedFileId) {
			var currentImage = seriesRecord.LowerLevelDirectoryRecord;
			var imageInstanceUid = dataset.Get<string>(DicomTag.SOPInstanceUID);


			while (currentImage != null) {
				if (currentImage.Get<string>(DicomTag.ReferencedSOPInstanceUIDInFile) == imageInstanceUid) {
					return;
				}

				if (currentImage.NextDirectoryRecord != null) {
					currentImage = currentImage.NextDirectoryRecord;
				} else {
					//no more patient records, break the loop
					break;
				}
			}
			var newImage = CreateRecordSequenceItem(DicomDirectoryRecordType.Image, dataset);
			newImage.Add(DicomTag.ReferencedFileID, referencedFileId);
			newImage.Add(DicomTag.ReferencedSOPClassUIDInFile, metaFileInfo.MediaStorageSOPClassUID.UID);
			newImage.Add(DicomTag.ReferencedSOPInstanceUIDInFile, metaFileInfo.MediaStorageSOPInstanceUID.UID);
			newImage.Add(DicomTag.ReferencedTransferSyntaxUIDInFile, metaFileInfo.TransferSyntax.UID);

			if (currentImage != null) {
				//study not found under patient record
				currentImage.NextDirectoryRecord = newImage;
			} else {
				//no studies record found under patient record
				seriesRecord.LowerLevelDirectoryRecord = newImage;
			}
		}
Exemple #20
0
		private void SetOffsets(DicomDirectoryRecord record) {
			if (record.NextDirectoryRecord != null) {
				record.Add<uint>(DicomTag.OffsetOfTheNextDirectoryRecord, record.NextDirectoryRecord.Offset);
				SetOffsets(record.NextDirectoryRecord);
			} else {
				record.Add<uint>(DicomTag.OffsetOfTheNextDirectoryRecord, 0);
			}

			if (record.LowerLevelDirectoryRecord != null) {
				record.Add<uint>(DicomTag.OffsetOfReferencedLowerLevelDirectoryEntity, record.LowerLevelDirectoryRecord.Offset);
				SetOffsets(record.LowerLevelDirectoryRecord);
			} else {
				record.Add<uint>(DicomTag.OffsetOfReferencedLowerLevelDirectoryEntity, 0);
			}
		}
Exemple #21
0
		private void AddDirectoryRecordsToSequenceItem(DicomDirectoryRecord recordItem) {
			if (recordItem == null)
				return;

			_directoryRecordSequence.Items.Add(recordItem);
			if (recordItem.LowerLevelDirectoryRecord != null)
				AddDirectoryRecordsToSequenceItem(recordItem.LowerLevelDirectoryRecord);

			if (recordItem.NextDirectoryRecord != null)
				AddDirectoryRecordsToSequenceItem(recordItem.NextDirectoryRecord);
		}