Ejemplo n.º 1
0
        /// <summary>
        /// Parses the stream for tags.
        /// </summary>
        /// <param name="parent">The parent Element that the tags will belong to, if any.</param>
        /// <param name="stream">The stream to Read from.</param>
        /// <param name="elements">The Elements collection to add the Elements to.</param>
        /// <param name="current">The current postion in the stream.</param>
        /// <param name="length">The maximum number of bytes to read.</param>
        /// <param name="stop">The group number ot read up to and including.</param>
        /// <param name="syntax">The Transfer Syntax of the stream.</param>
        /// <param name="encoding">The character encoding of the stream.</param>
        /// <returns>The final position in the stream Read to.</returns>
        public static long Scan(Element parent, Stream stream, Elements elements, long current, long length, ushort stop, string syntax, SpecificCharacterSet encoding)
        {
            //System.Diagnostics.Debug.WriteLine(String.Format("0x{0:X8}:{0}: Scan called parent={1}:{2}. current={3} length={4} stop={5}",
            //    stream.Position, (parent!=null)?parent.Tag.ToString():"root", (parent!=null)?parent.VR:"", current, length, stop));

            // we have to get the stream on top of the current position
            stream.Position = current;

            EndianBinaryReader reader = new EndianBinaryReader(stream, Syntax.GetEndian(syntax));

            // Scan stops when either the stream position exceeds length, or the group exceeds stop,
            // or we reach the end of a file, or we reach an ItemDelimiter or SequenceDelimiter, or
            // we can no longer read
            while (true)
            {
                if (!stream.CanRead)
                {
                    //System.Diagnostics.Debug.WriteLine("stream CanRead==false");
                    break;
                }

                if (length != -1 && (ulong)current >= (ulong)length)
                {
                    //System.Diagnostics.Debug.WriteLine(String.Format("0x{0:X8}:{0}: current={1} exceeds length={2}", stream.Position, current, length));
                    break;
                }

                // keep track of where we are before reading the next element
                long previous  = current;
                Tag  lookahead = PeekTag(reader, syntax);

                //System.Diagnostics.Debug.WriteLine(String.Format("0x{0:X8}:{0}: Peek {1} in Scan", stream.Position, lookahead.Name));

                // we scan up to and including the group specified by stop
                // so we check if we have gone beyond the specified group
                if (lookahead.Group > stop)
                {
                    //System.Diagnostics.Debug.WriteLine(String.Format("0x{0:X8}:{0}: group={1} exceeds stop={2}", stream.Position, lookahead.Group, stop));
                    // we need to rewind to before this element
                    current = previous;
                    break;
                }

                if (length == -1)
                {
                    //if (lookahead.Equals(t.ItemDelimitationItem) || lookahead.Equals(t.SequenceDelimitationItem))
                    if (lookahead.Equals(t.ItemDelimitationItem))
                    {
                        //System.Diagnostics.Debug.WriteLine(String.Format("0x{0:X8}:{0}: undefined length, found {1}:{2}", stream.Position, lookahead.Description, lookahead.Name));
                        // position stream beyond delimitation tag
                        stream.Position += sizeof(ushort) * 2;
                        // no need to check zero
                        int zero = reader.ReadInt32();
                        break;
                    }
                }

                Exception exception = null;
                Element   element   = Element.Factory(parent, lookahead);
                try
                {
                    //System.Diagnostics.Debug.WriteLine(String.Format("reading {0}", lookahead.ToString()));
                    element.Read(stream, syntax, encoding);
                }
                catch (Exception ex)
                {
                    // we are going to delay throwing an exception from reading
                    // until we see if we are going to add it to the collection
                    exception = ex;
                }

                current = stream.Position;

                // if we have the SpecificCharacterSet, create an Encoding for the rest of the DataSet
                if (element.Tag.Equals(t.SpecificCharacterSet))
                {
                    encoding = new SpecificCharacterSet(element.Value);
                }
                else if (element.Tag.Equals(t.PixelData) && !Syntax.IsExplicit(syntax))
                {
                    // if we have the PixelData, insure that it matches the BitsStored
                    // this can happen with implicit vrs and OW is the default

                    if (elements.Contains(t.BitsStored))
                    {
                        ushort stored = (ushort)elements[t.BitsStored].Value;
                        Type   type   = element.Value.GetType().GetElementType();
                        if (stored == 8 && element.Value is ushort[])
                        {
                            ushort[] pixels = element.Value as ushort[];
                            byte[]   bytes  = new byte[pixels.Length * 2];
                            Buffer.BlockCopy(pixels, 0, bytes, 0, bytes.Length);
                            element.Value = bytes;
                        }
                    }
                }
                else if (element.Tag.Equals(t.ItemDelimitationItem) || element.Tag.Equals(t.SequenceDelimitationItem) || element.Tag.Equals(t.Item))
                {
                    // if we have a sequence or item delimiter, stop scanning
                    if (length == -1)
                    {
                        return(current);
                    }
                }

                // now that we are about to add the tag, check and see if it parsed correctly
                if (exception != null)
                {
                    // we have failed to parse, so we create a tag that contains the rest of the data
                    stream.Position = previous;
                    element         = new Element("(BAAD,F00D)", reader.ReadBytes((int)(length - previous)));
                }

                string key = Tag.ToString(element);
                // and insert the tag name/value pair in the hash table, allows duplicates
                elements[key] = element;
                //Logging.Log("Adding {0}:{1}", key, element.ToString());

                // now we can throw the exception if there is one
                if (exception != null)
                {
                    throw exception;
                }

                if ((ulong)current >= (ulong)length)
                {
                    //System.Diagnostics.Debug.WriteLine(String.Format("0x{0:X8}:{0}: current={1} at or exceeds length={2}", stream.Position, current, length));
                    break;
                }
            }
            return(current);
        }