5

I have now tried a thousand times to solve this on my own without any success whatsoever. I've logged and debugged the application and from the information that I've gathered there is this one large spritesheet that is used for an animation. It's a .png with the size of 3000x1614 pixels. There are 10x6 sprites in the spritesheet that is essential for the animation. There are no gaps in between the sprites whatsoever to make it as memory-efficient as possible.

This is my method in which I load, decode and resize my bitmaps into the aspect ratio of the user's phone vs. my phone which I am building the game upon:

public Pixmap newResizedPixmap(String fileName, PixmapFormat format, double Width, double Height) {
    // TODO Auto-generated method stub
    Config config = null;
    if (format == PixmapFormat.RGB565)
        config = Config.RGB_565;
    else if (format == PixmapFormat.ARGB4444)
        config = Config.ARGB_4444;
    else
        config = Config.ARGB_8888;

    Options options = new Options();
    options.inPreferredConfig = config;
    options.inPurgeable=true;
    options.inInputShareable=true;
    options.inDither=false;

    InputStream in = null;
    Bitmap bitmap = null;
    try {
        //OPEN FILE INTO INPUTSTREAM
        in = assets.open(fileName);
        //DECODE INPUTSTREAM
        bitmap = BitmapFactory.decodeStream(in, null, options);

        if (bitmap == null)
            throw new RuntimeException("Couldn't load bitmap from asset '"+fileName+"'");
    } catch (IOException e) {
        throw new RuntimeException("Couldn't load bitmap from asset '"+fileName+"'");
    } finally {
        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
            }
        }
    }

    if (bitmap.getConfig() == Config.RGB_565)
        format = PixmapFormat.RGB565;
    else if (bitmap.getConfig() == Config.ARGB_4444)
        format = PixmapFormat.ARGB4444;
    else
        format = PixmapFormat.ARGB8888;

    //THIS IS WHERE THE OOM HAPPENS
    return new AndroidPixmap(Bitmap.createScaledBitmap(bitmap, (int)(Width+0.5f), (int)(Height+0.5f), true), format);
}

This is the LogCat output of the error:

05-07 12:57:18.570: E/dalvikvm-heap(636): Out of memory on a 29736016-byte allocation.
05-07 12:57:18.570: I/dalvikvm(636): "Thread-89" prio=5 tid=18 RUNNABLE
05-07 12:57:18.580: I/dalvikvm(636):   | group="main" sCount=0 dsCount=0 obj=0x414a3c78 self=0x2a1b1818
05-07 12:57:18.580: I/dalvikvm(636):   | sysTid=669 nice=0 sched=0/0 cgrp=apps handle=705796960
05-07 12:57:18.590: I/dalvikvm(636):   | schedstat=( 14462294890 67436634083 2735 ) utm=1335 stm=111 core=0
05-07 12:57:18.590: I/dalvikvm(636):   at android.graphics.Bitmap.nativeCreate(Native Method)
05-07 12:57:18.590: I/dalvikvm(636):   at android.graphics.Bitmap.createBitmap(Bitmap.java:640)
05-07 12:57:18.590: I/dalvikvm(636):   at android.graphics.Bitmap.createBitmap(Bitmap.java:586)
05-07 12:57:18.590: I/dalvikvm(636):   at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:466)
05-07 12:57:18.590: I/dalvikvm(636):   at com.NAME.framework.impl.AndroidGraphics.newResizedPixmap(AndroidGraphics.java:136)
05-07 12:57:18.590: I/dalvikvm(636):   at com.NAME.GAME.GameScreen.<init>(GameScreen.java:121)
05-07 12:57:18.600: I/dalvikvm(636):   at com.NAME.GAME.CategoryScreen.update(CategoryScreen.java:169)
05-07 12:57:18.600: I/dalvikvm(636):   at com.NAME.framework.impl.AndroidFastRenderView.run(AndroidFastRenderView.java:34)
05-07 12:57:18.600: I/dalvikvm(636):   at java.lang.Thread.run(Thread.java:856)
05-07 12:57:18.620: I/Choreographer(636): Skipped 100 frames!  The application may be doing too much work on its main thread.
05-07 12:57:18.670: W/dalvikvm(636): threadid=18: thread exiting with uncaught exception (group=0x40a13300)
05-07 12:57:18.720: E/AndroidRuntime(636): FATAL EXCEPTION: Thread-89
05-07 12:57:18.720: E/AndroidRuntime(636): java.lang.OutOfMemoryError
05-07 12:57:18.720: E/AndroidRuntime(636):  at android.graphics.Bitmap.nativeCreate(Native Method)
05-07 12:57:18.720: E/AndroidRuntime(636):  at android.graphics.Bitmap.createBitmap(Bitmap.java:640)
05-07 12:57:18.720: E/AndroidRuntime(636):  at android.graphics.Bitmap.createBitmap(Bitmap.java:586)
05-07 12:57:18.720: E/AndroidRuntime(636):  at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:466)
05-07 12:57:18.720: E/AndroidRuntime(636):  at com.NAME.framework.impl.AndroidGraphics.newResizedPixmap(AndroidGraphics.java:136)
05-07 12:57:18.720: E/AndroidRuntime(636):  at com.NAME.GAME.GameScreen.<init>(GameScreen.java:121)
05-07 12:57:18.720: E/AndroidRuntime(636):  at com.NAME.GAME.CategoryScreen.update(CategoryScreen.java:169)
05-07 12:57:18.720: E/AndroidRuntime(636):  at com.NAME.framework.impl.AndroidFastRenderView.run(AndroidFastRenderView.java:34)
05-07 12:57:18.720: E/AndroidRuntime(636):  at java.lang.Thread.run(Thread.java:856)
05-07 12:57:18.847: D/Activity:(636): Pausing...

