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; }
/// <summary> /// Create tilepart using reference to the parent codestream and indices /// of the tile and tilepart. Used when creating new tileparts from scratch /// </summary> /// <param name="parent"></param> /// <param name="tileIdx"></param> /// <param name="tpIdx"></param> internal JP2TilePart( JP2Codestream parent, ushort tileIdx, byte tpIdx, bool createPacketIndex) : base(parent) { // packet offsets always has (packets + 1) elements it keeps the // next offset at the last element _packetOffsets = new List <uint>() { 0 }; _sot = new SotMarker(tileIdx, tpIdx); _pltMarkers = new List <PltMarker>() { new PltMarker(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); }