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

finishLengthCalculation() public method

Terminates the calculation of the required length for each coding pass. This method must be called just after the 'terminate()' one has been called for each terminated MQ segment.

The values in 'rates' must have been compensated for any offset due to previous terminated segments, so that the correct index to the stored coded data is used.

public finishLengthCalculation ( int rates, int n ) : void
rates int The array containing the values returned by /// 'getNumCodedBytes()' for each coding pass. /// ///
n int The index in the 'rates' array of the last terminated length. /// ///
return void
        public virtual void finishLengthCalculation(int[] rates, int n)
        {
            if (ltype != LENGTH_NEAR_OPT)
            {
                // For the simple calculations the only thing we need to do is to
                // ensure that the calculated lengths are no greater than the
                // terminated one
                if (n > 0 && rates[n - 1] > rates[n])
                {
                    // We need correction
                    int tl = rates[n]; // The terminated length
                    n--;
                    do
                    {
                        rates[n--] = tl;
                    }
                    while (n >= 0 && rates[n] > tl);
                }
            }
            else
            {
                // We need to perform the more sophisticated near optimal
                // calculation.

                // The calculation of the length is based on the fact that the
                // decoder will pad the codestream with an endless string of
                // (binary) 1s after termination. If the codestream, padded with
                // 1s, is within the bounds of the current interval then correct
                // decoding is guaranteed. The lower inclusive bound of the
                // current interval is the value of C (i.e. if only lower
                // intervals would be coded in the future). The upper exclusive
                // bound of the current interval is C+A (i.e. if only upper
                // intervals would be coded in the future). We therefore calculate
                // the minimum length that would be needed so that padding with 1s
                // gives a codestream within the interval.

                // In order to know what will be appended to the current base of
                // the interval we need to know what is in the MQ bit stream after
                // the current last output byte until the termination. This is why
                // this calculation has to be performed after the MQ segment has
                // been entirely coded and terminated.

                int cLow; // lower bound on the C register for correct decoding
                int cUp; // upper bound on the C register for correct decoding
                int bLow; // lower bound on the byte buffer for correct decoding
                int bUp; // upper bound on the byte buffer for correct decoding
                int ridx; // index in the rates array of the pass we are
                // calculating
                int sidx; // index in the saved state array
                int clen; // current calculated length
                bool cdFF; // the current delayed FF state
                int nb; // the next byte of output
                int minlen; // minimum possible length
                int maxlen; // maximum possible length

                // Start on the first pass of this segment
                ridx = n - nSaved;
                // Minimum allowable length is length of previous termination
                minlen = (ridx - 1 >= 0)?rates[ridx - 1]:0;
                // Maximum possible length is the terminated length
                maxlen = rates[n];
                for (sidx = 0; ridx < n; ridx++, sidx++)
                {
                    // Load the initial values of the bounds
                    cLow = savedC[sidx];
                    cUp = savedC[sidx] + savedA[sidx];
                    bLow = savedB[sidx];
                    bUp = savedB[sidx];
                    // Normalize to cT=0 and propagate and reset any carry bits
                    cLow <<= savedCT[sidx];
                    if ((cLow & 0x8000000) != 0)
                    {
                        bLow++;
                        cLow &= 0x7FFFFFF;
                    }
                    cUp <<= savedCT[sidx];
                    if ((cUp & 0x8000000) != 0)
                    {
                        bUp++;
                        cUp &= 0x7FFFFFF;
                    }
                    // Initialize current calculated length
                    cdFF = savedDelFF[sidx];
                    // rates[ridx] contains the number of bytes already output
                    // when the state was saved, compensated for the offset in the
                    // output stream.
                    clen = rates[ridx] + (cdFF?1:0);
                    while (true)
                    {
                        // If we are at end of coded data then this is the length
                        if (clen >= maxlen)
                        {
                            clen = maxlen;
                            break;
                        }
                        // Check for sufficiency of coded data
                        if (cdFF)
                        {
                            if (bLow < 128 && bUp >= 128)
                            {
                                // We are done for this pass
                                clen--; // Don't need delayed FF
                                break;
                            }
                        }
                        else
                        {
                            if (bLow < 256 && bUp >= 256)
                            {
                                // We are done for this pass
                                break;
                            }
                        }
                        // Update bounds with next byte of coded data and
                        // normalize to cT = 0 again.
                        nb = (clen >= minlen)?out_Renamed.getByte(clen):0;
                        bLow -= nb;
                        bUp -= nb;
                        clen++;
                        if (nb == 0xFF)
                        {
                            bLow <<= 7;
                            bLow |= (cLow >> 20) & 0x7F;
                            cLow &= 0xFFFFF;
                            cLow <<= 7;
                            bUp <<= 7;
                            bUp |= (cUp >> 20) & 0x7F;
                            cUp &= 0xFFFFF;
                            cUp <<= 7;
                            cdFF = true;
                        }
                        else
                        {
                            bLow <<= 8;
                            bLow |= (cLow >> 19) & 0xFF;
                            cLow &= 0x7FFFF;
                            cLow <<= 8;
                            bUp <<= 8;
                            bUp |= (cUp >> 19) & 0xFF;
                            cUp &= 0x7FFFF;
                            cUp <<= 8;
                            cdFF = false;
                        }
                        // Test again
                    }
                    // Store the rate found
                    rates[ridx] = (clen >= minlen)?clen:minlen;
                }
                // Reset the saved states
                nSaved = 0;
            }
        }

Usage Example

Beispiel #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::finishLengthCalculation