public override DataBlk getCodeBlock(int c, int m, int n, SubbandSyn sb, DataBlk cblk)
{
//long stime = 0L; // Start time for timed sections
int[] zc_lut; // The ZC lookup table to use
int[] out_data; // The outupt data buffer
int npasses; // The number of coding passes to perform
int curbp; // The current magnitude bit-plane (starts at 30)
bool error; // Error indicator
int tslen; // Length of first terminated segment
int tsidx; // Index of current terminated segment
ByteInputBuffer in_Renamed = null;
bool isterm;
// Get the code-block to decode
srcblk = src.getCodeBlock(c, m, n, sb, 1, - 1, srcblk);
#if DO_TIMING
stime = (System.DateTime.Now.Ticks - 621355968000000000) / 10000;
#endif
// Retrieve options from decSpec
options = ((System.Int32) decSpec.ecopts.getTileCompVal(tIdx, c));
// Reset state
ArrayUtil.intArraySet(state, 0);
// Initialize output code-block
if (cblk == null)
cblk = new DataBlkInt();
cblk.progressive = srcblk.prog;
cblk.ulx = srcblk.ulx;
cblk.uly = srcblk.uly;
cblk.w = srcblk.w;
cblk.h = srcblk.h;
cblk.offset = 0;
cblk.scanw = cblk.w;
out_data = (int[]) cblk.Data;
if (out_data == null || out_data.Length < srcblk.w * srcblk.h)
{
out_data = new int[srcblk.w * srcblk.h];
cblk.Data = out_data;
}
else
{
// Set data values to 0
ArrayUtil.intArraySet(out_data, 0);
}
if (srcblk.nl <= 0 || srcblk.nTrunc <= 0)
{
// 0 layers => no data to decode => return all 0s
return cblk;
}
// Get the length of the first terminated segment
tslen = (srcblk.tsLengths == null)?srcblk.dl:srcblk.tsLengths[0];
tsidx = 0;
// Initialize for decoding
npasses = srcblk.nTrunc;
if (mq == null)
{
in_Renamed = new ByteInputBuffer(srcblk.data, 0, tslen);
mq = new MQDecoder(in_Renamed, NUM_CTXTS, MQ_INIT);
}
else
{
// We always start by an MQ segment
mq.nextSegment(srcblk.data, 0, tslen);
mq.resetCtxts();
}
error = false;
if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0)
{
if (bin == null)
{
if (in_Renamed == null)
in_Renamed = mq.ByteInputBuffer;
bin = new ByteToBitInput(in_Renamed);
}
}
// Choose correct ZC lookup table for global orientation
switch (sb.orientation)
{
case Subband.WT_ORIENT_HL:
zc_lut = ZC_LUT_HL;
break;
case Subband.WT_ORIENT_LH:
case Subband.WT_ORIENT_LL:
zc_lut = ZC_LUT_LH;
break;
case Subband.WT_ORIENT_HH:
zc_lut = ZC_LUT_HH;
break;
default:
throw new System.InvalidOperationException("JJ2000 internal error");
}
// NOTE: we don't currently detect which is the last magnitude
// bit-plane so that 'isterm' is true for the last pass of it. Doing
// so would aid marginally in error detection with the predictable
// error resilient MQ termination. However, determining which is the
// last magnitude bit-plane is quite hard (due to ROI, quantization,
// etc.) and in any case the predictable error resilient termination
// used without the arithmetic coding bypass and/or regular
// termination modes is almost useless.
// Loop on bit-planes and passes
curbp = 30 - srcblk.skipMSBP;
// Check for maximum number of bitplanes quit condition
if (mQuit != - 1 && (mQuit * 3 - 2) < npasses)
{
npasses = mQuit * 3 - 2;
}
// First bit-plane has only the cleanup pass
if (curbp >= 0 && npasses > 0)
{
isterm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0 || ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - srcblk.skipMSBP) >= curbp);
error = cleanuppass(cblk, mq, curbp, state, zc_lut, isterm);
npasses--;
if (!error || !doer)
curbp--;
}
// Other bit-planes have the three coding passes
if (!error || !doer)
{
while (curbp >= 0 && npasses > 0)
{
if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (curbp < 31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - srcblk.skipMSBP))
{
// Use bypass decoding mode (only all bit-planes
// after the first 4 bit-planes).
// Here starts a new raw segment
bin.setByteArray(null, - 1, srcblk.tsLengths[++tsidx]);
isterm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0;
error = rawSigProgPass(cblk, bin, curbp, state, isterm);
npasses--;
if (npasses <= 0 || (error && doer))
break;
if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0)
{
// Start a new raw segment
bin.setByteArray(null, - 1, srcblk.tsLengths[++tsidx]);
}
isterm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0 || ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - srcblk.skipMSBP > curbp));
error = rawMagRefPass(cblk, bin, curbp, state, isterm);
}
else
{
// Do not use bypass decoding mode
if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0)
{
// Here starts a new MQ segment
mq.nextSegment(null, - 1, srcblk.tsLengths[++tsidx]);
}
isterm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0;
error = sigProgPass(cblk, mq, curbp, state, zc_lut, isterm);
npasses--;
if (npasses <= 0 || (error && doer))
break;
if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0)
{
// Here starts a new MQ segment
mq.nextSegment(null, - 1, srcblk.tsLengths[++tsidx]);
}
isterm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0 || ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - srcblk.skipMSBP > curbp));
error = magRefPass(cblk, mq, curbp, state, isterm);
}
npasses--;
if (npasses <= 0 || (error && doer))
break;
if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0 || ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (curbp < 31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - srcblk.skipMSBP)))
{
// Here starts a new MQ segment
mq.nextSegment(null, - 1, srcblk.tsLengths[++tsidx]);
}
isterm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0 || ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - srcblk.skipMSBP) >= curbp);
error = cleanuppass(cblk, mq, curbp, state, zc_lut, isterm);
npasses--;
if (error && doer)
break;
// Goto next bit-plane
curbp--;
}
}
// If an error ocurred conceal it
if (error && doer)
{
if (verber)
{
FacilityManager.getMsgLogger().printmsg(CSJ2K.j2k.util.MsgLogger_Fields.WARNING, "Error detected at bit-plane " + curbp + " in code-block (" + m + "," + n + "), sb_idx " + sb.sbandIdx + ", res. level " + sb.resLvl + ". Concealing...");
}
conceal(cblk, curbp);
}
#if DO_TIMING
time[c] += (System.DateTime.Now.Ticks - 621355968000000000) / 10000 - stime;
#endif
// Return decoded block
return cblk;
}