This is the Memory leak report using the DDMS:

Problem Suspect 1

One instance of "com.NAME.framework.impl.AndroidPixmap" loaded by "dalvik.system.PathClassLoader @ 0x41a06f90" occupies 12 393 680 (54,30%) bytes. The memory is accumulated in one instance of "byte[]" loaded by "".

Keywords dalvik.system.PathClassLoader @ 0x41a06f90 com.NAME.framework.impl.AndroidPixmap byte[]

Details »

Problem Suspect 2

The class "android.content.res.Resources", loaded by "", occupies 4 133 808 (18,11%) bytes. The memory is accumulated in one instance of "java.lang.Object[]" loaded by "".

Keywords java.lang.Object[] android.content.res.Resources

Details »

Problem Suspect 3

8 instances of "android.graphics.Bitmap", loaded by "" occupy 2 696 680 (11,82%) bytes.

Biggest instances: •android.graphics.Bitmap @ 0x41462ba0 - 1 048 656 (4,59%) bytes. •android.graphics.Bitmap @ 0x41a08cf0 - 768 064 (3,37%) bytes. •android.graphics.Bitmap @ 0x41432990 - 635 872 (2,79%) bytes.

Keywords android.graphics.Bitmap

Details »


Additional Information: I use either RGB565 or ARGB4444 as the config for my images. I wish to use ARGB8888 for the images with gradients, but it just takes up too much memory. Another thing to note is that I do recycle my bitmaps when I do not need them anymore.

Another thing that seems to consume a lot of memory is my Assets class, which consists of all the "Pixmaps" that the game uses. The bitmaps loaded from the assets are stored in these "Pixmaps" and removed when not needed anymore (the bitmaps that is). Is there maybe a better way to store these objects? Please let me know:

public static Pixmap image1;
public static Pixmap image2;
public static Pixmap image3;
public static Pixmap image4;
public static Pixmap image5;
public static Pixmap image6;
public static Pixmap image7;
public static Pixmap image8;
public static Pixmap image9;
public static Pixmap image10;
public static Pixmap image11;
...

Another thing to note is that the OOM only happens on devices with higher resolutions than my own (800x480), which is because the bitmaps get scaled to make the app fit larger devices.

Also take note that the images are being drawn on a canvas, since what I am developing is a game and I'm not very experienced with OpenGL.


EDIT #1: JUST TO MAKE SURE YOU ARE AWARE OF WHAT MY ISSUE IS

I am getting OOM at the following line:

Bitmap.createScaledBitmap(bitmap, (int)(Width), (int)(Height), true)

I'm desperate for help! This is my final blockade from releasing this bloody game!


EDIT #2: NEW METHODS I'VE TRIED THAT DIDN'T WORK

I tried adding the decoded bitmaps to a LruCache before using them. I also tried a method where it creates a map of the bitmap in a temp file and then loads it in again. Like this:

ACTIVITY

// Get memory class of this device, exceeding this amount will throw an
// OutOfMemory exception.
final int memClass = ((ActivityManager) getSystemService(
        Context.ACTIVITY_SERVICE)).getMemoryClass();

