skelto
skelto

Reputation: 157

How to fix a memory leak in Android regarding array of arrays?

I've created an application that takes an image captured by the Android device, displays this image in the ImageView. The user can then press a button to either blur or deblur the image. When I run the application on my Android device I can take an image with the camera and display this without any problems. A problem occurs when I press the blur button, which runs some code to blur the image. The application becomes frozen and I get an OutOfMemoryException for a line of my code that creates a new array and stores this in another array in a nested for loop.

This is the code for the nested for loop:

for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
        int xTranslated = (x + width / 2) % width;
        int yTranslated = (y + height / 2) % height;

        double real = temp[2 * (xTranslated + yTranslated * width)];
        double imaginary = temp[2 * (xTranslated + yTranslated * width) + 1];

        degradation[2 * (x + y * width)] = real;
        degradation[2 * (x + y * width) + 1] = imaginary;

        Complex c = new Complex(real, imaginary);
        complex[y * width + x] = c;
    }
}

This nested for loop deals with data extracted from the input image, which is stored as a Bitmap.

Here is the full method that applies the motion blur:

public Complex[] motionBlur(double[] degradation, int width, int height, double alpha, double gamma, double sigma) {
    Complex[] complex = new Complex[width * height];

    double[] temp = new double[2 * width * height];

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            double teta = Math.PI * ( (((x - width/2) % width) * gamma) + ((((y - height/2) % height) * sigma) ));

            Sinc sinc = new Sinc();

            double real = (Math.cos(teta) * sinc.value(teta)) * alpha;
            double imaginary = (Math.sin(teta) * sinc.value(teta)) * alpha;

            Complex cConj = new Complex(real, imaginary).conjugate();

            temp[2 * (x + y * width)] = cConj.getReal();
            temp[2 * (x + y * width) + 1] = cConj.getImaginary();
        }
    }

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            int xTranslated = (x + width / 2) % width;
            int yTranslated = (y + height / 2) % height;

            double real = temp[2 * (xTranslated + yTranslated * width)];
            double imaginary = temp[2 * (xTranslated + yTranslated * width) + 1];

            degradation[2 * (x + y * width)] = real;
            degradation[2 * (x + y * width) + 1] = imaginary;

            Complex c = new Complex(real, imaginary);
            complex[y * width + x] = c;
        }
    }

    return complex;
}

Here is a link to what is being output by the logcat when I try to run the application: http://pastebin.com/ysbN9A3s

MainActivity.java:373 corresponds to the line,

Complex c = new Complex(real, imaginary);

Upvotes: 2

Views: 168

Answers (1)

Eugen Martynov
Eugen Martynov

Reputation: 20130

Here is nice talk about android crashes.

Pierre-Yves talks about OOM (OutOfMemory error) at the time 11:39. So the problem in OOM is not place where OOM happens. You should profile your app to find the place where most memory is consumed. I should admit that OOM is one of the hardest error to resolve.

Good luck!

Upvotes: 3

Related Questions