internal long AssignOffset(JP2TilePart tp) { bool rc = _nextUnboundTilepartIdx < _tileparts.Count; rc = rc && tp == _tileparts[_nextUnboundTilepartIdx]; if (!rc) { throw new InvalidOperationException(String.Concat( "Must add the tile-part to the codestream before assigning", " offsets. Call FlushHeaders in the same order that the ", " tile-parts were inserted into the codestream")); } long tpOffset = FirstChildOffset; if (_nextUnboundTilepartIdx > 0) { int prevIdx = _nextUnboundTilepartIdx - 1; var prev = _tileparts[prevIdx]; tpOffset = prev.Position - Position; tpOffset += prev.Length; if (prev.Length <= 0) { throw new InvalidOperationException(string.Format( "tilepart at position {0}, was not sealed", prevIdx)); } } _nextUnboundTilepartIdx++; return(tpOffset); }
/// <summary> /// Creates a new tile-part instance and adds it to /// an ordered list of tile-parts that compose this codestream. /// </summary> /// <param name="tileIdx"> /// The tile index that the tile-part belongs to /// </param> /// <param name="isLastInTile"> /// True if this should be the last tile-part /// for this tile. Needed for the TNsot field in the /// SOT marker. /// </param> /// <returns> /// A tile-part instance which is added to this codestream. /// </returns> public JP2TilePart CreateTilePart(ushort tileIdx, bool isLastInTile) { if (IsFlushed) { throw new InvalidOperationException(String.Concat( "Cannot add tile-parts to a codestream that ", "has already been flushed to the underlying IO ", "stream. You should call Flush only after you have ", "added all tile-parts and all packets")); } if (!IsOpened) { throw new InvalidOperationException(String.Concat( "Cannot add tile-parts to a codestream that has ", "been closed. You can add tile-parts only to a ", "codestream which has been newly created")); } byte tpIdx = Tiles[tileIdx].TilePartCount; JP2TilePart tp = new JP2TilePart(this, tileIdx, tpIdx, true); Tiles[tileIdx].Add(tp, isLastInTile); _tileparts.Add(tp); AddToTlm(tp); return(tp); }
private long AddTilePart(long offset, ushort tileIdx, long tpLength) { var tp = new JP2TilePart(this, offset, tpLength); Tiles[tileIdx].Add(tp, false); _tileparts.Add(tp); offset += tpLength; return(offset); }
/// <summary> /// Bulk transfer of source tile-part content to destination tile-part. /// </summary> /// <param name="dst">Destination tile-part</param> /// <param name="dstOffset"> /// Offset in the destination tile-part in bytes from the start of the FirstChildOffset /// </param> /// <param name="src">Source tile-part</param> /// <param name="startPacket">inclusive index</param> /// <param name="endPacket">exclusive index</param> /// <param name="buffer">optional buffer</param> /// <returns>The number of bytes transferred</returns> public static uint BulkTransferData( JP2TilePart dst, uint dstOffset, JP2TilePart src, int startPacket, int packetCount, byte[] buffer = null) { if (!dst.IsFlushed) { throw new InvalidOperationException(String.Concat( "trying to transfer data between IO streams ", "without sealing the destination tile-part to ", "further addition of packets. ", "Must call to JP2TilePart.Flush()")); } if (!dst.IsOpened || !src.IsOpened) { throw new InvalidOperationException(String.Concat( "Trying to transfer data between unopened ", "tile-parts. Call OpenTilePart on the source ", "or destination codestreams")); } if (buffer == null) { buffer = new byte[1 << 16]; } int endPacket = startPacket + packetCount; uint srcOffset = src._packetOffsets[startPacket]; uint endOffset = src._packetOffsets[endPacket]; uint dataCount = endOffset - srcOffset; // make it signed integer for bounds checking long left = dataCount; long srcPos = src.Position + src.FirstChildOffset + srcOffset; long dstPos = dst.Position + dst.FirstChildOffset + dstOffset; src.UnderlyingIO.Seek(srcPos, SeekOrigin.Begin); dst.UnderlyingIO.Seek(dstPos, SeekOrigin.Begin); while (left > 0) { // a tile-part can theoretically have 2^32 bytes but a byte // buffer is limited to Int32.MaxValue which is only 2^31 - 1. long countL = Math.Min(buffer.Length, left); int count = (int)countL; src.UnderlyingIO.Read(buffer, 0, count); dst.UnderlyingIO.Write(buffer, 0, count); left -= count; } return(dataCount); }
private void AddToTlm(JP2TilePart tp) { TlmMarker tlm = _tlmMarkers.Last(); if (tlm.IsFull) { if (_tlmMarkers.Count >= TlmMarker.MaxMarkers) { throw new InvalidOperationException(String.Concat( "Cannot add more tile-parts, Exceeded the ", "limit of TLM markers in codestream")); } _tlmMarkers.Add(new TlmMarker((byte)_tlmMarkers.Count)); tlm = _tlmMarkers.Last(); } tlm.Add(tp); }
internal void Add(JP2TilePart tilePart, bool isLast) { if (_isSealed) { throw new InvalidOperationException( "this tile has been sealed, tileIdx: " + TileIndex); } if (_tileParts.Count() > MAX_TILEPARTS) { throw new InvalidOperationException( "Tile-parts limit per tile has been reached"); } if (isLast) { tilePart.TilePartCount = (byte)(_tileParts.Count + 1); } _tileParts.Add(tilePart); _packetCounts.Add(PACKET_COUNT_NOT_SET); }
internal JP2Packet(JP2TilePart parent, long offset, long length) : base(parent, offset, length) { }