位图 - 内存不足异常
Posted
技术标签:
【中文标题】位图 - 内存不足异常【英文标题】:Bitmap - Out of memory exception 【发布时间】:2013-06-24 09:46:26 【问题描述】:当我尝试从相机或图库中获取图像时,出现错误。这是logcat的一部分:
06-27 05:51:47.297: E/dalvikvm-heap(438): Out of memory on a 35295376-byte allocation.
06-27 05:51:47.312: E/dalvikvm(438): Out of memory: Heap Size=108067KB, Allocated=71442KB, Limit=131072KB
06-27 05:51:47.312: E/dalvikvm(438): Extra info: Footprint=108067KB, Allowed Footprint=108067KB, Trimmed=56296KB
06-27 05:51:47.312: E/PowerManagerService(438): Excessive delay when setting lcd brightness: mLcdLight.setBrightness(176, 1) spend 288ms, mask=2
06-27 05:51:48.052: E/dalvikvm-heap(4332): Out of memory on a 24023056-byte allocation.
06-27 05:51:48.057: E/dalvikvm(4332): Out of memory: Heap Size=63139KB, Allocated=40922KB, Limit=65536KB
06-27 05:51:48.057: E/dalvikvm(4332): Extra info: Footprint=63139KB, Allowed Footprint=63139KB, Trimmed=0KB
06-27 05:51:48.057: E/EmbeddedLogger(438): App crashed! Process: <my_app_name>
这是我的代码,可让我拍摄图像:
Intent pickIntent = new Intent();
pickIntent.setType("image/*");
pickIntent.setAction(Intent.ACTION_GET_CONTENT);
Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Intent chooserIntent = Intent.createChooser(pickIntent, "Select or take a new Picture");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] takePhotoIntent );
startActivityForResult(chooserIntent, selectPic);
onActivityResult()
我愿意:
Bitmap bitmapSelectedImage = null;
Uri selectedImage = data.getData();
String[] filePathColumn = MediaStore.Images.Media.DATA ;
Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);
cursor.moveToFirst();
String filePath = cursor.getString(cursor.getColumnIndex(filePathColumn[0]));
cursor.close();
bitmapSelectedImage = BitmapFactory.decodeFile(filePath); // Here is where do I get error.
bitmapSelectedImage = BitmapFactory.decodeFile(filePath);
行出现错误。
我查看了很多网站/主题,但没有人能提供帮助。
有什么建议吗?
【问题讨论】:
你的“很多网站”肯定不是很多,这个official doc 可以帮助你。一般来说你需要resample
图片而不是直接调用BitmapFactory.decodeFile(filePath)
【参考方案1】:
您的内存分配堆大小非常有限。 尝试将高分辨率图像从文件加载到堆中很容易导致内存不足错误。
假设相机应用程序确实采用了非常高的分辨率(几乎可以肯定是这种情况),您应该仅将位图的缩放版本以显示所需的大小加载到内存中。
建议您查看的文档 - http://developer.android.com/training/displaying-bitmaps/load-bitmap.html 提供完整的功能方法来做到这一点。
1) 第一步是计算(不加载到内存)所需的比例。
这就是calculateInSampleSize
方法。
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight)
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth)
// Calculate ratios of height and width to requested height and
// width
final int heightRatio = Math.round((float)height / (float)reqHeight);
final int widthRatio = Math.round((float)width / (float)reqWidth);
// Choose the smallest ratio as inSampleSize value, this will
// guarantee
// a final image with both dimensions smaller than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
return inSampleSize;
2) 第二步是使用第一步的完整方法:
public static Bitmap getSampleBitmapFromFile(String bitmapFilePath, int reqWidth, int reqHeight)
// calculating image size
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(new File(bitmapFilePath)), null, options);
int scale = calculateInSampleSize(options, reqWidth, reqHeight);
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeStream(new FileInputStream(new File(bitmapFilePath)), null, o2);
reqHeight
和reqWith
是显示图像的图像视图的高度和宽度(以像素为单位)。
所以假设你的图像视图是 100x100 像素,你需要做的就是:
bitmapSelectedImage = getSampleBitmapFromFile(filePath, 100, 100);
【讨论】:
getSampleBitmapFromFile() 方法中的 f 变量是什么?是文件类声明吗? @JustWork: f 等于新文件(bitmapFilePath)。我也在答案中更新了该方法。您现在可以通过更正来查看它 @JustWork:如果我的回答对您有用,那么最好将其标记为已接受。那么其他人也可以从阅读此答案中受益 我知道标记为已接受。但我在尝试之前不会标记。这就是我没有标记它的原因。【参考方案2】:如果位图尺寸非常大或处理效率低下,则会出现此问题。要有效地解码位图,您可以在 android 开发者网站中查看这些提示。
Displaying Bitmaps Efficiently
【讨论】:
还可以查看这个 Android 开发者开发字节:youtube.com/watch?v=rsQet4nBVi8【参考方案3】:不要对位图使用强引用。如下使用它。始终使用弱引用,以便系统可以 gc 对象并减少内存泄漏
WeakReference<Bitmap> bitmapSelectedImage ;
【讨论】:
听起来不错但不起作用:WeakHashMapWeakReference
糟糕!对不起,是我的错。【参考方案4】:
您需要缩小图像。
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html.
使用适当的Bitmap.decode
方法并缩小图像。
Bitmap.decode
例子:
使用所需参数调用方法。
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;
【讨论】:
【参考方案5】:这段代码对我有用:试试这个
位图 ThumbImage = ThumbnailUtils.extractThumbnail(位图, 100, 100);
【讨论】:
这是合理调整大小的方式还是硬调整大小? 位图 ThumbImage = ThumbnailUtils.extractThumbnail(bitmap, width_u_want, height_u_want); & 做 [import android.media.ThumbnailUtils;]以上是关于位图 - 内存不足异常的主要内容,如果未能解决你的问题,请参考以下文章