This class implements the MQ arithmetic coder. When initialized a specific state can be specified for each context, which may be adapted to the probability distribution that is expected for that context.

The type of length calculation and termination can be chosen at construction time. ---- Tricks that have been tried to improve speed ----

1) Merging Qe and mPS and doubling the lookup tables
Merge the mPS into Qe, as the sign bit (if Qe>=0 the sense of MPS is 0, if Qe<0 the sense is 1), and double the lookup tables. The first half of the lookup tables correspond to Qe>=0 (i.e. the sense of MPS is 0) and the second half to Qe<0 (i.e. the sense of MPS is 1). The nLPS lookup table is modified to incorporate the changes in the sense of MPS, by making it jump from the first to the second half and vice-versa, when a change is specified by the swicthLM lookup table. See JPEG book, section 13.2, page 225.
There is NO speed improvement in doing this, actually there is a slight decrease, probably due to the fact that often Q has to be negated. Also the fact that a brach of the type "if (bit==mPS[li])" is replaced by two simpler braches of the type "if (bit==0)" and "if (q<0)" may contribute to that.

2) Removing cT
It is possible to remove the cT counter by setting a flag bit in the high bits of the C register. This bit will be automatically shifted left whenever a renormalization shift occurs, which is equivalent to decreasing cT. When the flag bit reaches the sign bit (leftmost bit), which is equivalenet to cT==0, the byteOut() procedure is called. This test can be done efficiently with "c<0" since C is a signed quantity. Care must be taken in byteOut() to reset the bit in order to not interfere with other bits in the C register. See JPEG book, page 228.
There is NO speed improvement in doing this. I don't really know why since the number of operations whenever a renormalization occurs is decreased. Maybe it is due to the number of extra operations in the byteOut(), terminate() and getNumCodedBytes() procedures.

3) Change the convention of MPS and LPS.
Making the LPS interval be above the MPS interval (MQ coder convention is the opposite) can reduce the number of operations along the MPS path. In order to generate the same bit stream as with the MQ convention the output bytes need to be modified accordingly. The basic rule for this is that C = (C'^0xFF...FF)-A, where C is the codestream for the MQ convention and C' is the codestream generated by this other convention. Note that this affects bit-stuffing as well.
This has not been tested yet.

4) Removing normalization while loop on MPS path
Since in the MPS path Q is guaranteed to be always greater than 0x4000 (decimal 0.375) it is never necessary to do more than 1 renormalization shift. Therefore the test of the while loop, and the loop itself, can be removed.

5) Simplifying test on A register
Since A is always less than or equal to 0xFFFF, the test "(a & 0x8000)==0" can be replaced by the simplete test "a < 0x8000". This test is simpler in Java since it involves only 1 operation (although the original test can be converted to only one operation by smart Just-In-Time compilers)
This change has been integrated in the decoding procedures.

6) Speedup mode
Implemented a method that uses the speedup mode of the MQ-coder if possible. This should greately improve performance when coding long runs of MPS symbols that have high probability. However, to take advantage of this, the entropy coder implementation has to explicetely use it. The generated bit stream is the same as if no speedup mode would have been used.
Implemented but performance not tested yet.

7) Multiple-symbol coding
Since the time spent in a method call is non-negligable, coding several symbols with one method call reduces the overhead per coded symbol. The decodeSymbols() method implements this. However, to take advantage of it, the implementation of the entropy coder has to explicitely use it.
Implemented but performance not tested yet.

