Beispiel #1
0
		/// <summary> Performs the cleanup pass on the specified data and bit-plane. It
		/// decodes all insignificant samples which have its "visited" state bit
		/// off, using the ZC, SC, and RLC primitives. It toggles the "visited"
		/// state bit to 0 (off) for all samples in the code-block.
		/// 
		/// <P>This method also checks for segmentation markers if those are
		/// present and returns true if an error is detected, or false
		/// otherwise. If an error is detected it measn that the bit stream
		/// contains some erroneous bit that have led to the decoding of incorrect
		/// data. This data affects the whole last decoded bit-plane
		/// (i.e. 'bp'). If 'true' is returned the 'conceal' method should be
		/// called and no more passes should be decoded for this code-block's bit
		/// stream.
		/// 
		/// </summary>
		/// <param name="cblk">The code-block data to code
		/// 
		/// </param>
		/// <param name="mq">The MQ-coder to use
		/// 
		/// </param>
		/// <param name="bp">The bit-plane to decode
		/// 
		/// </param>
		/// <param name="state">The state information for the code-block
		/// 
		/// </param>
		/// <param name="zc_lut">The ZC lookup table to use in ZC.
		/// 
		/// </param>
		/// <param name="isterm">If this pass has been terminated. If the pass has been
		/// terminated it can be used to check error resilience.
		/// 
		/// </param>
		/// <returns> True if an error was detected in the bit stream, false
		/// otherwise.
		/// 
		/// </returns>
		private bool cleanuppass(DataBlk cblk, MQDecoder mq, int bp, int[] state, int[] zc_lut, bool isterm)
		{
			int j, sj; // The state index for line and stripe
			int k, sk; // The data index for line and stripe
			int dscanw; // The data scan-width
			int sscanw; // The state scan-width
			int jstep; // Stripe to stripe step for 'sj'
			int kstep; // Stripe to stripe step for 'sk'
			int stopsk; // The loop limit on the variable sk
			int csj; // Local copy (i.e. cached) of 'state[j]'
			int setmask; // The mask to set current and lower bit-planes to 1/2
			// approximation
			int sym; // The decoded symbol
			int rlclen; // Length of RLC
			int ctxt; // The context to use
			int[] data; // The data buffer
			int s; // The stripe index
			bool causal; // Flag to indicate if stripe-causal context
			// formation is to be used
			int nstripes; // The number of stripes in the code-block
			int sheight; // Height of the current stripe
			int off_ul, off_ur, off_dr, off_dl; // offsets
			bool error; // The error condition
			
			// Initialize local variables
			dscanw = cblk.scanw;
			sscanw = cblk.w + 2;
			jstep = sscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT / 2 - cblk.w;
			kstep = dscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - cblk.w;
			setmask = (3 << bp) >> 1;
			data = (int[]) cblk.Data;
			nstripes = (cblk.h + CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - 1) / CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT;
			causal = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_VERT_STR_CAUSAL) != 0;
			
			// Pre-calculate offsets in 'state' for diagonal neighbors
			off_ul = - sscanw - 1; // up-left
			off_ur = - sscanw + 1; // up-right
			off_dr = sscanw + 1; // down-right
			off_dl = sscanw - 1; // down-left
			
			// Decode stripe by stripe
			sk = cblk.offset;
			sj = sscanw + 1;
			for (s = nstripes - 1; s >= 0; s--, sk += kstep, sj += jstep)
			{
				sheight = (s != 0)?CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT:cblk.h - (nstripes - 1) * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT;
				stopsk = sk + cblk.w;
				// Scan by set of 1 stripe column at a time
				for (; sk < stopsk; sk++, sj++)
				{
					// Start column
					j = sj;
					csj = state[j];
					{
						// Check for RLC: if all samples are not significant, not
						// visited and do not have a non-zero context, and column
						// is full height, we do RLC.
						if (csj == 0 && state[j + sscanw] == 0 && sheight == CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT)
						{
							if (mq.decodeSymbol(RLC_CTXT) != 0)
							{
								// run-length is significant, decode length
								rlclen = mq.decodeSymbol(UNIF_CTXT) << 1;
								rlclen |= mq.decodeSymbol(UNIF_CTXT);
								// Set 'k' and 'j' accordingly
								k = sk + rlclen * dscanw;
								if (rlclen > 1)
								{
									j += sscanw;
									csj = state[j];
								}
							}
							else
							{
								// RLC is insignificant
								// Goto next column
								continue;
							}
							// We just decoded the length of a significant RLC
							// and a sample became significant
							// Use sign coding
							if ((rlclen & 0x01) == 0)
							{
								// Sample that became significant is first row of
								// its column half
								ctxt = SC_LUT[(csj >> SC_SHIFT_R1) & SC_MASK];
								sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
								// Update the data
								data[k] = (sym << 31) | setmask;
								// Update state information (significant bit,
								// visited bit, neighbor significant bit of
								// neighbors, non zero context of neighbors, sign
								// of neighbors)
								if (rlclen != 0 || !causal)
								{
									// If in causal mode do not change
									// contexts of previous stripe.
									state[j + off_ul] |= STATE_NZ_CTXT_R2 | STATE_D_DR_R2;
									state[j + off_ur] |= STATE_NZ_CTXT_R2 | STATE_D_DL_R2;
								}
								// Update sign state information of neighbors
								if (sym != 0)
								{
									csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2 | STATE_V_U_SIGN_R2;
									if (rlclen != 0 || !causal)
									{
										// If in causal mode do not change
										// contexts of previous stripe.
										state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2 | STATE_V_D_SIGN_R2;
									}
									state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_H_L_SIGN_R1 | STATE_D_UL_R2;
									state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_H_R_SIGN_R1 | STATE_D_UR_R2;
								}
								else
								{
									csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2;
									if (rlclen != 0 || !causal)
									{
										// If in causal mode do not change
										// contexts of previous stripe.
										state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2;
									}
									state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_D_UL_R2;
									state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_D_UR_R2;
								}
								// Changes to csj are saved later
								if ((rlclen >> 1) != 0)
								{
									// Sample that became significant is in
									// bottom half of column => jump to bottom
									// half
									//UPGRADE_NOTE: Labeled break statement was changed to a goto statement. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1012'"
									goto top_half_brk;
								}
								// Otherwise sample that became significant is in
								// top half of column => continue on top half
							}
							else
							{
								// Sample that became significant is second row of
								// its column half
								ctxt = SC_LUT[(csj >> SC_SHIFT_R2) & SC_MASK];
								sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
								// Update the data
								data[k] = (sym << 31) | setmask;
								// Update state information (significant bit,
								// neighbor significant bit of neighbors, non zero
								// context of neighbors, sign of neighbors)
								state[j + off_dl] |= STATE_NZ_CTXT_R1 | STATE_D_UR_R1;
								state[j + off_dr] |= STATE_NZ_CTXT_R1 | STATE_D_UL_R1;
								// Update sign state information of neighbors
								if (sym != 0)
								{
									csj |= STATE_SIG_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1 | STATE_V_D_SIGN_R1;
									state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1 | STATE_V_U_SIGN_R1;
									state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2 | STATE_H_L_SIGN_R2;
									state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2 | STATE_H_R_SIGN_R2;
								}
								else
								{
									csj |= STATE_SIG_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1;
									state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1;
									state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2;
									state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2;
								}
								// Save changes to csj
								state[j] = csj;
								if ((rlclen >> 1) != 0)
								{
									// Sample that became significant is in bottom
									// half of column => we're done with this
									// column
									continue;
								}
								// Otherwise sample that became significant is in
								// top half of column => we're done with top
								// column
								j += sscanw;
								csj = state[j];
								//UPGRADE_NOTE: Labeled break statement was changed to a goto statement. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1012'"
								goto top_half_brk;
							}
						}
						// Do half top of column
						// If any of the two samples is not significant and has
						// not been visited in the current bit-plane we can not
						// skip them
						if ((((csj >> 1) | csj) & VSTD_MASK_R1R2) != VSTD_MASK_R1R2)
						{
							k = sk;
							// Scan first row
							if ((csj & (STATE_SIG_R1 | STATE_VISITED_R1)) == 0)
							{
								// Use zero coding
								if (mq.decodeSymbol(zc_lut[csj & ZC_MASK]) != 0)
								{
									// Became significant
									// Use sign coding
									ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R1)) & SC_MASK];
									sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
									// Update the data
									data[k] = (sym << 31) | setmask;
									// Update state information (significant bit,
									// visited bit, neighbor significant bit of
									// neighbors, non zero context of neighbors,
									// sign of neighbors)
									if (!causal)
									{
										// If in causal mode do not change
										// contexts of previous stripe.
										state[j + off_ul] |= STATE_NZ_CTXT_R2 | STATE_D_DR_R2;
										state[j + off_ur] |= STATE_NZ_CTXT_R2 | STATE_D_DL_R2;
									}
									// Update sign state information of neighbors
									if (sym != 0)
									{
										csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2 | STATE_V_U_SIGN_R2;
										if (!causal)
										{
											// If in causal mode do not change
											// contexts of previous stripe.
											state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2 | STATE_V_D_SIGN_R2;
										}
										state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_H_L_SIGN_R1 | STATE_D_UL_R2;
										state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_H_R_SIGN_R1 | STATE_D_UR_R2;
									}
									else
									{
										csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2;
										if (!causal)
										{
											// If in causal mode do not change
											// contexts of previous stripe.
											state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2;
										}
										state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_D_UL_R2;
										state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_D_UR_R2;
									}
								}
							}
							if (sheight < 2)
							{
								csj &= ~ (STATE_VISITED_R1 | STATE_VISITED_R2);
								state[j] = csj;
								continue;
							}
							// Scan second row
							if ((csj & (STATE_SIG_R2 | STATE_VISITED_R2)) == 0)
							{
								k += dscanw;
								// Use zero coding
								if (mq.decodeSymbol(zc_lut[(SupportClass.URShift(csj, STATE_SEP)) & ZC_MASK]) != 0)
								{
									// Became significant
									// Use sign coding
									ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R2)) & SC_MASK];
									sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
									// Update the data
									data[k] = (sym << 31) | setmask;
									// Update state information (significant bit,
									// visited bit, neighbor significant bit of
									// neighbors, non zero context of neighbors,
									// sign of neighbors)
									state[j + off_dl] |= STATE_NZ_CTXT_R1 | STATE_D_UR_R1;
									state[j + off_dr] |= STATE_NZ_CTXT_R1 | STATE_D_UL_R1;
									// Update sign state information of neighbors
									if (sym != 0)
									{
										csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1 | STATE_V_D_SIGN_R1;
										state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1 | STATE_V_U_SIGN_R1;
										state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2 | STATE_H_L_SIGN_R2;
										state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2 | STATE_H_R_SIGN_R2;
									}
									else
									{
										csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1;
										state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1;
										state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2;
										state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2;
									}
								}
							}
						}
						csj &= ~ (STATE_VISITED_R1 | STATE_VISITED_R2);
						state[j] = csj;
						// Do half bottom of column
						if (sheight < 3)
							continue;
						j += sscanw;
						csj = state[j];
					}
					//UPGRADE_NOTE: Label 'top_half_brk' was added. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1011'"

