/** Computes the phase correlation between two images. */
  public static void runTestPhaseCorrelationImageAlignment() throws FileNotFoundException {
    Log.setLogLevel(LogType.VERBOSE);
    Debug.setDebugLevel(DebugType.VERBOSE);

    Log.msg(LogType.MANDATORY, "Running Test Phase Correlation Image Alignment Java");

    // Read two images.
    File file1 = new File("F:\\StitchingData\\70perc_input_images\\F_2420.tif");
    File file2 = new File("F:\\StitchingData\\70perc_input_images\\F_2421.tif");

    // File file1 = new File("F:\\StitchingData\\70perc_input_images\\F_0001.tif");
    // File file2 = new File("F:\\StitchingData\\70perc_input_images\\F_0002.tif");

    JavaImageTile t1 = new JavaImageTile(file1, 0, 0, 2, 2, 0, 0);
    JavaImageTile t2 = new JavaImageTile(file2, 1, 0, 2, 2, 0, 0);

    JavaImageTile.initJavaPlan(t1);

    TimeUtil.tick();
    TileWorkerMemory memory = new JavaTileWorkerMemory(t1);

    CorrelationTriple result = Stitching.phaseCorrelationImageAlignmentJava(t1, t2, memory);

    Log.msg(
        LogType.MANDATORY,
        "Completed image alignment between "
            + t1.getFileName()
            + " and "
            + t2.getFileName()
            + " with "
            + result.toString()
            + " in "
            + TimeUtil.tock()
            + "ms");

    Log.msg(LogType.MANDATORY, "Test Completed.");
  }
  @Override
  public void run() {
    try {

      List<CorrelationTriple> multi_ccfs = new ArrayList<CorrelationTriple>();

      while (!this.isCancelled && (count < this.numNeighbors)) {
        multi_ccfs.clear();
        StitchingTask<T> task = this.ccfQueue.take();

        Debug.msg(
            DebugType.VERBOSE,
            "WP Task acquired: "
                + task.getTask()
                + "  size: "
                + this.ccfQueue.size()
                + " count: "
                + count);

        if (task.getTask() == TaskType.CCF_DONE) {
          break;
        } else if (task.getTask() == TaskType.CCF) {
          int[] indices = task.getIndices();
          ImageTile<T> tile = task.getTile();
          ImageTile<T> neighbor = task.getNeighbor();
          boolean north = false;
          boolean west = false;
          if (tile.isSameRowAs(neighbor)) west = true;
          else north = true;

          for (int index : indices) {
            int x = index % tile.getWidth();
            int y = index / tile.getWidth();

            if (west) multi_ccfs.add(Stitching.peakCrossCorrelationLR(neighbor, tile, x, y));
            else if (north) multi_ccfs.add(Stitching.peakCrossCorrelationUD(neighbor, tile, x, y));
          }

          CorrelationTriple corr = Collections.max(multi_ccfs);
          if (north) {
            tile.setNorthTranslation(corr);
            Log.msg(
                LogType.HELPFUL,
                "N: "
                    + tile.getFileName()
                    + " -> "
                    + neighbor.getFileName()
                    + " x: "
                    + tile.getNorthTranslation().getMatlabFormatStrX()
                    + " y: "
                    + tile.getNorthTranslation().getMatlabFormatStrY()
                    + " ccf: "
                    + tile.getNorthTranslation().getMatlatFormatStrCorr());
            incProgressBar();

            incCount();

            decrementAndReleasePixels(tile);
            decrementAndReleasePixels(neighbor);
          } else if (west) {
            tile.setWestTranslation(corr);
            Log.msg(
                LogType.HELPFUL,
                "W: "
                    + tile.getFileName()
                    + " -> "
                    + neighbor.getFileName()
                    + " x: "
                    + tile.getWestTranslation().getMatlabFormatStrX()
                    + " y: "
                    + tile.getWestTranslation().getMatlabFormatStrY()
                    + " ccf: "
                    + tile.getWestTranslation().getMatlatFormatStrCorr());

            incProgressBar();
            incCount();

            decrementAndReleasePixels(tile);
            decrementAndReleasePixels(neighbor);
          }

        } else if (task.getTask() == TaskType.CANCELLED) {
          this.isCancelled = true;
        }
      }

      Debug.msg(DebugType.HELPFUL, "CCF Done");

      // Signal other workers that may be waiting to finish
      this.ccfQueue.put(new StitchingTask<T>(null, null, TaskType.SENTINEL));

    } catch (InterruptedException e) {
      Log.msg(LogType.MANDATORY, "Interrupted CCF worker");
    }
  }