// Use 1/8th of the available memory for this memory cache.
final int cacheSize = 1024 * 1024 * memClass / 8;

mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
    @Override
    protected int sizeOf(String key, Bitmap bitmap) {
        // The cache size will be measured in kilobytes rather than
        // number of items.
        return (bitmap.getRowBytes() * bitmap.getHeight()) / 1024;
    }
};

LOADING THE BITMAP

        //Copy the byte to the file
//Assume source bitmap loaded using options.inPreferredConfig = Config.ARGB_8888;
FileChannel channel = randomAccessFile.getChannel();
MappedByteBuffer map = null;
try {
    map = channel.map(MapMode.READ_WRITE, 0, width*height*4);
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
bitmap.copyPixelsToBuffer(map);
//recycle the source bitmap, this will be no longer used.
bitmap.recycle();
//Create a new bitmap to load the bitmap again.
bitmap = Bitmap.createBitmap(width, height, config);
map.position(0);
//load it back from temporary 
bitmap.copyPixelsFromBuffer(map);
//close the temporary file and channel , then delete that also
try {
    channel.close();
    randomAccessFile.close();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

((AndroidGame) activity).addBitmapToMemoryCache(""+fileName, Bitmap.createScaledBitmap(bitmap, (int)(Width), (int)(Height), true));

return new AndroidPixmap(((AndroidGame) activity).getBitmapFromMemCache(""+fileName), format);

EDIT #3: IN CASE YOU DIDN'T KNOW...

I am enlarging the bitmaps, not scaling them down, so inSampleSize won't help me in this situation. I can say right now that I've already tried inSampleSize and that makes everything so blurry, I can't even see what stuff is, and that is when I set inSampleSize to 2!


So, what should I do to solve this issue? How am I able to load lots of scaled bitmaps without getting the OOM while keeping their quality?

  • Check out http://stackoverflow.com/questions/477572/strange-out-of-memory-issue-while-loading-an-image-to-a-bitmap-object and all linked questions. – EricRobertBrewer May 10 '13 at 01:09
  • I'm sorry, but there is nothing from what I've read that will help me. The most suggested solution for those questions are implementing inSampleSize, which reduces the quality of the image, which I don't want since I am enlarging the images. – Henrik Söderlund May 10 '13 at 12:36
  • How many bitmaps do you need to use simultaneously? If you MUST have more than one, then after how many bitmap creations do you receive the OOM? Can you have just one kept in memory at a time? Another thing is why are Width and Height double and then converted to int? (have you checked that the conversion to int worked for you well?) – EyalBellisha May 12 '13 at 13:58
  • I only use 1 bitmap of the spritesheet, since there is only one instance that needs it. I use 25 different bitmaps (a lot smaller than this one) simultaneously and all the bitmaps used before the loading that are not needed anymore are recycled beforehand. I convert the Width and Height (which is double, because I multiply the image's original size with the scale calculated as I mentioned in the beginning of the question) to int to remove eventual decimals, because pixels can not be split in half. (I actually forgot to add a +0.5f in there, but that is fixed now.) – Henrik Söderlund May 12 '13 at 14:24
  • I would try to load this bitmap in an entirely differnt process just to see whether it can be loaded at all (when no other bitmaps are cached). If it can be done, then I would consider two options: reduce the number of small bitmaps cached at a time to a bare minimum OR (a much more complex solution) have a separate process hold this bitmap for you and let you access a rectangle at a time (I once had a Service do that) – EyalBellisha May 12 '13 at 14:36
  • I don't think I am caching my bitmaps at all... I tried the method as mentioned in the question, but it didn't work. Is there maybe another way of caching bitmaps? Or maybe I did t entirely wrong? I would really appreciate an example of some sort to look through. Also, I've actually tried loading the bitmap in another process and it didn't work... :/ – Henrik Söderlund May 12 '13 at 15:04
  • If loading this bitmap in a totally different application is causing an OOM, then caching the bitmaps is the least of your problems (though it seems to me that you are caching them well with LRU). You should try to maybe split this file into separate files and load it, but in any case you should first laod it in a separate app just to see that it works – EyalBellisha May 12 '13 at 15:20
  • No, I think I misunderstood it then. No I haven't loaded anything from a different application. If that would potentially solve the problem, how should I begin? – Henrik Söderlund May 12 '13 at 15:37
  • What I am trying to say is that, for starters, create a new Android app which all it does is load this bitmap into memory. If it successfully loads it then you have something to work with, if not then the bitmap is too big for current Android devices and maybe you should split it. But I recommend that you start with building a new app that does just that... let me know what happens then – EyalBellisha May 13 '13 at 08:29
  • So, I have now tried loading the image from a new app that I built and despite that, it gives the OOM, so I guess I'll have to split it then? – Henrik Söderlund May 13 '13 at 10:36
  • There is a limit to the amount of memory a mobile app can use. It seems like you have exceeded that limit. Some devices that have a larger heap size may be able to handle this memory allocation, but for most current devices (judging by your results) it is too big. You may need to load this bitmap in pieces, and even then my guess is that you won't be able to hold all the pieces in memory simultaneously (you may need to implement a caching algorithm) – EyalBellisha May 13 '13 at 10:57

6 Answers6

4

This is a way to work around, but this will take a little bit longer than scaling bitmap directly.

  1. First, decode the original bitmap as original size
  2. Split into small bitmaps, in this case is 10 bitmaps with the width = originalWidth/10 and height = originalHeight. And width each bitmap of those, scale to the size of target/10 then save into file. (we do this one by one and release memory after each step.)
  3. Release the original bitmap
  4. Create a new bitmap with the target size.
  5. Decode each bitmap saved in file before and draw onto the new bitmap. Store the new scaled bitmap for future usage.

The method is something like this:

public Bitmap newResizedPixmapWorkAround(Bitmap.Config format,
            double width, double height) {
        int[] pids = { android.os.Process.myPid() };
        MemoryInfo myMemInfo = mAM.getProcessMemoryInfo(pids)[0];
        Log.e(TAG, "dalvikPss (beginning) = " + myMemInfo.dalvikPss);

        Config config = null;
        if (format == Bitmap.Config.RGB_565) {
            config = Config.RGB_565;
        } else if (format == Bitmap.Config.ARGB_4444) {
            config = Config.ARGB_4444;
        } else {
            config = Config.ARGB_8888;
        }

        Options options = new Options();
        options.inPreferredConfig = config;
        options.inPurgeable = true;
        options.inInputShareable = true;
        options.inDither = false;

        InputStream in = null;
        Bitmap bitmap = null;
        try {
            // OPEN FILE INTO INPUTSTREAM
            String path = Environment.getExternalStorageDirectory()
                    .getAbsolutePath();
            path += "/sprites.png";
            File file = new File(path);
            in = new FileInputStream(file);
            // DECODE INPUTSTREAM
            bitmap = BitmapFactory.decodeStream(in, null, options);

            if (bitmap == null) {
                Log.e(TAG, "bitmap == null");
            }
        } catch (IOException e) {
            Log.e(TAG, "IOException " + e.getMessage());
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                }
            }
        }

        if (bitmap.getConfig() == Config.RGB_565) {
            format = Bitmap.Config.RGB_565;
        } else if (bitmap.getConfig() == Config.ARGB_4444) {
            format = Bitmap.Config.ARGB_4444;
        } else {
            format = Bitmap.Config.ARGB_8888;
        }

        myMemInfo = mAM.getProcessMemoryInfo(pids)[0];
        Log.e(TAG, "dalvikPss (before separating) = " + myMemInfo.dalvikPss);

        // Create 10 small bitmaps and store into files.
        // After that load each of them and append to a large bitmap

        int desSpriteWidth = (int) (width + 0.5) / 10;
        int desSpriteAppend = (int) (width + 0.5) % 10;
        int desSpriteHeight = (int) (height + 0.5);

        int srcSpriteWidth = bitmap.getWidth() / 10;
        int srcSpriteHeight = bitmap.getHeight();

        Rect srcRect = new Rect(0, 0, srcSpriteWidth, srcSpriteHeight);
        Rect desRect = new Rect(0, 0, desSpriteWidth, desSpriteHeight);

        String pathPrefix = Environment.getExternalStorageDirectory()
                .getAbsolutePath() + "/sprites";

        for (int i = 0; i < 10; i++) {
            Bitmap sprite;
            if (i < 9) {
                sprite = Bitmap.createBitmap(desSpriteWidth, desSpriteHeight,
                        format);
                srcRect.left = i * srcSpriteWidth;
                srcRect.right = (i + 1) * srcSpriteWidth;
            } else { // last part
                sprite = Bitmap.createBitmap(desSpriteWidth + desSpriteAppend,
                        desSpriteHeight, format);
                desRect.right = desSpriteWidth + desSpriteAppend;
                srcRect.left = i * srcSpriteWidth;
                srcRect.right = bitmap.getWidth();
            }
            Canvas canvas = new Canvas(sprite);
            // NOTE: if using this drawBitmap method of canvas do not result
            // good quality scaled image, you can try create tile image with the
            // same size original then use Bitmap.createScaledBitmap()
            canvas.drawBitmap(bitmap, srcRect, desRect, null);

            String path = pathPrefix + i + ".png";
            File file = new File(path);
            try {
                if (file.exists()) {
                    file.delete();
                }
                file.createNewFile();
                FileOutputStream fos = new FileOutputStream(file);
                sprite.compress(Bitmap.CompressFormat.PNG, 100, fos);
                fos.flush();
                fos.close();
                sprite.recycle();
            } catch (FileNotFoundException e) {
                Log.e(TAG,
                        "FileNotFoundException  at tile " + i + " "
                                + e.getMessage());
            } catch (IOException e) {
                Log.e(TAG, "IOException  at tile " + i + " " + e.getMessage());
            }
        }

        bitmap.recycle();

        bitmap = Bitmap.createBitmap((int) (width + 0.5f),
                (int) (height + 0.5f), format);
        Canvas canvas = new Canvas(bitmap);

        desRect = new Rect(0, 0, 0, bitmap.getHeight());

        for (int i = 0; i < 10; i++) {
            String path = pathPrefix + i + ".png";
            File file = new File(path);
            try {
                FileInputStream fis = new FileInputStream(file);
                // DECODE INPUTSTREAM
                Bitmap sprite = BitmapFactory.decodeStream(fis, null, options);
                desRect.left = desRect.right;
                desRect.right = desRect.left + sprite.getWidth();
                canvas.drawBitmap(sprite,  null, desRect, null);
                sprite.recycle();
            } catch (IOException e) {
                Log.e(TAG, "IOException  at tile " + i + " " + e.getMessage());
            }
        }

        myMemInfo = mAM.getProcessMemoryInfo(pids)[0];
        Log.e(TAG, "dalvikPss (before scaling) = " + myMemInfo.dalvikPss);

        // THIS IS WHERE THE OOM HAPPENS
        return bitmap;
    }

I have tested with my phone and it run without OOM when scaling to 1.5 (which the original method will run into OOM)

Binh Tran
  • 2,478
  • 1
  • 21
  • 18
  • This looks very interesting! The sprite sheet consists of 10 sprites per row out of 6. That is 60 sprites. Will this method work anyways, or is there something that has to be changed? – Henrik Söderlund May 13 '13 at 11:53
  • I can't belive this... It actually worked! I have one question, though. I noticed one of your comments in the code where you said that if the bitmap quality is bad, I should use Bitmap.createScaledBitmap() again. How would I implement it into your code without ruining it and cause the OOM again? – Henrik Söderlund May 13 '13 at 12:26
  • In my experience, the method Bitmap.createScaledBitmap provider better or at least equal quality compare to other scaling methods supported by Android SDK like BitmapFactory.decodeImage or Canvas.drawBitmap as I use in the code above. So if you found the bitmap quality is not as you expected, you can modify the code in the loop to create sprite as below: – Binh Tran May 13 '13 at 13:24
  • Bitmap sprite; if (i < 9) { srcRect.left = i * srcSpriteWidth; srcRect.right = (i + 1) * srcSpriteWidth; } else { // last part srcRect.left = i * srcSpriteWidth; srcRect.right = bitmap.getWidth(); } desRect.right = srcRect.width(); desRect.bottom = srcRect.height(); sprite = Bitmap.createBitmap(srcRect.width(), srcRect.height(), format); Canvas canvas = new Canvas(sprite); canvas.drawBitmap(bitmap, srcRect, desRect, null); – Binh Tran May 13 '13 at 13:25
  • if (i < 9) { sprite = Bitmap.createScaledBitmap(sprite, desSpriteWidth, desSpriteHeight, true); } else { // last part sprite = Bitmap.createScaledBitmap(sprite, desSpriteWidth + desSpriteAppend, desSpriteHeight, true); } – Binh Tran May 13 '13 at 13:26
  • 1
    I tried adding paint with the Paint.FILTER_BITMAP_FLAG to the Canvas.drawBitmap methods and that also worked. – Henrik Söderlund May 13 '13 at 13:45
1

Why are you enlarging the bitmaps? Just scale them as you draw them.

3000x1614 is quite large, if you can drop support of <= 2.2; http://developer.android.com/reference/android/graphics/BitmapRegionDecoder.html can load specific sections of the bitmap (the sprites).

You're passing new bitmaps into the constructor of AndroidPixmap, and it looks like you're keeping static references to them - how exactly are you recycling them?

As a cop-out, you can ask for more memory using <application ... android:largeHeap="true" ...> in your manifest; http://developer.android.com/guide/topics/manifest/application-element.html#largeHeap I believe this requires > =3.0

FunkTheMonk
  • 10,908
  • 1
  • 31
  • 37
  • I am enlarging them in loading to make use of the filtering method that comes with `Bitmap.createScaledBitmap(Bitmap, boolean)`. **|** The whole bitmap is as compressed as it can be and the whole spritesheet is needed, since it all contains essential sprites. **|** I am recycling the ones not needed before loading the others (For example, when I leave the menu, the bitmaps gets recycled and then it loads new bitmaps that are needed for the rest of the game and vice versa to save up memory). **|** I am already using that...and it doesn't work (Using a device with 4.1). – Henrik Söderlund May 13 '13 at 09:40
  • Set the paint used when drawing the bitmap to canvas to use the same filtering: http://developer.android.com/reference/android/graphics/Paint.html#setFilterBitmap%28boolean%29 – FunkTheMonk May 13 '13 at 09:48
  • Is the entire sprite set required at once? If by compression you mean file compression, it makes no difference when reading the bitmap, as it will require the uncompressed size in memory: ~9megs at 4444 – FunkTheMonk May 13 '13 at 09:52
  • By compressed, I mean that the space between the sprites is 0px. The whole sprite sheet is used at once, yes. – Henrik Söderlund May 13 '13 at 12:08
  • I voted the question because the `largeHeap="true"` solved for me here, but, it will be the solution for all devices? – Armando Marques da S Sobrinho Apr 27 '17 at 21:48
0

Just for help (but no really the solution), have you read this :

http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

And this:

http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

Maybe can help you ! If you test the sample project delivered and changing the URL path with your big image !

And, when I have work on that I have read this :

http://twigstechtips.blogspot.com/2011/10/android-resize-bitmap-image-while.html

VincentLamoute
  • 800
  • 1
  • 9
  • 16
  • I belive I'll need an ImageView for those examples, which I haven't for my application. I am drawing my bitmaps on a canvas as mentioned in the post. – Henrik Söderlund May 07 '13 at 13:54
0

Try this function.

void scaleBitmap()
{


        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        o.inPurgeable = true;
        o.inScaled = true;
        BitmapFactory.decodeStream(new FileInputStream(f), null, o);
        int width_temp = o.outWidth, height_temp = o.outHeight;
        int scale = 1;
        while (true) {
                if (width_temp / 2 < 80 || height_temp / 2 < 80)
                    break;
                width_temp /= 2;
                height_temp /= 2;
                scale *= 2;
            }

            BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize = scale;
            return BitmapFactory.decodeStream(new FileInputStream(f), null,
                    o2);
}
Ajith M A
  • 3,838
  • 3
  • 32
  • 55
  • Sry, but again, I am enlarging the bitmaps, not scaling them down, so inSampleSize will only help with the OOM issue but worsen the quality even more so that won't work. – Henrik Söderlund May 12 '13 at 12:09
-1

Convert your image into Bitmap object. And use APIs of the Bitmap class to scale your image so that to avoid Out of Memory error.

       Bitpmap bm = BitmapFactory.decode ("image file path");
       bm.setDensity(integer);
       Bitmap bm1 = Bitmap.createScaledBitmap (bm, width, height, false);
       imageView.setImageBitmap(bm1);

Try to put the value of width and height so that it should not leak memory. May this help you out.

  • No ! Because if you decode the bitmap with an inputstream -> outOfMemorry !! And if you image in the path it's bigger than the free space of the java VM -> Out of memorry. For test your solution, copy/paste the decode() many times – VincentLamoute May 07 '13 at 13:37
-3

allow the JVM to use more memory using the -Xmx VM argument.

For instance, to allow the JVM to use 1 GB (1024 MB) of memory:

java -Xmx1024m

OR

Use any Image uploader and pass image url in demo

1) Nostra's Universal Image Loader.

2) Fedor's LazyList. And;

3) Novoda's ImageLoader.

Nirav Ranpara
  • 13,753
  • 3
  • 39
  • 54