corrade-vassal – Rev 1
?pathlinks?
/*
* CVS identifier:
*
* $Id: FileBitstreamReaderAgent.java,v 1.68 2002/07/19 12:34:38 grosbois Exp $
*
* Class: FileBitstreamReaderAgent
*
* Description: Retrieve code-blocks codewords in the bit stream
*
*
*
* COPYRIGHT:
*
* This software module was originally developed by Raphaël Grosbois and
* Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
* Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
* Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
* Centre France S.A) in the course of development of the JPEG2000
* standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
* software module is an implementation of a part of the JPEG 2000
* Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
* Systems AB and Canon Research Centre France S.A (collectively JJ2000
* Partners) agree not to assert against ISO/IEC and users of the JPEG
* 2000 Standard (Users) any of their rights under the copyright, not
* including other intellectual property rights, for this software module
* with respect to the usage by ISO/IEC and Users of this software module
* or modifications thereof for use in hardware or software products
* claiming conformance to the JPEG 2000 Standard. Those intending to use
* this software module in hardware or software products are advised that
* their use may infringe existing patents. The original developers of
* this software module, JJ2000 Partners and ISO/IEC assume no liability
* for use of this software module or modifications thereof. No license
* or right to this software module is granted for non JPEG 2000 Standard
* conforming products. JJ2000 Partners have full right to use this
* software module for his/her own purpose, assign or donate this
* software module to any third party and to inhibit third parties from
* using this software module for non JPEG 2000 Standard conforming
* products. This copyright notice must be included in all copies or
* derivative works of this software module.
*
* Copyright (c) 1999/2000 JJ2000 Partners.
* */
using System;
using CSJ2K.j2k.quantization.dequantizer;
using CSJ2K.j2k.wavelet.synthesis;
using CSJ2K.j2k.entropy.decoder;
using CSJ2K.j2k.codestream;
using CSJ2K.j2k.decoder;
using CSJ2K.j2k.entropy;
using CSJ2K.j2k.image;
using CSJ2K.j2k.util;
using CSJ2K.j2k.io;
using CSJ2K.j2k;
namespace CSJ2K.j2k.codestream.reader
{
/// <summary> This class reads the bit stream (with the help of HeaderDecoder for tile
/// headers and PktDecoder for packets header and body) and retrives location
/// of all code-block's codewords.
///
/// <p>Note: All tile-parts headers are read by the constructor whereas packets
/// are processed when decoding related tile (when setTile method is
/// called).</p>
///
/// <p>In parsing mode, the reader simulates a virtual layer-resolution
/// progressive bit stream with the same truncation points in each code-block,
/// whereas in truncation mode, only the first bytes are taken into account (it
/// behaves like if it is a real truncated codestream).</p>
///
/// </summary>
/// <seealso cref="HeaderDecoder">
/// </seealso>
/// <seealso cref="PktDecoder">
///
/// </seealso>
public class FileBitstreamReaderAgent:BitstreamReaderAgent
{
/// <summary>Gets the reference to the CBlkInfo array </summary>
virtual public CBlkInfo[][][][][] CBlkInfo
{
get
{
return cbI;
}
}
/// <summary>Whether or not the last read Psot value was zero. Only the Psot in the
/// last tile-part in the codestream can have such a value.
/// </summary>
private bool isPsotEqualsZero = true;
/// <summary>Reference to the PktDecoder instance </summary>
public PktDecoder pktDec;
/// <summary>Reference to the ParameterList instance </summary>
private ParameterList pl;
/// <summary>The RandomAccessIO where to get data from </summary>
private RandomAccessIO in_Renamed;
/// <summary>Offset of the first packet in each tile-part in each tile </summary>
private int[][] firstPackOff;
/// <summary> Returns the number of tile-part found for a given tile
///
/// </summary>
/// <param name="t">Tile index
///
///
/// </param>
public virtual int getNumTileParts(int t)
{
if (firstPackOff == null || firstPackOff[t] == null)
{
throw new System.ApplicationException("Tile " + t + " not found in input codestream.");
}
return firstPackOff[t].Length;
}
/// <summary> Number of bytes allocated to each tile. In parsing mode, this number
/// is related to the tile length in the codestream whereas in truncation
/// mode all the rate is affected to the first tiles.
/// </summary>
private int[] nBytes;
/// <summary>Whether or not to print information found in codestream </summary>
private bool printInfo = false;
/// <summary> Backup of the number of bytes allocated to each tile. This array is
/// used to restore the number of bytes to read in each tile when the
/// codestream is read several times (for instance when decoding an R,G,B
/// image to three output files)
///
/// </summary>
private int[] baknBytes;
/// <summary>Length of each tile-part (written in Psot) </summary>
private int[][] tilePartLen;
/// <summary>Total length of each tile </summary>
private int[] totTileLen;
/// <summary>Total length of tiles' header </summary>
private int[] totTileHeadLen;
/// <summary>First tile part header length</summary>
private int firstTilePartHeadLen;
/// <summary>Total length of all tile parts in all tiles </summary>
private double totAllTileLen;
/// <summary>Length of main header </summary>
private int mainHeadLen;
/// <summary>Length of main and tile-parts headers </summary>
private int headLen = 0;
/// <summary>Length of all tile-part headers </summary>
private int[][] tilePartHeadLen;
/// <summary>Length of each packet head found in the tile </summary>
private System.Collections.ArrayList pktHL;
/// <summary>Layer starting positions</summary>
public System.Collections.Generic.List<int> layerStarts;
/// <summary>True if truncation mode is used. False if parsing mode </summary>
private bool isTruncMode;
/// <summary>The number of tile-parts that remain to read </summary>
private int remainingTileParts;
/// <summary>The number of tile-parts read so far for each tile </summary>
private int[] tilePartsRead;
/// <summary>Thetotal number of tile-parts read so far </summary>
private int totTilePartsRead = 0;
/// <summary>The number of found tile-parts in each tile. </summary>
private int[] tileParts;
/// <summary>The current tile part being used </summary>
private int curTilePart;
/// <summary>The number of the tile-parts found in the codestream after reading the
/// tp'th tile-part of tile t
/// </summary>
private int[][] tilePartNum;
/// <summary>Whether or not a EOC marker has been found instead of a SOT </summary>
private bool isEOCFound = false;
/// <summary>Reference to the HeaderInfo instance (used when reading SOT marker
/// segments)
/// </summary>
private HeaderInfo hi;
/// <summary>Array containing information for all the code-blocks:
///
/// <ul>
/// <li>1st dim: component index.</li>
/// <li>2nd dim: resolution level index.</li>
/// <li>3rd dim: subband index.</li>
/// <li>4th/5th dim: code-block index (vert. and horiz.).</li>
/// </ul>
/// </summary>
private CBlkInfo[][][][][] cbI;
/// <summary>The maximum number of layers to decode for any code-block </summary>
private int lQuit;
/// <summary>Whether or not to use only first progression order </summary>
private bool usePOCQuit = false;
/// <summary> Reads all tiles headers and keep offset of their first
/// packet. Finally it calls the rate allocation method.
///
/// </summary>
/// <param name="hd">HeaderDecoder of the codestream.
///
/// </param>
/// <param name="ehs">The input stream where to read bit-stream.
///
/// </param>
/// <param name="decSpec">The decoder specifications
///
/// </param>
/// <param name="pl">The ParameterList instance created from the
/// command-line arguments.
///
/// </param>
/// <param name="cdstrInfo">Whether or not to print information found in
/// codestream.
///
/// </param>
/// <seealso cref="allocateRate">
///
/// </seealso>
public FileBitstreamReaderAgent(HeaderDecoder hd, RandomAccessIO ehs, DecoderSpecs decSpec, ParameterList pl, bool cdstrInfo, HeaderInfo hi):base(hd, decSpec)
{
this.pl = pl;
this.printInfo = cdstrInfo;
this.hi = hi;
// Check whether quit conditiosn used
usePOCQuit = pl.getBooleanParameter("poc_quit");
// Get decoding rate
bool rateInBytes;
bool parsing = pl.getBooleanParameter("parsing");
try
{
trate = pl.getFloatParameter("rate");
if (trate == - 1)
{
trate = System.Single.MaxValue;
}
}
catch (System.FormatException)
{
throw new System.ApplicationException("Invalid value in 'rate' option: " + pl.getParameter("rate"));
}
catch (System.ArgumentException)
{
throw new System.ApplicationException("'rate' option is missing");
}
try
{
tnbytes = pl.getIntParameter("nbytes");
}
catch (System.FormatException)
{
throw new System.ApplicationException("Invalid value in 'nbytes' option: " + pl.getParameter("nbytes"));
}
catch (System.ArgumentException)
{
throw new System.ApplicationException("'nbytes' option is missing");
}
// Check that '-rate' and '-nbytes' are not used at the same time
ParameterList defaults = pl.DefaultParameterList;
if (tnbytes != defaults.getFloatParameter("nbytes"))
{
rateInBytes = true;
}
else
{
rateInBytes = false;
}
if (rateInBytes)
{
trate = tnbytes * 8f / hd.MaxCompImgWidth / hd.MaxCompImgHeight;
}
else
{
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
tnbytes = (int) (trate * hd.MaxCompImgWidth * hd.MaxCompImgHeight) / 8;
if (tnbytes < 0) tnbytes = int.MaxValue;
}
isTruncMode = !pl.getBooleanParameter("parsing");
// Check if quit conditions are being used
int ncbQuit;
try
{
ncbQuit = pl.getIntParameter("ncb_quit");
}
catch (System.FormatException)
{
throw new System.ApplicationException("Invalid value in 'ncb_quit' option: " + pl.getParameter("ncb_quit"));
}
catch (System.ArgumentException)
{
throw new System.ApplicationException("'ncb_quit' option is missing");
}
if (ncbQuit != - 1 && !isTruncMode)
{
throw new System.ApplicationException("Cannot use -parsing and -ncb_quit condition at " + "the same time.");
}
try
{
lQuit = pl.getIntParameter("l_quit");
}
catch (System.FormatException)
{
throw new System.ApplicationException("Invalid value in 'l_quit' option: " + pl.getParameter("l_quit"));
}
catch (System.ArgumentException)
{
throw new System.ApplicationException("'l_quit' option is missing");
}
// initializations
in_Renamed = ehs;
pktDec = new PktDecoder(decSpec, hd, ehs, this, isTruncMode, ncbQuit);
tileParts = new int[nt];
totTileLen = new int[nt];
tilePartLen = new int[nt][];
tilePartNum = new int[nt][];
firstPackOff = new int[nt][];
tilePartsRead = new int[nt];
totTileHeadLen = new int[nt];
tilePartHeadLen = new int[nt][];
nBytes = new int[nt];
baknBytes = new int[nt];
hd.nTileParts = new int[nt];
// CONVERSION PROBLEM?
//this.isTruncMode = isTruncMode;
int t = 0, pos, tp = 0, tptot = 0;
// Keeps main header's length, takes file format overhead into account
int cdstreamStart = hd.mainHeadOff; // Codestream offset in the file
mainHeadLen = in_Renamed.Pos - cdstreamStart;
headLen = mainHeadLen;
// If ncb and lbody quit conditions are used, headers are not counted
if (ncbQuit == - 1)
{
anbytes = mainHeadLen;
}
else
{
anbytes = 0;
}
// If cannot even read the first tile-part
if (anbytes > tnbytes)
{
throw new System.ApplicationException("Requested bitrate is too small.");
}
// Read all tile-part headers from all tiles.
int tilePartStart;
bool rateReached = false;
int mdl;
//int numtp = 0;
totAllTileLen = 0;
remainingTileParts = nt; // at least as many tile-parts as tiles
int maxTP = nt; // If maximum 1 tile part per tile specified
try
{
while (remainingTileParts != 0)
{
tilePartStart = in_Renamed.Pos;
// Read tile-part header
try
{
t = readTilePartHeader();
if (isEOCFound)
{
// Some tiles are missing but the
// codestream is OK
break;
}
tp = tilePartsRead[t];
if (isPsotEqualsZero)
{
// Psot may equals zero for the
// last tile-part: it is assumed that this tile-part
// contain all data until EOC
tilePartLen[t][tp] = in_Renamed.length() - 2 - tilePartStart;
}
}
catch (System.IO.EndOfStreamException e)
{
firstPackOff[t][tp] = in_Renamed.length();
throw e;
}
pos = in_Renamed.Pos;
// In truncation mode, if target decoding rate is reached in
// tile-part header, skips the tile-part and stop reading
// unless the ncb and lbody quit condition is in use
if (isTruncMode && ncbQuit == - 1)
{
if ((pos - cdstreamStart) > tnbytes)
{
firstPackOff[t][tp] = in_Renamed.length();
rateReached = true;
break;
}
}
// Set tile part position and header length
firstPackOff[t][tp] = pos;
tilePartHeadLen[t][tp] = (pos - tilePartStart);
// Update length counters
totTileLen[t] += tilePartLen[t][tp];
totTileHeadLen[t] += tilePartHeadLen[t][tp];
totAllTileLen += tilePartLen[t][tp];
if (isTruncMode)
{
if (anbytes + tilePartLen[t][tp] > tnbytes)
{
anbytes += tilePartHeadLen[t][tp];
headLen += tilePartHeadLen[t][tp];
rateReached = true;
nBytes[t] += (tnbytes - anbytes);
break;
}
else
{
anbytes += tilePartHeadLen[t][tp];
headLen += tilePartHeadLen[t][tp];
nBytes[t] += (tilePartLen[t][tp] - tilePartHeadLen[t][tp]);
}
}
else
{
if (anbytes + tilePartHeadLen[t][tp] > tnbytes)
{
break;
}
else
{
anbytes += tilePartHeadLen[t][tp];
headLen += tilePartHeadLen[t][tp];
}
}
// If this is first tile-part, remember header length
if (tptot == 0)
firstTilePartHeadLen = tilePartHeadLen[t][tp];
// Go to the beginning of next tile part
tilePartsRead[t]++;
in_Renamed.seek(tilePartStart + tilePartLen[t][tp]);
remainingTileParts--;
maxTP--;
tptot++;
// If Psot of the current tile-part was equal to zero, it is
// assumed that it contains all data until the EOC marker
if (isPsotEqualsZero)
{
if (remainingTileParts != 0)
{
FacilityManager.getMsgLogger().printmsg(CSJ2K.j2k.util.MsgLogger_Fields.WARNING, "Some tile-parts have not " + "been found. The codestream may be corrupted.");
}
break;
}
}
}
catch (System.IO.EndOfStreamException)
{
if (printInfo)
{
}
FacilityManager.getMsgLogger().printmsg(CSJ2K.j2k.util.MsgLogger_Fields.WARNING, "Codestream truncated in tile " + t);
// Set specified rate to end of file if valid
int fileLen = in_Renamed.length();
if (fileLen < tnbytes)
{
tnbytes = fileLen;
trate = tnbytes * 8f / hd.MaxCompImgWidth / hd.MaxCompImgHeight;
}
// Bit-rate allocation
if (!isTruncMode)
{
allocateRate();
}
// Update 'res' value once all tile-part headers are read
if (pl.getParameter("res") == null)
{
targetRes = decSpec.dls.Min;
}
else
{
try
{
targetRes = pl.getIntParameter("res");
if (targetRes < 0)
{
throw new System.ArgumentException("Specified negative " + "resolution level " + "index: " + targetRes);
}
}
catch (System.FormatException)
{
throw new System.ArgumentException("Invalid resolution level " + "index ('-res' option) " + pl.getParameter("res"));
}
}
// Verify reduction in resolution level
mdl = decSpec.dls.Min;
if (targetRes > mdl)
{
FacilityManager.getMsgLogger().printmsg(CSJ2K.j2k.util.MsgLogger_Fields.WARNING, "Specified resolution level (" + targetRes + ") is larger" + " than the maximum value. Setting it to " + mdl + " (maximum value)");
targetRes = mdl;
}
// Backup nBytes
for (int tIdx = 0; tIdx < nt; tIdx++)
{
baknBytes[tIdx] = nBytes[tIdx];
}
return ;
}
remainingTileParts = 0;
// Update 'res' value once all tile-part headers are read
if (pl.getParameter("res") == null)
{
targetRes = decSpec.dls.Min;
}
else
{
try
{
targetRes = pl.getIntParameter("res");
if (targetRes < 0)
{
throw new System.ArgumentException("Specified negative " + "resolution level index: " + targetRes);
}
}
catch (System.FormatException)
{
throw new System.ArgumentException("Invalid resolution level " + "index ('-res' option) " + pl.getParameter("res"));
}
}
// Verify reduction in resolution level
mdl = decSpec.dls.Min;
if (targetRes > mdl)
{
FacilityManager.getMsgLogger().printmsg(CSJ2K.j2k.util.MsgLogger_Fields.WARNING, "Specified resolution level (" + targetRes + ") is larger" + " than the maximum possible. Setting it to " + mdl + " (maximum possible)");
targetRes = mdl;
}
if (printInfo)
{
}
// Check presence of EOC marker is decoding rate not reached or if
// this marker has not been found yet
if (!isEOCFound && !isPsotEqualsZero)
{
try
{
short eocCheck = 0;
if (in_Renamed.Pos + sizeof(short) <= in_Renamed.length())
eocCheck = in_Renamed.readShort();
if (!rateReached && !isPsotEqualsZero && eocCheck != CSJ2K.j2k.codestream.Markers.EOC)
{
FacilityManager.getMsgLogger().printmsg(CSJ2K.j2k.util.MsgLogger_Fields.WARNING, "EOC marker not found. " + "Codestream is corrupted.");
}
}
catch (System.IO.EndOfStreamException)
{
FacilityManager.getMsgLogger().printmsg(CSJ2K.j2k.util.MsgLogger_Fields.WARNING, "EOC marker is missing");
}
}
// Bit-rate allocation
if (!isTruncMode)
{
allocateRate();
}
else
{
// Take EOC into account if rate is not reached
if (in_Renamed.Pos >= tnbytes)
anbytes += 2;
}
// Backup nBytes
for (int tIdx = 0; tIdx < nt; tIdx++)
{
baknBytes[tIdx] = nBytes[tIdx];
if (printInfo)
{
FacilityManager.getMsgLogger().println("" + hi.toStringTileHeader(tIdx, tilePartLen[tIdx].Length), 2, 2);
}
}
}
/// <summary> Allocates output bit-rate for each tile in parsing mode: The allocator
/// simulates the truncation of a virtual layer-resolution progressive
/// codestream.
///
/// </summary>
private void allocateRate()
{
int stopOff = tnbytes;
// In parsing mode, the bitrate is allocated related to each tile's
// length in the bit stream
// EOC marker's length
anbytes += 2;
// If there are too few bytes to read the tile part headers throw an
// error
if (anbytes > stopOff)
{
throw new System.ApplicationException("Requested bitrate is too small for parsing");
}
// Calculate bitrate for each tile
int rem = stopOff - anbytes;
int totnByte = rem;
for (int t = nt - 1; t > 0; t--)
{
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
rem -= (nBytes[t] = (int) (totnByte * (totTileLen[t] / totAllTileLen)));
}
nBytes[0] = rem;
}
/// <summary> Reads SOT marker segment of the tile-part header and calls related
/// methods of the HeaderDecoder to read other markers segments. The
/// tile-part header is entirely read when a SOD marker is encountered.
///
/// </summary>
/// <returns> The tile number of the tile part that was read
///
/// </returns>
private int readTilePartHeader()
{
HeaderInfo.SOT ms = hi.NewSOT;
// SOT marker
short marker = in_Renamed.readShort();
if (marker != CSJ2K.j2k.codestream.Markers.SOT)
{
if (marker == CSJ2K.j2k.codestream.Markers.EOC)
{
isEOCFound = true;
return - 1;
}
else
{
throw new CorruptedCodestreamException("SOT tag not found " + "in tile-part start");
}
}
isEOCFound = false;
// Lsot (shall equals 10)
int lsot = in_Renamed.readUnsignedShort();
ms.lsot = lsot;
if (lsot != 10)
throw new CorruptedCodestreamException("Wrong length for " + "SOT marker segment: " + lsot);
// Isot
int tile = in_Renamed.readUnsignedShort();
ms.isot = tile;
if (tile > 65534)
{
throw new CorruptedCodestreamException("Tile index too high in " + "tile-part.");
}
// Psot
int psot = in_Renamed.readInt();
ms.psot = psot;
isPsotEqualsZero = (psot != 0)?false:true;
if (psot < 0)
{
throw new NotImplementedException("Tile length larger " + "than maximum supported");
}
// TPsot
int tilePart = in_Renamed.read();
ms.tpsot = tilePart;
if (tilePart != tilePartsRead[tile] || tilePart < 0 || tilePart > 254)
{
throw new CorruptedCodestreamException("Out of order tile-part");
}
// TNsot
int nrOfTileParts = in_Renamed.read();
ms.tnsot = nrOfTileParts;
hi.sotValue["t" + tile + "_tp" + tilePart] = ms;
if (nrOfTileParts == 0)
{
// The number of tile-part is not specified in
// this tile-part header.
// Assumes that there will be another tile-part in the codestream
// that will indicate the number of tile-parts for this tile)
int nExtraTp;
if (tileParts[tile] == 0 || tileParts[tile] == tilePartLen.Length)
{
// Then there are two tile-parts (one is the current and the
// other will indicate the number of tile-part for this tile)
nExtraTp = 2;
remainingTileParts += 1;
}
else
{
// There is already one scheduled extra tile-part. In this
// case just add place for the current one
nExtraTp = 1;
}
tileParts[tile] += nExtraTp;
nrOfTileParts = tileParts[tile];
FacilityManager.getMsgLogger().printmsg(CSJ2K.j2k.util.MsgLogger_Fields.WARNING, "Header of tile-part " + tilePart + " of tile " + tile + ", does not indicate the total" + " number of tile-parts. Assuming that there are " + nrOfTileParts + " tile-parts for this tile.");
// Increase and re-copy tilePartLen array
int[] tmpA = tilePartLen[tile];
tilePartLen[tile] = new int[nrOfTileParts];
for (int i = 0; i < nrOfTileParts - nExtraTp; i++)
{
tilePartLen[tile][i] = tmpA[i];
}
// Increase and re-copy tilePartNum array
tmpA = tilePartNum[tile];
tilePartNum[tile] = new int[nrOfTileParts];
for (int i = 0; i < nrOfTileParts - nExtraTp; i++)
{
tilePartNum[tile][i] = tmpA[i];
}
// Increase and re-copy firsPackOff array
tmpA = firstPackOff[tile];
firstPackOff[tile] = new int[nrOfTileParts];
for (int i = 0; i < nrOfTileParts - nExtraTp; i++)
{
firstPackOff[tile][i] = tmpA[i];
}
// Increase and re-copy tilePartHeadLen array
tmpA = tilePartHeadLen[tile];
tilePartHeadLen[tile] = new int[nrOfTileParts];
for (int i = 0; i < nrOfTileParts - nExtraTp; i++)
{
tilePartHeadLen[tile][i] = tmpA[i];
}
}
else
{
// The number of tile-parts is specified in the tile-part
// header
// Check if it is consistant with what was found in previous
// tile-part headers
if (tileParts[tile] == 0)
{
// First tile-part: OK
remainingTileParts += nrOfTileParts - 1;
tileParts[tile] = nrOfTileParts;
tilePartLen[tile] = new int[nrOfTileParts];
tilePartNum[tile] = new int[nrOfTileParts];
firstPackOff[tile] = new int[nrOfTileParts];
tilePartHeadLen[tile] = new int[nrOfTileParts];
}
else if (tileParts[tile] > nrOfTileParts)
{
// Already found more tile-parts than signaled here
throw new CorruptedCodestreamException("Invalid number " + "of tile-parts in" + " tile " + tile + ": " + nrOfTileParts);
}
else
{
// Signaled number of tile-part fits with number of
// previously found tile-parts
remainingTileParts += nrOfTileParts - tileParts[tile];
if (tileParts[tile] != nrOfTileParts)
{
// Increase and re-copy tilePartLen array
int[] tmpA = tilePartLen[tile];
tilePartLen[tile] = new int[nrOfTileParts];
for (int i = 0; i < tileParts[tile] - 1; i++)
{
tilePartLen[tile][i] = tmpA[i];
}
// Increase and re-copy tilePartNum array
tmpA = tilePartNum[tile];
tilePartNum[tile] = new int[nrOfTileParts];
for (int i = 0; i < tileParts[tile] - 1; i++)
{
tilePartNum[tile][i] = tmpA[i];
}
// Increase and re-copy firstPackOff array
tmpA = firstPackOff[tile];
firstPackOff[tile] = new int[nrOfTileParts];
for (int i = 0; i < tileParts[tile] - 1; i++)
{
firstPackOff[tile][i] = tmpA[i];
}
// Increase and re-copy tilePartHeadLen array
tmpA = tilePartHeadLen[tile];
tilePartHeadLen[tile] = new int[nrOfTileParts];
for (int i = 0; i < tileParts[tile] - 1; i++)
{
tilePartHeadLen[tile][i] = tmpA[i];
}
}
}
}
// Other markers
hd.resetHeaderMarkers();
hd.nTileParts[tile] = nrOfTileParts;
// Decode and store the tile-part header (i.e. until a SOD marker is
// found)
do
{
hd.extractTilePartMarkSeg(in_Renamed.readShort(), in_Renamed, tile, tilePart);
}
while ((hd.NumFoundMarkSeg & CSJ2K.j2k.codestream.reader.HeaderDecoder.SOD_FOUND) == 0);
// Read each marker segment previously found
hd.readFoundTilePartMarkSeg(tile, tilePart);
tilePartLen[tile][tilePart] = psot;
tilePartNum[tile][tilePart] = totTilePartsRead;
totTilePartsRead++;
// Add to list of which tile each successive tile-part belongs.
// This list is needed if there are PPM markers used
hd.TileOfTileParts = tile;
return tile;
}
/// <summary> Reads packets of the current tile according to the
/// layer-resolution-component-position progressiveness.
///
/// </summary>
/// <param name="lys">Index of the first layer for each component and resolution.
///
/// </param>
/// <param name="lye">Index of the last layer.
///
/// </param>
/// <param name="ress">Index of the first resolution level.
///
/// </param>
/// <param name="rese">Index of the last resolution level.
///
/// </param>
/// <param name="comps">Index of the first component.
///
/// </param>
/// <param name="compe">Index of the last component.
///
/// </param>
/// <returns> True if rate has been reached.
///
/// </returns>
private bool readLyResCompPos(int[][] lys, int lye, int ress, int rese, int comps, int compe)
{
int minlys = 10000;
for (int c = comps; c < compe; c++)
{
//loop on components
// Check if this component exists
if (c >= mdl.Length)
continue;
for (int r = ress; r < rese; r++)
{
//loop on resolution levels
if (lys[c] != null && r < lys[c].Length && lys[c][r] < minlys)
{
minlys = lys[c][r];
}
}
}
int t = TileIdx;
int start;
bool status = false;
int lastByte = firstPackOff[t][curTilePart] + tilePartLen[t][curTilePart] - 1 - tilePartHeadLen[t][curTilePart];
int numLayers = ((System.Int32) decSpec.nls.getTileDef(t));
int nPrec = 1;
int hlen, plen;
bool pph = false;
if (((System.Boolean) decSpec.pphs.getTileDef(t)))
{
pph = true;
}
for (int l = minlys; l < lye; l++)
{
// store the layer starting position
layerStarts.Add(in_Renamed.Pos);
// loop on layers
for (int r = ress; r < rese; r++)
{
// loop on resolution levels
for (int c = comps; c < compe; c++)
{
// loop on components
// Checks if component exists
if (c >= mdl.Length)
continue;
// Checks if resolution level exists
if (r >= lys[c].Length)
continue;
if (r > mdl[c])
continue;
// Checks if layer exists
if (l < lys[c][r] || l >= numLayers)
continue;
nPrec = pktDec.getNumPrecinct(c, r);
for (int p = 0; p < nPrec; p++)
{
// loop on precincts
start = in_Renamed.Pos;
// If packed packet headers are used, there is no need
// to check that there are bytes enough to read header
if (pph)
{
pktDec.readPktHead(l, r, c, p, cbI[c][r], nBytes);
}
// If we are about to read outside of tile-part,
// skip to next tile-part
if (start > lastByte && curTilePart < firstPackOff[t].Length - 1)
{
curTilePart++;
in_Renamed.seek(firstPackOff[t][curTilePart]);
lastByte = in_Renamed.Pos + tilePartLen[t][curTilePart] - 1 - tilePartHeadLen[t][curTilePart];
}
// Read SOP marker segment if necessary
status = pktDec.readSOPMarker(nBytes, p, c, r);
if (status)
{
if (printInfo)
{
}
return true;
}
if (!pph)
{
status = pktDec.readPktHead(l, r, c, p, cbI[c][r], nBytes);
}
if (status)
{
if (printInfo)
{
}
return true;
}
// Store packet's head length
hlen = in_Renamed.Pos - start;
pktHL.Add((System.Int32) hlen);
// Reads packet's body
status = pktDec.readPktBody(l, r, c, p, cbI[c][r], nBytes);
plen = in_Renamed.Pos - start;
if (status)
{
if (printInfo)
{
}
return true;
}
} // end loop on precincts
} // end loop on components
} // end loop on resolution levels
} // end loop on layers
if (printInfo)
{
}
return false; // Decoding rate was not reached
}
/// <summary> Reads packets of the current tile according to the
/// resolution-layer-component-position progressiveness.
///
/// </summary>
/// <param name="lys">Index of the first layer for each component and resolution.
///
/// </param>
/// <param name="lye">Index of the last layer.
///
/// </param>
/// <param name="ress">Index of the first resolution level.
///
/// </param>
/// <param name="rese">Index of the last resolution level.
///
/// </param>
/// <param name="comps">Index of the first component.
///
/// </param>
/// <param name="compe">Index of the last component.
///
/// </param>
/// <returns> True if rate has been reached.
///
/// </returns>
private bool readResLyCompPos(int[][] lys, int lye, int ress, int rese, int comps, int compe)
{
int t = TileIdx; // Current tile index
bool status = false; // True if decoding rate is reached when
int lastByte = firstPackOff[t][curTilePart] + tilePartLen[t][curTilePart] - 1 - tilePartHeadLen[t][curTilePart];
int minlys = 10000;
for (int c = comps; c < compe; c++)
{
//loop on components
// Check if this component exists
if (c >= mdl.Length)
continue;
for (int r = ress; r < rese; r++)
{
//loop on resolution levels
if (r > mdl[c])
continue;
if (lys[c] != null && r < lys[c].Length && lys[c][r] < minlys)
{
minlys = lys[c][r];
}
}
}
int numLayers = ((System.Int32) decSpec.nls.getTileDef(t));
bool pph = false;
if (((System.Boolean) decSpec.pphs.getTileDef(t)))
{
pph = true;
}
int nPrec = 1;
int start;
int hlen, plen;
for (int r = ress; r < rese; r++)
{
// loop on resolution levels
for (int l = minlys; l < lye; l++)
{
// loop on layers
for (int c = comps; c < compe; c++)
{
// loop on components
// Checks if component exists
if (c >= mdl.Length)
continue;
// Checks if resolution level exists
if (r > mdl[c])
continue;
if (r >= lys[c].Length)
continue;
// Checks if layer exists
if (l < lys[c][r] || l >= numLayers)
continue;
nPrec = pktDec.getNumPrecinct(c, r);
for (int p = 0; p < nPrec; p++)
{
// loop on precincts
start = in_Renamed.Pos;
// If packed packet headers are used, there is no need
// to check that there are bytes enough to read header
if (pph)
{
pktDec.readPktHead(l, r, c, p, cbI[c][r], nBytes);
}
// If we are about to read outside of tile-part,
// skip to next tile-part
if (start > lastByte && curTilePart < firstPackOff[t].Length - 1)
{
curTilePart++;
in_Renamed.seek(firstPackOff[t][curTilePart]);
lastByte = in_Renamed.Pos + tilePartLen[t][curTilePart] - 1 - tilePartHeadLen[t][curTilePart];
}
// Read SOP marker segment if necessary
status = pktDec.readSOPMarker(nBytes, p, c, r);
if (status)
{
if (printInfo)
{
}
return true;
}
if (!pph)
{
status = pktDec.readPktHead(l, r, c, p, cbI[c][r], nBytes);
}
if (status)
{
if (printInfo)
{
}
// Output rate of EOF reached
return true;
}
// Store packet's head length
hlen = in_Renamed.Pos - start;
pktHL.Add((System.Int32) hlen);
// Reads packet's body
status = pktDec.readPktBody(l, r, c, p, cbI[c][r], nBytes);
plen = in_Renamed.Pos - start;
if (status)
{
if (printInfo)
{
}
// Output rate or EOF reached
return true;
}
} // end loop on precincts
} // end loop on components
} // end loop on layers
} // end loop on resolution levels
if (printInfo)
{
}
return false; // Decoding rate was not reached
}
/// <summary> Reads packets of the current tile according to the
/// resolution-position-component-layer progressiveness.
///
/// </summary>
/// <param name="lys">Index of the first layer for each component and resolution.
///
/// </param>
/// <param name="lye">Index of the last layer.
///
/// </param>
/// <param name="ress">Index of the first resolution level.
///
/// </param>
/// <param name="rese">Index of the last resolution level.
///
/// </param>
/// <param name="comps">Index of the first component.
///
/// </param>
/// <param name="compe">Index of the last component.
///
/// </param>
/// <returns> True if rate has been reached.
///
/// </returns>
private bool readResPosCompLy(int[][] lys, int lye, int ress, int rese, int comps, int compe)
{
// Computes current tile offset in the reference grid
Coord nTiles = getNumTiles(null);
Coord tileI = getTile(null);
int x0siz = hd.ImgULX;
int y0siz = hd.ImgULY;
int xsiz = x0siz + hd.ImgWidth;
int ysiz = y0siz + hd.ImgHeight;
int xt0siz = TilePartULX;
int yt0siz = TilePartULY;
int xtsiz = NomTileWidth;
int ytsiz = NomTileHeight;
int tx0 = (tileI.x == 0)?x0siz:xt0siz + tileI.x * xtsiz;
int ty0 = (tileI.y == 0)?y0siz:yt0siz + tileI.y * ytsiz;
int tx1 = (tileI.x != nTiles.x - 1)?xt0siz + (tileI.x + 1) * xtsiz:xsiz;
int ty1 = (tileI.y != nTiles.y - 1)?yt0siz + (tileI.y + 1) * ytsiz:ysiz;
// Get precinct information (number,distance between two consecutive
// precincts in the reference grid) in each component and resolution
// level
int t = TileIdx; // Current tile index
PrecInfo prec; // temporary variable
int p; // Current precinct index
int gcd_x = 0; // Horiz. distance between 2 precincts in the ref. grid
int gcd_y = 0; // Vert. distance between 2 precincts in the ref. grid
int nPrec = 0; // Total number of found precincts
int[][] nextPrec = new int[compe][]; // Next precinct index in each
// component and resolution level
int minlys = 100000; // minimum layer start index of each component
int minx = tx1; // Horiz. offset of the second precinct in the
// reference grid
int miny = ty1; // Vert. offset of the second precinct in the
// reference grid.
int maxx = tx0; // Max. horiz. offset of precincts in the ref. grid
int maxy = ty0; // Max. vert. offset of precincts in the ref. grid
//Coord numPrec;
for (int c = comps; c < compe; c++)
{
// components
for (int r = ress; r < rese; r++)
{
// resolution levels
if (c >= mdl.Length)
continue;
if (r > mdl[c])
continue;
nextPrec[c] = new int[mdl[c] + 1];
if (lys[c] != null && r < lys[c].Length && lys[c][r] < minlys)
{
minlys = lys[c][r];
}
p = pktDec.getNumPrecinct(c, r) - 1;
for (; p >= 0; p--)
{
prec = pktDec.getPrecInfo(c, r, p);
if (prec.rgulx != tx0)
{
if (prec.rgulx < minx)
minx = prec.rgulx;
if (prec.rgulx > maxx)
maxx = prec.rgulx;
}
if (prec.rguly != ty0)
{
if (prec.rguly < miny)
miny = prec.rguly;
if (prec.rguly > maxy)
maxy = prec.rguly;
}
if (nPrec == 0)
{
gcd_x = prec.rgw;
gcd_y = prec.rgh;
}
else
{
gcd_x = MathUtil.gcd(gcd_x, prec.rgw);
gcd_y = MathUtil.gcd(gcd_y, prec.rgh);
}
nPrec++;
} // precincts
} // resolution levels
} // components
if (nPrec == 0)
{
throw new System.ApplicationException("Image cannot have no precinct");
}
int pyend = (maxy - miny) / gcd_y + 1;
int pxend = (maxx - minx) / gcd_x + 1;
int x, y;
int hlen, plen;
int start;
bool status = false;
int lastByte = firstPackOff[t][curTilePart] + tilePartLen[t][curTilePart] - 1 - tilePartHeadLen[t][curTilePart];
int numLayers = ((System.Int32) decSpec.nls.getTileDef(t));
bool pph = false;
if (((System.Boolean) decSpec.pphs.getTileDef(t)))
{
pph = true;
}
for (int r = ress; r < rese; r++)
{
// loop on resolution levels
y = ty0;
x = tx0;
for (int py = 0; py <= pyend; py++)
{
// Vertical precincts
for (int px = 0; px <= pxend; px++)
{
// Horiz. precincts
for (int c = comps; c < compe; c++)
{
// Components
if (c >= mdl.Length)
continue;
if (r > mdl[c])
continue;
if (nextPrec[c][r] >= pktDec.getNumPrecinct(c, r))
{
continue;
}
prec = pktDec.getPrecInfo(c, r, nextPrec[c][r]);
if ((prec.rgulx != x) || (prec.rguly != y))
{
continue;
}
for (int l = minlys; l < lye; l++)
{
// layers
if (r >= lys[c].Length)
continue;
if (l < lys[c][r] || l >= numLayers)
continue;
start = in_Renamed.Pos;
// If packed packet headers are used, there is no
// need to check that there are bytes enough to
// read header
if (pph)
{
pktDec.readPktHead(l, r, c, nextPrec[c][r], cbI[c][r], nBytes);
}
// If we are about to read outside of tile-part,
// skip to next tile-part
if (start > lastByte && curTilePart < firstPackOff[t].Length - 1)
{
curTilePart++;
in_Renamed.seek(firstPackOff[t][curTilePart]);
lastByte = in_Renamed.Pos + tilePartLen[t][curTilePart] - 1 - tilePartHeadLen[t][curTilePart];
}
// Read SOP marker segment if necessary
status = pktDec.readSOPMarker(nBytes, nextPrec[c][r], c, r);
if (status)
{
if (printInfo)
{
}
return true;
}
if (!pph)
{
status = pktDec.readPktHead(l, r, c, nextPrec[c][r], cbI[c][r], nBytes);
}
if (status)
{
if (printInfo)
{
}
return true;
}
// Store packet's head length
hlen = in_Renamed.Pos - start;
pktHL.Add((System.Int32) hlen);
// Reads packet's body
status = pktDec.readPktBody(l, r, c, nextPrec[c][r], cbI[c][r], nBytes);
plen = in_Renamed.Pos - start;
if (status)
{
if (printInfo)
{
}
return true;
}
} // layers
nextPrec[c][r]++;
} // Components
if (px != pxend)
{
x = minx + px * gcd_x;
}
else
{
x = tx0;
}
} // Horizontal precincts
if (py != pyend)
{
y = miny + py * gcd_y;
}
else
{
y = ty0;
}
} // Vertical precincts
} // end loop on resolution levels
if (printInfo)
{
}
return false; // Decoding rate was not reached
}
/// <summary> Reads packets of the current tile according to the
/// position-component-resolution-layer progressiveness.
///
/// </summary>
/// <param name="lys">Index of the first layer for each component and resolution.
///
/// </param>
/// <param name="lye">Index of the last layer.
///
/// </param>
/// <param name="ress">Index of the first resolution level.
///
/// </param>
/// <param name="rese">Index of the last resolution level.
///
/// </param>
/// <param name="comps">Index of the first component.
///
/// </param>
/// <param name="compe">Index of the last component.
///
/// </param>
/// <returns> True if rate has been reached.
///
/// </returns>
private bool readPosCompResLy(int[][] lys, int lye, int ress, int rese, int comps, int compe)
{
Coord nTiles = getNumTiles(null);
Coord tileI = getTile(null);
int x0siz = hd.ImgULX;
int y0siz = hd.ImgULY;
int xsiz = x0siz + hd.ImgWidth;
int ysiz = y0siz + hd.ImgHeight;
int xt0siz = TilePartULX;
int yt0siz = TilePartULY;
int xtsiz = NomTileWidth;
int ytsiz = NomTileHeight;
int tx0 = (tileI.x == 0)?x0siz:xt0siz + tileI.x * xtsiz;
int ty0 = (tileI.y == 0)?y0siz:yt0siz + tileI.y * ytsiz;
int tx1 = (tileI.x != nTiles.x - 1)?xt0siz + (tileI.x + 1) * xtsiz:xsiz;
int ty1 = (tileI.y != nTiles.y - 1)?yt0siz + (tileI.y + 1) * ytsiz:ysiz;
// Get precinct information (number,distance between two consecutive
// precincts in the reference grid) in each component and resolution
// level
int t = TileIdx; // Current tile index
PrecInfo prec; // temporary variable
int p; // Current precinct index
int gcd_x = 0; // Horiz. distance between 2 precincts in the ref. grid
int gcd_y = 0; // Vert. distance between 2 precincts in the ref. grid
int nPrec = 0; // Total number of found precincts
int[][] nextPrec = new int[compe][]; // Next precinct index in each
// component and resolution level
int minlys = 100000; // minimum layer start index of each component
int minx = tx1; // Horiz. offset of the second precinct in the
// reference grid
int miny = ty1; // Vert. offset of the second precinct in the
// reference grid.
int maxx = tx0; // Max. horiz. offset of precincts in the ref. grid
int maxy = ty0; // Max. vert. offset of precincts in the ref. grid
//Coord numPrec;
for (int c = comps; c < compe; c++)
{
// components
for (int r = ress; r < rese; r++)
{
// resolution levels
if (c >= mdl.Length)
continue;
if (r > mdl[c])
continue;
nextPrec[c] = new int[mdl[c] + 1];
if (lys[c] != null && r < lys[c].Length && lys[c][r] < minlys)
{
minlys = lys[c][r];
}
p = pktDec.getNumPrecinct(c, r) - 1;
for (; p >= 0; p--)
{
prec = pktDec.getPrecInfo(c, r, p);
if (prec.rgulx != tx0)
{
if (prec.rgulx < minx)
minx = prec.rgulx;
if (prec.rgulx > maxx)
maxx = prec.rgulx;
}
if (prec.rguly != ty0)
{
if (prec.rguly < miny)
miny = prec.rguly;
if (prec.rguly > maxy)
maxy = prec.rguly;
}
if (nPrec == 0)
{
gcd_x = prec.rgw;
gcd_y = prec.rgh;
}
else
{
gcd_x = MathUtil.gcd(gcd_x, prec.rgw);
gcd_y = MathUtil.gcd(gcd_y, prec.rgh);
}
nPrec++;
} // precincts
} // resolution levels
} // components
if (nPrec == 0)
{
throw new System.ApplicationException("Image cannot have no precinct");
}
int pyend = (maxy - miny) / gcd_y + 1;
int pxend = (maxx - minx) / gcd_x + 1;
int hlen, plen;
int start;
bool status = false;
int lastByte = firstPackOff[t][curTilePart] + tilePartLen[t][curTilePart] - 1 - tilePartHeadLen[t][curTilePart];
int numLayers = ((System.Int32) decSpec.nls.getTileDef(t));
bool pph = false;
if (((System.Boolean) decSpec.pphs.getTileDef(t)))
{
pph = true;
}
int y = ty0;
int x = tx0;
for (int py = 0; py <= pyend; py++)
{
// Vertical precincts
for (int px = 0; px <= pxend; px++)
{
// Horiz. precincts
for (int c = comps; c < compe; c++)
{
// Components
if (c >= mdl.Length)
continue;
for (int r = ress; r < rese; r++)
{
// Resolution levels
if (r > mdl[c])
continue;
if (nextPrec[c][r] >= pktDec.getNumPrecinct(c, r))
{
continue;
}
prec = pktDec.getPrecInfo(c, r, nextPrec[c][r]);
if ((prec.rgulx != x) || (prec.rguly != y))
{
continue;
}
for (int l = minlys; l < lye; l++)
{
// Layers
if (r >= lys[c].Length)
continue;
if (l < lys[c][r] || l >= numLayers)
continue;
start = in_Renamed.Pos;
// If packed packet headers are used, there is no
// need to check that there are bytes enough to
// read header
if (pph)
{
pktDec.readPktHead(l, r, c, nextPrec[c][r], cbI[c][r], nBytes);
}
// If we are about to read outside of tile-part,
// skip to next tile-part
if (start > lastByte && curTilePart < firstPackOff[t].Length - 1)
{
curTilePart++;
in_Renamed.seek(firstPackOff[t][curTilePart]);
lastByte = in_Renamed.Pos + tilePartLen[t][curTilePart] - 1 - tilePartHeadLen[t][curTilePart];
}
// Read SOP marker segment if necessary
status = pktDec.readSOPMarker(nBytes, nextPrec[c][r], c, r);
if (status)
{
if (printInfo)
{
}
return true;
}
if (!pph)
{
status = pktDec.readPktHead(l, r, c, nextPrec[c][r], cbI[c][r], nBytes);
}
if (status)
{
if (printInfo)
{
}
return true;
}
// Store packet's head length
hlen = in_Renamed.Pos - start;
pktHL.Add((System.Int32) hlen);
// Reads packet's body
status = pktDec.readPktBody(l, r, c, nextPrec[c][r], cbI[c][r], nBytes);
plen = in_Renamed.Pos - start;
if (status)
{
if (printInfo)
{
}
return true;
}
} // layers
nextPrec[c][r]++;
} // Resolution levels
} // Components
if (px != pxend)
{
x = minx + px * gcd_x;
}
else
{
x = tx0;
}
} // Horizontal precincts
if (py != pyend)
{
y = miny + py * gcd_y;
}
else
{
y = ty0;
}
} // Vertical precincts
if (printInfo)
{
}
return false; // Decoding rate was not reached
}
/// <summary> Reads packets of the current tile according to the
/// component-position-resolution-layer progressiveness.
///
/// </summary>
/// <param name="lys">Index of the first layer for each component and resolution.
///
/// </param>
/// <param name="lye">Index of the last layer.
///
/// </param>
/// <param name="ress">Index of the first resolution level.
///
/// </param>
/// <param name="rese">Index of the last resolution level.
///
/// </param>
/// <param name="comps">Index of the first component.
///
/// </param>
/// <param name="compe">Index of the last component.
///
/// </param>
/// <returns> True if rate has been reached.
///
/// </returns>
private bool readCompPosResLy(int[][] lys, int lye, int ress, int rese, int comps, int compe)
{
Coord nTiles = getNumTiles(null);
Coord tileI = getTile(null);
int x0siz = hd.ImgULX;
int y0siz = hd.ImgULY;
int xsiz = x0siz + hd.ImgWidth;
int ysiz = y0siz + hd.ImgHeight;
int xt0siz = TilePartULX;
int yt0siz = TilePartULY;
int xtsiz = NomTileWidth;
int ytsiz = NomTileHeight;
int tx0 = (tileI.x == 0)?x0siz:xt0siz + tileI.x * xtsiz;
int ty0 = (tileI.y == 0)?y0siz:yt0siz + tileI.y * ytsiz;
int tx1 = (tileI.x != nTiles.x - 1)?xt0siz + (tileI.x + 1) * xtsiz:xsiz;
int ty1 = (tileI.y != nTiles.y - 1)?yt0siz + (tileI.y + 1) * ytsiz:ysiz;
// Get precinct information (number,distance between two consecutive
// precincts in the reference grid) in each component and resolution
// level
int t = TileIdx; // Current tile index
PrecInfo prec; // temporary variable
int p; // Current precinct index
int gcd_x = 0; // Horiz. distance between 2 precincts in the ref. grid
int gcd_y = 0; // Vert. distance between 2 precincts in the ref. grid
int nPrec = 0; // Total number of found precincts
int[][] nextPrec = new int[compe][]; // Next precinct index in each
// component and resolution level
int minlys = 100000; // minimum layer start index of each component
int minx = tx1; // Horiz. offset of the second precinct in the
// reference grid
int miny = ty1; // Vert. offset of the second precinct in the
// reference grid.
int maxx = tx0; // Max. horiz. offset of precincts in the ref. grid
int maxy = ty0; // Max. vert. offset of precincts in the ref. grid
//Coord numPrec;
for (int c = comps; c < compe; c++)
{
// components
for (int r = ress; r < rese; r++)
{
// resolution levels
if (c >= mdl.Length)
continue;
if (r > mdl[c])
continue;
nextPrec[c] = new int[mdl[c] + 1];
if (lys[c] != null && r < lys[c].Length && lys[c][r] < minlys)
{
minlys = lys[c][r];
}
p = pktDec.getNumPrecinct(c, r) - 1;
for (; p >= 0; p--)
{
prec = pktDec.getPrecInfo(c, r, p);
if (prec.rgulx != tx0)
{
if (prec.rgulx < minx)
minx = prec.rgulx;
if (prec.rgulx > maxx)
maxx = prec.rgulx;
}
if (prec.rguly != ty0)
{
if (prec.rguly < miny)
miny = prec.rguly;
if (prec.rguly > maxy)
maxy = prec.rguly;
}
if (nPrec == 0)
{
gcd_x = prec.rgw;
gcd_y = prec.rgh;
}
else
{
gcd_x = MathUtil.gcd(gcd_x, prec.rgw);
gcd_y = MathUtil.gcd(gcd_y, prec.rgh);
}
nPrec++;
} // precincts
} // resolution levels
} // components
if (nPrec == 0)
{
throw new System.ApplicationException("Image cannot have no precinct");
}
int pyend = (maxy - miny) / gcd_y + 1;
int pxend = (maxx - minx) / gcd_x + 1;
int hlen, plen;
int start;
bool status = false;
int lastByte = firstPackOff[t][curTilePart] + tilePartLen[t][curTilePart] - 1 - tilePartHeadLen[t][curTilePart];
int numLayers = ((System.Int32) decSpec.nls.getTileDef(t));
bool pph = false;
if (((System.Boolean) decSpec.pphs.getTileDef(t)))
{
pph = true;
}
int x, y;
for (int c = comps; c < compe; c++)
{
// components
if (c >= mdl.Length)
continue;
y = ty0;
x = tx0;
for (int py = 0; py <= pyend; py++)
{
// Vertical precincts
for (int px = 0; px <= pxend; px++)
{
// Horiz. precincts
for (int r = ress; r < rese; r++)
{
// Resolution levels
if (r > mdl[c])
continue;
if (nextPrec[c][r] >= pktDec.getNumPrecinct(c, r))
{
continue;
}
prec = pktDec.getPrecInfo(c, r, nextPrec[c][r]);
if ((prec.rgulx != x) || (prec.rguly != y))
{
continue;
}
for (int l = minlys; l < lye; l++)
{
// Layers
if (r >= lys[c].Length)
continue;
if (l < lys[c][r])
continue;
start = in_Renamed.Pos;
// If packed packet headers are used, there is no
// need to check that there are bytes enough to
// read header
if (pph)
{
pktDec.readPktHead(l, r, c, nextPrec[c][r], cbI[c][r], nBytes);
}
// If we are about to read outside of tile-part,
// skip to next tile-part
if (start > lastByte && curTilePart < firstPackOff[t].Length - 1)
{
curTilePart++;
in_Renamed.seek(firstPackOff[t][curTilePart]);
lastByte = in_Renamed.Pos + tilePartLen[t][curTilePart] - 1 - tilePartHeadLen[t][curTilePart];
}
// Read SOP marker segment if necessary
status = pktDec.readSOPMarker(nBytes, nextPrec[c][r], c, r);
if (status)
{
if (printInfo)
{
}
return true;
}
if (!pph)
{
status = pktDec.readPktHead(l, r, c, nextPrec[c][r], cbI[c][r], nBytes);
}
if (status)
{
if (printInfo)
{
}
return true;
}
// Store packet's head length
hlen = in_Renamed.Pos - start;
pktHL.Add((System.Int32) hlen);
// Reads packet's body
status = pktDec.readPktBody(l, r, c, nextPrec[c][r], cbI[c][r], nBytes);
plen = in_Renamed.Pos - start;
if (status)
{
if (printInfo)
{
}
return true;
}
} // layers
nextPrec[c][r]++;
} // Resolution levels
if (px != pxend)
{
x = minx + px * gcd_x;
}
else
{
x = tx0;
}
} // Horizontal precincts
if (py != pyend)
{
y = miny + py * gcd_y;
}
else
{
y = ty0;
}
} // Vertical precincts
} // components
if (printInfo)
{
}
return false; // Decoding rate was not reached
}
/// <summary> Finish initialization of members for specified tile, reads packets head
/// of each tile and keeps location of each code-block's codewords. The
/// last 2 tasks are done by calling specific methods of PktDecoder.
///
/// <p>Then, if a parsing output rate is defined, it keeps information of
/// first layers only. This operation simulates a creation of a
/// layer-resolution-component progressive bit-stream which will be next
/// truncated and decoded.</p>
///
/// </summary>
/// <param name="t">Tile index
///
/// </param>
/// <seealso cref="PktDecoder">
///
/// </seealso>
private void readTilePkts(int t)
{
pktHL = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
layerStarts = new System.Collections.Generic.List<int>(5);
// Number of layers
int nl = ((System.Int32) decSpec.nls.getTileDef(t));
// If packed packet headers was used, get the packet headers for this
// tile
if (((System.Boolean) decSpec.pphs.getTileDef(t)))
{
// Gets packed headers as separate input stream
System.IO.MemoryStream pphbais = hd.getPackedPktHead(t);
// Restarts PktDecoder instance
cbI = pktDec.restart(this.nc, mdl, nl, cbI, true, pphbais);
}
else
{
// Restarts PktDecoder instance
cbI = pktDec.restart(this.nc, mdl, nl, cbI, false, null);
}
// Reads packets of the tile according to the progression order
int[][] pocSpec = ((int[][]) decSpec.pcs.getTileDef(t));
int nChg = (pocSpec == null)?1:pocSpec.Length;
// Create an array containing information about changes (progression
// order type, layers index start, layer index end, resolution level
// start, resolution level end, component index start, component index
// end). There is one row per progresion order
int[][] change = new int[nChg][];
for (int i = 0; i < nChg; i++)
{
change[i] = new int[6];
}
int idx = 0; // Index of the current progression order
change[0][1] = 0; // layer start
if (pocSpec == null)
{
change[idx][0] = ((System.Int32) decSpec.pos.getTileDef(t));
// Progression type found in COx marker segments
change[idx][1] = nl; // Layer index end
change[idx][2] = 0; // resolution level start
change[idx][3] = decSpec.dls.getMaxInTile(t) + 1; // res. level end
change[idx][4] = 0; // Component index start
change[idx][5] = this.nc; // Component index end
}
else
{
for (idx = 0; idx < nChg; idx++)
{
change[idx][0] = pocSpec[idx][5];
change[idx][1] = pocSpec[idx][2]; // layer end
change[idx][2] = pocSpec[idx][0]; // res. lev. start
change[idx][3] = pocSpec[idx][3]; // res. lev. end
change[idx][4] = pocSpec[idx][1]; // Comp. index start
change[idx][5] = pocSpec[idx][4]; // Comp. index end
}
}
// Seeks to the first packet of the first tile-part
try
{
// If in truncation mode, the first tile-part may be beyond the
// target decoding rate. In this case, the offset of the first
// packet is not defined.
if (isTruncMode && firstPackOff == null || firstPackOff[t] == null)
{
return ;
}
in_Renamed.seek(firstPackOff[t][0]);
}
catch (System.IO.EndOfStreamException)
{
FacilityManager.getMsgLogger().printmsg(CSJ2K.j2k.util.MsgLogger_Fields.WARNING, "Codestream truncated in tile " + t);
return ;
}
curTilePart = 0;
// Start and end indexes for layers, resolution levels and components.
int lye, ress, rese, comps, compe;
bool status = false;
int nb = nBytes[t];
int[][] lys = new int[this.nc][];
for (int c = 0; c < this.nc; c++)
{
lys[c] = new int[((System.Int32) decSpec.dls.getTileCompVal(t, c)) + 1];
}
try
{
for (int chg = 0; chg < nChg; chg++)
{
lye = change[chg][1];
ress = change[chg][2];
rese = change[chg][3];
comps = change[chg][4];
compe = change[chg][5];
switch (change[chg][0])
{
case CSJ2K.j2k.codestream.ProgressionType.LY_RES_COMP_POS_PROG:
status = readLyResCompPos(lys, lye, ress, rese, comps, compe);
break;
case CSJ2K.j2k.codestream.ProgressionType.RES_LY_COMP_POS_PROG:
status = readResLyCompPos(lys, lye, ress, rese, comps, compe);
break;
case CSJ2K.j2k.codestream.ProgressionType.RES_POS_COMP_LY_PROG:
status = readResPosCompLy(lys, lye, ress, rese, comps, compe);
break;
case CSJ2K.j2k.codestream.ProgressionType.POS_COMP_RES_LY_PROG:
status = readPosCompResLy(lys, lye, ress, rese, comps, compe);
break;
case CSJ2K.j2k.codestream.ProgressionType.COMP_POS_RES_LY_PROG:
status = readCompPosResLy(lys, lye, ress, rese, comps, compe);
break;
default:
throw new System.ArgumentException("Not recognized " + "progression type");
}
// Update next first layer index
for (int c = comps; c < compe; c++)
{
if (c >= lys.Length)
continue;
for (int r = ress; r < rese; r++)
{
if (r >= lys[c].Length)
continue;
lys[c][r] = lye;
}
}
if (status || usePOCQuit)
{
break;
}
}
}
catch (System.IO.EndOfStreamException e)
{
// Should never happen. Truncated codestream are normally found by
// the class constructor
throw e;
}
// In truncation mode, update the number of read bytes
if (isTruncMode)
{
anbytes += nb - nBytes[t];
// If truncation rate is reached
if (status)
{
nBytes[t] = 0;
}
}
else if (nBytes[t] < (totTileLen[t] - totTileHeadLen[t]))
{
// In parsing mode, if there is not enough rate to entirely read the
// tile. Then, parses the bit stream so as to create a virtual
// layer-resolution-component progressive bit stream that will be
// truncated and decoded afterwards.
CBlkInfo cb;
// Systematicaly reject all remaining code-blocks if one
// code-block, at least, is refused.
bool reject;
// Stop reading any data from the bit stream
bool stopCount = false;
// Length of each packet's head (in an array)
int[] pktHeadLen = new int[pktHL.Count];
for (int i = pktHL.Count - 1; i >= 0; i--)
{
pktHeadLen[i] = ((System.Int32) pktHL[i]);
}
// Parse each code-block, layer per layer until nBytes[t] is
// reached
reject = false;
for (int l = 0; l < nl; l++)
{
// layers
if (cbI == null)
continue;
int nc = cbI.Length;
int mres = 0;
for (int c = 0; c < nc; c++)
{
if (cbI[c] != null && cbI[c].Length > mres)
mres = cbI[c].Length;
}
for (int r = 0; r < mres; r++)
{
// resolutions
int msub = 0;
for (int c = 0; c < nc; c++)
{
if (cbI[c] != null && cbI[c][r] != null && cbI[c][r].Length > msub)
msub = cbI[c][r].Length;
}
for (int s = 0; s < msub; s++)
{
// subbands
// Only LL subband resolution level 0
if (r == 0 && s != 0)
{
continue;
}
else if (r != 0 && s == 0)
{
// No LL subband in resolution level > 0
continue;
}
int mnby = 0;
for (int c = 0; c < nc; c++)
{
if (cbI[c] != null && cbI[c][r] != null && cbI[c][r][s] != null && cbI[c][r][s].Length > mnby)
mnby = cbI[c][r][s].Length;
}
for (int m = 0; m < mnby; m++)
{
int mnbx = 0;
for (int c = 0; c < nc; c++)
{
if (cbI[c] != null && cbI[c][r] != null && cbI[c][r][s] != null && cbI[c][r][s][m] != null && cbI[c][r][s][m].Length > mnbx)
mnbx = cbI[c][r][s][m].Length;
}
for (int n = 0; n < mnbx; n++)
{
for (int c = 0; c < nc; c++)
{
if (cbI[c] == null || cbI[c][r] == null || cbI[c][r][s] == null || cbI[c][r][s][m] == null || cbI[c][r][s][m][n] == null)
{
continue;
}
cb = cbI[c][r][s][m][n];
// If no code-block has been refused until
// now
if (!reject)
{
// Rate is to low to allow reading of
// packet's head
if (nBytes[t] < pktHeadLen[cb.pktIdx[l]])
{
// Stop parsing
stopCount = true;
// Reject all next
// code-blocks
reject = true;
}
else
{
// Rate is enough to read packet's
// head
if (!stopCount)
{
//If parsing was not stopped
//Takes into account packet's
//head length
nBytes[t] -= pktHeadLen[cb.pktIdx[l]];
anbytes += pktHeadLen[cb.pktIdx[l]];
// Set packet's head length to
// 0, so that it won't be
// taken into account next
// time
pktHeadLen[cb.pktIdx[l]] = 0;
}
}
}
// Code-block has no data in this layer
if (cb.len[l] == 0)
{
continue;
}
// Accepts code-block if length is enough,
// if this code-block was not refused in a
// previous layer and if no code-block was
// refused in current component
if (cb.len[l] < nBytes[t] && !reject)
{
nBytes[t] -= cb.len[l];
anbytes += cb.len[l];
}
else
{
// Refuses code-block
// Forgets code-block's data
cb.len[l] = cb.off[l] = cb.ntp[l] = 0;
// Refuses all other code-block in
// current and next component
reject = true;
}
} // End loop on components
} // End loop on horiz. code-blocks
} // End loop on vert. code-blocks
} // End loop on subbands
} // End loop on resolutions
} // End loop on layers
}
else
{
// No parsing for this tile, adds tile's body to the total
// number of read bytes.
anbytes += totTileLen[t] - totTileHeadLen[t];
if (t < getNumTiles() - 1)
{
nBytes[t + 1] += nBytes[t] - (totTileLen[t] - totTileHeadLen[t]);
}
}
}
/// <summary> Changes the current tile, given the new indexes. An
/// IllegalArgumentException is thrown if the indexes do not correspond to
/// a valid tile.
///
/// </summary>
/// <param name="x">The horizontal indexes the tile.
///
/// </param>
/// <param name="y">The vertical indexes of the new tile.
///
/// </param>
public override void setTile(int x, int y)
{
int i; // counter
// Check validity of tile indexes
if (x < 0 || y < 0 || x >= ntX || y >= ntY)
{
throw new System.ArgumentException();
}
int t = (y * ntX + x);
// Reset number of read bytes if needed
if (t == 0)
{
anbytes = headLen;
if (!isTruncMode)
{
anbytes += 2;
}
// Restore values of nBytes
for (int tIdx = 0; tIdx < nt; tIdx++)
{
nBytes[tIdx] = baknBytes[tIdx];
}
}
// Set the new current tile
ctX = x;
ctY = y;
// Calculate tile relative points
int ctox = (x == 0)?ax:px + x * ntW;
int ctoy = (y == 0)?ay:py + y * ntH;
for (i = nc - 1; i >= 0; i--)
{
culx[i] = (ctox + hd.getCompSubsX(i) - 1) / hd.getCompSubsX(i);
culy[i] = (ctoy + hd.getCompSubsY(i) - 1) / hd.getCompSubsY(i);
offX[i] = (px + x * ntW + hd.getCompSubsX(i) - 1) / hd.getCompSubsX(i);
offY[i] = (py + y * ntH + hd.getCompSubsY(i) - 1) / hd.getCompSubsY(i);
}
// Initialize subband tree and number of resolution levels
subbTrees = new SubbandSyn[nc];
mdl = new int[nc];
derived = new bool[nc];
params_Renamed = new StdDequantizerParams[nc];
gb = new int[nc];
for (int c = 0; c < nc; c++)
{
derived[c] = decSpec.qts.isDerived(t, c);
params_Renamed[c] = (StdDequantizerParams) decSpec.qsss.getTileCompVal(t, c);
gb[c] = ((System.Int32) decSpec.gbs.getTileCompVal(t, c));
mdl[c] = ((System.Int32) decSpec.dls.getTileCompVal(t, c));
subbTrees[c] = new SubbandSyn(getTileCompWidth(t, c, mdl[c]), getTileCompHeight(t, c, mdl[c]), getResULX(c, mdl[c]), getResULY(c, mdl[c]), mdl[c], decSpec.wfs.getHFilters(t, c), decSpec.wfs.getVFilters(t, c));
initSubbandsFields(c, subbTrees[c]);
}
// Read tile's packets
try
{
readTilePkts(t);
}
catch (System.IO.IOException e)
{
SupportClass.WriteStackTrace(e, Console.Error);
throw new System.ApplicationException("IO Error when reading tile " + x + " x " + y);
}
}
/// <summary> Advances to the next tile, in standard scan-line order (by rows then
/// columns). A NoNextElementException is thrown if the current tile is the
/// last one (i.e. there is no next tile).
///
/// </summary>
public override void nextTile()
{
if (ctX == ntX - 1 && ctY == ntY - 1)
{
// Already at last tile
throw new NoNextElementException();
}
else if (ctX < ntX - 1)
{
// If not at end of current tile line
setTile(ctX + 1, ctY);
}
else
{
// Go to first tile at next line
setTile(0, ctY + 1);
}
}
/// <summary> Returns the specified coded code-block, for the specified component, in
/// the current tile. The first layer to return is indicated by 'fl'. The
/// number of layers that is returned depends on 'nl' and the amount of
/// available data.
///
/// <p>The argument 'fl' is to be used by subsequent calls to this method
/// for the same code-block. In this way supplemental data can be retrieved
/// at a later time. The fact that data from more than one layer can be
/// returned means that several packets from the same code-block, of the
/// same component, and the same tile, have been concatenated.</p>
///
/// <p>The returned compressed code-block can have its progressive
/// attribute set. If this attribute is set it means that more data can be
/// obtained by subsequent calls to this method (subject to transmission
/// delays, etc). If the progressive attribute is not set it means that the
/// returned data is all the data that can be obtained for the specified
/// code-block.</p>
///
/// <p>The compressed code-block is uniquely specified by the current tile,
/// the component (identified by 'c'), the subband (indentified by 'sb')
/// and the code-block vertical and horizontal indexes 'n' and 'm'.</p>
///
/// <p>The 'ulx' and 'uly' members of the returned 'DecLyrdCBlk' object
/// contain the coordinates of the top-left corner of the block, with
/// respect to the tile, not the subband.</p>
///
/// </summary>
/// <param name="c">The index of the component, from 0 to N-1.
///
/// </param>
/// <param name="m">The vertical index of the code-block to return, in the
/// specified subband.
///
/// </param>
/// <param name="n">The horizontal index of the code-block to return, in the
/// specified subband.
///
/// </param>
/// <param name="sb">The subband in whic the requested code-block is.
///
/// </param>
/// <param name="fl">The first layer to return.
///
/// </param>
/// <param name="nl">The number of layers to return, if negative all available
/// layers are returned, starting at 'fl'.
///
/// </param>
/// <param name="ccb">If not null this object is used to return the compressed
/// code-block. If null a new object is created and returned. If the data
/// array in ccb is not null then it can be reused to return the compressed
/// data.
///
/// </param>
/// <returns> The compressed code-block, with a certain number of layers
/// determined by the available data and 'nl'.
///
/// </returns>
public override DecLyrdCBlk getCodeBlock(int c, int m, int n, SubbandSyn sb, int fl, int nl, DecLyrdCBlk ccb)
{
int t = TileIdx;
CBlkInfo rcb; // requested code-block
int r = sb.resLvl; // Resolution level
int s = sb.sbandIdx; // Subband index
int tpidx;
int passtype;
// Number of layers
int numLayers = ((System.Int32) decSpec.nls.getTileDef(t));
int options = ((System.Int32) decSpec.ecopts.getTileCompVal(t, c));
if (nl < 0)
{
nl = numLayers - fl + 1;
}
// If the l quit condition is used, Make sure that no layer
// after lquit is returned
if (lQuit != - 1 && fl + nl > lQuit)
{
nl = lQuit - fl;
}
// Check validity of resquested resolution level (according to the
// "-res" option).
int maxdl = getSynSubbandTree(t, c).resLvl;
if (r > targetRes + maxdl - decSpec.dls.Min)
{
throw new System.ApplicationException("JJ2000 error: requesting a code-block " + "disallowed by the '-res' option.");
}
// Check validity of all the arguments
try
{
rcb = cbI[c][r][s][m][n];
if (fl < 1 || fl > numLayers || fl + nl - 1 > numLayers)
{
throw new System.ArgumentException();
}
}
catch (System.IndexOutOfRangeException)
{
throw new System.ArgumentException("Code-block (t:" + t + ", c:" + c + ", r:" + r + ", s:" + s + ", " + m + "x" + (+ n) + ") not found in codestream");
}
catch (System.NullReferenceException)
{
throw new System.ArgumentException("Code-block (t:" + t + ", c:" + c + ", r:" + r + ", s:" + s + ", " + m + "x" + n + ") not found in bit stream");
}
// Create DecLyrdCBlk object if necessary
if (ccb == null)
{
ccb = new DecLyrdCBlk();
}
ccb.m = m;
ccb.n = n;
ccb.nl = 0;
ccb.dl = 0;
ccb.nTrunc = 0;
if (rcb == null)
{
// This code-block was skipped when reading. Returns no data
ccb.skipMSBP = 0;
ccb.prog = false;
ccb.w = ccb.h = ccb.ulx = ccb.uly = 0;
return ccb;
}
// ccb initialization
ccb.skipMSBP = rcb.msbSkipped;
ccb.ulx = rcb.ulx;
ccb.uly = rcb.uly;
ccb.w = rcb.w;
ccb.h = rcb.h;
ccb.ftpIdx = 0;
// Search for index of first truncation point (first layer where
// length of data is not zero)
int l = 0;
while ((l < rcb.len.Length) && (rcb.len[l] == 0))
{
ccb.ftpIdx += rcb.ntp[l];
l++;
}
// Calculate total length, number of included layer and number of
// truncation points
for (l = fl - 1; l < fl + nl - 1; l++)
{
ccb.nl++;
ccb.dl += rcb.len[l];
ccb.nTrunc += rcb.ntp[l];
}
// Calculate number of terminated segments
int nts;
if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0)
{
// Regular termination in use One segment per pass
// (i.e. truncation point)
nts = ccb.nTrunc - ccb.ftpIdx;
}
else if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0)
{
// Selective arithmetic coding bypass mode in use, but no regular
// termination: 1 segment upto the end of the last pass of the 4th
// most significant bit-plane, and, in each following bit-plane,
// one segment upto the end of the 2nd pass and one upto the end
// of the 3rd pass.
if (ccb.nTrunc <= CSJ2K.j2k.entropy.StdEntropyCoderOptions.FIRST_BYPASS_PASS_IDX)
{
nts = 1;
}
else
{
nts = 1;
// Adds one for each terminated pass
for (tpidx = ccb.ftpIdx; tpidx < ccb.nTrunc; tpidx++)
{
if (tpidx >= CSJ2K.j2k.entropy.StdEntropyCoderOptions.FIRST_BYPASS_PASS_IDX - 1)
{
passtype = (tpidx + CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_EMPTY_PASSES_IN_MS_BP) % CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_PASSES;
if (passtype == 1 || passtype == 2)
{
// lazy pass just before MQ pass or MQ pass just
// before lazy pass => terminated
nts++;
}
}
}
}
}
else
{
// Nothing special in use, just one terminated segment
nts = 1;
}
// ccb.data creation
if (ccb.data == null || ccb.data.Length < ccb.dl)
{
ccb.data = new byte[ccb.dl];
}
// ccb.tsLengths creation
if (nts > 1 && (ccb.tsLengths == null || ccb.tsLengths.Length < nts))
{
ccb.tsLengths = new int[nts];
}
else if (nts > 1 && (options & (CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS | CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS)) == CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS)
{
ArrayUtil.intArraySet(ccb.tsLengths, 0);
}
// Fill ccb with compressed data
int dataIdx = - 1;
tpidx = ccb.ftpIdx;
int ctp = ccb.ftpIdx; // Cumulative number of truncation
// point for the current layer layer
int tsidx = 0;
int j;
for (l = fl - 1; l < fl + nl - 1; l++)
{
ctp += rcb.ntp[l];
// No data in this layer
if (rcb.len[l] == 0)
continue;
// Read data
// NOTE: we should never get an EOFException here since all
// data is checked to be within the file.
try
{
in_Renamed.seek(rcb.off[l]);
in_Renamed.readFully(ccb.data, dataIdx + 1, rcb.len[l]);
dataIdx += rcb.len[l];
}
catch (System.IO.IOException e)
{
JJ2KExceptionHandler.handleException(e);
}
// Get the terminated segment lengths, if any
if (nts == 1)
continue;
if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0)
{
// Regular termination => each pass is terminated
for (j = 0; tpidx < ctp; j++, tpidx++)
{
if (rcb.segLen[l] != null)
{
ccb.tsLengths[tsidx++] = rcb.segLen[l][j];
}
else
{
// Only one terminated segment in packet
ccb.tsLengths[tsidx++] = rcb.len[l];
}
}
}
else
{
// Lazy coding without regular termination
for (j = 0; tpidx < ctp; tpidx++)
{
if (tpidx >= CSJ2K.j2k.entropy.StdEntropyCoderOptions.FIRST_BYPASS_PASS_IDX - 1)
{
passtype = (tpidx + CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_EMPTY_PASSES_IN_MS_BP) % CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_PASSES;
if (passtype != 0)
{
// lazy pass just before MQ pass or MQ
// pass just before lazy pass =>
// terminated
if (rcb.segLen[l] != null)
{
ccb.tsLengths[tsidx++] += rcb.segLen[l][j++];
rcb.len[l] -= rcb.segLen[l][j - 1];
}
else
{
// Only one terminated segment in packet
ccb.tsLengths[tsidx++] += rcb.len[l];
rcb.len[l] = 0;
}
}
}
}
// Last length in packet always in (either terminated segment
// or contribution to terminated segment)
if (rcb.segLen[l] != null && j < rcb.segLen[l].Length)
{
ccb.tsLengths[tsidx] += rcb.segLen[l][j];
rcb.len[l] -= rcb.segLen[l][j];
}
else
{
// Only one terminated segment in packet
if (tsidx < nts)
{
ccb.tsLengths[tsidx] += rcb.len[l];
rcb.len[l] = 0;
}
}
}
}
if (nts == 1 && ccb.tsLengths != null)
{
ccb.tsLengths[0] = ccb.dl;
}
// Set the progressive flag
int lastlayer = fl + nl - 1;
if (lastlayer < numLayers - 1)
{
for (l = lastlayer + 1; l < numLayers; l++)
{
// It remains data for this code-block in the bit stream
if (rcb.len[l] != 0)
{
ccb.prog = true;
}
}
}
return ccb;
}
}
}
Generated by GNU Enscript 1.6.5.90.