All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jj2000.j2k.entropy.decoder.StdEntropyDecoder Maven / Gradle / Ivy

Go to download

JPEG2000 support for Java Advanced Imaging Image I/O Tools API core. This module is licensed under the [JJ2000 license](LICENSE.txt) and is therefore NOT compatible with the GPL 3 license. It should be compatible with the LGPL 2.1 license.

There is a newer version: 1.4.0
Show newest version
/*
 * $RCSfile: StdEntropyDecoder.java,v $
 * $Revision: 1.1 $
 * $Date: 2005/02/11 05:02:07 $
 * $State: 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.
 * */
package jj2000.j2k.entropy.decoder;
import jj2000.j2k.decoder.DecoderSpecs;
import jj2000.j2k.entropy.StdEntropyCoderOptions;
import jj2000.j2k.image.DataBlk;
import jj2000.j2k.image.DataBlkInt;
import jj2000.j2k.util.ArrayUtil;
import jj2000.j2k.util.FacilityManager;
import jj2000.j2k.util.MsgLogger;
import jj2000.j2k.wavelet.Subband;
import jj2000.j2k.wavelet.synthesis.SubbandSyn;

/**
 * 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-block are rectangular, with dimensions which must be powers of
 * 2. Each dimension has to be no smaller than 4 and no larger than 256. The
 * product of the two dimensions (i.e. area of the code-block) may not 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 extends EntropyDecoder implements StdEntropyCoderOptions { /** Whether to collect timing information or not: false. Used as a compile * time directive. */ private final static boolean 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 * * @see StdEntropyCoderOptions **/ private int options; /** Flag to indicate if we should try to detect errors or just ignore any * error resilient information */ private final boolean doer; /** Flag to indicate if we should be verbose about bit stream errors detected with the error resilience options */ private final boolean verber; /** Number of bits used for the Zero Coding lookup table */ private static final int ZC_LUT_BITS = 8; /** Zero Coding context lookup tables for the LH global orientation */ private static final int ZC_LUT_LH[] = new int[1<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"). * */ private final int state[]; /** The separation between the upper and lower bits in the state array: 16 * */ private static final int STATE_SEP = 16; /** The flag bit for the significance in the state array, for row 1. */ private static final int STATE_SIG_R1 = 1<<15; /** The flag bit for the "visited" bit in the state array, for row 1. */ private static final 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 static final 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 static final 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 static final 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 static final 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 static final 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 static final int STATE_PREV_MR_R1 = 1<<8; /** The flag bit for the horizontal-left significance in the state array, for row 1. */ private static final int STATE_H_L_R1 = 1<<7; /** The flag bit for the horizontal-right significance in the state array, for row 1. */ private static final int STATE_H_R_R1 = 1<<6; /** The flag bit for the vertical-up significance in the state array, for row 1. */ private static final int STATE_V_U_R1 = 1<<5; /** The flag bit for the vertical-down significance in the state array, for row 1. */ private static final int STATE_V_D_R1 = 1<<4; /** The flag bit for the diagonal up-left significance in the state array, for row 1. */ private static final int STATE_D_UL_R1 = 1<<3; /** The flag bit for the diagonal up-right significance in the state array, for row 1.*/ private static final int STATE_D_UR_R1 = 1<<2; /** The flag bit for the diagonal down-left significance in the state array, for row 1. */ private static final int STATE_D_DL_R1 = 1<<1; /** The flag bit for the diagonal down-right significance in the state array , for row 1.*/ private static final int STATE_D_DR_R1 = 1; /** The flag bit for the significance in the state array, for row 2. */ private static final int STATE_SIG_R2 = STATE_SIG_R1<> 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<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. * * @param c The component for which to return the next code-block. * * @param m The vertical index of the code-block to return, in the * specified subband. * * @param n The horizontal index of the code-block to return, in the * specified subband. * * @param sb The subband in which the code-block to return is. * * @param 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. * * @return The next code-block in the current tile for component 'n', or * null if all code-blocks for the current tile have been returned. * * @see DataBlk * */ public 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) boolean error; // Error indicator int tslen; // Length of first terminated segment int tsidx; // Index of current terminated segment ByteInputBuffer in = null; boolean isterm; // Get the code-block to decode srcblk = src.getCodeBlock(c,m,n,sb,1,-1,srcblk); if (DO_TIMING) stime = System.currentTimeMillis(); // Retrieve options from decSpec options = ((Integer)decSpec.ecopts. getTileCompVal(tIdx,c)).intValue(); // 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.getData(); if (out_data == null || out_data.length < srcblk.w*srcblk.h) { out_data = new int[srcblk.w*srcblk.h]; cblk.setData(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 = new ByteInputBuffer(srcblk.data,0,tslen); mq = new MQDecoder(in ,NUM_CTXTS,MQ_INIT); } else { // We always start by an MQ segment mq.nextSegment(srcblk.data,0,tslen); mq.resetCtxts(); } error = false; if ((options & OPT_BYPASS) != 0) { if(bin==null){ if (in == null) in = mq.getByteInputBuffer(); bin = new ByteToBitInput(in); } } // 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 Error("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 & OPT_TERM_PASS) != 0 || ((options & OPT_BYPASS) != 0 && (31-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 & OPT_BYPASS) != 0 && (curbp < 31-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 & OPT_TERM_PASS) != 0; error = rawSigProgPass(cblk,bin,curbp,state,isterm); npasses--; if (npasses <= 0 || (error && doer)) break; if ((options & OPT_TERM_PASS) != 0) { // Start a new raw segment bin.setByteArray(null,-1,srcblk.tsLengths[++tsidx]); } isterm = (options & OPT_TERM_PASS) != 0 || ((options & OPT_BYPASS) != 0 && (31-NUM_NON_BYPASS_MS_BP-srcblk.skipMSBP>curbp)); error = rawMagRefPass(cblk,bin,curbp,state,isterm); } else {// Do not use bypass decoding mode if ((options & OPT_TERM_PASS) != 0) { // Here starts a new MQ segment mq.nextSegment(null,-1,srcblk.tsLengths[++tsidx]); } isterm = (options & OPT_TERM_PASS) != 0; error = sigProgPass(cblk,mq,curbp,state,zc_lut,isterm); npasses--; if (npasses <= 0 || (error && doer)) break; if ((options & OPT_TERM_PASS) != 0) { // Here starts a new MQ segment mq.nextSegment(null,-1,srcblk.tsLengths[++tsidx]); } isterm = (options & OPT_TERM_PASS) != 0 || ((options & OPT_BYPASS) != 0 && (31-NUM_NON_BYPASS_MS_BP-srcblk.skipMSBP>curbp)); error = magRefPass(cblk,mq,curbp,state,isterm); } npasses--; if (npasses <= 0 || (error && doer)) break; if ((options & OPT_TERM_PASS) != 0 || ((options & OPT_BYPASS) != 0 && (curbp < 31-NUM_NON_BYPASS_MS_BP-srcblk.skipMSBP))) { // Here starts a new MQ segment mq.nextSegment(null,-1,srcblk.tsLengths[++tsidx]); } isterm = (options & OPT_TERM_PASS) != 0 || ((options & OPT_BYPASS) != 0 && (31-NUM_NON_BYPASS_MS_BP-srcblk.skipMSBP)>=curbp); error = cleanuppass(cblk,mq,curbp,state,zc_lut,isterm); npasses--; if (error) break; // Goto next bit-plane curbp--; } } // If an error ocurred conceal it if (error && doer) { if (verber) { FacilityManager.getMsgLogger(). printmsg(MsgLogger.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.currentTimeMillis()-stime; // 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. * * @param c The component for which to return the next code-block. * * @param m The vertical index of the code-block to return, in the * specified subband. * * @param n The horizontal index of the code-block to return, in the * specified subband. * * @param sb The subband in which the code-block to return is. * * @param 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. * * @return The next code-block in the current tile for component 'n', or * null if all code-blocks for the current tile have been returned. * * @see DataBlk * */ public 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. * * @param cblk The code-block data to decode * * @param mq The MQ-coder to use * * @param bp The bit-plane to decode * * @param state The state information for the code-block * * @param zc_lut The ZC lookup table to use in ZC. * * @param isterm If this pass has been terminated. If the pass has been * terminated it can be used to check error resilience. * * @return True if an error was detected in the bit stream, false otherwise. * */ private boolean sigProgPass(DataBlk cblk, MQDecoder mq, int bp, int state[], int zc_lut[], boolean 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 boolean 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 boolean error; // The error condition // Initialize local variables dscanw = cblk.scanw; sscanw = cblk.w+2; jstep = sscanw*STRIPE_HEIGHT/2-cblk.w; kstep = dscanw*STRIPE_HEIGHT-cblk.w; setmask = (3<>1; data = (int[]) cblk.getData(); nstripes = (cblk.h+STRIPE_HEIGHT-1)/STRIPE_HEIGHT; causal = (options & 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) ? STRIPE_HEIGHT : cblk.h-(nstripes-1)*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[(csj>>>SC_SHIFT_R1)&SC_MASK]; sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (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[(csj>>>STATE_SEP)& ZC_MASK]) != 0) { // Became significant // Use sign coding ctxt = SC_LUT[(csj>>>SC_SHIFT_R2)&SC_MASK]; sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (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[(csj>>>SC_SHIFT_R1)&SC_MASK]; sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (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[(csj>>>STATE_SEP)& ZC_MASK]) != 0) { // Became significant // Use sign coding ctxt = SC_LUT[(csj>>>SC_SHIFT_R2)&SC_MASK]; sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (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 resilient termination if (isterm && (options & OPT_PRED_TERM) != 0) { error = mq.checkPredTerm(); } // Reset the MQ context states if we need to if ((options & 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. * * @param cblk The code-block data to decode * * @param bin The raw bit based input * * @param bp The bit-plane to decode * * @param state The state information for the code-block * * @param isterm If this pass has been terminated. If the pass has been * terminated it can be used to check error resilience. * * @return True if an error was detected in the bit stream, false otherwise. * */ private boolean rawSigProgPass(DataBlk cblk, ByteToBitInput bin, int bp, int state[], boolean 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 boolean 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 boolean error; // The error condition // Initialize local variables dscanw = cblk.scanw; sscanw = cblk.w+2; jstep = sscanw*STRIPE_HEIGHT/2-cblk.w; kstep = dscanw*STRIPE_HEIGHT-cblk.w; setmask = (3<>1; data = (int[]) cblk.getData(); nstripes = (cblk.h+STRIPE_HEIGHT-1)/STRIPE_HEIGHT; causal = (options & 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) ? STRIPE_HEIGHT : cblk.h-(nstripes-1)*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 if (isterm) { 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. * * @param cblk The code-block data to decode * * @param mq The MQ-decoder to use * * @param bp The bit-plane to decode * * @param state The state information for the code-block * * @param isterm If this pass has been terminated. If the pass has been * terminated it can be used to check error resilience. * * @return True if an error was detected in the bit stream, false otherwise. * */ private boolean magRefPass(DataBlk cblk, MQDecoder mq, int bp, int state[], boolean 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 boolean error; // The error condition // Initialize local variables dscanw = cblk.scanw; sscanw = cblk.w+2; jstep = sscanw*STRIPE_HEIGHT/2-cblk.w; kstep = dscanw*STRIPE_HEIGHT-cblk.w; setmask = (1<>1; resetmask = (-1)<<(bp+1); data = (int[]) cblk.getData(); nstripes = (cblk.h+STRIPE_HEIGHT-1)/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) ? STRIPE_HEIGHT : cblk.h-(nstripes-1)*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 ((((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<>>STATE_SEP)& MR_MASK]); // Update the data data[k] &= resetmask; data[k] |= (sym<>> 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<>>STATE_SEP)& MR_MASK]); // Update the data data[k] &= resetmask; data[k] |= (sym<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. * * @param cblk The code-block data to decode * * @param bin The raw bit based input * * @param bp The bit-plane to decode * * @param state The state information for the code-block * * @param isterm If this pass has been terminated. If the pass has been * terminated it can be used to check error resilience. * * @return True if an error was detected in the bit stream, false otherwise. * */ private boolean rawMagRefPass(DataBlk cblk, ByteToBitInput bin, int bp, int state[], boolean 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 boolean error; // The error condition // Initialize local variables dscanw = cblk.scanw; sscanw = cblk.w+2; jstep = sscanw*STRIPE_HEIGHT/2-cblk.w; kstep = dscanw*STRIPE_HEIGHT-cblk.w; setmask = (1<>1; resetmask = (-1)<<(bp+1); data = (int[]) cblk.getData(); nstripes = (cblk.h+STRIPE_HEIGHT-1)/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) ? STRIPE_HEIGHT : cblk.h-(nstripes-1)*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 ((((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<>> 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<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. * * @param cblk The code-block data to code * * @param mq The MQ-coder to use * * @param bp The bit-plane to decode * * @param state The state information for the code-block * * @param zc_lut The ZC lookup table to use in ZC. * * @param isterm If this pass has been terminated. If the pass has been * terminated it can be used to check error resilience. * * @return True if an error was detected in the bit stream, false * otherwise. * */ private boolean cleanuppass(DataBlk cblk, MQDecoder mq, int bp, int state[], int zc_lut[], boolean 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 boolean 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 boolean error; // The error condition // Initialize local variables dscanw = cblk.scanw; sscanw = cblk.w+2; jstep = sscanw*STRIPE_HEIGHT/2-cblk.w; kstep = dscanw*STRIPE_HEIGHT-cblk.w; setmask = (3<>1; data = (int[]) cblk.getData(); nstripes = (cblk.h+STRIPE_HEIGHT-1)/STRIPE_HEIGHT; causal = (options & 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) ? STRIPE_HEIGHT : cblk.h-(nstripes-1)*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]; top_half: { // 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 == 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) ^ (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 break top_half; } // 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) ^ (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]; break top_half; } } // 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[(csj>>>SC_SHIFT_R1)&SC_MASK]; sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (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[(csj>>>STATE_SEP)& ZC_MASK]) != 0) { // Became significant // Use sign coding ctxt = SC_LUT[(csj>>>SC_SHIFT_R2)&SC_MASK]; sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (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]; } // 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) ^ (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[(csj>>>STATE_SEP)& ZC_MASK]) != 0) { // Became significant // Use sign coding ctxt = SC_LUT[(csj>>>SC_SHIFT_R2)&SC_MASK]; sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (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 marker if we need to if ((options & 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 resilient termination if (isterm && (options & OPT_PRED_TERM) != 0) { error = mq.checkPredTerm(); } // Reset the MQ context states if we need to if ((options & 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. * * @param cblk The code-block's data * * @param bp 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<=0; l--) { for (kmax = k+cblk.w; k 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; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy