corrade-vassal – Rev 1

Subversion Repositories:
Rev:
/*
* CVS identifier:
*
* $Id: PktEncoder.java,v 1.29 2001/11/08 18:32:09 grosbois Exp $
*
* Class:                   PktEncoder
*
* Description:             Builds bit stream packets and keeps
*                          interpacket dependencies.
*
*
*
* COPYRIGHT:
* 
* This software module was originally developed by Raphaël Grosbois and
* Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
* Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
* Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
* Centre France S.A) in the course of development of the JPEG2000
* standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
* software module is an implementation of a part of the JPEG 2000
* Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
* Systems AB and Canon Research Centre France S.A (collectively JJ2000
* Partners) agree not to assert against ISO/IEC and users of the JPEG
* 2000 Standard (Users) any of their rights under the copyright, not
* including other intellectual property rights, for this software module
* with respect to the usage by ISO/IEC and Users of this software module
* or modifications thereof for use in hardware or software products
* claiming conformance to the JPEG 2000 Standard. Those intending to use
* this software module in hardware or software products are advised that
* their use may infringe existing patents. The original developers of
* this software module, JJ2000 Partners and ISO/IEC assume no liability
* for use of this software module or modifications thereof. No license
* or right to this software module is granted for non JPEG 2000 Standard
* conforming products. JJ2000 Partners have full right to use this
* software module for his/her own purpose, assign or donate this
* software module to any third party and to inhibit third parties from
* using this software module for non JPEG 2000 Standard conforming
* products. This copyright notice must be included in all copies or
* derivative works of this software module.
* 
* Copyright (c) 1999/2000 JJ2000 Partners.
* */
using System;
using CSJ2K.j2k.wavelet.analysis;
using CSJ2K.j2k.entropy.encoder;
using CSJ2K.j2k.codestream;
using CSJ2K.j2k.encoder;
using CSJ2K.j2k.wavelet;
using CSJ2K.j2k.image;
using CSJ2K.j2k.util;
using CSJ2K.j2k;
namespace CSJ2K.j2k.codestream.writer
{
        
        /// <summary> This class builds packets and keeps the state information of packet
        /// interdependencies. It also supports saving the state and reverting
        /// (restoring) to the last saved state, with the save() and restore() methods.
        /// 
        /// <p>Each time the encodePacket() method is called a new packet is encoded,
        /// the packet header is returned by the method, and the packet body can be
        /// obtained with the getLastBodyBuf() and getLastBodyLen() methods.</p>
        /// 
        /// </summary>
        public class PktEncoder
        {
                /// <summary> Returns the buffer of the body of the last encoded packet. The length
                /// of the body can be retrieved with the getLastBodyLen() method. The
                /// length of the array returned by this method may be larger than the
                /// actual body length.
                /// 
                /// </summary>
                /// <returns> The buffer of body of the last encoded packet.
                /// 
                /// </returns>
                /// <exception cref="IllegalArgumentException">If no packet has been coded since
                /// last reset(), last restore(), or object creation.
                /// 
                /// </exception>
                /// <seealso cref="getLastBodyLen">
                /// 
                /// </seealso>
                virtual public byte[] LastBodyBuf
                {
                        get
                        {
                                if (lbbuf == null)
                                {
                                        throw new System.ArgumentException();
                                }
                                return lbbuf;
                        }
                        
                }
                /// <summary> Returns the length of the body of the last encoded packet, in
                /// bytes. The body itself can be retrieved with the getLastBodyBuf()
                /// method.
                /// 
                /// </summary>
                /// <returns> The length of the body of last encoded packet, in bytes.
                /// 
                /// </returns>
                /// <seealso cref="getLastBodyBuf">
                /// 
                /// </seealso>
                virtual public int LastBodyLen
                {
                        get
                        {
                                return lblen;
                        }
                        
                }
                /// <summary> Returns true if the current packet is writable i.e. should be written.
                /// Returns false otherwise.
                /// 
                /// </summary>
                virtual public bool PacketWritable
                {
                        get
                        {
                                return packetWritable;
                        }
                        
                }
                /// <summary> Tells if there was ROI information in the last written packet 
                /// 
                /// </summary>
                virtual public bool ROIinPkt
                {
                        get
                        {
                                return roiInPkt;
                        }
                        
                }
                /// <summary>Gives the length to read in current packet body to get all ROI
                /// information 
                /// </summary>
                virtual public int ROILen
                {
                        get
                        {
                                return roiLen;
                        }
                        
                }
                /// <summary> Returns the parameters that are used in this class and implementing
                /// classes. It returns a 2D String array. Each of the 1D arrays is for a
                /// different option, and they have 3 elements. The first element is the
                /// option name, the second one is the synopsis, the third one is a long
                /// description of what the parameter is and the fourth is its default
                /// value. The synopsis or description may be 'null', in which case it is
                /// assumed that there is no synopsis or description of the option,
                /// respectively. Null may be returned if no options are supported.
                /// 
                /// </summary>
                /// <returns> the options name, their synopsis and their explanation, 
                /// or null if no options are supported.
                /// 
                /// </returns>
                public static System.String[][] ParameterInfo
                {
                        get
                        {
                                return pinfo;
                        }
                        
                }
                
                /// <summary>The prefix for packet encoding options: 'P' </summary>
                public const char OPT_PREFIX = 'P';
                
                /// <summary>The list of parameters that is accepted for packet encoding.</summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'pinfo'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                private static readonly System.String[][] pinfo = new System.String[][]{new System.String[]{"Psop", "[<tile idx>] on|off" + "[ [<tile idx>] on|off ...]", "Specifies whether start of packet (SOP) markers should be used. " + "'on' enables, 'off' disables it.", "off"}, new System.String[]{"Peph", "[<tile idx>] on|off" + "[ [<tile  idx>] on|off ...]", "Specifies whether end of packet header (EPH) markers should be " + " used. 'on' enables, 'off' disables it.", "off"}};
                
