Exemple #1
0
        /// <summary> Instantiates a new MQ-decoder, with the specified number of contexts
        /// and initial states. The compressed bytestream is read from the
        /// 'iStream' object.
        ///
        /// </summary>
        /// <param name="iStream">the stream that contains the coded bits
        ///
        /// </param>
        /// <param name="nrOfContexts">The number of contexts used
        ///
        /// </param>
        /// <param name="initStates">The initial state for each context. A reference is
        /// kept to this array to reinitialize the contexts whenever 'reset()' or
        /// 'resetCtxts()' is called.
        ///
        /// </param>
        public MQDecoder(ByteInputBuffer iStream, int nrOfContexts, int[] initStates)
        {
            in_Renamed = iStream;

            // Default initialization of the statistics bins is MPS=0 and
            // I=0
            I   = new int[nrOfContexts];
            mPS = new int[nrOfContexts];
            // Save the initial states
            this.initStates = initStates;

            // Initialize
            init();

            // Set the contexts
            resetCtxts();
        }
		/// <summary> Instantiates a new 'ByteToBitInput' object that uses 'in' as the
		/// underlying byte based input.
		/// 
		/// </summary>
		/// <param name="in">The underlying byte based input.
		/// 
		/// </param>
		public ByteToBitInput(ByteInputBuffer in_Renamed)
		{
			this.in_Renamed = in_Renamed;
		}
