예제 #1
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();
                }
            }
        }
예제 #2
0
        private void OnCompleteFileMetaInfo(IAsyncResult result)
        {
            try {
                DicomDatasetWalker walker;

                if (result != null)
                {
                    walker = result.AsyncState as DicomDatasetWalker;
                    walker.EndWalk(result);
                }

                DicomTransferSyntax syntax = _fileMetaInfo.TransferSyntax;

                DicomWriter writer = new DicomWriter(syntax, _options, _target);
                walker = new DicomDatasetWalker(_dataset);
                walker.BeginWalk(writer, OnCompleteDataset, walker);
            } catch (Exception e) {
                _exception = e;
                _async.Set();
            }
        }
예제 #3
0
        private void OnCompleteFileMetaInfo(IAsyncResult result)
        {
            try {
                DicomDatasetWalker walker;

                if (result != null)
                {
                    walker = result.AsyncState as DicomDatasetWalker;
                    walker.EndWalk(result);
                }

                //DicomTransferSyntax syntax = _fileMetaInfo.TransferSyntax;
                DicomTransferSyntax syntax = _fileMetaInfo.InternalTransferSyntax;
                if (_options.KeepGroupLengths)
                {
                    // update transfer syntax and recalculate existing group lengths
                    _dataset.InternalTransferSyntax = syntax;
                    _dataset.RecalculateGroupLengths(false);
                }
                else
                {
                    // remove group lengths as suggested in PS 3.5 7.2
                    //
                    //	2. It is recommended that Group Length elements be removed during storage or transfer
                    //	   in order to avoid the risk of inconsistencies arising during coercion of data
                    //	   element values and changes in transfer syntax.
                    _dataset.RemoveGroupLengths();
                }

                DicomWriter writer = new DicomWriter(syntax, _options, _target);
                walker = new DicomDatasetWalker(_dataset);
                walker.BeginWalk(writer, OnCompleteDataset, walker);
            } catch (Exception e) {
                _exception = e;
                _async.Set();
            }
        }
예제 #4
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();
                }
            }
        }
예제 #5
0
        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();
                }
            }
        }
예제 #6
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();
                }
            }
        }