                /// <summary>The initial value for the lblock </summary>
                private const int INIT_LBLOCK = 3;
                
                /// <summary>The source object </summary>
                private CodedCBlkDataSrcEnc infoSrc;
                
                /// <summary>The encoder specs </summary>
                private EncoderSpecs encSpec;
                
                /// <summary> The tag tree for inclusion information. The indexes are outlined
                /// below. Note that the layer indexes start at 1, therefore, the layer
                /// index minus 1 is used. The subband indices are used as they are defined
                /// in the Subband class. The tile indices start at 0 and follow a
                /// lexicographical order.
                /// 
                /// <ul>
                /// <li>1st index: tile index, in lexicographical order</li>
                /// <li>2nd index: component index </li>
                /// <li>3rd index: resolution level </li>
                /// <li>4th index: precinct index </li>
                /// <li>5th index: subband index </li>
                /// </ul>
                /// 
                /// </summary>
                private TagTreeEncoder[][][][][] ttIncl;
                
                /// <summary> The tag tree for the maximum significant bit-plane. The indexes are
                /// outlined below. Note that the layer indexes start at 1, therefore, the
                /// layer index minus 1 is used. The subband indices are used as they are
                /// defined in the Subband class. The tile indices start at 0 and follow a
                /// lexicographical order.
                /// 
                /// <ul>
                /// <li>1st index: tile index, in lexicographical order</li>
                /// <li>2nd index: component index </li>
                /// <li>3rd index: resolution level </li>
                /// <li>4th index: precinct index </li>
                /// <li>5th index: subband index</li>
                /// </ul>
                /// 
                /// </summary>
                private TagTreeEncoder[][][][][] ttMaxBP;
                
                /// <summary> The base number of bits for sending code-block length information
                /// (referred as Lblock in the JPEG 2000 standard). The indexes are
                /// outlined below. Note that the layer indexes start at 1, therefore, the
                /// layer index minus 1 is used. The subband indices are used as they are
                /// defined in the Subband class. The tile indices start at 0 and follow a
                /// lexicographical order.
                /// 
                /// <ul>
                /// <li>1st index: tile index, in lexicographical order </li>
                /// <li>2nd index: component index </li>
                /// <li>3rd index: resolution level </li>
                /// <li>4th index: subband index </li>
                /// <li>5th index: code-block index, in lexicographical order</li>
                /// </ul>
                /// 
                /// </summary>
                private int[][][][][] lblock;
                
                /// <summary> The last encoded truncation point for each code-block. A negative value
                /// means that no information has been included for the block, yet. The
                /// indexes are outlined below. The subband indices are used as they are
                /// defined in the Subband class. The tile indices start at 0 and follow a
                /// lexicographical order. The code-block indices follow a lexicographical
                /// order within the subband tile.
                /// 
                /// <P>What is actually stored is the index of the element in
                /// CBlkRateDistStats.truncIdxs that gives the real truncation point.
                /// 
                /// <ul>
                /// <li>1st index: tile index, in lexicographical order </li>
                /// <li>2nd index: component index </li>
                /// <li>3rd index: resolution level </li>
                /// <li>4th index: subband index</li>
                /// <li>5th index: code-block index, in lexicographical order </li>
                /// </ul>
                /// 
                /// </summary>
                private int[][][][][] prevtIdxs;
                
                /// <summary> The saved base number of bits for sending code-block length
                /// information. It is used for restoring previous saved state by
                /// restore(). The indexes are outlined below. Note that the layer indexes
                /// start at 1, therefore, the layer index minus 1 is used. The subband
                /// indices are used as they are defined in the Subband class. The tile
                /// indices start at 0 and follow a lexicographical order.
                /// 
                /// <ul> 
                /// <li>1st index: tile index, in lexicographical order </li>
                /// <li>2nd index: component index </li>
                /// <li>3rd index: resolution level </li>
                /// <li>4th index: subband index </li>
                /// <li>5th index: code-block index, in lexicographical order</li>
                /// </ul>
                /// 
                /// </summary>
                private int[][][][][] bak_lblock;
                
                /// <summary> The saved last encoded truncation point for each code-block. It is used
                /// for restoring previous saved state by restore(). A negative value means
                /// that no information has been included for the block, yet. The indexes
                /// are outlined below. The subband indices are used as they are defined in
                /// the Subband class. The tile indices start at 0 and follow a
                /// lexicographical order. The code-block indices follow a lexicographical
                /// order within the subband tile.
                /// 
                /// <ul>
                /// <li>1st index: tile index, in lexicographical order </li>
                /// <li>2nd index: component index </li>
                /// <li>3rd index: resolution level </li>
                /// <li>4th index: subband index </li>
                /// <li>5th index: code-block index, in lexicographical order </li>
                /// </ul>
                /// 
                /// </summary>
                private int[][][][][] bak_prevtIdxs;
                
                /// <summary>The body buffer of the last encoded packet </summary>
                private byte[] lbbuf;
                
                /// <summary>The body length of the last encoded packet </summary>
                private int lblen;
                
                /// <summary>The saved state </summary>
                private bool saved;
                
                /// <summary>Whether or not there is ROI information in the last encoded Packet </summary>
                private bool roiInPkt = false;
                
                /// <summary>Length to read in current packet body to get all the ROI information </summary>
                private int roiLen = 0;
                
                /// <summary> Array containing the coordinates, width, height, indexes, ... of the
                /// precincts.
                /// 
                /// <ul>
                /// <li> 1st dim: tile index.</li>
                /// <li> 2nd dim: component index.</li>
                /// <li> 3rd dim: resolution level index.</li>
                /// <li> 4th dim: precinct index.</li>
                /// </ul> 
                /// 
                /// </summary>
                private PrecInfo[][][][] ppinfo;
                
                /// <summary>Whether or not the current packet is writable </summary>
                private bool packetWritable;
                
