1

I have hundreds of images in my virtual magazine. The images are 1241* 1754 pixels with 150 pixels/inch resolution. After sliding to 3/4 of those pages i get an out of memory error as shown in the log.

12-04 10:20:50.781: E/AndroidRuntime(3236): java.lang.OutOfMemoryError
12-04 10:20:50.781: E/AndroidRuntime(3236):     at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
12-04 10:20:50.781: E/AndroidRuntime(3236):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:572)
12-04 10:20:50.781: E/AndroidRuntime(3236):     at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:440)
12-04 10:20:50.781: E/AndroidRuntime(3236):     at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:773)
12-04 10:20:50.781: E/AndroidRuntime(3236):     at android.content.res.Resources.loadDrawable(Resources.java:1974)
12-04 10:20:50.781: E/AndroidRuntime(3236):     at android.content.res.Resources.getDrawable(Resources.java:677)
12-04 10:20:50.781: E/AndroidRuntime(3236):     at fi.harism.curl.LPMagHome$PageProvider.loadBitmap(LPMagHome.java:192)
12-04 10:20:50.781: E/AndroidRuntime(3236):     at fi.harism.curl.LPMagHome$PageProvider.updatePage(LPMagHome.java:266)
12-04 10:20:50.781: E/AndroidRuntime(3236):     at fi.harism.curl.CurlView.updatePage(CurlView.java:713)
12-04 10:20:50.781: E/AndroidRuntime(3236):     at fi.harism.curl.CurlView.startCurl(CurlView.java:554)
12-04 10:20:50.781: E/AndroidRuntime(3236):     at fi.harism.curl.CurlView.onTouch(CurlView.java:280)
12-04 10:20:50.781: E/AndroidRuntime(3236):     at android.view.View.dispatchTouchEvent(View.java:5583)
12-04 10:20:50.781: E/AndroidRuntime(3236):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1968)
12-04 10:20:50.781: E/AndroidRuntime(3236):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1695)
12-04 10:20:50.781: E/AndroidRuntime(3236):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1968)
12-04 10:20:50.781: E/AndroidRuntime(3236):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1695)
12-04 10:20:50.781: E/AndroidRuntime(3236):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1968)

*

Here is part of my work that load the bitmap image. Can someone help me how to handle this out of memory error, through some researh i saw this blog java.lang.OutOfMemoryError BitmapFactory.nativeDecodeAsset() but i can't apply it to the method loadBitmap below.

private Bitmap loadBitmap(int width, int height, int index) {
            Bitmap b = Bitmap.createBitmap(width, height,
                    Bitmap.Config.ARGB_8888);
            b.eraseColor(0xFFFFFFFF);
            c = new Canvas(b);
            d = getResources().getDrawable(mBitmapIds[index]);
            System.out.println("canvas width: "+c.getWidth());

            int margin = 3;//7
            int border = 3;//2
            Rect r = new Rect(margin, margin, width - margin, height - margin);
            int imageWidth = r.width() - (border * 2);
            int imageHeight = imageWidth * d.getIntrinsicHeight()
                    / d.getIntrinsicWidth();
            if (imageHeight > r.height() - (border * 2)) {
                imageHeight = r.height() - (border * 2);
                imageWidth = imageHeight * d.getIntrinsicWidth()
                        / d.getIntrinsicHeight();
            }
            Log.d("TAG", String.valueOf(imageHeight));
            if (lp.getWindow().getWindowManager().getDefaultDisplay()
                    .getOrientation() == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
                // portrait mode
                r.left += ((r.width() - imageWidth) / 2) - border;
                r.right = r.left + imageWidth + border + border;
            } else if (lp.getWindow().getWindowManager().getDefaultDisplay()
                    .getOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
                // landscape
                r.left += ((r.width() - imageWidth)) - border-122;
                r.right = r.left + imageWidth + border + border+122;
            }
            r.top += ((r.height() - imageHeight) / 2) - border;
            r.bottom = r.top + imageHeight + border + border;
            Paint p = new Paint();
            p.setColor(0xFFC0C0C0);
            c.drawRect(r, p);
            r.left += border;
            r.right -= border;
            r.top += border;
            r.bottom -= border;
            d.setBounds(r);
            d.draw(c);
            return b;
        }*

UPDATE: The page are updated when sliding using this method