top_half_brk: ;
					 // end of 'top_half' block
					// If any of the two samples is not significant and has
					// not been visited in the current bit-plane we can not
					// skip them
					if ((((csj >> 1) | csj) & VSTD_MASK_R1R2) != VSTD_MASK_R1R2)
					{
						k = sk + (dscanw << 1);
						// Scan first row
						if ((csj & (STATE_SIG_R1 | STATE_VISITED_R1)) == 0)
						{
							// Use zero coding
							if (mq.decodeSymbol(zc_lut[csj & ZC_MASK]) != 0)
							{
								// Became significant
								// Use sign coding
								ctxt = SC_LUT[(csj >> SC_SHIFT_R1) & SC_MASK];
								sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
								// Update the data
								data[k] = (sym << 31) | setmask;
								// Update state information (significant bit,
								// visited bit, neighbor significant bit of
								// neighbors, non zero context of neighbors,
								// sign of neighbors)
								state[j + off_ul] |= STATE_NZ_CTXT_R2 | STATE_D_DR_R2;
								state[j + off_ur] |= STATE_NZ_CTXT_R2 | STATE_D_DL_R2;
								// Update sign state information of neighbors
								if (sym != 0)
								{
									csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2 | STATE_V_U_SIGN_R2;
									state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2 | STATE_V_D_SIGN_R2;
									state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_H_L_SIGN_R1 | STATE_D_UL_R2;
									state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_H_R_SIGN_R1 | STATE_D_UR_R2;
								}
								else
								{
									csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2;
									state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2;
									state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_D_UL_R2;
									state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_D_UR_R2;
								}
							}
						}
						if (sheight < 4)
						{
							csj &= ~ (STATE_VISITED_R1 | STATE_VISITED_R2);
							state[j] = csj;
							continue;
						}
						// Scan second row
						if ((csj & (STATE_SIG_R2 | STATE_VISITED_R2)) == 0)
						{
							k += dscanw;
							// Use zero coding
							if (mq.decodeSymbol(zc_lut[(SupportClass.URShift(csj, STATE_SEP)) & ZC_MASK]) != 0)
							{
								// Became significant
								// Use sign coding
								ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R2)) & SC_MASK];
								sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
								// Update the data
								data[k] = (sym << 31) | setmask;
								// Update state information (significant bit,
								// visited bit, neighbor significant bit of
								// neighbors, non zero context of neighbors,
								// sign of neighbors)
								state[j + off_dl] |= STATE_NZ_CTXT_R1 | STATE_D_UR_R1;
								state[j + off_dr] |= STATE_NZ_CTXT_R1 | STATE_D_UL_R1;
								// Update sign state information of neighbors
								if (sym != 0)
								{
									csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1 | STATE_V_D_SIGN_R1;
									state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1 | STATE_V_U_SIGN_R1;
									state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2 | STATE_H_L_SIGN_R2;
									state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2 | STATE_H_R_SIGN_R2;
								}
								else
								{
									csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1;
									state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1;
									state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2;
									state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2;
								}
							}
						}
					}
					csj &= ~ (STATE_VISITED_R1 | STATE_VISITED_R2);
					state[j] = csj;
				}
			}
			
			// Decode segment symbol if we need to
			if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_SEG_SYMBOLS) != 0)
			{
				sym = mq.decodeSymbol(UNIF_CTXT) << 3;
				sym |= mq.decodeSymbol(UNIF_CTXT) << 2;
				sym |= mq.decodeSymbol(UNIF_CTXT) << 1;
				sym |= mq.decodeSymbol(UNIF_CTXT);
				// Set error condition accordingly
				error = sym != SEG_SYMBOL;
			}
			else
			{
				// We can not detect any errors
				error = false;
			}
			
			// Check the error resilience termination
			if (isterm && (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_PRED_TERM) != 0)
			{
				error = mq.checkPredTerm();
			}
			
			// Reset the MQ context states if we need to
			if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_RESET_MQ) != 0)
			{
				mq.resetCtxts();
			}
			
			// Return error condition
			return error;
		}