                /// <summary> Creates a new packet encoder object, using the information from the
                /// 'infoSrc' object. 
                /// 
                /// </summary>
                /// <param name="infoSrc">The source of information to construct the object.
                /// 
                /// </param>
                /// <param name="encSpec">The encoding parameters.
                /// 
                /// </param>
                /// <param name="numPrec">Maximum number of precincts in each tile, component
                /// and resolution level.
                /// 
                /// </param>
                /// <param name="pl">ParameterList instance that holds command line options
                /// 
                /// </param>
                public PktEncoder(CodedCBlkDataSrcEnc infoSrc, EncoderSpecs encSpec, Coord[][][] numPrec, ParameterList pl)
                {
                        this.infoSrc = infoSrc;
                        this.encSpec = encSpec;
                        
                        // Check parameters
                        pl.checkList(OPT_PREFIX, CSJ2K.j2k.util.ParameterList.toNameArray(pinfo));
                        
                        // Get number of components and tiles
                        int nc = infoSrc.NumComps;
                        int nt = infoSrc.getNumTiles();
                        
                        // Do initial allocation
                        ttIncl = new TagTreeEncoder[nt][][][][];
                        for (int i = 0; i < nt; i++)
                        {
                                ttIncl[i] = new TagTreeEncoder[nc][][][];
                        }
                        ttMaxBP = new TagTreeEncoder[nt][][][][];
                        for (int i2 = 0; i2 < nt; i2++)
                        {
                                ttMaxBP[i2] = new TagTreeEncoder[nc][][][];
                        }
                        lblock = new int[nt][][][][];
                        for (int i3 = 0; i3 < nt; i3++)
                        {
                                lblock[i3] = new int[nc][][][];
                        }
                        prevtIdxs = new int[nt][][][][];
                        for (int i4 = 0; i4 < nt; i4++)
                        {
                                prevtIdxs[i4] = new int[nc][][][];
                        }
                        ppinfo = new PrecInfo[nt][][][];
                        for (int i5 = 0; i5 < nt; i5++)
                        {
                                ppinfo[i5] = new PrecInfo[nc][][];
                        }
                        
                        // Finish allocation
                        SubbandAn root, sb;
                        int maxs, mins;
                        int mrl;
                        //Coord tmpCoord = null;
                        int numcb; // Number of code-blocks
                        //System.Collections.ArrayList cblks = null;
                        infoSrc.setTile(0, 0);
                        for (int t = 0; t < nt; t++)
                        {
                                // Loop on tiles
                                for (int c = 0; c < nc; c++)
                                {
                                        // Loop on components
                                        // Get number of resolution levels
                                        root = infoSrc.getAnSubbandTree(t, c);
                                        mrl = root.resLvl;
                                        
                                        lblock[t][c] = new int[mrl + 1][][];
                                        ttIncl[t][c] = new TagTreeEncoder[mrl + 1][][];
                                        ttMaxBP[t][c] = new TagTreeEncoder[mrl + 1][][];
                                        prevtIdxs[t][c] = new int[mrl + 1][][];
                                        ppinfo[t][c] = new PrecInfo[mrl + 1][];
                                        
                                        for (int r = 0; r <= mrl; r++)
                                        {
                                                // Loop on resolution levels
                                                mins = (r == 0)?0:1;
                                                maxs = (r == 0)?1:4;
                                                
                                                int maxPrec = numPrec[t][c][r].x * numPrec[t][c][r].y;
                                                
                                                ttIncl[t][c][r] = new TagTreeEncoder[maxPrec][];
                                                for (int i6 = 0; i6 < maxPrec; i6++)
                                                {
                                                        ttIncl[t][c][r][i6] = new TagTreeEncoder[maxs];
                                                }
                                                ttMaxBP[t][c][r] = new TagTreeEncoder[maxPrec][];
                                                for (int i7 = 0; i7 < maxPrec; i7++)
                                                {
                                                        ttMaxBP[t][c][r][i7] = new TagTreeEncoder[maxs];
                                                }
                                                prevtIdxs[t][c][r] = new int[maxs][];
                                                lblock[t][c][r] = new int[maxs][];
                                                
                                                // Precincts and code-blocks
                                                ppinfo[t][c][r] = new PrecInfo[maxPrec];
                                                fillPrecInfo(t, c, r);
                                                
                                                for (int s = mins; s < maxs; s++)
                                                {
                                                        // Loop on subbands
                                                        sb = (SubbandAn) root.getSubbandByIdx(r, s);
                                                        numcb = sb.numCb.x * sb.numCb.y;
                                                        
                                                        lblock[t][c][r][s] = new int[numcb];
                                                        ArrayUtil.intArraySet(lblock[t][c][r][s], INIT_LBLOCK);
                                                        
                                                        prevtIdxs[t][c][r][s] = new int[numcb];
                                                        ArrayUtil.intArraySet(prevtIdxs[t][c][r][s], - 1);
                                                }
                                        }
                                }
                                if (t != nt - 1)
                                        infoSrc.nextTile();
                        }
                }
                
