Q:

Processing an image in parallel using java 8

I am processing a plenty of 4k images by calculating a parameter on small (64X64 pixel) patches of the image. The task is now being carried out in a sequential fashion, one patch at a time. A snippet of my code is copied below to show you the idea.
for (int i = 0; i < imageW / pSize; i++) {
  for (int j = 0; j < imageH / pSize; j++) {

  thisPatch = MatrixUtil.getSubMatrixAsMatrix(image, i * pSize, j * pSize, pSize);
  results[i][j] = computeParamForPatch(thisPatch);
  }
}

I now need to parallelize this to possibly save some time. As you can see, the process for each patch is completely independent from all others. To do so, I either need to remember the location of each patch by using a Map or use forEachOrdered(). Unfortunately I don't think using maps, something like Map<Point, double[][]> would be parallelized. So this is my question: Apart from using forEachOrdered() which affects the performance negatively, is there any other way to process an image in parallel?

One solution:
I tried the following code (suggested by @DHa) which makes a significant improvement:
int outputW = imageW / pSize;
int outputH = imageH / pSize;
IntStream.range(0, outputW * outputH).parallel().forEach(i -> {

 int x = (i % outputW);
 int y = (i / outputH);
 tDirectionalities[x][y] = computeDirectionalityForPatch(
                    MatrixUtil.computeParamForPatch(image, x * pSize, y * pSize, pSize));
});

Results:

Sequential: 15754 ms
Parallel: 5899 ms

A:

This solution uses a parallel stream.
See also How many threads are spawned in parallelStream in Java 8 for how to control amount of threads that work on the stream simultaneously.
    int patchWidth = (int)Math.ceil((double)imageW / pSize);
    int patchHeight = (int)Math.ceil((double)imageH / pSize);

    IntStream.range(0, patchWidth * patchHeight).parallel().forEach(i -> {
        int x = (i % patchWidth);
        int y = (i / patchWidth);

        thisPatch = MatrixUtil.getSubMatrixAsMatrix(image, x * pSize, y * pSize, pSize);
        results[x][y] = computeParamForPatch(thisPatch);
    });

