/* * 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 { /// 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. /// ///

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.

/// ///

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).

/// ///

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.

/// ///
public class StdEntropyDecoder:EntropyDecoder { /// Whether to collect timing information or not: false. Used as a compile /// time directive. /// private const bool DO_TIMING = false; /// The cumulative wall time for the entropy coding engine, for each /// component. /// //private long[] time; /// The bit based input for arithmetic coding bypass (i.e. raw) coding private ByteToBitInput bin; /// The MQ decoder to use. It has in as the underlying source of coded /// data. /// private MQDecoder mq; /// The decoder spec private DecoderSpecs decSpec; /// 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 /// /// /// /// /// private int options; /// Flag to indicate if we should try to detect errors or just ignore any /// error resilient information /// //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; /// Flag to indicate if we should be verbose about bit stream errors /// detected with the error resilience options /// //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; /// Number of bits used for the Zero Coding lookup table private const int ZC_LUT_BITS = 8; /// Zero Coding context lookup tables for the LH global orientation //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]; /// Zero Coding context lookup tables for the HL global orientation //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]; /// Zero Coding context lookup tables for the HH global orientation //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]; /// Number of bits used for the Sign Coding lookup table private const int SC_LUT_BITS = 9; /// 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". /// //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]; /// The mask to obtain the context index from the 'SC_LUT' private const int SC_LUT_MASK = (1 << 4) - 1; /// The shift to obtain the sign predictor from the 'SC_LUT'. It must be /// an unsigned shift. /// private const int SC_SPRED_SHIFT = 31; /// The sign bit for int data private const int INT_SIGN_BIT = 1 << 31; /// The number of bits used for the Magnitude Refinement lookup table private const int MR_LUT_BITS = 9; /// Magnitude Refinement context lookup table //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]; /// The number of contexts used private const int NUM_CTXTS = 19; /// The RLC context private const int RLC_CTXT = 1; /// The UNIFORM context (with a uniform probability distribution which /// does not adapt) /// private const int UNIF_CTXT = 0; /// The initial states for the MQ coder //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}; /// The 4 bits of the error resilience segmentation symbol (decimal 10, /// which is binary sequence 1010) /// private const int SEG_SYMBOL = 10; /// 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. /// ///

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). /// ///

The upper 16 bits the state is stored as in the lower 16 bits, but /// with the bits shifted up by 16. /// ///

The lower 16 bits are referred to as "row 1" ("R1") while the upper /// 16 bits are referred to as "row 2" ("R2"). /// ///

//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; /// The separation between the upper and lower bits in the state array: 16 /// /// private const int STATE_SEP = 16; /// The flag bit for the significance in the state array, for row 1. private const int STATE_SIG_R1 = 1 << 15; /// The flag bit for the "visited" bit in the state array, for row 1. private const int STATE_VISITED_R1 = 1 << 14; /// 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. /// private const int STATE_NZ_CTXT_R1 = 1 << 13; /// 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. /// private const int STATE_H_L_SIGN_R1 = 1 << 12; /// 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. /// private const int STATE_H_R_SIGN_R1 = 1 << 11; /// 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. /// private const int STATE_V_U_SIGN_R1 = 1 << 10; /// 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. /// private const int STATE_V_D_SIGN_R1 = 1 << 9; /// The flag bit for the previous MR primitive applied in the state array, /// for row 1. /// private const int STATE_PREV_MR_R1 = 1 << 8; /// The flag bit for the horizontal-left significance in the state array, /// for row 1. /// private const int STATE_H_L_R1 = 1 << 7; /// The flag bit for the horizontal-right significance in the state array, /// for row 1. /// private const int STATE_H_R_R1 = 1 << 6; /// The flag bit for the vertical-up significance in the state array, for /// row 1. /// private const int STATE_V_U_R1 = 1 << 5; /// The flag bit for the vertical-down significance in the state array, /// for row 1. /// private const int STATE_V_D_R1 = 1 << 4; /// The flag bit for the diagonal up-left significance in the state array, /// for row 1. /// private const int STATE_D_UL_R1 = 1 << 3; /// The flag bit for the diagonal up-right significance in the state /// array, for row 1. /// private const int STATE_D_UR_R1 = 1 << 2; /// The flag bit for the diagonal down-left significance in the state /// array, for row 1. /// private const int STATE_D_DL_R1 = 1 << 1; /// The flag bit for the diagonal down-right significance in the state /// array , for row 1. /// private const int STATE_D_DR_R1 = 1; /// The flag bit for the significance in the state array, for row 2. //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; /// The flag bit for the "visited" bit in the state array, for row 2. //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; /// 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. /// //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; /// 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. /// //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; /// 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. /// //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; /// 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. /// //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; /// 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. /// //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; /// The flag bit for the previous MR primitive applied in the state array, /// for row 2. /// //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; /// The flag bit for the horizontal-left significance in the state array, /// for row 2. /// //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; /// The flag bit for the horizontal-right significance in the state array, /// for row 2. /// //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; /// The flag bit for the vertical-up significance in the state array, for /// row 2. /// //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; /// The flag bit for the vertical-down significance in the state array, /// for row 2. /// //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; /// The flag bit for the diagonal up-left significance in the state array, /// for row 2. /// //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; /// The flag bit for the diagonal up-right significance in the state /// array, for row 2. /// //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; /// The flag bit for the diagonal down-left significance in the state /// array, for row 2. /// //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; /// The flag bit for the diagonal down-right significance in the state /// array , for row 2. /// //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; /// The mask to isolate the significance bits for row 1 and 2 of the state /// array. /// //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; /// The mask to isolate the visited bits for row 1 and 2 of the state /// array. /// //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; /// The mask to isolate the bits necessary to identify RLC coding state /// (significant, visited and non-zero context, for row 1 and 2). /// //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; /// The mask to obtain the ZC_LUT index from the 'state' information // 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; /// The shift to obtain the SC index to 'SC_LUT' from the 'state' /// information, for row 1. /// private const int SC_SHIFT_R1 = 4; /// The shift to obtain the SC index to 'SC_LUT' from the state /// information, for row 2. /// //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; /// The bit mask to isolate the state bits relative to the sign coding /// lookup table ('SC_LUT'). /// //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; /// The mask to obtain the MR index to 'MR_LUT' from the 'state' /// information. It is to be applied after the 'MR_SHIFT' /// private const int MR_MASK = (1 << 9) - 1; /// The source code-block to entropy code (avoids reallocation for each /// code-block). /// private DecLyrdCBlk srcblk; /// The maximum number of bit planes to decode for any code-block private int mQuit; /// Instantiates a new entropy decoder engine, with the specified source of /// data, nominal block width and height. /// /// /// The source of data /// /// /// 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. /// /// /// If true error detection will be performed, if any error /// detection features have been enabled. /// /// /// This flag indicates if the entropy decoder should be /// verbose about bit stream errors that are detected and concealed. /// /// /// the maximum number of bit planes to decode according to /// the m quit condition /// /// 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 /// Prints the timing information, if collected, and calls 'finalize' on /// the super class. /// /// ~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 /// Returns the specified code-block in the current tile for the specified /// component, as a copy (see below). /// ///

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. /// ///

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. /// ///

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. /// ///

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

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.

/// ///

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.

/// ///

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.

/// ///
/// The component for which to return the next code-block. /// /// /// The vertical index of the code-block to return, in the /// specified subband. /// /// /// The horizontal index of the code-block to return, in the /// specified subband. /// /// /// The subband in which the code-block to return is. /// /// /// 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. /// /// /// The next code-block in the current tile for component 'n', or /// null if all code-blocks for the current tile have been returned. /// /// /// /// /// public override DataBlk getInternCodeBlock(int c, int m, int n, SubbandSyn sb, DataBlk cblk) { return getCodeBlock(c, m, n, sb, cblk); } /// 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. /// ///

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.

/// ///
/// The code-block data to decode /// /// /// The MQ-coder to use /// /// /// The bit-plane to decode /// /// /// The state information for the code-block /// /// /// The ZC lookup table to use in ZC. /// /// /// If this pass has been terminated. If the pass has been /// terminated it can be used to check error resilience. /// /// /// True if an error was detected in the bit stream, false /// otherwise. /// /// 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; } /// 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. /// ///

This method bypasses the arithmetic coder and reads "raw" symbols /// from the bit stream.

/// ///

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.

/// ///
/// The code-block data to decode /// /// /// The raw bit based input /// /// /// The bit-plane to decode /// /// /// The state information for the code-block /// /// /// If this pass has been terminated. If the pass has been /// terminated it can be used to check error resilience. /// /// /// True if an error was detected in the bit stream, false /// otherwise. /// /// 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; } /// 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. /// ///

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. /// ///

/// The code-block data to decode /// /// /// The MQ-decoder to use /// /// /// The bit-plane to decode /// /// /// The state information for the code-block /// /// /// If this pass has been terminated. If the pass has been /// terminated it can be used to check error resilience. /// /// /// True if an error was detected in the bit stream, false /// otherwise. /// /// 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; } /// 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. /// ///

This method bypasses the arithmetic coder and reads "raw" symbols /// from the bit stream. /// ///

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. /// ///

/// The code-block data to decode /// /// /// The raw bit based input /// /// /// The bit-plane to decode /// /// /// The state information for the code-block /// /// /// If this pass has been terminated. If the pass has been /// terminated it can be used to check error resilience. /// /// /// True if an error was detected in the bit stream, false /// otherwise. /// /// 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; } /// Performs the cleanup pass on the specified data and bit-plane. It /// decodes all insignificant samples which have its "visited" state bit /// off, using the ZC, SC, and RLC primitives. It toggles the "visited" /// state bit to 0 (off) for all samples in the code-block. /// ///

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

/// The code-block data to code /// /// /// The MQ-coder to use /// /// /// The bit-plane to decode /// /// /// The state information for the code-block /// /// /// The ZC lookup table to use in ZC. /// /// /// If this pass has been terminated. If the pass has been /// terminated it can be used to check error resilience. /// /// /// True if an error was detected in the bit stream, false /// otherwise. /// /// 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; } /// 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. /// /// /// The code-block's data /// /// /// The last decoded bit-plane (which contains errors). /// /// 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; } } /// Static initializer: initializes all the lookup tables. 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; } } } } }