예제 #1
0
		/// <summary> Compresses the code-block in 'srcblk' and puts the results in 'ccb',
		/// using the specified options and temporary storage.
		/// 
		/// </summary>
		/// <param name="c">The component for which to return the next code-block.
		/// 
		/// </param>
		/// <param name="ccb">The object where the compressed data will be stored. If the
		/// 'data' array of 'cbb' is not null it may be reused to return the
		/// compressed data.
		/// 
		/// </param>
		/// <param name="srcblk">The code-block data to code
		/// 
		/// </param>
		/// <param name="mq">The MQ-coder to use
		/// 
		/// </param>
		/// <param name="bout">The bit level output to use. Used only if 'OPT_BYPASS' is
		/// turned on in the 'options' argument.
		/// 
		/// </param>
		/// <param name="out">The byte buffer trough which the compressed data is stored.
		/// 
		/// </param>
		/// <param name="state">The state information for the code-block
		/// 
		/// </param>
		/// <param name="distbuf">The buffer where to store the distortion  at 
		/// the end of each coding pass.
		/// 
		/// </param>
		/// <param name="ratebuf">The buffer where to store the rate (i.e. coded lenth) at 
		/// the end of each coding pass.
		/// 
		/// </param>
		/// <param name="istermbuf">The buffer where to store the terminated flag for each 
		/// coding pass.
		/// 
		/// </param>
		/// <param name="symbuf">The buffer to hold symbols to send to the MQ coder
		/// 
		/// </param>
		/// <param name="ctxtbuf">A buffer to hold the contexts to use in sending the
		/// buffered symbols to the MQ coder.
		/// 
		/// </param>
		/// <param name="options">The options to use when coding this code-block
		/// 
		/// </param>
		/// <param name="rev">The reversible flag. Should be true if the source of this
		/// code-block's data is reversible.
		/// 
		/// </param>
		/// <param name="lcType">The type of length calculation to use with the MQ coder.
		/// 
		/// </param>
		/// <param name="tType">The type of termination to use with the MQ coder.
		/// 
		/// </param>
		/// <seealso cref="getNextCodeBlock">
		/// 
		/// </seealso>
		static private void  compressCodeBlock(int c, CBlkRateDistStats ccb, CBlkWTData srcblk, MQCoder mq, BitToByteOutput bout, ByteOutputBuffer out_Renamed, int[] state, double[] distbuf, int[] ratebuf, bool[] istermbuf, int[] symbuf, int[] ctxtbuf, int options, bool rev, int lcType, int tType)
		{
			// NOTE: This method should not access any non-final instance or
			// static variables, either directly or indirectly through other
			// methods in order to be sure that the method is thread safe.
			
			int[] zc_lut; // The ZC lookup table to use
			int skipbp; // The number of non-significant bit-planes to skip
			int curbp; // The current magnitude bit-plane (starts at 30)
			int[] fm; // The distortion estimation lookup table for MR
			int[] fs; // The distortion estimation lookup table for SC
			int lmb; // The least significant magnitude bit
			int npass; // The number of coding passes, for R-D statistics
			double msew; // The distortion (MSE weight) for the current bit-plane
			double totdist; // The total cumulative distortion decrease
			int ltpidx; // The index of the last pass which is terminated
			
			// Check error-resilient termination
			if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_PRED_TERM) != 0 && tType != MQCoder.TERM_PRED_ER)
			{
				throw new System.ArgumentException("Embedded error-resilient info " + "in MQ termination option " + "specified but incorrect MQ " + "termination " + "policy specified");
			}
			// Set MQ flags
			mq.LenCalcType = lcType;
			mq.TermType = tType;
			
			lmb = 30 - srcblk.magbits + 1;
			// If there are more bit-planes to code than the implementation
			// bit-depth set lmb to 0
			lmb = (lmb < 0)?0:lmb;
			
			// Reset state
			ArrayUtil.intArraySet(state, 0);
			
			// Find the most significant bit-plane
			skipbp = calcSkipMSBP(srcblk, lmb);
			
			// Initialize output code-block
			ccb.m = srcblk.m;
			ccb.n = srcblk.n;
			ccb.sb = srcblk.sb;
			ccb.nROIcoeff = srcblk.nROIcoeff;
			ccb.skipMSBP = skipbp;
			if (ccb.nROIcoeff != 0)
			{
				ccb.nROIcp = 3 * (srcblk.nROIbp - skipbp - 1) + 1;
			}
			else
			{
				ccb.nROIcp = 0;
			}
			
			// Choose correct ZC lookup table for global orientation
			switch (srcblk.sb.orientation)
			{
				
				case Subband.WT_ORIENT_HL: 
					zc_lut = ZC_LUT_HL;
					break;
				
				case Subband.WT_ORIENT_LL: 
				case Subband.WT_ORIENT_LH: 
					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");
				
			}
			
			// Loop on significant magnitude bit-planes doing the 3 passes
			curbp = 30 - skipbp;
			fs = FS_LOSSY;
			fm = FM_LOSSY;
			msew = System.Math.Pow(2, ((curbp - lmb) << 1) - MSE_LKP_FRAC_BITS) * srcblk.sb.stepWMSE * srcblk.wmseScaling;
			totdist = 0f;
			npass = 0;
			ltpidx = - 1;
			
			// First significant bit-plane has only the pass pass
			if (curbp >= lmb)
			{
				// Do we need the "lossless" 'fs' table ?
				if (rev && curbp == lmb)
				{
					fs = FM_LOSSLESS;
				}
				// We terminate if regular termination, last bit-plane, or next
				// bit-plane is "raw".
				istermbuf[npass] = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0 || curbp == lmb || ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - skipbp) >= curbp);
				totdist += cleanuppass(srcblk, mq, istermbuf[npass], curbp, state, fs, zc_lut, symbuf, ctxtbuf, ratebuf, npass, ltpidx, options) * msew;
				distbuf[npass] = totdist;
				if (istermbuf[npass])
					ltpidx = npass;
				npass++;
				msew *= 0.25;
				curbp--;
			}
			// Other bit-planes have all passes
			while (curbp >= lmb)
			{
				// Do we need the "lossless" 'fs' and 'fm' tables ?
				if (rev && curbp == lmb)
				{
					fs = FS_LOSSLESS;
					fm = FM_LOSSLESS;
				}
				
				// Do the significance propagation pass
				// We terminate if regular termination only
				istermbuf[npass] = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0;
				if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) == 0 || (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - skipbp <= curbp))
				{
					// No bypass coding
					totdist += sigProgPass(srcblk, mq, istermbuf[npass], curbp, state, fs, zc_lut, symbuf, ctxtbuf, ratebuf, npass, ltpidx, options) * msew;
				}
				else
				{
					// Bypass ("raw") coding
					bout.PredTerm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_PRED_TERM) != 0;
					totdist += rawSigProgPass(srcblk, bout, istermbuf[npass], curbp, state, fs, ratebuf, npass, ltpidx, options) * msew;
				}
				distbuf[npass] = totdist;
				if (istermbuf[npass])
					ltpidx = npass;
				npass++;
				
				// Do the magnitude refinement pass
				// We terminate if regular termination or bypass ("raw") coding
				istermbuf[npass] = (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 - skipbp > curbp));
				if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) == 0 || (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - skipbp <= curbp))
				{
					// No bypass coding
					totdist += magRefPass(srcblk, mq, istermbuf[npass], curbp, state, fm, symbuf, ctxtbuf, ratebuf, npass, ltpidx, options) * msew;
				}
				else
				{
					// Bypass ("raw") coding
					bout.PredTerm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_PRED_TERM) != 0;
					totdist += rawMagRefPass(srcblk, bout, istermbuf[npass], curbp, state, fm, ratebuf, npass, ltpidx, options) * msew;
				}
				distbuf[npass] = totdist;
				if (istermbuf[npass])
					ltpidx = npass;
				npass++;
				
				// Do the clenup pass
				// We terminate if regular termination, last bit-plane, or next
				// bit-plane is "raw".
				istermbuf[npass] = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0 || curbp == lmb || ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - skipbp) >= curbp);
				totdist += cleanuppass(srcblk, mq, istermbuf[npass], curbp, state, fs, zc_lut, symbuf, ctxtbuf, ratebuf, npass, ltpidx, options) * msew;
				distbuf[npass] = totdist;
				
				if (istermbuf[npass])
					ltpidx = npass;
				npass++;
				
				// Goto next bit-plane
				msew *= 0.25;
				curbp--;
			}
			
			// Copy compressed data and rate-distortion statistics to output
			ccb.data = new byte[out_Renamed.size()];
			out_Renamed.toByteArray(0, out_Renamed.size(), ccb.data, 0);
			checkEndOfPassFF(ccb.data, ratebuf, istermbuf, npass);
			ccb.selectConvexHull(ratebuf, distbuf, (options & (CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS | CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS)) != 0?istermbuf:null, npass, rev);
			
			// Reset MQ coder and bit output for next code-block
			mq.reset();
			if (bout != null)
				bout.reset();
		}
