예제 #1
0
        private bool IsPrivateSequenceBad(IByteSource source)
        {
            source.Mark();

            try {
                var group   = source.GetUInt16();
                var element = source.GetUInt16();
                var tag     = new DicomTag(group, element);
                var length  = source.GetUInt32();

                group   = source.GetUInt16();
                element = source.GetUInt16();
                tag     = new DicomTag(group, element);

                byte[]  bytes = source.GetBytes(2);
                string  vr    = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
                DicomVR dummy;
                if (DicomVR.TryParse(vr, out dummy))
                {
                    return(!_explicit);
                }
                // unable to parse VR
                if (_explicit)
                {
                    return(true);
                }
            } finally {
                source.Rewind();
            }

            return(false);
        }
예제 #2
0
            private static bool IsPrivateSequenceBad(IByteSource source, bool isExplicitVR)
            {
                source.Mark();

                try
                {
                    source.GetUInt16(); // group
                    source.GetUInt16(); // element
                    source.GetUInt32(); // length

                    source.GetUInt16(); // group
                    source.GetUInt16(); // element

                    var     bytes = source.GetBytes(2);
                    var     vr    = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
                    DicomVR dummy;
                    if (DicomVR.TryParse(vr, out dummy))
                    {
                        return(!isExplicitVR);
                    }
                    // unable to parse VR
                    if (isExplicitVR)
                    {
                        return(true);
                    }
                }
                finally
                {
                    source.Rewind();
                }

                return(false);
            }
예제 #3
0
            private static bool IsPrivateSequenceBad(IByteSource source, bool isExplicitVR)
            {
                source.Mark();

                try
                {
                    // Skip "item" tags; continue skipping until length is non-zero (#223)
                    while (new DicomTag(source.GetUInt16(), source.GetUInt16()) == DicomTag.Item // group, element
                           & source.GetUInt32() == 0)                                            // length (using & instead of && enforces RHS to be evaluated regardless of LHS)
                    {
                    }

                    source.GetUInt16(); // group
                    source.GetUInt16(); // element

                    var     bytes = source.GetBytes(2);
                    var     vr    = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
                    DicomVR dummy;
                    if (DicomVR.TryParse(vr, out dummy))
                    {
                        return(!isExplicitVR);
                    }
                    // unable to parse VR
                    if (isExplicitVR)
                    {
                        return(true);
                    }
                }
                finally
                {
                    source.Rewind();
                }

                return(false);
            }
예제 #4
0
            private static bool IsPrivateSequenceBad(IByteSource source, uint count, bool isExplicitVR)
            {
                source.Mark();

                try
                {
                    // Skip "item" tags; continue skipping until length is non-zero (#223)
                    // Using & instead of && enforces RHS to be evaluated regardless of LHS
                    uint length;
                    while (source.GetUInt16() == DicomTag.Item.Group &
                           source.GetUInt16() == DicomTag.Item.Element &
                           (length = source.GetUInt32()) < uint.MaxValue)   // Dummy condition to ensure that length is included in parsing
                    {
                        // Length non-zero, end skipping (#223)
                        if (length > 0)
                        {
                            break;
                        }

                        // Handle scenario where last tag is private sequence with empty items (#487)
                        count -= 8;
                        if (count <= 0)
                        {
                            return(false);
                        }
                    }

                    source.GetUInt16(); // group
                    source.GetUInt16(); // element

                    var     bytes = source.GetBytes(2);
                    var     vr    = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
                    DicomVR dummy;
                    if (DicomVR.TryParse(vr, out dummy))
                    {
                        return(!isExplicitVR);
                    }
                    // unable to parse VR
                    if (isExplicitVR)
                    {
                        return(true);
                    }
                }
                finally
                {
                    source.Rewind();
                }

                return(false);
            }
예제 #5
0
        public void All_Known_VRs_Exist()
        {
            foreach (var vr in AllVRs)
            {
                Assert.True(DicomVR.Parse(vr).Code == vr);
                Assert.True(DicomVR.Parse(vr).ToString() == vr);
                DicomVR parsedVr;
                Assert.True(DicomVR.TryParse(vr, out parsedVr));
                Assert.True(parsedVr.Code == vr);
                Assert.False(DicomVR.TryParse(vr + "X", out parsedVr));
                Assert.False(DicomVR.TryParse(vr + " ", out parsedVr));
                Assert.False(DicomVR.TryParse(" " + vr, out parsedVr));
            }

            // "NONE" is a special case, so let's make it so here as well.
            Assert.True(DicomVR.Parse("NONE") == DicomVR.NONE);
        }
예제 #6
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();
                }
            }
        }
예제 #7
0
            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);
            }
예제 #8
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);
            }
예제 #9
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 || 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);
            }