                /// <summary> Retrives precincts and code-blocks coordinates in the given resolution,
                /// component and tile. It terminates TagTreeEncoder initialization as
                /// well.
                /// 
                /// </summary>
                /// <param name="t">Tile index.
                /// 
                /// </param>
                /// <param name="c">Component index.
                /// 
                /// </param>
                /// <param name="r">Resolution level index.
                /// 
                /// </param>
                private void  fillPrecInfo(int t, int c, int r)
                {
                        if (ppinfo[t][c][r].Length == 0)
                                return ; // No precinct in this
                        // resolution level
                        
                        Coord tileI = infoSrc.getTile(null);
                        Coord nTiles = infoSrc.getNumTiles(null);
                        
                        int x0siz = infoSrc.ImgULX;
                        int y0siz = infoSrc.ImgULY;
                        int xsiz = x0siz + infoSrc.ImgWidth;
                        int ysiz = y0siz + infoSrc.ImgHeight;
                        int xt0siz = infoSrc.TilePartULX;
                        int yt0siz = infoSrc.TilePartULY;
                        int xtsiz = infoSrc.NomTileWidth;
                        int ytsiz = infoSrc.NomTileHeight;
                        
                        int tx0 = (tileI.x == 0)?x0siz:xt0siz + tileI.x * xtsiz;
                        int ty0 = (tileI.y == 0)?y0siz:yt0siz + tileI.y * ytsiz;
                        int tx1 = (tileI.x != nTiles.x - 1)?xt0siz + (tileI.x + 1) * xtsiz:xsiz;
                        int ty1 = (tileI.y != nTiles.y - 1)?yt0siz + (tileI.y + 1) * ytsiz:ysiz;
                        
                        int xrsiz = infoSrc.getCompSubsX(c);
                        int yrsiz = infoSrc.getCompSubsY(c);
                        
                        //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'"
                        int 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'"
                        int 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'"
                        int 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'"
                        int tcy1 = (int) System.Math.Ceiling(ty1 / (double) (yrsiz));
                        
                        int ndl = infoSrc.getAnSubbandTree(t, c).resLvl - 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'"
                        int trx0 = (int) System.Math.Ceiling(tcx0 / (double) (1 << ndl));
                        //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'"
                        int try0 = (int) System.Math.Ceiling(tcy0 / (double) (1 << ndl));
                        //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'"
                        int trx1 = (int) System.Math.Ceiling(tcx1 / (double) (1 << ndl));
                        //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'"
                        int try1 = (int) System.Math.Ceiling(tcy1 / (double) (1 << ndl));
                        
                        int cb0x = infoSrc.CbULX;
                        int cb0y = infoSrc.CbULY;
                        
                        double twoppx = (double) encSpec.pss.getPPX(t, c, r);
                        double twoppy = (double) encSpec.pss.getPPY(t, c, 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'"
                        int twoppx2 = (int) (twoppx / 2);
                        //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'"
                        int twoppy2 = (int) (twoppy / 2);
                        
                        // Precincts are located at (cb0x+i*twoppx,cb0y+j*twoppy)
                        // Valid precincts are those which intersect with the current
                        // resolution level
                        int maxPrec = ppinfo[t][c][r].Length;
                        int nPrec = 0;
                        
                        //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'"
                        int istart = (int) System.Math.Floor((try0 - cb0y) / twoppy);
                        //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'"
                        int iend = (int) System.Math.Floor((try1 - 1 - cb0y) / twoppy);
                        //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'"
                        int jstart = (int) System.Math.Floor((trx0 - cb0x) / twoppx);
                        //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'"
                        int jend = (int) System.Math.Floor((trx1 - 1 - cb0x) / twoppx);
                        
                        int acb0x, acb0y;
                        
                        SubbandAn root = infoSrc.getAnSubbandTree(t, c);
                        SubbandAn sb = null;
                        
                        int p0x, p0y, p1x, p1y; // Precinct projection in subband
                        int s0x, s0y, s1x, s1y; // Active subband portion
                        int cw, ch;
                        int kstart, kend, lstart, lend, k0, l0;
                        int prg_ulx, prg_uly;
                        //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'"
                        int prg_w = (int) twoppx << ndl;
                        //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'"
                        int prg_h = (int) twoppy << ndl;
                        
                        CBlkCoordInfo cb;
                        
                        for (int i = istart; i <= iend; i++)
                        {
                                // Vertical precincts
                                for (int j = jstart; j <= jend; j++, nPrec++)
                                {
                                        // Horizontal precincts
                                        //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'"
                                        if (j == jstart && (trx0 - cb0x) % (xrsiz * ((int) twoppx)) != 0)
                                        {
                                                prg_ulx = tx0;
                                        }
                                        else
                                        {
                                                //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'"
                                                prg_ulx = cb0x + j * xrsiz * ((int) twoppx << ndl);
                                        }
                                        //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'"
                                        if (i == istart && (try0 - cb0y) % (yrsiz * ((int) twoppy)) != 0)
                                        {
                                                prg_uly = ty0;
                                        }
                                        else
                                        {
                                                //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'"
                                                prg_uly = cb0y + i * yrsiz * ((int) twoppy << ndl);
                                        }
                                        
                                        //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'"
                                        ppinfo[t][c][r][nPrec] = new PrecInfo(r, (int) (cb0x + j * twoppx), (int) (cb0y + i * twoppy), (int) twoppx, (int) twoppy, prg_ulx, prg_uly, prg_w, prg_h);
                                        
                                        if (r == 0)
                                        {
                                                // LL subband
                                                acb0x = cb0x;
                                                acb0y = cb0y;
                                                
                                                //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'"
                                                p0x = acb0x + j * (int) twoppx;
                                                //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'"
                                                p1x = p0x + (int) twoppx;
                                                //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'"
                                                p0y = acb0y + i * (int) twoppy;
                                                //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'"
                                                p1y = p0y + (int) twoppy;
                                                
                                                sb = (SubbandAn) root.getSubbandByIdx(0, 0);
                                                s0x = (p0x < sb.ulcx)?sb.ulcx:p0x;
                                                s1x = (p1x > sb.ulcx + sb.w)?sb.ulcx + sb.w:p1x;
                                                s0y = (p0y < sb.ulcy)?sb.ulcy:p0y;
                                                s1y = (p1y > sb.ulcy + sb.h)?sb.ulcy + sb.h:p1y;
                                                
                                                // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch)
                                                cw = sb.nomCBlkW;
                                                ch = sb.nomCBlkH;
                                                //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'"
                                                k0 = (int) System.Math.Floor((sb.ulcy - acb0y) / (double) ch);
                                                //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'"
                                                kstart = (int) System.Math.Floor((s0y - acb0y) / (double) ch);
                                                //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'"
                                                kend = (int) System.Math.Floor((s1y - 1 - acb0y) / (double) ch);
                                                //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'"
                                                l0 = (int) System.Math.Floor((sb.ulcx - acb0x) / (double) cw);
                                                //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'"
                                                lstart = (int) System.Math.Floor((s0x - acb0x) / (double) cw);
                                                //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'"
                                                lend = (int) System.Math.Floor((s1x - 1 - acb0x) / (double) cw);
                                                
                                                if (s1x - s0x <= 0 || s1y - s0y <= 0)
                                                {
                                                        ppinfo[t][c][r][nPrec].nblk[0] = 0;
                                                        ttIncl[t][c][r][nPrec][0] = new TagTreeEncoder(0, 0);
                                                        ttMaxBP[t][c][r][nPrec][0] = new TagTreeEncoder(0, 0);
                                                }
                                                else
                                                {
                                                        ttIncl[t][c][r][nPrec][0] = new TagTreeEncoder(kend - kstart + 1, lend - lstart + 1);
                                                        ttMaxBP[t][c][r][nPrec][0] = new TagTreeEncoder(kend - kstart + 1, lend - lstart + 1);
                                                        CBlkCoordInfo[][] tmpArray = new CBlkCoordInfo[kend - kstart + 1][];
                                                        for (int i2 = 0; i2 < kend - kstart + 1; i2++)
                                                        {
                                                                tmpArray[i2] = new CBlkCoordInfo[lend - lstart + 1];
                                                        }
                                                        ppinfo[t][c][r][nPrec].cblk[0] = tmpArray;
                                                        ppinfo[t][c][r][nPrec].nblk[0] = (kend - kstart + 1) * (lend - lstart + 1);
                                                        
                                                        for (int k = kstart; k <= kend; k++)
                                                        {
                                                                // Vertical cblks
                                                                for (int l = lstart; l <= lend; l++)
                                                                {
                                                                        // Horiz. cblks
                                                                        
                                                                        cb = new CBlkCoordInfo(k - k0, l - l0);
                                                                        ppinfo[t][c][r][nPrec].cblk[0][k - kstart][l - lstart] = cb;
                                                                } // Horizontal code-blocks
                                                        } // Vertical code-blocks
                                                }
                                        }
                                        else
                                        {
                                                // HL, LH and HH subbands
                                                // HL subband
                                                acb0x = 0;
                                                acb0y = cb0y;
                                                
                                                p0x = acb0x + j * twoppx2;
                                                p1x = p0x + twoppx2;
                                                p0y = acb0y + i * twoppy2;
                                                p1y = p0y + twoppy2;
                                                
                                                sb = (SubbandAn) root.getSubbandByIdx(r, 1);
                                                s0x = (p0x < sb.ulcx)?sb.ulcx:p0x;
                                                s1x = (p1x > sb.ulcx + sb.w)?sb.ulcx + sb.w:p1x;
                                                s0y = (p0y < sb.ulcy)?sb.ulcy:p0y;
                                                s1y = (p1y > sb.ulcy + sb.h)?sb.ulcy + sb.h:p1y;
                                                
                                                // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch)
                                                cw = sb.nomCBlkW;
                                                ch = sb.nomCBlkH;
                                                //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'"
                                                k0 = (int) System.Math.Floor((sb.ulcy - acb0y) / (double) ch);
                                                //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'"
                                                kstart = (int) System.Math.Floor((s0y - acb0y) / (double) ch);
                                                //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'"
                                                kend = (int) System.Math.Floor((s1y - 1 - acb0y) / (double) ch);
                                                //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'"
                                                l0 = (int) System.Math.Floor((sb.ulcx - acb0x) / (double) cw);
                                                //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'"
                                                lstart = (int) System.Math.Floor((s0x - acb0x) / (double) cw);
                                                //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'"
                                                lend = (int) System.Math.Floor((s1x - 1 - acb0x) / (double) cw);
                                                
                                                if (s1x - s0x <= 0 || s1y - s0y <= 0)
                                                {
                                                        ppinfo[t][c][r][nPrec].nblk[1] = 0;
                                                        ttIncl[t][c][r][nPrec][1] = new TagTreeEncoder(0, 0);
                                                        ttMaxBP[t][c][r][nPrec][1] = new TagTreeEncoder(0, 0);
                                                }
                                                else
                                                {
                                                        ttIncl[t][c][r][nPrec][1] = new TagTreeEncoder(kend - kstart + 1, lend - lstart + 1);
                                                        ttMaxBP[t][c][r][nPrec][1] = new TagTreeEncoder(kend - kstart + 1, lend - lstart + 1);
                                                        CBlkCoordInfo[][] tmpArray2 = new CBlkCoordInfo[kend - kstart + 1][];
                                                        for (int i3 = 0; i3 < kend - kstart + 1; i3++)
                                                        {
                                                                tmpArray2[i3] = new CBlkCoordInfo[lend - lstart + 1];
                                                        }
                                                        ppinfo[t][c][r][nPrec].cblk[1] = tmpArray2;
                                                        ppinfo[t][c][r][nPrec].nblk[1] = (kend - kstart + 1) * (lend - lstart + 1);
                                                        
                                                        for (int k = kstart; k <= kend; k++)
                                                        {
                                                                // Vertical cblks
                                                                for (int l = lstart; l <= lend; l++)
                                                                {
                                                                        // Horiz. cblks
                                                                        cb = new CBlkCoordInfo(k - k0, l - l0);
                                                                        ppinfo[t][c][r][nPrec].cblk[1][k - kstart][l - lstart] = cb;
                                                                } // Horizontal code-blocks
                                                        } // Vertical code-blocks
                                                }
                                                
                                                // LH subband
                                                acb0x = cb0x;
                                                acb0y = 0;
                                                
                                                p0x = acb0x + j * twoppx2;
                                                p1x = p0x + twoppx2;
                                                p0y = acb0y + i * twoppy2;
                                                p1y = p0y + twoppy2;
                                                
                                                sb = (SubbandAn) root.getSubbandByIdx(r, 2);
                                                s0x = (p0x < sb.ulcx)?sb.ulcx:p0x;
                                                s1x = (p1x > sb.ulcx + sb.w)?sb.ulcx + sb.w:p1x;
                                                s0y = (p0y < sb.ulcy)?sb.ulcy:p0y;
                                                s1y = (p1y > sb.ulcy + sb.h)?sb.ulcy + sb.h:p1y;
                                                
                                                // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch)
                                                cw = sb.nomCBlkW;
                                                ch = sb.nomCBlkH;
                                                //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'"
                                                k0 = (int) System.Math.Floor((sb.ulcy - acb0y) / (double) ch);
                                                //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'"
                                                kstart = (int) System.Math.Floor((s0y - acb0y) / (double) ch);
                                                //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'"
                                                kend = (int) System.Math.Floor((s1y - 1 - acb0y) / (double) ch);
                                                //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'"
                                                l0 = (int) System.Math.Floor((sb.ulcx - acb0x) / (double) cw);
                                                //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'"
                                                lstart = (int) System.Math.Floor((s0x - acb0x) / (double) cw);
                                                //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'"
                                                lend = (int) System.Math.Floor((s1x - 1 - acb0x) / (double) cw);
                                                
                                                if (s1x - s0x <= 0 || s1y - s0y <= 0)
                                                {
                                                        ppinfo[t][c][r][nPrec].nblk[2] = 0;
                                                        ttIncl[t][c][r][nPrec][2] = new TagTreeEncoder(0, 0);
                                                        ttMaxBP[t][c][r][nPrec][2] = new TagTreeEncoder(0, 0);
                                                }
                                                else
                                                {
                                                        ttIncl[t][c][r][nPrec][2] = new TagTreeEncoder(kend - kstart + 1, lend - lstart + 1);
                                                        ttMaxBP[t][c][r][nPrec][2] = new TagTreeEncoder(kend - kstart + 1, lend - lstart + 1);
                                                        CBlkCoordInfo[][] tmpArray3 = new CBlkCoordInfo[kend - kstart + 1][];
                                                        for (int i4 = 0; i4 < kend - kstart + 1; i4++)
                                                        {
                                                                tmpArray3[i4] = new CBlkCoordInfo[lend - lstart + 1];
                                                        }
                                                        ppinfo[t][c][r][nPrec].cblk[2] = tmpArray3;
                                                        ppinfo[t][c][r][nPrec].nblk[2] = (kend - kstart + 1) * (lend - lstart + 1);
                                                        
                                                        for (int k = kstart; k <= kend; k++)
                                                        {
                                                                // Vertical cblks
                                                                for (int l = lstart; l <= lend; l++)
                                                                {
                                                                        // Horiz cblks
                                                                        cb = new CBlkCoordInfo(k - k0, l - l0);
                                                                        ppinfo[t][c][r][nPrec].cblk[2][k - kstart][l - lstart] = cb;
                                                                } // Horizontal code-blocks
                                                        } // Vertical code-blocks
                                                }
                                                
                                                // HH subband
                                                acb0x = 0;
                                                acb0y = 0;
                                                
                                                p0x = acb0x + j * twoppx2;
                                                p1x = p0x + twoppx2;
                                                p0y = acb0y + i * twoppy2;
                                                p1y = p0y + twoppy2;
                                                
                                                sb = (SubbandAn) root.getSubbandByIdx(r, 3);
                                                s0x = (p0x < sb.ulcx)?sb.ulcx:p0x;
                                                s1x = (p1x > sb.ulcx + sb.w)?sb.ulcx + sb.w:p1x;
                                                s0y = (p0y < sb.ulcy)?sb.ulcy:p0y;
                                                s1y = (p1y > sb.ulcy + sb.h)?sb.ulcy + sb.h:p1y;
                                                
                                                // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch)
                                                cw = sb.nomCBlkW;
                                                ch = sb.nomCBlkH;
                                                //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'"
                                                k0 = (int) System.Math.Floor((sb.ulcy - acb0y) / (double) ch);
                                                //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'"
                                                kstart = (int) System.Math.Floor((s0y - acb0y) / (double) ch);
                                                //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'"
                                                kend = (int) System.Math.Floor((s1y - 1 - acb0y) / (double) ch);
                                                //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'"
                                                l0 = (int) System.Math.Floor((sb.ulcx - acb0x) / (double) cw);
                                                //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'"
                                                lstart = (int) System.Math.Floor((s0x - acb0x) / (double) cw);
                                                //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'"
                                                lend = (int) System.Math.Floor((s1x - 1 - acb0x) / (double) cw);
                                                
                                                if (s1x - s0x <= 0 || s1y - s0y <= 0)
                                                {
                                                        ppinfo[t][c][r][nPrec].nblk[3] = 0;
                                                        ttIncl[t][c][r][nPrec][3] = new TagTreeEncoder(0, 0);
                                                        ttMaxBP[t][c][r][nPrec][3] = new TagTreeEncoder(0, 0);
                                                }
                                                else
                                                {
                                                        ttIncl[t][c][r][nPrec][3] = new TagTreeEncoder(kend - kstart + 1, lend - lstart + 1);
                                                        ttMaxBP[t][c][r][nPrec][3] = new TagTreeEncoder(kend - kstart + 1, lend - lstart + 1);
                                                        CBlkCoordInfo[][] tmpArray4 = new CBlkCoordInfo[kend - kstart + 1][];
                                                        for (int i5 = 0; i5 < kend - kstart + 1; i5++)
                                                        {
                                                                tmpArray4[i5] = new CBlkCoordInfo[lend - lstart + 1];
                                                        }
                                                        ppinfo[t][c][r][nPrec].cblk[3] = tmpArray4;
                                                        ppinfo[t][c][r][nPrec].nblk[3] = (kend - kstart + 1) * (lend - lstart + 1);
                                                        
                                                        for (int k = kstart; k <= kend; k++)
                                                        {
                                                                // Vertical cblks
                                                                for (int l = lstart; l <= lend; l++)
                                                                {
                                                                        // Horiz cblks
                                                                        cb = new CBlkCoordInfo(k - k0, l - l0);
                                                                        ppinfo[t][c][r][nPrec].cblk[3][k - kstart][l - lstart] = cb;
                                                                } // Horizontal code-blocks
                                                        } // Vertical code-blocks
                                                }
                                        }
                                } // Horizontal precincts
                        } // Vertical precincts
                }
                
                /// <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.ApplicationException("You have found a bug in PktEncoder, method:" + " encodePacket");
                        }
                        
