Beispiel #1
0
        /// <summary> Initializes the EBCOT rate allocator of entropy coded data. The layout
        /// of layers, and their bitrate constraints, is specified by the 'lyrs'
        /// parameter.
        /// 
        /// </summary>
        /// <param name="src">The source of entropy coded data.
        /// 
        /// </param>
        /// <param name="lyrs">The layers layout specification.
        /// 
        /// </param>
        /// <param name="writer">The bit stream writer.
        /// 
        /// </param>
        /// <seealso cref="ProgressionType">
        /// 
        /// </seealso>
        public EBCOTRateAllocator(CodedCBlkDataSrcEnc src, LayersInfo lyrs, CodestreamWriter writer, EncoderSpecs encSpec, ParameterList pl)
            : base(src, lyrs.TotNumLayers, writer, encSpec)
        {
            int minsbi, maxsbi;
            int i;
            SubbandAn sb, sb2;
            Coord ncblks = null;

            // If we do timing create necessary structures
            #if DO_TIMING
            // If we are timing make sure that 'finalize' gets called.
            //UPGRADE_ISSUE: Method 'java.lang.System.runFinalizersOnExit' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javalangSystem'"
            // CONVERSION PROBLEM?
            //System_Renamed.runFinalizersOnExit(true);
            // The System.runFinalizersOnExit() method is deprecated in Java
            // 1.2 since it can cause a deadlock in some cases. However, here
            // we use it only for profiling purposes and is disabled in
            // production code.
            initTime = 0L;
            buildTime = 0L;
            writeTime = 0L;
            #endif

            // Save the layer specs
            lyrSpec = lyrs;

            //Initialize the size of the RD slope rates array
            RDSlopesRates = new int[RD_SUMMARY_SIZE];

            //Get number of tiles, components
            int nt = src.getNumTiles();
            int nc = NumComps;

            //Allocate the coded code-blocks and truncation points indexes arrays
            cblks = new CBlkRateDistStats[nt][][][][];
            for (int i2 = 0; i2 < nt; i2++)
            {
                cblks[i2] = new CBlkRateDistStats[nc][][][];
            }
            truncIdxs = new int[nt][][][][][];
            for (int i3 = 0; i3 < nt; i3++)
            {
                truncIdxs[i3] = new int[num_Layers][][][][];
                for (int i4 = 0; i4 < num_Layers; i4++)
                {
                    truncIdxs[i3][i4] = new int[nc][][][];
                }
            }

            int cblkPerSubband; // Number of code-blocks per subband
            int mrl; // Number of resolution levels
            int l; // layer index
            int s; //subband index

            // Used to compute the maximum number of precincts for each resolution
            // level
            int tx0, ty0, tx1, ty1; // Current tile position in the reference grid
            int tcx0, tcy0, tcx1, tcy1; // Current tile position in the domain of
            // the image component
            int trx0, try0, trx1, try1; // Current tile position in the reduced
            // resolution image domain
            int xrsiz, yrsiz; // Component sub-sampling factors
            Coord tileI = null;
            Coord nTiles = null;
            int xsiz, ysiz, x0siz, y0siz;
            int xt0siz, yt0siz;
            int xtsiz, ytsiz;

            int cb0x = src.CbULX;
            int cb0y = src.CbULY;

            src.setTile(0, 0);
            for (int t = 0; t < nt; t++)
            {
                // Loop on tiles
                nTiles = src.getNumTiles(nTiles);
                tileI = src.getTile(tileI);
                x0siz = ImgULX;
                y0siz = ImgULY;
                xsiz = x0siz + ImgWidth;
                ysiz = y0siz + ImgHeight;
                xt0siz = src.TilePartULX;
                yt0siz = src.TilePartULY;
                xtsiz = src.NomTileWidth;
                ytsiz = src.NomTileHeight;

                // Tile's coordinates on the reference grid
                tx0 = (tileI.x == 0)?x0siz:xt0siz + tileI.x * xtsiz;
                ty0 = (tileI.y == 0)?y0siz:yt0siz + tileI.y * ytsiz;
                tx1 = (tileI.x != nTiles.x - 1)?xt0siz + (tileI.x + 1) * xtsiz:xsiz;
                ty1 = (tileI.y != nTiles.y - 1)?yt0siz + (tileI.y + 1) * ytsiz:ysiz;

                for (int c = 0; c < nc; c++)
                {
                    // loop on components

                    //Get the number of resolution levels
                    sb = src.getAnSubbandTree(t, c);
                    mrl = sb.resLvl + 1;

                    // Initialize maximum number of precincts per resolution array
                    if (numPrec == null)
                    {
                        Coord[][][] tmpArray = new Coord[nt][][];
                        for (int i5 = 0; i5 < nt; i5++)
                        {
                            tmpArray[i5] = new Coord[nc][];
                        }
                        numPrec = tmpArray;
                    }
                    if (numPrec[t][c] == null)
                    {
                        numPrec[t][c] = new Coord[mrl];
                    }

                    // Subsampling factors
                    xrsiz = src.getCompSubsX(c);
                    yrsiz = src.getCompSubsY(c);

                    // Tile's coordinates in the image component domain
                    //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                    tcx0 = (int) System.Math.Ceiling(tx0 / (double) (xrsiz));
                    //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                    tcy0 = (int) System.Math.Ceiling(ty0 / (double) (yrsiz));
                    //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                    tcx1 = (int) System.Math.Ceiling(tx1 / (double) (xrsiz));
                    //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                    tcy1 = (int) System.Math.Ceiling(ty1 / (double) (yrsiz));

                    cblks[t][c] = new CBlkRateDistStats[mrl][][];

                    for (l = 0; l < num_Layers; l++)
                    {
                        truncIdxs[t][l][c] = new int[mrl][][];
                    }

                    for (int r = 0; r < mrl; r++)
                    {
                        // loop on resolution levels

                        // Tile's coordinates in the reduced resolution image
                        // domain
                        //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                        trx0 = (int) System.Math.Ceiling(tcx0 / (double) (1 << (mrl - 1 - r)));
                        //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                        try0 = (int) System.Math.Ceiling(tcy0 / (double) (1 << (mrl - 1 - r)));
                        //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                        trx1 = (int) System.Math.Ceiling(tcx1 / (double) (1 << (mrl - 1 - r)));
                        //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                        try1 = (int) System.Math.Ceiling(tcy1 / (double) (1 << (mrl - 1 - r)));

                        // Calculate the maximum number of precincts for each
                        // resolution level taking into account tile specific
                        // options.
                        double twoppx = (double) encSpec.pss.getPPX(t, c, r);
                        double twoppy = (double) encSpec.pss.getPPY(t, c, r);
                        numPrec[t][c][r] = new Coord();
                        if (trx1 > trx0)
                        {
                            //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                            numPrec[t][c][r].x = (int) System.Math.Ceiling((trx1 - cb0x) / twoppx) - (int) System.Math.Floor((trx0 - cb0x) / twoppx);
                        }
                        else
                        {
                            numPrec[t][c][r].x = 0;
                        }
                        if (try1 > try0)
                        {
                            //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                            numPrec[t][c][r].y = (int) System.Math.Ceiling((try1 - cb0y) / twoppy) - (int) System.Math.Floor((try0 - cb0y) / (double) twoppy);
                        }
                        else
                        {
                            numPrec[t][c][r].y = 0;
                        }

                        minsbi = (r == 0)?0:1;
                        maxsbi = (r == 0)?1:4;

                        cblks[t][c][r] = new CBlkRateDistStats[maxsbi][];
                        for (l = 0; l < num_Layers; l++)
                        {
                            truncIdxs[t][l][c][r] = new int[maxsbi][];
                        }

                        for (s = minsbi; s < maxsbi; s++)
                        {
                            // loop on subbands
                            //Get the number of blocks in the current subband
                            sb2 = (SubbandAn) sb.getSubbandByIdx(r, s);
                            ncblks = sb2.numCb;
                            cblkPerSubband = ncblks.x * ncblks.y;
                            cblks[t][c][r][s] = new CBlkRateDistStats[cblkPerSubband];

                            for (l = 0; l < num_Layers; l++)
                            {
                                truncIdxs[t][l][c][r][s] = new int[cblkPerSubband];
                                for (i = 0; i < cblkPerSubband; i++)
                                {
                                    truncIdxs[t][l][c][r][s][i] = - 1;
                                }
                            }
                        } // End loop on subbands
                    } // End lopp on resolution levels
                } // End loop on components
                if (t != nt - 1)
                {
                    src.nextTile();
                }
            } // End loop on tiles

            //Initialize the packet encoder
            pktEnc = new PktEncoder(src, encSpec, numPrec, pl);

            // The layers array has to be initialized after the constructor since
            // it is needed that the bit stream header has been entirely written
        }
