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