/** * Retrives precincts and code-blocks coordinates in the given resolution, component and tile. It * terminates TagTreeEncoder initialization as well. * * @param t Tile index. * @param c Component index. * @param r Resolution level index. */ private void fillPrecInfo(int t, int c, int r) { if (ppinfo[t][c][r].length == 0) return; // No precinct in this // resolution level Point tileI = infoSrc.getTile(null); Point nTiles = infoSrc.getNumTiles(null); int x0siz = infoSrc.getImgULX(); int y0siz = infoSrc.getImgULY(); int xsiz = x0siz + infoSrc.getImgWidth(); int ysiz = y0siz + infoSrc.getImgHeight(); int xt0siz = infoSrc.getTilePartULX(); int yt0siz = infoSrc.getTilePartULY(); int xtsiz = infoSrc.getNomTileWidth(); int ytsiz = infoSrc.getNomTileHeight(); 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); int tcx0 = (int) Math.ceil(tx0 / (double) (xrsiz)); int tcy0 = (int) Math.ceil(ty0 / (double) (yrsiz)); int tcx1 = (int) Math.ceil(tx1 / (double) (xrsiz)); int tcy1 = (int) Math.ceil(ty1 / (double) (yrsiz)); int ndl = infoSrc.getAnSubbandTree(t, c).resLvl - r; int trx0 = (int) Math.ceil(tcx0 / (double) (1 << ndl)); int try0 = (int) Math.ceil(tcy0 / (double) (1 << ndl)); int trx1 = (int) Math.ceil(tcx1 / (double) (1 << ndl)); int try1 = (int) Math.ceil(tcy1 / (double) (1 << ndl)); int cb0x = infoSrc.getCbULX(); int cb0y = infoSrc.getCbULY(); double twoppx = (double) wp.getPrecinctPartition().getPPX(t, c, r); double twoppy = (double) wp.getPrecinctPartition().getPPY(t, c, r); int twoppx2 = (int) (twoppx / 2); 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; int istart = (int) Math.floor((try0 - cb0y) / twoppy); int iend = (int) Math.floor((try1 - 1 - cb0y) / twoppy); int jstart = (int) Math.floor((trx0 - cb0x) / twoppx); int jend = (int) 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; int prg_w = (int) twoppx << ndl; 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 if (j == jstart && (trx0 - cb0x) % (xrsiz * ((int) twoppx)) != 0) { prg_ulx = tx0; } else { prg_ulx = cb0x + j * xrsiz * ((int) twoppx << ndl); } if (i == istart && (try0 - cb0y) % (yrsiz * ((int) twoppy)) != 0) { prg_uly = ty0; } else { prg_uly = cb0y + i * yrsiz * ((int) twoppy << ndl); } 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; p0x = acb0x + j * (int) twoppx; p1x = p0x + (int) twoppx; p0y = acb0y + i * (int) twoppy; 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; k0 = (int) Math.floor((sb.ulcy - acb0y) / (double) ch); kstart = (int) Math.floor((s0y - acb0y) / (double) ch); kend = (int) Math.floor((s1y - 1 - acb0y) / (double) ch); l0 = (int) Math.floor((sb.ulcx - acb0x) / (double) cw); lstart = (int) Math.floor((s0x - acb0x) / (double) cw); lend = (int) 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); ppinfo[t][c][r][nPrec].cblk[0] = new CBlkCoordInfo[kend - kstart + 1][lend - lstart + 1]; 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; k0 = (int) Math.floor((sb.ulcy - acb0y) / (double) ch); kstart = (int) Math.floor((s0y - acb0y) / (double) ch); kend = (int) Math.floor((s1y - 1 - acb0y) / (double) ch); l0 = (int) Math.floor((sb.ulcx - acb0x) / (double) cw); lstart = (int) Math.floor((s0x - acb0x) / (double) cw); lend = (int) 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); ppinfo[t][c][r][nPrec].cblk[1] = new CBlkCoordInfo[kend - kstart + 1][lend - lstart + 1]; 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; k0 = (int) Math.floor((sb.ulcy - acb0y) / (double) ch); kstart = (int) Math.floor((s0y - acb0y) / (double) ch); kend = (int) Math.floor((s1y - 1 - acb0y) / (double) ch); l0 = (int) Math.floor((sb.ulcx - acb0x) / (double) cw); lstart = (int) Math.floor((s0x - acb0x) / (double) cw); lend = (int) 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); ppinfo[t][c][r][nPrec].cblk[2] = new CBlkCoordInfo[kend - kstart + 1][lend - lstart + 1]; 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; k0 = (int) Math.floor((sb.ulcy - acb0y) / (double) ch); kstart = (int) Math.floor((s0y - acb0y) / (double) ch); kend = (int) Math.floor((s1y - 1 - acb0y) / (double) ch); l0 = (int) Math.floor((sb.ulcx - acb0x) / (double) cw); lstart = (int) Math.floor((s0x - acb0x) / (double) cw); lend = (int) 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); ppinfo[t][c][r][nPrec].cblk[3] = new CBlkCoordInfo[kend - kstart + 1][lend - lstart + 1]; 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 }
/** * 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. * * @param ly The layer index (starts at 1). * @param c The component index. * @param r The resolution level * @param t Index of the current tile * @param cbs The 3D array of coded code-blocks. * @param tIndx The truncation point indices for each code-block. * @param hbuf The header buffer. If null a new BitOutputBuffer is created and returned. This * buffer is reset before anything is written to it. * @param bbuf The body buffer. If null a new one is created. If not large enough a new one is * created. * @param pIdx The precinct index. * @return The buffer containing the packet header. */ public 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; 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; Point 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) boolean 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 ArithmeticException( "Maximum number " + "of truncation " + "points exceeded"); } } } 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]]]; System.arraycopy(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]]]; System.arraycopy( 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.getLength() == 0) { throw new Error("You have found a bug in PktEncoder, method:" + " encodePacket"); } return hbuf; }
/** * Creates a new packet header encoder, using the information from the 'infoSrc' object. The * information used is the number of components, number of tiles, subband decomposition, etc. * * <p>Note that this constructor visits all the tiles in the 'infoSrc' object. The 'infoSrc' * object is left at the original tile (i.e. the current tile before calling this constructor), * but any side effects of visiting the tiles is not reverted. * * @param infoSrc The source of information to construct the object. * @param encSpec The parameters for the encoding * @param maxNumPrec Maximum number of precinct in each tile, component and resolution level. * @param pl ParameterList instance that holds command line options */ public PktEncoder(CodedCBlkDataSrcEnc infoSrc, J2KImageWriteParamJava wp, Point[][][] numPrec) { this.infoSrc = infoSrc; this.wp = wp; // this.numPrec = numPrec; // Get number of components and tiles int nc = infoSrc.getNumComps(); int nt = infoSrc.getNumTiles(); // Do initial allocation ttIncl = new TagTreeEncoder[nt][nc][][][]; ttMaxBP = new TagTreeEncoder[nt][nc][][][]; lblock = new int[nt][nc][][][]; prevtIdxs = new int[nt][nc][][][]; ppinfo = new PrecInfo[nt][nc][][]; // Finish allocation SubbandAn root, sb; int maxs, mins; int mrl; Point tmpCoord = null; int numcb; // Number of code-blocks Vector 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][maxs]; ttMaxBP[t][c][r] = new TagTreeEncoder[maxPrec][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(); } }