Exemple #1
0
        /// <summary>
        /// <para>
        /// Traverses a contiguous sequence of JPEG2000 boxes.
        /// Visits recursively the contiguous sequence of boxes of
        /// every superbox.
        /// </para>
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="boxLimit"></param>
        /// <returns>
        /// An ordered collection representing the sequence
        /// of boxes that appear in the underlying IO stream
        /// </returns>
        public static IEnumerable <Jp2Box> TraverseBoxes(Stream stream, long boxLimit)
        {
            List <Jp2Box> boxes     = new List <Jp2Box>();
            long          bytesLeft = boxLimit;

            while (bytesLeft > 0)
            {
                Jp2Box box = Jp2Box.Open(stream, bytesLeft);
                bytesLeft -= box.Length;
                boxes.Add(box);
            }

            return(boxes);
        }
Exemple #2
0
        /// <summary>
        /// <para>
        /// Parses a JPEG2000 box from the underlying IO stream.
        /// </para>
        /// <para>
        /// Stream must be positioned at the start of the box
        /// </para>
        /// <para>
        /// Advances the stream to the first byte of the box content
        /// </para>
        /// </summary>
        /// <param name="stream">the underlying IO stream</param>
        /// <param name="boxLimit">
        /// number of bytes that are left to be read in the box container
        /// </param>
        /// <returns></returns>
        public static Jp2Box Open(Stream stream, long boxLimit)
        {
            if (boxLimit < MIN_BOX_LENGTH)
            {
                throw new ArgumentException(
                          "Not enough data left to parse JPEG2000 box");
            }

            long length = stream.ReadUInt32();

            if (length == 0)
            {
                // ISO 15443-1, Annex I section 4 Box Definition
                //  If the value of this field is 0, then the length of the
                // box was not known when the LBox field was written. In this
                // case, this box contains all bytes up to the end of the file.
                length = boxLimit;
            }
            else if (length > USE_EXTENDED_LENGTH && length < MIN_BOX_LENGTH)
            {
                // these values are supposedly reserved for ISO use..
                throw new ArgumentException(
                          "JPEG2000 box length cannot be determined");
            }

            uint ucode      = stream.ReadUInt32();
            uint dataOffset = 8;

            if (length == USE_EXTENDED_LENGTH)
            {
                if (boxLimit < (MIN_BOX_LENGTH + 8))
                {
                    throw new ArgumentException(
                              "not enough data to read extended length field");
                }
                ulong ulLength = stream.ReadUInt64();
                if (ulLength > long.MaxValue)
                {
                    throw new ArgumentOutOfRangeException(
                              "box is larger than 2^63 bytes");
                }

                length      = (long)ulLength;
                dataOffset += 8;
            }
            if (length > boxLimit)
            {
                throw new ArgumentException(
                          "Box length is larger than the limit on box container");
            }

            if (Jp2Box.IsSuperbox(ucode))
            {
                var boxes = TraverseBoxes(stream, length - dataOffset);
                return(new Jp2Box(ucode, length, dataOffset, boxes));
            }
            else
            {
                // advance the stream position beyond the content of this box.
                // TraverseBoxes recursive call relies on Open call to
                // advance the stream position.
                stream.Seek(length - dataOffset, SeekOrigin.Current);
                return(new Jp2Box(ucode, length, dataOffset));
            }
        }