예제 #1
0
  /**
   * 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!");
    }
  }
예제 #2
0
  /**
   * 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
    }
  }
예제 #4
0
  /**
   * 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);
    }
  }
예제 #5
0
  /**
   * 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!");
    }
  }
예제 #6
0
  /**
   * 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;
  }