                        return hbuf;
                }
                
                /// <summary> Saves the current state of this object. The last saved state
                /// can be restored with the restore() method.
                /// 
                /// </summary>
                /// <seealso cref="restore">
                /// 
                /// </seealso>
                public virtual void  save()
                {
                        int maxsbi, minsbi;
                        
                        // Have we done any save yet?
                        if (bak_lblock == null)
                        {
                                // Allocate backup buffers
                                bak_lblock = new int[ttIncl.Length][][][][];
                                bak_prevtIdxs = new int[ttIncl.Length][][][][];
                                for (int t = ttIncl.Length - 1; t >= 0; t--)
                                {
                                        bak_lblock[t] = new int[ttIncl[t].Length][][][];
                                        bak_prevtIdxs[t] = new int[ttIncl[t].Length][][][];
                                        for (int c = ttIncl[t].Length - 1; c >= 0; c--)
                                        {
                                                bak_lblock[t][c] = new int[lblock[t][c].Length][][];
                                                bak_prevtIdxs[t][c] = new int[ttIncl[t][c].Length][][];
                                                for (int r = lblock[t][c].Length - 1; r >= 0; r--)
                                                {
                                                        bak_lblock[t][c][r] = new int[lblock[t][c][r].Length][];
                                                        bak_prevtIdxs[t][c][r] = new int[prevtIdxs[t][c][r].Length][];
                                                        minsbi = (r == 0)?0:1;
                                                        maxsbi = (r == 0)?1:4;
                                                        for (int s = minsbi; s < maxsbi; s++)
                                                        {
                                                                bak_lblock[t][c][r][s] = new int[lblock[t][c][r][s].Length];
                                                                bak_prevtIdxs[t][c][r][s] = new int[prevtIdxs[t][c][r][s].Length];
                                                        }
                                                }
                                        }
                                }
                        }
                        
                        //-- Save the data
                        
                        // Use reference caches to minimize array access overhead
                        TagTreeEncoder[][][] ttIncl_t_c, ttMaxBP_t_c;
                        TagTreeEncoder[][] ttIncl_t_c_r, ttMaxBP_t_c_r;
                        int[][][] lblock_t_c, bak_lblock_t_c;
                        int[][] prevtIdxs_t_c_r, bak_prevtIdxs_t_c_r;
                        
                        // Loop on tiles
                        for (int t = ttIncl.Length - 1; t >= 0; t--)
                        {
                                // Loop on components
                                for (int c = ttIncl[t].Length - 1; c >= 0; c--)
                                {
                                        // Initialize reference caches
                                        lblock_t_c = lblock[t][c];
                                        bak_lblock_t_c = bak_lblock[t][c];
                                        ttIncl_t_c = ttIncl[t][c];
                                        ttMaxBP_t_c = ttMaxBP[t][c];
                                        // Loop on resolution levels
                                        for (int r = lblock_t_c.Length - 1; r >= 0; r--)
                                        {
                                                // Initialize reference caches
                                                ttIncl_t_c_r = ttIncl_t_c[r];
                                                ttMaxBP_t_c_r = ttMaxBP_t_c[r];
                                                prevtIdxs_t_c_r = prevtIdxs[t][c][r];
                                                bak_prevtIdxs_t_c_r = bak_prevtIdxs[t][c][r];
                                                
                                                // Loop on subbands
                                                minsbi = (r == 0)?0:1;
                                                maxsbi = (r == 0)?1:4;
                                                for (int s = minsbi; s < maxsbi; s++)
                                                {
                                                        // Save 'lblock'
                                                        Array.Copy(lblock_t_c[r][s], 0, bak_lblock_t_c[r][s], 0, lblock_t_c[r][s].Length);
                                                        // Save 'prevtIdxs'
                                                        Array.Copy(prevtIdxs_t_c_r[s], 0, bak_prevtIdxs_t_c_r[s], 0, prevtIdxs_t_c_r[s].Length);
                                                } // End loop on subbands
                                                
                                                // Loop on precincts
                                                for (int p = ppinfo[t][c][r].Length - 1; p >= 0; p--)
                                                {
                                                        if (p < ttIncl_t_c_r.Length)
                                                        {
                                                                // Loop on subbands
                                                                for (int s = minsbi; s < maxsbi; s++)
                                                                {
                                                                        ttIncl_t_c_r[p][s].save();
                                                                        ttMaxBP_t_c_r[p][s].save();
                                                                } // End loop on subbands
                                                        }
                                                } // End loop on precincts
                                        } // End loop on resolutions
                                } // End loop on components
                        } // End loop on tiles
                        
                        // Set the saved state
                        saved = true;
                }
                
