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.InvalidOperationException("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 e)
{
throw new System.ArgumentException("Code-block (t:" + t + ", c:" + c + ", r:" + r + ", s:" + s + ", " + m + "x" + (+ n) + ") not found in codestream");
}
catch (System.NullReferenceException e)
{
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;
}