Пример #1
0
        public override void Flush()
        {
            if (UnderlyingIO == null)
            {
                throw new InvalidOperationException(
                          @"UnderlyingI stream missing. Tilepart headers should be
                    written after codestream headers");
            }

            if (!IsOpened)
            {
                throw new InvalidOperationException(String.Concat(
                                                        "Trying to flush to IO stream ",
                                                        "a closed tile-part"));
            }

            if (_offset == OFFSET_NOT_SET)
            {
                _offset = (Parent as JP2Codestream).AssignOffset(this);
            }

            // SOT marker includes the full tile-part length we should write the
            // SOT marker after all the packets have been added, and we know in
            // advance what is the full tile-part length (markers and packets).

            UnderlyingIO.Seek(Position, SeekOrigin.Begin);
            _sot.WriteMarkerSegment(UnderlyingIO);
            foreach (var plt in _pltMarkers)
            {
                plt.WriteMarkerSegment(UnderlyingIO);
            }
            MarkerSegment.WriteMarker(MarkerType.SOD, UnderlyingIO);
            // can be safely closed and reopened from the underlying stream.
            IsFlushed = true;
        }
Пример #2
0
        public override void Flush()
        {
            if (_offset == OFFSET_NOT_SET)
            {
                throw new InvalidOperationException(
                          "Should bind CodestreamNode to a stream");
            }
            // Writes the main headers of this codestream The headers include
            // SOC and every other marker in the Markers collection except TLM.
            // TLM is written when the codestream is sealed, after all of the
            // tileparts are generated. To write the TLM and EOC marker invoke
            // WriteFinalizers().

            UnderlyingIO.Seek(Position, SeekOrigin.Begin);
            int offset = 0;

            offset += MarkerSegment.WriteMarker(MarkerType.SOC, UnderlyingIO);
            offset += Markers[MarkerType.SIZ].WriteMarkerSegment(UnderlyingIO);
            offset += Markers[MarkerType.COD].WriteMarkerSegment(UnderlyingIO);
            offset += Markers[MarkerType.QCD].WriteMarkerSegment(UnderlyingIO);
            var optionalMarkers = Markers.Keys.Except(MandatoryMarkers);

            foreach (var opt in optionalMarkers)
            {
                offset += Markers[opt].WriteMarkerSegment(UnderlyingIO);
            }
            foreach (var tlm in _tlmMarkers)
            {
                offset += tlm.WriteMarkerSegment(UnderlyingIO);
            }
            // flush only the ones that were not flushed incrementally
            // by user code.
            foreach (var tp in _tileparts.Where(tp => !tp.IsFlushed))
            {
                tp.Flush();
            }
            long tpLength = _tileparts.Sum(tp => tp.Length);

            // account for all headers, all tile-parts and EOC marker
            Length = FirstChildOffset + tpLength + MarkerSegment.MarkerLength;
            long eocOffset = Position + FirstChildOffset + tpLength;

            UnderlyingIO.Seek(eocOffset, SeekOrigin.Begin);
            MarkerSegment.WriteMarker(MarkerType.EOC, UnderlyingIO);
            // can be safely closed an re-opened from the underlying stream
            IsFlushed = true;
        }
Пример #3
0
        private void ConstructTilesFromCodestream()
        {
            if (_sotOffset == 0)
            {
                throw new InvalidOperationException(
                          "SOT offset uninitialized, cannot traverse tile-parts " +
                          "before main header was parsed and first tile part" +
                          " was encountered");
            }

            int tileCount = Tiles.Count();

            UnderlyingIO.Seek(Position + _sotOffset, SeekOrigin.Begin);

            long       offset = _sotOffset;
            MarkerType type;

            while ((type = MarkerSegment.Peek(UnderlyingIO)) != MarkerType.EOC)
            {
                if (type != MarkerType.SOT)
                {
                    throw new InvalidOperationException(
                              "Expected only SOT markers in codestream traversal");
                }

                // get the length of the tile part from the SOT and continue as
                // if we have read a TLM entry.
                SotMarker sot = MarkerSegment.Open(UnderlyingIO) as SotMarker;

                if (sot.TileIndex >= tileCount)
                {
                    throw new ArgumentOutOfRangeException(
                              "SOT TileIndex is too large for number of tiles" +
                              " calculated from SIZ tile and image size");
                }
                AddTilePart(offset, sot.TileIndex, sot.TilePartLength);
                offset += sot.TilePartLength;
                // skip to the next marker segment,
                // account for the already read SOT_MARKER
                long skip = sot.TilePartLength;
                skip -= SotMarker.SOT_MARKER_LENGTH;
                skip -= MarkerSegment.MarkerLength;
                UnderlyingIO.Seek(skip, SeekOrigin.Current);
            }
            return;
        }
Пример #4
0
        private static Dictionary <ushort, byte[]> ReadSegments(Stream str)
        {
            var rawSegments = new Dictionary <ushort, byte[]>();

            for (ushort mrkType = str.ReadUInt16();
                 mrkType != (ushort)MarkerType.SOT;
                 mrkType = str.ReadUInt16())
            {
                if (MarkerSegment.IsSegment((MarkerType)mrkType))
                {
                    ushort mrkLength = str.ReadUInt16();
                    byte[] segment   = new byte[mrkLength - 2];
                    str.Read(segment, 0, mrkLength - 2);
                    rawSegments[mrkType] = segment;
                }
            }
            return(rawSegments);
        }
Пример #5
0
        internal override CodestreamNode Open()
        {
            if (IsOpened)
            {
                return(this);
            }

            UnderlyingIO.Seek(Position, SeekOrigin.Begin);
            MarkerType marker = MarkerSegment.Peek(UnderlyingIO);

            if (marker != MarkerType.SOT)
            {
                throw new ArgumentException(
                          "SOT marker expected but was not found");
            }
            List <PltMarker> pltMarkers = new List <PltMarker>();
            int  zIdx = -1;                 // current z-idx of plt markers
            bool isZOrderConsistent = true; // true iff every consequent plt
            // maintains ascending order from zero, without gaps.

            long offset = 0;

            while (MarkerSegment.Peek(UnderlyingIO) != MarkerType.SOD)
            {
                MarkerSegment ms = MarkerSegment.Open(UnderlyingIO);
                switch (ms.Type)
                {
                case MarkerType.SOT:
                    _sot = ms as SotMarker;
                    break;

                case MarkerType.PLT:
                    var plt = ms as PltMarker;
                    isZOrderConsistent &= (++zIdx) == plt.ZIndex;
                    pltMarkers.Add(plt);
                    break;

                case MarkerType.COD:
                case MarkerType.COC:
                case MarkerType.QCD:
                case MarkerType.QCC:
                    throw new NotSupportedException(
                              "Codestream and quantization markers are " +
                              " not supported in tile part header");

                default:
                    break;
                }
                offset += MarkerSegment.MarkerLength + ms.Length;
            }

            _sodOffset = offset;
            if (!isZOrderConsistent)
            {
                // needs sorting!
                pltMarkers.Sort((PltMarker pltX, PltMarker pltY) =>
                                pltX.ZIndex.CompareTo(pltY.ZIndex));
            }

            if (!pltMarkers.Any() && Length > EMPTY_TILEPART_LENGTH)
            {
                throw new NotSupportedException(
                          "packet lengths are not specified in a non empty tile-part"
                          + " decoding packet headers is not supported yet");
            }

            _pltMarkers = pltMarkers;

            // flatten
            uint packOffset = 0;

            foreach (var plt in pltMarkers)
            {
                foreach (var packLength in plt)
                {
                    packOffset += packLength;
                    _packetOffsets.Add(packOffset);
                }
            }
            // read and parsed successfully.
            IsOpened = true;
            return(this);
        }
Пример #6
0
        internal override CodestreamNode Open()
        {
            if (IsOpened)
            {
                return(this);
            }

            UnderlyingIO.Seek(Position, SeekOrigin.Begin);

            if (MarkerSegment.Peek(UnderlyingIO) != MarkerType.SOC)
            {
                throw new ArgumentException(
                          "expected SOC marker at stream position: " + Position);
            }

            var markers = new Dictionary <MarkerType, MarkerSegment>();

            bool isZOrderConsistent = true; // true iff every consequent tlm
            // maintains ascending order from zero, without gaps.
            int zIdx = -1;                  // current z-index of plt markers
            List <TlmMarker> tlmMarkers = new List <TlmMarker>();

            MarkerSegment ms;
            long          offset = 0; // offset from the beginning of the codestream

            while (MarkerSegment.Peek(UnderlyingIO) != MarkerType.SOT)
            {
                ms = MarkerSegment.Open(UnderlyingIO);
                switch (ms.Type)
                {
                case MarkerType.SIZ:
                case MarkerType.COD:
                case MarkerType.QCD:
                    if (markers.ContainsKey(ms.Type))
                    {
                        throw new InvalidDataException(
                                  "Already have a " + ms.Type + "marker");
                    }
                    markers[ms.Type] = ms;
                    break;

                case MarkerType.TLM:
                    var tlm = ms as TlmMarker;
                    isZOrderConsistent &= (++zIdx) == tlm.ZIndex;
                    tlmMarkers.Add(tlm);
                    break;

                case MarkerType.COC:
                case MarkerType.QCC:
                    throw new NotSupportedException(
                              "Codestream and Quantization markers for specific" +
                              " components are not supported in main header");

                default:
                    break;
                }
                offset += MarkerSegment.MarkerLength + ms.Length;
            }

            _sotOffset = offset;
            Markers    = markers;

            if (!isZOrderConsistent)
            {
                // need sorting!
                tlmMarkers.Sort((TlmMarker tlmX, TlmMarker tlmY) =>
                                tlmX.ZIndex.CompareTo(tlmY.ZIndex));
            }

            Tiles = ConstructTiles();
            if (tlmMarkers.Any())
            {
                ConstructTilesFromTlm(tlmMarkers);
            }
            else
            {
                ConstructTilesFromCodestream();
            }

            // parsed and opened successfully.
            IsOpened = true;
            return(this);
        }