private static DicomTag GetTagFromAttributeNode(XmlNode attributeNode) { String tag = attributeNode.Attributes["Tag"].Value; DicomTag theTag; if (tag.StartsWith("$")) { theTag = DicomTagDictionary.GetDicomTag(tag.Substring(1)); } else { uint tagValue = uint.Parse(tag, NumberStyles.HexNumber); theTag = DicomTagDictionary.GetDicomTag(tagValue); DicomVr xmlVr = DicomVr.GetVR(attributeNode.Attributes["VR"].Value); if (theTag == null) { theTag = new DicomTag(tagValue, "Unknown tag", "UnknownTag", xmlVr, false, 1, uint.MaxValue, false); } if (!theTag.VR.Equals(xmlVr)) { theTag = new DicomTag(tagValue, theTag.Name, theTag.VariableName, xmlVr, theTag.MultiVR, theTag.VMLow, theTag.VMHigh, theTag.Retired); } } return(theTag); }
private static DicomTag CreateTag(int id, DicomVr vr) { uint tagValue = (uint)id; tagValue = ((((tagValue >> 16) << 1) + 0x11) << 16) + (tagValue & 0x0000ffff); // this generates a serial private tag return(new DicomTag(tagValue, string.Format("({0:x4},{1:x4})", (tagValue >> 16), (tagValue & 0x0000ffff)), string.Format("tag{0:x8}", tagValue), vr, true, 0, 10, false)); }
public void TestAttributeFD() { DicomVr vr = DicomVr.FDvr; SetCurrentCulture(); try { //there seems to invariably be some precision loss with floats //SetAndAssertFloat32(vr, "0", 0.00000000f); //SetAndAssertFloat32(vr, "2.048", 2.048f); //SetAndAssertFloat32(vr, "-2.048", -2.048f); //SetAndAssertFloat32(vr, "12345.6", 12345.6f); //SetAndAssertFloat32(vr, "-12345.6", -12345.6f); //SetAndAssertFloat32(vr, "1.797693E+38", 1.797693e38f); //SetAndAssertFloat32(vr, "-1.797693E+38", -1.797693e38f); //SetAndAssertFloat32(vr, "1.797693E-38", 1.797693e-38f); //SetAndAssertFloat32(vr, "-1.797693E-38", -1.797693e-38f); SetAndAssertFloat64(vr, "0", 0.00000000); SetAndAssertFloat64(vr, "12.3456789", 12.3456789); SetAndAssertFloat64(vr, "-12.3456789", -12.3456789); SetAndAssertFloat64(vr, "12345.6789", 12345.6789); SetAndAssertFloat64(vr, "-12345.6789", -12345.6789); SetAndAssertFloat64(vr, "1.7976931349E+38", 1.7976931349e38); SetAndAssertFloat64(vr, "-1.797693135E+38", -1.797693135e38); SetAndAssertFloat64(vr, "1.7976931349E-38", 1.7976931349e-38); SetAndAssertFloat64(vr, "-1.797693135E-38", -1.797693135e-38); } finally { ResetCurrentCulture(); } }
internal FileReference(string file, long offset, long length, Endian endian, DicomVr vr) { _filename = file; _offset = offset; _length = length; _endian = endian; _vr = vr; }
private static void SetAndAssertDateTime(DicomVr vr, DateTime value, string expected) { DicomAttributeCollection dataset = new DicomAttributeCollection(); DicomTag tag = CreateTag(1, vr); dataset[tag].SetDateTime(0, value); Trace.WriteLine(string.Format("Testing {0} attribute with {1} (set as DateTime)", vr.Name, value)); Trace.WriteLine(string.Format("Attribute Value is: \"{0}\"", dataset[tag].ToString())); Assert.AreEqual(value, dataset[tag].GetDateTime(0)); Assert.AreEqual(expected, dataset[tag].ToString()); }
protected virtual IDicomXmlVrWriter CreateDefualtVrWriter(DicomVr dicomVr) { IDicomXmlVrWriter writer = null; if (!_defaultVrWriters.TryGetValue(dicomVr.Name, out writer)) { throw new ApplicationException("Default VR writer not registered!"); } return(writer); }
private static IEnumerable <DicomTag> GetTags(IList <uint> tags, DicomVr vr) { var dicomTags = new List <DicomTag>(); for (int i = 0; i < tags.Count; ++i) { var tag = tags[i]; var theVr = i < tags.Count - 1 ? DicomVr.SQvr : vr; dicomTags.Add(NewTag(tag, theVr)); } return(dicomTags); }
/// <summary> /// Fixes the VR of the specified DICOM tag, which is especially important for multi-VR tags. /// </summary> private static DicomTag FixVR(uint tag, DicomVr newVR) { var dicomTag = DicomTagDictionary.GetDicomTag(tag); if (dicomTag.VR == newVR) { return(dicomTag); } if (!dicomTag.MultiVR) { throw new ArgumentException("The specified DICOM tag does not support multiple VRs.", "tag"); } return(new DicomTag(dicomTag.TagValue, dicomTag.Name, dicomTag.VariableName, newVR, true, dicomTag.VMLow, dicomTag.VMHigh, dicomTag.Retired)); }
internal static bool IsWildcardCriterion(DicomVr vr, string criterion) { if (String.IsNullOrEmpty(criterion)) { return(false); } if (!IsWildcardCriterionAllowed(vr)) { return(false); } return(criterion.Contains("*") || criterion.Contains("?")); }
internal static DicomTag NewTag(uint tag, DicomVr vr) { var theTag = DicomTagDictionary.GetDicomTag(tag); if (theTag == null) { theTag = new DicomTag(tag, "Unknown tag", "UnknownTag", vr ?? DicomVr.UNvr, false, 1, uint.MaxValue, false); } else if (vr != null && !theTag.VR.Equals(vr)) { theTag = new DicomTag(tag, theTag.Name, theTag.VariableName, vr, theTag.MultiVR, theTag.VMLow, theTag.VMHigh, theTag.Retired); } return(theTag); }
private bool MatchVr(DicomAttribute element) { DicomVr elementVr = element.Tag.VR; if (!elementVr.Equals(DicomVr.DAvr) && !elementVr.Equals(DicomVr.TMvr) && !elementVr.Equals(DicomVr.DTvr)) { return(false); } if (HasWildcardMatching(element.ToString( ))) { return(false); } return(true); }
/// <summary> /// 获取VR类型 /// </summary> /// <returns></returns> private string GetVR() { try { _buffer.SetOrder(ByteOrder.BigEndian); _vr = _buffer.ReadUInt16(); _strVr = DicomVr.ToString(_vr); _buffer.SetOrder(ByteOrder.LittleEndian); return(_strVr); } catch (Exception ex) { Console.WriteLine(ex.Message); _buffer.Close(); return(_strVr + " GetVR ERROR"); } }
private static IEnumerable <DicomTag> GetTags(string path, DicomVr vr) { Platform.CheckForEmptyString(path, "path"); var dicomTags = new List <DicomTag>(); string[] groupElementValues = path.Split(_pathSeparators); for (int i = 0; i < groupElementValues.Length; ++i) { var groupElement = groupElementValues[i]; string[] values = groupElement.Split(_tagSeparator); if (values.Length != 2) { throw new ArgumentException(String.Format(_exceptionFormatInvalidTagPath, path)); } string group = values[0]; if (!group.StartsWith("(") || group.Length != 5) { throw new ArgumentException(String.Format(_exceptionFormatInvalidTagPath, path)); } string element = values[1]; if (!element.EndsWith(")") || element.Length != 5) { throw new ArgumentException(String.Format(_exceptionFormatInvalidTagPath, path)); } try { ushort groupValue = Convert.ToUInt16(group.TrimStart('('), 16); ushort elementValue = Convert.ToUInt16(element.TrimEnd(')'), 16); var theVr = i < groupElementValues.Length - 1 ? DicomVr.SQvr : vr; dicomTags.Add(NewTag(DicomTag.GetTagValue(groupValue, elementValue), theVr)); } catch { throw new ArgumentException(String.Format(_exceptionFormatInvalidTagPath, path)); } } return(dicomTags); }
/// <summary> /// 获取Group为0002的Tag占用的Length /// </summary> /// <returns></returns> private int GetLength0002() { try { if (DicomVr.IsLengthField16Bit(_vr)) { return(_buffer.ReadUInt16()); } _buffer.ReadUInt16(); return(_buffer.ReadInt32()); } catch (Exception ex) { Console.WriteLine(ex.Message); _buffer.Close(); return(-1); } }
public void TestAttributeSL() { DicomVr vr = DicomVr.SLvr; SetCurrentCulture(); try { SetAndAssertInt16(vr, "0", 0); SetAndAssertInt16(vr, "1", 1); SetAndAssertInt16(vr, "-1", -1); SetAndAssertInt16(vr, "32767", 32767); SetAndAssertInt16(vr, "-32768", -32768); SetAndAssertInt32(vr, "0", 0); SetAndAssertInt32(vr, "1", 1); SetAndAssertInt32(vr, "-1", -1); SetAndAssertInt32(vr, "2147483647", 2147483647); SetAndAssertInt32(vr, "-2147483648", -2147483648); SetAndAssertInt64(vr, "0", 0); SetAndAssertInt64(vr, "1", 1); SetAndAssertInt64(vr, "-1", -1); SetAndAssertInt64(vr, "2147483647", 2147483647); SetAndAssertInt64(vr, "-2147483648", -2147483648); SetAndAssertUInt16(vr, "0", 0); SetAndAssertUInt16(vr, "1", 1); SetAndAssertUInt16(vr, "65535", 65535); SetAndAssertUInt32(vr, "0", 0); SetAndAssertUInt32(vr, "1", 1); SetAndAssertUInt32(vr, "2147483647", 2147483647); SetAndAssertUInt64(vr, "0", 0); SetAndAssertUInt64(vr, "1", 1); SetAndAssertUInt64(vr, "2147483647", 2147483647); } finally { ResetCurrentCulture(); } }
public static string GetValue(ByteBuffer buffer, int vr, int length) { if (DicomVr.IsStringValue(vr)) { return(buffer.ReadBytesToString(length)); } switch (vr) { case DicomVr.AT: return(GetValueAT(buffer, length)); case DicomVr.FD: return(GetValueFD(buffer, length)); case DicomVr.FL: return(GetValueFL(buffer, length)); case DicomVr.OB: case DicomVr.OW: case DicomVr.UN: return(GetValueOB(buffer, length)); case DicomVr.SL: return(GetValueSL(buffer, length)); case DicomVr.SQ: return(GetValueSQ(buffer, length)); case DicomVr.SS: return(GetValueSS(buffer, length)); case DicomVr.UL: return(GetValueUL(buffer, length)); case DicomVr.US: return(GetValueUS(buffer, length)); default: return("GetValue ERROR"); } }
public void TestAttributeUS() { DicomVr vr = DicomVr.USvr; SetCurrentCulture(); try { SetAndAssertInt16(vr, "0", 0); SetAndAssertInt16(vr, "1", 1); SetAndAssertInt16(vr, "32767", 32767); SetAndAssertUInt16(vr, "0", 0); SetAndAssertUInt16(vr, "1", 1); SetAndAssertUInt16(vr, "65535", 65535); } finally { ResetCurrentCulture(); } }
public void TestAttributeDT() { DicomVr vr = DicomVr.DTvr; SetCurrentCulture(); try { SetAndAssertDateTime(vr, @"20090101000000+0000", new DateTime(2009, 1, 1, 0, 0, 0, DateTimeKind.Utc)); SetAndAssertDateTime(vr, @"20080101000000-0500", new DateTime(2007, 12, 31, 19, 0, 0, DateTimeKind.Utc)); SetAndAssertDateTime(vr, @"20070101000000+0500", new DateTime(2007, 1, 1, 5, 0, 0, DateTimeKind.Utc)); SetAndAssertDateTime(vr, @"20060101000000-0000", new DateTime(2006, 1, 1, 0, 0, 0, DateTimeKind.Utc)); SetAndAssertDateTime(vr, new DateTime(2009, 1, 2, 3, 4, 5, 6, DateTimeKind.Utc), "20090102030405.006000"); SetAndAssertDateTime(vr, new DateTime(2009, 1, 2, 3, 4, 5, 6, DateTimeKind.Local), "20090102030405.006000"); } finally { ResetCurrentCulture(); } }
public void TestAttributeFL() { DicomVr vr = DicomVr.FLvr; SetCurrentCulture(); try { SetAndAssertFloat32(vr, "0", 0.00000000f); SetAndAssertFloat32(vr, "2.048", 2.048f); SetAndAssertFloat32(vr, "-2.048", -2.048f); SetAndAssertFloat32(vr, "12345.6", 12345.6f); SetAndAssertFloat32(vr, "-12345.6", -12345.6f); SetAndAssertFloat32(vr, "1.797693E+38", 1.797693e38f); SetAndAssertFloat32(vr, "-1.797693E+38", -1.797693e38f); SetAndAssertFloat32(vr, "1.797693E-38", 1.797693e-38f); SetAndAssertFloat32(vr, "-1.797693E-38", -1.797693e-38f); } finally { ResetCurrentCulture(); } }
private static void ConvertValue(DicomAttribute element, XmlWriter writer) { DicomVr dicomVr = element.Tag.VR; for (int index = 0; index < element.Count; index++) { writer.WriteStartElement("Value"); WriteNumberAttrib(writer, index); if (dicomVr.Equals(DicomVr.ATvr)) { writer.WriteString(element.GetString(index, string.Empty)); //TODO: check standard } else { writer.WriteString(element.GetString(index, string.Empty)); } writer.WriteEndElement( ); } }
public void TestAttributeSS() { DicomVr vr = DicomVr.SSvr; SetCurrentCulture(); try { SetAndAssertInt16(vr, "0", 0); SetAndAssertInt16(vr, "1", 1); SetAndAssertInt16(vr, "-1", -1); SetAndAssertInt16(vr, "32767", 32767); SetAndAssertInt16(vr, "-32768", -32768); SetAndAssertUInt16(vr, "0", 0); SetAndAssertUInt16(vr, "1", 1); SetAndAssertUInt16(vr, "32767", 32767); } finally { ResetCurrentCulture(); } }
private static void SetAndAssertFloat64(DicomVr vr, string szValue, double dValue) { DicomAttributeCollection dataset = new DicomAttributeCollection(); DicomTag tag = CreateTag(1, vr); dataset[tag].SetStringValue(szValue); Trace.WriteLine(string.Format("Testing {0} attribute with {1} (set as string)", vr.Name, szValue)); Trace.WriteLine(string.Format("Attribute Value is: \"{0}\"", dataset[tag].ToString())); Assert.AreEqual(szValue, dataset[tag].ToString(), "SetStringValue (double) vs dataset[tag].ToString()"); Assert.AreEqual(dValue, dataset[tag].GetFloat64(0, -123), "SetStringValue (double) vs dataset[tag].GetFloat64(...)"); dataset[tag].SetFloat64(0, dValue); Trace.WriteLine(string.Format("Testing {0} attribute with {1} (set as double)", vr.Name, dValue)); Trace.WriteLine(string.Format("Attribute Value is: \"{0}\"", dataset[tag].ToString())); Assert.AreEqual(szValue, dataset[tag].ToString(), "SetFloat64 vs dataset[tag].ToString()"); Assert.AreEqual(dValue, dataset[tag].GetFloat64(0, -123), "SetFloat64 vs dataset[tag].GetFloat64(...)"); dataset[tag].AppendFloat64(dValue); Trace.WriteLine(string.Format("Testing {0} attribute with {1} (append as double)", vr.Name, dValue)); Trace.WriteLine(string.Format("Attribute Value is: \"{0}\"", dataset[tag].ToString())); Assert.AreEqual(szValue + @"\" + szValue, dataset[tag].ToString(), "AppendFloat64 vs dataset[tag].ToString()"); Assert.AreEqual(dValue, dataset[tag].GetFloat64(1, -123), "AppendFloat64 vs dataset[tag].GetFloat64(...)"); }
private static void SetAndAssertUInt32(DicomVr vr, string szValue, uint uiValue) { DicomAttributeCollection dataset = new DicomAttributeCollection(); DicomTag tag = CreateTag(1, vr); dataset[tag].SetStringValue(szValue); Trace.WriteLine(string.Format("Testing {0} attribute with {1} (set as string)", vr.Name, szValue)); Trace.WriteLine(string.Format("Attribute Value is: \"{0}\"", dataset[tag].ToString())); Assert.AreEqual(szValue, dataset[tag].ToString(), "SetStringValue (uint) vs dataset[tag].ToString()"); Assert.AreEqual(uiValue, dataset[tag].GetUInt32(0, 123), "SetStringValue (uint) vs dataset[tag].GetUInt32(...)"); dataset[tag].SetUInt32(0, uiValue); Trace.WriteLine(string.Format("Testing {0} attribute with {1} (set as uint)", vr.Name, uiValue)); Trace.WriteLine(string.Format("Attribute Value is: \"{0}\"", dataset[tag].ToString())); Assert.AreEqual(szValue, dataset[tag].ToString(), "SetUInt32 vs dataset[tag].ToString()"); Assert.AreEqual(uiValue, dataset[tag].GetUInt32(0, 123), "SetUInt32 vs dataset[tag].GetUInt32(...)"); dataset[tag].AppendUInt32(uiValue); Trace.WriteLine(string.Format("Testing {0} attribute with {1} (append as uint)", vr.Name, uiValue)); Trace.WriteLine(string.Format("Attribute Value is: \"{0}\"", dataset[tag].ToString())); Assert.AreEqual(szValue + @"\" + szValue, dataset[tag].ToString(), "AppendUInt32 vs dataset[tag].ToString()"); Assert.AreEqual(uiValue, dataset[tag].GetUInt32(1, 123), "AppendUInt32 vs dataset[tag].GetUInt32(...)"); }
public void TestAttributeAT() { DicomVr vr = DicomVr.ATvr; SetCurrentCulture(); try { SetAndAssertInt16(vr, "0", 0); SetAndAssertInt16(vr, "1", 1); SetAndAssertInt16(vr, "7FFF", 0x7FFF); SetAndAssertInt32(vr, "0", 0); SetAndAssertInt32(vr, "1", 1); SetAndAssertInt32(vr, "7FFFFFFF", 0x7FFFFFFF); SetAndAssertInt64(vr, "0", 0); SetAndAssertInt64(vr, "1", 1); SetAndAssertInt64(vr, "FFFFFFFF", 0xFFFFFFFF); SetAndAssertUInt16(vr, "0", 0); SetAndAssertUInt16(vr, "1", 1); SetAndAssertUInt16(vr, "FFFF", 0xFFFF); SetAndAssertUInt32(vr, "0", 0); SetAndAssertUInt32(vr, "1", 1); SetAndAssertUInt32(vr, "FFFFFFFF", 0xFFFFFFFF); SetAndAssertUInt64(vr, "0", 0); SetAndAssertUInt64(vr, "1", 1); SetAndAssertUInt64(vr, "FFFFFFFF", 0xFFFFFFFF); } finally { ResetCurrentCulture(); } }
public void TestAttributeUL() { DicomVr vr = DicomVr.ULvr; SetCurrentCulture(); try { SetAndAssertInt16(vr, "0", 0); SetAndAssertInt16(vr, "1", 1); SetAndAssertInt16(vr, "32767", 32767); SetAndAssertInt32(vr, "0", 0); SetAndAssertInt32(vr, "1", 1); SetAndAssertInt32(vr, "2147483647", 2147483647); SetAndAssertInt64(vr, "0", 0); SetAndAssertInt64(vr, "1", 1); SetAndAssertInt64(vr, "4294967295", 4294967295); SetAndAssertUInt16(vr, "0", 0); SetAndAssertUInt16(vr, "1", 1); SetAndAssertUInt16(vr, "65535", 65535); SetAndAssertUInt32(vr, "0", 0); SetAndAssertUInt32(vr, "1", 1); SetAndAssertUInt32(vr, "4294967295", 4294967295); SetAndAssertUInt64(vr, "0", 0); SetAndAssertUInt64(vr, "1", 1); SetAndAssertUInt64(vr, "4294967295", 4294967295); } finally { ResetCurrentCulture(); } }
private void WriteDicomAttribute ( DicomAttributeCollection ds, DicomAttribute element, XmlWriter writer ) { if (null == element) { return; } DicomVr dicomVr = element.Tag.VR; writer.WriteStartElement("DiocomAttribute"); writer.WriteAttributeString("keyword", element.Tag.VariableName); writer.WriteAttributeString("tag", element.Tag.Group.ToString("D4") + element.Tag.Element.ToString("D4")); writer.WriteAttributeString("vr", element.Tag.VR.Name); //VR should at least support a switch! if (dicomVr.Name == DicomVr.SQvr.Name) { ConvertSequence(element, writer); } else if (dicomVr.Equals(DicomVr.PNvr)) { for (int index = 0; index < element.Count; index++) { writer.WriteStartElement("PersonName"); WriteNumberAttrib(writer, index); writer.WriteElementString("Alphabetic", element.ToString()); //TODO: check the standard writer.WriteEndElement( ); } } else if (dicomVr.Equals(DicomVr.OBvr) || dicomVr.Equals(DicomVr.ODvr) || dicomVr.Equals(DicomVr.OFvr) || dicomVr.Equals(DicomVr.OWvr) || dicomVr.Equals(DicomVr.UNvr)) //TODO inline bulk { if (element.Tag.TagValue == DicomTags.PixelData) { } else { byte[] data = (byte[])element.Values; writer.WriteBase64(data, 0, data.Length); } } //else if ( dicomVr.Equals (DicomVr.PNvr) ) //TODO bulk reference //{ //} else { ConvertValue(element, writer); } if (element.Tag.IsPrivate) { //TODO: //writer.WriteAttributeString ("privateCreator", ds[DicomTags.privatecreatro. ) ; } writer.WriteEndElement( ); }
internal static bool IsWildcardCriterionAllowed(DicomVr vr) { return(!WildcardExcludedVRs.Any(excludedVr => excludedVr == vr.Name)); }
private static DicomTag CreateTag(int id, DicomVr vr) { uint tagValue = (uint) id; tagValue = ((((tagValue >> 16) << 1) + 0x11) << 16) + (tagValue & 0x0000ffff); // this generates a serial private tag return new DicomTag(tagValue, string.Format("({0:x4},{1:x4})", (tagValue >> 16), (tagValue & 0x0000ffff)), string.Format("tag{0:x8}", tagValue), vr, true, 0, 10, false); }
private void WriteDicomAttribute ( DicomAttributeCollection ds, DicomAttribute element, JsonWriter writer ) { DicomVr dicomVr = element.Tag.VR; writer.WritePropertyName(element.Tag.HexString, false); //writer.WritePropertyName(element.Tag.Group.ToString("D4") + element.Tag.Element.ToString("D4"), false); writer.WriteStartObject(); writer.WritePropertyName("temp"); writer.WriteValue(element.Tag.VariableName); writer.WritePropertyName("vr"); writer.WriteValue(element.Tag.VR.Name); //VR should at least support a switch! if (dicomVr.Name == DicomVr.SQvr.Name) { ConvertSequence(element, writer); } else if (dicomVr.Equals(DicomVr.PNvr)) { writer.WritePropertyName(JsonConstants.ValueField); writer.WriteStartArray(); writer.WriteStartObject(); writer.WritePropertyName(JsonConstants.Alphabetic); writer.WriteValue(element.ToString().TrimEnd()); //TODO: not sure if PN need to be trimmed writer.WriteEndObject(); writer.WriteEndArray(); } else if (dicomVr.Equals(DicomVr.OBvr) || dicomVr.Equals(DicomVr.ODvr) || dicomVr.Equals(DicomVr.OFvr) || dicomVr.Equals(DicomVr.OWvr) || dicomVr.Equals(DicomVr.UNvr)) //TODO inline bulk { if (element.Tag.TagValue == DicomTags.PixelData) { } else { byte[] data = (byte[])element.Values; WriteStringValue(writer, System.Convert.ToBase64String(data)); } } //else if ( dicomVr.Equals (DicomVr.PNvr) ) //TODO bulk reference //{ //} else { ConvertValue(element, writer); } if (element.Tag.IsPrivate) { //TODO: //writer.WriteAttributeString ("privateCreator", ds[DicomTags.privatecreatro. ) ; } writer.WriteEndObject( ); }
public void TestAttributeDS() { DicomVr vr = DicomVr.DSvr; SetCurrentCulture(); try { SetAndAssertInt16(vr, "0", 0); SetAndAssertInt16(vr, "1", 1); SetAndAssertInt16(vr, "-1", -1); SetAndAssertInt16(vr, "32767", 32767); SetAndAssertInt16(vr, "-32768", -32768); SetAndAssertInt32(vr, "0", 0); SetAndAssertInt32(vr, "1", 1); SetAndAssertInt32(vr, "-1", -1); SetAndAssertInt32(vr, "2147483647", 2147483647); SetAndAssertInt32(vr, "-2147483648", -2147483648); SetAndAssertInt64(vr, "0", 0); SetAndAssertInt64(vr, "1", 1); SetAndAssertInt64(vr, "-1", -1); SetAndAssertInt64(vr, "2147483647", 2147483647); SetAndAssertInt64(vr, "-2147483648", -2147483648); SetAndAssertUInt16(vr, "0", 0); SetAndAssertUInt16(vr, "1", 1); SetAndAssertUInt16(vr, "65535", 65535); SetAndAssertUInt32(vr, "0", 0); SetAndAssertUInt32(vr, "1", 1); SetAndAssertUInt32(vr, "2147483647", 2147483647); SetAndAssertUInt64(vr, "0", 0); SetAndAssertUInt64(vr, "1", 1); SetAndAssertUInt64(vr, "2147483647", 2147483647); //there seems to invariably be some precision loss with floats //SetAndAssertFloat32(vr, "0", 0.00000000f); //SetAndAssertFloat32(vr, "2.048", 2.048f); //SetAndAssertFloat32(vr, "-2.048", -2.048f); //SetAndAssertFloat32(vr, "12345.6", 12345.6f); //SetAndAssertFloat32(vr, "-12345.6", -12345.6f); //SetAndAssertFloat32(vr, "1.797693E+38", 1.797693e38f); //SetAndAssertFloat32(vr, "-1.797693E+38", -1.797693e38f); //SetAndAssertFloat32(vr, "1.797693E-38", 1.797693e-38f); //SetAndAssertFloat32(vr, "-1.797693E-38", -1.797693e-38f); SetAndAssertFloat64(vr, "0", 0.00000000); SetAndAssertFloat64(vr, "12.3456789", 12.3456789); SetAndAssertFloat64(vr, "-12.3456789", -12.3456789); SetAndAssertFloat64(vr, "12345.6789", 12345.6789); SetAndAssertFloat64(vr, "-12345.6789", -12345.6789); SetAndAssertFloat64(vr, "1.7976931349E+38", 1.7976931349e38); SetAndAssertFloat64(vr, "-1.797693135E+38", -1.797693135e38); SetAndAssertFloat64(vr, "1.7976931349E-38", 1.7976931349e-38); SetAndAssertFloat64(vr, "-1.797693135E-38", -1.797693135e-38); } finally { ResetCurrentCulture(); } }
/// <summary> /// Fixes the VR of the specified DICOM tag, which is especially important for multi-VR tags. /// </summary> private static DicomTag FixVR(uint tag, DicomVr newVR) { var dicomTag = DicomTagDictionary.GetDicomTag(tag); if (dicomTag.VR == newVR) return dicomTag; if (!dicomTag.MultiVR) throw new ArgumentException("The specified DICOM tag does not support multiple VRs.", "tag"); return new DicomTag(dicomTag.TagValue, dicomTag.Name, dicomTag.VariableName, newVR, true, dicomTag.VMLow, dicomTag.VMHigh, dicomTag.Retired); }
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; } }