CSJ2K.j2k.entropy.decoder.StdEntropyDecoder.cleanuppass C# (CSharp) Method

cleanuppass() private method

Performs the cleanup pass on the specified data and bit-plane. It decodes all insignificant samples which have its "visited" state bit off, using the ZC, SC, and RLC primitives. It toggles the "visited" state bit to 0 (off) for all samples in the code-block.

This method also checks for segmentation markers if those are present and returns true if an error is detected, or false otherwise. If an error is detected it measn that the bit stream contains some erroneous bit that have led to the decoding of incorrect data. This data affects the whole last decoded bit-plane (i.e. 'bp'). If 'true' is returned the 'conceal' method should be called and no more passes should be decoded for this code-block's bit stream.

private cleanuppass ( CSJ2K.j2k.image.DataBlk cblk, CSJ2K.j2k.entropy.decoder.MQDecoder mq, int bp, int state, int zc_lut, bool isterm ) : bool
cblk CSJ2K.j2k.image.DataBlk The code-block data to code /// ///
mq CSJ2K.j2k.entropy.decoder.MQDecoder The MQ-coder to use /// ///
bp int The bit-plane to decode /// ///
state int The state information for the code-block /// ///
zc_lut int The ZC lookup table to use in ZC. /// ///
isterm bool If this pass has been terminated. If the pass has been /// terminated it can be used to check error resilience. /// ///
return bool
        private bool cleanuppass(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 decoded symbol
            int rlclen; // Length of RLC
            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++)
                {
                    // Start column
                    j = sj;
                    csj = state[j];
                    {
                        // Check for RLC: if all samples are not significant, not
                        // visited and do not have a non-zero context, and column
                        // is full height, we do RLC.
                        if (csj == 0 && state[j + sscanw] == 0 && sheight == CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT)
                        {
                            if (mq.decodeSymbol(RLC_CTXT) != 0)
                            {
                                // run-length is significant, decode length
                                rlclen = mq.decodeSymbol(UNIF_CTXT) << 1;
                                rlclen |= mq.decodeSymbol(UNIF_CTXT);
                                // Set 'k' and 'j' accordingly
                                k = sk + rlclen * dscanw;
                                if (rlclen > 1)
                                {
                                    j += sscanw;
                                    csj = state[j];
                                }
                            }
                            else
                            {
                                // RLC is insignificant
                                // Goto next column
                                continue;
                            }
                            // We just decoded the length of a significant RLC
                            // and a sample became significant
                            // Use sign coding
                            if ((rlclen & 0x01) == 0)
                            {
                                // Sample that became significant is first row of
                                // its column half
                                ctxt = SC_LUT[(csj >> SC_SHIFT_R1) & SC_MASK];
                                sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
                                // Update the 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 (rlclen != 0 || !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 (rlclen != 0 || !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 (rlclen != 0 || !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;
                                }
                                // Changes to csj are saved later
                                if ((rlclen >> 1) != 0)
                                {
                                    // Sample that became significant is in
                                    // bottom half of column => jump to bottom
                                    // half
                                    //UPGRADE_NOTE: Labeled break statement was changed to a goto statement. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1012'"
                                    goto top_half_brk;
                                }
                                // Otherwise sample that became significant is in
                                // top half of column => continue on top half
                            }
                            else
                            {
                                // Sample that became significant is second row of
                                // its column half
                                ctxt = SC_LUT[(csj >> SC_SHIFT_R2) & SC_MASK];
                                sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
                                // Update the data
                                data[k] = (sym << 31) | setmask;
                                // Update state information (significant 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_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_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;
                                }
                                // Save changes to csj
                                state[j] = csj;
                                if ((rlclen >> 1) != 0)
                                {
                                    // Sample that became significant is in bottom
                                    // half of column => we're done with this
                                    // column
                                    continue;
                                }
                                // Otherwise sample that became significant is in
                                // top half of column => we're done with top
                                // column
                                j += sscanw;
                                csj = state[j];
                                //UPGRADE_NOTE: Labeled break statement was changed to a goto statement. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1012'"
                                goto top_half_brk;
                            }
                        }
                        // Do half top of column
                        // If any of the two samples is not significant and has
                        // not been visited in the current bit-plane we can not
                        // skip them
                        if ((((csj >> 1) | csj) & VSTD_MASK_R1R2) != VSTD_MASK_R1R2)
                        {
                            k = sk;
                            // Scan first row
                            if ((csj & (STATE_SIG_R1 | STATE_VISITED_R1)) == 0)
                            {
                                // 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 the 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;
                                    }
                                }
                            }
                            if (sheight < 2)
                            {
                                csj &= ~ (STATE_VISITED_R1 | STATE_VISITED_R2);
                                state[j] = csj;
                                continue;
                            }
                            // Scan second row
                            if ((csj & (STATE_SIG_R2 | STATE_VISITED_R2)) == 0)
                            {
                                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 the 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;
                                    }
                                }
                            }
                        }
                        csj &= ~ (STATE_VISITED_R1 | STATE_VISITED_R2);
                        state[j] = csj;
                        // Do half bottom of column
                        if (sheight < 3)
                            continue;
                        j += sscanw;
                        csj = state[j];
                    }
                    //UPGRADE_NOTE: Label 'top_half_brk' was added. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1011'"

            top_half_brk: ;
                     // end of 'top_half' block
                    // If any of the two samples is not significant and has
                    // not been visited in the current bit-plane we can not
                    // skip them
                    if ((((csj >> 1) | csj) & VSTD_MASK_R1R2) != VSTD_MASK_R1R2)
                    {
                        k = sk + (dscanw << 1);
                        // Scan first row
                        if ((csj & (STATE_SIG_R1 | STATE_VISITED_R1)) == 0)
                        {
                            // Use zero coding
                            if (mq.decodeSymbol(zc_lut[csj & ZC_MASK]) != 0)
                            {
                                // Became significant
                                // Use sign coding
                                ctxt = SC_LUT[(csj >> SC_SHIFT_R1) & SC_MASK];
                                sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
                                // Update the 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;
                                }
                            }
                        }
                        if (sheight < 4)
                        {
                            csj &= ~ (STATE_VISITED_R1 | STATE_VISITED_R2);
                            state[j] = csj;
                            continue;
                        }
                        // Scan second row
                        if ((csj & (STATE_SIG_R2 | STATE_VISITED_R2)) == 0)
                        {
                            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 the 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;
                                }
                            }
                        }
                    }
                    csj &= ~ (STATE_VISITED_R1 | STATE_VISITED_R2);
                    state[j] = csj;
                }
            }

            // Decode segment symbol if we need to
            if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_SEG_SYMBOLS) != 0)
            {
                sym = mq.decodeSymbol(UNIF_CTXT) << 3;
                sym |= mq.decodeSymbol(UNIF_CTXT) << 2;
                sym |= mq.decodeSymbol(UNIF_CTXT) << 1;
                sym |= mq.decodeSymbol(UNIF_CTXT);
                // Set error condition accordingly
                error = sym != SEG_SYMBOL;
            }
            else
            {
                // We can not detect any errors
                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;
        }