Esempio n. 1
0
		/// <summary> Encodes information for the specified element of the tree, given the
		/// threshold and sends it to the 'out' stream. The information that is
		/// coded is whether or not the value of the element is greater than or
		/// equal to the value of the threshold.
		/// 
		/// </summary>
		/// <param name="m">The vertical index of the element.
		/// 
		/// </param>
		/// <param name="n">The horizontal index of the element.
		/// 
		/// </param>
		/// <param name="t">The threshold to use for encoding. It must be non-negative.
		/// 
		/// </param>
		/// <param name="out">The stream where to write the coded information.
		/// 
		/// </param>
		public virtual void  encode(int m, int n, int t, BitOutputBuffer out_Renamed)
		{
			int k, ts, idx, tmin;
			
			// Check arguments
			if (m >= h || n >= w || t < 0)
			{
				throw new System.ArgumentException();
			}
			
			// Initialize
			k = lvls - 1;
			tmin = treeS[k][0];
			
			// Loop on levels
			while (true)
			{
				// Index of element in level 'k'
				idx = (m >> k) * ((w + (1 << k) - 1) >> k) + (n >> k);
				// Cache state
				ts = treeS[k][idx];
				if (ts < tmin)
				{
					ts = tmin;
				}
				while (t > ts)
				{
					if (treeV[k][idx] > ts)
					{
						out_Renamed.writeBit(0); // Send '0' bit
					}
					else if (treeV[k][idx] == ts)
					{
						out_Renamed.writeBit(1); // Send '1' bit
					}
					else
					{
						// we are done: set ts and get out of this while
						ts = t;
						break;
					}
					// Increment of treeS[k][idx]
					ts++;
				}
				// Update state
				treeS[k][idx] = ts;
				// Update tmin or terminate
				if (k > 0)
				{
					tmin = ts < treeV[k][idx]?ts:treeV[k][idx];
					k--;
				}
				else
				{
					// Terminate
					return ;
				}
			}
		}
Esempio n. 2
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;
        }