/// <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); }