예제 #2
0
		/// <summary> Instantiates a new entropy coder engine, with the specified source of
		/// data, nominal block width and height.
		/// 
		/// <p>If the 'OPT_PRED_TERM' option is given then the MQ termination must
		/// be 'TERM_PRED_ER' or an exception is thrown.</p>
		/// 
		/// </summary>
		/// <param name="src">The source of data
		/// 
		/// </param>
		/// <param name="cbks">Code-block size specifications
		/// 
		/// </param>
		/// <param name="pss">Precinct partition specifications
		/// 
		/// </param>
		/// <param name="bms">By-pass mode specifications
		/// 
		/// </param>
		/// <param name="mqrs">MQ-reset specifications
		/// 
		/// </param>
		/// <param name="rts">Regular termination specifications
		/// 
		/// </param>
		/// <param name="css">Causal stripes specifications
		/// 
		/// </param>
		/// <param name="sss">Error resolution segment symbol use specifications
		/// 
		/// </param>
		/// <param name="lcs">Length computation specifications
		/// 
		/// </param>
		/// <param name="tts">Termination type specifications
		/// 
		/// </param>
		/// <seealso cref="MQCoder">
		/// 
		/// </seealso>
		public StdEntropyCoder(CBlkQuantDataSrcEnc src, CBlkSizeSpec cblks, PrecinctSizeSpec pss, StringSpec bms, StringSpec mqrs, StringSpec rts, StringSpec css, StringSpec sss, StringSpec lcs, StringSpec tts):base(src)
		{
			this.cblks = cblks;
			this.pss = pss;
			this.bms = bms;
			this.mqrs = mqrs;
			this.rts = rts;
			this.css = css;
			this.sss = sss;
			this.lcs = lcs;
			this.tts = tts;
			int maxCBlkWidth, maxCBlkHeight;
			int i; // Counter
			int tsl; // Size for thread structures
			
			// Get the biggest width/height for the code-blocks
			maxCBlkWidth = cblks.MaxCBlkWidth;
			maxCBlkHeight = cblks.MaxCBlkHeight;
			
			// 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
		
			tsl = 1;
			finishedTileComponent = null;
			
			// Allocate data structures
			outT = new ByteOutputBuffer[tsl];
			mqT = new MQCoder[tsl];
			boutT = new BitToByteOutput[tsl];
			stateT = new int[tsl][];
			for (int i2 = 0; i2 < tsl; i2++)
			{
				stateT[i2] = new int[(maxCBlkWidth + 2) * ((maxCBlkHeight + 1) / 2 + 2)];
			}
			symbufT = new int[tsl][];
			for (int i3 = 0; i3 < tsl; i3++)
			{
				symbufT[i3] = new int[maxCBlkWidth * (CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT * 2 + 2)];
			}
			ctxtbufT = new int[tsl][];
			for (int i4 = 0; i4 < tsl; i4++)
			{
				ctxtbufT[i4] = new int[maxCBlkWidth * (CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT * 2 + 2)];
			}
			distbufT = new double[tsl][];
			for (int i5 = 0; i5 < tsl; i5++)
			{
				distbufT[i5] = new double[32 * CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_PASSES];
			}
			ratebufT = new int[tsl][];
			for (int i6 = 0; i6 < tsl; i6++)
			{
				ratebufT[i6] = new int[32 * CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_PASSES];
			}
			istermbufT = new bool[tsl][];
			for (int i7 = 0; i7 < tsl; i7++)
			{
				istermbufT[i7] = new bool[32 * CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_PASSES];
			}
			srcblkT = new CBlkWTData[tsl];
			for (i = 0; i < tsl; i++)
			{
				outT[i] = new ByteOutputBuffer();
				mqT[i] = new MQCoder(outT[i], NUM_CTXTS, MQ_INIT);
			}
			precinctPartition = new bool[src.NumComps][];
			for (int i8 = 0; i8 < src.NumComps; i8++)
			{
				precinctPartition[i8] = new bool[src.getNumTiles()];
			}
			
			// Create the subband description for each component and each tile
			//Subband sb = null;
			Coord numTiles = null;
			int nc = NumComps;
			numTiles = src.getNumTiles(numTiles);
			initTileComp(getNumTiles(), nc);
			
			for (int c = 0; c < nc; c++)
			{
				for (int tY = 0; tY < numTiles.y; tY++)
				{
					for (int tX = 0; tX < numTiles.x; tX++)
					{
						precinctPartition[c][tIdx] = false;
					}
				}
			}
		}
