コード例 #1
0
            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);
            }
コード例 #2
0
            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);
            }
コード例 #3
0
            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);
            }
コード例 #4
0
        private static ParseResult Parse(
            IByteSource source,
            IDicomReaderObserver fileMetasetInfoObserver,
            IDicomReaderObserver datasetObserver,
            Func <ParseState, bool> stop)
        {
            if (!source.Require(132))
            {
                return(new ParseResult(DicomReaderResult.Error, DicomFileFormat.Unknown, null));
            }

            var fileFormat = DicomFileFormat.Unknown;
            var syntax     = DicomTransferSyntax.ExplicitVRLittleEndian;

            Preprocess(source, ref fileFormat, ref syntax);

            var result = DoParse(
                source,
                fileMetasetInfoObserver,
                datasetObserver,
                stop,
                ref syntax,
                ref fileFormat);

            return(new ParseResult(result, fileFormat, syntax));
        }
コード例 #5
0
ファイル: DicomReader.cs プロジェクト: fo-dicom/fo-dicom
            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);
            }
コード例 #6
0
            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);
            }
コード例 #7
0
ファイル: DicomReader.cs プロジェクト: fo-dicom/fo-dicom
            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);
            }
コード例 #8
0
ファイル: DicomReader.cs プロジェクト: fo-dicom/fo-dicom
            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);
            }
コード例 #9
0
ファイル: DicomReader.cs プロジェクト: yuya-goojooob/fo-dicom
            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);
            }
コード例 #10
0
ファイル: DicomReader.cs プロジェクト: zinan/fo-dicom
            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);
            }
コード例 #11
0
            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);
            }
コード例 #12
0
        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();
                }
            }
        }
コード例 #13
0
        private static async Task <Tuple <DicomReaderResult, DicomFileFormat, DicomTransferSyntax> > ParseAsync(
            IByteSource source,
            IDicomReaderObserver fileMetasetInfoObserver,
            IDicomReaderObserver datasetObserver,
            Func <ParseState, bool> stop)
        {
            if (!source.Require(132))
            {
                return(Tuple.Create(DicomReaderResult.Error, DicomFileFormat.Unknown, (DicomTransferSyntax)null));
            }

            var fileFormat = DicomFileFormat.Unknown;
            var syntax     = DicomTransferSyntax.ExplicitVRLittleEndian;

            Preprocess(source, ref fileFormat, ref syntax);

            return
                (await
                 DoParseAsync(source, fileMetasetInfoObserver, datasetObserver, stop, syntax, fileFormat).ConfigureAwait(false));
        }
コード例 #14
0
ファイル: DicomReader.cs プロジェクト: fo-dicom/fo-dicom
            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);
            }
コード例 #15
0
        private void ParseDataset(IByteSource source, object state)
        {
            try {
                _result = DicomReaderResult.Processing;

                while (!source.IsEOF && !source.HasReachedMilestone())
                {
                    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.ASCII.GetString(bytes);
                            _vr = DicomVR.Parse(vr);
                        }
                        else
                        {
                            DicomDictionaryEntry entry = Dictionary[_tag];
                            if (entry != null)
                            {
                                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;
                            }

                            if (_tag.Group.IsOdd())
                            {
                                if (_tag.Element <= 0x00ff)
                                {
                                    // Private Creator to LO
                                    _vr = DicomVR.LO;
                                    break;
                                }
                                else if (IsExplicitVR)
                                {
                                    DicomDictionaryEntry entry = Dictionary[_tag];
                                    if (entry != null)
                                    {
                                        _vr = entry.ValueRepresentations.FirstOrDefault();
                                    }

                                    if (_vr == null)
                                    {
                                        _vr = DicomVR.UN;
                                    }

                                    break;
                                }
                            }
                        }
                    }

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

                        _state = ParseState.Value;
                    }

                    if (_state == ParseState.Value)
                    {
                        if (_tag == DicomTag.ItemDelimitationItem)
                        {
                            // end of sequence item
                            ParseItemSequence(source, state);
                            return;
                        }

                        if (_vr == DicomVR.SQ)
                        {
                            // start of sequence
                            _observer.OnBeginSequence(source, _tag, _length);
                            _state = ParseState.Tag;
                            if (_length != UndefinedLength)
                            {
                                source.PushMilestone(_length);
                            }
                            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);

                        ResetState();
                    }
                }

                if (source.HasReachedMilestone())
                {
                    // end of explicit length sequence item
                    _observer.OnEndSequenceItem();
                    source.PopMilestone();
                    ParseItemSequence(source, state);
                    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();
                }
            }
        }
コード例 #16
0
ファイル: DicomReader.cs プロジェクト: gustavosaita/fo-dicom
            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;
            }
