/// CVS identifier: /// /// $Id: PktDecoder.java,v 1.46 2002/07/19 12:35:14 grosbois Exp $ /// /// Class: PktDecoder /// /// Description: Reads packets heads and keeps location of /// code-blocks' codewords /// /// /// /// 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.synthesis; using CSJ2K.j2k.codestream; using CSJ2K.j2k.entropy; using CSJ2K.j2k.wavelet; using CSJ2K.j2k.decoder; using CSJ2K.j2k.image; using CSJ2K.j2k.util; using CSJ2K.j2k.io; namespace CSJ2K.j2k.codestream.reader { /// This class is used to read packet's head and body. All the members must be /// re-initialized at the beginning of each tile thanks to the restart() /// method. /// /// public class PktDecoder { /// Reference to the codestream reader agent private BitstreamReaderAgent src; /// Flag indicating whether packed packet header was used for this tile private bool pph = false; /// The packed packet header if it was used private System.IO.MemoryStream pphbais; /// Reference to decoder specifications private DecoderSpecs decSpec; /// Reference to the HeaderDecoder private HeaderDecoder hd; /// Initial value of the state variable associated with code-block /// length. /// //UPGRADE_NOTE: Final was removed from the declaration of 'INIT_LBLOCK '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" private int INIT_LBLOCK = 3; /// The wrapper to read bits for the packet heads private PktHeaderBitReader bin; /// Reference to the stream where to read from private RandomAccessIO ehs; /// Maximum number of precincts : /// /// /// /// private Coord[][] numPrec; /// Index of the current tile private int tIdx; /// Array containing the coordinates, width, height, indexes, ... of the /// precincts in the current tile: /// /// /// /// private PrecInfo[][][] ppinfo; /// Lblock value used to read code size information in each packet head: /// /// /// /// private int[][][][][] lblock; /// Tag tree used to read inclusion informations in packet's head: /// /// private TagTreeDecoder[][][][] ttIncl; /// Tag tree used to read bit-depth information in packet's head: /// /// /// /// private TagTreeDecoder[][][][] ttMaxBP; /// Number of layers in t he current tile private int nl = 0; /// The number of components private int nc; /// Whether or not SOP marker segment are used private bool sopUsed = false; /// Whether or not EPH marker are used private bool ephUsed = false; /// Index of the current packet in the tile. Used with SOP marker segment /// /// private int pktIdx; /// List of code-blocks found in last read packet head (one list /// per subband) /// private System.Collections.ArrayList[] cblks; /// Number of codeblocks encountered. used for ncb quit condition private int ncb; /// Maximum number of codeblocks to read before ncb quit condition is /// reached /// private int maxCB; /// Flag indicating whether ncb quit condition has been reached private bool ncbQuit; /// The tile in which the ncb quit condition was reached private int tQuit; /// The component in which the ncb quit condition was reached private int cQuit; /// The subband in which the ncb quit condition was reached private int sQuit; /// The resolution in which the ncb quit condition was reached private int rQuit; /// The x position of the last code block before ncb quit reached private int xQuit; /// The y position of the last code block before ncb quit reached private int yQuit; /// True if truncation mode is used. False if it is parsing mode private bool isTruncMode; /// Creates an empty PktDecoder object associated with given decoder /// specifications and HeaderDecoder. This object must be initialized /// thanks to the restart method before being used. /// /// /// The decoder specifications. /// /// /// The HeaderDecoder instance. /// /// /// The stream where to read data from. /// /// /// The bit stream reader agent. /// /// /// Whether or not truncation mode is required. /// /// /// The maximum number of code-blocks to read before ncbquit /// /// /// public PktDecoder(DecoderSpecs decSpec, HeaderDecoder hd, RandomAccessIO ehs, BitstreamReaderAgent src, bool isTruncMode, int maxCB) { this.decSpec = decSpec; this.hd = hd; this.ehs = ehs; this.isTruncMode = isTruncMode; bin = new PktHeaderBitReader(ehs); this.src = src; ncb = 0; ncbQuit = false; this.maxCB = maxCB; } /// Re-initialize the PktDecoder instance at the beginning of a new tile. /// /// /// The number of components in this tile /// /// /// The maximum number of decomposition level in each component /// of this tile /// /// /// The number of layers in this tile /// /// /// The code-blocks array /// /// /// Flag indicating whether packed packet headers was used /// /// /// Stream containing the packed packet headers /// /// public virtual CBlkInfo[][][][][] restart(int nc, int[] mdl, int nl, CBlkInfo[][][][][] cbI, bool pph, System.IO.MemoryStream pphbais) { this.nc = nc; this.nl = nl; this.tIdx = src.TileIdx; this.pph = pph; this.pphbais = pphbais; sopUsed = ((System.Boolean) decSpec.sops.getTileDef(tIdx)); pktIdx = 0; ephUsed = ((System.Boolean) decSpec.ephs.getTileDef(tIdx)); cbI = new CBlkInfo[nc][][][][]; lblock = new int[nc][][][][]; ttIncl = new TagTreeDecoder[nc][][][]; ttMaxBP = new TagTreeDecoder[nc][][][]; numPrec = new Coord[nc][]; ppinfo = new PrecInfo[nc][][]; // Used to compute the maximum number of precincts for each resolution // level int tcx0, tcy0, tcx1, tcy1; // Current tile position in the domain of // the image component int trx0, try0, trx1, try1; // Current tile position in the reduced // resolution image domain //int xrsiz, yrsiz; // Component sub-sampling factors SubbandSyn root, sb; int mins, maxs; Coord nBlk = null; int cb0x = src.CbULX; int cb0y = src.CbULY; for (int c = 0; c < nc; c++) { cbI[c] = new CBlkInfo[mdl[c] + 1][][][]; lblock[c] = new int[mdl[c] + 1][][][]; ttIncl[c] = new TagTreeDecoder[mdl[c] + 1][][]; ttMaxBP[c] = new TagTreeDecoder[mdl[c] + 1][][]; numPrec[c] = new Coord[mdl[c] + 1]; ppinfo[c] = new PrecInfo[mdl[c] + 1][]; // Get the tile-component coordinates on the reference grid tcx0 = src.getResULX(c, mdl[c]); tcy0 = src.getResULY(c, mdl[c]); tcx1 = tcx0 + src.getTileCompWidth(tIdx, c, mdl[c]); tcy1 = tcy0 + src.getTileCompHeight(tIdx, c, mdl[c]); for (int r = 0; r <= mdl[c]; r++) { // Tile's coordinates in the reduced resolution image domain //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" trx0 = (int) System.Math.Ceiling(tcx0 / (double) (1 << (mdl[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'" try0 = (int) System.Math.Ceiling(tcy0 / (double) (1 << (mdl[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'" trx1 = (int) System.Math.Ceiling(tcx1 / (double) (1 << (mdl[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'" try1 = (int) System.Math.Ceiling(tcy1 / (double) (1 << (mdl[c] - r))); // Calculate the maximum number of precincts for each // resolution level taking into account tile specific options. double twoppx = (double) getPPX(tIdx, c, r); double twoppy = (double) getPPY(tIdx, c, r); numPrec[c][r] = new Coord(); if (trx1 > trx0) { //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" numPrec[c][r].x = (int) System.Math.Ceiling((trx1 - cb0x) / twoppx) - (int) System.Math.Floor((trx0 - cb0x) / twoppx); } else { numPrec[c][r].x = 0; } if (try1 > try0) { //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" numPrec[c][r].y = (int) System.Math.Ceiling((try1 - cb0y) / twoppy) - (int) System.Math.Floor((try0 - cb0y) / twoppy); } else { numPrec[c][r].y = 0; } // First and last subbands indexes mins = (r == 0)?0:1; maxs = (r == 0)?1:4; int maxPrec = numPrec[c][r].x * numPrec[c][r].y; ttIncl[c][r] = new TagTreeDecoder[maxPrec][]; for (int i = 0; i < maxPrec; i++) { ttIncl[c][r][i] = new TagTreeDecoder[maxs + 1]; } ttMaxBP[c][r] = new TagTreeDecoder[maxPrec][]; for (int i2 = 0; i2 < maxPrec; i2++) { ttMaxBP[c][r][i2] = new TagTreeDecoder[maxs + 1]; } cbI[c][r] = new CBlkInfo[maxs + 1][][]; lblock[c][r] = new int[maxs + 1][][]; ppinfo[c][r] = new PrecInfo[maxPrec]; fillPrecInfo(c, r, mdl[c]); root = (SubbandSyn) src.getSynSubbandTree(tIdx, c); for (int s = mins; s < maxs; s++) { sb = (SubbandSyn) root.getSubbandByIdx(r, s); nBlk = sb.numCb; cbI[c][r][s] = new CBlkInfo[nBlk.y][]; for (int i3 = 0; i3 < nBlk.y; i3++) { cbI[c][r][s][i3] = new CBlkInfo[nBlk.x]; } lblock[c][r][s] = new int[nBlk.y][]; for (int i4 = 0; i4 < nBlk.y; i4++) { lblock[c][r][s][i4] = new int[nBlk.x]; } for (int i = nBlk.y - 1; i >= 0; i--) { ArrayUtil.intArraySet(lblock[c][r][s][i], INIT_LBLOCK); } } // loop on subbands } // End loop on resolution levels } // End loop on components return cbI; } /// Retrives precincts and code-blocks coordinates in the given resolution, /// level and component. Finishes TagTreeEncoder initialization as well. /// /// /// Component index. /// /// /// Resolution level index. /// /// /// Number of decomposition level in component c. /// /// private void fillPrecInfo(int c, int r, int mdl) { if (ppinfo[c][r].Length == 0) return ; // No precinct in this // resolution level Coord tileI = src.getTile(null); Coord nTiles = src.getNumTiles(null); int xsiz, ysiz, x0siz, y0siz; int xt0siz, yt0siz; int xtsiz, ytsiz; xt0siz = src.TilePartULX; yt0siz = src.TilePartULY; xtsiz = src.NomTileWidth; ytsiz = src.NomTileHeight; x0siz = hd.ImgULX; y0siz = hd.ImgULY; xsiz = hd.ImgWidth; ysiz = hd.ImgHeight; 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 = hd.getCompSubsX(c); int yrsiz = hd.getCompSubsY(c); int tcx0 = src.getResULX(c, mdl); int tcy0 = src.getResULY(c, mdl); int tcx1 = tcx0 + src.getTileCompWidth(tIdx, c, mdl); int tcy1 = tcy0 + src.getTileCompHeight(tIdx, c, mdl); int ndl = mdl - 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 = src.CbULX; int cb0y = src.CbULY; double twoppx = (double) getPPX(tIdx, c, r); double twoppy = (double) getPPY(tIdx, 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[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; SubbandSyn root = src.getSynSubbandTree(tIdx, c); SubbandSyn 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; int tmp1, tmp2; 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[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 = (SubbandSyn) 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[c][r][nPrec].nblk[0] = 0; ttIncl[c][r][nPrec][0] = new TagTreeDecoder(0, 0); ttMaxBP[c][r][nPrec][0] = new TagTreeDecoder(0, 0); } else { ttIncl[c][r][nPrec][0] = new TagTreeDecoder(kend - kstart + 1, lend - lstart + 1); ttMaxBP[c][r][nPrec][0] = new TagTreeDecoder(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[c][r][nPrec].cblk[0] = tmpArray; ppinfo[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); if (l == l0) { cb.ulx = sb.ulx; } else { cb.ulx = sb.ulx + l * cw - (sb.ulcx - acb0x); } if (k == k0) { cb.uly = sb.uly; } else { cb.uly = sb.uly + k * ch - (sb.ulcy - acb0y); } tmp1 = acb0x + l * cw; tmp1 = (tmp1 > sb.ulcx)?tmp1:sb.ulcx; tmp2 = acb0x + (l + 1) * cw; tmp2 = (tmp2 > sb.ulcx + sb.w)?sb.ulcx + sb.w:tmp2; cb.w = tmp2 - tmp1; tmp1 = acb0y + k * ch; tmp1 = (tmp1 > sb.ulcy)?tmp1:sb.ulcy; tmp2 = acb0y + (k + 1) * ch; tmp2 = (tmp2 > sb.ulcy + sb.h)?sb.ulcy + sb.h:tmp2; cb.h = tmp2 - tmp1; ppinfo[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 = (SubbandSyn) 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[c][r][nPrec].nblk[1] = 0; ttIncl[c][r][nPrec][1] = new TagTreeDecoder(0, 0); ttMaxBP[c][r][nPrec][1] = new TagTreeDecoder(0, 0); } else { ttIncl[c][r][nPrec][1] = new TagTreeDecoder(kend - kstart + 1, lend - lstart + 1); ttMaxBP[c][r][nPrec][1] = new TagTreeDecoder(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[c][r][nPrec].cblk[1] = tmpArray2; ppinfo[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); if (l == l0) { cb.ulx = sb.ulx; } else { cb.ulx = sb.ulx + l * cw - (sb.ulcx - acb0x); } if (k == k0) { cb.uly = sb.uly; } else { cb.uly = sb.uly + k * ch - (sb.ulcy - acb0y); } tmp1 = acb0x + l * cw; tmp1 = (tmp1 > sb.ulcx)?tmp1:sb.ulcx; tmp2 = acb0x + (l + 1) * cw; tmp2 = (tmp2 > sb.ulcx + sb.w)?sb.ulcx + sb.w:tmp2; cb.w = tmp2 - tmp1; tmp1 = acb0y + k * ch; tmp1 = (tmp1 > sb.ulcy)?tmp1:sb.ulcy; tmp2 = acb0y + (k + 1) * ch; tmp2 = (tmp2 > sb.ulcy + sb.h)?sb.ulcy + sb.h:tmp2; cb.h = tmp2 - tmp1; ppinfo[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 = (SubbandSyn) 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[c][r][nPrec].nblk[2] = 0; ttIncl[c][r][nPrec][2] = new TagTreeDecoder(0, 0); ttMaxBP[c][r][nPrec][2] = new TagTreeDecoder(0, 0); } else { ttIncl[c][r][nPrec][2] = new TagTreeDecoder(kend - kstart + 1, lend - lstart + 1); ttMaxBP[c][r][nPrec][2] = new TagTreeDecoder(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[c][r][nPrec].cblk[2] = tmpArray3; ppinfo[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); if (l == l0) { cb.ulx = sb.ulx; } else { cb.ulx = sb.ulx + l * cw - (sb.ulcx - acb0x); } if (k == k0) { cb.uly = sb.uly; } else { cb.uly = sb.uly + k * ch - (sb.ulcy - acb0y); } tmp1 = acb0x + l * cw; tmp1 = (tmp1 > sb.ulcx)?tmp1:sb.ulcx; tmp2 = acb0x + (l + 1) * cw; tmp2 = (tmp2 > sb.ulcx + sb.w)?sb.ulcx + sb.w:tmp2; cb.w = tmp2 - tmp1; tmp1 = acb0y + k * ch; tmp1 = (tmp1 > sb.ulcy)?tmp1:sb.ulcy; tmp2 = acb0y + (k + 1) * ch; tmp2 = (tmp2 > sb.ulcy + sb.h)?sb.ulcy + sb.h:tmp2; cb.h = tmp2 - tmp1; ppinfo[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 = (SubbandSyn) 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[c][r][nPrec].nblk[3] = 0; ttIncl[c][r][nPrec][3] = new TagTreeDecoder(0, 0); ttMaxBP[c][r][nPrec][3] = new TagTreeDecoder(0, 0); } else { ttIncl[c][r][nPrec][3] = new TagTreeDecoder(kend - kstart + 1, lend - lstart + 1); ttMaxBP[c][r][nPrec][3] = new TagTreeDecoder(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[c][r][nPrec].cblk[3] = tmpArray4; ppinfo[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); if (l == l0) { cb.ulx = sb.ulx; } else { cb.ulx = sb.ulx + l * cw - (sb.ulcx - acb0x); } if (k == k0) { cb.uly = sb.uly; } else { cb.uly = sb.uly + k * ch - (sb.ulcy - acb0y); } tmp1 = acb0x + l * cw; tmp1 = (tmp1 > sb.ulcx)?tmp1:sb.ulcx; tmp2 = acb0x + (l + 1) * cw; tmp2 = (tmp2 > sb.ulcx + sb.w)?sb.ulcx + sb.w:tmp2; cb.w = tmp2 - tmp1; tmp1 = acb0y + k * ch; tmp1 = (tmp1 > sb.ulcy)?tmp1:sb.ulcy; tmp2 = acb0y + (k + 1) * ch; tmp2 = (tmp2 > sb.ulcy + sb.h)?sb.ulcy + sb.h:tmp2; cb.h = tmp2 - tmp1; ppinfo[c][r][nPrec].cblk[3][k - kstart][l - lstart] = cb; } // Horizontal code-blocks } // Vertical code-blocks } } } // Horizontal precincts } // Vertical precincts } /// Gets the number of precincts in a given component and resolution level. /// /// /// Component index /// /// /// Resolution index /// /// public virtual int getNumPrecinct(int c, int r) { return numPrec[c][r].x * numPrec[c][r].y; } /// Read specified packet head and found length of each code-block's piece /// of codewords as well as number of skipped most significant bit-planes. /// /// /// layer index /// /// /// Resolution level index /// /// /// Component index /// /// /// Precinct index /// /// /// CBlkInfo array of relevant component and resolution /// level. /// /// /// The number of bytes to read in each tile before reaching /// output rate (used by truncation mode) /// /// /// True if specified output rate or EOF is reached. /// /// public virtual bool readPktHead(int l, int r, int c, int p, CBlkInfo[][][] cbI, int[] nb) { CBlkInfo ccb; int nSeg; // number of segment to read int cbLen; // Length of cblk's code-words int ltp; // last truncation point index int passtype; // coding pass type TagTreeDecoder tdIncl, tdBD; int tmp, tmp2, totnewtp, lblockCur, tpidx; int sumtotnewtp = 0; Coord cbc; int startPktHead = ehs.Pos; if (startPktHead >= ehs.length()) { // EOF reached at the beginning of this packet head return true; } int tIdx = src.TileIdx; PktHeaderBitReader bin; int mend, nend; int b; SubbandSyn sb; SubbandSyn root = src.getSynSubbandTree(tIdx, c); // If packed packet headers was used, use separate stream for reading // of packet headers if (pph) { bin = new PktHeaderBitReader(pphbais); } else { bin = this.bin; } int mins = (r == 0)?0:1; int maxs = (r == 0)?1:4; bool precFound = false; for (int s = mins; s < maxs; s++) { if (p < ppinfo[c][r].Length) { precFound = true; } } if (!precFound) { return false; } PrecInfo prec = ppinfo[c][r][p]; // Synchronize for bit reading bin.sync(); // If packet is empty there is no info in it (i.e. no code-blocks) if (bin.readBit() == 0) { // No code-block is included cblks = new System.Collections.ArrayList[maxs + 1]; for (int s = mins; s < maxs; s++) { cblks[s] = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10)); } pktIdx++; // If truncation mode, checks if output rate is reached // unless ncb quit condition is used in which case headers // are not counted if (isTruncMode && maxCB == - 1) { tmp = ehs.Pos - startPktHead; if (tmp > nb[tIdx]) { nb[tIdx] = 0; return true; } else { nb[tIdx] -= tmp; } } // Read EPH marker if needed if (ephUsed) { readEPHMarker(bin); } return false; } // Packet is not empty => decode info // Loop on each subband in this resolution level if (cblks == null || cblks.Length < maxs + 1) { cblks = new System.Collections.ArrayList[maxs + 1]; } for (int s = mins; s < maxs; s++) { if (cblks[s] == null) { cblks[s] = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10)); } else { cblks[s].Clear(); } sb = (SubbandSyn) root.getSubbandByIdx(r, s); // No code-block in this precinct if (prec.nblk[s] == 0) { // Go to next subband continue; } tdIncl = ttIncl[c][r][p][s]; tdBD = ttMaxBP[c][r][p][s]; 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++) { // Horizontal code-blocks cbc = prec.cblk[s][m][n].idx; b = cbc.x + cbc.y * sb.numCb.x; ccb = cbI[s][cbc.y][cbc.x]; try { // If code-block not included in previous layer(s) if (ccb == null || ccb.ctp == 0) { if (ccb == null) { ccb = cbI[s][cbc.y][cbc.x] = new CBlkInfo(prec.cblk[s][m][n].ulx, prec.cblk[s][m][n].uly, prec.cblk[s][m][n].w, prec.cblk[s][m][n].h, nl); } ccb.pktIdx[l] = pktIdx; // Read inclusion using tag-tree tmp = tdIncl.update(m, n, l + 1, bin); if (tmp > l) { // Not included continue; } // Read bitdepth using tag-tree tmp = 1; // initialization for (tmp2 = 1; tmp >= tmp2; tmp2++) { tmp = tdBD.update(m, n, tmp2, bin); } ccb.msbSkipped = tmp2 - 2; // New code-block => at least one truncation point totnewtp = 1; ccb.addNTP(l, 0); // Check whether ncb quit condition is reached ncb++; if (maxCB != - 1 && !ncbQuit && ncb == maxCB) { // ncb quit contidion reached ncbQuit = true; tQuit = tIdx; cQuit = c; sQuit = s; rQuit = r; xQuit = cbc.x; yQuit = cbc.y; } } else { // If code-block already included in one of // the previous layers. ccb.pktIdx[l] = pktIdx; // If not inclused if (bin.readBit() != 1) { continue; } // At least 1 more truncation point than // prev. packet totnewtp = 1; } // Read new truncation points if (bin.readBit() == 1) { // if bit is 1 totnewtp++; // if next bit is 0 do nothing if (bin.readBit() == 1) { //if is 1 totnewtp++; tmp = bin.readBits(2); totnewtp += tmp; // If next 2 bits are not 11 do nothing if (tmp == 0x3) { //if 11 tmp = bin.readBits(5); totnewtp += tmp; // If next 5 bits are not 11111 do nothing if (tmp == 0x1F) { //if 11111 totnewtp += bin.readBits(7); } } } } ccb.addNTP(l, totnewtp); sumtotnewtp += totnewtp; cblks[s].Add(prec.cblk[s][m][n]); // Code-block length // -- Compute the number of bit to read to obtain // code-block length. // numBits = betaLamda + log2(totnewtp); // The length is signalled for each segment in // addition to the final one. The total length is the // sum of all segment lengths. // If regular termination in use, then there is one // segment per truncation point present. Otherwise, if // selective arithmetic bypass coding mode is present, // then there is one termination per bypass/MQ and // MQ/bypass transition. Otherwise the only // termination is at the end of the code-block. int options = ((System.Int32) decSpec.ecopts.getTileCompVal(tIdx, c)); if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0) { // Regular termination in use, one segment per new // pass (i.e. truncation point) nSeg = totnewtp; } else if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0) { // Selective arithmetic coding bypass coding mode // in use, but no regular termination 1 segment up // to the end of the last pass of the 4th most // significant bit-plane, and, in each following // bit-plane, one segment upto the end of the 2nd // pass and one upto the end of the 3rd pass. if (ccb.ctp <= CSJ2K.j2k.entropy.StdEntropyCoderOptions.FIRST_BYPASS_PASS_IDX) { nSeg = 1; } else { nSeg = 1; // One at least for last pass // And one for each other terminated pass for (tpidx = ccb.ctp - totnewtp; tpidx < ccb.ctp - 1; tpidx++) { if (tpidx >= CSJ2K.j2k.entropy.StdEntropyCoderOptions.FIRST_BYPASS_PASS_IDX - 1) { passtype = (tpidx + CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_EMPTY_PASSES_IN_MS_BP) % CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_PASSES; if (passtype == 1 || passtype == 2) { // bypass coding just before MQ // pass or MQ pass just before // bypass coding => terminated nSeg++; } } } } } else { // Nothing special in use, just one segment nSeg = 1; } // Reads lblock increment (common to all segments) while (bin.readBit() != 0) { lblock[c][r][s][cbc.y][cbc.x]++; } if (nSeg == 1) { // Only one segment in packet cbLen = bin.readBits(lblock[c][r][s][cbc.y][cbc.x] + MathUtil.log2(totnewtp)); } else { // We must read one length per segment ccb.segLen[l] = new int[nSeg]; cbLen = 0; int j; if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0) { // Regular termination: each pass is terminated for (tpidx = ccb.ctp - totnewtp, j = 0; tpidx < ccb.ctp; tpidx++, j++) { lblockCur = lblock[c][r][s][cbc.y][cbc.x]; tmp = bin.readBits(lblockCur); ccb.segLen[l][j] = tmp; cbLen += tmp; } } else { // Bypass coding: only some passes are // terminated ltp = ccb.ctp - totnewtp - 1; for (tpidx = ccb.ctp - totnewtp, j = 0; tpidx < ccb.ctp - 1; tpidx++) { if (tpidx >= CSJ2K.j2k.entropy.StdEntropyCoderOptions.FIRST_BYPASS_PASS_IDX - 1) { passtype = (tpidx + CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_EMPTY_PASSES_IN_MS_BP) % CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_PASSES; if (passtype == 0) continue; lblockCur = lblock[c][r][s][cbc.y][cbc.x]; tmp = bin.readBits(lblockCur + MathUtil.log2(tpidx - ltp)); ccb.segLen[l][j] = tmp; cbLen += tmp; ltp = tpidx; j++; } } // Last pass has always the length sent lblockCur = lblock[c][r][s][cbc.y][cbc.x]; tmp = bin.readBits(lblockCur + MathUtil.log2(tpidx - ltp)); cbLen += tmp; ccb.segLen[l][j] = tmp; } } ccb.len[l] = cbLen; // If truncation mode, checks if output rate is reached // unless ncb and lbody quit contitions used. if (isTruncMode && maxCB == - 1) { tmp = ehs.Pos - startPktHead; if (tmp > nb[tIdx]) { nb[tIdx] = 0; // Remove found information in this code-block if (l == 0) { cbI[s][cbc.y][cbc.x] = null; } else { ccb.off[l] = ccb.len[l] = 0; ccb.ctp -= ccb.ntp[l]; ccb.ntp[l] = 0; ccb.pktIdx[l] = - 1; } return true; } } } catch (System.IO.EndOfStreamException) { // Remove found information in this code-block if (l == 0) { cbI[s][cbc.y][cbc.x] = null; } else { ccb.off[l] = ccb.len[l] = 0; ccb.ctp -= ccb.ntp[l]; ccb.ntp[l] = 0; ccb.pktIdx[l] = - 1; } // throw new EOFException(); return true; } } // End loop on horizontal code-blocks } // End loop on vertical code-blocks } // End loop on subbands // Read EPH marker if needed if (ephUsed) { readEPHMarker(bin); } pktIdx++; // If truncation mode, checks if output rate is reached if (isTruncMode && maxCB == - 1) { tmp = ehs.Pos - startPktHead; if (tmp > nb[tIdx]) { nb[tIdx] = 0; return true; } else { nb[tIdx] -= tmp; } } return false; } /// Reads specificied packet body in order to find offset of each /// code-block's piece of codeword. This use the list of found code-blocks /// in previous red packet head. /// /// /// layer index /// /// /// Resolution level index /// /// /// Component index /// /// /// Precinct index /// /// /// CBlkInfo array of relevant component and resolution /// level. /// /// /// The remainding number of bytes to read from the bit stream in /// each tile before reaching the decoding rate (in truncation mode) /// /// /// True if decoding rate is reached /// /// public virtual bool readPktBody(int l, int r, int c, int p, CBlkInfo[][][] cbI, int[] nb) { int curOff = ehs.Pos; //Coord curCB; CBlkInfo ccb; bool stopRead = false; int tIdx = src.TileIdx; Coord cbc; bool precFound = false; int mins = (r == 0)?0:1; int maxs = (r == 0)?1:4; for (int s = mins; s < maxs; s++) { if (p < ppinfo[c][r].Length) { precFound = true; } } if (!precFound) { return false; } for (int s = mins; s < maxs; s++) { for (int numCB = 0; numCB < cblks[s].Count; numCB++) { cbc = ((CBlkCoordInfo) cblks[s][numCB]).idx; ccb = cbI[s][cbc.y][cbc.x]; ccb.off[l] = curOff; curOff += ccb.len[l]; try { ehs.seek(curOff); } catch (System.IO.EndOfStreamException) { if (l == 0) { cbI[s][cbc.y][cbc.x] = null; } else { ccb.off[l] = ccb.len[l] = 0; ccb.ctp -= ccb.ntp[l]; ccb.ntp[l] = 0; ccb.pktIdx[l] = - 1; } // JH: If we try and seek past the end of the stream just stop the decoding curOff = ehs.length() - 1; ehs.seek(curOff); stopRead = true; return true; //throw new System.IO.EndOfStreamException(); } // If truncation mode if (isTruncMode) { if (stopRead || ccb.len[l] > nb[tIdx]) { // Remove found information in this code-block if (l == 0) { cbI[s][cbc.y][cbc.x] = null; } else { ccb.off[l] = ccb.len[l] = 0; ccb.ctp -= ccb.ntp[l]; ccb.ntp[l] = 0; ccb.pktIdx[l] = - 1; } stopRead = true; } if (!stopRead) { nb[tIdx] -= ccb.len[l]; } } // If ncb quit condition reached if (ncbQuit && r == rQuit && s == sQuit && cbc.x == xQuit && cbc.y == yQuit && tIdx == tQuit && c == cQuit) { cbI[s][cbc.y][cbc.x] = null; stopRead = true; } } // Loop on code-blocks } // End loop on subbands // Seek to the end of the packet ehs.seek(curOff); if (stopRead) { return true; } else { return false; } } /// Returns the precinct partition width for the specified component, /// resolution level and tile. /// /// /// the tile index /// /// /// The index of the component (between 0 and C-1) /// /// /// The resolution level, from 0 to L. /// /// /// the precinct partition width for the specified component, /// resolution level and tile. /// /// public int getPPX(int t, int c, int r) { return decSpec.pss.getPPX(t, c, r); } /// Returns the precinct partition height for the specified component, /// resolution level and tile. /// /// /// the tile index /// /// /// The index of the component (between 0 and C-1) /// /// /// The resolution level, from 0 to L. /// /// /// the precinct partition height in the specified component, for /// the specified resolution level, for the current tile. /// /// public int getPPY(int t, int c, int rl) { return decSpec.pss.getPPY(t, c, rl); } /// Try to read a SOP marker and check that its sequence number if not out /// of sequence. If so, an error is thrown. /// /// /// The number of bytes left to read from each tile /// /// /// Precinct index /// /// /// Resolution level index /// /// /// Component index /// /// public virtual bool readSOPMarker(int[] nBytes, int p, int c, int r) { int val; byte[] sopArray = new byte[6]; int tIdx = src.TileIdx; int mins = (r == 0)?0:1; int maxs = (r == 0)?1:4; bool precFound = false; for (int s = mins; s < maxs; s++) { if (p < ppinfo[c][r].Length) { precFound = true; } } if (!precFound) { return false; } // If SOP markers are not used, return if (!sopUsed) { return false; } // Check if SOP is used for this packet int pos = ehs.Pos; if ((short) ((ehs.read() << 8) | ehs.read()) != CSJ2K.j2k.codestream.Markers.SOP) { ehs.seek(pos); return false; } ehs.seek(pos); // If length of SOP marker greater than remaining bytes to read for // this tile return true if (nBytes[tIdx] < 6) { return true; } nBytes[tIdx] -= 6; // Read marker into array 'sopArray' ehs.readFully(sopArray, 0, CSJ2K.j2k.codestream.Markers.SOP_LENGTH); // Check if this is the correct marker val = sopArray[0]; val <<= 8; val |= sopArray[1]; if (val != CSJ2K.j2k.codestream.Markers.SOP) { throw new System.ApplicationException("Corrupted Bitstream: Could not parse SOP " + "marker !"); } // Check if length is correct val = (sopArray[2] & 0xff); val <<= 8; val |= (sopArray[3] & 0xff); if (val != 4) { throw new System.ApplicationException("Corrupted Bitstream: Corrupted SOP marker !"); } // Check if sequence number if ok val = (sopArray[4] & 0xff); val <<= 8; val |= (sopArray[5] & 0xff); if (!pph && val != pktIdx) { throw new System.ApplicationException("Corrupted Bitstream: SOP marker out of " + "sequence !"); } if (pph && val != pktIdx - 1) { // if packed packet headers are used, packet header was read // before SOP marker segment throw new System.ApplicationException("Corrupted Bitstream: SOP marker out of " + "sequence !"); } return false; } /// Try to read an EPH marker. If it is not possible then an Error is /// thrown. /// /// /// The packet header reader to read the EPH marker from /// /// public virtual void readEPHMarker(PktHeaderBitReader bin) { int val; byte[] ephArray = new byte[2]; if (bin.usebais) { bin.bais.Read(ephArray, 0, CSJ2K.j2k.codestream.Markers.EPH_LENGTH); } else { bin.in_Renamed.readFully(ephArray, 0, CSJ2K.j2k.codestream.Markers.EPH_LENGTH); } // Check if this is the correct marker val = ephArray[0]; val <<= 8; val |= ephArray[1]; if (val != CSJ2K.j2k.codestream.Markers.EPH) { throw new System.ApplicationException("Corrupted Bitstream: Could not parse EPH " + "marker ! "); } } /// Get PrecInfo instance of the specified resolution level, component and /// precinct. /// /// /// Component index. /// /// /// Resolution level index. /// /// /// Precinct index. /// /// public virtual PrecInfo getPrecInfo(int c, int r, int p) { return ppinfo[c][r][p]; } } }