예제 #3
0
		/// <summary> Performs the cleanup pass on the specified data and bit-plane. It codes
		/// 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.
		/// 
		/// </summary>
		/// <param name="srcblk">The code-block data to code
		/// 
		/// </param>
		/// <param name="mq">The MQ-coder to use
		/// 
		/// </param>
		/// <param name="doterm">If true it performs an MQ-coder termination after the end
		/// of the pass
		/// 
		/// </param>
		/// <param name="bp">The bit-plane to code
		/// 
		/// </param>
		/// <param name="state">The state information for the code-block
		/// 
		/// </param>
		/// <param name="fs">The distortion estimation lookup table for SC
		/// 
		/// </param>
		/// <param name="zc_lut">The ZC lookup table to use in ZC.
		/// 
		/// </param>
		/// <param name="symbuf">The buffer to hold symbols to send to the MQ coder
		/// 
		/// </param>
		/// <param name="ctxtbuf">A buffer to hold the contexts to use in sending the
		/// buffered symbols to the MQ coder.
		/// 
		/// </param>
		/// <param name="ratebuf">The buffer where to store the rate (i.e. coded lenth) at 
		/// the end of this coding pass.
		/// 
		/// </param>
		/// <param name="pidx">The coding pass index. Is the index in the 'ratebuf' array
		/// where to store the coded length after this coding pass.
		/// 
		/// </param>
		/// <param name="ltpidx">The index of the last pass that was terminated, or
		/// negative if none.
		/// 
		/// </param>
		/// <param name="options">The bitmask of entropy coding options to apply to the
		/// code-block
		/// 
		/// </param>
		/// <returns> The decrease in distortion for this pass, in the fixed-point
		/// normalized representation of the 'FS_LOSSY' and 'FS_LOSSLESS' tables.
		/// 
		/// </returns>
		static private int cleanuppass(CBlkWTData srcblk, MQCoder mq, bool doterm, int bp, int[] state, int[] fs, int[] zc_lut, int[] symbuf, int[] ctxtbuf, int[] ratebuf, int pidx, int ltpidx, int options)
		{
			// NOTE: The speedup mode of the MQ coder has been briefly tried to
			// speed up the coding of insignificants RLCs, without any success
			// (i.e. no speedup whatsoever). The use of the speedup mode should be
			// revisisted more in depth and the implementationn of it in MQCoder
			// should be reviewed for optimization opportunities.
			int j, sj; // The state index for line and stripe
			int k, sk; // The data index for line and stripe
			int nsym = 0; // Symbol counter for symbol and context buffers
			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 mask; // The mask for the current bit-plane
			int sym; // The symbol to code
			int rlclen; // Length of RLC
			int ctxt; // The context to use
			int[] data; // The data buffer
			int dist; // The distortion reduction for this pass
			int shift; // Shift amount for distortion
			int upshift; // Shift left amount for distortion
			int downshift; // Shift right amount for distortion
			int normval; // The normalized sample magnitude value
			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
			
			// Initialize local variables
			dscanw = srcblk.scanw;
			sscanw = srcblk.w + 2;
			jstep = sscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT / 2 - srcblk.w;
			kstep = dscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - srcblk.w;
			mask = 1 << bp;
			data = (int[]) srcblk.Data;
			nstripes = (srcblk.h + CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - 1) / CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT;
			dist = 0;
			// We use the MSE_LKP_BITS-1 bits below the bit just coded for
			// distortion estimation.
			shift = bp - (MSE_LKP_BITS - 1);
			upshift = (shift >= 0)?0:- shift;
			downshift = (shift <= 0)?0:shift;
			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
			
			// Code stripe by stripe
			sk = srcblk.offset;
			sj = sscanw + 1;
			for (s = nstripes - 1; s >= 0; s--, sk += kstep, sj += jstep)
			{
				sheight = (s != 0)?CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT:srcblk.h - (nstripes - 1) * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT;
				stopsk = sk + srcblk.w;
				// Scan by set of 1 stripe column at a time
				for (nsym = 0; 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)
						{
							k = sk;
							if ((data[k] & mask) != 0)
							{
								rlclen = 0;
							}
							else if ((data[k += dscanw] & mask) != 0)
							{
								rlclen = 1;
							}
							else if ((data[k += dscanw] & mask) != 0)
							{
								rlclen = 2;
								j += sscanw;
								csj = state[j];
							}
							else if ((data[k += dscanw] & mask) != 0)
							{
								rlclen = 3;
								j += sscanw;
								csj = state[j];
							}
							else
							{
								// Code insignificant RLC
								symbuf[nsym] = 0;
								ctxtbuf[nsym++] = RLC_CTXT;
								// Goto next column
								continue;
							}
							// Code significant RLC
							symbuf[nsym] = 1;
							ctxtbuf[nsym++] = RLC_CTXT;
							// Send MSB bit index
							symbuf[nsym] = rlclen >> 1;
							ctxtbuf[nsym++] = UNIF_CTXT;
							// Send LSB bit index
							symbuf[nsym] = rlclen & 0x01;
							ctxtbuf[nsym++] = UNIF_CTXT;
							// Code sign of sample that became significant
							// Update distortion
							normval = (data[k] >> downshift) << upshift;
							dist += fs[normval & ((1 << (MSE_LKP_BITS - 1)) - 1)];
							// Apply sign coding
							sym = SupportClass.URShift(data[k], 31);
							if ((rlclen & 0x01) == 0)
							{
								// Sample that became significant is first row of
								// its column half
								ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R1)) & SC_MASK];
								symbuf[nsym] = sym ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
								ctxtbuf[nsym++] = ctxt & SC_LUT_MASK;
								// 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[(SupportClass.URShift(csj, SC_SHIFT_R2)) & SC_MASK];
								symbuf[nsym] = sym ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
								ctxtbuf[nsym++] = ctxt & SC_LUT_MASK;
								// 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)
							{
								// Apply zero coding
								ctxtbuf[nsym] = zc_lut[csj & ZC_MASK];
								if ((symbuf[nsym++] = SupportClass.URShift((data[k] & mask), bp)) != 0)
								{
									// Became significant
									// Apply sign coding
									sym = SupportClass.URShift(data[k], 31);
									ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R1)) & SC_MASK];
									symbuf[nsym] = sym ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
									ctxtbuf[nsym++] = ctxt & SC_LUT_MASK;
									// 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;
									}
									// Update distortion
									normval = (data[k] >> downshift) << upshift;
									dist += fs[normval & ((1 << (MSE_LKP_BITS - 1)) - 1)];
								}
							}
							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;
								// Apply zero coding
								ctxtbuf[nsym] = zc_lut[(SupportClass.URShift(csj, STATE_SEP)) & ZC_MASK];
								if ((symbuf[nsym++] = SupportClass.URShift((data[k] & mask), bp)) != 0)
								{
									// Became significant
									// Apply sign coding
									sym = SupportClass.URShift(data[k], 31);
									ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R2)) & SC_MASK];
									symbuf[nsym] = sym ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
									ctxtbuf[nsym++] = ctxt & SC_LUT_MASK;
									// 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;
									}
									// Update distortion
									normval = (data[k] >> downshift) << upshift;
									dist += fs[normval & ((1 << (MSE_LKP_BITS - 1)) - 1)];
								}
							}
						}
						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)
						{
							// Apply zero coding
							ctxtbuf[nsym] = zc_lut[csj & ZC_MASK];
							if ((symbuf[nsym++] = SupportClass.URShift((data[k] & mask), bp)) != 0)
							{
								// Became significant
								// Apply sign coding
								sym = SupportClass.URShift(data[k], 31);
								ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R1)) & SC_MASK];
								symbuf[nsym] = sym ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
								ctxtbuf[nsym++] = ctxt & SC_LUT_MASK;
								// 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;
								}
								// Update distortion
								normval = (data[k] >> downshift) << upshift;
								dist += fs[normval & ((1 << (MSE_LKP_BITS - 1)) - 1)];
							}
						}
						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;
							// Apply zero coding
							ctxtbuf[nsym] = zc_lut[(SupportClass.URShift(csj, STATE_SEP)) & ZC_MASK];
							if ((symbuf[nsym++] = SupportClass.URShift((data[k] & mask), bp)) != 0)
							{
								// Became significant
								// Apply sign coding
								sym = SupportClass.URShift(data[k], 31);
								ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R2)) & SC_MASK];
								symbuf[nsym] = sym ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
								ctxtbuf[nsym++] = ctxt & SC_LUT_MASK;
								// 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;
								}
								// Update distortion
								normval = (data[k] >> downshift) << upshift;
								dist += fs[normval & ((1 << (MSE_LKP_BITS - 1)) - 1)];
							}
						}
					}
					csj &= ~ (STATE_VISITED_R1 | STATE_VISITED_R2);
					state[j] = csj;
				}
				// Code all buffered symbols, if any
				if (nsym > 0)
					mq.codeSymbols(symbuf, ctxtbuf, nsym);
			}
			
			// Insert a segment marker if we need to
			if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_SEG_SYMBOLS) != 0)
			{
				mq.codeSymbols(SEG_SYMBOLS, SEG_SYMB_CTXTS, SEG_SYMBOLS.Length);
			}
			
			// Reset the MQ context states if we need to
			if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_RESET_MQ) != 0)
			{
				mq.resetCtxts();
			}
			
			// Terminate the MQ bit stream if we need to
			if (doterm)
			{
				ratebuf[pidx] = mq.terminate(); // Termination has special length
			}
			else
			{
				// Use normal length calculation
				ratebuf[pidx] = mq.NumCodedBytes;
			}
			// Add length of previous segments, if any
			if (ltpidx >= 0)
			{
				ratebuf[pidx] += ratebuf[ltpidx];
			}
			// Finish length calculation if needed
			if (doterm)
			{
				mq.finishLengthCalculation(ratebuf, pidx);
			}
			// Return the reduction in distortion
			return dist;
		}