コード例 #17
0
ファイル: DicomReader.cs プロジェクト: gustavosaita/fo-dicom
            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;
            }
コード例 #18
0
ファイル: DicomReader.cs プロジェクト: gustavosaita/fo-dicom
            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;
            }
コード例 #19
0
ファイル: DicomReader.cs プロジェクト: gustavosaita/fo-dicom
            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;
            }
コード例 #20
0
            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);
            }
コード例 #21
0
        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();
                }
            }
        }
コード例 #22
0
        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);
                }
            }
        }
コード例 #23
0
            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);
            }
コード例 #24
0
ファイル: DicomReader.cs プロジェクト: fo-dicom/fo-dicom
            private bool ParseItemSequenceTag(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();

                    _tag = new DicomTag(@group, element);

                    if (_tag != DicomTag.Item && _tag != DicomTag.SequenceDelimitationItem)
                    {
                        // assume invalid sequence
                        source.Rewind();
                        if (!_implicit)
                        {
                            source.PopMilestone();
                        }
                        _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;
                        }
                        return(false);
                    }

                    _length = source.GetUInt32();

                    if (_tag == DicomTag.SequenceDelimitationItem)
                    {
                        // #64, in case explicit length has been specified despite occurrence of Sequence Delimitation Item
                        if (source.HasReachedMilestone() && source.MilestonesCount > _sequenceDepth)
                        {
                            ResetState();
                            return(true);
                        }

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

                    _parseStage = ParseStage.Value;
                }
                return(true);
            }
コード例 #25
0
ファイル: DicomReader.cs プロジェクト: fo-dicom/fo-dicom
            private bool ParseLength(IByteSource source)
            {
                while (_parseStage == ParseStage.Length)
                {
                    if (_tag == DicomTag.Item || _tag == DicomTag.ItemDelimitationItem ||
                        _tag == DicomTag.SequenceDelimitationItem)
                    {
                        if (!source.Require(4))
                        {
                            _result = DicomReaderResult.Suspended;
                            return(false);
                        }

                        _length = source.GetUInt32();

                        _parseStage = ParseStage.Value;
                        break;
                    }

                    if (_isExplicitVR || _badPrivateSequence)
                    {
                        if (_vr == DicomVR.Implicit)
                        {
                            if (!source.Require(4))
                            {
                                _result = DicomReaderResult.Suspended;
                                return(false);
                            }

                            _length = source.GetUInt32();

                            // assume that undefined length in implicit VR element is SQ
                            if (_length == _undefinedLength)
                            {
                                _vr = DicomVR.SQ;
                            }
                        }
                        else if (_vr.Is16bitLength)
                        {
                            if (!source.Require(2))
                            {
                                _result = DicomReaderResult.Suspended;
                                return(false);
                            }

                            _length = source.GetUInt16();
                        }
                        else
                        {
                            if (!source.Require(6))
                            {
                                _result = DicomReaderResult.Suspended;
                                return(false);
                            }

                            source.Skip(2);
                            _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 (_length == _undefinedLength && _vr == DicomVR.UN && _tag.IsPrivate)
                            {
                                _vr = DicomVR.SQ;
                            }
                        }
                    }
                    else
                    {
                        if (!source.Require(4))
                        {
                            _result = DicomReaderResult.Suspended;
                            return(false);
                        }

                        _length = source.GetUInt32();

                        // assume that undefined length in implicit dataset is SQ
                        if (_length == _undefinedLength && _vr == DicomVR.UN)
                        {
                            _vr = DicomVR.SQ;
                        }
                    }

                    _parseStage = ParseStage.Value;
                }
                return(true);
            }
コード例 #26
0
ファイル: DicomReader.cs プロジェクト: yuya-goojooob/fo-dicom
            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 || this.badPrivateSequence)
                    {
                        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.IsNullOrEmpty(vr.Trim()))
                        {
                            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
                            // change 20161216: if changing from UN to UL then ParseLength causes a error, since length in UL is 2 bytes while length in UN is 6 bytes.
                            // so the source hat UN and coded the length in 6 bytes. if here the VR was changed to UL then ParseLength would only read 2 bytes and the parser is then wrong.
                            // but no worry: in ParseValue in the first lines there is a lookup in the Dictionary of DicomTags and there the VR is changed to UL so that the value is finally interpreted correctly as 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);
            }
コード例 #27
0
ファイル: DicomFileReader.cs プロジェクト: jwake/fo-dicom
        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();
                }
            }
        }
コード例 #28
0
ファイル: DicomFileReader.cs プロジェクト: vdrm/fo-dicom
        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.ASCII.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.ASCII.GetString(ea.Data.Data);
                            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.ASCII.GetString(ea.Data.Data);
                        _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();
                }
            }
        }
