/// <summary> Splits the current subband in its four subbands. It changes the status /// of this element (from a leaf to a node, and sets the filters), creates /// the childs and initializes them. An IllegalArgumentException is thrown /// if this subband is not a leaf. /// /// <p>It uses the initChilds() method to initialize the childs.</p> /// /// </summary> /// <param name="hfilter">The horizontal wavelet filter used to decompose this /// subband. It has to be a AnWTFilter object. /// /// </param> /// <param name="vfilter">The vertical wavelet filter used to decompose this /// subband. It has to be a AnWTFilter object. /// /// </param> /// <returns> A reference to the LL leaf (subb_LL). /// /// </returns> /// <seealso cref="Subband.initChilds"> /// /// </seealso> protected internal override Subband split(WaveletFilter hfilter, WaveletFilter vfilter) { // Test that this is a node if (isNode) { throw new System.ArgumentException(); } // Modify this element into a node and set the filters isNode = true; this.hFilter = (AnWTFilter)hfilter; this.vFilter = (AnWTFilter)vfilter; // Create childs subb_LL = new SubbandAn(); subb_LH = new SubbandAn(); subb_HL = new SubbandAn(); subb_HH = new SubbandAn(); // Assign parent subb_LL.parentband = this; subb_HL.parentband = this; subb_LH.parentband = this; subb_HH.parentband = this; // Initialize childs initChilds(); // Return reference to LL subband return(subb_LL); }
/// <summary> Returns a reference to the subband tree structure representing the /// subband decomposition for the specified tile-component of the source. /// /// </summary> /// <param name="t">The index of the tile. /// /// </param> /// <param name="c">The index of the component. /// /// </param> /// <returns> The subband tree structure, see Subband. /// /// </returns> /// <seealso cref="SubbandAn"> /// </seealso> /// <seealso cref="Subband"> /// /// </seealso> public override SubbandAn getAnSubbandTree(int t, int c) { if (subbTrees[t][c] == null) { subbTrees[t][c] = new SubbandAn(getTileCompWidth(t, c), getTileCompHeight(t, c), getCompULX(c), getCompULY(c), getDecompLevels(t, c), getHorAnWaveletFilters(t, c), getVertAnWaveletFilters(t, c)); initSubbandsFields(t, c, subbTrees[t][c]); } return(subbTrees[t][c]); }
/// <summary> Performs the forward wavelet transform on the whole band. It /// iteratively decomposes the subbands from the top node to the leaves. /// /// </summary> /// <param name="band">The band containing the float data to decompose /// /// </param> /// <param name="subband">The structure containing the coordinates of the current /// subband in the whole band to decompose. /// /// </param> /// <param name="c">The index of the current component to decompose /// /// </param> private void waveletTreeDecomposition(DataBlk band, SubbandAn subband, int c) { //If the current subband is a leaf then nothing to be done (a leaf is //not decomposed). if (!subband.isNode) { return; } else { //Perform the 2D wavelet decomposition of the current subband wavelet2DDecomposition(band, (SubbandAn)subband, c); //Perform the decomposition of the four resulting subbands waveletTreeDecomposition(band, (SubbandAn)subband.HH, c); waveletTreeDecomposition(band, (SubbandAn)subband.LH, c); waveletTreeDecomposition(band, (SubbandAn)subband.HL, c); waveletTreeDecomposition(band, (SubbandAn)subband.LL, c); } }
/// <summary> Initializes this object with the given source of image data and with /// all the decompositon parameters /// /// </summary> /// <param name="src">From where the image data should be obtained. /// /// </param> /// <param name="encSpec">The encoder specifications /// /// </param> /// <param name="cb0x">The horizontal coordinate of the code-block partition /// origin on the reference grid. /// /// </param> /// <param name="cb0y">The vertical coordinate of the code-block partition origin /// on the reference grid. /// /// </param> /// <seealso cref="ForwardWT"> /// /// </seealso> public ForwWTFull(BlkImgDataSrc src, EncoderSpecs encSpec, int cb0x, int cb0y) : base(src) { this.src = src; this.cb0x = cb0x; this.cb0y = cb0y; this.dls = encSpec.dls; this.filters = encSpec.wfs; this.cblks = encSpec.cblks; this.pss = encSpec.pss; int ncomp = src.NumComps; int ntiles = src.getNumTiles(); currentSubband = new SubbandAn[ncomp]; decomposedComps = new DataBlk[ncomp]; subbTrees = new SubbandAn[ntiles][]; for (int i = 0; i < ntiles; i++) { subbTrees[i] = new SubbandAn[ncomp]; } lastn = new int[ncomp]; lastm = new int[ncomp]; }
/// <summary> This function finds the new truncation points indices for a packet. It /// does so by including the data from the code-blocks in the component, /// resolution level and tile, associated with a R-D slope which is larger /// than or equal to 'fthresh'. /// /// </summary> /// <param name="layerIdx">The index of the current layer /// /// </param> /// <param name="compIdx">The index of the current component /// /// </param> /// <param name="lvlIdx">The index of the current resolution level /// /// </param> /// <param name="tileIdx">The index of the current tile /// /// </param> /// <param name="subb">The LL subband in the resolution level lvlIdx, which is /// parent of all the subbands in the packet. Except for resolution level 0 /// this subband is always a node. /// /// </param> /// <param name="fthresh">The value of the rate-distortion threshold /// /// </param> private void findTruncIndices(int layerIdx, int compIdx, int lvlIdx, int tileIdx, SubbandAn subb, float fthresh, int precinctIdx) { int minsbi, maxsbi, b, n; // bIdx removed //Coord ncblks = null; SubbandAn sb; CBlkRateDistStats cur_cblk; PrecInfo prec = pktEnc.getPrecInfo(tileIdx, compIdx, lvlIdx, precinctIdx); Coord cbCoord; sb = subb; while (sb.subb_HH != null) { sb = sb.subb_HH; } minsbi = (lvlIdx == 0)?0:1; maxsbi = (lvlIdx == 0)?1:4; int yend, xend; sb = (SubbandAn) subb.getSubbandByIdx(lvlIdx, minsbi); for (int s = minsbi; s < maxsbi; s++) { //loop on subbands yend = (prec.cblk[s] != null)?prec.cblk[s].Length:0; for (int y = 0; y < yend; y++) { xend = (prec.cblk[s][y] != null)?prec.cblk[s][y].Length:0; for (int x = 0; x < xend; x++) { cbCoord = prec.cblk[s][y][x].idx; b = cbCoord.x + cbCoord.y * sb.numCb.x; //Get the current code-block cur_cblk = cblks[tileIdx][compIdx][lvlIdx][s][b]; for (n = 0; n < cur_cblk.nVldTrunc; n++) { if (cur_cblk.truncSlopes[n] < fthresh) { break; } else { continue; } } // Store the index in the code-block truncIdxs that gives // the real truncation index. truncIdxs[tileIdx][layerIdx][compIdx][lvlIdx][s][b] = n - 1; } // End loop on horizontal code-blocks } // End loop on vertical code-blocks sb = (SubbandAn) sb.nextSubband(); } // End loop on subbands }
/// <summary> Splits the current subband in its four subbands. It changes the status /// of this element (from a leaf to a node, and sets the filters), creates /// the childs and initializes them. An IllegalArgumentException is thrown /// if this subband is not a leaf. /// /// <p>It uses the initChilds() method to initialize the childs.</p> /// /// </summary> /// <param name="hfilter">The horizontal wavelet filter used to decompose this /// subband. It has to be a AnWTFilter object. /// /// </param> /// <param name="vfilter">The vertical wavelet filter used to decompose this /// subband. It has to be a AnWTFilter object. /// /// </param> /// <returns> A reference to the LL leaf (subb_LL). /// /// </returns> /// <seealso cref="Subband.initChilds"> /// /// </seealso> protected internal override Subband split(WaveletFilter hfilter, WaveletFilter vfilter) { // Test that this is a node if (isNode) { throw new System.ArgumentException(); } // Modify this element into a node and set the filters isNode = true; this.hFilter = (AnWTFilter) hfilter; this.vFilter = (AnWTFilter) vfilter; // Create childs subb_LL = new SubbandAn(); subb_LH = new SubbandAn(); subb_HL = new SubbandAn(); subb_HH = new SubbandAn(); // Assign parent subb_LL.parentband = this; subb_HL.parentband = this; subb_LH.parentband = this; subb_HH.parentband = this; // Initialize childs initChilds(); // Return reference to LL subband return subb_LL; }
/// <summary> Performs the 2D forward wavelet transform on a subband of the initial /// band. This method will successively perform 1D filtering steps on all /// lines and then all columns of the subband. In this class only filters /// with floating point implementations can be used. /// /// </summary> /// <param name="band">The band containing the float data to decompose /// /// </param> /// <param name="subband">The structure containing the coordinates of the subband /// in the whole band to decompose. /// /// </param> /// <param name="c">The index of the current component to decompose /// /// </param> private void wavelet2DDecomposition(DataBlk band, SubbandAn subband, int c) { int ulx, uly, w, h; int band_w, band_h; // If subband is empty (i.e. zero size) nothing to do if (subband.w == 0 || subband.h == 0) { return ; } ulx = subband.ulx; uly = subband.uly; w = subband.w; h = subband.h; band_w = getTileCompWidth(tIdx, c); band_h = getTileCompHeight(tIdx, c); if (intData) { //Perform the decompositions if the filter is implemented with an //integer arithmetic. int i, j; int offset; int[] tmpVector = new int[System.Math.Max(w, h)]; int[] data = ((DataBlkInt) band).DataInt; //Perform the vertical decomposition if (subband.ulcy % 2 == 0) { // Even start index => use LPF for (j = 0; j < w; j++) { offset = uly * band_w + ulx + j; for (i = 0; i < h; i++) tmpVector[i] = data[offset + (i * band_w)]; subband.vFilter.analyze_lpf(tmpVector, 0, h, 1, data, offset, band_w, data, offset + ((h + 1) / 2) * band_w, band_w); } } else { // Odd start index => use HPF for (j = 0; j < w; j++) { offset = uly * band_w + ulx + j; for (i = 0; i < h; i++) tmpVector[i] = data[offset + (i * band_w)]; subband.vFilter.analyze_hpf(tmpVector, 0, h, 1, data, offset, band_w, data, offset + (h / 2) * band_w, band_w); } } //Perform the horizontal decomposition. if (subband.ulcx % 2 == 0) { // Even start index => use LPF for (i = 0; i < h; i++) { offset = (uly + i) * band_w + ulx; for (j = 0; j < w; j++) tmpVector[j] = data[offset + j]; subband.hFilter.analyze_lpf(tmpVector, 0, w, 1, data, offset, 1, data, offset + (w + 1) / 2, 1); } } else { // Odd start index => use HPF for (i = 0; i < h; i++) { offset = (uly + i) * band_w + ulx; for (j = 0; j < w; j++) tmpVector[j] = data[offset + j]; subband.hFilter.analyze_hpf(tmpVector, 0, w, 1, data, offset, 1, data, offset + w / 2, 1); } } } else { //Perform the decompositions if the filter is implemented with a //float arithmetic. int i, j; int offset; float[] tmpVector = new float[System.Math.Max(w, h)]; float[] data = ((DataBlkFloat) band).DataFloat; //Perform the vertical decomposition. if (subband.ulcy % 2 == 0) { // Even start index => use LPF for (j = 0; j < w; j++) { offset = uly * band_w + ulx + j; for (i = 0; i < h; i++) tmpVector[i] = data[offset + (i * band_w)]; subband.vFilter.analyze_lpf(tmpVector, 0, h, 1, data, offset, band_w, data, offset + ((h + 1) / 2) * band_w, band_w); } } else { // Odd start index => use HPF for (j = 0; j < w; j++) { offset = uly * band_w + ulx + j; for (i = 0; i < h; i++) tmpVector[i] = data[offset + (i * band_w)]; subband.vFilter.analyze_hpf(tmpVector, 0, h, 1, data, offset, band_w, data, offset + (h / 2) * band_w, band_w); } } //Perform the horizontal decomposition. if (subband.ulcx % 2 == 0) { // Even start index => use LPF for (i = 0; i < h; i++) { offset = (uly + i) * band_w + ulx; for (j = 0; j < w; j++) tmpVector[j] = data[offset + j]; subband.hFilter.analyze_lpf(tmpVector, 0, w, 1, data, offset, 1, data, offset + (w + 1) / 2, 1); } } else { // Odd start index => use HPF for (i = 0; i < h; i++) { offset = (uly + i) * band_w + ulx; for (j = 0; j < w; j++) tmpVector[j] = data[offset + j]; subband.hFilter.analyze_hpf(tmpVector, 0, w, 1, data, offset, 1, data, offset + w / 2, 1); } } } }
/// <summary> Performs the forward wavelet transform on the whole band. It /// iteratively decomposes the subbands from the top node to the leaves. /// /// </summary> /// <param name="band">The band containing the float data to decompose /// /// </param> /// <param name="subband">The structure containing the coordinates of the current /// subband in the whole band to decompose. /// /// </param> /// <param name="c">The index of the current component to decompose /// /// </param> private void waveletTreeDecomposition(DataBlk band, SubbandAn subband, int c) { //If the current subband is a leaf then nothing to be done (a leaf is //not decomposed). if (!subband.isNode) { return ; } else { //Perform the 2D wavelet decomposition of the current subband wavelet2DDecomposition(band, (SubbandAn) subband, c); //Perform the decomposition of the four resulting subbands waveletTreeDecomposition(band, (SubbandAn) subband.HH, c); waveletTreeDecomposition(band, (SubbandAn) subband.LH, c); waveletTreeDecomposition(band, (SubbandAn) subband.HL, c); waveletTreeDecomposition(band, (SubbandAn) subband.LL, c); } }
/// <summary> Initializes this object with the given source of image data and with /// all the decompositon parameters /// /// </summary> /// <param name="src">From where the image data should be obtained. /// /// </param> /// <param name="encSpec">The encoder specifications /// /// </param> /// <param name="cb0x">The horizontal coordinate of the code-block partition /// origin on the reference grid. /// /// </param> /// <param name="cb0y">The vertical coordinate of the code-block partition origin /// on the reference grid. /// /// </param> /// <seealso cref="ForwardWT"> /// /// </seealso> public ForwWTFull(BlkImgDataSrc src, EncoderSpecs encSpec, int cb0x, int cb0y):base(src) { this.src = src; this.cb0x = cb0x; this.cb0y = cb0y; this.dls = encSpec.dls; this.filters = encSpec.wfs; this.cblks = encSpec.cblks; this.pss = encSpec.pss; int ncomp = src.NumComps; int ntiles = src.getNumTiles(); currentSubband = new SubbandAn[ncomp]; decomposedComps = new DataBlk[ncomp]; subbTrees = new SubbandAn[ntiles][]; for (int i = 0; i < ntiles; i++) { subbTrees[i] = new SubbandAn[ncomp]; } lastn = new int[ncomp]; lastm = new int[ncomp]; }
/// <summary> Returns a reference to the subband tree structure representing the /// subband decomposition for the specified tile-component of the source. /// /// </summary> /// <param name="t">The index of the tile. /// /// </param> /// <param name="c">The index of the component. /// /// </param> /// <returns> The subband tree structure, see Subband. /// /// </returns> /// <seealso cref="SubbandAn"> /// </seealso> /// <seealso cref="Subband"> /// /// </seealso> public override SubbandAn getAnSubbandTree(int t, int c) { if (subbTrees[t][c] == null) { subbTrees[t][c] = new SubbandAn(getTileCompWidth(t, c), getTileCompHeight(t, c), getCompULX(c), getCompULY(c), getDecompLevels(t, c), getHorAnWaveletFilters(t, c), getVertAnWaveletFilters(t, c)); initSubbandsFields(t, c, subbTrees[t][c]); } return subbTrees[t][c]; }
/// <summary> Calculates the parameters of the SubbandAn objects that depend on the /// Quantizer. The 'stepWMSE' field is calculated for each subband which is /// a leaf in the tree rooted at 'sb', for the specified component. The /// subband tree 'sb' must be the one for the component 'n'. /// /// </summary> /// <param name="sb">The root of the subband tree. /// /// </param> /// <param name="n">The component index. /// /// </param> /// <seealso cref="SubbandAn.stepWMSE"> /// /// </seealso> protected internal abstract void calcSbParams(SubbandAn sb, int n);
/// <summary> Calculates the parameters of the SubbandAn objects that depend on the /// Quantizer. The 'stepWMSE' field is calculated for each subband which is /// a leaf in the tree rooted at 'sb', for the specified component. The /// subband tree 'sb' must be the one for the component 'n'. /// /// </summary> /// <param name="sb">The root of the subband tree. /// /// </param> /// <param name="c">The component index /// /// </param> /// <seealso cref="SubbandAn.stepWMSE"> /// /// </seealso> protected internal override void calcSbParams(SubbandAn sb, int c) { float baseStep; if (sb.stepWMSE > 0f) // parameters already calculated return ; if (!sb.isNode) { if (isReversible(tIdx, 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'" sb.stepWMSE = (float) System.Math.Pow(2, - (src.getNomRangeBits(c) << 1)) * sb.l2Norm * sb.l2Norm; } else { //UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Float.floatValue' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'" baseStep = (float) ((System.Single) qsss.getTileCompVal(tIdx, c)); if (isDerived(tIdx, 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'" sb.stepWMSE = baseStep * baseStep * (float) System.Math.Pow(2, (sb.anGainExp - sb.level) << 1) * sb.l2Norm * sb.l2Norm; } else { sb.stepWMSE = baseStep * baseStep; } } } else { calcSbParams((SubbandAn) sb.LL, c); calcSbParams((SubbandAn) sb.HL, c); calcSbParams((SubbandAn) sb.LH, c); calcSbParams((SubbandAn) sb.HH, c); sb.stepWMSE = 1f; // Signal that we already calculated this branch } }
/// <summary> Performs the 2D forward wavelet transform on a subband of the initial /// band. This method will successively perform 1D filtering steps on all /// lines and then all columns of the subband. In this class only filters /// with floating point implementations can be used. /// /// </summary> /// <param name="band">The band containing the float data to decompose /// /// </param> /// <param name="subband">The structure containing the coordinates of the subband /// in the whole band to decompose. /// /// </param> /// <param name="c">The index of the current component to decompose /// /// </param> private void wavelet2DDecomposition(DataBlk band, SubbandAn subband, int c) { int ulx, uly, w, h; int band_w, band_h; // If subband is empty (i.e. zero size) nothing to do if (subband.w == 0 || subband.h == 0) { return; } ulx = subband.ulx; uly = subband.uly; w = subband.w; h = subband.h; band_w = getTileCompWidth(tIdx, c); band_h = getTileCompHeight(tIdx, c); if (intData) { //Perform the decompositions if the filter is implemented with an //integer arithmetic. int i, j; int offset; int[] tmpVector = new int[System.Math.Max(w, h)]; int[] data = ((DataBlkInt)band).DataInt; //Perform the vertical decomposition if (subband.ulcy % 2 == 0) { // Even start index => use LPF for (j = 0; j < w; j++) { offset = uly * band_w + ulx + j; for (i = 0; i < h; i++) { tmpVector[i] = data[offset + (i * band_w)]; } subband.vFilter.analyze_lpf(tmpVector, 0, h, 1, data, offset, band_w, data, offset + ((h + 1) / 2) * band_w, band_w); } } else { // Odd start index => use HPF for (j = 0; j < w; j++) { offset = uly * band_w + ulx + j; for (i = 0; i < h; i++) { tmpVector[i] = data[offset + (i * band_w)]; } subband.vFilter.analyze_hpf(tmpVector, 0, h, 1, data, offset, band_w, data, offset + (h / 2) * band_w, band_w); } } //Perform the horizontal decomposition. if (subband.ulcx % 2 == 0) { // Even start index => use LPF for (i = 0; i < h; i++) { offset = (uly + i) * band_w + ulx; for (j = 0; j < w; j++) { tmpVector[j] = data[offset + j]; } subband.hFilter.analyze_lpf(tmpVector, 0, w, 1, data, offset, 1, data, offset + (w + 1) / 2, 1); } } else { // Odd start index => use HPF for (i = 0; i < h; i++) { offset = (uly + i) * band_w + ulx; for (j = 0; j < w; j++) { tmpVector[j] = data[offset + j]; } subband.hFilter.analyze_hpf(tmpVector, 0, w, 1, data, offset, 1, data, offset + w / 2, 1); } } } else { //Perform the decompositions if the filter is implemented with a //float arithmetic. int i, j; int offset; float[] tmpVector = new float[System.Math.Max(w, h)]; float[] data = ((DataBlkFloat)band).DataFloat; //Perform the vertical decomposition. if (subband.ulcy % 2 == 0) { // Even start index => use LPF for (j = 0; j < w; j++) { offset = uly * band_w + ulx + j; for (i = 0; i < h; i++) { tmpVector[i] = data[offset + (i * band_w)]; } subband.vFilter.analyze_lpf(tmpVector, 0, h, 1, data, offset, band_w, data, offset + ((h + 1) / 2) * band_w, band_w); } } else { // Odd start index => use HPF for (j = 0; j < w; j++) { offset = uly * band_w + ulx + j; for (i = 0; i < h; i++) { tmpVector[i] = data[offset + (i * band_w)]; } subband.vFilter.analyze_hpf(tmpVector, 0, h, 1, data, offset, band_w, data, offset + (h / 2) * band_w, band_w); } } //Perform the horizontal decomposition. if (subband.ulcx % 2 == 0) { // Even start index => use LPF for (i = 0; i < h; i++) { offset = (uly + i) * band_w + ulx; for (j = 0; j < w; j++) { tmpVector[j] = data[offset + j]; } subband.hFilter.analyze_lpf(tmpVector, 0, w, 1, data, offset, 1, data, offset + (w + 1) / 2, 1); } } else { // Odd start index => use HPF for (i = 0; i < h; i++) { offset = (uly + i) * band_w + ulx; for (j = 0; j < w; j++) { tmpVector[j] = data[offset + j]; } subband.hFilter.analyze_hpf(tmpVector, 0, w, 1, data, offset, 1, data, offset + w / 2, 1); } } } }