Exemplo n.º 1
0
            private bool ParseValue(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;
                        }

                        ParseItemSequence(source);

                        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;
                        ParseFragmentSequence(source);
                        return(true);
                    }

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

                    var buffer = source.GetBuffer(_length);

                    if (buffer != null)
                    {
                        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);
            }
Exemplo n.º 2
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();
                }
            }
        }
Exemplo n.º 3
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();
                }
            }
        }