コード例 #29
0
ファイル: DicomFileReader.cs プロジェクト: ZeryZhang/fo-dicom
		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();
				}
			}
		}
コード例 #30
0
ファイル: DicomReader.cs プロジェクト: peerct/fo-dicom
		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();
				}
			}
		}
コード例 #31
0
ファイル: DicomReader.cs プロジェクト: fo-dicom/fo-dicom
            private bool ParseVR(IByteSource source)
            {
                while (_parseStage == ParseStage.VR)
                {
                    if (_tag == DicomTag.Item || _tag == DicomTag.ItemDelimitationItem ||
                        _tag == DicomTag.SequenceDelimitationItem)
                    {
                        _vr         = DicomVR.NONE;
                        _parseStage = ParseStage.Length;
                        break;
                    }

                    if (_isExplicitVR || _badPrivateSequence)
                    {
                        if (!source.Require(2))
                        {
                            _result = DicomReaderResult.Suspended;
                            return(false);
                        }

                        source.Mark();
                        var bytes = source.GetBytes(2);
                        var vr    = Encoding.UTF8.GetString(bytes, 0, bytes.Length);

                        if (string.IsNullOrEmpty(vr.Trim()))
                        {
                            if (_entry != null)
                            {
                                _vr = _entry.ValueRepresentations.FirstOrDefault();
                            }
                        }
                        else if (!DicomVR.TryParse(vr, out _vr))
                        {
                            // unable to parse VR; rewind VR bytes for continued attempt to interpret the data.
                            _vr = DicomVR.Implicit;
                            source.Rewind();
                        }
                    }
                    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;
                    }

                    _parseStage = ParseStage.Length;

                    if (_vr == DicomVR.UN)
                    {
                        if (_tag.Element == 0x0000)
                        {
                            // Group Length to UL
                            // change 20161216: if changing from UN to UL then ParseLength causes a error, since length in UL is 2 bytes while length in UN is 6 bytes.
                            // so the source hat UN and coded the length in 6 bytes. if here the VR was changed to UL then ParseLength would only read 2 bytes and the parser is then wrong.
                            // but no worry: in ParseValue in the first lines there is a lookup in the Dictionary of DicomTags and there the VR is changed to UL so that the value is finally interpreted correctly as UL.
                            // _vr = DicomVR.UL;
                            break;
                        }
                        if (_isExplicitVR)
                        {
                            break;
                        }
                    }

                    if (_tag.IsPrivate)
                    {
                        // according to
                        // http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_7.8.html
                        // Private Creator Data Elements numbered (gggg,0010-00FF) (gggg is odd)
                        // The VR of the private identification code shall be LO (Long String) and the VM shall be equal to 1.
                        if (_tag.Element >= 0x0010 && _tag.Element <= 0x00ff && _vr == DicomVR.UN)
                        {
                            _vr = DicomVR.LO; // force private creator to LO
                        }
                    }
                }
                return(true);
            }
コード例 #32
0
ファイル: DicomFileReader.cs プロジェクト: aerik/fo-dicom
        private static ParseResult Parse(
            IByteSource source,
            IDicomReaderObserver fileMetasetInfoObserver,
            IDicomReaderObserver datasetObserver,
            Func<ParseState, bool> stop)
        {
            if (!source.Require(132))
            {
                return new ParseResult(DicomReaderResult.Error, DicomFileFormat.Unknown, null);
            }

            var fileFormat = DicomFileFormat.Unknown;
            var syntax = DicomTransferSyntax.ExplicitVRLittleEndian;

            Preprocess(source, ref fileFormat, ref syntax);

            var result = DoParse(
                source,
                fileMetasetInfoObserver,
                datasetObserver,
                stop,
                ref syntax,
                ref fileFormat);

            return new ParseResult(result, fileFormat, syntax);
        }
