public DicomReadStatus Read(DicomTag stopAtTag, DicomReadOptions options) { if (stopAtTag == null) { stopAtTag = new DicomTag(0xFFFFFFFF, "Bogus Tag", "BogusTag", DicomVr.UNvr, false, 1, 1, false); } // Counters: // _remain - bytes remaining in stream // _bytes - estimates bytes to end of dataset // _read - number of bytes read from stream try { BytesNeeded = 0; _remain = _stream.Length - _stream.Position; while (_remain > 0) { if (_inGroup2 && BytesRead >= _endGroup2) { _inGroup2 = false; // Only change if we're still reading the meta info if (Dataset.StartTagValue < DicomTags.TransferSyntaxUid) { TransferSyntax group2Syntax = TransferSyntax.GetTransferSyntax( Dataset[DicomTags.TransferSyntaxUid].GetString(0, String.Empty)); if (group2Syntax == null) { throw new DicomException("Unsupported transfer syntax in group 2 elements"); } TransferSyntax = group2Syntax; } } uint tagValue; if (LastTagRead == null) { if (_remain < 4) { return(NeedMoreData(4)); } _pos = _stream.Position; ushort g = _reader.ReadUInt16(); ushort e = _reader.ReadUInt16(); tagValue = DicomTag.GetTagValue(g, e); if (DicomTag.IsPrivateGroup(g) && e > 0x00ff) { SaveTagRead = LastTagRead = DicomTagDictionary.GetDicomTag(g, e) ?? new DicomTag((uint)g << 16 | e, "Private Tag", "PrivateTag", DicomVr.UNvr, false, 1, uint.MaxValue, false); } else { if (e == 0x0000) { SaveTagRead = LastTagRead = new DicomTag((uint)g << 16 | e, "Group Length", "GroupLength", DicomVr.ULvr, false, 1, 1, false); } else { SaveTagRead = LastTagRead = DicomTagDictionary.GetDicomTag(g, e) ?? new DicomTag((uint)g << 16 | e, "Private Tag", "PrivateTag", DicomVr.UNvr, false, 1, uint.MaxValue, false); } } _remain -= 4; BytesEstimated += 4; BytesRead += 4; } else { tagValue = LastTagRead.TagValue; } if ((tagValue >= stopAtTag.TagValue) && (_sqrs.Count == 0)) // only exit in root message when after stop tag { if (_inGroup2 && tagValue > 0x0002FFFF) { if (_endGroup2 != BytesRead - 4) { Platform.Log(LogLevel.Debug, "File Meta Info Length, {0}, not equal to actual bytes read in file, {1}, overwriting length.", EndGroupTwo, BytesRead - 4); _endGroup2 = BytesRead - 4; } _inGroup2 = false; } EncounteredStopTag = true; return(DicomReadStatus.Success); } bool twoByteLength; if (_vr == null) { if (_syntax.ExplicitVr) { if (LastTagRead == DicomTag.Item || LastTagRead == DicomTag.ItemDelimitationItem || LastTagRead == DicomTag.SequenceDelimitationItem) { _vr = DicomVr.NONE; twoByteLength = _vr.Is16BitLengthField; } else { if (_remain < 2) { return(NeedMoreData(2)); } string vr = new string(_reader.ReadChars(2)); _vr = DicomVr.GetVR(vr); twoByteLength = _vr.Is16BitLengthField; _remain -= 2; BytesEstimated += 2; BytesRead += 2; if (LastTagRead.VR.Equals(DicomVr.UNvr)) { LastTagRead = new DicomTag(LastTagRead.TagValue, "Private Tag", "PrivateTag", _vr, false, 1, uint.MaxValue, false); if (vr.Equals("??")) { twoByteLength = true; } } else if (!LastTagRead.VR.Equals(_vr)) { if (!vr.Equals(" ")) { DicomTag tag = new DicomTag(LastTagRead.TagValue, LastTagRead.Name, LastTagRead.VariableName, _vr, LastTagRead.MultiVR, LastTagRead.VMLow, LastTagRead.VMHigh, LastTagRead.Retired); LastTagRead = tag; ; // TODO, log something } } } } else { _vr = LastTagRead.VR; twoByteLength = _vr.Is16BitLengthField; } if (_vr == DicomVr.UNvr) { if (LastTagRead.IsPrivate) { if (LastTagRead.Element <= 0x00ff && LastTagRead.Element >= 0x0010) { // Reset the tag with the right VR and a more descriptive name. LastTagRead = new DicomTag(LastTagRead.TagValue, "Private Creator Code", "PrivateCreatorCode", DicomVr.LOvr, false, 1, uint.MaxValue, false); // private creator id // Only set the VR to LO for Implicit VR, if we do it for // Explicit VR syntaxes, we would incorrectly read the tag // length below. if (!_syntax.ExplicitVr) { _vr = DicomVr.LOvr; } } else if (_stream.CanSeek && Flags.IsSet(options, DicomReadOptions.AllowSeekingForContext)) { // attempt to identify private sequence by checking if the tag has // an undefined length long pos = _stream.Position; int bytesToCheck = _syntax.ExplicitVr ? 6 : 4; if (_remain >= bytesToCheck) { if (_syntax.ExplicitVr) { _reader.ReadUInt16(); } uint l = _reader.ReadUInt32(); if (l == _undefinedLength) { _vr = DicomVr.SQvr; } } _stream.Position = pos; } } } } else { twoByteLength = _vr.Is16BitLengthField; } // Read the value length if (_len == _undefinedLength) { if (_syntax.ExplicitVr) { if (LastTagRead == DicomTag.Item || LastTagRead == DicomTag.ItemDelimitationItem || LastTagRead == DicomTag.SequenceDelimitationItem) { if (_remain < 4) { return(NeedMoreData(4)); } _len = _reader.ReadUInt32(); _remain -= 4; BytesEstimated += 4; BytesRead += 4; } else { if (twoByteLength) { if (_remain < 2) { return(NeedMoreData(2)); } _len = _reader.ReadUInt16(); _remain -= 2; BytesEstimated += 2; BytesRead += 2; } else { if (_remain < 6) { return(NeedMoreData(6)); } _reader.ReadByte(); _reader.ReadByte(); _len = _reader.ReadUInt32(); _remain -= 6; BytesEstimated += 6; BytesRead += 6; } } } else { if (_remain < 4) { return(NeedMoreData(4)); } _len = _reader.ReadUInt32(); _remain -= 4; BytesEstimated += 4; BytesRead += 4; } if ((_len != _undefinedLength) && !_vr.Equals(DicomVr.SQvr) && !(LastTagRead.Equals(DicomTag.Item) && _fragment == null)) { BytesEstimated += _len; } } // If we have a private creator code, set the VR to LO, because // that is what it is. We must do this after we read the length // so that the 32 bit length is read properly. if ((LastTagRead.IsPrivate) && (_vr.Equals(DicomVr.UNvr)) && (LastTagRead.Element <= 0x00ff)) { _vr = DicomVr.LOvr; } if (_fragment != null) { // In the middle of parsing pixels if (LastTagRead == DicomTag.Item) { if (_remain < _len) { return(NeedMoreData(_remain - _len)); } if (Flags.IsSet(options, DicomReadOptions.StorePixelDataReferences) && _fragment.HasOffsetTable) { FileReference reference = new FileReference(StreamOpener, _stream.Position, _len, _endian, DicomVr.OBvr); DicomFragment fragment = new DicomFragment(reference); _fragment.AddFragment(fragment); if (_stream.CanSeek) { _stream.Seek(_len, SeekOrigin.Current); } else { ConsumeStreamBytes(_stream, _len); } } else { ByteBuffer data = new ByteBuffer(_endian, _len); data.CopyFrom(_stream, (int)_len); if (!_fragment.HasOffsetTable) { _fragment.SetOffsetTable(data); } else { DicomFragment fragment = new DicomFragment(data); _fragment.AddFragment(fragment); } } _remain -= _len; BytesRead += _len; } else if (LastTagRead == DicomTag.SequenceDelimitationItem) { if (_sqrs.Count > 0) { SequenceRecord rec = _sqrs.Peek(); DicomAttributeCollection ds = rec.Current; ds[_fragment.Tag] = _fragment; if (rec.Curlen != _undefinedLength) { long end = rec.Curpos + rec.Curlen; if (_stream.Position >= end) { rec.Current = null; } } } else { Dataset[_fragment.Tag] = _fragment; } _fragment = null; } else { Platform.Log(LogLevel.Error, "Encountered unexpected tag in stream: {0}", LastTagRead.ToString()); // unexpected tag return(DicomReadStatus.UnknownError); } } else if (_sqrs.Count > 0 && (LastTagRead == DicomTag.Item || LastTagRead == DicomTag.ItemDelimitationItem || LastTagRead == DicomTag.SequenceDelimitationItem)) { SequenceRecord rec = _sqrs.Peek(); if (LastTagRead.Equals(DicomTag.Item)) { if (_len != _undefinedLength) { if (_len > _remain) { return(NeedMoreData(_remain - _len)); } } DicomSequenceItem ds; if (rec.Tag.TagValue.Equals(DicomTags.DirectoryRecordSequence)) { DirectoryRecordSequenceItem dr = new DirectoryRecordSequenceItem { Offset = (uint)_pos }; ds = dr; } else { ds = new DicomSequenceItem(); } rec.Current = ds; if (rec.Tag.VR.Equals(DicomVr.UNvr)) { DicomTag tag = new DicomTag(rec.Tag.TagValue, rec.Tag.Name, rec.Tag.VariableName, DicomVr.SQvr, rec.Tag.MultiVR, rec.Tag.VMLow, rec.Tag.VMHigh, rec.Tag.Retired); rec.Parent[tag].AddSequenceItem(ds); } else { rec.Parent[rec.Tag].AddSequenceItem(ds); } // Specific character set is inherited, save it. It will be overwritten // if a new value of the tag is encountered in the sequence. rec.Current.SpecificCharacterSet = rec.Parent.SpecificCharacterSet; // save the sequence length rec.Curpos = _pos + 8; rec.Curlen = _len; _sqrs.Pop(); _sqrs.Push(rec); if (_len != _undefinedLength) { ByteBuffer data = new ByteBuffer(_endian, _len); data.CopyFrom(_stream, (int)_len); data.Stream.Position = 0; _remain -= _len; BytesRead += _len; DicomStreamReader idsr = new DicomStreamReader(data.Stream) { Dataset = ds, TransferSyntax = rec.Tag.VR.Equals(DicomVr.UNvr) ? TransferSyntax.ImplicitVrLittleEndian : _syntax, StreamOpener = StreamOpener }; DicomReadStatus stat = idsr.Read(null, options & ~DicomReadOptions.StorePixelDataReferences); if (stat != DicomReadStatus.Success) { Platform.Log(LogLevel.Error, "Unexpected parsing error ({0}) when reading sequence attribute: {1}.", stat, rec.Tag.ToString()); return(stat); } } } else if (LastTagRead == DicomTag.ItemDelimitationItem) { } else if (LastTagRead == DicomTag.SequenceDelimitationItem) { SequenceRecord rec2 = _sqrs.Pop(); if (rec2.Current == null) { rec2.Parent[rec.Tag].SetNullValue(); } } if (rec.Len != _undefinedLength) { long end = rec.Pos + 8 + rec.Len; if (_syntax.ExplicitVr) { end += 2 + 2; } if (_stream.Position >= end) { _sqrs.Pop(); } } } else { if (_len == _undefinedLength) { if (_vr.Equals(DicomVr.UNvr)) { if (!_syntax.ExplicitVr) { _vr = DicomVr.SQvr; LastTagRead = LastTagRead.IsPrivate ? new DicomTag(LastTagRead.TagValue, "Private Tag", "PrivateTag", DicomVr.SQvr, false, 1, uint.MaxValue, false) : new DicomTag(LastTagRead.TagValue, "Unknown Tag", "UnknownTag", DicomVr.SQvr, false, 1, uint.MaxValue, false); } else { // To handle this case, we'd have to add a new mechanism to transition the parser to implicit VR parsing, // and then return back to implicit once the parsing of the SQ is complete. Platform.Log(LogLevel.Error, "Encountered unknown tag {0}, encoded as undefined length in an Explicit VR transfer syntax at offset {1}. Unable to parse.", LastTagRead, _stream.Position); return(DicomReadStatus.UnknownError); } } if (_vr.Equals(DicomVr.SQvr)) { SequenceRecord rec = new SequenceRecord { Parent = _sqrs.Count > 0 ? _sqrs.Peek().Current : Dataset, Current = null, Tag = LastTagRead, Len = _undefinedLength }; _sqrs.Push(rec); } else { _fragment = new DicomFragmentSequence(LastTagRead); } } else { if (_vr.Equals(DicomVr.SQvr)) { if (_len == 0) { DicomAttributeCollection ds; if (_sqrs.Count > 0) { SequenceRecord rec = _sqrs.Peek(); ds = rec.Current; } else { ds = Dataset; } ds[LastTagRead].SetNullValue(); } else { SequenceRecord rec = new SequenceRecord { Len = _len, Pos = _pos, Tag = LastTagRead, Parent = _sqrs.Count > 0 ? _sqrs.Peek().Current : Dataset }; _sqrs.Push(rec); } } else { if (_remain < _len) { return(NeedMoreData(_len - _remain)); } if ((LastTagRead.TagValue == DicomTags.PixelData) && Flags.IsSet(options, DicomReadOptions.DoNotStorePixelDataInDataSet)) { // Skip PixelData !! if (_stream.CanSeek) { _stream.Seek((int)_len, SeekOrigin.Current); } else { ConsumeStreamBytes(_stream, _len); } _remain -= _len; BytesRead += _len; } else if ((LastTagRead.TagValue == DicomTags.PixelData) && Flags.IsSet(options, DicomReadOptions.StorePixelDataReferences)) { var reference = new FileReference(StreamOpener, _stream.Position, _len, _endian, LastTagRead.VR); if (_stream.CanSeek) { _stream.Seek((int)_len, SeekOrigin.Current); } else { ConsumeStreamBytes(_stream, _len); } DicomAttribute elem; if (LastTagRead.VR.Equals(DicomVr.OWvr)) { elem = new DicomAttributeOW(LastTagRead, reference); } else if (LastTagRead.VR.Equals(DicomVr.OBvr)) { elem = new DicomAttributeOB(LastTagRead, reference); } else if (LastTagRead.VR.Equals(DicomVr.ODvr)) { elem = new DicomAttributeOD(LastTagRead, reference); } else { elem = new DicomAttributeOF(LastTagRead, reference); } if (_sqrs.Count > 0) { SequenceRecord rec = _sqrs.Peek(); DicomAttributeCollection ds = rec.Current; ds[LastTagRead] = elem; if (rec.Curlen != _undefinedLength) { long end = rec.Curpos + rec.Curlen; if (_stream.Position >= end) { rec.Current = null; } } } else { Dataset[LastTagRead] = elem; } _remain -= _len; BytesRead += _len; } else { ByteBuffer bb = new ByteBuffer(_len); // If the tag is impacted by specific character set, // set the encoding properly. if (LastTagRead.VR.SpecificCharacterSet) { if (_sqrs.Count > 0) { SequenceRecord rec = _sqrs.Peek(); bb.SpecificCharacterSet = rec.Current.SpecificCharacterSet; } else { bb.SpecificCharacterSet = Dataset.SpecificCharacterSet; } } if (LastTagRead.VR.Equals(DicomVr.UNvr) && !SaveTagRead.VR.Equals(DicomVr.UNvr) && !SaveTagRead.VR.Equals(DicomVr.SQvr) && Flags.IsSet(options, DicomReadOptions.UseDictionaryForExplicitUN)) { LastTagRead = SaveTagRead; bb.Endian = Endian.Little; } else { bb.Endian = _endian; } bb.CopyFrom(_stream, (int)_len); DicomAttribute elem = LastTagRead.CreateDicomAttribute(bb); _remain -= _len; BytesRead += _len; if (_sqrs.Count > 0) { SequenceRecord rec = _sqrs.Peek(); DicomAttributeCollection ds = rec.Current; if (elem.Tag.TagValue == DicomTags.SpecificCharacterSet) { ds.SpecificCharacterSet = elem.ToString(); } if (LastTagRead.Element == 0x0000) { if (Flags.IsSet(options, DicomReadOptions.KeepGroupLengths)) { ds[LastTagRead] = elem; } } else { ds[LastTagRead] = elem; } if (rec.Curlen != _undefinedLength) { long end = rec.Curpos + rec.Curlen; if (_stream.Position >= end) { rec.Current = null; } } } else { if (LastTagRead.TagValue == DicomTags.FileMetaInformationGroupLength) { // Save the end of the group 2 elements, so that we can automatically // check and change our transfer syntax when needed. _inGroup2 = true; uint group2Len; elem.TryGetUInt32(0, out group2Len); _endGroup2 = BytesRead + group2Len; } else if (LastTagRead.TagValue == DicomTags.SpecificCharacterSet) { Dataset.SpecificCharacterSet = elem.ToString(); } if (LastTagRead.Element == 0x0000) { if (Flags.IsSet(options, DicomReadOptions.KeepGroupLengths)) { Dataset[LastTagRead] = elem; } } else { Dataset[LastTagRead] = elem; } } } } } } LastTagRead = null; _vr = null; _len = _undefinedLength; } return(DicomReadStatus.Success); } catch (EndOfStreamException e) { // should never happen Platform.Log(LogLevel.Error, "Unexpected exception when reading file: {0}", e.ToString()); return(DicomReadStatus.UnknownError); } }
public DicomReadStatus Read(DicomTag stopAtTag, DicomReadOptions options) { if (stopAtTag == null) stopAtTag = new DicomTag(0xFFFFFFFF, "Bogus Tag", "BogusTag", DicomVr.UNvr, false, 1, 1, false); // Counters: // _remain - bytes remaining in stream // _bytes - estimates bytes to end of dataset // _read - number of bytes read from stream try { BytesNeeded = 0; _remain = _stream.Length - _stream.Position; while (_remain > 0) { if (_inGroup2 && BytesRead >= _endGroup2) { _inGroup2 = false; // Only change if we're still reading the meta info if (Dataset.StartTagValue < DicomTags.TransferSyntaxUid) { TransferSyntax group2Syntax = TransferSyntax.GetTransferSyntax( Dataset[DicomTags.TransferSyntaxUid].GetString(0, String.Empty)); if (group2Syntax == null) throw new DicomException("Unsupported transfer syntax in group 2 elements"); TransferSyntax = group2Syntax; } } uint tagValue; if (LastTagRead == null) { if (_remain < 4) return NeedMoreData(4); _pos = _stream.Position; ushort g = _reader.ReadUInt16(); ushort e = _reader.ReadUInt16(); tagValue = DicomTag.GetTagValue(g, e); if (DicomTag.IsPrivateGroup(g) && e > 0x00ff) { SaveTagRead = LastTagRead = DicomTagDictionary.GetDicomTag(g, e) ?? new DicomTag((uint) g << 16 | e, "Private Tag", "PrivateTag", DicomVr.UNvr, false, 1, uint.MaxValue, false); } else { if (e == 0x0000) SaveTagRead = LastTagRead = new DicomTag((uint)g << 16 | e, "Group Length", "GroupLength", DicomVr.ULvr, false, 1, 1, false); else { SaveTagRead = LastTagRead = DicomTagDictionary.GetDicomTag(g, e) ?? new DicomTag((uint) g << 16 | e, "Private Tag", "PrivateTag", DicomVr.UNvr, false, 1, uint.MaxValue, false); } } _remain -= 4; BytesEstimated += 4; BytesRead += 4; } else tagValue = LastTagRead.TagValue; if ((tagValue >= stopAtTag.TagValue) && (_sqrs.Count == 0)) // only exit in root message when after stop tag return DicomReadStatus.Success; bool twoByteLength; if (_vr == null) { if (_syntax.ExplicitVr) { if (LastTagRead == DicomTag.Item || LastTagRead == DicomTag.ItemDelimitationItem || LastTagRead == DicomTag.SequenceDelimitationItem) { _vr = DicomVr.NONE; twoByteLength = _vr.Is16BitLengthField; } else { if (_remain < 2) return NeedMoreData(2); string vr = new string(_reader.ReadChars(2)); _vr = DicomVr.GetVR(vr); twoByteLength = _vr.Is16BitLengthField; _remain -= 2; BytesEstimated += 2; BytesRead += 2; if (LastTagRead.VR.Equals(DicomVr.UNvr)) { LastTagRead = new DicomTag(LastTagRead.TagValue, "Private Tag", "PrivateTag", _vr, false, 1, uint.MaxValue, false); if (vr.Equals("??")) twoByteLength = true; } else if (!LastTagRead.VR.Equals(_vr)) { if (!vr.Equals(" ")) { DicomTag tag = new DicomTag(LastTagRead.TagValue, LastTagRead.Name, LastTagRead.VariableName, _vr, LastTagRead.MultiVR, LastTagRead.VMLow, LastTagRead.VMHigh, LastTagRead.Retired); LastTagRead = tag; ; // TODO, log something } } } } else { _vr = LastTagRead.VR; twoByteLength = _vr.Is16BitLengthField; } if (_vr == DicomVr.UNvr) { if (LastTagRead.IsPrivate) { if (LastTagRead.Element <= 0x00ff && LastTagRead.Element >= 0x0010) { // Reset the tag with the right VR and a more descriptive name. LastTagRead = new DicomTag(LastTagRead.TagValue, "Private Creator Code", "PrivateCreatorCode", DicomVr.LOvr, false, 1, uint.MaxValue, false); // private creator id // Only set the VR to LO for Implicit VR, if we do it for // Explicit VR syntaxes, we would incorrectly read the tag // length below. if (!_syntax.ExplicitVr) _vr = DicomVr.LOvr; } else if (_stream.CanSeek && Flags.IsSet(options, DicomReadOptions.AllowSeekingForContext)) { // attempt to identify private sequence by checking if the tag has // an undefined length long pos = _stream.Position; int bytesToCheck = _syntax.ExplicitVr ? 6 : 4; if (_remain >= bytesToCheck) { if (_syntax.ExplicitVr) _reader.ReadUInt16(); uint l = _reader.ReadUInt32(); if (l == UndefinedLength) _vr = DicomVr.SQvr; } _stream.Position = pos; } } } } else twoByteLength = _vr.Is16BitLengthField; // Read the value length if (_len == UndefinedLength) { if (_syntax.ExplicitVr) { if (LastTagRead == DicomTag.Item || LastTagRead == DicomTag.ItemDelimitationItem || LastTagRead == DicomTag.SequenceDelimitationItem) { if (_remain < 4) return NeedMoreData(4); _len = _reader.ReadUInt32(); _remain -= 4; BytesEstimated += 4; BytesRead += 4; } else { if (twoByteLength) { if (_remain < 2) return NeedMoreData(2); _len = _reader.ReadUInt16(); _remain -= 2; BytesEstimated += 2; BytesRead += 2; } else { if (_remain < 6) return NeedMoreData(6); _reader.ReadByte(); _reader.ReadByte(); _len = _reader.ReadUInt32(); _remain -= 6; BytesEstimated += 6; BytesRead += 6; } } } else { if (_remain < 4) return NeedMoreData(4); _len = _reader.ReadUInt32(); _remain -= 4; BytesEstimated += 4; BytesRead += 4; } if ((_len != UndefinedLength) && !_vr.Equals(DicomVr.SQvr) && !(LastTagRead.Equals(DicomTag.Item) && _fragment == null)) BytesEstimated += _len; } // If we have a private creator code, set the VR to LO, because // that is what it is. We must do this after we read the length // so that the 32 bit length is read properly. if ((LastTagRead.IsPrivate) && (_vr.Equals(DicomVr.UNvr)) && (LastTagRead.Element <= 0x00ff)) _vr = DicomVr.LOvr; if (_fragment != null) { // In the middle of parsing pixels if (LastTagRead == DicomTag.Item) { if (_remain < _len) return NeedMoreData(_remain - _len); if (Flags.IsSet(options, DicomReadOptions.StorePixelDataReferences) && _fragment.HasOffsetTable) { FileReference reference = new FileReference(Filename, _stream.Position, _len, _endian, DicomVr.OBvr); DicomFragment fragment = new DicomFragment(reference); _fragment.AddFragment(fragment); _stream.Seek(_len, SeekOrigin.Current); } else { ByteBuffer data = new ByteBuffer(_endian, _len); data.CopyFrom(_stream, (int) _len); if (!_fragment.HasOffsetTable) _fragment.SetOffsetTable(data); else { DicomFragment fragment = new DicomFragment(data); _fragment.AddFragment(fragment); } } _remain -= _len; BytesRead += _len; } else if (LastTagRead == DicomTag.SequenceDelimitationItem) { Dataset[_fragment.Tag] = _fragment; _fragment = null; } else { Platform.Log(LogLevel.Error, "Encountered unexpected tag in stream: {0}", LastTagRead.ToString()); // unexpected tag return DicomReadStatus.UnknownError; } } else if (_sqrs.Count > 0 && (LastTagRead == DicomTag.Item || LastTagRead == DicomTag.ItemDelimitationItem || LastTagRead == DicomTag.SequenceDelimitationItem)) { SequenceRecord rec = _sqrs.Peek(); if (LastTagRead.Equals(DicomTag.Item)) { if (_len != UndefinedLength) { if (_len > _remain) return NeedMoreData(_remain - _len); } DicomSequenceItem ds; if (rec.Tag.TagValue.Equals(DicomTags.DirectoryRecordSequence)) { DirectoryRecordSequenceItem dr = new DirectoryRecordSequenceItem { Offset = (uint) _pos }; ds = dr; } else ds = new DicomSequenceItem(); rec.Current = ds; if (rec.Tag.VR.Equals(DicomVr.UNvr)) { DicomTag tag = new DicomTag(rec.Tag.TagValue, rec.Tag.Name, rec.Tag.VariableName, DicomVr.SQvr, rec.Tag.MultiVR, rec.Tag.VMLow, rec.Tag.VMHigh, rec.Tag.Retired); rec.Parent[tag].AddSequenceItem(ds); } else rec.Parent[rec.Tag].AddSequenceItem(ds); // Specific character set is inherited, save it. It will be overwritten // if a new value of the tag is encountered in the sequence. rec.Current.SpecificCharacterSet = rec.Parent.SpecificCharacterSet; // save the sequence length rec.Curpos = _pos + 8; rec.Curlen = _len; _sqrs.Pop(); _sqrs.Push(rec); if (_len != UndefinedLength) { ByteBuffer data = new ByteBuffer(_endian, _len); data.CopyFrom(_stream, (int)_len); data.Stream.Position = 0; _remain -= _len; BytesRead += _len; DicomStreamReader idsr = new DicomStreamReader(data.Stream) { Dataset = ds, TransferSyntax = rec.Tag.VR.Equals(DicomVr.UNvr) ? TransferSyntax.ImplicitVrLittleEndian : _syntax, Filename = Filename }; DicomReadStatus stat = idsr.Read(null, options); if (stat != DicomReadStatus.Success) { Platform.Log(LogLevel.Error, "Unexpected parsing error ({0}) when reading sequence attribute: {1}.", stat, rec.Tag.ToString()); return stat; } } } else if (LastTagRead == DicomTag.ItemDelimitationItem) { } else if (LastTagRead == DicomTag.SequenceDelimitationItem) { SequenceRecord rec2 = _sqrs.Pop(); if (rec2.Current==null) rec2.Parent[rec.Tag].SetNullValue(); } if (rec.Len != UndefinedLength) { long end = rec.Pos + 8 + rec.Len; if (_syntax.ExplicitVr) end += 2 + 2; if (_stream.Position >= end) { _sqrs.Pop(); } } } else { if (_len == UndefinedLength) { if (_vr.Equals(DicomVr.UNvr)) { if (!_syntax.ExplicitVr) { _vr = DicomVr.SQvr; LastTagRead = LastTagRead.IsPrivate ? new DicomTag(LastTagRead.TagValue, "Private Tag", "PrivateTag", DicomVr.SQvr, false, 1, uint.MaxValue, false) : new DicomTag(LastTagRead.TagValue, "Unknown Tag", "UnknownTag", DicomVr.SQvr, false, 1, uint.MaxValue, false); } else { // To handle this case, we'd have to add a new mechanism to transition the parser to implicit VR parsing, // and then return back to implicit once the parsing of the SQ is complete. Platform.Log(LogLevel.Error, "Encountered unknown tag {0}, encoded as undefined length in an Explicit VR transfer syntax at offset {1}. Unable to parse.", LastTagRead, _stream.Position); return DicomReadStatus.UnknownError; } } if (_vr.Equals(DicomVr.SQvr)) { SequenceRecord rec = new SequenceRecord { Parent = _sqrs.Count > 0 ? _sqrs.Peek().Current : Dataset, Current = null, Tag = LastTagRead, Len = UndefinedLength }; _sqrs.Push(rec); } else { _fragment = new DicomFragmentSequence(LastTagRead); Dataset.LoadDicomFields(_fragment); } } else { if (_vr.Equals(DicomVr.SQvr)) { if (_len == 0) { DicomAttributeCollection ds; if (_sqrs.Count > 0) { SequenceRecord rec = _sqrs.Peek(); ds = rec.Current; } else ds = Dataset; ds[LastTagRead].SetNullValue(); } else { SequenceRecord rec = new SequenceRecord { Len = _len, Pos = _pos, Tag = LastTagRead, Parent = _sqrs.Count > 0 ? _sqrs.Peek().Current : Dataset }; _sqrs.Push(rec); } } else { if (_remain < _len) return NeedMoreData(_len - _remain); if ((LastTagRead.TagValue == DicomTags.PixelData) && Flags.IsSet(options, DicomReadOptions.DoNotStorePixelDataInDataSet)) { // Skip PixelData !! _stream.Seek((int) _len, SeekOrigin.Current); _remain -= _len; BytesRead += _len; } else if ((LastTagRead.TagValue == DicomTags.PixelData) && Flags.IsSet(options, DicomReadOptions.StorePixelDataReferences)) { FileReference reference = new FileReference(Filename, _stream.Position, _len, _endian, LastTagRead.VR); _stream.Seek((int) _len, SeekOrigin.Current); if (LastTagRead.VR.Equals(DicomVr.OWvr)) { DicomAttributeOW elem = new DicomAttributeOW(LastTagRead, reference); Dataset[LastTagRead] = elem; } else if (LastTagRead.VR.Equals(DicomVr.OBvr)) { DicomAttributeOB elem = new DicomAttributeOB(LastTagRead, reference); Dataset[LastTagRead] = elem; } else { DicomAttributeOF elem = new DicomAttributeOF(LastTagRead, reference); Dataset[LastTagRead] = elem; } _remain -= _len; BytesRead += _len; } else { ByteBuffer bb = new ByteBuffer(_len); // If the tag is impacted by specific character set, // set the encoding properly. if (LastTagRead.VR.SpecificCharacterSet) { if (_sqrs.Count > 0) { SequenceRecord rec = _sqrs.Peek(); bb.SpecificCharacterSet = rec.Current.SpecificCharacterSet; } else { bb.SpecificCharacterSet = Dataset.SpecificCharacterSet; } } if (LastTagRead.VR.Equals(DicomVr.UNvr) && !SaveTagRead.VR.Equals(DicomVr.UNvr) && !SaveTagRead.VR.Equals(DicomVr.SQvr) && Flags.IsSet(options, DicomReadOptions.UseDictionaryForExplicitUN)) { LastTagRead = SaveTagRead; bb.Endian = Endian.Little; } else { bb.Endian = _endian; } bb.CopyFrom(_stream, (int) _len); DicomAttribute elem = LastTagRead.CreateDicomAttribute(bb); _remain -= _len; BytesRead += _len; if (_sqrs.Count > 0) { SequenceRecord rec = _sqrs.Peek(); DicomAttributeCollection ds = rec.Current; if (elem.Tag.TagValue == DicomTags.SpecificCharacterSet) { ds.SpecificCharacterSet = elem.ToString(); } if (LastTagRead.Element == 0x0000) { if (Flags.IsSet(options, DicomReadOptions.KeepGroupLengths)) ds[LastTagRead] = elem; } else ds[LastTagRead] = elem; if (rec.Curlen != UndefinedLength) { long end = rec.Curpos + rec.Curlen; if (_stream.Position >= end) { rec.Current = null; } } } else { if (LastTagRead.TagValue == DicomTags.FileMetaInformationGroupLength) { // Save the end of the group 2 elements, so that we can automatically // check and change our transfer syntax when needed. _inGroup2 = true; uint group2Len; elem.TryGetUInt32(0, out group2Len); _endGroup2 = BytesRead + group2Len; } else if (LastTagRead.TagValue == DicomTags.SpecificCharacterSet) { Dataset.SpecificCharacterSet = elem.ToString(); } if (LastTagRead.Element == 0x0000) { if (Flags.IsSet(options, DicomReadOptions.KeepGroupLengths)) Dataset[LastTagRead] = elem; } else Dataset[LastTagRead] = elem; } } } } } LastTagRead = null; _vr = null; _len = UndefinedLength; } return DicomReadStatus.Success; } catch (EndOfStreamException e) { // should never happen Platform.Log(LogLevel.Error, "Unexpected exception when reading file: {0}", e.ToString()); return DicomReadStatus.UnknownError; } }