Question

In Android, how do you display an image (of any size) from the SD card, without getting an out of memory error?

Is it necessary to put the image in the Media Store first?

A pseudo-code example would be greatly appreciated. Extra points if the displayed image is as big as the memory level of the device allows.

Was it helpful?

Solution

Edit: this question has actually been already answered at Strange out of memory issue while loading an image to a Bitmap object (the two highest voted answers). It does also use the inSampleSize option, but with a small method to automatically get the appropriate value.

My original answer:

The inSampleSize of the BitmapFactory.Options class can solve your issue (http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inSampleSize). It works by making a bitmap with the resulting width and height 1/inSampleSize than the original, thus reducing memory consumption (by inSampleSize^2?). You should read the doc before using it.

Example:

BitmapFactory.Options options = new BitmapFactory.Options();
// will results in a much smaller image than the original
options.inSampleSize = 8;

// don't ever use a path to /sdcard like this, but I'm sure you have a sane way to do that
// in this case nebulae.jpg is a 19MB 8000x3874px image
final Bitmap b = BitmapFactory.decodeFile("/sdcard/nebulae.jpg", options);

final ImageView iv = (ImageView)findViewById(R.id.image_id);
iv.setImageBitmap(b);
Log.d("ExampleImage", "decoded bitmap dimensions:" + b.getWidth() + "x" + b.getHeight()); // 1000x485

However here it will only work for images up to, I guess, inSampleSize^2 times the size of the allowed memory and will reduce the quality of small images. The trick would be to find the appropriate inSampleSize.

OTHER TIPS

I'm displaying any sized images using code:

ImageView imageView=new ImageView(this);
imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
imageView.setAdjustViewBounds(true);
FileInputStream fis=new FileInputStream(file);
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize=2; //try to decrease decoded image
options.inPurgeable=true; //if necessary purge pixels into disk
options.inScaled=true; //scale down image to actual device density
Bitmap bm=BitmapFactory.decodeStream(is, null, options);
imageView.setImageBitmap(bm);
fis.close();

For example:

yourImgView.setImageBitmap(BitmapFactory.decodeFile("/sdcard/1.jpg"));

http://www.developer.com/ws/other/article.php/3748281/Working-with-Images-in-Googles-Android.htm covers all you'll ever need to know on the subject of images, including getting them from an SD card. You'll notice the code to do so there, copied below:

try {
   FileOutputStream fos = super.openFileOutput("output.jpg",
      MODE_WORLD_READABLE);

   mBitmap.compress(CompressFormat.JPEG, 75, fos);

   fos.flush();
   fos.close();
   } catch (Exception e) {
   Log.e("MyLog", e.toString());
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top