/**
   * Fills the whole image with the specified pixel value
   *
   * @param img An image.
   * @param value The value that the image is being filled with.
   */
  public static void fill(ImageSInt64 img, long value) {
    final int h = img.getHeight();
    final int w = img.getWidth();

    long[] data = img.data;

    for (int y = 0; y < h; y++) {
      int index = img.getStartIndex() + y * img.getStride();
      for (int x = 0; x < w; x++) {
        data[index++] = value;
      }
    }
  }
  /**
   * Computes the mean squared error (MSE) between the two images.
   *
   * @param imgA first image. Not modified.
   * @param imgB second image. Not modified.
   * @return error between the two images.
   */
  public static double computeMeanSquaredError(ImageSInt64 imgA, ImageSInt64 imgB) {
    final int h = imgA.getHeight();
    final int w = imgA.getWidth();

    double total = 0;

    for (int y = 0; y < h; y++) {
      for (int x = 0; x < w; x++) {
        double difference = imgA.get(x, y) - imgB.get(x, y);
        total += difference * difference;
      }
    }

    return total / (w * h);
  }
  /**
   * Sets each value in the image to a value drawn from an uniform distribution that has a range of
   * min <= X < max.
   */
  public static void randomize(ImageSInt64 img, Random rand, long min, long max) {
    final int h = img.getHeight();
    final int w = img.getWidth();

    long range = max - min;

    long[] data = img.data;

    for (int y = 0; y < h; y++) {
      int index = img.getStartIndex() + y * img.getStride();
      for (int x = 0; x < w; x++) {
        data[index++] = rand.nextInt((int) range) + min;
      }
    }
  }
  /** Adds Gaussian/normal i.i.d noise to each pixel in the image. */
  public static void addGaussian(ImageSInt64 img, Random rand, double sigma, long min, long max) {
    final int h = img.getHeight();
    final int w = img.getWidth();

    long[] data = img.data;

    for (int y = 0; y < h; y++) {
      int index = img.getStartIndex() + y * img.getStride();
      for (int x = 0; x < w; x++) {
        long value = (data[index]) + (long) (rand.nextGaussian() * sigma);
        if (value < min) value = min;
        if (value > max) value = max;

        data[index++] = value;
      }
    }
  }