/** * Assigns the given L2-norm to the first leaf that does not have an L2-norm value yet (i.e. * l2norm is negative). The search is done recursively and in the same order as that of the * calcBasisWaveForms() method, so that this method is used to assigne the l2norm of the * previously computed waveforms. * * <p>This method can not be called on an element that ahs a non-negative value in l2Norm, since * that means that we are done. * * @param l2n The L2-norm to assign. */ private void assignL2Norm(float l2n) { if (l2Norm < 0) { // We are not finished with this element yet if (isNode) { // We are on a node => search on childs if (subb_LL.l2Norm < 0f) { subb_LL.assignL2Norm(l2n); } else if (subb_HL.l2Norm < 0f) { subb_HL.assignL2Norm(l2n); } else if (subb_LH.l2Norm < 0f) { subb_LH.assignL2Norm(l2n); } else if (subb_HH.l2Norm < 0f) { subb_HH.assignL2Norm(l2n); // If child now is done, we are done if (subb_HH.l2Norm >= 0f) { l2Norm = 0f; // We are on a node, any non-neg value OK } } else { // There is an error! If all childs have // non-negative l2norm, then this node should have // non-negative l2norm throw new Error("You have found a bug in JJ2000!"); } } else { // This is a leaf, assign the L2-norm l2Norm = l2n; } } else { // This is an error! The assignL2Norm() method is // never called on an element with non-negative l2norm throw new Error("You have found a bug in JJ2000!"); } }
/** * 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. * * @param hfilter The horizontal wavelet filter used to decompose this subband. It has to be a * AnWTFilter object. * @param vfilter The vertical wavelet filter used to decompose this subband. It has to be a * AnWTFilter object. * @return A reference to the LL leaf (subb_LL). * @see Subband#initChilds */ protected Subband split(WaveletFilter hfilter, WaveletFilter vfilter) { // Test that this is a node if (isNode) { throw new IllegalArgumentException(); } // 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.parent = this; subb_HL.parent = this; subb_LH.parent = this; subb_HH.parent = this; // Initialize childs initChilds(); // Return reference to LL subband return subb_LL; }
/** * 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'. * * @param sb The root of the subband tree. * @param c The component index * @see SubbandAn#stepWMSE */ protected void calcSbParams(SubbandAn sb, int c) { float baseStep; if (sb.stepWMSE > 0f) // parameters already calculated return; if (!sb.isNode) { if (isReversible(tIdx, c)) { sb.stepWMSE = (float) Math.pow(2, -(src.getNomRangeBits(c) << 1)) * sb.l2Norm * sb.l2Norm; } else { baseStep = ((Float) qsss.getTileCompVal(tIdx, c)).floatValue(); if (isDerived(tIdx, c)) { sb.stepWMSE = baseStep * baseStep * (float) Math.pow(2, (sb.anGainExp - sb.level) << 1) * sb.l2Norm * sb.l2Norm; } else { sb.stepWMSE = baseStep * baseStep; } } } else { calcSbParams((SubbandAn) sb.getLL(), c); calcSbParams((SubbandAn) sb.getHL(), c); calcSbParams((SubbandAn) sb.getLH(), c); calcSbParams((SubbandAn) sb.getHH(), c); sb.stepWMSE = 1f; // Signal that we already calculated this branch } }
/** * Performs the forward wavelet transform on the whole band. It iteratively decomposes the * subbands from the top node to the leaves. * * @param band The band containing the float data to decompose * @param subband The structure containing the coordinates of the current subband in the whole * band to decompose. * @param c The index of the current component to decompose */ 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.getHH(), c); waveletTreeDecomposition(band, (SubbandAn) subband.getLH(), c); waveletTreeDecomposition(band, (SubbandAn) subband.getHL(), c); waveletTreeDecomposition(band, (SubbandAn) subband.getLL(), c); } }
/** * Calculates the basis waveform of the first leaf for which the L2-norm has not been calculated * yet. This method searches recursively for the first leaf for which the value has not been * calculated yet, and then calculates the L2-norm on the return path. * * <p>The wfs argument should be a size 2 array of float arrays (i.e. 2D array) and it must be of * length 2 (or more). When returning, wfs[0] will contain the line waveform, and wfs[1] will * contain the column waveform. * * <p>This method can not be called on an element that ahs a non-negative value in l2Norm, since * that means that we are done. * * @param wfs An size 2 array where the line and column waveforms will be returned. */ private void calcBasisWaveForms(float wfs[][]) { if (l2Norm < 0) { // We are not finished with this element yet if (isNode) { // We are on a node => search on childs if (subb_LL.l2Norm < 0f) { subb_LL.calcBasisWaveForms(wfs); wfs[0] = hFilter.getLPSynWaveForm(wfs[0], null); wfs[1] = vFilter.getLPSynWaveForm(wfs[1], null); } else if (subb_HL.l2Norm < 0f) { subb_HL.calcBasisWaveForms(wfs); wfs[0] = hFilter.getHPSynWaveForm(wfs[0], null); wfs[1] = vFilter.getLPSynWaveForm(wfs[1], null); } else if (subb_LH.l2Norm < 0f) { subb_LH.calcBasisWaveForms(wfs); wfs[0] = hFilter.getLPSynWaveForm(wfs[0], null); wfs[1] = vFilter.getHPSynWaveForm(wfs[1], null); } else if (subb_HH.l2Norm < 0f) { subb_HH.calcBasisWaveForms(wfs); wfs[0] = hFilter.getHPSynWaveForm(wfs[0], null); wfs[1] = vFilter.getHPSynWaveForm(wfs[1], null); } else { // There is an error! If all childs have // non-negative l2norm, then this node should have // non-negative l2norm throw new Error("You have found a bug in JJ2000!"); } } else { // This is a leaf, just use diracs (null is // equivalent to dirac) wfs[0] = new float[1]; wfs[0][0] = 1.0f; wfs[1] = new float[1]; wfs[1][0] = 1.0f; } } else { // This is an error! The calcBasisWaveForms() method is // never called on an element with non-negative l2norm throw new Error("You have found a bug in JJ2000!"); } }
/** * Returns the next subband that will be used to get the next code-block to return by the * getNext[Intern]CodeBlock method. * * @param c The component * @return Its returns the next subband that will be used to get the next code-block to return by * the getNext[Intern]CodeBlock method. */ private SubbandAn getNextSubband(int c) { int down = 1; int up = 0; int direction = down; SubbandAn nextsb; nextsb = currentSubband[c]; // If it is the first call to this method if (nextsb == null) { nextsb = this.getAnSubbandTree(tIdx, c); // If there is no decomposition level then send the whole image if (!nextsb.isNode) { return nextsb; } } // Find the next subband to send do { // If the current subband is null then break if (nextsb == null) { break; } // If the current subband is a leaf then select the next leaf to // send or go up in the decomposition tree if the leaf was a LL // one. else if (!nextsb.isNode) { switch (nextsb.orientation) { case Subband.WT_ORIENT_HH: nextsb = (SubbandAn) nextsb.getParent().getLH(); direction = down; break; case Subband.WT_ORIENT_LH: nextsb = (SubbandAn) nextsb.getParent().getHL(); direction = down; break; case Subband.WT_ORIENT_HL: nextsb = (SubbandAn) nextsb.getParent().getLL(); direction = down; break; case Subband.WT_ORIENT_LL: nextsb = (SubbandAn) nextsb.getParent(); direction = up; break; } } // Else if the current subband is a node else if (nextsb.isNode) { // If the direction is down the select the HH subband of the // current node. if (direction == down) { nextsb = (SubbandAn) nextsb.getHH(); } // Else the direction is up the select the next node to cover // or still go up in the decomposition tree if the node is a LL // subband else if (direction == up) { switch (nextsb.orientation) { case Subband.WT_ORIENT_HH: nextsb = (SubbandAn) nextsb.getParent().getLH(); direction = down; break; case Subband.WT_ORIENT_LH: nextsb = (SubbandAn) nextsb.getParent().getHL(); direction = down; break; case Subband.WT_ORIENT_HL: nextsb = (SubbandAn) nextsb.getParent().getLL(); direction = down; break; case Subband.WT_ORIENT_LL: nextsb = (SubbandAn) nextsb.getParent(); direction = up; break; } } } if (nextsb == null) { break; } } while (nextsb.isNode); return nextsb; }