Exemple #3
0
		/// <summary> Instantiates a new MQ-decoder, with the specified number of contexts
		/// and initial states. The compressed bytestream is read from the
		/// 'iStream' object.
		/// 
		/// </summary>
		/// <param name="iStream">the stream that contains the coded bits 
		/// 
		/// </param>
		/// <param name="nrOfContexts">The number of contexts used
		/// 
		/// </param>
		/// <param name="initStates">The initial state for each context. A reference is
		/// kept to this array to reinitialize the contexts whenever 'reset()' or
		/// 'resetCtxts()' is called.
		/// 
		/// </param>
		public MQDecoder(ByteInputBuffer iStream, int nrOfContexts, int[] initStates)
		{
			in_Renamed = iStream;
			
			// Default initialization of the statistics bins is MPS=0 and
			// I=0
			I = new int[nrOfContexts];
			mPS = new int[nrOfContexts];
			// Save the initial states
			this.initStates = initStates;
			
			// Initialize
			init();
			
			// Set the contexts
			resetCtxts();
		}
		/// <summary> Returns the specified code-block in the current tile for the specified
		/// component, as a copy (see below).
		/// 
		/// <P>The returned code-block may be progressive, which is indicated by
		/// the 'progressive' variable of the returned 'DataBlk' object. If a
		/// code-block is progressive it means that in a later request to this
		/// method for the same code-block it is possible to retrieve data which is
		/// a better approximation, since meanwhile more data to decode for the
		/// code-block could have been received. If the code-block is not
		/// progressive then later calls to this method for the same code-block
		/// will return the exact same data values.
		/// 
		/// <P>The data returned by this method is always a copy of the internal
		/// data of this object, if any, and it can be modified "in place" without
		/// any problems after being returned. The 'offset' of the returned data is
		/// 0, and the 'scanw' is the same as the code-block width. See the
		/// 'DataBlk' class.
		/// 
		/// <P>The 'ulx' and 'uly' members of the returned 'DataBlk' object
		/// contain the coordinates of the top-left corner of the block, with
		/// respect to the tile, not the subband.
		/// 
		/// </summary>
		/// <param name="c">The component for which to return the next code-block.
		/// 
		/// </param>
		/// <param name="m">The vertical index of the code-block to return, in the
		/// specified subband.
		/// 
		/// </param>
		/// <param name="n">The horizontal index of the code-block to return, in the
		/// specified subband.
		/// 
		/// </param>
		/// <param name="sb">The subband in which the code-block to return is.
		/// 
		/// </param>
		/// <param name="cblk">If non-null this object will be used to return the new
		/// code-block. If null a new one will be allocated and returned. If the
		/// "data" array of the object is non-null it will be reused, if possible,
		/// to return the data.
		/// 
		/// </param>
		/// <returns> The next code-block in the current tile for component 'n', or
		/// null if all code-blocks for the current tile have been returned.
		/// 
		/// </returns>
		/// <seealso cref="DataBlk">
		/// 
		/// </seealso>
		public override DataBlk getCodeBlock(int c, int m, int n, SubbandSyn sb, DataBlk cblk)
		{
			//long stime = 0L; // Start time for timed sections
			int[] zc_lut; // The ZC lookup table to use
			int[] out_data; // The outupt data buffer
			int npasses; // The number of coding passes to perform
			int curbp; // The current magnitude bit-plane (starts at 30)
			bool error; // Error indicator
			int tslen; // Length of first terminated segment
			int tsidx; // Index of current terminated segment
			ByteInputBuffer in_Renamed = null;
			
			bool isterm;
			
			// Get the code-block to decode
			srcblk = src.getCodeBlock(c, m, n, sb, 1, - 1, srcblk);
			
#if DO_TIMING
			stime = (System.DateTime.Now.Ticks - 621355968000000000) / 10000;
#endif

			// Retrieve options from decSpec
			options = ((System.Int32) decSpec.ecopts.getTileCompVal(tIdx, c));
			
			// Reset state
			ArrayUtil.intArraySet(state, 0);
			
			// Initialize output code-block
			if (cblk == null)
				cblk = new DataBlkInt();
			cblk.progressive = srcblk.prog;
			cblk.ulx = srcblk.ulx;
			cblk.uly = srcblk.uly;
			cblk.w = srcblk.w;
			cblk.h = srcblk.h;
			cblk.offset = 0;
			cblk.scanw = cblk.w;
			out_data = (int[]) cblk.Data;
			
			if (out_data == null || out_data.Length < srcblk.w * srcblk.h)
			{
				out_data = new int[srcblk.w * srcblk.h];
				cblk.Data = out_data;
			}
			else
			{
				// Set data values to 0
				ArrayUtil.intArraySet(out_data, 0);
			}
			
			if (srcblk.nl <= 0 || srcblk.nTrunc <= 0)
			{
				// 0 layers => no data to decode => return all 0s
				return cblk;
			}
			
			// Get the length of the first terminated segment
			tslen = (srcblk.tsLengths == null)?srcblk.dl:srcblk.tsLengths[0];
			tsidx = 0;
			// Initialize for decoding
			npasses = srcblk.nTrunc;
			if (mq == null)
			{
				in_Renamed = new ByteInputBuffer(srcblk.data, 0, tslen);
				mq = new MQDecoder(in_Renamed, NUM_CTXTS, MQ_INIT);
			}
			else
			{
				// We always start by an MQ segment
				mq.nextSegment(srcblk.data, 0, tslen);
				mq.resetCtxts();
			}
			error = false;
			
			if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0)
			{
				if (bin == null)
				{
					if (in_Renamed == null)
						in_Renamed = mq.ByteInputBuffer;
					bin = new ByteToBitInput(in_Renamed);
				}
			}
			
			// Choose correct ZC lookup table for global orientation
			switch (sb.orientation)
			{
				
				case Subband.WT_ORIENT_HL: 
					zc_lut = ZC_LUT_HL;
					break;
				
				case Subband.WT_ORIENT_LH: 
				case Subband.WT_ORIENT_LL: 
					zc_lut = ZC_LUT_LH;
					break;
				
				case Subband.WT_ORIENT_HH: 
					zc_lut = ZC_LUT_HH;
					break;
				
				default: 
					throw new System.ApplicationException("JJ2000 internal error");
				
			}
			
			// NOTE: we don't currently detect which is the last magnitude
			// bit-plane so that 'isterm' is true for the last pass of it. Doing
			// so would aid marginally in error detection with the predictable
			// error resilient MQ termination. However, determining which is the
			// last magnitude bit-plane is quite hard (due to ROI, quantization,
			// etc.)  and in any case the predictable error resilient termination
			// used without the arithmetic coding bypass and/or regular
			// termination modes is almost useless.
			
			// Loop on bit-planes and passes
			
			curbp = 30 - srcblk.skipMSBP;
			
			// Check for maximum number of bitplanes quit condition
			if (mQuit != - 1 && (mQuit * 3 - 2) < npasses)
			{
				npasses = mQuit * 3 - 2;
			}
			
			// First bit-plane has only the cleanup pass
			if (curbp >= 0 && npasses > 0)
			{
				isterm = (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 - srcblk.skipMSBP) >= curbp);
				error = cleanuppass(cblk, mq, curbp, state, zc_lut, isterm);
				npasses--;
				if (!error || !doer)
					curbp--;
			}
			
			// Other bit-planes have the three coding passes
			if (!error || !doer)
			{
				while (curbp >= 0 && npasses > 0)
				{
					
					if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (curbp < 31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - srcblk.skipMSBP))
					{
						// Use bypass decoding mode (only all bit-planes
						// after the first 4 bit-planes).
						
						// Here starts a new raw segment
						bin.setByteArray(null, - 1, srcblk.tsLengths[++tsidx]);
						isterm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0;
						error = rawSigProgPass(cblk, bin, curbp, state, isterm);
						npasses--;
						if (npasses <= 0 || (error && doer))
							break;
						
						if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0)
						{
							// Start a new raw segment
							bin.setByteArray(null, - 1, srcblk.tsLengths[++tsidx]);
						}
						isterm = (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 - srcblk.skipMSBP > curbp));
						error = rawMagRefPass(cblk, bin, curbp, state, isterm);
					}
					else
					{
						// Do not use bypass decoding mode
						if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0)
						{
							// Here starts a new MQ segment
							mq.nextSegment(null, - 1, srcblk.tsLengths[++tsidx]);
						}
						isterm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0;
						error = sigProgPass(cblk, mq, curbp, state, zc_lut, isterm);
						npasses--;
						if (npasses <= 0 || (error && doer))
							break;
						
						if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0)
						{
							// Here starts a new MQ segment
							mq.nextSegment(null, - 1, srcblk.tsLengths[++tsidx]);
						}
						isterm = (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 - srcblk.skipMSBP > curbp));
						error = magRefPass(cblk, mq, curbp, state, isterm);
					}
					
					npasses--;
					if (npasses <= 0 || (error && doer))
						break;
					
					if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0 || ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (curbp < 31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - srcblk.skipMSBP)))
					{
						// Here starts a new MQ segment
						mq.nextSegment(null, - 1, srcblk.tsLengths[++tsidx]);
					}
					isterm = (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 - srcblk.skipMSBP) >= curbp);
					error = cleanuppass(cblk, mq, curbp, state, zc_lut, isterm);
					npasses--;
					if (error && doer)
						break;
					// Goto next bit-plane
					curbp--;
				}
			}
			
			// If an error ocurred conceal it
			if (error && doer)
			{
				if (verber)
				{
					FacilityManager.getMsgLogger().printmsg(CSJ2K.j2k.util.MsgLogger_Fields.WARNING, "Error detected at bit-plane " + curbp + " in code-block (" + m + "," + n + "), sb_idx " + sb.sbandIdx + ", res. level " + sb.resLvl + ". Concealing...");
				}
				conceal(cblk, curbp);
			}
			
#if DO_TIMING
			time[c] += (System.DateTime.Now.Ticks - 621355968000000000) / 10000 - stime;
#endif
			
			// Return decoded block
			return cblk;
		}
 /// <summary> Instantiates a new 'ByteToBitInput' object that uses 'in' as the
 /// underlying byte based input.
 ///
 /// </summary>
 /// <param name="in">The underlying byte based input.
 ///
 /// </param>
 public ByteToBitInput(ByteInputBuffer in_Renamed)
 {
     this.in_Renamed = in_Renamed;
 }