/// <summary> /// Method for adding a <see cref="DicomSequenceItem"/> to an attributes value. /// </summary> /// <param name="item">The <see cref="DicomSequenceItem"/> to add to the attribute.</param> /// <remarks> /// This method is value for <see cref="DicomAttributeSQ"/> attributes only. /// </remarks> public override void AddSequenceItem(DicomSequenceItem item) { if (_values == null) { _values = new DicomSequenceItem[1]; _values[0] = item; } else { DicomSequenceItem[] oldValues = _values; _values = new DicomSequenceItem[oldValues.Length + 1]; oldValues.CopyTo(_values, 0); _values[oldValues.Length] = item; } if (item.SpecificCharacterSet == null) item.SpecificCharacterSet = ParentCollection.SpecificCharacterSet; base.Count = _values.Length; base.StreamLength = (uint)base.Count; }
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; } }
/// <summary> /// Initializes a new instance of the <see cref="VoiLutMacro"/> class. /// </summary> /// <param name="dicomSequenceItem">The dicom sequence item.</param> public VoiLutMacro(DicomSequenceItem dicomSequenceItem) : base(dicomSequenceItem) {}
/// <summary> /// Initializes a new instance of the <see cref="VoiLutSequenceItem"/> class. /// </summary> /// <param name="dicomSequenceItem">The dicom sequence item.</param> public VoiLutSequenceItem(DicomSequenceItem dicomSequenceItem) : base(dicomSequenceItem) {}
/// <summary> /// Method for adding a <see cref="DicomSequenceItem"/> to an attributes value. /// </summary> /// <remarks> /// This method is value for <see cref="DicomAttributeSQ"/> attributes only. /// </remarks> /// <param name="item">The <see cref="DicomSequenceItem"/> to add to the attribute.</param> public virtual void AddSequenceItem(DicomSequenceItem item) { throw new DicomException(SR.InvalidType); }
/// <summary> /// Update an <see cref="DicomAttributeCollection"/> with pixel data related tags. /// </summary> /// <param name="dataset">The collection to update.</param> public override void UpdateAttributeCollection(DicomAttributeCollection dataset) { if (dataset.Contains(DicomTags.NumberOfFrames) || NumberOfFrames > 1) dataset[DicomTags.NumberOfFrames].SetInt32(0, NumberOfFrames); if (dataset.Contains(DicomTags.PlanarConfiguration)) dataset[DicomTags.PlanarConfiguration].SetInt32(0, PlanarConfiguration); if (dataset.Contains(DicomTags.LossyImageCompression) || LossyImageCompression.Length > 0) dataset[DicomTags.LossyImageCompression].SetString(0, LossyImageCompression); if (dataset.Contains(DicomTags.LossyImageCompressionRatio) || (LossyImageCompressionRatio != 1.0f && LossyImageCompressionRatio != 0.0f)) dataset[DicomTags.LossyImageCompressionRatio].SetFloat32(0, LossyImageCompressionRatio); if (dataset.Contains(DicomTags.LossyImageCompressionMethod) || LossyImageCompressionMethod.Length > 0) dataset[DicomTags.LossyImageCompressionMethod].SetString(0, LossyImageCompressionMethod); if (dataset.Contains(DicomTags.DerivationDescription) || DerivationDescription.Length > 0) { string currentValue = dataset[DicomTags.DerivationDescription].ToString(); dataset[DicomTags.DerivationDescription].SetStringValue(DerivationDescription); if (!currentValue.Equals(DerivationDescription)) { DicomSequenceItem item = new DicomSequenceItem(); CodeSequenceMacro macro = new CodeSequenceMacro(item); macro.CodeMeaning = "Lossy Compression"; macro.CodeValue = "113040"; macro.CodingSchemeDesignator = "DCM"; macro.ContextGroupVersion = new DateTime(2005, 8, 22); macro.ContextIdentifier = "7203"; macro.MappingResource = "DCMR"; dataset[DicomTags.DerivationCodeSequence].AddSequenceItem(item); } } if (dataset.Contains(DicomTags.RescaleSlope) || DecimalRescaleSlope != 1.0M || DecimalRescaleIntercept != 0.0M) dataset[DicomTags.RescaleSlope].SetString(0, RescaleSlope); if (dataset.Contains(DicomTags.RescaleIntercept) || DecimalRescaleSlope != 1.0M || DecimalRescaleIntercept != 0.0M) dataset[DicomTags.RescaleIntercept].SetString(0, RescaleIntercept); if (dataset.Contains(DicomTags.WindowCenter) || LinearVoiLuts.Count > 0) Window.SetWindowCenterAndWidth(dataset, LinearVoiLuts); //Remove the palette color lut, if the pixels were translated to RGB if (dataset.Contains(DicomTags.RedPaletteColorLookupTableData) && dataset.Contains(DicomTags.BluePaletteColorLookupTableData) && dataset.Contains(DicomTags.GreenPaletteColorLookupTableData) && !HasPaletteColorLut) { dataset.RemoveAttribute(DicomTags.BluePaletteColorLookupTableDescriptor); dataset.RemoveAttribute(DicomTags.BluePaletteColorLookupTableData); dataset.RemoveAttribute(DicomTags.RedPaletteColorLookupTableDescriptor); dataset.RemoveAttribute(DicomTags.RedPaletteColorLookupTableData); dataset.RemoveAttribute(DicomTags.GreenPaletteColorLookupTableDescriptor); dataset.RemoveAttribute(DicomTags.GreenPaletteColorLookupTableData); } dataset.SaveDicomFields(this); dataset[DicomTags.PixelData] = _sq; }