@Override public void updatePage(CurlPage page, int width, int height, int index) {

        DisplayMetrics displaymetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
        int wwidth = displaymetrics.widthPixels;
        int hheight = displaymetrics.heightPixels;


        if(wwidth > hheight){

            System.out.println("index "+(index*2));
            System.out.println("index2 "+(index*2)+1);
            System.out.println("case landscape orientation...");

            if (index >0){

                front = loadBitmap(width, height, (index*2));
                back = loadBitmap(width, height, (index*2)+1);

            }else {

                front = loadBitmap(width, height, (index));
                back = loadBitmap(width, height, (index));
            }

            Matrix matrix = new Matrix(); 
            matrix.preScale(-1.0f, 1.0f); 
            Bitmap mirroredBitmap = Bitmap.createBitmap(back, 0, 0, back.getWidth(), back.getHeight(), matrix, false);

            page.setTexture(front, CurlPage.SIDE_FRONT);
            page.setTexture(mirroredBitmap, CurlPage.SIDE_BACK);



        } else {

            System.out.println("case portrait orientation...");
            Bitmap front = loadBitmap(width, height, index);
            Bitmap back = loadBitmap(width, height, index);

            System.out.println( "MyActivity.onCreate debug message "+String.valueOf(index));

            page.setTexture(front, CurlPage.SIDE_FRONT);
            page.setTexture(back, CurlPage.SIDE_BACK);

        }

    }

}
Community
  • 1
  • 1
Dimitri
  • 1,924
  • 9
  • 43
  • 65
  • Have you seen this: http://stackoverflow.com/q/477572/827110? Also post you code (adapter or something) where you are swiping/displaying images.. – Amulya Khare Dec 04 '13 at 06:29
  • Do you store `page` objects in a list or something? The old `page` objects that have been viewed already are still alive in the memory causing the memory to overflow.. you will have to device a way to detect those pages that have been viewed and re-cycle the images in them. If you post more code then maybe I can give a concrete way of doing it – Amulya Khare Dec 04 '13 at 07:18
  • Hi Amulya I am using Harism page curl library https://github.com/harism/android_page_curl you can refer to it – Dimitri Dec 04 '13 at 07:20

5 Answers5

2

You are properbly leaking memory. Check that you free your memory by removing all references to it to avoid this problem. Also keep in mind that some devices have not much memory so you need to use less memory.

See also my answer about how to find memory leaks.

Community
  • 1
  • 1
rekire
  • 47,260
  • 30
  • 167
  • 264
2

You might have to resize your bitmaps.I also faced this issue and solved that with below code :

public static Bitmap getResizedBitmap(Bitmap image, int newHeight, int newWidth) {
    int width = image.getWidth();
    int height = image.getHeight();
    float scaleWidth = ((float) newWidth) / width;
    float scaleHeight = ((float) newHeight) / height;
    // create a matrix for the manipulation
    Matrix matrix = new Matrix();
    // resize the bit map
    matrix.postScale(scaleWidth, scaleHeight);
    // recreate the new Bitmap
    Bitmap resizedBitmap = Bitmap.createBitmap(image, 0, 0, width, height,
            matrix, false);
    return resizedBitmap;
}
Zankhna
  • 4,570
  • 9
  • 62
  • 103
  • resizing bitmap will reduce image resolution ? – Dimitri Dec 04 '13 at 06:36
  • It will not affect real images but it will change the resolution while displaying images.You are using large resolution images and therefore `OutofMemory` error is thrown. Recycling image is also advisable. – Zankhna Dec 04 '13 at 06:41
  • ok but i guess newHeight and newWidth are hardcoded int numbers – Dimitri Dec 04 '13 at 06:44
  • yes..they are hardcoded numbers. But you can also set their values according to device screen resolution. – Zankhna Dec 04 '13 at 06:46
  • Please look updates for the part where the image are updated and loaded on the view. – Dimitri Dec 04 '13 at 06:55
1

That a general issue while playing with lots of images. Nikita I suggest you to use an api library that takes care of loading the images, clearing the cache when image is out of foucs and other essential things. Here is the link of the github project, download the jar and add it to the libs folder of your project.

For Configuring the image check this.

Hardik4560
  • 3,202
  • 1
  • 20
  • 31
1

There maybe memory leak. You can call bitmap.recycle() , if that bitmap has no further use, to save memory. Also, you can try to scale down your bitmap:

Bitmap scale_down = Bitmap.createScaledBitmap(original_bmp, original_bmp.getWidth()/2, original_bmp.getHeight()/2, true);
Siu
  • 1,422
  • 1
  • 12
  • 17
0

I do not see your all codes , so I can only suppose that you put all image into memory . I thing that you could put the image what showing in screen into memory ,and the other image release from memory, This way can be realized and reduce the occupied memory,. Please read this :Strange out of memory issue while loading an image to a Bitmap object

I am sorry for my bad english!

Community
  • 1
  • 1
Simon Xu
  • 156
  • 5