Image filtering application I'm building an image filtering application, and I'm new to the Java frameworks that I need to do so. Right now, I can apply a simple 3x3 kernel blur to my thing by overwriting the RGB values of the destination picture pixel by pixel using the RGB averages from the original photo. I'm trying to increase the speed at which I can perform these filter calculations so there's less lag in my app.

I've done some surface level optimization, but if there's anything you see that could better utilize the cache or an entirely different framework that's faster than BufferedImage.getRGB(), I'd love to hear!

public void boxBlur(ImageView iv) {
       for (int height = 0; height &lt; sourceImage.getHeight(); height++) {
           for (int width = 0; width &lt; sourceImage.getWidth(); width++) {
               int[][] kernel = new int[][]{ // Contruct RGB array to manipulate. Edges are accounted for in construction
                   {(height == 0 || width == 0) ? sourceImage.getRGB(width, height) : sourceImage.getRGB(width - 1, height - 1), (height == 0) ? sourceImage.getRGB(width, height) : sourceImage.getRGB(width, height - 1), (height == 0 || width &gt;= sourceImage.getWidth() - 1) ? sourceImage.getRGB(width, height) : sourceImage.getRGB(width + 1, height - 1)},
                   {(width == 0) ? sourceImage.getRGB(width, height) : sourceImage.getRGB(width - 1, height), sourceImage.getRGB(width, height), (width == sourceImage.getWidth() - 1) ? sourceImage.getRGB(width, height) : sourceImage.getRGB(width + 1, height)},
                   {(height &gt;= sourceImage.getHeight() - 1 || width == 0) ? sourceImage.getRGB(width, height) : sourceImage.getRGB(width - 1, height + 1), (height &gt;= sourceImage.getHeight() - 1) ? sourceImage.getRGB(width, height) : sourceImage.getRGB(width, height + 1), (height &gt;= sourceImage.getHeight() - 1 || width &gt;= sourceImage.getWidth() - 1) ? sourceImage.getRGB(width, height) : sourceImage.getRGB(width + 1, height + 1)}
               };
               int redAvg = 0, blueAvg = 0, greenAvg = 0;
               for (int i[] : kernel) {
                   for (int j : i) {
                       redAvg += getRed(j); // Get bitwise value from RGB int
                       greenAvg += getGreen(j);
                       blueAvg += getBlue(j);
                   }
               }
               redAvg /= 9; // 9 is size of kernel
               greenAvg /= 9;
               blueAvg /= 9;
               destinationImage.setRGB(width, height, 65536 * redAvg + 256 * greenAvg + blueAvg); // setRGB() takes the integer value of an rgb color
           }
       }
       iv.setImage(updateDisplay());
   }
Throwaway memory

I haven't done any analysis on the code but based on my experience the worst part is the allocation of throwaway memory inside the innermost loop. Instead of allocating a 3x3 array 9 million times and throwing it to the garbage colletor immediately, allocate it once at the start of the method and reuse it in the loop.

int[][] kernel = new int[][] { ... }


Repeated calculations

Second obvious thing is the repeating of same mathematical operations. You calculate the right and bottom border several times inside the innermost loop even though the result never changes during the image processing. Calculate these at the start of the method and store the results to local variables:

sourceImage.getHeight() - 1
sourceImage.getWidth() - 1


Sacrifice readability for performance

After solving the obvious parts, you can start breaking good coding conventions. The only reason you have those mile long unreadable ternary operations is to handle the edge cases that affect 0.1% of your data. Take out the easy code inside the edges that covers 99.9% of your running time, that doesn't need any bounds checking, and make it as fast as possible. Then make a separate loop that handle only the edges.

Bad variable naming

The choice of loop variables are bad. Width and height are constants of the image that refer to the right and bottom border. You are using these names to refer to single pixels inside the image. The correct names here would be x and y. This makes following your code extremely difficult.

Refer to the good old StackOverflow-side of this site for more info about accessing the color values directly:

https://stackoverflow.com/questions/37779515/how-can-i-convert-an-imageview-to-byte-array-in-android-studio