/**
   * Computes the geodesic distance function for each pixel in mask, using the given mask. Mask and
   * marker should be ImageProcessor the same size and containing float values. The function returns
   * a new Float processor the same size as the input, with values greater or equal to zero.
   */
  @Override
  public FloatProcessor geodesicDistanceMap(ImageProcessor marker, ImageProcessor mask) {
    // size of image
    width = mask.getWidth();
    height = mask.getHeight();

    // update mask
    this.maskProc = mask;

    // create new empty image, and fill it with black
    FloatProcessor result = new FloatProcessor(width, height);
    result.setValue(0);
    result.fill();

    // initialize empty image with either 0 (foreground) or Inf (background)
    array = result.getFloatArray();
    for (int i = 0; i < width; i++) {
      for (int j = 0; j < height; j++) {
        int val = marker.get(i, j) & 0x00ff;
        array[i][j] = val == 0 ? backgroundValue : 0;
      }
    }

    int iter = 0;
    do {
      modif = false;

      // forward iteration
      IJ.showStatus("Forward iteration " + iter);
      forwardIteration();

      // backward iteration
      IJ.showStatus("Backward iteration " + iter);
      backwardIteration();

      // Iterate while pixels have been modified
      iter++;
    } while (modif);

    // Normalize values by the first weight
    if (this.normalizeMap) {
      for (int i = 0; i < width; i++) {
        for (int j = 0; j < height; j++) {
          array[i][j] /= this.weights[0];
        }
      }
    }

    // Compute max value within the mask
    float maxVal = 0;
    for (int i = 0; i < width; i++) {
      for (int j = 0; j < height; j++) {
        if (maskProc.getPixel(i, j) != 0) maxVal = Math.max(maxVal, array[i][j]);
      }
    }

    // update and return resulting Image processor
    result.setFloatArray(array);
    result.setMinAndMax(0, maxVal);
    // Forces the display to non-inverted LUT
    if (result.isInvertedLut()) result.invertLut();
    return result;
  }