예제 #4
0
		/// <summary> Performs the magnitude refinement pass on the specified data and
		/// bit-plane. It codes 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.
		/// 
		/// </summary>
		/// <param name="srcblk">The code-block data to code
		/// 
		/// </param>
		/// <param name="mq">The MQ-coder to use
		/// 
		/// </param>
		/// <param name="doterm">If true it performs an MQ-coder termination after the end
		/// of the pass
		/// 
		/// </param>
		/// <param name="bp">The bit-plane to code
		/// 
		/// </param>
		/// <param name="state">The state information for the code-block
		/// 
		/// </param>
		/// <param name="fm">The distortion estimation lookup table for MR
		/// 
		/// </param>
		/// <param name="symbuf">The buffer to hold symbols to send to the MQ coder
		/// 
		/// </param>
		/// <param name="ctxtbuf">A buffer to hold the contexts to use in sending the
		/// buffered symbols to the MQ coder.
		/// 
		/// </param>
		/// <param name="ratebuf">The buffer where to store the rate (i.e. coded lenth) at 
		/// the end of this coding pass.
		/// 
		/// </param>
		/// <param name="pidx">The coding pass index. Is the index in the 'ratebuf' array
		/// where to store the coded length after this coding pass.
		/// 
		/// </param>
		/// <param name="ltpidx">The index of the last pass that was terminated, or
		/// negative if none.
		/// 
		/// </param>
		/// <param name="options">The bitmask of entropy coding options to apply to the
		/// code-block
		/// 
		/// </param>
		/// <returns> The decrease in distortion for this pass, in the fixed-point
		/// normalized representation of the 'FS_LOSSY' and 'FS_LOSSLESS' tables.
		/// 
		/// </returns>
		static private int magRefPass(CBlkWTData srcblk, MQCoder mq, bool doterm, int bp, int[] state, int[] fm, int[] symbuf, int[] ctxtbuf, int[] ratebuf, int pidx, int ltpidx, int options)
		{
			int j, sj; // The state index for line and stripe
			int k, sk; // The data index for line and stripe
			int nsym = 0; // Symbol counter for symbol and context buffers
			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 mask; // The mask for the current bit-plane
			int[] data; // The data buffer
			int dist; // The distortion reduction for this pass
			int shift; // Shift amount for distortion
			int upshift; // Shift left amount for distortion
			int downshift; // Shift right amount for distortion
			int normval; // The normalized sample magnitude value
			int s; // The stripe index
			int nstripes; // The number of stripes in the code-block
			int sheight; // Height of the current stripe
			
			// Initialize local variables
			dscanw = srcblk.scanw;
			sscanw = srcblk.w + 2;
			jstep = sscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT / 2 - srcblk.w;
			kstep = dscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - srcblk.w;
			mask = 1 << bp;
			data = (int[]) srcblk.Data;
			nstripes = (srcblk.h + CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - 1) / CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT;
			dist = 0;
			// We use the bit just coded plus MSE_LKP_BITS-1 bits below the bit
			// just coded for distortion estimation.
			shift = bp - (MSE_LKP_BITS - 1);
			upshift = (shift >= 0)?0:- shift;
			downshift = (shift <= 0)?0:shift;
			
			// Code stripe by stripe
			sk = srcblk.offset;
			sj = sscanw + 1;
			for (s = nstripes - 1; s >= 0; s--, sk += kstep, sj += jstep)
			{
				sheight = (s != 0)?CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT:srcblk.h - (nstripes - 1) * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT;
				stopsk = sk + srcblk.w;
				// Scan by set of 1 stripe column at a time
				for (nsym = 0; 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)
						{
							// Apply MR primitive
							symbuf[nsym] = SupportClass.URShift((data[k] & mask), bp);
							ctxtbuf[nsym++] = MR_LUT[csj & MR_MASK];
							// Update the STATE_PREV_MR bit
							csj |= STATE_PREV_MR_R1;
							// Update distortion
							normval = (data[k] >> downshift) << upshift;
							dist += fm[normval & ((1 << MSE_LKP_BITS) - 1)];
						}
						if (sheight < 2)
						{
							state[j] = csj;
							continue;
						}
						// Scan second row
						if ((csj & (STATE_SIG_R2 | STATE_VISITED_R2)) == STATE_SIG_R2)
						{
							k += dscanw;
							// Apply MR primitive
							symbuf[nsym] = SupportClass.URShift((data[k] & mask), bp);
							ctxtbuf[nsym++] = MR_LUT[(SupportClass.URShift(csj, STATE_SEP)) & MR_MASK];
							// Update the STATE_PREV_MR bit
							csj |= STATE_PREV_MR_R2;
							// Update distortion
							normval = (data[k] >> downshift) << upshift;
							dist += fm[normval & ((1 << MSE_LKP_BITS) - 1)];
						}
						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)
						{
							// Apply MR primitive
							symbuf[nsym] = SupportClass.URShift((data[k] & mask), bp);
							ctxtbuf[nsym++] = MR_LUT[csj & MR_MASK];
							// Update the STATE_PREV_MR bit
							csj |= STATE_PREV_MR_R1;
							// Update distortion
							normval = (data[k] >> downshift) << upshift;
							dist += fm[normval & ((1 << MSE_LKP_BITS) - 1)];
						}
						if (sheight < 4)
						{
							state[j] = csj;
							continue;
						}
						// Scan second row
						if ((state[j] & (STATE_SIG_R2 | STATE_VISITED_R2)) == STATE_SIG_R2)
						{
							k += dscanw;
							// Apply MR primitive
							symbuf[nsym] = SupportClass.URShift((data[k] & mask), bp);
							ctxtbuf[nsym++] = MR_LUT[(SupportClass.URShift(csj, STATE_SEP)) & MR_MASK];
							// Update the STATE_PREV_MR bit
							csj |= STATE_PREV_MR_R2;
							// Update distortion
							normval = (data[k] >> downshift) << upshift;
							dist += fm[normval & ((1 << MSE_LKP_BITS) - 1)];
						}
						state[j] = csj;
					}
				}
				// Code all buffered symbols, if any
				if (nsym > 0)
					mq.codeSymbols(symbuf, ctxtbuf, nsym);
			}
			
			// Reset the MQ context states if we need to
			if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_RESET_MQ) != 0)
			{
				mq.resetCtxts();
			}
			
			// Terminate the MQ bit stream if we need to
			if (doterm)
			{
				ratebuf[pidx] = mq.terminate(); // Termination has special length
			}
			else
			{
				// Use normal length calculation
				ratebuf[pidx] = mq.NumCodedBytes;
			}
			// Add length of previous segments, if any
			if (ltpidx >= 0)
			{
				ratebuf[pidx] += ratebuf[ltpidx];
			}
			// Finish length calculation if needed
			if (doterm)
			{
				mq.finishLengthCalculation(ratebuf, pidx);
			}
			
			// Return the reduction in distortion
			return dist;
		}
