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); }
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; }
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); }
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); }
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); }
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; } }
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)); }
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); } }
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); }
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); }
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); }
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; }
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; }
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; }
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; } }
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); } }
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); }