1561 lines
61 KiB
C#
1561 lines
61 KiB
C#
/*
|
|
* 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.InvalidOperationException("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];
|
|
}
|
|
}
|
|
} |