예제 #5
0
		/// <summary> Performs the significance propagation pass on the specified data and
		/// bit-plane. It codes 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.
		/// 
		/// </summary>
		/// <param name="srcblk">The code-block data to code
		/// 
		/// </param>
		/// <param name="mq">The MQ-coder to use
		/// 
		/// </param>
		/// <param name="doterm">If true it performs an MQ-coder termination after the end
		/// of the pass
		/// 
		/// </param>
		/// <param name="bp">The bit-plane to code
		/// 
		/// </param>
		/// <param name="state">The state information for the code-block
		/// 
		/// </param>
		/// <param name="fs">The distortion estimation lookup table for SC
		/// 
		/// </param>
		/// <param name="zc_lut">The ZC lookup table to use in ZC.
		/// 
		/// </param>
		/// <param name="symbuf">The buffer to hold symbols to send to the MQ coder
		/// 
		/// </param>
		/// <param name="ctxtbuf">A buffer to hold the contexts to use in sending the
		/// buffered symbols to the MQ coder.
		/// 
		/// </param>
		/// <param name="ratebuf">The buffer where to store the rate (i.e. coded lenth) at 
		/// the end of this coding pass.
		/// 
		/// </param>
		/// <param name="pidx">The coding pass index. Is the index in the 'ratebuf' array
		/// where to store the coded length after this coding pass.
		/// 
		/// </param>
		/// <param name="ltpidx">The index of the last pass that was terminated, or
		/// negative if none.
		/// 
		/// </param>
		/// <param name="options">The bitmask of entropy coding options to apply to the
		/// code-block
		/// 
		/// </param>
		/// <returns> The decrease in distortion for this pass, in the fixed-point
		/// normalized representation of the 'FS_LOSSY' and 'FS_LOSSLESS' tables.
		/// 
		/// </returns>
		static private int sigProgPass(CBlkWTData srcblk, MQCoder mq, bool doterm, int bp, int[] state, int[] fs, int[] zc_lut, int[] symbuf, int[] ctxtbuf, int[] ratebuf, int pidx, int ltpidx, int options)
		{
			int j, sj; // The state index for line and stripe
			int k, sk; // The data index for line and stripe
			int nsym = 0; // Symbol counter for symbol and context buffers
			int dscanw; // The data scan-width
			int sscanw; // The state and packed 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 mask; // The mask for the current bit-plane
			int sym; // The symbol to code
			int ctxt; // The context to use
			int[] data; // The data buffer
			int dist; // The distortion reduction for this pass
			int shift; // Shift amount for distortion
			int upshift; // Shift left amount for distortion
			int downshift; // Shift right amount for distortion
			int normval; // The normalized sample magnitude value
			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
			
			// Initialize local variables
			dscanw = srcblk.scanw;
			sscanw = srcblk.w + 2;
			jstep = sscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT / 2 - srcblk.w;
			kstep = dscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - srcblk.w;
			mask = 1 << bp;
			data = (int[]) srcblk.Data;
			nstripes = (srcblk.h + CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - 1) / CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT;
			dist = 0;
			// We use the MSE_LKP_BITS-1 bits below the bit just coded for
			// distortion estimation.
			shift = bp - (MSE_LKP_BITS - 1);
			upshift = (shift >= 0)?0:- shift;
			downshift = (shift <= 0)?0:shift;
			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
			
			// Code stripe by stripe
			sk = srcblk.offset;
			sj = sscanw + 1;
			for (s = nstripes - 1; s >= 0; s--, sk += kstep, sj += jstep)
			{
				sheight = (s != 0)?CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT:srcblk.h - (nstripes - 1) * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT;
				stopsk = sk + srcblk.w;
				// Scan by set of 1 stripe column at a time
				for (nsym = 0; 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)
						{
							// Apply zero coding
							ctxtbuf[nsym] = zc_lut[csj & ZC_MASK];
							if ((symbuf[nsym++] = SupportClass.URShift((data[k] & mask), bp)) != 0)
							{
								// Became significant
								// Apply sign coding
								sym = SupportClass.URShift(data[k], 31);
								ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R1)) & SC_MASK];
								symbuf[nsym] = sym ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
								ctxtbuf[nsym++] = ctxt & SC_LUT_MASK;
								// 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;
								}
								// Update distortion
								normval = (data[k] >> downshift) << upshift;
								dist += fs[normval & ((1 << (MSE_LKP_BITS - 1)) - 1)];
							}
							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;
							// Apply zero coding
							ctxtbuf[nsym] = zc_lut[(SupportClass.URShift(csj, STATE_SEP)) & ZC_MASK];
							if ((symbuf[nsym++] = SupportClass.URShift((data[k] & mask), bp)) != 0)
							{
								// Became significant
								// Apply sign coding
								sym = SupportClass.URShift(data[k], 31);
								ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R2)) & SC_MASK];
								symbuf[nsym] = sym ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
								ctxtbuf[nsym++] = ctxt & SC_LUT_MASK;
								// 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;
								}
								// Update distortion
								normval = (data[k] >> downshift) << upshift;
								dist += fs[normval & ((1 << (MSE_LKP_BITS - 1)) - 1)];
							}
							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)
						{
							// Apply zero coding
							ctxtbuf[nsym] = zc_lut[csj & ZC_MASK];
							if ((symbuf[nsym++] = SupportClass.URShift((data[k] & mask), bp)) != 0)
							{
								// Became significant
								// Apply sign coding
								sym = SupportClass.URShift(data[k], 31);
								ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R1)) & SC_MASK];
								symbuf[nsym] = sym ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
								ctxtbuf[nsym++] = ctxt & SC_LUT_MASK;
								// 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;
								}
								// Update distortion
								normval = (data[k] >> downshift) << upshift;
								dist += fs[normval & ((1 << (MSE_LKP_BITS - 1)) - 1)];
							}
							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;
							// Apply zero coding
							ctxtbuf[nsym] = zc_lut[(SupportClass.URShift(csj, STATE_SEP)) & ZC_MASK];
							if ((symbuf[nsym++] = SupportClass.URShift((data[k] & mask), bp)) != 0)
							{
								// Became significant
								// Apply sign coding
								sym = SupportClass.URShift(data[k], 31);
								ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R2)) & SC_MASK];
								symbuf[nsym] = sym ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
								ctxtbuf[nsym++] = ctxt & SC_LUT_MASK;
								// 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;
								}
								// Update distortion
								normval = (data[k] >> downshift) << upshift;
								dist += fs[normval & ((1 << (MSE_LKP_BITS - 1)) - 1)];
							}
							else
							{
								csj |= STATE_VISITED_R2;
							}
						}
						state[j] = csj;
					}
				}
				// Code all buffered symbols
				mq.codeSymbols(symbuf, ctxtbuf, nsym);
			}
			// Reset the MQ context states if we need to
			if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_RESET_MQ) != 0)
			{
				mq.resetCtxts();
			}
			
			// Terminate the MQ bit stream if we need to
			if (doterm)
			{
				ratebuf[pidx] = mq.terminate(); // Termination has special length
			}
			else
			{
				// Use normal length calculation
				ratebuf[pidx] = mq.NumCodedBytes;
			}
			// Add length of previous segments, if any
			if (ltpidx >= 0)
			{
				ratebuf[pidx] += ratebuf[ltpidx];
			}
			// Finish length calculation if needed
			if (doterm)
			{
				mq.finishLengthCalculation(ratebuf, pidx);
			}
			
			// Return the reduction in distortion
			return dist;
		}