                /// <summary> Restores the last saved state of this object. An
                /// IllegalArgumentException is thrown if no state has been saved.
                /// 
                /// </summary>
                /// <seealso cref="save">
                /// 
                /// </seealso>
                public virtual void  restore()
                {
                        int maxsbi, minsbi;
                        
                        if (!saved)
                        {
                                throw new System.ArgumentException();
                        }
                        
                        // Invalidate last encoded body buffer
                        lbbuf = null;
                        
                        //-- Restore tha data
                        
                        // Use reference caches to minimize array access overhead
                        TagTreeEncoder[][][] ttIncl_t_c, ttMaxBP_t_c;
                        TagTreeEncoder[][] ttIncl_t_c_r, ttMaxBP_t_c_r;
                        int[][][] lblock_t_c, bak_lblock_t_c;
                        int[][] prevtIdxs_t_c_r, bak_prevtIdxs_t_c_r;
                        
                        // Loop on tiles
                        for (int t = ttIncl.Length - 1; t >= 0; t--)
                        {
                                // Loop on components
                                for (int c = ttIncl[t].Length - 1; c >= 0; c--)
                                {
                                        // Initialize reference caches
                                        lblock_t_c = lblock[t][c];
                                        bak_lblock_t_c = bak_lblock[t][c];
                                        ttIncl_t_c = ttIncl[t][c];
                                        ttMaxBP_t_c = ttMaxBP[t][c];
                                        // Loop on resolution levels
                                        for (int r = lblock_t_c.Length - 1; r >= 0; r--)
                                        {
                                                // Initialize reference caches
                                                ttIncl_t_c_r = ttIncl_t_c[r];
                                                ttMaxBP_t_c_r = ttMaxBP_t_c[r];
                                                prevtIdxs_t_c_r = prevtIdxs[t][c][r];
                                                bak_prevtIdxs_t_c_r = bak_prevtIdxs[t][c][r];
                                                
                                                // Loop on subbands
                                                minsbi = (r == 0)?0:1;
                                                maxsbi = (r == 0)?1:4;
                                                for (int s = minsbi; s < maxsbi; s++)
                                                {
                                                        // Restore 'lblock'
                                                        Array.Copy(bak_lblock_t_c[r][s], 0, lblock_t_c[r][s], 0, lblock_t_c[r][s].Length);
                                                        // Restore 'prevtIdxs'
                                                        Array.Copy(bak_prevtIdxs_t_c_r[s], 0, prevtIdxs_t_c_r[s], 0, prevtIdxs_t_c_r[s].Length);
                                                } // End loop on subbands
                                                
                                                // Loop on precincts
                                                for (int p = ppinfo[t][c][r].Length - 1; p >= 0; p--)
                                                {
                                                        if (p < ttIncl_t_c_r.Length)
                                                        {
                                                                // Loop on subbands
                                                                for (int s = minsbi; s < maxsbi; s++)
                                                                {
                                                                        ttIncl_t_c_r[p][s].restore();
                                                                        ttMaxBP_t_c_r[p][s].restore();
                                                                } // End loop on subbands
                                                        }
                                                } // End loop on precincts
                                        } // End loop on resolution levels
                                } // End loop on components
                        } // End loop on tiles
                }
                
