在Android中,如何从SD卡中显示一张图片(任意大小),而不会出现内存不足错误?是否需要先将图像放入媒体库中?
如果设备允许的内存水平越大,则显示的图像就越大。以下是伪代码示例:
如果设备允许的内存水平越大,则显示的图像就越大。以下是伪代码示例:
编辑:这个问题已经在加载图像到位图对象时出现奇怪的内存不足问题 (前两个得票最高的答案) 中得到了解答。它也使用了inSampleSize
选项,但是提供了一个小方法来自动获取适当的值。
我的原始回答:
BitmapFactory.Options
类中的inSampleSize
可以解决您的问题(http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inSampleSize)。它通过创建一个结果宽度和高度为原始宽度和高度的1/inSampleSize
的位图来工作,从而减少内存消耗(通过inSampleSize
^2?)。在使用之前,您应该阅读文档。
示例:
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
然而,在这里,它只适用于尺寸不超过inSampleSize
的平方倍允许内存大小的图片,并且会降低小图片的质量。诀窍在于找到合适的inSampleSize
值。
我使用以下代码来显示各种大小的图像:
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();
例如:
yourImgView.setImageBitmap(BitmapFactory.decodeFile("/sdcard/1.jpg"));
http://www.developer.com/ws/other/article.php/3748281/Working-with-Images-in-Googles-Android.htm涵盖了您在图像方面所需了解的一切,包括从SD卡中获取它们的方法。您可以在下面找到复制代码:
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());
}