예제 #6
0
		/// <summary> Instantiates a new entropy coder engine, with the specified source of
		/// data, nominal block width and height.
		/// 
		/// <p>If the 'OPT_PRED_TERM' option is given then the MQ termination must
		/// be 'TERM_PRED_ER' or an exception is thrown.</p>
		/// 
		/// </summary>
		/// <param name="src">The source of data
		/// 
		/// </param>
		/// <param name="cbks">Code-block size specifications
		/// 
		/// </param>
		/// <param name="pss">Precinct partition specifications
		/// 
		/// </param>
		/// <param name="bms">By-pass mode specifications
		/// 
		/// </param>
		/// <param name="mqrs">MQ-reset specifications
		/// 
		/// </param>
		/// <param name="rts">Regular termination specifications
		/// 
		/// </param>
		/// <param name="css">Causal stripes specifications
		/// 
		/// </param>
		/// <param name="sss">Error resolution segment symbol use specifications
		/// 
		/// </param>
		/// <param name="lcs">Length computation specifications
		/// 
		/// </param>
		/// <param name="tts">Termination type specifications
		/// 
		/// </param>
		/// <seealso cref="MQCoder">
		/// 
		/// </seealso>
		public StdEntropyCoder(CBlkQuantDataSrcEnc src, CBlkSizeSpec cblks, PrecinctSizeSpec pss, StringSpec bms, StringSpec mqrs, StringSpec rts, StringSpec css, StringSpec sss, StringSpec lcs, StringSpec tts):base(src)
		{
			this.cblks = cblks;
			this.pss = pss;
			this.bms = bms;
			this.mqrs = mqrs;
			this.rts = rts;
			this.css = css;
			this.sss = sss;
			this.lcs = lcs;
			this.tts = tts;
			int maxCBlkWidth, maxCBlkHeight;
			int i; // Counter
			int nt; // The number of threads
			int tsl; // Size for thread structures
			
			// Get the biggest width/height for the code-blocks
			maxCBlkWidth = cblks.MaxCBlkWidth;
			maxCBlkHeight = cblks.MaxCBlkHeight;
			
            nt = Environment.ProcessorCount;
            /*
			// Get the number of threads to use, or default to one
			try
			{
				//UPGRADE_ISSUE: Method 'java.lang.System.getProperty' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javalangSystem'"
				nt = System.Int32.Parse(System_Renamed.getProperty(THREADS_PROP_NAME, DEF_THREADS_NUM));
				if (nt < 0)
					throw new System.FormatException();
			}
			catch (System.FormatException e)
			{
				throw new System.ArgumentException("Invalid number of threads " + "for " + "entropy coding in property " + THREADS_PROP_NAME);
			}
			*/

			// 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			
			// If using multithreaded implementation get necessasry objects
			if (nt > 0)
			{
				FacilityManager.getMsgLogger().printmsg(CSJ2K.j2k.util.MsgLogger_Fields.INFO, "Using multithreaded entropy coder " + "with " + nt + " compressor threads.");
				tsl = nt;
				tPool = new ThreadPool(nt, (System.Int32) SupportClass.ThreadClass.Current().Priority + THREADS_PRIORITY_INC, "StdEntropyCoder");
				idleComps = new System.Collections.ArrayList();
				completedComps = new System.Collections.ArrayList[src.NumComps];
				nBusyComps = new int[src.NumComps];
				finishedTileComponent = new bool[src.NumComps];
				for (i = src.NumComps - 1; i >= 0; i--)
				{
					completedComps[i] = new System.Collections.ArrayList();
				}
				for (i = 0; i < nt; i++)
				{
					idleComps.Add(new StdEntropyCoder.Compressor(this, i));
				}
			}
			else
			{
				tsl = 1;
				tPool = null;
				idleComps = null;
				completedComps = null;
				nBusyComps = null;
				finishedTileComponent = null;
			}
			
			// Allocate data structures
			outT = new ByteOutputBuffer[tsl];
			mqT = new MQCoder[tsl];
			boutT = new BitToByteOutput[tsl];
			stateT = new int[tsl][];
			for (int i2 = 0; i2 < tsl; i2++)
			{
				stateT[i2] = new int[(maxCBlkWidth + 2) * ((maxCBlkHeight + 1) / 2 + 2)];
			}
			symbufT = new int[tsl][];
			for (int i3 = 0; i3 < tsl; i3++)
			{
				symbufT[i3] = new int[maxCBlkWidth * (CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT * 2 + 2)];
			}
			ctxtbufT = new int[tsl][];
			for (int i4 = 0; i4 < tsl; i4++)
			{
				ctxtbufT[i4] = new int[maxCBlkWidth * (CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT * 2 + 2)];
			}
			distbufT = new double[tsl][];
			for (int i5 = 0; i5 < tsl; i5++)
			{
				distbufT[i5] = new double[32 * CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_PASSES];
			}
			ratebufT = new int[tsl][];
			for (int i6 = 0; i6 < tsl; i6++)
			{
				ratebufT[i6] = new int[32 * CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_PASSES];
			}
			istermbufT = new bool[tsl][];
			for (int i7 = 0; i7 < tsl; i7++)
			{
				istermbufT[i7] = new bool[32 * CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_PASSES];
			}
			srcblkT = new CBlkWTData[tsl];
			for (i = 0; i < tsl; i++)
			{
				outT[i] = new ByteOutputBuffer();
				mqT[i] = new MQCoder(outT[i], NUM_CTXTS, MQ_INIT);
			}
			precinctPartition = new bool[src.NumComps][];
			for (int i8 = 0; i8 < src.NumComps; i8++)
			{
				precinctPartition[i8] = new bool[src.getNumTiles()];
			}
			
			// Create the subband description for each component and each tile
			//Subband sb = null;
			Coord numTiles = null;
			int nc = NumComps;
			numTiles = src.getNumTiles(numTiles);
			initTileComp(getNumTiles(), nc);
			
			for (int c = 0; c < nc; c++)
			{
				for (int tY = 0; tY < numTiles.y; tY++)
				{
					for (int tX = 0; tX < numTiles.x; tX++)
					{
						precinctPartition[c][tIdx] = false;
					}
				}
			}
		}