                /// <summary> Resets the state of the object to the initial state, as if the object
                /// was just created.
                /// 
                /// </summary>
                public virtual void  reset()
                {
                        int maxsbi, minsbi;
                        
                        // Invalidate save
                        saved = false;
                        // Invalidate last encoded body buffer
                        lbbuf = null;
                        
                        // Reinitialize each element in the arrays
                        
                        // Use reference caches to minimize array access overhead
                        TagTreeEncoder[][][] ttIncl_t_c, ttMaxBP_t_c;
                        TagTreeEncoder[][] ttIncl_t_c_r, ttMaxBP_t_c_r;
                        int[][][] lblock_t_c;
                        int[][] prevtIdxs_t_c_r;
                        
                        // Loop on tiles
                        for (int t = ttIncl.Length - 1; t >= 0; t--)
                        {
                                // Loop on components
                                for (int c = ttIncl[t].Length - 1; c >= 0; c--)
                                {
                                        // Initialize reference caches
                                        lblock_t_c = lblock[t][c];
                                        ttIncl_t_c = ttIncl[t][c];
                                        ttMaxBP_t_c = ttMaxBP[t][c];
                                        // Loop on resolution levels
                                        for (int r = lblock_t_c.Length - 1; r >= 0; r--)
                                        {
                                                // Initialize reference caches
                                                ttIncl_t_c_r = ttIncl_t_c[r];
                                                ttMaxBP_t_c_r = ttMaxBP_t_c[r];
                                                prevtIdxs_t_c_r = prevtIdxs[t][c][r];
                                                
                                                // Loop on subbands
                                                minsbi = (r == 0)?0:1;
                                                maxsbi = (r == 0)?1:4;
                                                for (int s = minsbi; s < maxsbi; s++)
                                                {
                                                        // Reset 'prevtIdxs'
                                                        ArrayUtil.intArraySet(prevtIdxs_t_c_r[s], - 1);
                                                        // Reset 'lblock'
                                                        ArrayUtil.intArraySet(lblock_t_c[r][s], INIT_LBLOCK);
                                                } // End loop on subbands
                                                
                                                // Loop on precincts
                                                for (int p = ppinfo[t][c][r].Length - 1; p >= 0; p--)
                                                {
                                                        if (p < ttIncl_t_c_r.Length)
                                                        {
                                                                // Loop on subbands
                                                                for (int s = minsbi; s < maxsbi; s++)
                                                                {
                                                                        ttIncl_t_c_r[p][s].reset();
                                                                        ttMaxBP_t_c_r[p][s].reset();
                                                                } // End loop on subbands
                                                        }
                                                } // End loop on precincts
                                        } // End loop on resolution levels
                                } // End loop on components
                        } // End loop on tiles
                }
                
                /// <summary> Returns information about a given precinct
                /// 
                /// </summary>
                /// <param name="t">Tile index.
                /// 
                /// </param>
                /// <param name="c">Component index.
                /// 
                /// </param>
                /// <param name="r">Resolution level index.
                /// 
                /// </param>
                /// <param name="p">Precinct index
                /// 
                /// </param>
                public virtual PrecInfo getPrecInfo(int t, int c, int r, int p)
                {
                        return ppinfo[t][c][r][p];
                }
        }
}

Generated by GNU Enscript 1.6.5.90.