Пример #1
0
        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;
                    }
                }
            }
        }
Пример #2
0
        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);
        }