/** * Returns the maximum number of magnitude bits in any subband of the current tile if reversible * quantization is used * * @param sb The root of the subband tree of the current tile * @param c the component number * @return The highest number of magnitude bit-planes */ private int getMaxMagBitsRev(Subband sb, int c) { int tmp, max = 0; int g = ((Integer) gbs.getTileCompVal(tIdx, c)).intValue(); if (!sb.isNode) return g - 1 + src.getNomRangeBits(c) + sb.anGainExp; max = getMaxMagBitsRev(sb.getLL(), c); tmp = getMaxMagBitsRev(sb.getLH(), c); if (tmp > max) max = tmp; tmp = getMaxMagBitsRev(sb.getHL(), c); if (tmp > max) max = tmp; tmp = getMaxMagBitsRev(sb.getHH(), c); if (tmp > max) max = tmp; return max; }
/** * Returns the maximum number of magnitude bits in any subband in the given tile-component if * derived quantization is used * * @param sb The root of the subband tree of the tile-component * @param t Tile index * @param c Component index * @return The highest number of magnitude bit-planes */ private int getMaxMagBitsDerived(Subband sb, int t, int c) { int tmp, max = 0; int g = ((Integer) gbs.getTileCompVal(t, c)).intValue(); if (!sb.isNode) { float baseStep = ((Float) qsss.getTileCompVal(t, c)).floatValue(); return g - 1 + sb.level - (int) Math.floor(Math.log(baseStep) / log2); } max = getMaxMagBitsDerived(sb.getLL(), t, c); tmp = getMaxMagBitsDerived(sb.getLH(), t, c); if (tmp > max) max = tmp; tmp = getMaxMagBitsDerived(sb.getHL(), t, c); if (tmp > max) max = tmp; tmp = getMaxMagBitsDerived(sb.getHH(), t, c); if (tmp > max) max = tmp; return max; }
/** * Returns the maximum number of magnitude bits in any subband in the given tile-component if * expounded quantization is used * * @param sb The root of the subband tree of the tile-component * @param t Tile index * @param c Component index * @return The highest number of magnitude bit-planes */ private int getMaxMagBitsExpounded(Subband sb, int t, int c) { int tmp, max = 0; int g = ((Integer) gbs.getTileCompVal(t, c)).intValue(); if (!sb.isNode) { float baseStep = ((Float) qsss.getTileCompVal(t, c)).floatValue(); return g - 1 - (int) Math.floor( Math.log(baseStep / (((SubbandAn) sb).l2Norm * (1 << sb.anGainExp))) / log2); } max = getMaxMagBitsExpounded(sb.getLL(), t, c); tmp = getMaxMagBitsExpounded(sb.getLH(), t, c); if (tmp > max) max = tmp; tmp = getMaxMagBitsExpounded(sb.getHL(), t, c); if (tmp > max) max = tmp; tmp = getMaxMagBitsExpounded(sb.getHH(), t, c); if (tmp > max) max = tmp; return max; }
/** * Initialises subbands fields, such as number of code-blocks and code-blocks dimension, in the * subband tree. The nominal code-block width/height depends on the precincts dimensions if used. * * @param t The tile index of the subband * @param c The component index * @param sb The subband tree to be initialised. */ private void initSubbandsFields(int t, int c, Subband sb) { int cbw = cblks.getCBlkWidth(ModuleSpec.SPEC_TILE_COMP, t, c); int cbh = cblks.getCBlkHeight(ModuleSpec.SPEC_TILE_COMP, t, c); if (!sb.isNode) { // Code-blocks dimension int ppx, ppy; int ppxExp, ppyExp, cbwExp, cbhExp; ppx = pss.getPPX(t, c, sb.resLvl); ppy = pss.getPPY(t, c, sb.resLvl); if (ppx != Markers.PRECINCT_PARTITION_DEF_SIZE || ppy != Markers.PRECINCT_PARTITION_DEF_SIZE) { ppxExp = MathUtil.log2(ppx); ppyExp = MathUtil.log2(ppy); cbwExp = MathUtil.log2(cbw); cbhExp = MathUtil.log2(cbh); // Precinct partition is used switch (sb.resLvl) { case 0: sb.nomCBlkW = (cbwExp < ppxExp ? (1 << cbwExp) : (1 << ppxExp)); sb.nomCBlkH = (cbhExp < ppyExp ? (1 << cbhExp) : (1 << ppyExp)); break; default: sb.nomCBlkW = (cbwExp < ppxExp - 1 ? (1 << cbwExp) : (1 << (ppxExp - 1))); sb.nomCBlkH = (cbhExp < ppyExp - 1 ? (1 << cbhExp) : (1 << (ppyExp - 1))); break; } } else { sb.nomCBlkW = cbw; sb.nomCBlkH = cbh; } // Number of code-blocks if (sb.numCb == null) sb.numCb = new Point(); if (sb.w != 0 && sb.h != 0) { int acb0x = cb0x; int acb0y = cb0y; int tmp; // Project code-block partition origin to subband. Since the // origin is always 0 or 1, it projects to the low-pass side // (throught the ceil operator) as itself (i.e. no change) and // to the high-pass side (through the floor operator) as 0, // always. switch (sb.sbandIdx) { case Subband.WT_ORIENT_LL: // No need to project since all low-pass => nothing to do break; case Subband.WT_ORIENT_HL: acb0x = 0; break; case Subband.WT_ORIENT_LH: acb0y = 0; break; case Subband.WT_ORIENT_HH: acb0x = 0; acb0y = 0; break; default: throw new Error("Internal JJ2000 error"); } if (sb.ulcx - acb0x < 0 || sb.ulcy - acb0y < 0) { throw new IllegalArgumentException( "Invalid code-blocks " + "partition origin or " + "image offset in the " + "reference grid."); } // NOTE: when calculating "floor()" by integer division the // dividend and divisor must be positive, we ensure that by // adding the divisor to the dividend and then substracting 1 // to the result of the division tmp = sb.ulcx - acb0x + sb.nomCBlkW; sb.numCb.x = (tmp + sb.w - 1) / sb.nomCBlkW - (tmp / sb.nomCBlkW - 1); tmp = sb.ulcy - acb0y + sb.nomCBlkH; sb.numCb.y = (tmp + sb.h - 1) / sb.nomCBlkH - (tmp / sb.nomCBlkH - 1); } else { sb.numCb.x = sb.numCb.y = 0; } } else { initSubbandsFields(t, c, sb.getLL()); initSubbandsFields(t, c, sb.getHL()); initSubbandsFields(t, c, sb.getLH()); initSubbandsFields(t, c, sb.getHH()); } }