0

I made an image viewer project with a TouchImageView to implement zoom, drag and fling, a panorama viewer, etc.

The viewer works fine, except that I get OutOfMemory errors when rotating the device, specially for panoramas (not really big, 3.5 MB should be easily handled by a Galaxy Note). This is the offending line:

final Bitmap myBitmap = BitmapFactory.decodeFile(filename);

Of course, since it is a panorama, I want to zoom, so compressing the image at decoding time, as suggested here, is not an option (I've tried it, and works, but the low quality kills the idea of a panorama).

I don't think there's a memory leak in my project, since it is not memory intensive, only freezes at rotation, and the offending line is executed only once at rotation. I can see the panorama freezing diagonally in the screen. I think the problem is the "rotation animation" of the ImageView. Maybe I should disable it? If so, how?

Below is the crash log.

Thanks!!

LOG-

58:38.845: W/dalvikvm(2465): threadid=1: thread exiting with uncaught exception (group=0x40c531f8)
12-24 02:58:38.850: E/AndroidRuntime(2465): FATAL EXCEPTION: main
12-24 02:58:38.850: E/AndroidRuntime(2465): java.lang.OutOfMemoryError
12-24 02:58:38.850: E/AndroidRuntime(2465):     at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
12-24 02:58:38.850: E/AndroidRuntime(2465):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:587)
12-24 02:58:38.850: E/AndroidRuntime(2465):     at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:389)
12-24 02:58:38.850: E/AndroidRuntime(2465):     at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:418)
12-24 02:58:38.850: E/AndroidRuntime(2465):     at com.floritfoto.apps.xvf.Foto.pic(Foto.java:180)
12-24 02:58:38.850: E/AndroidRuntime(2465):     at com.floritfoto.apps.xvf.Foto.onCreate(Foto.java:383)
12-24 02:58:38.850: E/AndroidRuntime(2465):     at android.app.Activity.performCreate(Activity.java:4465)
12-24 02:58:38.850: E/AndroidRuntime(2465):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1052)
12-24 02:58:38.850: E/AndroidRuntime(2465):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1932)
12-24 02:58:38.850: E/AndroidRuntime(2465):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1993)
12-24 02:58:38.850: E/AndroidRuntime(2465):     at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3363)
12-24 02:58:38.850: E/AndroidRuntime(2465):     at android.app.ActivityThread.access$700(ActivityThread.java:127)
12-24 02:58:38.850: E/AndroidRuntime(2465):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1163)
12-24 02:58:38.850: E/AndroidRuntime(2465):     at android.os.Handler.dispatchMessage(Handler.java:99)
12-24 02:58:38.850: E/AndroidRuntime(2465):     at android.os.Looper.loop(Looper.java:137)
12-24 02:58:38.850: E/AndroidRuntime(2465):     at android.app.ActivityThread.main(ActivityThread.java:4507)
12-24 02:58:38.850: E/AndroidRuntime(2465):     at java.lang.reflect.Method.invokeNative(Native Method)
12-24 02:58:38.850: E/AndroidRuntime(2465):     at java.lang.reflect.Method.invoke(Method.java:511)
12-24 02:58:38.850: E/AndroidRuntime(2465):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:980)
12-24 02:58:38.850: E/AndroidRuntime(2465):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:747)
12-24 02:58:38.850: E/AndroidRuntime(2465):     at dalvik.system.NativeStart.main(Native Method)
Community
  • 1
  • 1
Luis A. Florit
  • 2,169
  • 1
  • 33
  • 58
  • 2
    **Rotated**? I expect your activity is destroyed and recreated is it? If it is, have you called ``recycle()`` to your bitmap before your activity destroyed? –  Dec 24 '12 at 05:53
  • Oh, I had no idea about this `recycle()` thing! I put it below the offending line, and crashed. But then I put it in the `onDestroy()` method as described here http://stackoverflow.com/a/7009362/1483390 (this is what you meant??) and it seems to work! Thanks!! – Luis A. Florit Dec 24 '12 at 06:11
  • Yep, that was my mistake (forgetting to recycle the bitmap) –  Dec 24 '12 at 06:16
  • The mistake (actually, ignorance) was mine, and you solved it. Thanks again! :) – Luis A. Florit Dec 24 '12 at 06:20

2 Answers2

0

First try to debug the Code and check the Heap Size how it Increase and then Look on the Following Link

to understand how android calculate the Image size with its dimensions . To scale down the Image you can try the Below code if you want to scale down programetically

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;
}

if you want to manually scale down the Size you can change the dimension of the image approximatly half of its orignal dimension

Usman Kurd
  • 7,212
  • 7
  • 57
  • 86
  • As I wrote, I tried this kind of solutions. It's a panorama viewer, so I actually do not want to scale down, you loose too much quality. And the Zoom function will be destroyed. – Luis A. Florit Dec 24 '12 at 06:14
-2

try with this function..

public static Bitmap decodeFile(File f,int WIDTH,int HIGHT){
        try {
            //Decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(new FileInputStream(f),null,o);

            //The new size we want to scale to
            final int REQUIRED_WIDTH=WIDTH;
            final int REQUIRED_HIGHT=HIGHT;
            //Find the correct scale value. It should be the power of 2.
            int scale=1;
            while(o.outWidth/scale/2>=REQUIRED_WIDTH && o.outHeight/scale/2>=REQUIRED_HIGHT)
                scale*=2;

            //Decode with inSampleSize
            BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize=scale;
            return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
        } catch (FileNotFoundException e) {}
        return null;
    }
Sanket Kachhela
  • 10,861
  • 8
  • 50
  • 75
  • 2
    if it is not your effort mention the link from where you took it,, – Amit Hooda Dec 24 '12 at 06:01
  • than use google why are you on SO? and i don't want upvote but why downvote? – Sanket Kachhela Dec 24 '12 at 06:05
  • 1
    @SanketKachhela Because firstly, you've made no attempt to answer the question. Throwing code at people is not helpful in any way and does not promote learning, which is what this site is for. Secondly, according to the [StackOverflow content license](http://blog.stackoverflow.com/2009/06/stack-overflow-creative-commons-data-dump/), all content from other sources *must* be attributed. [(1)](http://meta.stackexchange.com/q/83955/192960) [(2)](http://meta.stackexchange.com/q/87175/192960) [(3)](http://meta.stackexchange.com/q/122056/192960) – Cat Dec 24 '12 at 06:09