private void ParseDataSet(long StreamPositionEnd, XElement theParentNode) { // Each Sequence does have it's own 'Private Code Dictionary' PrivateCodeDictionary aPrivateCodeDictionary = new PrivateCodeDictionary(); while (mBinaryReader.BaseStream.Position < StreamPositionEnd) { DICOMDataElement aTag = GetNextTag(aPrivateCodeDictionary); if (aTag != null) { // Check for 'Transfer Syntax UID (0002,0010)' // =========================================== if (aTag.Tag.Equals("(0002,0010)")) { mTransferSyntax = aTag.ValueField; } // Private Creator Code Handling // ============================= // Reset Private Creator Code List if current Tag is 'Item' if (aTag.Tag.Equals("(FFFE,E000)")) { aPrivateCodeDictionary.ClearPrivateCreatorCode(); } // Add new Private Creator Code if ((aTag.GroupNumber % 2) == 1 && (aTag.ElementNumber <= 0xFF)) { string aGroupNumberString = aTag.GroupNumber.ToString("X4"); string aElementNumberString = aTag.ElementNumber.ToString("X2"); aPrivateCodeDictionary.LoadPrivateCreatorCode(aGroupNumberString, aElementNumberString, aTag.ValueField.Trim()); } // Add new Tag to XDocument // ======================== XElement newXDataElement = new XElement("DataElement"); theParentNode.Add(newXDataElement); newXDataElement.Add(new XAttribute("Tag", aTag.Tag)); newXDataElement.Add(new XAttribute("TagName", aTag.TagName)); newXDataElement.Add(new XAttribute("VR", aTag.VR)); newXDataElement.Add(new XAttribute("VM", aTag.VM)); newXDataElement.Add(new XAttribute("Data", aTag.ValueField)); newXDataElement.Add(new XAttribute("Length", aTag.ValueLength.ToString())); newXDataElement.Add(new XAttribute("StreamPosition", aTag.StreamPosition.ToString())); // Call 'ParseDataSet' recursively for nested datasets // =================================================== if (aTag.VR.Equals("SQ")) { if (aTag.ValueLength == -1) { ParseDataSet(mBinaryReader.BaseStream.Length, newXDataElement); } else { ParseDataSet(mBinaryReader.BaseStream.Position + aTag.ValueLength, newXDataElement); } } // End criteria for sequence reached? // ================================== // Break if current Tag is 'Sequence Delimitation Item' if (aTag.Tag.Equals("(FFFE,E0DD)")) { break; } } } }
private DICOMDataElement GetNextTag(PrivateCodeDictionary thePrivateCodeDictionary) { DICOMDataElement aTag = new DICOMDataElement(); // Check, if we still read the 'File Meta Information' (attributes of type '(0002,xxxx)') // For this purpose, we do a look-up of the GroupNumber with the default 'Little Endian' encoding mode // If the GroupNumer is different to 0x0002, we have left the 'File Meta Information' section // Don't forget to adjust the Stream Position afterwards (decrement by '2') // Afterwars, the GroupNumber is read again (this time with the correct encoding mode) ushort aGroupNumberLookup = GetUnsignedShort_16Bit(EndianEncodingMode.LittleEndian); if (aGroupNumberLookup != 0x0002) { mFileMetaInfoReadingOngoingFlag = false; } mBinaryReader.BaseStream.Position -= 2; // Set the Encoding Mode for this tag // ================================== // All 'File Meta Information Attributes (0002,xxxx)' shall be encoded as 'VR explicit, little endian' // All other Attributes have to be encoded according to the transfer syntax value VREncodingMode aTagVREncodingMode = VREncodingMode.Undefined; EndianEncodingMode aTagEndianEncodingMode = EndianEncodingMode.Undefined; if (mFileMetaInfoReadingOngoingFlag) { aTagVREncodingMode = VREncodingMode.ExplicitVR; aTagEndianEncodingMode = EndianEncodingMode.LittleEndian; } else { switch (mTransferSyntax) { // Explicit VR Encoding, little endian case "1.2.840.10008.1.2.1": aTagVREncodingMode = VREncodingMode.ExplicitVR; aTagEndianEncodingMode = EndianEncodingMode.LittleEndian; break; // Implicit VR Encoding, little endian case "1.2.840.10008.1.2": aTagVREncodingMode = VREncodingMode.ImplicitVR; aTagEndianEncodingMode = EndianEncodingMode.LittleEndian; break; // Explicit VR Encoding, big endian case "1.2.840.10008.1.2.2": aTagVREncodingMode = VREncodingMode.ExplicitVR; aTagEndianEncodingMode = EndianEncodingMode.BigEndian; break; // For every other Transfer Syntax (e.g. JPEG encoding), 'Exlicit VR, little endian' shall be used default: aTagVREncodingMode = VREncodingMode.ExplicitVR; aTagEndianEncodingMode = EndianEncodingMode.LittleEndian; break; } } // Read GroupNumber aTag.GroupNumber = GetUnsignedShort_16Bit(aTagEndianEncodingMode); // Read ElementNumber aTag.ElementNumber = GetUnsignedShort_16Bit(aTagEndianEncodingMode); // Format the Tag string aTag.Tag = string.Format("({0},{1})", aTag.GroupNumber.ToString("X4"), aTag.ElementNumber.ToString("X4")); // Get VR value aTag.VR = GetVR(aTag.GroupNumber, aTag.ElementNumber, aTag.Tag, thePrivateCodeDictionary, aTagVREncodingMode); // Get DICOM attribute name aTag.TagName = GetTagName(aTag.GroupNumber, aTag.ElementNumber, aTag.Tag, thePrivateCodeDictionary); switch (aTag.VR) { case "OB": // Other Byte String case "OF": // Other Float String case "OW": // Other Word String case "UN": // Unknown content { // Reference: DCIOM Standard 2009, PS 3.5: Data Structures and Encoding // Table 7.1-1 // ------------------------------------- // | Reserved | ValueLength | ValueField | // ------------------------------------- // | 2 Bytes | 4 Bytes | n Bytes | // ------------------------------------- if (aTagVREncodingMode == VREncodingMode.ExplicitVR) { // Skip the two Reserved bytes byte ReservedByte0 = mBinaryReader.ReadByte(); byte ReservedByte1 = mBinaryReader.ReadByte(); } aTag.ValueLength = GetLength_32Bit(aTagEndianEncodingMode); aTag.StreamPosition = mBinaryReader.BaseStream.Position; // Parse out the data if (aTag.ValueLength > 10) { for (int i = 0; i < 10; i++) { byte b = mBinaryReader.ReadByte(); aTag.ValueField += string.Format("{0} ", b.ToString("X2")); } aTag.ValueField += "...."; mBinaryReader.BaseStream.Position += aTag.ValueLength - 10; } else { for (int i = 0; i < aTag.ValueLength; i++) { byte b = mBinaryReader.ReadByte(); aTag.ValueField += string.Format("{0} ", b.ToString("X2")); } } aTag.ValueField = aTag.ValueField.Trim(); aTag.VM = 1; break; } case "UT": // Unlimited Text { // Reference: DCIOM Standard 2009, PS 3.5: Data Structures and Encoding // Table 7.1-1 // ------------------------------------- // | Reserved | ValueLength | ValueField | // ------------------------------------- // | 2 Bytes | 4 Bytes | n Bytes | // ------------------------------------- if (aTagVREncodingMode == VREncodingMode.ExplicitVR) { // Skip the two Reserved bytes byte ReservedByte0 = mBinaryReader.ReadByte(); byte ReservedByte1 = mBinaryReader.ReadByte(); } aTag.ValueLength = GetLength_32Bit(aTagEndianEncodingMode); aTag.StreamPosition = mBinaryReader.BaseStream.Position; // Parse out the Value string using the Default Encoder byte[] aBuffer = new byte[aTag.ValueLength]; mBinaryReader.Read(aBuffer, 0, (int)aTag.ValueLength); Encoding myStringEncoder = System.Text.Encoding.Default; aTag.ValueField = myStringEncoder.GetString(aBuffer).Trim(); aTag.ValueField = aTag.ValueField.Replace(Environment.NewLine, " "); aTag.ValueField = aTag.ValueField.Replace(Convert.ToChar(0x00).ToString(), ""); aTag.VM = 1; break; } case "SQ": // Sequence of Items { // Reference: DCIOM Standard 2009, PS 3.5: Data Structures and Encoding // Table 7.1-1 // ------------------------ // | Reserved | ValueLength | // | 2 Bytes | 4 Bytes | // ------------------------ if (aTagVREncodingMode == VREncodingMode.ExplicitVR) { // Skip the two Reserved bytes byte ReservedByte0 = mBinaryReader.ReadByte(); byte ReservedByte1 = mBinaryReader.ReadByte(); } aTag.ValueLength = GetLength_32Bit(aTagEndianEncodingMode); aTag.StreamPosition = mBinaryReader.BaseStream.Position; aTag.VM = 1; break; } case "AE": // Application Entity case "AS": // Age String case "CS": // Code String case "DA": // Date case "DT": // Date Time case "LT": // Long Text case "PN": // Person Name case "SH": // Short String case "ST": // Short Text case "TM": // Time { // Reference: DCIOM Standard 2009, PS 3.5: Data Structures and Encoding // Table 7.1-2 // -------------------------- // | ValueLength | ValueField | // -------------------------- // | 2 Bytes | n Bytes | // -------------------------- if (aTagVREncodingMode == VREncodingMode.ExplicitVR) { aTag.ValueLength = GetLength_16Bit(aTagEndianEncodingMode); } else { aTag.ValueLength = GetLength_32Bit(aTagEndianEncodingMode); } aTag.StreamPosition = mBinaryReader.BaseStream.Position; // Parse out the Value string using the Default Encoder byte[] aBuffer = new byte[aTag.ValueLength]; mBinaryReader.Read(aBuffer, 0, (int)aTag.ValueLength); Encoding myStringEncoder = System.Text.Encoding.Default; aTag.ValueField = myStringEncoder.GetString(aBuffer).Trim(); aTag.ValueField = aTag.ValueField.Replace(Environment.NewLine, " "); aTag.ValueField = aTag.ValueField.Replace(Convert.ToChar(0x00).ToString(), ""); aTag.VM = 1; break; } case "DS": // Decimal String case "IS": // Integer String case "LO": // Long String { // Reference: DCIOM Standard 2009, PS 3.5: Data Structures and Encoding // Table 7.1-2 // -------------------------- // | ValueLength | ValueField | // -------------------------- // | 2 Bytes | n Bytes | // -------------------------- if (aTagVREncodingMode == VREncodingMode.ExplicitVR) { aTag.ValueLength = GetLength_16Bit(aTagEndianEncodingMode); } else { aTag.ValueLength = GetLength_32Bit(aTagEndianEncodingMode); } aTag.StreamPosition = mBinaryReader.BaseStream.Position; // Parse out the Value string using the Default Encoder byte[] aBuffer = new byte[aTag.ValueLength]; mBinaryReader.Read(aBuffer, 0, (int)aTag.ValueLength); Encoding myStringEncoder = System.Text.Encoding.Default; aTag.ValueField = myStringEncoder.GetString(aBuffer).Trim(); aTag.ValueField = aTag.ValueField.Replace(Environment.NewLine, " "); aTag.ValueField = aTag.ValueField.Replace(Convert.ToChar(0x00).ToString(), ""); string[] split = aTag.ValueField.Split(new Char[] { '\\' }); aTag.VM = split.Count(); break; } case "UI": // Unique Identifier (UID) { // Reference: DCIOM Standard 2009, PS 3.5: Data Structures and Encoding // Table 7.1-2 // -------------------------- // | ValueLength | ValueField | // -------------------------- // | 2 Bytes | n Bytes | // -------------------------- if (aTagVREncodingMode == VREncodingMode.ExplicitVR) { aTag.ValueLength = GetLength_16Bit(aTagEndianEncodingMode); } else { aTag.ValueLength = GetLength_32Bit(aTagEndianEncodingMode); } aTag.StreamPosition = mBinaryReader.BaseStream.Position; // Parse out the Value string using the Default Encoder byte[] aBuffer = new byte[aTag.ValueLength]; mBinaryReader.Read(aBuffer, 0, (int)aTag.ValueLength); Encoding myStringEncoder = System.Text.Encoding.Default; aTag.ValueField = myStringEncoder.GetString(aBuffer).Trim(); aTag.ValueField = aTag.ValueField.Replace(Environment.NewLine, " "); aTag.ValueField = aTag.ValueField.Replace(Convert.ToChar(0x00).ToString(), ""); aTag.VM = 1; break; } case "AT": // Attribute Tag { // Reference: DCIOM Standard 2009, PS 3.5: Data Structures and Encoding // Table 7.1-2 // ----------------------------- // | ValueLength | ValueField | // ----------------------------- // | 2 Bytes | 4 Bytes fixed | // ----------------------------- if (aTagVREncodingMode == VREncodingMode.ExplicitVR) { aTag.ValueLength = GetLength_16Bit(aTagEndianEncodingMode); } else { aTag.ValueLength = GetLength_32Bit(aTagEndianEncodingMode); } aTag.StreamPosition = mBinaryReader.BaseStream.Position; ushort aGroupNumber = GetUnsignedShort_16Bit(aTagEndianEncodingMode); ushort aElementNumber = GetUnsignedShort_16Bit(aTagEndianEncodingMode); aTag.Tag = string.Format("({0}),({1})", aGroupNumber.ToString("X4"), aElementNumber.ToString("X4")); aTag.VM = 1; break; } case "UL": // Unsigned Long (32 Bit, 4 Bytes) { // Reference: DCIOM Standard 2009, PS 3.5: Data Structures and Encoding // Table 7.1-2 // ---------------------------------------- // | ValueLength | ValueField | // ---------------------------------------- // | 2 Bytes | ValueLength x 4 Bytes | // ---------------------------------------- if (aTagVREncodingMode == VREncodingMode.ExplicitVR) { aTag.ValueLength = GetLength_16Bit(aTagEndianEncodingMode); } else { aTag.ValueLength = GetLength_32Bit(aTagEndianEncodingMode); } aTag.StreamPosition = mBinaryReader.BaseStream.Position; for (int i = 0; i < aTag.ValueLength; i += 4) { ulong Value = GetUnsignedInt_32Bit(aTagEndianEncodingMode); aTag.ValueField += Value.ToString() + " "; aTag.VM++; } break; } case "US": // Unsigned Short { // Reference: DCIOM Standard 2009, PS 3.5: Data Structures and Encoding // Table 7.1-2 // ------------------------------------- // | ValueLength | ValueField | // ------------------------------------- // | 2 Bytes | ValueLength x 2 Bytes | // ------------------------------------- if (aTagVREncodingMode == VREncodingMode.ExplicitVR) { aTag.ValueLength = GetLength_16Bit(aTagEndianEncodingMode); } else { aTag.ValueLength = GetLength_32Bit(aTagEndianEncodingMode); } aTag.StreamPosition = mBinaryReader.BaseStream.Position; for (int i = 0; i < aTag.ValueLength; i += 2) { ushort Value = GetUnsignedShort_16Bit(aTagEndianEncodingMode); aTag.ValueField += Value.ToString() + " "; aTag.VM++; } break; } case "SL": // Signed long (32 Bit, 4 Bytes) { // Reference: DCIOM Standard 2009, PS 3.5: Data Structures and Encoding // Table 7.1-2 // ------------------------------------- // | ValueLength | ValueField | // ------------------------------------- // | 2 Bytes | ValueLength x 4 Bytes | // ------------------------------------- if (aTagVREncodingMode == VREncodingMode.ExplicitVR) { aTag.ValueLength = GetLength_16Bit(aTagEndianEncodingMode); } else { aTag.ValueLength = GetLength_32Bit(aTagEndianEncodingMode); } aTag.StreamPosition = mBinaryReader.BaseStream.Position; for (int i = 0; i < aTag.ValueLength; i += 4) { long Value = GetSignedInt_32Bit(aTagEndianEncodingMode); aTag.ValueField += Value.ToString() + " "; aTag.VM++; } break; } case "SS": // Signed short (16 Bit, 2 Bytes) { // Reference: DCIOM Standard 2009, PS 3.5: Data Structures and Encoding // Table 7.1-2 // ------------------------------------- // | ValueLength | ValueField | // ------------------------------------- // | 2 Bytes | ValueLength x 2 Bytes | // ------------------------------------- if (aTagVREncodingMode == VREncodingMode.ExplicitVR) { aTag.ValueLength = GetLength_16Bit(aTagEndianEncodingMode); } else { aTag.ValueLength = GetLength_32Bit(aTagEndianEncodingMode); } aTag.StreamPosition = mBinaryReader.BaseStream.Position; for (int i = 0; i < aTag.ValueLength; i += 2) { short Value = GetSignedShort_16Bit(aTagEndianEncodingMode); aTag.ValueField += Value.ToString() + " "; aTag.VM++; } break; } case "FL": // Floating Point Single (32 Bit, 4 Byte) { // Reference: DCIOM Standard 2009, PS 3.5: Data Structures and Encoding // Table 7.1-2 // ------------------------------------- // | ValueLength | ValueField | // ------------------------------------- // | 2 Bytes | ValueLength x 4 Bytes | // ------------------------------------- if (aTagVREncodingMode == VREncodingMode.ExplicitVR) { aTag.ValueLength = GetLength_16Bit(aTagEndianEncodingMode); } else { aTag.ValueLength = GetLength_32Bit(aTagEndianEncodingMode); } aTag.StreamPosition = mBinaryReader.BaseStream.Position; for (int i = 0; i < aTag.ValueLength; i += 4) { float Value = GetFloatingPointSingle_32Bit(aTagEndianEncodingMode); aTag.ValueField += Value.ToString() + " "; aTag.VM++; } break; } case "FD": // Floating Point Double (64 Bit, 8 Byte) { // Reference: DCIOM Standard 2009, PS 3.5: Data Structures and Encoding // Table 7.1-2 // ------------------------------------- // | ValueLength | ValueField | // ------------------------------------- // | 2 Bytes | ValueLength x 8 Bytes | // ------------------------------------- if (aTagVREncodingMode == VREncodingMode.ExplicitVR) { aTag.ValueLength = GetLength_16Bit(aTagEndianEncodingMode); } else { aTag.ValueLength = GetLength_32Bit(aTagEndianEncodingMode); } aTag.StreamPosition = mBinaryReader.BaseStream.Position; for (int i = 0; i < aTag.ValueLength; i += 8) { double Value = GetFloatingPointDouble_64Bit(aTagEndianEncodingMode); aTag.ValueField += Value.ToString() + " "; aTag.VM++; } break; } case "DL": // Special SQ related Data Elements Items: // - (FFFE,E000) Item // - (FFFE,E00D) Item Delimitation Item // - (FFFE,E0DD) Sequence Delimitation Item aTag.ValueLength = GetLength_32Bit(aTagEndianEncodingMode); aTag.StreamPosition = mBinaryReader.BaseStream.Position; aTag.VM = 1; break; default: aTag.VR = "UN"; aTag.ValueLength = GetLength_32Bit(aTagEndianEncodingMode); aTag.StreamPosition = mBinaryReader.BaseStream.Position; aTag.ValueField = "???"; aTag.VM = 1; mBinaryReader.BaseStream.Position += aTag.ValueLength; break; } return(aTag); }