CSJ2K.j2k.entropy.encoder.MQCoder.codeSymbols C# (CSharp) Method

codeSymbols() public method

This function performs the arithmetic encoding of several symbols together. The function receives an array of symbols that are to be encoded and an array containing the contexts with which to encode them.

The advantage of using this function is that the cost of the method call is amortized by the number of coded symbols per method call.

Each context has a current MPS and an index describing what the current probability is for the LPS. Each bit is encoded and if the probability of the LPS exceeds .5, the MPS and LPS are switched.

public codeSymbols ( int bits, int cX, int n ) : void
bits int An array containing the symbols to be encoded. Valid /// symbols are 0 and 1. /// ///
cX int The context for each of the symbols to be encoded. /// ///
n int The number of symbols to encode. /// ///
return void
        public void codeSymbols(int[] bits, int[] cX, int n)
        {
            int q;
            int li; // local cache of I[context]
            int la;
            int nc;
            int ctxt; // context of current symbol
            int i; // counter

            // NOTE: here we could use symbol aggregation to speed things up.
            // It remains to be studied.

            la = a; // cache A register in local variable
            for (i = 0; i < n; i++)
            {
                // NOTE: (a<0x8000) is equivalent to ((a&0x8000)==0)
                // since 'a' is always less than or equal to 0xFFFF

                // NOTE: conditional exchange guarantees that A for MPS is
                // always greater than 0x4000 (i.e. 0.375)
                // => one renormalization shift is enough for MPS
                // => no need to do a renormalization while loop for MPS

                ctxt = cX[i];
                li = I[ctxt];
                q = qe[li]; // Retrieve current LPS prob.

                if (bits[i] == mPS[ctxt])
                {
                    // -- Code MPS

                    la -= q; // Interval division associated with MPS coding

                    if (la >= 0x8000)
                    {
                        // Interval big enough
                        c += q;
                    }
                    else
                    {
                        // Interval too short
                        if (la < q)
                        {
                            // Probabilities are inverted
                            la = q;
                        }
                        else
                        {
                            c += q;
                        }

                        I[ctxt] = nMPS[li];

                        // -- Renormalization (MPS: no need for while loop)
                        la <<= 1; // a is doubled
                        c <<= 1; // c is doubled
                        cT--;
                        if (cT == 0)
                        {
                            byteOut();
                        }
                        // -- End of renormalization
                    }
                }
                else
                {
                    // -- Code LPS
                    la -= q; // Interval division according to LPS coding

                    if (la < q)
                    {
                        c += q;
                    }
                    else
                    {
                        la = q;
                    }
                    if (switchLM[li] != 0)
                    {
                        mPS[ctxt] = 1 - mPS[ctxt];
                    }
                    I[ctxt] = nLPS[li];

                    // -- Renormalization

                    // sligthly better than normal loop
                    nc = 0;
                    do
                    {
                        la <<= 1;
                        nc++; // count number of necessary shifts
                    }
                    while (la < 0x8000);
                    if (cT > nc)
                    {
                        c <<= nc;
                        cT -= nc;
                    }
                    else
                    {
                        do
                        {
                            c <<= cT;
                            nc -= cT;
                            // cT = 0; // not necessary
                            byteOut();
                        }
                        while (cT <= nc);
                        c <<= nc;
                        cT -= nc;
                    }

                    // -- End of renormalization
                }
            }
            a = la; // save cached A register
        }

Usage Example

Example #1
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;
		}
All Usage Examples Of CSJ2K.j2k.entropy.encoder.MQCoder::codeSymbols