CSJ2K.j2k.entropy.encoder.StdEntropyCoder.sigProgPass C# (CSharp) Method

sigProgPass() static private method

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.
static private sigProgPass ( CSJ2K.j2k.wavelet.analysis.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
srcblk CSJ2K.j2k.wavelet.analysis.CBlkWTData The code-block data to code /// ///
mq MQCoder The MQ-coder to use /// ///
doterm bool If true it performs an MQ-coder termination after the end /// of the pass /// ///
bp int The bit-plane to code /// ///
state int The state information for the code-block /// ///
fs int The distortion estimation lookup table for SC /// ///
zc_lut int The ZC lookup table to use in ZC. /// ///
symbuf int The buffer to hold symbols to send to the MQ coder /// ///
ctxtbuf int A buffer to hold the contexts to use in sending the /// buffered symbols to the MQ coder. /// ///
ratebuf int The buffer where to store the rate (i.e. coded lenth) at /// the end of this coding pass. /// ///
pidx int The coding pass index. Is the index in the 'ratebuf' array /// where to store the coded length after this coding pass. /// ///
ltpidx int The index of the last pass that was terminated, or /// negative if none. /// ///
options int The bitmask of entropy coding options to apply to the /// code-block /// ///
return int
		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;
		}