Beispiel #2
0
		/// <summary> Compresses the code-block in 'srcblk' and puts the results in 'ccb',
		/// using the specified options and temporary storage.
		/// 
		/// </summary>
		/// <param name="c">The component for which to return the next code-block.
		/// 
		/// </param>
		/// <param name="ccb">The object where the compressed data will be stored. If the
		/// 'data' array of 'cbb' is not null it may be reused to return the
		/// compressed data.
		/// 
		/// </param>
		/// <param name="srcblk">The code-block data to code
		/// 
		/// </param>
		/// <param name="mq">The MQ-coder to use
		/// 
		/// </param>
		/// <param name="bout">The bit level output to use. Used only if 'OPT_BYPASS' is
		/// turned on in the 'options' argument.
		/// 
		/// </param>
		/// <param name="out">The byte buffer trough which the compressed data is stored.
		/// 
		/// </param>
		/// <param name="state">The state information for the code-block
		/// 
		/// </param>
		/// <param name="distbuf">The buffer where to store the distortion  at 
		/// the end of each coding pass.
		/// 
		/// </param>
		/// <param name="ratebuf">The buffer where to store the rate (i.e. coded lenth) at 
		/// the end of each coding pass.
		/// 
		/// </param>
		/// <param name="istermbuf">The buffer where to store the terminated flag for each 
		/// coding pass.
		/// 
		/// </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="options">The options to use when coding this code-block
		/// 
		/// </param>
		/// <param name="rev">The reversible flag. Should be true if the source of this
		/// code-block's data is reversible.
		/// 
		/// </param>
		/// <param name="lcType">The type of length calculation to use with the MQ coder.
		/// 
		/// </param>
		/// <param name="tType">The type of termination to use with the MQ coder.
		/// 
		/// </param>
		/// <seealso cref="getNextCodeBlock">
		/// 
		/// </seealso>
		static private void  compressCodeBlock(int c, CBlkRateDistStats ccb, CBlkWTData srcblk, MQCoder mq, BitToByteOutput bout, ByteOutputBuffer out_Renamed, int[] state, double[] distbuf, int[] ratebuf, bool[] istermbuf, int[] symbuf, int[] ctxtbuf, int options, bool rev, int lcType, int tType)
		{
			// NOTE: This method should not access any non-final instance or
			// static variables, either directly or indirectly through other
			// methods in order to be sure that the method is thread safe.
			
			int[] zc_lut; // The ZC lookup table to use
			int skipbp; // The number of non-significant bit-planes to skip
			int curbp; // The current magnitude bit-plane (starts at 30)
			int[] fm; // The distortion estimation lookup table for MR
			int[] fs; // The distortion estimation lookup table for SC
			int lmb; // The least significant magnitude bit
			int npass; // The number of coding passes, for R-D statistics
			double msew; // The distortion (MSE weight) for the current bit-plane
			double totdist; // The total cumulative distortion decrease
			int ltpidx; // The index of the last pass which is terminated
			
			// Check error-resilient termination
			if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_PRED_TERM) != 0 && tType != MQCoder.TERM_PRED_ER)
			{
				throw new System.ArgumentException("Embedded error-resilient info " + "in MQ termination option " + "specified but incorrect MQ " + "termination " + "policy specified");
			}
			// Set MQ flags
			mq.LenCalcType = lcType;
			mq.TermType = tType;
			
			lmb = 30 - srcblk.magbits + 1;
			// If there are more bit-planes to code than the implementation
			// bit-depth set lmb to 0
			lmb = (lmb < 0)?0:lmb;
			
			// Reset state
			ArrayUtil.intArraySet(state, 0);
			
			// Find the most significant bit-plane
			skipbp = calcSkipMSBP(srcblk, lmb);
			
			// Initialize output code-block
			ccb.m = srcblk.m;
			ccb.n = srcblk.n;
			ccb.sb = srcblk.sb;
			ccb.nROIcoeff = srcblk.nROIcoeff;
			ccb.skipMSBP = skipbp;
			if (ccb.nROIcoeff != 0)
			{
				ccb.nROIcp = 3 * (srcblk.nROIbp - skipbp - 1) + 1;
			}
			else
			{
				ccb.nROIcp = 0;
			}
			
			// Choose correct ZC lookup table for global orientation
			switch (srcblk.sb.orientation)
			{
				
				case Subband.WT_ORIENT_HL: 
					zc_lut = ZC_LUT_HL;
					break;
				
				case Subband.WT_ORIENT_LL: 
				case Subband.WT_ORIENT_LH: 
					zc_lut = ZC_LUT_LH;
					break;
				
				case Subband.WT_ORIENT_HH: 
					zc_lut = ZC_LUT_HH;
					break;
				
				default: 
					throw new System.InvalidOperationException("JJ2000 internal error");
				
			}
			
			// Loop on significant magnitude bit-planes doing the 3 passes
			curbp = 30 - skipbp;
			fs = FS_LOSSY;
			fm = FM_LOSSY;
			msew = System.Math.Pow(2, ((curbp - lmb) << 1) - MSE_LKP_FRAC_BITS) * srcblk.sb.stepWMSE * srcblk.wmseScaling;
			totdist = 0f;
			npass = 0;
			ltpidx = - 1;
			
			// First significant bit-plane has only the pass pass
			if (curbp >= lmb)
			{
				// Do we need the "lossless" 'fs' table ?
				if (rev && curbp == lmb)
				{
					fs = FM_LOSSLESS;
				}
				// We terminate if regular termination, last bit-plane, or next
				// bit-plane is "raw".
				istermbuf[npass] = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0 || curbp == lmb || ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - skipbp) >= curbp);
				totdist += cleanuppass(srcblk, mq, istermbuf[npass], curbp, state, fs, zc_lut, symbuf, ctxtbuf, ratebuf, npass, ltpidx, options) * msew;
				distbuf[npass] = totdist;
				if (istermbuf[npass])
					ltpidx = npass;
				npass++;
				msew *= 0.25;
				curbp--;
			}
			// Other bit-planes have all passes
			while (curbp >= lmb)
			{
				// Do we need the "lossless" 'fs' and 'fm' tables ?
				if (rev && curbp == lmb)
				{
					fs = FS_LOSSLESS;
					fm = FM_LOSSLESS;
				}
				
				// Do the significance propagation pass
				// We terminate if regular termination only
				istermbuf[npass] = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0;
				if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) == 0 || (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - skipbp <= curbp))
				{
					// No bypass coding
					totdist += sigProgPass(srcblk, mq, istermbuf[npass], curbp, state, fs, zc_lut, symbuf, ctxtbuf, ratebuf, npass, ltpidx, options) * msew;
				}
				else
				{
					// Bypass ("raw") coding
					bout.PredTerm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_PRED_TERM) != 0;
					totdist += rawSigProgPass(srcblk, bout, istermbuf[npass], curbp, state, fs, ratebuf, npass, ltpidx, options) * msew;
				}
				distbuf[npass] = totdist;
				if (istermbuf[npass])
					ltpidx = npass;
				npass++;
				
				// Do the magnitude refinement pass
				// We terminate if regular termination or bypass ("raw") coding
				istermbuf[npass] = (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 - skipbp > curbp));
				if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) == 0 || (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - skipbp <= curbp))
				{
					// No bypass coding
					totdist += magRefPass(srcblk, mq, istermbuf[npass], curbp, state, fm, symbuf, ctxtbuf, ratebuf, npass, ltpidx, options) * msew;
				}
				else
				{
					// Bypass ("raw") coding
					bout.PredTerm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_PRED_TERM) != 0;
					totdist += rawMagRefPass(srcblk, bout, istermbuf[npass], curbp, state, fm, ratebuf, npass, ltpidx, options) * msew;
				}
				distbuf[npass] = totdist;
				if (istermbuf[npass])
					ltpidx = npass;
				npass++;
				
				// Do the clenup pass
				// We terminate if regular termination, last bit-plane, or next
				// bit-plane is "raw".
				istermbuf[npass] = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0 || curbp == lmb || ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - skipbp) >= curbp);
				totdist += cleanuppass(srcblk, mq, istermbuf[npass], curbp, state, fs, zc_lut, symbuf, ctxtbuf, ratebuf, npass, ltpidx, options) * msew;
				distbuf[npass] = totdist;
				
				if (istermbuf[npass])
					ltpidx = npass;
				npass++;
				
				// Goto next bit-plane
				msew *= 0.25;
				curbp--;
			}
			
			// Copy compressed data and rate-distortion statistics to output
			ccb.data = new byte[out_Renamed.size()];
			out_Renamed.toByteArray(0, out_Renamed.size(), ccb.data, 0);
			checkEndOfPassFF(ccb.data, ratebuf, istermbuf, npass);
			ccb.selectConvexHull(ratebuf, distbuf, (options & (CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS | CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS)) != 0?istermbuf:null, npass, rev);
			
			// Reset MQ coder and bit output for next code-block
			mq.reset();
			if (bout != null)
				bout.reset();
		}