コード例 #33
0
ファイル: DicomReader.cs プロジェクト: fo-dicom/fo-dicom
            private async Task <bool> ParseValueAsync(IByteSource source)
            {
                if (_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 = _vr;

                    // check dictionary for VR after reading length to handle 16-bit lengths
                    // check before reading value to handle SQ elements
                    if (_vr == DicomVR.Implicit || (_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 || _tag == DicomTag.SequenceDelimitationItem)
                    {
                        // end of sequence item
                        return(false);
                    }

                    while (_vr == DicomVR.SQ && _tag.IsPrivate && _length > 0)
                    {
                        if (!IsPrivateSequence(source))
                        {
                            _vr = DicomVR.UN;
                            break;
                        }

                        if (IsPrivateSequenceBad(source, _length, _isExplicitVR))
                        {
                            _badPrivateSequence = true;
                            // store the depth of the bad sequence, we only want to switch back once we've processed
                            // the entire sequence, regardless of any sub-sequences.
                            _badPrivateSequenceDepth = _sequenceDepth;
                            _isExplicitVR            = !_isExplicitVR;
                        }
                        break;
                    }

                    var curIndex = source.Position;
                    // Fix to handle sequence items not associated with any sequence (#364)
                    if (_tag.Equals(DicomTag.Item))
                    {
                        source.Rewind();
                        _vr = DicomVR.SQ;
                    }

                    if (_vr == DicomVR.SQ)
                    {
                        // start of sequence
                        _observer.OnBeginSequence(source, _tag, _length);
                        _parseStage = ParseStage.Tag;
                        if (_length == 0)
                        {
                            _implicit = false;
                            source.PushMilestone((uint)(source.Position - curIndex));
                        }
                        else if (_length != _undefinedLength)
                        {
                            _implicit = false;
                            source.PushMilestone(_length);
                        }
                        else
                        {
                            _implicit = true;
                        }
                        var last = source.Position;

                        // Conformance with CP-246 (#177)
                        var needtoChangeEndian = false;
                        if (parsedVR == DicomVR.UN && !_tag.IsPrivate)
                        {
                            _implicit          = true;
                            needtoChangeEndian = source.Endian == Endian.Big;
                        }
                        if (needtoChangeEndian)
                        {
                            source.Endian = Endian.Little;
                        }

                        await 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 || _length == 0)
                        {
                            return(true);
                        }

                        _parseStage = ParseStage.Value;
                        _vr         = parsedVR;
                    }

                    if (_length == _undefinedLength)
                    {
                        _observer.OnBeginFragmentSequence(source, _tag, _vr);
                        _parseStage = ParseStage.Tag;
                        await ParseFragmentSequenceAsync(source).ConfigureAwait(false);

                        return(true);
                    }

                    if (!source.Require(_length))
                    {
                        _result = DicomReaderResult.Suspended;
                        return(false);
                    }

                    var buffer = await source.GetBufferAsync(_length).ConfigureAwait(false);

                    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
                    // according to
                    // http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_7.8.html
                    // Private Creator Data Elements numbered (gggg,0010-00FF) (gggg is odd)
                    // The VR of the private identification code shall be LO (Long String) and the VM shall be equal to 1.
                    if (_tag.IsPrivate && _tag.Element >= 0x0010 && _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) + _tag.Element;

                        lock (_locker)
                        {
                            _private[card] = creator;
                        }
                    }

                    ResetState();
                }
                return(true);
            }
コード例 #34
0
ファイル: DicomFileReader.cs プロジェクト: aerik/fo-dicom
        private static async Task<Tuple<DicomReaderResult, DicomFileFormat, DicomTransferSyntax>> ParseAsync(
            IByteSource source,
            IDicomReaderObserver fileMetasetInfoObserver,
            IDicomReaderObserver datasetObserver,
            Func<ParseState, bool> stop)
        {
            if (!source.Require(132))
            {
                return Tuple.Create(DicomReaderResult.Error, DicomFileFormat.Unknown, (DicomTransferSyntax)null);
            }

            var fileFormat = DicomFileFormat.Unknown;
            var syntax = DicomTransferSyntax.ExplicitVRLittleEndian;

            Preprocess(source, ref fileFormat, ref syntax);

            return
                await
                DoParseAsync(source, fileMetasetInfoObserver, datasetObserver, stop, syntax, fileFormat).ConfigureAwait(false);
        }
コード例 #35
0
ファイル: DicomReader.cs プロジェクト: gustavosaita/fo-dicom
            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;
            }
コード例 #36
0
ファイル: DicomReader.cs プロジェクト: gustavosaita/fo-dicom
            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;
            }
コード例 #37
0
ファイル: DicomReader.cs プロジェクト: peerct/fo-dicom
		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();
				}
			}
		}
コード例 #38
0
ファイル: DicomReader.cs プロジェクト: gustavosaita/fo-dicom
            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;
            }
コード例 #39
0
ファイル: DicomReader.cs プロジェクト: peerct/fo-dicom
		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();
				}
			}
		}
コード例 #40
0
ファイル: DicomReader.cs プロジェクト: gustavosaita/fo-dicom
            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;
            }
コード例 #41
0
        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();
                }
            }
        }
コード例 #42
0
ファイル: DicomReader.cs プロジェクト: gustavosaita/fo-dicom
            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;
            }
コード例 #43
0
        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();
                }
            }
        }
コード例 #44
0
ファイル: DicomReader.cs プロジェクト: ZeryZhang/fo-dicom
        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);

                }


            }

        }