private static DicomDirectory FinalizeDicomDirectoryLoad( DicomDirectory df, DicomFileReader reader, DicomDirectoryReaderObserver dirObserver, DicomReaderResult result) { 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; df._directoryRecordSequence = df.Dataset.Get <DicomSequence>(DicomTag.DirectoryRecordSequence); df.RootDirectoryRecord = dirObserver.BuildDirectoryRecords(); return(df); }
private async Task <bool> ParseItemSequenceValueAsync(IByteSource source) { if (this.parseStage == ParseStage.Value) { if (this.length != UndefinedLength) { if (!source.Require(this.length)) { this.result = DicomReaderResult.Suspended; return(false); } source.PushMilestone(this.length); } this.observer.OnBeginSequenceItem(source, this.length); this.ResetState(); await this.ParseDatasetAsync(source).ConfigureAwait(false); this.ResetState(); this.observer.OnEndSequenceItem(); } return(true); }
private bool ParseItemSequenceTag(IByteSource source) { if (this.parseStage == ParseStage.Tag) { source.Mark(); if (!source.Require(8)) { this.result = DicomReaderResult.Suspended; return(false); } var group = source.GetUInt16(); var element = source.GetUInt16(); this._tag = new DicomTag(@group, element); if (this._tag != DicomTag.Item && this._tag != DicomTag.SequenceDelimitationItem) { // assume invalid sequence source.Rewind(); if (!this._implicit) { source.PopMilestone(); } this.observer.OnEndSequence(); if (this.badPrivateSequence) { this.isExplicitVR = !this.isExplicitVR; this.badPrivateSequence = false; } return(false); } this.length = source.GetUInt32(); if (this._tag == DicomTag.SequenceDelimitationItem) { // #64, in case explicit length has been specified despite occurrence of Sequence Delimitation Item if (source.HasReachedMilestone() && source.MilestonesCount > this.sequenceDepth) { this.ResetState(); return(true); } // end of sequence this.observer.OnEndSequence(); if (this.badPrivateSequence) { this.isExplicitVR = !this.isExplicitVR; this.badPrivateSequence = false; } this.ResetState(); return(false); } this.parseStage = ParseStage.Value; } return(true); }
private bool ParseItemSequenceValue(IByteSource source) { if (this.parseStage == ParseStage.Value) { if (this.length != UndefinedLength) { if (!source.Require(this.length)) { this.result = DicomReaderResult.Suspended; return(false); } source.PushMilestone(this.length); } this.observer.OnBeginSequenceItem(source, this.length); this.ResetState(); ++this.sequenceDepth; this.ParseDataset(source); --this.sequenceDepth; this.ResetState(); this.observer.OnEndSequenceItem(); } return(true); }
private void OnFileMetaInfoParseComplete(IAsyncResult result) { try { if (_reader.EndRead(result) != DicomReaderResult.Stopped) { throw new DicomReaderException("DICOM File Meta Info ended prematurely"); } // rewind to last marker (start of previous tag)... ugly because // it requires knowledge of how the parser is implemented _source.Rewind(); _source.Endian = _syntax.Endian; _reader.IsExplicitVR = _syntax.IsExplicitVR; _reader.BeginRead(_source, _dataObserver, null, OnDatasetParseComplete, null); } catch (Exception e) { if (_exception == null) { _exception = e; } _result = DicomReaderResult.Error; } finally { if (_result == DicomReaderResult.Error) { _async.Set(); } } }
public IAsyncResult BeginRead(IByteSource source, IDicomReaderObserver observer, DicomTag stop, AsyncCallback callback, object state) { _stop = stop; _observer = observer; _result = DicomReaderResult.Processing; _exception = null; _async = new EventAsyncResult(callback, state); ThreadPool.QueueUserWorkItem(ParseProc, source); return _async; }
public IAsyncResult BeginRead(IByteSource source, IDicomReaderObserver fileMetaInfo, IDicomReaderObserver dataset, AsyncCallback callback, object state) { _result = DicomReaderResult.Processing; _source = source; _fmiObserver = fileMetaInfo; _dataObserver = dataset; _async = new EventAsyncResult(callback, state); ParsePreamble(source, null); // ThreadPool? return _async; }
public IAsyncResult BeginRead(IByteSource source, IDicomReaderObserver fileMetaInfo, IDicomReaderObserver dataset, AsyncCallback callback, object state) { _result = DicomReaderResult.Processing; _source = source; _fmiObserver = fileMetaInfo; _dataObserver = dataset; _async = new EventAsyncResult(callback, state); ParsePreamble(source, null); // ThreadPool? return(_async); }
public IAsyncResult BeginRead(IByteSource source, IDicomReaderObserver observer, DicomTag stop, AsyncCallback callback, object state) { _stop = stop; _observer = observer; _result = DicomReaderResult.Processing; _exception = null; _async = new EventAsyncResult(callback, state); ThreadPool.QueueUserWorkItem(ParseProc, source); return(_async); }
private bool ParseTag(IByteSource source) { if (_parseStage == ParseStage.Tag) { source.Mark(); if (!source.Require(4)) { _result = DicomReaderResult.Suspended; return(false); } var group = source.GetUInt16(); var element = source.GetUInt16(); DicomPrivateCreator creator = null; // according to // http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_7.8.html // The requirements of this section do not allow any use of elements in the ranges // (gggg,0001-000F) and (gggg,0100-0FFF) where gggg is odd. // So element at [0x0100-0x0FFF] should not has a creator if (@group.IsOdd() && element >= 0x1000) { var card = (uint)(@group << 16) + (uint)(element >> 8); lock (_locker) { if (_private.TryGetValue(card, out string pvt)) { creator = _dictionary.GetPrivateCreator(pvt); } } } _tag = new DicomTag(@group, element, creator); _entry = _dictionary[_tag]; if (!_tag.IsPrivate && _entry != null && _entry.MaskTag == null) { _tag = _entry.Tag; // Use dictionary tag } if (_stop != null && _stop(new ParseState { Tag = _tag, SequenceDepth = _sequenceDepth })) { _result = DicomReaderResult.Stopped; return(false); } _parseStage = ParseStage.VR; } return(true); }
private void OnDatasetParseComplete(IAsyncResult result) { try { _result = _reader.EndRead(result); } catch (Exception e) { if (_exception == null) _exception = e; _result = DicomReaderResult.Error; } finally { _async.Set(); } }
/// <summary> /// Throw if reading the file resulted in an error. /// </summary> /// <exception cref="DicomFileException">If the file could not be read properly.</exception> protected static void HandleOpenError(DicomFile dicomFile, DicomReaderResult result) { switch (result) { case DicomReaderResult.Processing: throw new DicomFileException(dicomFile, $"Failed to parse {dicomFile} - probably not a valid DICOM file"); case DicomReaderResult.Error: throw new DicomFileException(dicomFile, $"Not a valid DICOM file: {dicomFile}"); } }
/// <summary> /// Asynchronously read the byte source. /// </summary> /// <param name="source">Byte source to read.</param> /// <returns>Awaitable read result.</returns> internal async Task <DicomReaderResult> DoWorkAsync(IByteSource source) { ResetState(); source = ConvertSource(source); await ParseDatasetAsync(source).ConfigureAwait(false); if (_tag == DicomTag.SequenceDelimitationItem && _result == DicomReaderResult.Processing && source.IsEOF) { _result = DicomReaderResult.Success; } return(_result); }
/// <summary> /// Read the byte source. /// </summary> /// <param name="source">Byte source to read.</param> /// <returns>Read result.</returns> internal DicomReaderResult DoWork(IByteSource source) { ResetState(); source = ConvertSource(source); ParseDataset(source); if (_tag == DicomTag.SequenceDelimitationItem && _result == DicomReaderResult.Processing && source.IsEOF) { _result = DicomReaderResult.Success; } return(_result); }
public void EndRead_ValidSource_ReturnsSuccess() { using (var stream = File.OpenRead(@".\Test Data\CT1_J2KI")) { var source = new StreamByteSource(stream); var reader = new DicomFileReader(); const DicomReaderResult expected = DicomReaderResult.Success; var actual = reader.EndRead( reader.BeginRead(source, new MockObserver(), new MockObserver(), null, null)); Assert.Equal(expected, actual); } }
private bool ParseTag(IByteSource source) { if (this.parseStage == ParseStage.Tag) { source.Mark(); if (!source.Require(4)) { this.result = DicomReaderResult.Suspended; return(false); } var group = source.GetUInt16(); var element = source.GetUInt16(); DicomPrivateCreator creator = null; if (@group.IsOdd() && element > 0x00ff) { var card = (uint)(@group << 16) + (uint)(element >> 8); lock (this.locker) { string pvt; if (this._private.TryGetValue(card, out pvt)) { creator = this.dictionary.GetPrivateCreator(pvt); } } } this._tag = new DicomTag(@group, element, creator); this._entry = this.dictionary[this._tag]; if (!this._tag.IsPrivate && this._entry != null && this._entry.MaskTag == null) { this._tag = this._entry.Tag; // Use dictionary tag } if (this.stop != null && this.stop(new ParseState { Tag = this._tag, SequenceDepth = this.sequenceDepth })) { this.result = DicomReaderResult.Stopped; return(false); } this.parseStage = ParseStage.VR; } return(true); }
private void OnDatasetParseComplete(IAsyncResult result) { try { _result = _reader.EndRead(result); } catch (Exception e) { if (_exception == null) { _exception = e; } _result = DicomReaderResult.Error; } finally { _async.Set(); } }
private void ParseDataset(IByteSource source) { if (this.isDeflated) { #if NET35 throw new NotSupportedException("Deflated datasets not supported in Unity."); #else source = this.Decompress(source); #endif } this.result = DicomReaderResult.Processing; while (!source.IsEOF && !source.HasReachedMilestone() && this.result == DicomReaderResult.Processing) { if (!this.ParseTag(source)) { return; } if (!this.ParseVR(source)) { return; } if (!this.ParseLength(source)) { return; } if (!this.ParseValue(source)) { return; } } if (source.HasReachedMilestone()) { // end of explicit length sequence item source.PopMilestone(); return; } if (this.result != DicomReaderResult.Processing) { return; } // end of processing this.result = DicomReaderResult.Success; }
private async Task ParseFragmentSequenceAsync(IByteSource source) { _result = DicomReaderResult.Processing; while (!source.IsEOF) { if (!ParseFragmentSequenceTag(source)) { return; } if (!await ParseFragmentSequenceValueAsync(source).ConfigureAwait(false)) { return; } } }
private void ParseFragmentSequence(IByteSource source) { _result = DicomReaderResult.Processing; while (!source.IsEOF) { if (!ParseFragmentSequenceTag(source)) { return; } if (!ParseFragmentSequenceValue(source)) { return; } } }
private async Task <bool> ParseItemSequenceValueAsync(IByteSource source) { if (_parseStage == ParseStage.Value) { if (_length != _undefinedLength) { if (!source.Require(_length)) { _result = DicomReaderResult.Suspended; return(false); } source.PushMilestone(_length); } _observer.OnBeginSequenceItem(source, _length); ResetState(); ++_sequenceDepth; await ParseDatasetAsync(source).ConfigureAwait(false); --_sequenceDepth; // bugfix k-pacs. there a sequence was not ended by ItemDelimitationItem>SequenceDelimitationItem, but directly with SequenceDelimitationItem bool isEndSequence = (_tag == DicomTag.SequenceDelimitationItem); ResetState(); _observer.OnEndSequenceItem(); if (isEndSequence) { // end of sequence _observer.OnEndSequence(); // #565 Only reset the badPrivate sequence if we're in the correct depth // This prevents prematurely resetting in case of sub-sequences contained in the bad private sequence if (_badPrivateSequence && _sequenceDepth == _badPrivateSequenceDepth) { _isExplicitVR = !_isExplicitVR; _badPrivateSequence = false; } ResetState(); return(false); } } return(true); }
private async Task ParseItemSequenceAsync(IByteSource source) { _result = DicomReaderResult.Processing; while (!source.IsEOF && !source.HasReachedMilestone()) { if (!ParseItemSequenceTag(source)) { return; } if (!await ParseItemSequenceValueAsync(source).ConfigureAwait(false)) { return; } } ParseItemSequencePostProcess(source); }
private void ParseItemSequence(IByteSource source) { _result = DicomReaderResult.Processing; while (!source.IsEOF && !source.HasReachedMilestone()) { if (!ParseItemSequenceTag(source)) { return; } if (!ParseItemSequenceValue(source)) { return; } } ParseItemSequencePostProcess(source); }
private bool ParseFragmentSequenceValue(IByteSource source) { if (_parseStage == ParseStage.Value) { if (!source.Require(_length)) { _result = DicomReaderResult.Suspended; return(false); } var buffer = source.GetBuffer(_length); buffer = EndianByteBuffer.Create(buffer, source.Endian, _fragmentItem == 1 ? 4 : _vr.UnitSize); _observer.OnFragmentSequenceItem(source, buffer); _parseStage = ParseStage.Tag; } return(true); }
private async Task ParseDatasetAsync(IByteSource source) { if (this.isDeflated) { source = this.Decompress(source); } this.result = DicomReaderResult.Processing; while (!source.IsEOF && !source.HasReachedMilestone() && this.result == DicomReaderResult.Processing) { if (!this.ParseTag(source)) { return; } if (!this.ParseVR(source)) { return; } if (!this.ParseLength(source)) { return; } if (!await this.ParseValueAsync(source).ConfigureAwait(false)) { return; } } if (source.HasReachedMilestone()) { // end of explicit length sequence item source.PopMilestone(); return; } if (this.result != DicomReaderResult.Processing) { return; } // end of processing this.result = DicomReaderResult.Success; }
private bool ParseItemSequenceValue(IByteSource source) { if (this.parseStage == ParseStage.Value) { if (this.length != UndefinedLength) { if (!source.Require(this.length)) { this.result = DicomReaderResult.Suspended; return(false); } source.PushMilestone(this.length); } this.observer.OnBeginSequenceItem(source, this.length); this.ResetState(); ++this.sequenceDepth; this.ParseDataset(source); --this.sequenceDepth; // bugfix k-pacs. there a sequence was not ended by ItemDelimitationItem>SequenceDelimitationItem, but directly with SequenceDelimitationItem bool isEndSequence = (this._tag == DicomTag.SequenceDelimitationItem); this.ResetState(); this.observer.OnEndSequenceItem(); if (isEndSequence) { // end of sequence this.observer.OnEndSequence(); // #565 Only reset the badPrivate sequence if we're in the correct depth // This prevents prematurely resetting in case of sub-sequences contained in the bad private sequence if (this.badPrivateSequence && this.sequenceDepth == this.badPrivateSequenceDepth) { this.isExplicitVR = !this.isExplicitVR; this.badPrivateSequence = false; } this.ResetState(); return(false); } } return(true); }
private void ParseDataset(IByteSource source) { if (_isDeflated) { source = Decompress(source); } _result = DicomReaderResult.Processing; while (!source.IsEOF && !source.HasReachedMilestone() && _result == DicomReaderResult.Processing) { if (!ParseTag(source)) { return; } if (!ParseVR(source)) { return; } if (!ParseLength(source)) { return; } if (!ParseValue(source)) { return; } } if (source.HasReachedMilestone()) { // end of explicit length sequence item source.PopMilestone(); return; } if (_result != DicomReaderResult.Processing) { return; } // end of processing _result = DicomReaderResult.Success; }
private async Task <bool> ParseFragmentSequenceValueAsync(IByteSource source) { if (this.parseStage == ParseStage.Value) { if (!source.Require(this.length)) { this.result = DicomReaderResult.Suspended; return(false); } var buffer = await source.GetBufferAsync(this.length).ConfigureAwait(false); buffer = EndianByteBuffer.Create(buffer, source.Endian, this.fragmentItem == 1 ? 4 : this._vr.UnitSize); this.observer.OnFragmentSequenceItem(source, buffer); this.parseStage = ParseStage.Tag; } return(true); }
private async Task <bool> ParseItemSequenceValueAsync(IByteSource source) { if (this.parseStage == ParseStage.Value) { if (this.length != UndefinedLength) { if (!source.Require(this.length)) { this.result = DicomReaderResult.Suspended; return(false); } source.PushMilestone(this.length); } this.observer.OnBeginSequenceItem(source, this.length); this.ResetState(); ++this.sequenceDepth; await this.ParseDatasetAsync(source).ConfigureAwait(false); --this.sequenceDepth; // bugfix k-pacs. there a sequence was not ended by ItemDelimitationItem>SequenceDelimitationItem, but directly with SequenceDelimitationItem bool isEndSequence = (this._tag == DicomTag.SequenceDelimitationItem); this.ResetState(); this.observer.OnEndSequenceItem(); if (isEndSequence) { // end of sequence this.observer.OnEndSequence(); if (this.badPrivateSequence) { this.isExplicitVR = !this.isExplicitVR; this.badPrivateSequence = false; } this.ResetState(); return(false); } } return(true); }
private void ParsePreamble(IByteSource source, object state) { try { if (!source.Require(132, ParsePreamble, state)) { return; } _source.Skip(128); if (_source.GetUInt8() != 'D' || _source.GetUInt8() != 'I' || _source.GetUInt8() != 'C' || _source.GetUInt8() != 'M') { throw new DicomReaderException("Invalid preamble found in DICOM file parser"); } DicomReaderCallbackObserver obs = new DicomReaderCallbackObserver(); obs.Add(DicomTag.TransferSyntaxUID, delegate(object sender, DicomReaderEventArgs ea) { try { string uid = Encoding.ASCII.GetString(ea.Data.Data); _syntax = DicomTransferSyntax.Parse(uid); } catch { } }); _source.Endian = _syntax.Endian; _reader.IsExplicitVR = _syntax.IsExplicitVR; _reader.BeginRead(_source, new DicomReaderMultiObserver(obs, _fmiObserver), FileMetaInfoStopTag, OnFileMetaInfoParseComplete, null); } catch (Exception e) { if (_exception == null) { _exception = e; } _result = DicomReaderResult.Error; } finally { if (_result != DicomReaderResult.Processing && _result != DicomReaderResult.Suspended) { _async.Set(); } } }
public void Read_ValidSource_ReturnsSuccess() { using var stream = File.OpenRead(TestData.Resolve("CT1_J2KI")); var source = new StreamByteSource(stream); var reader = new DicomFileReader(); var fileMetaInfo = new DicomFileMetaInformation(); var dataset = new DicomDataset(); const DicomReaderResult expected = DicomReaderResult.Success; var actual = reader.Read( source, new DicomDatasetReaderObserver(fileMetaInfo), new DicomDatasetReaderObserver(dataset)); Assert.Equal(expected, actual); var modality = dataset.GetString(DicomTag.Modality); Assert.Equal("CT", modality); }
private bool ParseFragmentSequenceTag(IByteSource source) { if (_parseStage == ParseStage.Tag) { source.Mark(); if (!source.Require(8)) { _result = DicomReaderResult.Suspended; return(false); } var group = source.GetUInt16(); var element = source.GetUInt16(); var tag = new DicomTag(@group, element); if (tag != DicomTag.Item && tag != DicomTag.SequenceDelimitationItem) { throw new DicomReaderException($"Unexpected tag in DICOM fragment sequence: {tag}"); } _length = source.GetUInt32(); if (tag == DicomTag.SequenceDelimitationItem) { // end of fragment _observer.OnEndFragmentSequence(); _fragmentItem = 0; ResetState(); return(false); } _fragmentItem++; _parseStage = ParseStage.Value; } return(true); }
private void ParseDataset(IByteSource source) { if (this.isDeflated) { #if NET35 throw new NotSupportedException("Deflated datasets not supported in Unity."); #else source = this.Decompress(source); #endif } this.result = DicomReaderResult.Processing; while (!source.IsEOF && !source.HasReachedMilestone() && this.result == DicomReaderResult.Processing) { if (!this.ParseTag(source)) return; if (!this.ParseVR(source)) return; if (!this.ParseLength(source)) return; if (!this.ParseValue(source)) return; } if (source.HasReachedMilestone()) { // end of explicit length sequence item source.PopMilestone(); return; } if (this.result != DicomReaderResult.Processing) return; // end of processing this.result = DicomReaderResult.Success; }
private static DicomDirectory FinalizeDicomDirectoryLoad( DicomDirectory df, DicomFileReader reader, DicomDirectoryReaderObserver dirObserver, DicomReaderResult result) { 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; df._directoryRecordSequence = df.Dataset.Get<DicomSequence>(DicomTag.DirectoryRecordSequence); df.RootDirectoryRecord = dirObserver.BuildDirectoryRecords(); return df; }
private void ParsePreamble(IByteSource source, object state) { try { if (!source.Require(132, ParsePreamble, state)) return; _source.Skip(128); if (_source.GetUInt8() != 'D' || _source.GetUInt8() != 'I' || _source.GetUInt8() != 'C' || _source.GetUInt8() != 'M') throw new DicomReaderException("Invalid preamble found in DICOM file parser"); DicomReaderCallbackObserver obs = new DicomReaderCallbackObserver(); obs.Add(DicomTag.TransferSyntaxUID, delegate(object sender, DicomReaderEventArgs ea) { try { string uid = Encoding.ASCII.GetString(ea.Data.Data); _syntax = DicomTransferSyntax.Parse(uid); } catch { } }); _source.Endian = _syntax.Endian; _reader.IsExplicitVR = _syntax.IsExplicitVR; _reader.BeginRead(_source, new DicomReaderMultiObserver(obs, _fmiObserver), FileMetaInfoStopTag, OnFileMetaInfoParseComplete, null); } catch (Exception e) { if (_exception == null) _exception = e; _result = DicomReaderResult.Error; } finally { if (_result != DicomReaderResult.Processing && _result != DicomReaderResult.Suspended) { _async.Set(); } } }
private async Task<bool> ParseValueAsync(IByteSource source) { if (this.parseStage == ParseStage.Value) { // check dictionary for VR after reading length to handle 16-bit lengths // check before reading value to handle SQ elements var parsedVR = this._vr; // check dictionary for VR after reading length to handle 16-bit lengths // check before reading value to handle SQ elements if (this._vr == DicomVR.Implicit || (this._vr == DicomVR.UN && this.isExplicitVR)) { var entry = this.dictionary[this._tag]; if (entry != null) { this._vr = entry.ValueRepresentations.FirstOrDefault(); } if (this._vr == null) { this._vr = DicomVR.UN; } } if (this._tag == DicomTag.ItemDelimitationItem) { // end of sequence item return false; } while (this._vr == DicomVR.SQ && this._tag.IsPrivate) { if (!IsPrivateSequence(source)) { this._vr = DicomVR.UN; break; } if (IsPrivateSequenceBad(source, this.isExplicitVR)) { this.badPrivateSequence = true; this.isExplicitVR = !this.isExplicitVR; } break; } if (this._vr == DicomVR.SQ) { // start of sequence this.observer.OnBeginSequence(source, this._tag, this.length); this.parseStage = ParseStage.Tag; if (this.length != UndefinedLength) { this._implicit = false; source.PushMilestone(this.length); } else { this._implicit = true; } var last = source.Position; // Conformance with CP-246 (#177) var needtoChangeEndian = false; if (parsedVR == DicomVR.UN && !this._tag.IsPrivate) { this._implicit = true; needtoChangeEndian = source.Endian == Endian.Big; } if (needtoChangeEndian) { source.Endian = Endian.Little; } await this.ParseItemSequenceAsync(source).ConfigureAwait(false); if (needtoChangeEndian) { source.Endian = Endian.Big; } // Aeric Sylvan - https://github.com/rcd/fo-dicom/issues/62#issuecomment-46248073 // Fix reading of SQ with parsed VR of UN if (source.Position > last || this.length == 0) { return true; } this.parseStage = ParseStage.Value; this._vr = parsedVR; } if (this.length == UndefinedLength) { this.observer.OnBeginFragmentSequence(source, this._tag, this._vr); this.parseStage = ParseStage.Tag; await this.ParseFragmentSequenceAsync(source).ConfigureAwait(false); return true; } if (!source.Require(this.length)) { this.result = DicomReaderResult.Suspended; return false; } var buffer = await source.GetBufferAsync(this.length).ConfigureAwait(false); if (!this._vr.IsString) { buffer = EndianByteBuffer.Create(buffer, source.Endian, this._vr.UnitSize); } this.observer.OnElement(source, this._tag, this._vr, buffer); // parse private creator value and add to lookup table if (this._tag.IsPrivate && this._tag.Element != 0x0000 && this._tag.Element <= 0x00ff) { var creator = DicomEncoding.Default.GetString(buffer.Data, 0, buffer.Data.Length) .TrimEnd((char)DicomVR.LO.PaddingValue); var card = (uint)(this._tag.Group << 16) + this._tag.Element; lock (this.locker) { this._private[card] = creator; } } this.ResetState(); } return true; }
private async Task<bool> ParseFragmentSequenceValueAsync(IByteSource source) { if (this.parseStage == ParseStage.Value) { if (!source.Require(this.length)) { this.result = DicomReaderResult.Suspended; return false; } var buffer = await source.GetBufferAsync(this.length).ConfigureAwait(false); buffer = EndianByteBuffer.Create(buffer, source.Endian, this.fragmentItem == 1 ? 4 : this._vr.UnitSize); this.observer.OnFragmentSequenceItem(source, buffer); this.parseStage = ParseStage.Tag; } return true; }
private void ParsePreamble(IByteSource source, object state) { try { if (!source.Require(132, ParsePreamble, state)) return; // mark file origin _source.Mark(); // test for DICM preamble _source.Skip(128); if (_source.GetUInt8() == 'D' && _source.GetUInt8() == 'I' && _source.GetUInt8() == 'C' && _source.GetUInt8() == 'M') _fileFormat = DicomFileFormat.DICOM3; // test for incorrect syntax in file meta info do { if (_fileFormat == DicomFileFormat.DICOM3) { // move milestone to after preamble _source.Mark(); } else { // rewind to origin milestone _source.Rewind(); } // test for file meta info var group = _source.GetUInt16(); if (group > 0x00ff) { _source.Endian = Endian.Big; _syntax = DicomTransferSyntax.ExplicitVRBigEndian; group = Endian.Swap(group); } if (group > 0x00ff) { // invalid starting tag _fileFormat = DicomFileFormat.Unknown; _source.Rewind(); break; } if (_fileFormat == DicomFileFormat.Unknown) { if (group == 0x0002) _fileFormat = DicomFileFormat.DICOM3NoPreamble; else _fileFormat = DicomFileFormat.DICOM3NoFileMetaInfo; } var element = _source.GetUInt16(); var tag = new DicomTag(group, element); // test for explicit VR var vrt = Encoding.UTF8.GetBytes(tag.DictionaryEntry.ValueRepresentations[0].Code); var vrs = _source.GetBytes(2); if (vrt[0] != vrs[0] || vrt[1] != vrs[1]) { // implicit VR if (_syntax.Endian == Endian.Little) _syntax = DicomTransferSyntax.ImplicitVRLittleEndian; else _syntax = DicomTransferSyntax.ImplicitVRBigEndian; } _source.Rewind(); } while (_fileFormat == DicomFileFormat.Unknown); if (_fileFormat == DicomFileFormat.Unknown) throw new DicomReaderException("Attempted to read invalid DICOM file"); var obs = new DicomReaderCallbackObserver(); if (_fileFormat != DicomFileFormat.DICOM3) { obs.Add(DicomTag.RecognitionCodeRETIRED, (object sender, DicomReaderEventArgs ea) => { try { string code = Encoding.UTF8.GetString(ea.Data.Data, 0, ea.Data.Data.Length); if (code == "ACR-NEMA 1.0") _fileFormat = DicomFileFormat.ACRNEMA1; else if (code == "ACR-NEMA 2.0") _fileFormat = DicomFileFormat.ACRNEMA2; } catch { } }); } obs.Add(DicomTag.TransferSyntaxUID, (object sender, DicomReaderEventArgs ea) => { try { string uid = Encoding.UTF8.GetString(ea.Data.Data, 0, ea.Data.Data.Length); _syntax = DicomTransferSyntax.Parse(uid); } catch { } }); _source.Endian = _syntax.Endian; _reader.IsExplicitVR = _syntax.IsExplicitVR; if (_fileFormat == DicomFileFormat.DICOM3NoFileMetaInfo) _reader.BeginRead(_source, new DicomReaderMultiObserver(obs, _dataObserver), null, OnDatasetParseComplete, null); else _reader.BeginRead(_source, new DicomReaderMultiObserver(obs, _fmiObserver), FileMetaInfoStopTag, OnFileMetaInfoParseComplete, null); } catch (Exception e) { if (_exception == null) _exception = e; _result = DicomReaderResult.Error; } finally { if (_result != DicomReaderResult.Processing && _result != DicomReaderResult.Suspended) { _async.Set(); } } }
private async Task ParseFragmentSequenceAsync(IByteSource source) { this.result = DicomReaderResult.Processing; while (!source.IsEOF) { if (!this.ParseFragmentSequenceTag(source)) return; if (!await this.ParseFragmentSequenceValueAsync(source).ConfigureAwait(false)) return; } }
private void autoCheckTransferSyntax(IByteSource source, ushort group, ushort element, object state) { //start checking Transfer Syntax after reading premable bytes if (group > 0x0002 && !bAutoDetectVRType) { bAutoDetectVRType = true;//just check once source.Mark();//mark the original position of pointer //try to parse VR uint tmpLength = 0; source.Skip(2); if (!source.Require(2, ParseDataset, state)) { _result = DicomReaderResult.Suspended; source.Rewind(); return; } tmpLength = source.GetUInt16(); try { if (!source.Require(tmpLength, ParseDataset, state)) { _result = DicomReaderResult.Suspended; source.Rewind(); return; } source.Skip((int)tmpLength); if (!source.Require(4, ParseDataset, state)) { _result = DicomReaderResult.Suspended; source.Rewind(); return; } ushort group2 = source.GetUInt16(); ushort element2 = source.GetUInt16(); DicomPrivateCreator creator2 = null; if (group2.IsOdd() && element2 > 0x00ff) { string pvt2 = null; uint card2 = (uint)(group2 << 16) + (uint)(element2 >> 8); if (_private.TryGetValue(card2, out pvt2)) creator2 = Dictionary.GetPrivateCreator(pvt2); } var tmpTag = new DicomTag(group2, element2, creator2); var tmpEntry = Dictionary[tmpTag]; if (!tmpTag.IsPrivate && tmpEntry != null && tmpEntry.MaskTag == null) { tmpTag = tmpEntry.Tag; // Use dictionary tag IsExplicitVR = true; } else { IsExplicitVR = false; } source.Rewind(); } catch (Exception exin) { source.Rewind(); //说明有错误,直接抛出异常 throw new DicomIoException("Auto Check Transfer Syntax Exception by zssure,Details:{0}", exin.StackTrace); } } }
private void ParseItemSequence(IByteSource source, object state) { try { _result = DicomReaderResult.Processing; while (!source.IsEOF && !source.HasReachedMilestone()) { if (_state == ParseState.Tag) { source.Mark(); if (!source.Require(8, ParseItemSequence, state)) { _result = DicomReaderResult.Suspended; return; } ushort group = source.GetUInt16(); ushort element = source.GetUInt16(); _tag = new DicomTag(group, element); if (_tag != DicomTag.Item && _tag != DicomTag.SequenceDelimitationItem) { // assume invalid sequence source.Rewind(); if (!_implicit) source.PopMilestone(); _observer.OnEndSequence(); if (_badPrivateSequence) { _explicit = !_explicit; _badPrivateSequence = false; } return; } _length = source.GetUInt32(); if (_tag == DicomTag.SequenceDelimitationItem) { // end of sequence _observer.OnEndSequence(); if (_badPrivateSequence) { _explicit = !_explicit; _badPrivateSequence = false; } ResetState(); return; } _state = ParseState.Value; } if (_state == ParseState.Value) { if (_length != UndefinedLength) { if (!source.Require(_length, ParseItemSequence, state)) { _result = DicomReaderResult.Suspended; return; } source.PushMilestone(_length); } _observer.OnBeginSequenceItem(source, _length); ResetState(); ParseDataset(source, state); ResetState(); _observer.OnEndSequenceItem(); continue; } } // end of explicit length sequence if (source.HasReachedMilestone()) source.PopMilestone(); _observer.OnEndSequence(); if (_badPrivateSequence) { _explicit = !_explicit; _badPrivateSequence = false; } } catch (Exception e) { _exception = e; _result = DicomReaderResult.Error; } finally { if (_result != DicomReaderResult.Processing && _result != DicomReaderResult.Suspended) { _async.Set(); } } }
private bool ParseItemSequenceTag(IByteSource source) { if (this.parseStage == ParseStage.Tag) { source.Mark(); if (!source.Require(8)) { this.result = DicomReaderResult.Suspended; return false; } var group = source.GetUInt16(); var element = source.GetUInt16(); this._tag = new DicomTag(@group, element); if (this._tag != DicomTag.Item && this._tag != DicomTag.SequenceDelimitationItem) { // assume invalid sequence source.Rewind(); if (!this._implicit) { source.PopMilestone(); } this.observer.OnEndSequence(); if (this.badPrivateSequence) { this.isExplicitVR = !this.isExplicitVR; this.badPrivateSequence = false; } return false; } this.length = source.GetUInt32(); if (this._tag == DicomTag.SequenceDelimitationItem) { // #64, in case explicit length has been specified despite occurrence of Sequence Delimitation Item if (source.HasReachedMilestone() && source.MilestonesCount > this.sequenceDepth) { this.ResetState(); return true; } // end of sequence this.observer.OnEndSequence(); if (this.badPrivateSequence) { this.isExplicitVR = !this.isExplicitVR; this.badPrivateSequence = false; } this.ResetState(); return false; } this.parseStage = ParseStage.Value; } return true; }
private async Task ParseItemSequenceAsync(IByteSource source) { this.result = DicomReaderResult.Processing; while (!source.IsEOF && !source.HasReachedMilestone()) { if (!this.ParseItemSequenceTag(source)) return; if (!await this.ParseItemSequenceValueAsync(source).ConfigureAwait(false)) return; } this.ParseItemSequencePostProcess(source); }
private void ParseItemSequence(IByteSource source) { this.result = DicomReaderResult.Processing; while (!source.IsEOF && !source.HasReachedMilestone()) { if (!this.ParseItemSequenceTag(source)) return; if (!this.ParseItemSequenceValue(source)) return; } this.ParseItemSequencePostProcess(source); }
public ParseResult(DicomReaderResult result, DicomFileFormat format, DicomTransferSyntax syntax) { this.Result = result; this.Format = format; this.Syntax = syntax; }
private bool ParseFragmentSequenceTag(IByteSource source) { if (this.parseStage == ParseStage.Tag) { source.Mark(); if (!source.Require(8)) { this.result = DicomReaderResult.Suspended; return false; } var group = source.GetUInt16(); var element = source.GetUInt16(); DicomTag tag = new DicomTag(@group, element); if (tag != DicomTag.Item && tag != DicomTag.SequenceDelimitationItem) { throw new DicomReaderException("Unexpected tag in DICOM fragment sequence: {0}", tag); } this.length = source.GetUInt32(); if (tag == DicomTag.SequenceDelimitationItem) { // end of fragment this.observer.OnEndFragmentSequence(); this.fragmentItem = 0; this.ResetState(); return false; } this.fragmentItem++; this.parseStage = ParseStage.Value; } return true; }
private bool ParseItemSequenceValue(IByteSource source) { if (this.parseStage == ParseStage.Value) { if (this.length != UndefinedLength) { if (!source.Require(this.length)) { this.result = DicomReaderResult.Suspended; return false; } source.PushMilestone(this.length); } this.observer.OnBeginSequenceItem(source, this.length); this.ResetState(); ++this.sequenceDepth; this.ParseDataset(source); --this.sequenceDepth; this.ResetState(); this.observer.OnEndSequenceItem(); } return true; }
private bool ParseLength(IByteSource source) { while (this.parseStage == ParseStage.Length) { if (this._tag == DicomTag.Item || this._tag == DicomTag.ItemDelimitationItem || this._tag == DicomTag.SequenceDelimitationItem) { if (!source.Require(4)) { this.result = DicomReaderResult.Suspended; return false; } this.length = source.GetUInt32(); this.parseStage = ParseStage.Value; break; } if (this.isExplicitVR) { if (this._vr == DicomVR.Implicit) { if (!source.Require(4)) { this.result = DicomReaderResult.Suspended; return false; } this.length = source.GetUInt32(); // assume that undefined length in implicit VR element is SQ if (this.length == UndefinedLength) { this._vr = DicomVR.SQ; } } else if (this._vr.Is16bitLength) { if (!source.Require(2)) { this.result = DicomReaderResult.Suspended; return false; } this.length = source.GetUInt16(); } else { if (!source.Require(6)) { this.result = DicomReaderResult.Suspended; return false; } source.Skip(2); this.length = source.GetUInt32(); // CP-246 (#177) handling // assume that Undefined Length in explicit datasets with VR UN are sequences // According to CP-246 the sequence shall be handled as ILE, but this will be handled later... // in the current code this needs to be restricted to privates if (this.length == UndefinedLength && this._vr == DicomVR.UN && this._tag.IsPrivate) { this._vr = DicomVR.SQ; } } } else { if (!source.Require(4)) { this.result = DicomReaderResult.Suspended; return false; } this.length = source.GetUInt32(); // assume that undefined length in implicit dataset is SQ if (this.length == UndefinedLength && this._vr == DicomVR.UN) { this._vr = DicomVR.SQ; } } this.parseStage = ParseStage.Value; } return true; }
private async Task<bool> ParseItemSequenceValueAsync(IByteSource source) { if (this.parseStage == ParseStage.Value) { if (this.length != UndefinedLength) { if (!source.Require(this.length)) { this.result = DicomReaderResult.Suspended; return false; } source.PushMilestone(this.length); } this.observer.OnBeginSequenceItem(source, this.length); this.ResetState(); await this.ParseDatasetAsync(source).ConfigureAwait(false); this.ResetState(); this.observer.OnEndSequenceItem(); } return true; }
private void ParseFragmentSequence(IByteSource source) { this.result = DicomReaderResult.Processing; while (!source.IsEOF) { if (!this.ParseFragmentSequenceTag(source)) return; if (!this.ParseFragmentSequenceValue(source)) return; } }
private void ParseDataset(IByteSource source) { this.result = DicomReaderResult.Processing; while (!source.IsEOF && !source.HasReachedMilestone() && this.result == DicomReaderResult.Processing) { if (!this.ParseTag(source)) return; if (!this.ParseVR(source)) return; if (!this.ParseLength(source)) return; if (!this.ParseValue(source)) return; } if (source.HasReachedMilestone()) { // end of explicit length sequence item source.PopMilestone(); return; } if (this.result != DicomReaderResult.Processing) return; // end of processing this.result = DicomReaderResult.Success; }
private void OnFileMetaInfoParseComplete(IAsyncResult result) { try { if (_reader.EndRead(result) != DicomReaderResult.Stopped) throw new DicomReaderException("DICOM File Meta Info ended prematurely"); // rewind to last marker (start of previous tag)... ugly because // it requires knowledge of how the parser is implemented _source.Rewind(); _source.Endian = _syntax.Endian; _reader.IsExplicitVR = _syntax.IsExplicitVR; _reader.BeginRead(_source, _dataObserver, null, OnDatasetParseComplete, null); } catch (Exception e) { if (_exception == null) _exception = e; _result = DicomReaderResult.Error; } finally { if (_result == DicomReaderResult.Error) { _async.Set(); } } }
private void ParseFragmentSequence(IByteSource source, object state) { try { _result = DicomReaderResult.Processing; while (!source.IsEOF) { if (_state == ParseState.Tag) { source.Mark(); if (!source.Require(8, ParseFragmentSequence, state)) { _result = DicomReaderResult.Suspended; return; } ushort group = source.GetUInt16(); ushort element = source.GetUInt16(); DicomTag tag = new DicomTag(group, element); if (tag != DicomTag.Item && tag != DicomTag.SequenceDelimitationItem) throw new DicomReaderException("Unexpected tag in DICOM fragment sequence: {0}", tag); _length = source.GetUInt32(); if (tag == DicomTag.SequenceDelimitationItem) { // end of fragment _observer.OnEndFragmentSequence(); _fragmentItem = 0; ResetState(); ParseDataset(source, PopState()); return; } _fragmentItem++; _state = ParseState.Value; } if (_state == ParseState.Value) { if (!source.Require(_length, ParseFragmentSequence, state)) { _result = DicomReaderResult.Suspended; return; } IByteBuffer buffer = source.GetBuffer(_length); if (_fragmentItem == 1) buffer = EndianByteBuffer.Create(buffer, source.Endian, 4); else buffer = EndianByteBuffer.Create(buffer, source.Endian, _vr.UnitSize); _observer.OnFragmentSequenceItem(source, buffer); _state = ParseState.Tag; } } } catch (Exception e) { _exception = e; _result = DicomReaderResult.Error; } finally { if (_result != DicomReaderResult.Processing && _result != DicomReaderResult.Suspended) { _async.Set(); } } }
private async Task ParseDatasetAsync(IByteSource source) { this.result = DicomReaderResult.Processing; while (!source.IsEOF && !source.HasReachedMilestone() && this.result == DicomReaderResult.Processing) { if (!this.ParseTag(source)) return; if (!this.ParseVR(source)) return; if (!this.ParseLength(source)) return; if (!await this.ParseValueAsync(source).ConfigureAwait(false)) return; } if (source.HasReachedMilestone()) { // end of explicit length sequence item source.PopMilestone(); return; } if (this.result != DicomReaderResult.Processing) return; // end of processing this.result = DicomReaderResult.Success; }
private void ParseDataset(IByteSource source, object state) { try { _result = DicomReaderResult.Processing; while (!source.IsEOF && !source.HasReachedMilestone() && _result == DicomReaderResult.Processing) { if (_state == ParseState.Tag) { source.Mark(); if (!source.Require(4, ParseDataset, state)) { _result = DicomReaderResult.Suspended; return; } ushort group = source.GetUInt16(); ushort element = source.GetUInt16(); DicomPrivateCreator creator = null; if (group.IsOdd() && element > 0x00ff) { string pvt = null; uint card = (uint)(group << 16) + (uint)(element >> 8); if (_private.TryGetValue(card, out pvt)) creator = Dictionary.GetPrivateCreator(pvt); } _tag = new DicomTag(group, element, creator); if (_stop != null && _tag.CompareTo(_stop) >= 0) { _result = DicomReaderResult.Stopped; return; } _state = ParseState.VR; } while (_state == ParseState.VR) { if (_tag == DicomTag.Item || _tag == DicomTag.ItemDelimitationItem || _tag == DicomTag.SequenceDelimitationItem) { _vr = DicomVR.NONE; _state = ParseState.Length; break; } if (IsExplicitVR) { if (!source.Require(2, ParseDataset, state)) { _result = DicomReaderResult.Suspended; return; } byte[] bytes = source.GetBytes(2); string vr = Encoding.UTF8.GetString(bytes, 0, bytes.Length); try { _vr = DicomVR.Parse(vr); } catch { // unable to parse VR _vr = DicomVR.UN; } } else { DicomDictionaryEntry entry = Dictionary[_tag]; if (entry != null) { if (entry == DicomDictionary.UnknownTag) _vr = DicomVR.UN; else if (entry.ValueRepresentations.Contains(DicomVR.OB) && entry.ValueRepresentations.Contains(DicomVR.OW)) _vr = DicomVR.OW; // ??? else _vr = entry.ValueRepresentations.FirstOrDefault(); } } if (_vr == null) _vr = DicomVR.UN; _state = ParseState.Length; if (_vr == DicomVR.UN) { if (_tag.Element == 0x0000) { // Group Length to UL _vr = DicomVR.UL; break; } else if (IsExplicitVR) { break; } } if (_tag.IsPrivate) { if (_tag.Element != 0x0000 && _tag.Element <= 0x00ff && _vr == DicomVR.UN) _vr = DicomVR.LO; // force private creator to LO } } while (_state == ParseState.Length) { if (_tag == DicomTag.Item || _tag == DicomTag.ItemDelimitationItem || _tag == DicomTag.SequenceDelimitationItem) { if (!source.Require(4, ParseDataset, state)) { _result = DicomReaderResult.Suspended; return; } _length = source.GetUInt32(); _state = ParseState.Value; break; } if (IsExplicitVR) { if (_vr.Is16bitLength) { if (!source.Require(2, ParseDataset, state)) { _result = DicomReaderResult.Suspended; return; } _length = source.GetUInt16(); } else { if (!source.Require(6, ParseDataset, state)) { _result = DicomReaderResult.Suspended; return; } source.Skip(2); _length = source.GetUInt32(); } } else { if (!source.Require(4, ParseDataset, state)) { _result = DicomReaderResult.Suspended; return; } _length = source.GetUInt32(); // assume that undefined length in implicit dataset is SQ if (_length == UndefinedLength && _vr == DicomVR.UN) _vr = DicomVR.SQ; } _state = ParseState.Value; } if (_state == ParseState.Value) { // check dictionary for VR after reading length to handle 16-bit lengths // check before reading value to handle SQ elements if (_vr == DicomVR.UN && IsExplicitVR) { var entry = Dictionary[_tag]; if (entry != null) _vr = entry.ValueRepresentations.FirstOrDefault(); if (_vr == null) _vr = DicomVR.UN; } if (_tag == DicomTag.ItemDelimitationItem) { // end of sequence item return; } while (_vr == DicomVR.SQ && _tag.IsPrivate) { if (!IsPrivateSequence(source)) { _vr = DicomVR.UN; break; } if (IsPrivateSequenceBad(source)) { _badPrivateSequence = true; _explicit = !_explicit; } break; } if (_vr == DicomVR.SQ) { // start of sequence _observer.OnBeginSequence(source, _tag, _length); _state = ParseState.Tag; if (_length != UndefinedLength) { _implicit = false; source.PushMilestone(_length); } else _implicit = true; PushState(state); ParseItemSequence(source, null); continue; } if (_length == UndefinedLength) { _observer.OnBeginFragmentSequence(source, _tag, _vr); _state = ParseState.Tag; PushState(state); ParseFragmentSequence(source, null); continue; } if (!source.Require(_length, ParseDataset, state)) { _result = DicomReaderResult.Suspended; return; } IByteBuffer buffer = source.GetBuffer(_length); if (!_vr.IsString) buffer = EndianByteBuffer.Create(buffer, source.Endian, _vr.UnitSize); _observer.OnElement(source, _tag, _vr, buffer); // parse private creator value and add to lookup table if (_tag.IsPrivate && _tag.Element != 0x0000 && _tag.Element <= 0x00ff) { var creator = DicomEncoding.Default.GetString(buffer.Data, 0, buffer.Data.Length).TrimEnd((char)DicomVR.LO.PaddingValue); var card = (uint)(_tag.Group << 16) + (uint)(_tag.Element); _private[card] = creator; } ResetState(); } } if (source.HasReachedMilestone()) { // end of explicit length sequence item source.PopMilestone(); return; } if (_result != DicomReaderResult.Processing) return; // end of processing _result = DicomReaderResult.Success; } catch (Exception e) { _exception = e; _result = DicomReaderResult.Error; } finally { if (_result != DicomReaderResult.Processing && _result != DicomReaderResult.Suspended) { _async.Set(); } } }
private bool ParseTag(IByteSource source) { if (this.parseStage == ParseStage.Tag) { source.Mark(); if (!source.Require(4)) { this.result = DicomReaderResult.Suspended; return false; } var group = source.GetUInt16(); var element = source.GetUInt16(); DicomPrivateCreator creator = null; if (@group.IsOdd() && element > 0x00ff) { var card = (uint)(@group << 16) + (uint)(element >> 8); lock (this.locker) { string pvt; if (this._private.TryGetValue(card, out pvt)) { creator = this.dictionary.GetPrivateCreator(pvt); } } } this._tag = new DicomTag(@group, element, creator); this._entry = this.dictionary[this._tag]; if (!this._tag.IsPrivate && this._entry != null && this._entry.MaskTag == null) { this._tag = this._entry.Tag; // Use dictionary tag } if (this.stop != null && this.stop(new ParseState { Tag = this._tag, SequenceDepth = this.sequenceDepth })) { this.result = DicomReaderResult.Stopped; return false; } this.parseStage = ParseStage.VR; } return true; }
private void ParseDataset(IByteSource source, object state) { try { _result = DicomReaderResult.Processing; while (!source.IsEOF && !source.HasReachedMilestone() && _result == DicomReaderResult.Processing) { if (_state == ParseState.Tag) { source.Mark(); if (!source.Require(4, ParseDataset, state)) { _result = DicomReaderResult.Suspended; return; } ushort group = source.GetUInt16(); ushort element = source.GetUInt16(); DicomPrivateCreator creator = null; if (group.IsOdd() && element > 0x00ff) { string pvt = null; uint card = (uint)(group << 16) + (uint)(element >> 8); if (_private.TryGetValue(card, out pvt)) { creator = Dictionary.GetPrivateCreator(pvt); } } _tag = new DicomTag(group, element, creator); _entry = Dictionary[_tag]; if (!_tag.IsPrivate && _entry != null && _entry.MaskTag == null) { _tag = _entry.Tag; // Use dictionary tag } if (_stop != null && _tag.CompareTo(_stop) >= 0) { _result = DicomReaderResult.Stopped; return; } _state = ParseState.VR; } while (_state == ParseState.VR) { if (_tag == DicomTag.Item || _tag == DicomTag.ItemDelimitationItem || _tag == DicomTag.SequenceDelimitationItem) { _vr = DicomVR.NONE; _state = ParseState.Length; break; } if (IsExplicitVR) { if (!source.Require(2, ParseDataset, state)) { _result = DicomReaderResult.Suspended; return; } byte[] bytes = source.GetBytes(2); string vr = Encoding.UTF8.GetString(bytes, 0, bytes.Length); if (!DicomVR.TryParse(vr, out _vr)) { // unable to parse VR _vr = DicomVR.UN; } } else { if (_entry != null) { if (_entry == DicomDictionary.UnknownTag) { _vr = DicomVR.UN; } else if (_entry.ValueRepresentations.Contains(DicomVR.OB) && _entry.ValueRepresentations.Contains(DicomVR.OW)) { _vr = DicomVR.OW; // ??? } else { _vr = _entry.ValueRepresentations.FirstOrDefault(); } } } if (_vr == null) { _vr = DicomVR.UN; } _state = ParseState.Length; if (_vr == DicomVR.UN) { if (_tag.Element == 0x0000) { // Group Length to UL _vr = DicomVR.UL; break; } else if (IsExplicitVR) { break; } } if (_tag.IsPrivate) { if (_tag.Element != 0x0000 && _tag.Element <= 0x00ff && _vr == DicomVR.UN) { _vr = DicomVR.LO; // force private creator to LO } } } while (_state == ParseState.Length) { if (_tag == DicomTag.Item || _tag == DicomTag.ItemDelimitationItem || _tag == DicomTag.SequenceDelimitationItem) { if (!source.Require(4, ParseDataset, state)) { _result = DicomReaderResult.Suspended; return; } _length = source.GetUInt32(); _state = ParseState.Value; break; } if (IsExplicitVR) { if (_vr.Is16bitLength) { if (!source.Require(2, ParseDataset, state)) { _result = DicomReaderResult.Suspended; return; } _length = source.GetUInt16(); } else { if (!source.Require(6, ParseDataset, state)) { _result = DicomReaderResult.Suspended; return; } source.Skip(2); _length = source.GetUInt32(); } } else { if (!source.Require(4, ParseDataset, state)) { _result = DicomReaderResult.Suspended; return; } _length = source.GetUInt32(); // assume that undefined length in implicit dataset is SQ if (_length == UndefinedLength && _vr == DicomVR.UN) { _vr = DicomVR.SQ; } } _state = ParseState.Value; } if (_state == ParseState.Value) { // check dictionary for VR after reading length to handle 16-bit lengths // check before reading value to handle SQ elements var parsedVR = _vr; // check dictionary for VR after reading length to handle 16-bit lengths // check before reading value to handle SQ elements if (_vr == DicomVR.UN && IsExplicitVR) { var entry = Dictionary[_tag]; if (entry != null) { _vr = entry.ValueRepresentations.FirstOrDefault(); } if (_vr == null) { _vr = DicomVR.UN; } } if (_tag == DicomTag.ItemDelimitationItem) { // end of sequence item return; } while (_vr == DicomVR.SQ && _tag.IsPrivate) { if (!IsPrivateSequence(source)) { _vr = DicomVR.UN; break; } if (IsPrivateSequenceBad(source)) { _badPrivateSequence = true; _explicit = !_explicit; } break; } if (_vr == DicomVR.SQ) { // start of sequence _observer.OnBeginSequence(source, _tag, _length); _state = ParseState.Tag; if (_length != UndefinedLength) { _implicit = false; source.PushMilestone(_length); } else { _implicit = true; } PushState(state); var last = source.Position; ParseItemSequence(source, null); // Aeric Sylvan - https://github.com/rcd/fo-dicom/issues/62#issuecomment-46248073 // Fix reading of SQ with parsed VR of UN if (source.Position > last || _length == 0) { continue; } else { _state = ParseState.Value; _vr = parsedVR; } } if (_length == UndefinedLength) { _observer.OnBeginFragmentSequence(source, _tag, _vr); _state = ParseState.Tag; PushState(state); ParseFragmentSequence(source, null); continue; } if (!source.Require(_length, ParseDataset, state)) { _result = DicomReaderResult.Suspended; return; } IByteBuffer buffer = source.GetBuffer(_length); if (!_vr.IsString) { buffer = EndianByteBuffer.Create(buffer, source.Endian, _vr.UnitSize); } _observer.OnElement(source, _tag, _vr, buffer); // parse private creator value and add to lookup table if (_tag.IsPrivate && _tag.Element != 0x0000 && _tag.Element <= 0x00ff) { var creator = DicomEncoding.Default.GetString(buffer.Data, 0, buffer.Data.Length).TrimEnd((char)DicomVR.LO.PaddingValue); var card = (uint)(_tag.Group << 16) + (uint)(_tag.Element); _private[card] = creator; } ResetState(); } } if (source.HasReachedMilestone()) { // end of explicit length sequence item source.PopMilestone(); return; } if (_result != DicomReaderResult.Processing) { return; } // end of processing _result = DicomReaderResult.Success; } catch (Exception e) { _exception = e; _result = DicomReaderResult.Error; } finally { if (_result != DicomReaderResult.Processing && _result != DicomReaderResult.Suspended) { _async.Set(); } } }
private bool ParseVR(IByteSource source) { while (this.parseStage == ParseStage.VR) { if (this._tag == DicomTag.Item || this._tag == DicomTag.ItemDelimitationItem || this._tag == DicomTag.SequenceDelimitationItem) { this._vr = DicomVR.NONE; this.parseStage = ParseStage.Length; break; } if (this.isExplicitVR) { if (!source.Require(2)) { this.result = DicomReaderResult.Suspended; return false; } source.Mark(); var bytes = source.GetBytes(2); var vr = Encoding.UTF8.GetString(bytes, 0, bytes.Length); if (string.IsNullOrWhiteSpace(vr)) { if (this._entry != null) { this._vr = this._entry.ValueRepresentations.FirstOrDefault(); } } else if (!DicomVR.TryParse(vr, out this._vr)) { // unable to parse VR; rewind VR bytes for continued attempt to interpret the data. this._vr = DicomVR.Implicit; source.Rewind(); } } else { if (this._entry != null) { if (this._entry == DicomDictionary.UnknownTag) { this._vr = DicomVR.UN; } else if (this._entry.ValueRepresentations.Contains(DicomVR.OB) && this._entry.ValueRepresentations.Contains(DicomVR.OW)) { this._vr = DicomVR.OW; // ??? } else { this._vr = this._entry.ValueRepresentations.FirstOrDefault(); } } } if (this._vr == null) { this._vr = DicomVR.UN; } this.parseStage = ParseStage.Length; if (this._vr == DicomVR.UN) { if (this._tag.Element == 0x0000) { // Group Length to UL this._vr = DicomVR.UL; break; } if (this.isExplicitVR) { break; } } if (this._tag.IsPrivate) { if (this._tag.Element != 0x0000 && this._tag.Element <= 0x00ff && this._vr == DicomVR.UN) { this._vr = DicomVR.LO; // force private creator to LO } } } return true; }