0

I'm new to android and developing an app that saves large images from drawable folder to phone storage. These files have resolution of 2560x2560 and I want to save these files without loosing image quality.

I use following method to save images and it gives me Out of Memory Exception. I have seen many answers how to load a large bitmap efficiently. But I cant really find an answer for this problem.

In my code, I use

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), imageId);
File file = new File(root.getAbsolutePath() + "/Pictures/" + getResources().getString(R.string.app_name) + "/" + timeStamp + ".jpg");
file.createNewFile();
FileOutputStream oStream = new FileOutputStream(file);
bitmap.compress(CompressFormat.JPEG, 100, oStream);
oStream.close();
bitmap.recycle();

Is there anything wrong with my code? This works without any exception for smaller images.

If I use android:largeHeap="true", this does not throw any exception. But I know it is not a good practice to use android:largeHeap="true".

Is there any efficient way to save large images from drawable folder without an exception?

Thank you in advance.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Vajira Lasantha
  • 2,435
  • 3
  • 23
  • 39

1 Answers1

3

If you just want to copy the image file, you shouldn't decode it into a bitmap in the first place.

You can copy a raw resource file with this for example:

InputStream in = getResources().openRawResource(imageId);
String path = root.getAbsolutePath() + "/Pictures/" + getResources().getString(R.string.app_name) + "/" + timeStamp + ".jpg";
FileOutputStream out = new FileOutputStream(path);
try {
    byte[] b = new byte[4096];
    int len = 0;
    while ((len = in.read(b)) > 0) {
        out.write(b, 0, len);
    }
}
finally {
    in.close();
    out.close();
}

Note that you have to store your image in the res/raw/ directory instead of res/drawable/.

Floern
  • 33,559
  • 24
  • 104
  • 119
  • 1
    Agreed. Or, store them as assets (e.g., in `src/main/assets/` of an Android Studio module), and copy them from there (call `open()` on the `AssetManager` that you get by calling `getAssets()`). – CommonsWare Jan 10 '16 at 23:42
  • @Floern It looks like a good idea. But I load same images to my app's ImageView (using external lib called Subsampling Scale Image View by davemorrissey). So if I put those images in raw folder, the app simply crash with Out of Memory exception again (at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:500)). – Vajira Lasantha Jan 11 '16 at 01:23
  • @VajiraLasantha it crash because your device does not have enough RAM to hold your image. Your `ImageView` should be smaller than your screen, so you can resize your image to fit your `ImageView` then display it. Here is useful link: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html – mr.icetea Jan 11 '16 at 02:14
  • @Floern Fixed it. Used Bitmap.Config.RGB_565 and inDither = true options when decoding bitmap from raw image file to display in ImageView and it works fine now. Thank you for your answer. – Vajira Lasantha Jan 11 '16 at 03:26