/**
  * This method will be called when the mouse is clicked over the image being displayed. The
  * coordinates and pixel value will be stored on an ArrayList.
  *
  * @param me the mouse event that caused the execution of this method.
  */
 public void mouseClicked(MouseEvent me) {
   int x = me.getX();
   int y = me.getY();
   System.out.println("Storing " + x + "," + y);
   if ((x >= width) || (y >= height)) {
     clicksInformation.add("No data!");
     return;
   }
   if (isDoubleType) // process the pixel as an array of double values
   {
     StringBuffer coords = new StringBuffer();
     coords.append(x + "," + y + " [");
     readIterator.getPixel(x, y, dpixel); // read the pixel
     for (int b = 0; b < dpixel.length; b++)
       coords.append(dpixel[b] + ","); // append to the StringBuffer
     coords.deleteCharAt(coords.length() - 1); // erase last comma
     coords.append("]");
     // Put the formatted StringBuffer on the
     clicksInformation.add(coords.toString());
   } else // pixel type is not floating point, will be processed as integers.
   {
     if (isIndexed) // if color model is indexed
     {
       StringBuffer coords = new StringBuffer();
       coords.append(x + "," + y + " ");
       readIterator.getPixel(x, y, ipixel); // read the pixel
       // Assume ipixel.length = 1
       coords.append("Index: " + ipixel[0] + " [");
       // Add also the RGB entry from the LUT.
       coords.append(
           " RGB:"
               + lutData[0][ipixel[0]]
               + ","
               + lutData[1][ipixel[0]]
               + ","
               + lutData[2][ipixel[0]]);
       coords.append("]");
       // Put the formatted StringBuffer on the
       clicksInformation.add(coords.toString());
     } else // pixels are of integer type, but not indexed
     {
       StringBuffer coords = new StringBuffer();
       coords.append(x + "," + y + " [");
       readIterator.getPixel(x, y, ipixel); // read the pixel
       for (int b = 0; b < ipixel.length; b++)
         coords.append(ipixel[b] + ","); // append to the StringBuffer
       coords.deleteCharAt(coords.length() - 1); // erase last comma
       coords.append("]");
       // Put the formatted StringBuffer on the
       clicksInformation.add(coords.toString());
     }
   } // pixel is integer type
 } // end of method mouseClicked
  public double[] findNeighPixel(
      PlanarImage im,
      int x,
      int y,
      int width,
      int height,
      SampleModel sm,
      int nbands,
      RandomIter iterator) {
    double[] SumPixels = new double[nbands];
    double[] pixel = new double[nbands];
    int numPointsUsed = 0;
    int numNeighborsToConsider = 30;
    for (int h = Math.max(y - numNeighborsToConsider, 0);
        h < Math.min(y + numNeighborsToConsider, height);
        h++) {
      for (int w = Math.max(x - numNeighborsToConsider, 0);
          w < Math.min(x + numNeighborsToConsider, width);
          w++) {
        // Get the array of values for the pixel on the w,h coordinate.
        iterator.getPixel(w, h, pixel);
        // Add the values.
        if (!isWhite(pixel) && !isBlack(pixel)) {
          for (int i = 0; i < nbands; i++) {
            SumPixels[i] += pixel[i];
          }
          numPointsUsed++;
        }
      }
    }
    if (numPointsUsed > 0) {
      for (int i = 0; i < nbands; i++) {
        pixel[i] = SumPixels[i] / numPointsUsed;
      }
    } else {
      pixel = new double[] {0, 0, 0};
    }

    return pixel;
  }
  /*
   * This method averages the pixel values around a central point and return the
   * average as an instance of Color. The point coordinates are proportional to
   * the image.
   */
  private Color averageAround(BufferedImage i, double px, double py) {
    // Get an iterator for the image.
    RandomIter iterator = RandomIterFactory.create(i, null);
    // Get memory for a pixel and for the accumulator.
    double[] pixel = new double[i.getSampleModel().getNumBands()];
    double[] accum = new double[3];
    int numPixels = 0;
    // Sample the pixels.

    for (double x = px * i.getWidth() - sampleSize; x < px * i.getWidth() + sampleSize; x++) {
      for (double y = py * i.getHeight() - sampleSize; y < py * i.getHeight() + sampleSize; y++) {
        iterator.getPixel((int) x, (int) y, pixel);
        accum[0] += pixel[0];
        accum[1] += pixel[1];
        accum[2] += pixel[2];
        numPixels++;
      }
    }
    // Average the accumulated values.
    accum[0] /= numPixels;
    accum[1] /= numPixels;
    accum[2] /= numPixels;
    return new Color((int) accum[0], (int) accum[1], (int) accum[2]);
  }
  public double[][] PlanarImage2DataGrid(PlanarImage img, String EmageType) {
    double[][] BucketArray = new double[img.getHeight()][img.getWidth()];

    int width = img.getWidth();
    int height = img.getHeight();

    // Get the number of bands on the image.
    SampleModel sm = img.getSampleModel();
    int nbands = sm.getNumBands();

    // We assume that we can get the pixels values in a integer array.
    double[] pixel = new double[nbands];

    // Get an iterator for the image.
    RandomIter iterator = RandomIterFactory.create(img, null);

    if (ignoreColorSamplesBeyond > -1) {

      for (int i = 0; i < width; i++) {
        for (int j = 0; j < height; j++) {

          iterator.getPixel(i, j, pixel);

          double curDiff = 999999999;
          double diff = 0;
          int curBucket = -1;
          for (int i2 = 0; i2 < colorMatrix.length; i2++) {
            for (int j2 = 0; j2 < Math.min(nbands, colorMatrix[0].length); j2++) {
              diff += (pixel[j2] - colorMatrix[i2][j2]) * (pixel[j2] - colorMatrix[i2][j2]);
            }
            if (diff < curDiff) {
              curDiff = diff;
              curBucket = i2;
            }
            // log.info("i: " + i2 + ", val: " + diff);
            diff = 0;
          }
          if (curBucket >= ignoreColorSamplesBeyond) curBucket = -1;
          BucketArray[j][i] =
              (curBucket
                  + 1); // *255 / (colorMatrix.length); actually show the categories not normalized
                        // to 255 now.
          // if(curBucket >= 0)	log.info(curBucket + "," + BucketArray[j][i]);
        }
      }
    } else {
      log.info("Ignoring any binning. Going with gray values");
      for (int i = 0; i < height; i++) {

        for (int j = 0; j < width; j++) {
          int sumChannels = 0;

          iterator.getPixel(j, i, pixel);
          for (int j2 = 0; j2 < nbands; j2++) {
            sumChannels += pixel[j2];
          }
          BucketArray[i][j] = (sumChannels) / (nbands);
        }
      }
    }
    return BucketArray;
  }
  public PlanarImage PostProcessEmage(PlanarImage img) {
    if (maskImgFName != null) {
      int width = img.getWidth();
      int height = img.getHeight();

      // Get the number of bands on the image.
      SampleModel sm = img.getSampleModel();
      int nbands = sm.getNumBands();

      // We assume that we can get the pixels values in a integer array.
      double[] pixel = new double[nbands];

      // Get an iterator for the image.
      RandomIter iterator = RandomIterFactory.create(img, null);
      WritableRaster rasterImage =
          RasterFactory.createBandedRaster(
              DataBuffer.TYPE_BYTE, width, height, nbands, new Point(0, 0));

      double[] pixelNeighb = new double[nbands];
      double[] pixelblack = new double[nbands];
      for (int i = 0; i < nbands; i++) {
        pixelNeighb[i] = 0;
        pixelblack[i] = 0;
      }

      PlanarImage mask = JAI.create("FileLoad", maskImgFName);
      RandomIter iteratorMask = RandomIterFactory.create(mask, null);
      double[] pixelMask = new double[mask.getSampleModel().getNumBands()];

      for (int i = 0; i < width; i++) {
        for (int j = 0; j < height; j++) {
          iteratorMask.getPixel(i, j, pixelMask);
          if (!isBlack(pixelMask)) {
            iterator.getPixel(i, j, pixel);
            if (isWhite(pixel)) {;
            } else {
              rasterImage.setPixel(i, j, pixel);
            }
          } else {
            rasterImage.setPixel(i, j, pixelblack);
          }
        }
      }
      SampleModel sModel2 =
          RasterFactory.createBandedSampleModel(DataBuffer.TYPE_BYTE, width, height, nbands);

      // Try to create a compatible ColorModel - if the number of bands is
      // larger than 4, it will be null.
      ColorModel cModel2 = PlanarImage.createColorModel(sModel2);

      // Create a TiledImage using the sample and color models.
      TiledImage processedImage = new TiledImage(0, 0, width, height, 0, 0, sModel2, cModel2);

      // Set the data of the tiled image to be the raster.
      processedImage.setData(rasterImage);

      // Save the image to a file.
      try {
        ImageIO.write(processedImage, "jpg", new File("proc_" + theme + ".jpg"));
      } catch (IOException e) {
        log.error(e.getMessage());
      }

      // Save the image on a file.
      return processedImage;
    } else {
      // Save the image to a file.
      try {
        ImageIO.write(img, "jpg", new File("NOTproc_" + theme + ".jpg"));
      } catch (IOException e) {
        log.error(e.getMessage());
      }
      return img;
    }
  }
  public PlanarImage createRectifiedImage(PlanarImage Image) {
    int nRows = params.getNumOfRows();
    int nCols = params.getNumOfColumns();
    Point rectifiedPoint;

    // Get the image dimensions of the unrectified image
    int width = Image.getWidth();
    int height = Image.getHeight();
    log.info(nRows + ", " + nCols + "\t" + width + ", " + height);
    // Get an iterator for the image.
    RandomIter iterator = RandomIterFactory.create(Image, null);

    // Get the number of bands on the image.
    SampleModel smO = Image.getSampleModel();
    int nbandsO = smO.getNumBands();

    // We assume that we can get the pixels values in a integer array.
    double[] pixelO = new double[nbandsO];

    // Get an iterator for the image.
    WritableRaster rasterPollenO =
        RasterFactory.createBandedRaster(
            DataBuffer.TYPE_BYTE, nCols, nRows, nbandsO, new Point(0, 0));

    for (int i = 0; i < nCols; i++) {
      for (int j = 0; j < nRows; j++) {
        rectifiedPoint =
            this.getMatchingCoord(
                new Point(i + 1, j + 1)); // coz java array start at 0 matlab its 1.
        if (rectifiedPoint.x >= 1
            && rectifiedPoint.x < width
            && rectifiedPoint.y >= 1
            && rectifiedPoint.y < height) {
          iterator.getPixel(rectifiedPoint.x - 1, rectifiedPoint.y - 1, pixelO);
          rasterPollenO.setPixel(i, j, pixelO);
          // log.info("setpixel: " + i + ", " + j  + ", value " + pixelO[0] + ", " + pixelO[1] + ",
          // " + pixelO[2] + ", " + pixelO[3]);
        } else {

        }
      }
    }

    SampleModel sModel2 =
        RasterFactory.createBandedSampleModel(DataBuffer.TYPE_BYTE, nCols, nRows, nbandsO);

    // Try to create a compatible ColorModel - if the number of bands is
    // larger than 4, it will be null.
    ColorModel cModel2 = PlanarImage.createColorModel(sModel2);

    // Create a TiledImage using the sample and color models.
    TiledImage rectPollenImage = new TiledImage(0, 0, nCols, nRows, 0, 0, sModel2, cModel2);

    // log.info(rasterPollenO.getMinX() + ", " + rasterPollenO.getMinY() );
    // Set the data of the tiled image to be the raster.
    rectPollenImage.setData(rasterPollenO);

    // Save the image to a file.
    try {
      ImageIO.write(rectPollenImage, "jpg", new File("rect" + theme + ".jpg"));
    } catch (IOException e) {
      log.error(e.getMessage());
    }
    return rectPollenImage;
  }