CSJ2K.j2k.codestream.writer.PktEncoder.encodePacket C# (CSharp) Method

encodePacket() public method

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.

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.

public encodePacket ( int ly, int c, int r, int t, CSJ2K.j2k.entropy.encoder.CBlkRateDistStats cbs, int tIndx, CSJ2K.j2k.codestream.writer.BitOutputBuffer hbuf, byte bbuf, int pIdx ) : CSJ2K.j2k.codestream.writer.BitOutputBuffer
ly int The layer index (starts at 1). /// ///
c int The component index. /// ///
r int The resolution level /// ///
t int Index of the current tile /// ///
cbs CSJ2K.j2k.entropy.encoder.CBlkRateDistStats The 3D array of coded code-blocks. /// ///
tIndx int The truncation point indices for each code-block. /// ///
hbuf CSJ2K.j2k.codestream.writer.BitOutputBuffer The header buffer. If null a new BitOutputBuffer is created /// and returned. This buffer is reset before anything is written to it. /// ///
bbuf byte The body buffer. If null a new one is created. If not large /// enough a new one is created. /// ///
pIdx int The precinct index. /// ///
return CSJ2K.j2k.codestream.writer.BitOutputBuffer
        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;
        }