Beispiel #3
0
        /// <summary> Encodes a packet and returns the buffer containing the encoded packet
        /// header. The code-blocks appear in a 3D array of CBlkRateDistStats,
        /// 'cbs'. The first index is the tile index in lexicographical order, the
        /// second index is the subband index (as defined in the Subband class),
        /// and the third index is the code-block index (whithin the subband tile)
        /// in lexicographical order as well. The indexes of the new truncation
        /// points for each code-block are specified by the 3D array of int
        /// 'tIndx'. The indices of this array are the same as for cbs. The
        /// truncation point indices in 'tIndx' are the indices of the elements of
        /// the 'truncIdxs' array, of the CBlkRateDistStats class, that give the
        /// real truncation points. If a truncation point index is negative it
        /// means that the code-block has not been included in any layer yet. If
        /// the truncation point is less than or equal to the highest truncation
        /// point used in previous layers then the code-block is not included in
        /// the packet. Otherwise, if larger, the code-block is included in the
        /// packet. The body of the packet can be obtained with the
        /// getLastBodyBuf() and getLastBodyLen() methods.
        /// 
        /// <p>Layers must be coded in increasing order, in consecutive manner, for
        /// each tile, component and resolution level (e.g., layer 1, then layer 2,
        /// etc.). For different tile, component and/or resolution level no
        /// particular order must be followed.</p>
        /// 
        /// </summary>
        /// <param name="ly">The layer index (starts at 1).
        /// 
        /// </param>
        /// <param name="c">The component index.
        /// 
        /// </param>
        /// <param name="r">The resolution level
        /// 
        /// </param>
        /// <param name="t">Index of the current tile
        /// 
        /// </param>
        /// <param name="cbs">The 3D array of coded code-blocks.
        /// 
        /// </param>
        /// <param name="tIndx">The truncation point indices for each code-block.
        /// 
        /// </param>
        /// <param name="hbuf">The header buffer. If null a new BitOutputBuffer is created
        /// and returned. This buffer is reset before anything is written to it.
        /// 
        /// </param>
        /// <param name="bbuf">The body buffer. If null a new one is created. If not large
        /// enough a new one is created.
        /// 
        /// </param>
        /// <param name="pIdx">The precinct index.
        /// 
        /// </param>
        /// <returns> The buffer containing the packet header.
        /// 
        /// </returns>
        public virtual BitOutputBuffer encodePacket(int ly, int c, int r, int t, CBlkRateDistStats[][] cbs, int[][] tIndx, BitOutputBuffer hbuf, byte[] bbuf, int pIdx)
        {
            int b, i, maxi;
            int ncb;
            int thmax;
            int newtp;
            int cblen;
            int prednbits, nbits; // deltabits removed
            TagTreeEncoder cur_ttIncl, cur_ttMaxBP; // inclusion and bit-depth tag
            // trees
            int[] cur_prevtIdxs; // last encoded truncation points
            CBlkRateDistStats[] cur_cbs;
            int[] cur_tIndx; // truncation points to encode
            int minsb = (r == 0)?0:1;
            int maxsb = (r == 0)?1:4;
            Coord cbCoord = null;
            SubbandAn root = infoSrc.getAnSubbandTree(t, c);
            SubbandAn sb;
            roiInPkt = false;
            roiLen = 0;
            int mend, nend;

            // Checks if a precinct with such an index exists in this resolution
            // level
            if (pIdx >= ppinfo[t][c][r].Length)
            {
                packetWritable = false;
                return hbuf;
            }
            PrecInfo prec = ppinfo[t][c][r][pIdx];

            // First, we check if packet is empty (i.e precinct 'pIdx' has no
            // code-block in any of the subbands)
            bool isPrecVoid = true;

            for (int s = minsb; s < maxsb; s++)
            {
                if (prec.nblk[s] == 0)
                {
                    // The precinct has no code-block in this subband.
                    continue;
                }
                else
                {
                    // The precinct is not empty in at least one subband ->
                    // stop
                    isPrecVoid = false;
                    break;
                }
            }

            if (isPrecVoid)
            {
                packetWritable = true;

                if (hbuf == null)
                {
                    hbuf = new BitOutputBuffer();
                }
                else
                {
                    hbuf.reset();
                }
                if (bbuf == null)
                {
                    lbbuf = bbuf = new byte[1];
                }
                hbuf.writeBit(0);
                lblen = 0;

                return hbuf;
            }

            if (hbuf == null)
            {
                hbuf = new BitOutputBuffer();
            }
            else
            {
                hbuf.reset();
            }

            // Invalidate last body buffer
            lbbuf = null;
            lblen = 0;

            // Signal that packet is present
            hbuf.writeBit(1);

            for (int s = minsb; s < maxsb; s++)
            {
                // Loop on subbands
                sb = (SubbandAn) root.getSubbandByIdx(r, s);

                // Go directly to next subband if the precinct has no code-block
                // in the current one.
                if (prec.nblk[s] == 0)
                {
                    continue;
                }

                cur_ttIncl = ttIncl[t][c][r][pIdx][s];
                cur_ttMaxBP = ttMaxBP[t][c][r][pIdx][s];
                cur_prevtIdxs = prevtIdxs[t][c][r][s];
                cur_cbs = cbs[s];
                cur_tIndx = tIndx[s];

                // Set tag tree values for code-blocks in this precinct
                mend = (prec.cblk[s] == null)?0:prec.cblk[s].Length;
                for (int m = 0; m < mend; m++)
                {
                    nend = (prec.cblk[s][m] == null)?0:prec.cblk[s][m].Length;
                    for (int n = 0; n < nend; n++)
                    {
                        cbCoord = prec.cblk[s][m][n].idx;
                        b = cbCoord.x + cbCoord.y * sb.numCb.x;

                        if (cur_tIndx[b] > cur_prevtIdxs[b] && cur_prevtIdxs[b] < 0)
                        {
                            // First inclusion
                            cur_ttIncl.setValue(m, n, ly - 1);
                        }
                        if (ly == 1)
                        {
                            // First layer, need to set the skip of MSBP
                            cur_ttMaxBP.setValue(m, n, cur_cbs[b].skipMSBP);
                        }
                    }
                }

                // Now encode the information
                for (int m = 0; m < prec.cblk[s].Length; m++)
                {
                    // Vertical code-blocks
                    for (int n = 0; n < prec.cblk[s][m].Length; n++)
                    {
                        // Horiz. cblks
                        cbCoord = prec.cblk[s][m][n].idx;
                        b = cbCoord.x + cbCoord.y * sb.numCb.x;

                        // 1) Inclusion information
                        if (cur_tIndx[b] > cur_prevtIdxs[b])
                        {
                            // Code-block included in this layer
                            if (cur_prevtIdxs[b] < 0)
                            {
                                // First inclusion
                                // Encode layer info
                                cur_ttIncl.encode(m, n, ly, hbuf);

                                // 2) Max bitdepth info. Encode value
                                thmax = cur_cbs[b].skipMSBP + 1;
                                for (i = 1; i <= thmax; i++)
                                {
                                    cur_ttMaxBP.encode(m, n, i, hbuf);
                                }

                                // Count body size for packet
                                lblen += cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_tIndx[b]]];
                            }
                            else
                            {
                                // Already in previous layer
                                // Send "1" bit
                                hbuf.writeBit(1);
                                // Count body size for packet
                                lblen += cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_tIndx[b]]] - cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_prevtIdxs[b]]];
                            }

                            // 3) Truncation point information
                            if (cur_prevtIdxs[b] < 0)
                            {
                                newtp = cur_cbs[b].truncIdxs[cur_tIndx[b]];
                            }
                            else
                            {
                                newtp = cur_cbs[b].truncIdxs[cur_tIndx[b]] - cur_cbs[b].truncIdxs[cur_prevtIdxs[b]] - 1;
                            }

                            // Mix of switch and if is faster
                            switch (newtp)
                            {

                                case 0:
                                    hbuf.writeBit(0); // Send one "0" bit
                                    break;

                                case 1:
                                    hbuf.writeBits(2, 2); // Send one "1" and one "0"
                                    break;

                                case 2:
                                case 3:
                                case 4:
                                    // Send two "1" bits followed by 2 bits
                                    // representation of newtp-2
                                    hbuf.writeBits((3 << 2) | (newtp - 2), 4);
                                    break;

                                default:
                                    if (newtp <= 35)
                                    {
                                        // Send four "1" bits followed by a five bits
                                        // representation of newtp-5
                                        hbuf.writeBits((15 << 5) | (newtp - 5), 9);
                                    }
                                    else if (newtp <= 163)
                                    {
                                        // Send nine "1" bits followed by a seven bits
                                        // representation of newtp-36
                                        hbuf.writeBits((511 << 7) | (newtp - 36), 16);
                                    }
                                    else
                                    {
                                        throw new System.ArithmeticException("Maximum number " + "of truncation " + "points exceeded");
                                    }
                                    break;

                            }
                        }
                        else
                        {
                            // Block not included in this layer
                            if (cur_prevtIdxs[b] >= 0)
                            {
                                // Already in previous layer. Send "0" bit
                                hbuf.writeBit(0);
                            }
                            else
                            {
                                // Not in any previous layers
                                cur_ttIncl.encode(m, n, ly, hbuf);
                            }
                            // Go to the next one.
                            continue;
                        }

                        // Code-block length

                        // We need to compute the maximum number of bits needed to
                        // signal the length of each terminated segment and the
                        // final truncation point.
                        newtp = 1;
                        maxi = cur_cbs[b].truncIdxs[cur_tIndx[b]];
                        cblen = (cur_prevtIdxs[b] < 0)?0:cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_prevtIdxs[b]]];

                        // Loop on truncation points
                        i = (cur_prevtIdxs[b] < 0)?0:cur_cbs[b].truncIdxs[cur_prevtIdxs[b]] + 1;
                        int minbits = 0;
                        for (; i < maxi; i++, newtp++)
                        {
                            // If terminated truncation point calculate length
                            if (cur_cbs[b].isTermPass != null && cur_cbs[b].isTermPass[i])
                            {

                                // Calculate length
                                cblen = cur_cbs[b].truncRates[i] - cblen;

                                // Calculate number of needed bits
                                prednbits = lblock[t][c][r][s][b] + MathUtil.log2(newtp);
                                minbits = ((cblen > 0)?MathUtil.log2(cblen):0) + 1;

                                // Update Lblock increment if needed
                                for (int j = prednbits; j < minbits; j++)
                                {
                                    lblock[t][c][r][s][b]++;
                                    hbuf.writeBit(1);
                                }
                                // Initialize for next length
                                newtp = 0;
                                cblen = cur_cbs[b].truncRates[i];
                            }
                        }

                        // Last truncation point length always sent

                        // Calculate length
                        cblen = cur_cbs[b].truncRates[i] - cblen;

                        // Calculate number of bits
                        prednbits = lblock[t][c][r][s][b] + MathUtil.log2(newtp);
                        minbits = ((cblen > 0)?MathUtil.log2(cblen):0) + 1;
                        // Update Lblock increment if needed
                        for (int j = prednbits; j < minbits; j++)
                        {
                            lblock[t][c][r][s][b]++;
                            hbuf.writeBit(1);
                        }

                        // End of comma-code increment
                        hbuf.writeBit(0);

                        // There can be terminated several segments, send length
                        // info for all terminated truncation points in addition
                        // to final one
                        newtp = 1;
                        maxi = cur_cbs[b].truncIdxs[cur_tIndx[b]];
                        cblen = (cur_prevtIdxs[b] < 0)?0:cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_prevtIdxs[b]]];
                        // Loop on truncation points and count the groups
                        i = (cur_prevtIdxs[b] < 0)?0:cur_cbs[b].truncIdxs[cur_prevtIdxs[b]] + 1;
                        for (; i < maxi; i++, newtp++)
                        {
                            // If terminated truncation point, send length
                            if (cur_cbs[b].isTermPass != null && cur_cbs[b].isTermPass[i])
                            {

                                cblen = cur_cbs[b].truncRates[i] - cblen;
                                nbits = MathUtil.log2(newtp) + lblock[t][c][r][s][b];
                                hbuf.writeBits(cblen, nbits);

                                // Initialize for next length
                                newtp = 0;
                                cblen = cur_cbs[b].truncRates[i];
                            }
                        }
                        // Last truncation point length is always signalled
                        // First calculate number of bits needed to signal
                        // Calculate length
                        cblen = cur_cbs[b].truncRates[i] - cblen;
                        nbits = MathUtil.log2(newtp) + lblock[t][c][r][s][b];
                        hbuf.writeBits(cblen, nbits);
                    } // End loop on horizontal code-blocks
                } // End loop on vertical code-blocks
            } // End loop on subband

            // -> Copy the data to the body buffer

            // Ensure size for body data
            if (bbuf == null || bbuf.Length < lblen)
            {
                bbuf = new byte[lblen];
            }
            lbbuf = bbuf;
            lblen = 0;

            for (int s = minsb; s < maxsb; s++)
            {
                // Loop on subbands
                sb = (SubbandAn) root.getSubbandByIdx(r, s);

                cur_prevtIdxs = prevtIdxs[t][c][r][s];
                cur_cbs = cbs[s];
                cur_tIndx = tIndx[s];
                ncb = cur_prevtIdxs.Length;

                mend = (prec.cblk[s] == null)?0:prec.cblk[s].Length;
                for (int m = 0; m < mend; m++)
                {
                    // Vertical code-blocks
                    nend = (prec.cblk[s][m] == null)?0:prec.cblk[s][m].Length;
                    for (int n = 0; n < nend; n++)
                    {
                        // Horiz. cblks
                        cbCoord = prec.cblk[s][m][n].idx;
                        b = cbCoord.x + cbCoord.y * sb.numCb.x;

                        if (cur_tIndx[b] > cur_prevtIdxs[b])
                        {

                            // Block included in this precinct -> Copy data to
                            // body buffer and get code-size
                            if (cur_prevtIdxs[b] < 0)
                            {
                                cblen = cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_tIndx[b]]];
                                Array.Copy(cur_cbs[b].data, 0, lbbuf, lblen, cblen);
                            }
                            else
                            {
                                cblen = cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_tIndx[b]]] - cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_prevtIdxs[b]]];
                                Array.Copy(cur_cbs[b].data, cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_prevtIdxs[b]]], lbbuf, lblen, cblen);
                            }
                            lblen += cblen;

                            // Verifies if this code-block contains new ROI
                            // information
                            if (cur_cbs[b].nROIcoeff != 0 && (cur_prevtIdxs[b] == - 1 || cur_cbs[b].truncIdxs[cur_prevtIdxs[b]] <= cur_cbs[b].nROIcp - 1))
                            {
                                roiInPkt = true;
                                roiLen = lblen;
                            }

                            // Update truncation point
                            cur_prevtIdxs[b] = cur_tIndx[b];
                        }
                    } // End loop on horizontal code-blocks
                } // End loop on vertical code-blocks
            } // End loop on subbands

            packetWritable = true;

            // Must never happen
            if (hbuf.Length == 0)
            {
                throw new System.InvalidOperationException("You have found a bug in PktEncoder, method:" + " encodePacket");
            }

            return hbuf;
        }