Beispiel #2
0
		/// <summary> Performs the significance propagation pass on the specified data and
		/// bit-plane. It decodes all insignificant samples which have, at least,
		/// one of its immediate eight neighbors already significant, using the ZC
		/// and SC primitives as needed. It toggles the "visited" state bit to 1
		/// for all those samples.
		/// 
		/// <p>This method also checks for segmentation markers if those are
		/// present and returns true if an error is detected, or false
		/// otherwise. If an error is detected it means that the bit stream
		/// contains some erroneous bit that have led to the decoding of incorrect
		/// data. This data affects the whole last decoded bit-plane
		/// (i.e. 'bp'). If 'true' is returned the 'conceal' method should be
		/// called and no more passes should be decoded for this code-block's bit
		/// stream.</p>
		/// 
		/// </summary>
		/// <param name="cblk">The code-block data to decode
		/// 
		/// </param>
		/// <param name="mq">The MQ-coder to use
		/// 
		/// </param>
		/// <param name="bp">The bit-plane to decode
		/// 
		/// </param>
		/// <param name="state">The state information for the code-block
		/// 
		/// </param>
		/// <param name="zc_lut">The ZC lookup table to use in ZC.
		/// 
		/// </param>
		/// <param name="isterm">If this pass has been terminated. If the pass has been
		/// terminated it can be used to check error resilience.
		/// 
		/// </param>
		/// <returns> True if an error was detected in the bit stream, false
		/// otherwise.
		/// 
		/// </returns>
		private bool sigProgPass(DataBlk cblk, MQDecoder mq, int bp, int[] state, int[] zc_lut, bool isterm)
		{
			int j, sj; // The state index for line and stripe
			int k, sk; // The data index for line and stripe
			int dscanw; // The data scan-width
			int sscanw; // The state scan-width
			int jstep; // Stripe to stripe step for 'sj'
			int kstep; // Stripe to stripe step for 'sk'
			int stopsk; // The loop limit on the variable sk
			int csj; // Local copy (i.e. cached) of 'state[j]'
			int setmask; // The mask to set current and lower bit-planes to 1/2
			// approximation
			int sym; // The symbol to code
			int ctxt; // The context to use
			int[] data; // The data buffer
			int s; // The stripe index
			bool causal; // Flag to indicate if stripe-causal context
			// formation is to be used
			int nstripes; // The number of stripes in the code-block
			int sheight; // Height of the current stripe
			int off_ul, off_ur, off_dr, off_dl; // offsets
			bool error; // The error condition
			
			// Initialize local variables
			dscanw = cblk.scanw;
			sscanw = cblk.w + 2;
			jstep = sscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT / 2 - cblk.w;
			kstep = dscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - cblk.w;
			setmask = (3 << bp) >> 1;
			data = (int[]) cblk.Data;
			nstripes = (cblk.h + CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - 1) / CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT;
			causal = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_VERT_STR_CAUSAL) != 0;
			
			// Pre-calculate offsets in 'state' for diagonal neighbors
			off_ul = - sscanw - 1; // up-left
			off_ur = - sscanw + 1; // up-right
			off_dr = sscanw + 1; // down-right
			off_dl = sscanw - 1; // down-left
			
			// Decode stripe by stripe
			sk = cblk.offset;
			sj = sscanw + 1;
			for (s = nstripes - 1; s >= 0; s--, sk += kstep, sj += jstep)
			{
				sheight = (s != 0)?CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT:cblk.h - (nstripes - 1) * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT;
				stopsk = sk + cblk.w;
				// Scan by set of 1 stripe column at a time
				for (; sk < stopsk; sk++, sj++)
				{
					// Do half top of column
					j = sj;
					csj = state[j];
					// If any of the two samples is not significant and has a
					// non-zero context (i.e. some neighbor is significant) we can 
					// not skip them
					if ((((~ csj) & (csj << 2)) & SIG_MASK_R1R2) != 0)
					{
						k = sk;
						// Scan first row
						if ((csj & (STATE_SIG_R1 | STATE_NZ_CTXT_R1)) == STATE_NZ_CTXT_R1)
						{
							// Use zero coding
							if (mq.decodeSymbol(zc_lut[csj & ZC_MASK]) != 0)
							{
								// Became significant
								// Use sign coding
								ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R1)) & SC_MASK];
								sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
								// Update data
								data[k] = (sym << 31) | setmask;
								// Update state information (significant bit,
								// visited bit, neighbor significant bit of
								// neighbors, non zero context of neighbors, sign
								// of neighbors)
								if (!causal)
								{
									// If in causal mode do not change contexts of 
									// previous stripe.
									state[j + off_ul] |= STATE_NZ_CTXT_R2 | STATE_D_DR_R2;
									state[j + off_ur] |= STATE_NZ_CTXT_R2 | STATE_D_DL_R2;
								}
								// Update sign state information of neighbors
								if (sym != 0)
								{
									csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2 | STATE_V_U_SIGN_R2;
									if (!causal)
									{
										// If in causal mode do not change
										// contexts of previous stripe.
										state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2 | STATE_V_D_SIGN_R2;
									}
									state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_H_L_SIGN_R1 | STATE_D_UL_R2;
									state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_H_R_SIGN_R1 | STATE_D_UR_R2;
								}
								else
								{
									csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2;
									if (!causal)
									{
										// If in causal mode do not change
										// contexts of previous stripe.
										state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2;
									}
									state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_D_UL_R2;
									state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_D_UR_R2;
								}
							}
							else
							{
								csj |= STATE_VISITED_R1;
							}
						}
						if (sheight < 2)
						{
							state[j] = csj;
							continue;
						}
						// Scan second row
						if ((csj & (STATE_SIG_R2 | STATE_NZ_CTXT_R2)) == STATE_NZ_CTXT_R2)
						{
							k += dscanw;
							// Use zero coding
							if (mq.decodeSymbol(zc_lut[(SupportClass.URShift(csj, STATE_SEP)) & ZC_MASK]) != 0)
							{
								// Became significant
								// Use sign coding
								ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R2)) & SC_MASK];
								sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
								// Update data
								data[k] = (sym << 31) | setmask;
								// Update state information (significant bit,
								// visited bit, neighbor significant bit of
								// neighbors, non zero context of neighbors, sign
								// of neighbors)
								state[j + off_dl] |= STATE_NZ_CTXT_R1 | STATE_D_UR_R1;
								state[j + off_dr] |= STATE_NZ_CTXT_R1 | STATE_D_UL_R1;
								// Update sign state information of neighbors
								if (sym != 0)
								{
									csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1 | STATE_V_D_SIGN_R1;
									state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1 | STATE_V_U_SIGN_R1;
									state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2 | STATE_H_L_SIGN_R2;
									state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2 | STATE_H_R_SIGN_R2;
								}
								else
								{
									csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1;
									state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1;
									state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2;
									state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2;
								}
							}
							else
							{
								csj |= STATE_VISITED_R2;
							}
						}
						state[j] = csj;
					}
					// Do half bottom of column
					if (sheight < 3)
						continue;
					j += sscanw;
					csj = state[j];
					// If any of the two samples is not significant and has a
					// non-zero context (i.e. some neighbor is significant) we can 
					// not skip them
					if ((((~ csj) & (csj << 2)) & SIG_MASK_R1R2) != 0)
					{
						k = sk + (dscanw << 1);
						// Scan first row
						if ((csj & (STATE_SIG_R1 | STATE_NZ_CTXT_R1)) == STATE_NZ_CTXT_R1)
						{
							// Use zero coding
							if (mq.decodeSymbol(zc_lut[csj & ZC_MASK]) != 0)
							{
								// Became significant
								// Use sign coding
								ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R1)) & SC_MASK];
								sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
								// Update data
								data[k] = (sym << 31) | setmask;
								// Update state information (significant bit,
								// visited bit, neighbor significant bit of
								// neighbors, non zero context of neighbors, sign
								// of neighbors)
								state[j + off_ul] |= STATE_NZ_CTXT_R2 | STATE_D_DR_R2;
								state[j + off_ur] |= STATE_NZ_CTXT_R2 | STATE_D_DL_R2;
								// Update sign state information of neighbors
								if (sym != 0)
								{
									csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2 | STATE_V_U_SIGN_R2;
									state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2 | STATE_V_D_SIGN_R2;
									state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_H_L_SIGN_R1 | STATE_D_UL_R2;
									state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_H_R_SIGN_R1 | STATE_D_UR_R2;
								}
								else
								{
									csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2;
									state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2;
									state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_D_UL_R2;
									state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_D_UR_R2;
								}
							}
							else
							{
								csj |= STATE_VISITED_R1;
							}
						}
						if (sheight < 4)
						{
							state[j] = csj;
							continue;
						}
						// Scan second row
						if ((csj & (STATE_SIG_R2 | STATE_NZ_CTXT_R2)) == STATE_NZ_CTXT_R2)
						{
							k += dscanw;
							// Use zero coding
							if (mq.decodeSymbol(zc_lut[(SupportClass.URShift(csj, STATE_SEP)) & ZC_MASK]) != 0)
							{
								// Became significant
								// Use sign coding
								ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R2)) & SC_MASK];
								sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT));
								// Update data
								data[k] = (sym << 31) | setmask;
								// Update state information (significant bit,
								// visited bit, neighbor significant bit of
								// neighbors, non zero context of neighbors, sign
								// of neighbors)
								state[j + off_dl] |= STATE_NZ_CTXT_R1 | STATE_D_UR_R1;
								state[j + off_dr] |= STATE_NZ_CTXT_R1 | STATE_D_UL_R1;
								// Update sign state information of neighbors
								if (sym != 0)
								{
									csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1 | STATE_V_D_SIGN_R1;
									state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1 | STATE_V_U_SIGN_R1;
									state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2 | STATE_H_L_SIGN_R2;
									state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2 | STATE_H_R_SIGN_R2;
								}
								else
								{
									csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1;
									state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1;
									state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2;
									state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2;
								}
							}
							else
							{
								csj |= STATE_VISITED_R2;
							}
						}
						state[j] = csj;
					}
				}
			}
			
			error = false;
			
			// Check the error resilience termination
			if (isterm && (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_PRED_TERM) != 0)
			{
				error = mq.checkPredTerm();
			}
			
			// Reset the MQ context states if we need to
			if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_RESET_MQ) != 0)
			{
				mq.resetCtxts();
			}
			
			// Return error condition
			return error;
		}
