2

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);
8
  • Please post more code. Commented Apr 24, 2015 at 13:00
  • @Okas I have now added the full motion blur method Commented Apr 24, 2015 at 13:42
  • 1
    Try to calculate how much memory you are trying to allocate ie what are the height and width values etc. Looking at your code it looks quite possible that you are just allocating too much memory and actually there is no leak. Commented Apr 24, 2015 at 13:45
  • @Okas it doesn't look like the loops are allocating too much. Even if they are repeatedly created, they are mostly primitives. The biggest concern is a leak to complex somewhere outside the method. Check to see if there is a constructor not properly dereferencing the object. Commented Apr 24, 2015 at 13:52
  • 1
    So size of temp array will be 2 * 2000 * 2000 * 8 bytes (size of double) that will be a little less than 64 megabytes. Why do you think you can allocate that much? Commented Apr 24, 2015 at 14:16

1 Answer 1

3

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!

Sign up to request clarification or add additional context in comments.

1 Comment

For tracking down OOM, do a heap dump and analyze it using eclipse.org/mat

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.