private bool sigProgPass(DataBlk cblk, MQDecoder mq, int bp, int[] state, int[] zc_lut, bool isterm)
{
int j, sj; // The state index for line and stripe
int k, sk; // The data index for line and stripe
int dscanw; // The data scan-width
int sscanw; // The state scan-width
int jstep; // Stripe to stripe step for 'sj'
int kstep; // Stripe to stripe step for 'sk'
int stopsk; // The loop limit on the variable sk
int csj; // Local copy (i.e. cached) of 'state[j]'
int setmask; // The mask to set current and lower bit-planes to 1/2
// approximation
int sym; // The symbol to code
int ctxt; // The context to use
int[] data; // The data buffer
int s; // The stripe index
bool causal; // Flag to indicate if stripe-causal context
// formation is to be used
int nstripes; // The number of stripes in the code-block
int sheight; // Height of the current stripe
int off_ul, off_ur, off_dr, off_dl; // offsets
bool error; // The error condition
// Initialize local variables
dscanw = cblk.scanw;
sscanw = cblk.w + 2;
jstep = sscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT / 2 - cblk.w;
kstep = dscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - cblk.w;
setmask = (3 << bp) >> 1;
data = (int[]) cblk.Data;
nstripes = (cblk.h + CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - 1) / CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT;
causal = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_VERT_STR_CAUSAL) != 0;
// Pre-calculate offsets in 'state' for diagonal neighbors
off_ul = - sscanw - 1; // up-left
off_ur = - sscanw + 1; // up-right
off_dr = sscanw + 1; // down-right
off_dl = sscanw - 1; // down-left
// Decode stripe by stripe
sk = cblk.offset;
sj = sscanw + 1;
for (s = nstripes - 1; s >= 0; s--, sk += kstep, sj += jstep)
{
sheight = (s != 0)?CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT:cblk.h - (nstripes - 1) * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT;
stopsk = sk + cblk.w;
// Scan by set of 1 stripe column at a time
for (; sk < stopsk; sk++, sj++)
{
// Do half top of column
j = sj;
csj = state[j];
// If any of the two samples is not significant and has a
// non-zero context (i.e. some neighbor is significant) we can
// not skip them
if ((((~ csj) & (csj << 2)) & SIG_MASK_R1R2) != 0)
{
k = sk;
// Scan first row
if ((csj & (STATE_SIG_R1 | STATE_NZ_CTXT_R1)) == STATE_NZ_CTXT_R1)
{
// Use zero coding
if (mq.decodeSymbol(zc_lut[csj & ZC_MASK]) != 0)
{
// Became significant
// Use sign coding
ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R1)) & SC_MASK];
sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
// Update data
data[k] = (sym << 31) | setmask;
// Update state information (significant bit,
// visited bit, neighbor significant bit of
// neighbors, non zero context of neighbors, sign
// of neighbors)
if (!causal)
{
// If in causal mode do not change contexts of
// previous stripe.
state[j + off_ul] |= STATE_NZ_CTXT_R2 | STATE_D_DR_R2;
state[j + off_ur] |= STATE_NZ_CTXT_R2 | STATE_D_DL_R2;
}
// Update sign state information of neighbors
if (sym != 0)
{
csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2 | STATE_V_U_SIGN_R2;
if (!causal)
{
// If in causal mode do not change
// contexts of previous stripe.
state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2 | STATE_V_D_SIGN_R2;
}
state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_H_L_SIGN_R1 | STATE_D_UL_R2;
state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_H_R_SIGN_R1 | STATE_D_UR_R2;
}
else
{
csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2;
if (!causal)
{
// If in causal mode do not change
// contexts of previous stripe.
state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2;
}
state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_D_UL_R2;
state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_D_UR_R2;
}
}
else
{
csj |= STATE_VISITED_R1;
}
}
if (sheight < 2)
{
state[j] = csj;
continue;
}
// Scan second row
if ((csj & (STATE_SIG_R2 | STATE_NZ_CTXT_R2)) == STATE_NZ_CTXT_R2)
{
k += dscanw;
// Use zero coding
if (mq.decodeSymbol(zc_lut[(SupportClass.URShift(csj, STATE_SEP)) & ZC_MASK]) != 0)
{
// Became significant
// Use sign coding
ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R2)) & SC_MASK];
sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
// Update data
data[k] = (sym << 31) | setmask;
// Update state information (significant bit,
// visited bit, neighbor significant bit of
// neighbors, non zero context of neighbors, sign
// of neighbors)
state[j + off_dl] |= STATE_NZ_CTXT_R1 | STATE_D_UR_R1;
state[j + off_dr] |= STATE_NZ_CTXT_R1 | STATE_D_UL_R1;
// Update sign state information of neighbors
if (sym != 0)
{
csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1 | STATE_V_D_SIGN_R1;
state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1 | STATE_V_U_SIGN_R1;
state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2 | STATE_H_L_SIGN_R2;
state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2 | STATE_H_R_SIGN_R2;
}
else
{
csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1;
state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1;
state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2;
state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2;
}
}
else
{
csj |= STATE_VISITED_R2;
}
}
state[j] = csj;
}
// Do half bottom of column
if (sheight < 3)
continue;
j += sscanw;
csj = state[j];
// If any of the two samples is not significant and has a
// non-zero context (i.e. some neighbor is significant) we can
// not skip them
if ((((~ csj) & (csj << 2)) & SIG_MASK_R1R2) != 0)
{
k = sk + (dscanw << 1);
// Scan first row
if ((csj & (STATE_SIG_R1 | STATE_NZ_CTXT_R1)) == STATE_NZ_CTXT_R1)
{
// Use zero coding
if (mq.decodeSymbol(zc_lut[csj & ZC_MASK]) != 0)
{
// Became significant
// Use sign coding
ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R1)) & SC_MASK];
sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
// Update data
data[k] = (sym << 31) | setmask;
// Update state information (significant bit,
// visited bit, neighbor significant bit of
// neighbors, non zero context of neighbors, sign
// of neighbors)
state[j + off_ul] |= STATE_NZ_CTXT_R2 | STATE_D_DR_R2;
state[j + off_ur] |= STATE_NZ_CTXT_R2 | STATE_D_DL_R2;
// Update sign state information of neighbors
if (sym != 0)
{
csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2 | STATE_V_U_SIGN_R2;
state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2 | STATE_V_D_SIGN_R2;
state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_H_L_SIGN_R1 | STATE_D_UL_R2;
state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_H_R_SIGN_R1 | STATE_D_UR_R2;
}
else
{
csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2;
state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2;
state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_D_UL_R2;
state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_D_UR_R2;
}
}
else
{
csj |= STATE_VISITED_R1;
}
}
if (sheight < 4)
{
state[j] = csj;
continue;
}
// Scan second row
if ((csj & (STATE_SIG_R2 | STATE_NZ_CTXT_R2)) == STATE_NZ_CTXT_R2)
{
k += dscanw;
// Use zero coding
if (mq.decodeSymbol(zc_lut[(SupportClass.URShift(csj, STATE_SEP)) & ZC_MASK]) != 0)
{
// Became significant
// Use sign coding
ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R2)) & SC_MASK];
sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
// Update data
data[k] = (sym << 31) | setmask;
// Update state information (significant bit,
// visited bit, neighbor significant bit of
// neighbors, non zero context of neighbors, sign
// of neighbors)
state[j + off_dl] |= STATE_NZ_CTXT_R1 | STATE_D_UR_R1;
state[j + off_dr] |= STATE_NZ_CTXT_R1 | STATE_D_UL_R1;
// Update sign state information of neighbors
if (sym != 0)
{
csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1 | STATE_V_D_SIGN_R1;
state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1 | STATE_V_U_SIGN_R1;
state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2 | STATE_H_L_SIGN_R2;
state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2 | STATE_H_R_SIGN_R2;
}
else
{
csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1;
state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1;
state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2;
state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2;
}
}
else
{
csj |= STATE_VISITED_R2;
}
}
state[j] = csj;
}
}
}
error = false;
// Check the error resilience termination
if (isterm && (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_PRED_TERM) != 0)
{
error = mq.checkPredTerm();
}
// Reset the MQ context states if we need to
if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_RESET_MQ) != 0)
{
mq.resetCtxts();
}
// Return error condition
return error;
}