Beispiel #3
0
		/// <summary> Performs the magnitude refinement pass on the specified data and
		/// bit-plane. It decodes the samples which are significant and which do not
		/// have the "visited" state bit turned on, using the MR primitive. The
		/// "visited" state bit is not mofified for any samples.
		/// 
		/// <P>This method also checks for segmentation markers if those are
		/// present and returns true if an error is detected, or false
		/// otherwise. If an error is detected it means that the bit stream contains
		/// some erroneous bit that have led to the decoding of incorrect
		/// data. This data affects the whole last decoded bit-plane (i.e. 'bp'). If
		/// 'true' is returned the 'conceal' method should be called and no more
		/// passes should be decoded for this code-block's bit stream.
		/// 
		/// </summary>
		/// <param name="cblk">The code-block data to decode
		/// 
		/// </param>
		/// <param name="mq">The MQ-decoder to use
		/// 
		/// </param>
		/// <param name="bp">The bit-plane to decode
		/// 
		/// </param>
		/// <param name="state">The state information for the code-block
		/// 
		/// </param>
		/// <param name="isterm">If this pass has been terminated. If the pass has been
		/// terminated it can be used to check error resilience.
		/// 
		/// </param>
		/// <returns> True if an error was detected in the bit stream, false
		/// otherwise.
		/// 
		/// </returns>
		private bool magRefPass(DataBlk cblk, MQDecoder mq, int bp, int[] state, bool isterm)
		{
			int j, sj; // The state index for line and stripe
			int k, sk; // The data index for line and stripe
			int dscanw; // The data scan-width
			int sscanw; // The state scan-width
			int jstep; // Stripe to stripe step for 'sj'
			int kstep; // Stripe to stripe step for 'sk'
			int stopsk; // The loop limit on the variable sk
			int csj; // Local copy (i.e. cached) of 'state[j]'
			int setmask; // The mask to set lower bit-planes to 1/2 approximation
			int resetmask; // The mask to reset approximation bit-planes
			int sym; // The symbol to decode
			int[] data; // The data buffer
			int s; // The stripe index
			int nstripes; // The number of stripes in the code-block
			int sheight; // Height of the current stripe
			bool error; // The error condition
			
			// Initialize local variables
			dscanw = cblk.scanw;
			sscanw = cblk.w + 2;
			jstep = sscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT / 2 - cblk.w;
			kstep = dscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - cblk.w;
			setmask = (1 << bp) >> 1;
			resetmask = (- 1) << (bp + 1);
			data = (int[]) cblk.Data;
			nstripes = (cblk.h + CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - 1) / CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT;
			
			// Decode stripe by stripe
			sk = cblk.offset;
			sj = sscanw + 1;
			for (s = nstripes - 1; s >= 0; s--, sk += kstep, sj += jstep)
			{
				sheight = (s != 0)?CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT:cblk.h - (nstripes - 1) * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT;
				stopsk = sk + cblk.w;
				// Scan by set of 1 stripe column at a time
				for (; sk < stopsk; sk++, sj++)
				{
					// Do half top of column
					j = sj;
					csj = state[j];
					// If any of the two samples is significant and not yet
					// visited in the current bit-plane we can not skip them
					if ((((SupportClass.URShift(csj, 1)) & (~ csj)) & VSTD_MASK_R1R2) != 0)
					{
						k = sk;
						// Scan first row
						if ((csj & (STATE_SIG_R1 | STATE_VISITED_R1)) == STATE_SIG_R1)
						{
							// Use MR primitive
							sym = mq.decodeSymbol(MR_LUT[csj & MR_MASK]);
							// Update the data
							data[k] &= resetmask;
							data[k] |= (sym << bp) | setmask;
							// Update the STATE_PREV_MR bit
							csj |= STATE_PREV_MR_R1;
						}
						if (sheight < 2)
						{
							state[j] = csj;
							continue;
						}
						// Scan second row
						if ((csj & (STATE_SIG_R2 | STATE_VISITED_R2)) == STATE_SIG_R2)
						{
							k += dscanw;
							// Use MR primitive
							sym = mq.decodeSymbol(MR_LUT[(SupportClass.URShift(csj, STATE_SEP)) & MR_MASK]);
							// Update the data
							data[k] &= resetmask;
							data[k] |= (sym << bp) | setmask;
							// Update the STATE_PREV_MR bit
							csj |= STATE_PREV_MR_R2;
						}
						state[j] = csj;
					}
					// Do half bottom of column
					if (sheight < 3)
						continue;
					j += sscanw;
					csj = state[j];
					// If any of the two samples is significant and not yet
					// visited in the current bit-plane we can not skip them
					if ((((SupportClass.URShift(csj, 1)) & (~ csj)) & VSTD_MASK_R1R2) != 0)
					{
						k = sk + (dscanw << 1);
						// Scan first row
						if ((csj & (STATE_SIG_R1 | STATE_VISITED_R1)) == STATE_SIG_R1)
						{
							// Use MR primitive
							sym = mq.decodeSymbol(MR_LUT[csj & MR_MASK]);
							// Update the data
							data[k] &= resetmask;
							data[k] |= (sym << bp) | setmask;
							// Update the STATE_PREV_MR bit
							csj |= STATE_PREV_MR_R1;
						}
						if (sheight < 4)
						{
							state[j] = csj;
							continue;
						}
						// Scan second row
						if ((state[j] & (STATE_SIG_R2 | STATE_VISITED_R2)) == STATE_SIG_R2)
						{
							k += dscanw;
							// Use MR primitive
							sym = mq.decodeSymbol(MR_LUT[(SupportClass.URShift(csj, STATE_SEP)) & MR_MASK]);
							// Update the data
							data[k] &= resetmask;
							data[k] |= (sym << bp) | setmask;
							// Update the STATE_PREV_MR bit
							csj |= STATE_PREV_MR_R2;
						}
						state[j] = csj;
					}
				}
			}
			
			error = false;
			
			// Check the error resilient termination
			if (isterm && (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_PRED_TERM) != 0)
			{
				error = mq.checkPredTerm();
			}
			
			// Reset the MQ context states if we need to
			if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_RESET_MQ) != 0)
			{
				mq.resetCtxts();
			}
			
			// Return error condition
			return error;
		}