corrade-vassal – Rev 1

Subversion Repositories:
Rev:
/* 
* CVS identifier:
* 
* $Id: StdEntropyDecoder.java,v 1.30 2001/10/25 12:12:16 qtxjoas Exp $
* 
* Class:                   StdEntropyDecoder
* 
* Description:             Entropy decoding engine of stripes in code-blocks
* 
* 
* 
* 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.wavelet.synthesis;
using CSJ2K.j2k.wavelet;
using CSJ2K.j2k.entropy;
using CSJ2K.j2k.decoder;
using CSJ2K.j2k.image;
using CSJ2K.j2k.util;
using CSJ2K.j2k.io;
using CSJ2K.j2k;
namespace CSJ2K.j2k.entropy.decoder
{
        
        /// <summary> This class implements the JPEG 2000 entropy decoder, which codes stripes in
        /// code-blocks. This entropy decoding engine decodes one code-block at a time.
        /// 
        /// <p>The code-blocks are rectangular and their dimensions must be powers of
        /// 2. Each dimension cannot be smaller than 4 and larger than 256. The product
        /// of the two dimensions (i.e. area of the code-block) cannot exceed 4096.</p>
        /// 
        /// <p>Context 0 of the MQ-coder is used as the uniform one (uniform,
        /// non-adaptive probability distribution). Context 1 is used for RLC
        /// coding. Contexts 2-10 are used for zero-coding (ZC), contexts 11-15 are
        /// used for sign-coding (SC) and contexts 16-18 are used for
        /// magnitude-refinement (MR).</p>
        /// 
        /// <p>This implementation also provides some timing features. They can be
        /// enabled by setting the 'DO_TIMING' constant of this class to true and
        /// recompiling. The timing uses the 'System.currentTimeMillis()' Java API
        /// call, which returns wall clock time, not the actual CPU time used. The
        /// timing results will be printed on the message output. Since the times
        /// reported are wall clock times and not CPU usage times they can not be added
        /// to find the total used time (i.e. some time might be counted in several
        /// places). When timing is disabled ('DO_TIMING' is false) there is no penalty
        /// if the compiler performs some basic optimizations. Even if not the penalty
        /// should be negligeable.</p>
        /// 
        /// </summary>
        public class StdEntropyDecoder:EntropyDecoder
        {
                
                /// <summary>Whether to collect timing information or not: false. Used as a compile 
                /// time directive. 
                /// </summary>
                private const bool DO_TIMING = false;
                
                /// <summary>The cumulative wall time for the entropy coding engine, for each
                /// component. 
                /// </summary>
                //private long[] time;
                
                /// <summary>The bit based input for arithmetic coding bypass (i.e. raw) coding </summary>
                private ByteToBitInput bin;
                
                /// <summary>The MQ decoder to use. It has in as the underlying source of coded
                /// data. 
                /// </summary>
                private MQDecoder mq;
                
                /// <summary>The decoder spec </summary>
                private DecoderSpecs decSpec;
                
                /// <summary>The options that are turned on, as flag bits. The options are
                /// 'OPT_TERM_PASS', 'OPT_RESET_MQ', 'OPT_VERT_STR_CAUSAL', 'OPT_BYPASS'
                /// and 'OPT_SEG_SYMBOLS' as defined in the StdEntropyCoderOptions
                /// interface
                /// 
                /// </summary>
                /// <seealso cref="StdEntropyCoderOptions">
                /// 
                /// </seealso>
                private int options;
                
                /// <summary>Flag to indicate if we should try to detect errors or just ignore any
                /// error resilient information 
                /// </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'doer '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private bool doer;
                
                /// <summary>Flag to indicate if we should be verbose about bit stream errors
                /// detected with the error resilience options 
                /// </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'verber '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private bool verber;
                
                /// <summary>Number of bits used for the Zero Coding lookup table </summary>
                private const int ZC_LUT_BITS = 8;
                
                /// <summary>Zero Coding context lookup tables for the LH global orientation </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'ZC_LUT_LH '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int[] ZC_LUT_LH = new int[1 << ZC_LUT_BITS];
                
                /// <summary>Zero Coding context lookup tables for the HL global orientation </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'ZC_LUT_HL '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int[] ZC_LUT_HL = new int[1 << ZC_LUT_BITS];
                
                /// <summary>Zero Coding context lookup tables for the HH global orientation </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'ZC_LUT_HH '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int[] ZC_LUT_HH = new int[1 << ZC_LUT_BITS];
                
                /// <summary>Number of bits used for the Sign Coding lookup table </summary>
                private const int SC_LUT_BITS = 9;
                
                /// <summary>Sign Coding context lookup table. The index into the table is a 9 bit
                /// index, which correspond the the value in the 'state' array shifted by
                /// 'SC_SHIFT'. Bits 8-5 are the signs of the horizontal-left,
                /// horizontal-right, vertical-up and vertical-down neighbors,
                /// respectively. Bit 4 is not used (0 or 1 makes no difference). Bits 3-0
                /// are the significance of the horizontal-left, horizontal-right,
                /// vertical-up and vertical-down neighbors, respectively. The least 4 bits
                /// of the value in the lookup table define the context number and the sign
                /// bit defines the "sign predictor". 
                /// </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'SC_LUT '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int[] SC_LUT = new int[1 << SC_LUT_BITS];
                
                /// <summary>The mask to obtain the context index from the 'SC_LUT' </summary>
                private const int SC_LUT_MASK = (1 << 4) - 1;
                
                /// <summary>The shift to obtain the sign predictor from the 'SC_LUT'. It must be
                /// an unsigned shift. 
                /// </summary>
                private const int SC_SPRED_SHIFT = 31;
                
                /// <summary>The sign bit for int data </summary>
                private const int INT_SIGN_BIT = 1 << 31;
                
                /// <summary>The number of bits used for the Magnitude Refinement lookup table </summary>
                private const int MR_LUT_BITS = 9;
                
                /// <summary>Magnitude Refinement context lookup table </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'MR_LUT '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int[] MR_LUT = new int[1 << MR_LUT_BITS];
                
                /// <summary>The number of contexts used </summary>
                private const int NUM_CTXTS = 19;
                
                /// <summary>The RLC context </summary>
                private const int RLC_CTXT = 1;
                
                /// <summary>The UNIFORM context (with a uniform probability distribution which
                /// does not adapt) 
                /// </summary>
                private const int UNIF_CTXT = 0;
                
                /// <summary>The initial states for the MQ coder </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'MQ_INIT'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int[] MQ_INIT = new int[]{46, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
                
                /// <summary>The 4 bits of the error resilience segmentation symbol (decimal 10,
                /// which is binary sequence 1010) 
                /// </summary>
                private const int SEG_SYMBOL = 10;
                
                /// <summary> The state array for entropy coding. Each element of the state array
                /// stores the state of two coefficients. The lower 16 bits store the state
                /// of a coefficient in row 'i' and column 'j', while the upper 16 bits
                /// store the state of a coefficient in row 'i+1' and column 'j'. The 'i'
                /// row is either the first or the third row of a stripe. This packing of
                /// the states into 32 bit words allows a faster scan of all coefficients
                /// on each coding pass and diminished the amount of data transferred. The
                /// size of the state array is increased by 1 on each side (top, bottom,
                /// left, right) to handle boundary conditions without any special logic.
                /// 
                /// <P>The state of a coefficient is stored in the following way in the
                /// lower 16 bits, where bit 0 is the least significant bit. Bit 15 is the
                /// significance of a coefficient (0 if non-significant, 1 otherwise). Bit
                /// 14 is the visited state (i.e. if a coefficient has been coded in the
                /// significance propagation pass of the current bit-plane). Bit 13 is the
                /// "non zero-context" state (i.e. if one of the eight immediate neighbors
                /// is significant it is 1, otherwise is 0). Bits 12 to 9 store the sign of
                /// the already significant left, right, up and down neighbors (1 for
                /// negative, 0 for positive or not yet significant). Bit 8 indicates if
                /// the magnitude refinement has already been applied to the
                /// coefficient. Bits 7 to 4 store the significance of the left, right, up
                /// and down neighbors (1 for significant, 0 for non significant). Bits 3
                /// to 0 store the significance of the diagonal coefficients (up-left,
                /// up-right, down-left and down-right; 1 for significant, 0 for non
                /// significant).
                /// 
                /// <P>The upper 16 bits the state is stored as in the lower 16 bits, but
                /// with the bits shifted up by 16.
                /// 
                /// <P>The lower 16 bits are referred to as "row 1" ("R1") while the upper
                /// 16 bits are referred to as "row 2" ("R2").
                /// 
                /// </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'state '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private int[] state;
                
                /// <summary>The separation between the upper and lower bits in the state array: 16
                /// 
                /// </summary>
                private const int STATE_SEP = 16;
                
                /// <summary>The flag bit for the significance in the state array, for row 1. </summary>
                private const int STATE_SIG_R1 = 1 << 15;
                
                /// <summary>The flag bit for the "visited" bit in the state array, for row 1. </summary>
                private const int STATE_VISITED_R1 = 1 << 14;
                
                /// <summary>The flag bit for the "not zero context" bit in the state array, for
                /// row 1. This bit is always the OR of bits STATE_H_L_R1, STATE_H_R_R1,
                /// STATE_V_U_R1, STATE_V_D_R1, STATE_D_UL_R1, STATE_D_UR_R1, STATE_D_DL_R1
                /// and STATE_D_DR_R1. 
                /// </summary>
                private const int STATE_NZ_CTXT_R1 = 1 << 13;
                
                /// <summary>The flag bit for the horizontal-left sign in the state array, for row
                /// 1. This bit can only be set if the STATE_H_L_R1 is also set. 
                /// </summary>
                private const int STATE_H_L_SIGN_R1 = 1 << 12;
                
                /// <summary>The flag bit for the horizontal-right sign in the state array, for
                /// row 1. This bit can only be set if the STATE_H_R_R1 is also set. 
                /// </summary>
                private const int STATE_H_R_SIGN_R1 = 1 << 11;
                
                /// <summary>The flag bit for the vertical-up sign in the state array, for row
                /// 1. This bit can only be set if the STATE_V_U_R1 is also set. 
                /// </summary>
                private const int STATE_V_U_SIGN_R1 = 1 << 10;
                
                /// <summary>The flag bit for the vertical-down sign in the state array, for row
                /// 1. This bit can only be set if the STATE_V_D_R1 is also set. 
                /// </summary>
                private const int STATE_V_D_SIGN_R1 = 1 << 9;
                
                /// <summary>The flag bit for the previous MR primitive applied in the state array,
                /// for row 1. 
                /// </summary>
                private const int STATE_PREV_MR_R1 = 1 << 8;
                
                /// <summary>The flag bit for the horizontal-left significance in the state array,
                /// for row 1. 
                /// </summary>
                private const int STATE_H_L_R1 = 1 << 7;
                
                /// <summary>The flag bit for the horizontal-right significance in the state array,
                /// for row 1. 
                /// </summary>
                private const int STATE_H_R_R1 = 1 << 6;
                
                /// <summary>The flag bit for the vertical-up significance in the state array, for
                /// row 1.  
                /// </summary>
                private const int STATE_V_U_R1 = 1 << 5;
                
                /// <summary>The flag bit for the vertical-down significance in the state array,
                /// for row 1.  
                /// </summary>
                private const int STATE_V_D_R1 = 1 << 4;
                
                /// <summary>The flag bit for the diagonal up-left significance in the state array,
                /// for row 1. 
                /// </summary>
                private const int STATE_D_UL_R1 = 1 << 3;
                
                /// <summary>The flag bit for the diagonal up-right significance in the state
                /// array, for row 1.
                /// </summary>
                private const int STATE_D_UR_R1 = 1 << 2;
                
                /// <summary>The flag bit for the diagonal down-left significance in the state
                /// array, for row 1. 
                /// </summary>
                private const int STATE_D_DL_R1 = 1 << 1;
                
                /// <summary>The flag bit for the diagonal down-right significance in the state
                /// array , for row 1.
                /// </summary>
                private const int STATE_D_DR_R1 = 1;
                
                /// <summary>The flag bit for the significance in the state array, for row 2. </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_SIG_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int STATE_SIG_R2 = STATE_SIG_R1 << STATE_SEP;
                
                /// <summary>The flag bit for the "visited" bit in the state array, for row 2. </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_VISITED_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int STATE_VISITED_R2 = STATE_VISITED_R1 << STATE_SEP;
                
                /// <summary>The flag bit for the "not zero context" bit in the state array, for
                /// row 2. This bit is always the OR of bits STATE_H_L_R2, STATE_H_R_R2,
                /// STATE_V_U_R2, STATE_V_D_R2, STATE_D_UL_R2, STATE_D_UR_R2, STATE_D_DL_R2
                /// and STATE_D_DR_R2. 
                /// </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_NZ_CTXT_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int STATE_NZ_CTXT_R2 = STATE_NZ_CTXT_R1 << STATE_SEP;
                
                /// <summary>The flag bit for the horizontal-left sign in the state array, for row
                /// 2. This bit can only be set if the STATE_H_L_R2 is also set. 
                /// </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_H_L_SIGN_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int STATE_H_L_SIGN_R2 = STATE_H_L_SIGN_R1 << STATE_SEP;
                
                /// <summary>The flag bit for the horizontal-right sign in the state array, for row
                /// 2. This bit can only be set if the STATE_H_R_R2 is also set. 
                /// </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_H_R_SIGN_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int STATE_H_R_SIGN_R2 = STATE_H_R_SIGN_R1 << STATE_SEP;
                
                /// <summary>The flag bit for the vertical-up sign in the state array, for row
                /// 2. This bit can only be set if the STATE_V_U_R2 is also set. 
                /// </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_V_U_SIGN_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int STATE_V_U_SIGN_R2 = STATE_V_U_SIGN_R1 << STATE_SEP;
                
                /// <summary>The flag bit for the vertical-down sign in the state array, for row
                /// 2. This bit can only be set if the STATE_V_D_R2 is also set. 
                /// </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_V_D_SIGN_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int STATE_V_D_SIGN_R2 = STATE_V_D_SIGN_R1 << STATE_SEP;
                
                /// <summary>The flag bit for the previous MR primitive applied in the state array,
                /// for row 2. 
                /// </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_PREV_MR_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int STATE_PREV_MR_R2 = STATE_PREV_MR_R1 << STATE_SEP;
                
                /// <summary>The flag bit for the horizontal-left significance in the state array,
                /// for row 2. 
                /// </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_H_L_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int STATE_H_L_R2 = STATE_H_L_R1 << STATE_SEP;
                
                /// <summary>The flag bit for the horizontal-right significance in the state array,
                /// for row 2. 
                /// </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_H_R_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int STATE_H_R_R2 = STATE_H_R_R1 << STATE_SEP;
                
                /// <summary>The flag bit for the vertical-up significance in the state array, for
                /// row 2.  
                /// </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_V_U_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int STATE_V_U_R2 = STATE_V_U_R1 << STATE_SEP;
                
                /// <summary>The flag bit for the vertical-down significance in the state array,
                /// for row 2.  
                /// </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_V_D_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int STATE_V_D_R2 = STATE_V_D_R1 << STATE_SEP;
                
                /// <summary>The flag bit for the diagonal up-left significance in the state array,
                /// for row 2. 
                /// </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_D_UL_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int STATE_D_UL_R2 = STATE_D_UL_R1 << STATE_SEP;
                
                /// <summary>The flag bit for the diagonal up-right significance in the state
                /// array, for row 2.
                /// </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_D_UR_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int STATE_D_UR_R2 = STATE_D_UR_R1 << STATE_SEP;
                
                /// <summary>The flag bit for the diagonal down-left significance in the state
                /// array, for row 2. 
                /// </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_D_DL_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int STATE_D_DL_R2 = STATE_D_DL_R1 << STATE_SEP;
                
                /// <summary>The flag bit for the diagonal down-right significance in the state
                /// array , for row 2.
                /// </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_D_DR_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int STATE_D_DR_R2 = STATE_D_DR_R1 << STATE_SEP;
                
                /// <summary>The mask to isolate the significance bits for row 1 and 2 of the state 
                /// array. 
                /// </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'SIG_MASK_R1R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int SIG_MASK_R1R2 = STATE_SIG_R1 | STATE_SIG_R2;
                
                /// <summary>The mask to isolate the visited bits for row 1 and 2 of the state 
                /// array. 
                /// </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'VSTD_MASK_R1R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int VSTD_MASK_R1R2 = STATE_VISITED_R1 | STATE_VISITED_R2;
                
                /// <summary>The mask to isolate the bits necessary to identify RLC coding state
                /// (significant, visited and non-zero context, for row 1 and 2). 
                /// </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'RLC_MASK_R1R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int RLC_MASK_R1R2 = STATE_SIG_R1 | STATE_SIG_R2 | STATE_VISITED_R1 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2;
                
                /// <summary>The mask to obtain the ZC_LUT index from the 'state' information </summary>
                // This is needed because of the STATE_V_D_SIGN, STATE_V_U_SIGN,
                // STATE_H_R_SIGN, and STATE_H_L_SIGN bits.
                private const int ZC_MASK = (1 << 8) - 1;
                
                /// <summary>The shift to obtain the SC index to 'SC_LUT' from the 'state'
                /// information, for row 1. 
                /// </summary>
                private const int SC_SHIFT_R1 = 4;
                
                /// <summary>The shift to obtain the SC index to 'SC_LUT' from the state
                /// information, for row 2. 
                /// </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'SC_SHIFT_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int SC_SHIFT_R2 = SC_SHIFT_R1 + STATE_SEP;
                
                /// <summary>The bit mask to isolate the state bits relative to the sign coding
                /// lookup table ('SC_LUT'). 
                /// </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'SC_MASK '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly int SC_MASK = (1 << SC_LUT_BITS) - 1;
                
                /// <summary>The mask to obtain the MR index to 'MR_LUT' from the 'state'
                /// information. It is to be applied after the 'MR_SHIFT' 
                /// </summary>
                private const int MR_MASK = (1 << 9) - 1;
                
                /// <summary>The source code-block to entropy code (avoids reallocation for each
                /// code-block). 
                /// </summary>
                private DecLyrdCBlk srcblk;
                
                /// <summary>The maximum number of bit planes to decode for any code-block </summary>
                private int mQuit;
                
                /// <summary> Instantiates a new entropy decoder engine, with the specified source of
                /// data, nominal block width and height.
                /// 
                /// </summary>
                /// <param name="src">The source of data
                /// 
                /// </param>
                /// <param name="opt">The options to use for this encoder. It is a mix of the
                /// 'OPT_TERM_PASS', 'OPT_RESET_MQ', 'OPT_VERT_STR_CAUSAL', 'OPT_BYPASS'
                /// and 'OPT_SEG_SYMBOLS' option flags.
                /// 
                /// </param>
                /// <param name="doer">If true error detection will be performed, if any error
                /// detection features have been enabled.
                /// 
                /// </param>
                /// <param name="verber">This flag indicates if the entropy decoder should be
                /// verbose about bit stream errors that are detected and concealed.
                /// 
                /// </param>
                /// <param name="mQuit">the maximum number of bit planes to decode according to
                /// the m quit condition
                /// 
                /// </param>
                public StdEntropyDecoder(CodedCBlkDataSrcDec src, DecoderSpecs decSpec, bool doer, bool verber, int mQuit):base(src)
                {
                        
                        this.decSpec = decSpec;
                        this.doer = doer;
                        this.verber = verber;
                        this.mQuit = mQuit;
                        
                        // If we do timing create necessary structures
#if DO_TIMING
                        time = new long[src.NumComps];
                        // If we are timing make sure that 'finalize' gets called.
                        //UPGRADE_ISSUE: Method 'java.lang.System.runFinalizersOnExit' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javalangSystem'"
            // CONVERSION PROBLEM?
                        //System_Renamed.runFinalizersOnExit(true);
#endif
                        
                        // Initialize internal variables
                        state = new int[(decSpec.cblks.MaxCBlkWidth + 2) * ((decSpec.cblks.MaxCBlkHeight + 1) / 2 + 2)];
                }
                
#if DO_TIMING
                /// <summary> Prints the timing information, if collected, and calls 'finalize' on
                /// the super class.
                /// 
                /// </summary>
        ~StdEntropyDecoder()
        {
            int c;
            System.Text.StringBuilder sb;

            sb = new System.Text.StringBuilder("StdEntropyDecoder decompression wall " + "clock time:");
            for (c = 0; c < time.Length; c++)
            {
                sb.Append("\n  component ");
                sb.Append(c);
                sb.Append(": ");
                sb.Append(time[c]);
                sb.Append(" ms");
            }
            FacilityManager.getMsgLogger().printmsg(CSJ2K.j2k.util.MsgLogger_Fields.INFO, sb.ToString());

            //UPGRADE_NOTE: Call to 'super.finalize()' was removed. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1124'"
        }
#endif

                /// <summary> Returns the specified code-block in the current tile for the specified
                /// component, as a copy (see below).
                /// 
                /// <P>The returned code-block may be progressive, which is indicated by
                /// the 'progressive' variable of the returned 'DataBlk' object. If a
                /// code-block is progressive it means that in a later request to this
                /// method for the same code-block it is possible to retrieve data which is
                /// a better approximation, since meanwhile more data to decode for the
                /// code-block could have been received. If the code-block is not
                /// progressive then later calls to this method for the same code-block
                /// will return the exact same data values.
                /// 
                /// <P>The data returned by this method is always a copy of the internal
                /// data of this object, if any, and it can be modified "in place" without
                /// any problems after being returned. The 'offset' of the returned data is
                /// 0, and the 'scanw' is the same as the code-block width. See the
                /// 'DataBlk' class.
                /// 
                /// <P>The 'ulx' and 'uly' members of the returned 'DataBlk' object
                /// contain the coordinates of the top-left corner of the block, with
                /// respect to the tile, not the subband.
                /// 
                /// </summary>
                /// <param name="c">The component for which to return the next code-block.
                /// 
                /// </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 which the code-block to return is.
                /// 
                /// </param>
                /// <param name="cblk">If non-null this object will be used to return the new
                /// code-block. If null a new one will be allocated and returned. If the
                /// "data" array of the object is non-null it will be reused, if possible,
                /// to return the data.
                /// 
                /// </param>
                /// <returns> The next code-block in the current tile for component 'n', or
                /// null if all code-blocks for the current tile have been returned.
                /// 
                /// </returns>
                /// <seealso cref="DataBlk">
                /// 
                /// </seealso>
                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.ApplicationException("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;
                }
                
                /// <summary> Returns the specified code-block in the current tile for the specified
                /// component (as a reference or copy).
                /// 
                /// <p>The returned code-block may be progressive, which is indicated by
                /// the 'progressive' variable of the returned 'DataBlk' object. If a
                /// code-block is progressive it means that in a later request to this
                /// method for the same code-block it is possible to retrieve data which is
                /// a better approximation, since meanwhile more data to decode for the
                /// code-block could have been received. If the code-block is not
                /// progressive then later calls to this method for the same code-block
                /// will return the exact same data values.</p>
                /// 
                /// <p>The data returned by this method can be the data in the internal
                /// buffer of this object, if any, and thus can not be modified by the
                /// caller. The 'offset' and 'scanw' of the returned data can be
                /// arbitrary. See the 'DataBlk' class.</p>
                /// 
                /// <p>The 'ulx' and 'uly' members of the returned 'DataBlk' 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 component for which to return the next code-block.
                /// 
                /// </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 which the code-block to return is.
                /// 
                /// </param>
                /// <param name="cblk">If non-null this object will be used to return the new
                /// code-block. If null a new one will be allocated and returned. If the
                /// "data" array of the object is non-null it will be reused, if possible,
                /// to return the data.
                /// 
                /// </param>
                /// <returns> The next code-block in the current tile for component 'n', or
                /// null if all code-blocks for the current tile have been returned.
                /// 
                /// </returns>
                /// <seealso cref="DataBlk">
                /// 
                /// </seealso>
                public override DataBlk getInternCodeBlock(int c, int m, int n, SubbandSyn sb, DataBlk cblk)
                {
                        return getCodeBlock(c, m, n, sb, cblk);
                }
                
                /// <summary> Performs the significance propagation pass on the specified data and
                /// bit-plane. It decodes all insignificant samples which have, at least,
                /// one of its immediate eight neighbors already significant, using the ZC
                /// and SC primitives as needed. It toggles the "visited" state bit to 1
                /// for all those samples.
                /// 
                /// <p>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 means 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.</p>
                /// 
                /// </summary>
                /// <param name="cblk">The code-block data to decode
                /// 
                /// </param>
                /// <param name="mq">The MQ-coder to use
                /// 
                /// </param>
                /// <param name="bp">The bit-plane to decode
                /// 
                /// </param>
                /// <param name="state">The state information for the code-block
                /// 
                /// </param>
                /// <param name="zc_lut">The ZC lookup table to use in ZC.
                /// 
                /// </param>
                /// <param name="isterm">If this pass has been terminated. If the pass has been
                /// terminated it can be used to check error resilience.
                /// 
                /// </param>
                /// <returns> True if an error was detected in the bit stream, false
                /// otherwise.
                /// 
                /// </returns>
                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;
                }
                
                /// <summary> Performs the significance propagation pass on the specified data and
                /// bit-plane. It decodes all insignificant samples which have, at least,
                /// one of its immediate eight neighbors already significant, using the ZC
                /// and SC primitives as needed. It toggles the "visited" state bit to 1
                /// for all those samples.
                /// 
                /// <p>This method bypasses the arithmetic coder and reads "raw" symbols
                /// from the bit stream.</p>
                /// 
                /// <p>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.</p>
                /// 
                /// </summary>
                /// <param name="cblk">The code-block data to decode
                /// 
                /// </param>
                /// <param name="bin">The raw bit based input
                /// 
                /// </param>
                /// <param name="bp">The bit-plane to decode
                /// 
                /// </param>
                /// <param name="state">The state information for the code-block
                /// 
                /// </param>
                /// <param name="isterm">If this pass has been terminated. If the pass has been
                /// terminated it can be used to check error resilience.
                /// 
                /// </param>
                /// <returns> True if an error was detected in the bit stream, false
                /// otherwise.
                /// 
                /// </returns>
                private bool rawSigProgPass(DataBlk cblk, ByteToBitInput bin, int bp, int[] state, 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[] 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 (bin.readBit() != 0)
                                                        {
                                                                // Became significant
                                                                // Use sign coding
                                                                sym = bin.readBit();
                                                                // 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;
                                                }
                                                if ((csj & (STATE_SIG_R2 | STATE_NZ_CTXT_R2)) == STATE_NZ_CTXT_R2)
                                                {
                                                        k += dscanw;
                                                        // Use zero coding
                                                        if (bin.readBit() != 0)
                                                        {
                                                                // Became significant
                                                                // Use sign coding
                                                                sym = bin.readBit();
                                                                // 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 (bin.readBit() != 0)
                                                        {
                                                                // Became significant
                                                                // Use sign coding
                                                                sym = bin.readBit();
                                                                // 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 (bin.readBit() != 0)
                                                        {
                                                                // Became significant
                                                                // Use sign coding
                                                                sym = bin.readBit();
                                                                // 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 byte padding if the pass is terminated and if the error
                        // resilience predictable termination is signaled in COx marker.
                        if (isterm && (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_PRED_TERM) != 0)
                        {
                                error = bin.checkBytePadding();
                        }
                        
                        // Return error condition
                        return error;
                }
                
                /// <summary> Performs the magnitude refinement pass on the specified data and
                /// bit-plane. It decodes the samples which are significant and which do not
                /// have the "visited" state bit turned on, using the MR primitive. The
                /// "visited" state bit is not mofified for any samples.
                /// 
                /// <P>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 means 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.
                /// 
                /// </summary>
                /// <param name="cblk">The code-block data to decode
                /// 
                /// </param>
                /// <param name="mq">The MQ-decoder to use
                /// 
                /// </param>
                /// <param name="bp">The bit-plane to decode
                /// 
                /// </param>
                /// <param name="state">The state information for the code-block
                /// 
                /// </param>
                /// <param name="isterm">If this pass has been terminated. If the pass has been
                /// terminated it can be used to check error resilience.
                /// 
                /// </param>
                /// <returns> True if an error was detected in the bit stream, false
                /// otherwise.
                /// 
                /// </returns>
                private bool magRefPass(DataBlk cblk, MQDecoder mq, int bp, int[] state, 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 lower bit-planes to 1/2 approximation
                        int resetmask; // The mask to reset approximation bit-planes
                        int sym; // The symbol to decode
                        int[] data; // The data buffer
                        int s; // The stripe index
                        int nstripes; // The number of stripes in the code-block
                        int sheight; // Height of the current stripe
                        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 = (1 << bp) >> 1;
                        resetmask = (- 1) << (bp + 1);
                        data = (int[]) cblk.Data;
                        nstripes = (cblk.h + CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - 1) / CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT;
                        
                        // 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 significant and not yet
                                        // visited in the current bit-plane we can not skip them
                                        if ((((SupportClass.URShift(csj, 1)) & (~ csj)) & VSTD_MASK_R1R2) != 0)
                                        {
                                                k = sk;
                                                // Scan first row
                                                if ((csj & (STATE_SIG_R1 | STATE_VISITED_R1)) == STATE_SIG_R1)
                                                {
                                                        // Use MR primitive
                                                        sym = mq.decodeSymbol(MR_LUT[csj & MR_MASK]);
                                                        // Update the data
                                                        data[k] &= resetmask;
                                                        data[k] |= (sym << bp) | setmask;
                                                        // Update the STATE_PREV_MR bit
                                                        csj |= STATE_PREV_MR_R1;
                                                }
                                                if (sheight < 2)
                                                {
                                                        state[j] = csj;
                                                        continue;
                                                }
                                                // Scan second row
                                                if ((csj & (STATE_SIG_R2 | STATE_VISITED_R2)) == STATE_SIG_R2)
                                                {
                                                        k += dscanw;
                                                        // Use MR primitive
                                                        sym = mq.decodeSymbol(MR_LUT[(SupportClass.URShift(csj, STATE_SEP)) & MR_MASK]);
                                                        // Update the data
                                                        data[k] &= resetmask;
                                                        data[k] |= (sym << bp) | setmask;
                                                        // Update the STATE_PREV_MR bit
                                                        csj |= STATE_PREV_MR_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 significant and not yet
                                        // visited in the current bit-plane we can not skip them
                                        if ((((SupportClass.URShift(csj, 1)) & (~ csj)) & VSTD_MASK_R1R2) != 0)
                                        {
                                                k = sk + (dscanw << 1);
                                                // Scan first row
                                                if ((csj & (STATE_SIG_R1 | STATE_VISITED_R1)) == STATE_SIG_R1)
                                                {
                                                        // Use MR primitive
                                                        sym = mq.decodeSymbol(MR_LUT[csj & MR_MASK]);
                                                        // Update the data
                                                        data[k] &= resetmask;
                                                        data[k] |= (sym << bp) | setmask;
                                                        // Update the STATE_PREV_MR bit
                                                        csj |= STATE_PREV_MR_R1;
                                                }
                                                if (sheight < 4)
                                                {
                                                        state[j] = csj;
                                                        continue;
                                                }
                                                // Scan second row
                                                if ((state[j] & (STATE_SIG_R2 | STATE_VISITED_R2)) == STATE_SIG_R2)
                                                {
                                                        k += dscanw;
                                                        // Use MR primitive
                                                        sym = mq.decodeSymbol(MR_LUT[(SupportClass.URShift(csj, STATE_SEP)) & MR_MASK]);
                                                        // Update the data
                                                        data[k] &= resetmask;
                                                        data[k] |= (sym << bp) | setmask;
                                                        // Update the STATE_PREV_MR bit
                                                        csj |= STATE_PREV_MR_R2;
                                                }
                                                state[j] = csj;
                                        }
                                }
                        }
                        
                        error = false;
                        
                        // Check the error resilient 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;
                }
                
                /// <summary> Performs the magnitude refinement pass on the specified data and
                /// bit-plane. It decodes the samples which are significant and which do
                /// not have the "visited" state bit turned on, using the MR primitive. The
                /// "visited" state bit is not mofified for any samples.
                /// 
                /// <P>This method bypasses the arithmetic coder and reads "raw" symbols
                /// from the bit stream.
                /// 
                /// <P>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.
                /// 
                /// </summary>
                /// <param name="cblk">The code-block data to decode
                /// 
                /// </param>
                /// <param name="bin">The raw bit based input
                /// 
                /// </param>
                /// <param name="bp">The bit-plane to decode
                /// 
                /// </param>
                /// <param name="state">The state information for the code-block
                /// 
                /// </param>
                /// <param name="isterm">If this pass has been terminated. If the pass has been
                /// terminated it can be used to check error resilience.
                /// 
                /// </param>
                /// <returns> True if an error was detected in the bit stream, false
                /// otherwise.
                /// 
                /// </returns>
                private bool rawMagRefPass(DataBlk cblk, ByteToBitInput bin, int bp, int[] state, 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 lower bit-planes to 1/2 approximation
                        int resetmask; // The mask to reset approximation bit-planes
                        int sym; // The symbol to decode
                        int[] data; // The data buffer
                        int s; // The stripe index
                        int nstripes; // The number of stripes in the code-block
                        int sheight; // Height of the current stripe
                        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 = (1 << bp) >> 1;
                        resetmask = (- 1) << (bp + 1);
                        data = (int[]) cblk.Data;
                        nstripes = (cblk.h + CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - 1) / CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT;
                        
                        // 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 significant and not yet
                                        // visited in the current bit-plane we can not skip them
                                        if ((((SupportClass.URShift(csj, 1)) & (~ csj)) & VSTD_MASK_R1R2) != 0)
                                        {
                                                k = sk;
                                                // Scan first row
                                                if ((csj & (STATE_SIG_R1 | STATE_VISITED_R1)) == STATE_SIG_R1)
                                                {
                                                        // Read raw bit (no MR primative)
                                                        sym = bin.readBit();
                                                        // Update the data
                                                        data[k] &= resetmask;
                                                        data[k] |= (sym << bp) | setmask;
                                                        // No need to set STATE_PREV_MR_R1 since all magnitude 
                                                        // refinement passes to follow are "raw"
                                                }
                                                if (sheight < 2)
                                                        continue;
                                                // Scan second row
                                                if ((csj & (STATE_SIG_R2 | STATE_VISITED_R2)) == STATE_SIG_R2)
                                                {
                                                        k += dscanw;
                                                        // Read raw bit (no MR primative)
                                                        sym = bin.readBit();
                                                        // Update the data
                                                        data[k] &= resetmask;
                                                        data[k] |= (sym << bp) | setmask;
                                                        // No need to set STATE_PREV_MR_R1 since all magnitude 
                                                        // refinement passes to follow are "raw"
                                                }
                                        }
                                        // Do half bottom of column
                                        if (sheight < 3)
                                                continue;
                                        j += sscanw;
                                        csj = state[j];
                                        // If any of the two samples is significant and not yet
                                        // visited in the current bit-plane we can not skip them
                                        if ((((SupportClass.URShift(csj, 1)) & (~ csj)) & VSTD_MASK_R1R2) != 0)
                                        {
                                                k = sk + (dscanw << 1);
                                                // Scan first row
                                                if ((csj & (STATE_SIG_R1 | STATE_VISITED_R1)) == STATE_SIG_R1)
                                                {
                                                        // Read raw bit (no MR primative)
                                                        sym = bin.readBit();
                                                        // Update the data
                                                        data[k] &= resetmask;
                                                        data[k] |= (sym << bp) | setmask;
                                                        // No need to set STATE_PREV_MR_R1 since all magnitude 
                                                        // refinement passes to follow are "raw"
                                                }
                                                if (sheight < 4)
                                                        continue;
                                                // Scan second row
                                                if ((state[j] & (STATE_SIG_R2 | STATE_VISITED_R2)) == STATE_SIG_R2)
                                                {
                                                        k += dscanw;
                                                        // Read raw bit (no MR primative)
                                                        sym = bin.readBit();
                                                        // Update the data
                                                        data[k] &= resetmask;
                                                        data[k] |= (sym << bp) | setmask;
                                                        // No need to set STATE_PREV_MR_R1 since all magnitude 
                                                        // refinement passes to follow are "raw"
                                                }
                                        }
                                }
                        }
                        
                        error = false;
                        
                        //  Check the byte padding if the pass is terminated and the
                        // predictable termination is signaled in COx marker.
                        if (isterm && (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_PRED_TERM) != 0)
                        {
                                error = bin.checkBytePadding();
                        }
                        
                        // Return error condition
                        return error;
                }
                
                /// <summary> 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.
                /// 
                /// <P>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.
                /// 
                /// </summary>
                /// <param name="cblk">The code-block data to code
                /// 
                /// </param>
                /// <param name="mq">The MQ-coder to use
                /// 
                /// </param>
                /// <param name="bp">The bit-plane to decode
                /// 
                /// </param>
                /// <param name="state">The state information for the code-block
                /// 
                /// </param>
                /// <param name="zc_lut">The ZC lookup table to use in ZC.
                /// 
                /// </param>
                /// <param name="isterm">If this pass has been terminated. If the pass has been
                /// terminated it can be used to check error resilience.
                /// 
                /// </param>
                /// <returns> True if an error was detected in the bit stream, false
                /// otherwise.
                /// 
                /// </returns>
                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;
                }
                
                /// <summary> Conceals decoding errors detected in the last bit-plane. The
                /// concealement resets the state of the decoded data to what it was before
                /// the decoding of bit-plane 'bp' started. No more data should be decoded
                /// after this method is called for this code-block's data to which it is
                /// applied.
                /// 
                /// </summary>
                /// <param name="cblk">The code-block's data
                /// 
                /// </param>
                /// <param name="bp">The last decoded bit-plane (which contains errors).
                /// 
                /// </param>
                private void  conceal(DataBlk cblk, int bp)
                {
                        int l; // line index
                        int k; // array index
                        int kmax; // 'k' limit
                        int dk; // Value of data[k]
                        int[] data; // the data array
                        int setmask; // Bitmask to set approximation to 1/2 of
                        // known interval on significant data
                        int resetmask; // Bitmask to erase all the data from
                        // bit-plane 'bp' 
                        
                        // Initialize masks
                        setmask = 1 << bp;
                        resetmask = (- 1) << (bp);
                        
                        // Get the data array
                        data = (int[]) cblk.Data;
                        
                        // Visit each sample, apply the reset mask to it and add an
                        // approximation if significant.
                        for (l = cblk.h - 1, k = cblk.offset; l >= 0; l--)
                        {
                                for (kmax = k + cblk.w; k < kmax; k++)
                                {
                                        dk = data[k];
                                        if ((dk & resetmask & 0x7FFFFFFF) != 0)
                                        {
                                                // Something was decoded in previous bit-planes => set the
                                                // approximation for previous bit-plane
                                                data[k] = (dk & resetmask) | setmask;
                                        }
                                        else
                                        {
                                                // Was insignificant in previous bit-planes = set to zero
                                                data[k] = 0;
                                        }
                                }
                                k += cblk.scanw - cblk.w;
                        }
                }
                /// <summary>Static initializer: initializes all the lookup tables. </summary>
                static StdEntropyDecoder()
                {
                        {
                                int i, j;
                                //double val, deltaMSE;
                                int[] inter_sc_lut;
                                int ds, us, rs, ls;
                                int dsgn, usgn, rsgn, lsgn;
                                int h, v;
                                
                                // Initialize the zero coding lookup tables
                                
                                // LH
                                
                                // - No neighbors significant
                                ZC_LUT_LH[0] = 2;
                                // - No horizontal or vertical neighbors significant
                                for (i = 1; i < 16; i++)
                                {
                                        // Two or more diagonal coeffs significant
                                        ZC_LUT_LH[i] = 4;
                                }
                                for (i = 0; i < 4; i++)
                                {
                                        // Only one diagonal coeff significant
                                        ZC_LUT_LH[1 << i] = 3;
                                }
                                // - No horizontal neighbors significant, diagonal irrelevant
                                for (i = 0; i < 16; i++)
                                {
                                        // Only one vertical coeff significant
                                        ZC_LUT_LH[STATE_V_U_R1 | i] = 5;
                                        ZC_LUT_LH[STATE_V_D_R1 | i] = 5;
                                        // The two vertical coeffs significant
                                        ZC_LUT_LH[STATE_V_U_R1 | STATE_V_D_R1 | i] = 6;
                                }
                                // - One horiz. neighbor significant, diagonal/vertical non-significant
                                ZC_LUT_LH[STATE_H_L_R1] = 7;
                                ZC_LUT_LH[STATE_H_R_R1] = 7;
                                // - One horiz. significant, no vertical significant, one or more
                                // diagonal significant
                                for (i = 1; i < 16; i++)
                                {
                                        ZC_LUT_LH[STATE_H_L_R1 | i] = 8;
                                        ZC_LUT_LH[STATE_H_R_R1 | i] = 8;
                                }
                                // - One horiz. significant, one or more vertical significant,
                                // diagonal irrelevant
                                for (i = 1; i < 4; i++)
                                {
                                        for (j = 0; j < 16; j++)
                                        {
                                                ZC_LUT_LH[STATE_H_L_R1 | (i << 4) | j] = 9;
                                                ZC_LUT_LH[STATE_H_R_R1 | (i << 4) | j] = 9;
                                        }
                                }
                                // - Two horiz. significant, others irrelevant
                                for (i = 0; i < 64; i++)
                                {
                                        ZC_LUT_LH[STATE_H_L_R1 | STATE_H_R_R1 | i] = 10;
                                }
                                
                                // HL
                                
                                // - No neighbors significant
                                ZC_LUT_HL[0] = 2;
                                // - No horizontal or vertical neighbors significant
                                for (i = 1; i < 16; i++)
                                {
                                        // Two or more diagonal coeffs significant
                                        ZC_LUT_HL[i] = 4;
                                }
                                for (i = 0; i < 4; i++)
                                {
                                        // Only one diagonal coeff significant
                                        ZC_LUT_HL[1 << i] = 3;
                                }
                                // - No vertical significant, diagonal irrelevant
                                for (i = 0; i < 16; i++)
                                {
                                        // One horiz. significant
                                        ZC_LUT_HL[STATE_H_L_R1 | i] = 5;
                                        ZC_LUT_HL[STATE_H_R_R1 | i] = 5;
                                        // Two horiz. significant
                                        ZC_LUT_HL[STATE_H_L_R1 | STATE_H_R_R1 | i] = 6;
                                }
                                // - One vert. significant, diagonal/horizontal non-significant
                                ZC_LUT_HL[STATE_V_U_R1] = 7;
                                ZC_LUT_HL[STATE_V_D_R1] = 7;
                                // - One vert. significant, horizontal non-significant, one or more
                                // diag. significant
                                for (i = 1; i < 16; i++)
                                {
                                        ZC_LUT_HL[STATE_V_U_R1 | i] = 8;
                                        ZC_LUT_HL[STATE_V_D_R1 | i] = 8;
                                }
                                // - One vertical significant, one or more horizontal significant,
                                // diagonal irrelevant
                                for (i = 1; i < 4; i++)
                                {
                                        for (j = 0; j < 16; j++)
                                        {
                                                ZC_LUT_HL[(i << 6) | STATE_V_U_R1 | j] = 9;
                                                ZC_LUT_HL[(i << 6) | STATE_V_D_R1 | j] = 9;
                                        }
                                }
                                // - Two vertical significant, others irrelevant
                                for (i = 0; i < 4; i++)
                                {
                                        for (j = 0; j < 16; j++)
                                        {
                                                ZC_LUT_HL[(i << 6) | STATE_V_U_R1 | STATE_V_D_R1 | j] = 10;
                                        }
                                }
                                
                                // HH
                                int[] twoBits = new int[]{3, 5, 6, 9, 10, 12}; // Figures (between 0 and 15)
                                // countaning 2 and only 2 bits on in its binary representation.
                                
                                int[] oneBit = new int[]{1, 2, 4, 8}; // Figures (between 0 and 15)
                                // countaning 1 and only 1 bit on in its binary representation.
                                
                                int[] twoLeast = new int[]{3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15}; // Figures
                                // (between 0 and 15) countaining, at least, 2 bits on in its
                                // binary representation. 
                                
                                int[] threeLeast = new int[]{7, 11, 13, 14, 15}; // Figures
                                // (between 0 and 15) countaining, at least, 3 bits on in its
                                // binary representation.
                                
                                // - None significant
                                ZC_LUT_HH[0] = 2;
                                
                                // - One horizontal+vertical significant, none diagonal
                                for (i = 0; i < oneBit.Length; i++)
                                        ZC_LUT_HH[oneBit[i] << 4] = 3;
                                
                                // - Two or more horizontal+vertical significant, diagonal non-signif
                                for (i = 0; i < twoLeast.Length; i++)
                                        ZC_LUT_HH[twoLeast[i] << 4] = 4;
                                
                                // - One diagonal significant, horiz./vert. non-significant
                                for (i = 0; i < oneBit.Length; i++)
                                        ZC_LUT_HH[oneBit[i]] = 5;
                                
                                // - One diagonal significant, one horiz.+vert. significant
                                for (i = 0; i < oneBit.Length; i++)
                                        for (j = 0; j < oneBit.Length; j++)
                                                ZC_LUT_HH[(oneBit[i] << 4) | oneBit[j]] = 6;
                                
                                // - One diag signif, two or more horiz+vert signif
                                for (i = 0; i < twoLeast.Length; i++)
                                        for (j = 0; j < oneBit.Length; j++)
                                                ZC_LUT_HH[(twoLeast[i] << 4) | oneBit[j]] = 7;
                                
                                // - Two diagonal significant, none horiz+vert significant
                                for (i = 0; i < twoBits.Length; i++)
                                        ZC_LUT_HH[twoBits[i]] = 8;
                                
                                // - Two diagonal significant, one or more horiz+vert significant
                                for (j = 0; j < twoBits.Length; j++)
                                        for (i = 1; i < 16; i++)
                                                ZC_LUT_HH[(i << 4) | twoBits[j]] = 9;
                                
                                // - Three or more diagonal significant, horiz+vert irrelevant
                                for (i = 0; i < 16; i++)
                                        for (j = 0; j < threeLeast.Length; j++)
                                                ZC_LUT_HH[(i << 4) | threeLeast[j]] = 10;
                                
                                
                                // Initialize the SC lookup tables
                                
                                // Use an intermediate sign code lookup table that is similar to the
                                // one in the VM text, in that it depends on the 'h' and 'v'
                                // quantities. The index into this table is a 6 bit index, the top 3
                                // bits are (h+1) and the low 3 bits (v+1).
                                inter_sc_lut = new int[36];
                                inter_sc_lut[(2 << 3) | 2] = 15;
                                inter_sc_lut[(2 << 3) | 1] = 14;
                                inter_sc_lut[(2 << 3) | 0] = 13;
                                inter_sc_lut[(1 << 3) | 2] = 12;
                                inter_sc_lut[(1 << 3) | 1] = 11;
                                inter_sc_lut[(1 << 3) | 0] = 12 | INT_SIGN_BIT;
                                inter_sc_lut[(0 << 3) | 2] = 13 | INT_SIGN_BIT;
                                inter_sc_lut[(0 << 3) | 1] = 14 | INT_SIGN_BIT;
                                inter_sc_lut[(0 << 3) | 0] = 15 | INT_SIGN_BIT;
                                
                                // Using the intermediate sign code lookup table create the final
                                // one. The index into this table is a 9 bit index, the low 4 bits are
                                // the significance of the 4 horizontal/vertical neighbors, while the
                                // top 4 bits are the signs of those neighbors. The bit in the middle
                                // is ignored. This index arrangement matches the state bits in the
                                // 'state' array, thus direct addressing of the table can be done from
                                // the sate information.
                                for (i = 0; i < (1 << SC_LUT_BITS) - 1; i++)
                                {
                                        ds = i & 0x01; // significance of down neighbor
                                        us = (i >> 1) & 0x01; // significance of up neighbor
                                        rs = (i >> 2) & 0x01; // significance of right neighbor
                                        ls = (i >> 3) & 0x01; // significance of left neighbor
                                        dsgn = (i >> 5) & 0x01; // sign of down neighbor
                                        usgn = (i >> 6) & 0x01; // sign of up neighbor
                                        rsgn = (i >> 7) & 0x01; // sign of right neighbor
                                        lsgn = (i >> 8) & 0x01; // sign of left neighbor
                                        // Calculate 'h' and 'v' as in VM text
                                        h = ls * (1 - 2 * lsgn) + rs * (1 - 2 * rsgn);
                                        h = (h >= - 1)?h:- 1;
                                        h = (h <= 1)?h:1;
                                        v = us * (1 - 2 * usgn) + ds * (1 - 2 * dsgn);
                                        v = (v >= - 1)?v:- 1;
                                        v = (v <= 1)?v:1;
                                        // Get context and sign predictor from 'inter_sc_lut'
                                        SC_LUT[i] = inter_sc_lut[(h + 1) << 3 | (v + 1)];
                                }
                                inter_sc_lut = null;
                                
                                // Initialize the MR lookup tables
                                
                                // None significant, prev MR off
                                MR_LUT[0] = 16;
                                // One or more significant, prev MR off
                                for (i = 1; i < (1 << (MR_LUT_BITS - 1)); i++)
                                {
                                        MR_LUT[i] = 17;
                                }
                                // Previous MR on, significance irrelevant
                                for (; i < (1 << MR_LUT_BITS); i++)
                                {
                                        MR_LUT[i] = 18;
                                }
                        }
                }
        }
}

Generated by GNU Enscript 1.6.5.90.