Beispiel #4
0
		/// <summary> Returns the next coded code-block in the current tile for the specified
		/// component, as a copy (see below). The order in which code-blocks are
		/// returned is not specified. However each code-block is returned only
		/// once and all code-blocks will be returned if the method is called 'N'
		/// times, where 'N' is the number of code-blocks in the tile. After all
		/// the code-blocks have been returned for the current tile calls to this
		/// method will return 'null'.
		/// 
		/// <p>When changing the current tile (through 'setTile()' or 'nextTile()')
		/// this method will always return the first code-block, as if this method
		/// was never called before for the new current tile.</p>
		/// 
		/// <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.</p>
		/// 
		/// </summary>
		/// <param name="c">The component for which to return the next code-block.
		/// 
		/// </param>
		/// <param name="ccb">If non-null this object might be used in returning the coded
		/// code-block in this or any subsequent call to this method. If null a new
		/// one is created and returned. If the 'data' array of 'cbb' is not null
		/// it may be reused to return the compressed data.
		/// 
		/// </param>
		/// <returns> The next coded 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="CBlkRateDistStats">
		/// 
		/// </seealso>
		public override CBlkRateDistStats getNextCodeBlock(int c, CBlkRateDistStats ccb)
		{
#if DO_TIMING
			long stime = 0L; // Start time for timed sections
#endif
			// Use single threaded implementation
			// Get code-block data from source
			srcblkT[0] = src.getNextInternCodeBlock(c, srcblkT[0]);
				
#if DO_TIMING
			stime = (System.DateTime.Now.Ticks - 621355968000000000) / 10000;
#endif

			if (srcblkT[0] == null)
			{
				// We got all code-blocks
				return null;
			}
			// Initialize thread local variables
			if ((opts[tIdx][c] & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && boutT[0] == null)
			{
				boutT[0] = new BitToByteOutput(outT[0]);
			}
			// Initialize output code-block
			if (ccb == null)
			{
				ccb = new CBlkRateDistStats();
			}
			// Compress code-block
			compressCodeBlock(c, ccb, srcblkT[0], mqT[0], boutT[0], outT[0], stateT[0], distbufT[0], ratebufT[0], istermbufT[0], symbufT[0], ctxtbufT[0], opts[tIdx][c], isReversible(tIdx, c), lenCalc[tIdx][c], tType[tIdx][c]);
				
#if DO_TIMING
			time[c] += (System.DateTime.Now.Ticks - 621355968000000000) / 10000 - stime;
#endif

			// Return result
			return ccb;
		}
Beispiel #5
0
		/// <summary> Returns the next coded code-block in the current tile for the specified
		/// component, as a copy (see below). The order in which code-blocks are
		/// returned is not specified. However each code-block is returned only
		/// once and all code-blocks will be returned if the method is called 'N'
		/// times, where 'N' is the number of code-blocks in the tile. After all
		/// the code-blocks have been returned for the current tile calls to this
		/// method will return 'null'.
		/// 
		/// <p>When changing the current tile (through 'setTile()' or 'nextTile()')
		/// this method will always return the first code-block, as if this method
		/// was never called before for the new current tile.</p>
		/// 
		/// <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.</p>
		/// 
		/// </summary>
		/// <param name="c">The component for which to return the next code-block.
		/// 
		/// </param>
		/// <param name="ccb">If non-null this object might be used in returning the coded
		/// code-block in this or any subsequent call to this method. If null a new
		/// one is created and returned. If the 'data' array of 'cbb' is not null
		/// it may be reused to return the compressed data.
		/// 
		/// </param>
		/// <returns> The next coded 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="CBlkRateDistStats">
		/// 
		/// </seealso>
		public override CBlkRateDistStats getNextCodeBlock(int c, CBlkRateDistStats ccb)
		{
#if DO_TIMING
			long stime = 0L; // Start time for timed sections
#endif
			if (tPool == null)
			{
				// Use single threaded implementation
				// Get code-block data from source
				srcblkT[0] = src.getNextInternCodeBlock(c, srcblkT[0]);
				
#if DO_TIMING
			    stime = (System.DateTime.Now.Ticks - 621355968000000000) / 10000;
#endif

				if (srcblkT[0] == null)
				{
					// We got all code-blocks
					return null;
				}
				// Initialize thread local variables
				if ((opts[tIdx][c] & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && boutT[0] == null)
				{
					boutT[0] = new BitToByteOutput(outT[0]);
				}
				// Initialize output code-block
				if (ccb == null)
				{
					ccb = new CBlkRateDistStats();
				}
				// Compress code-block
				compressCodeBlock(c, ccb, srcblkT[0], mqT[0], boutT[0], outT[0], stateT[0], distbufT[0], ratebufT[0], istermbufT[0], symbufT[0], ctxtbufT[0], opts[tIdx][c], isReversible(tIdx, c), lenCalc[tIdx][c], tType[tIdx][c]);
				
#if DO_TIMING
				time[c] += (System.DateTime.Now.Ticks - 621355968000000000) / 10000 - stime;
#endif

				// Return result
				return ccb;
			}
			else
			{
				// Use multiple threaded implementation
				int cIdx; // Compressor idx
				Compressor compr; // Compressor
				
#if DO_TIMING
				stime = (System.DateTime.Now.Ticks - 621355968000000000) / 10000;
#endif
				// Give data to all free compressors, using the current component
				while (!finishedTileComponent[c] && !(idleComps.Count == 0))
				{
					// Get an idle compressor
					compr = (Compressor) SupportClass.StackSupport.Pop(idleComps);
					cIdx = compr.Idx;
					// Get data for the compressor and wake it up
#if DO_TIMING
					time[c] += (System.DateTime.Now.Ticks - 621355968000000000) / 10000 - stime;
#endif
					srcblkT[cIdx] = src.getNextInternCodeBlock(c, srcblkT[cIdx]);
#if DO_TIMING
					stime = (System.DateTime.Now.Ticks - 621355968000000000) / 10000;
#endif
					if (srcblkT[cIdx] != null)
					{
						// Initialize thread local variables
						if ((opts[tIdx][c] & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && boutT[cIdx] == null)
						{
							boutT[cIdx] = new BitToByteOutput(outT[cIdx]);
						}
						// Initialize output code-block and compressor thread
						if (ccb == null)
							ccb = new CBlkRateDistStats();
						compr.ccb = ccb;
						compr.c = c;
						compr.options = opts[tIdx][c];
						compr.rev = isReversible(tIdx, c);
						compr.lcType = lenCalc[tIdx][c];
						compr.tType = tType[tIdx][c];
						nBusyComps[c]++;
						ccb = null;
						// Send compressor to execution in thread pool
						tPool.runTarget(compr, completedComps[c]);
					}
					else
					{
						// We finished with all the code-blocks in the current
						// tile component
						idleComps.Add(compr);
						finishedTileComponent[c] = true;
					}
				}
				// If there are threads for this component which result has not
				// been returned yet, get it
				if (nBusyComps[c] > 0)
				{
					lock (completedComps[c])
					{
						// If no compressor is done, wait until one is
						if ((completedComps[c].Count == 0))
						{
							try
							{
#if DO_TIMING
								time[c] += (System.DateTime.Now.Ticks - 621355968000000000) / 10000 - stime;
#endif
								System.Threading.Monitor.Wait(completedComps[c]);
#if DO_TIMING
								stime = (System.DateTime.Now.Ticks - 621355968000000000) / 10000;
#endif
							}
							catch (System.Threading.ThreadInterruptedException)
							{
							}
						}
						// Remove the thread from the completed queue and put it
						// on the idle queue
						compr = (Compressor) SupportClass.StackSupport.Pop(completedComps[c]);
						cIdx = compr.Idx;
						nBusyComps[c]--;
						idleComps.Add(compr);
						// Check targets error condition
						tPool.checkTargetErrors();
						// Get the result of compression and return that.
#if DO_TIMING
						time[c] += (System.DateTime.Now.Ticks - 621355968000000000) / 10000 - stime;
#endif
						return compr.ccb;
					}
				}
				else
				{
					// Check targets error condition
					tPool.checkTargetErrors();
					// Printing timing info if necessary
#if DO_TIMING
					time[c] += (System.DateTime.Now.Ticks - 621355968000000000) / 10000 - stime;
#endif
					// Nothing is running => no more code-blocks
					return null;
				}
			}
		}