OutofMemoryError:位图大小超出 VM 预算 (Android)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1586685/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
OutofMemoryError: bitmap size exceeds VM budget (Android)
提问by Chrispix
Getting an Exception in the BitmapFactory. Not sure what is the issue. (Well I can guess the issue, but not sure why its happening)
在 BitmapFactory 中获取异常。不知道是什么问题。(嗯,我能猜到问题,但不知道为什么会发生)
ERROR/AndroidRuntime(7906): java.lang.OutOfMemoryError: bitmap size exceeds VM budget ERROR/AndroidRuntime(7906): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:295)
My code is pretty straight forward. I defined an XML layout w/ a default image. I try to load a bm on the SDCard (if present - it is). If not it shows the default image. Anyway.. Here is code :
我的代码非常简单。我定义了一个带有默认图像的 XML 布局。我尝试在 SDCard 上加载一个 bm(如果存在 - 它是)。如果不是,则显示默认图像。无论如何..这是代码:
public class showpicture extends Activity {
public void onCreate(Bundle savedInstanceState) {
/** Remove menu/status bar **/
requestWindowFeature(Window.FEATURE_NO_TITLE);
final Window win = getWindow();
win.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
Bitmap bm;
super.onCreate(savedInstanceState);
setContentView(R.layout.showpicture);
try {
ImageView mImageButton = (ImageView)findViewById(R.id.displayPicture);
bm = Bitmap.createScaledBitmap(BitmapFactory.decodeFile("/sdcard/dcim/Camera/20091018203339743.jpg"),100, 100, true);
parkImageButton.setImageBitmap(bm);
}
catch (IllegalArgumentException ex) {
Log.d("MYAPP",ex.getMessage());
}
catch (IllegalStateException ex) {
It fails on the bm=Bitmap.createScaledBitmap
any thoughts? I did some research on the forums, and it pointed to this postI just don't know why it is not working. Any help would be great! Thanks,
它在bm=Bitmap.createScaledBitmap
任何想法上都失败了?我在论坛上做了一些研究,它指向了这篇文章,我只是不知道为什么它不起作用。任何帮助都会很棒!谢谢,
Chris.
克里斯。
采纳答案by Steven Shih
回答by M. Schenk
inSampleSize is a good hint. But a fixed value often doesn't work fine, since large bitmaps from files usually are user files, which can vary from tiny thumbnails to 12MP images from the digicam.
inSampleSize 是一个很好的提示。但是固定值通常不能正常工作,因为文件中的大位图通常是用户文件,可以从微小的缩略图到来自数码相机的 12MP 图像。
Here's a quick and dirty loading routine. I know there's room for improvement, like a nicer coded loop, using powers of 2 for faster decoding, and so on. But it's a working start...
这是一个快速而肮脏的加载例程。我知道还有改进的余地,比如更好的编码循环,使用 2 的幂来更快地解码,等等。但这是一个工作开始......
public static Bitmap loadResizedBitmap( String filename, int width, int height, boolean exact ) {
Bitmap bitmap = null;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile( filename, options );
if ( options.outHeight > 0 && options.outWidth > 0 ) {
options.inJustDecodeBounds = false;
options.inSampleSize = 2;
while ( options.outWidth / options.inSampleSize > width
&& options.outHeight / options.inSampleSize > height ) {
options.inSampleSize++;
}
options.inSampleSize--;
bitmap = BitmapFactory.decodeFile( filename, options );
if ( bitmap != null && exact ) {
bitmap = Bitmap.createScaledBitmap( bitmap, width, height, false );
}
}
return bitmap;
}
Btw, in the newer APIs there are also lots of BitmapFactory.Option's for fitting the image to screen DPIs, but I'm not sure whether they really simplify anything. Using android.util.DisplayMetrics.density or simply a fixed size for less memory consumption seem to work better imho.
顺便说一句,在较新的 API 中,还有很多 BitmapFactory.Option 用于将图像拟合到屏幕 DPI,但我不确定它们是否真的简化了任何事情。使用 android.util.DisplayMetrics.density 或简单的固定大小以减少内存消耗似乎效果更好恕我直言。
回答by SampsonTan
With reference to this link, please note the outOfMemory
error can be solved by the following way:
参考此链接,请注意outOfMemory
错误可以通过以下方式解决:
public Bitmap decodeFile(String filePath) {
Bitmap bitmap = null;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPurgeable = true;
try {
BitmapFactory.Options.class.getField("inNativeAlloc").setBoolean(options,true);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
if(filePath != null)
{
bitmap = BitmapFactory.decodeFile(filePath, options);
}
return bitmap;
}
回答by Chrispix
I ended up resizing the bitmap using the following code which seems to have resolved the issue.
我最终使用以下似乎解决了问题的代码调整了位图的大小。
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap preview_bitmap = BitmapFactory.decodeFile(mPathName, options);
回答by Ralphleon
Make sure to guard your bitmap creation from out of memory errors! With most platforms, android doesn't have much memory to play with and it runs out quickly with bitmaps. Also, make sure to manually recycle your bitmaps as much as possible, I've noticed that the garbage collection can be rather slow.
确保保护您的位图创建免受内存不足错误的影响!对于大多数平台,android 没有太多内存可以使用,并且它在使用位图时很快就会耗尽。另外,请确保尽可能多地手动回收位图,我注意到垃圾收集可能相当慢。
try{
Bitmap myFragileBitmap = Bitmap.createBitmap(500, 500, Bitmap.Config.ARGB_8888);
}
catch(IllegalArgumentException e){
Log.e(TAG,"Illegal argument exception.");
}
catch(OutOfMemoryError e){
Log.e(TAG,"Out of memory error :(");
}
回答by Bostone
I think it is - what it it say it is. Your image is too big and since it is loaded in the stream when the memory is exhausted the exception is thrown. It's not even the question on how much memory you have overall but how much your particular Activity has available.
我认为它是 - 它说的是什么。您的图像太大,并且由于在内存耗尽时将其加载到流中,因此会引发异常。这甚至不是关于您总体拥有多少内存的问题,而是关于您的特定 Activity 有多少可用的问题。
回答by Sando
use these options in decodefile. hope u can elemenate bitmap exceeds vm budget problem..
在解码文件中使用这些选项。希望你能解决位图超出虚拟机预算问题..
BitmapFactory.Options bfOptions=new BitmapFactory.Options();
bfOptions.inDither=false; //Disable Dithering mode
bfOptions.inPurgeable=true; //Tell to gc that whether it needs free memory, the Bitmap can be cleared
bfOptions.inInputShareable=true; //Which kind of reference will be used to recover the Bitmap data after being clear, when it will be used in the future
bfOptions.inTempStorage=new byte[32 * 1024];
回答by calav3ra
I got this error when i began to resize an image from 320x240 to something like 64x240 (downscale), then import into my project (since i wanted to improve rendering speed and it contained a lot of useless alpha regions until this point).
当我开始将图像大小从 320x240 调整为 64x240(缩小),然后导入到我的项目中时(因为我想提高渲染速度并且在此之前它包含很多无用的 alpha 区域),我收到了这个错误。
now the last answer makes much sense:
现在最后一个答案很有意义:
You can "expand" your heap by adding this static { @SuppressWarnings("unused") byte dummy[] = new byte[ 8*1024*1024 ]; } to your code, to force the heap to expand. It may make it a bit less frequent.
您可以通过添加此静态 { @SuppressWarnings("unused") byte dummy[] = new byte[8*1024*1024]; 来“扩展”您的堆。到您的代码,强制堆扩展。它可能会使它不那么频繁。
I think this is what happened to me. Android automatically decodes drawables into bitmaps, (and then get stored on a heap, all on compilation time?)
我想这就是发生在我身上的事情。Android 会自动将 drawable 解码为位图,(然后在编译时存储在堆中?)
i began seeing the error, when i used the smaller version of my image in runtime (i scale them up on runtime since i program a VGA-game with retro graphics, using BitmapFactory.decodeResource and Bitmap.createScaledBitmap).
当我在运行时使用较小版本的图像时,我开始看到错误(我在运行时放大了它们,因为我使用 BitmapFactory.decodeResource 和 Bitmap.createScaledBitmap 编写了带有复古图形的 VGA 游戏)。
it must be like Marve said: The Heap is not big enough in my case after shrinking my drawable/image and import it into my project.
它必须像 Marve 说的那样:在缩小我的可绘制对象/图像并将其导入我的项目后,堆在我的情况下不够大。
I was able to get rid of my OutOfMemoryException when resizing the image back to a bigger size (320x240), which verifies the problem i guess?
将图像调整回更大的尺寸 (320x240) 时,我能够摆脱 OutOfMemoryException,这验证了我猜的问题吗?
回答by Meymann
Have you checked the DDMS? With what I have been encountering, it's probably not the size of the images, because Android seems to handle large images pretty well. If you trace the heap with DDMS you may find that you happen to have a lot of free memory. You can "expand" your heap by adding this
你检查过DDMS吗?根据我遇到的情况,可能不是图像的大小,因为 Android 似乎可以很好地处理大图像。如果您使用 DDMS 跟踪堆,您可能会发现您碰巧有很多空闲内存。你可以通过添加这个来“扩展”你的堆
static { @SuppressWarnings("unused")
byte dummy[] = new byte[ 8*1024*1024 ]; }
to your code, to force the heap to expand. It may make it a bit less frequent. Unfortunately, with the exception it claims that it can't allocate some amount of bytes. Say 1M. If you take a look at the "free" line you will see that the largest block is >> 1M. There is something strange there that I can't figure out. It is not related even to the speed of swiping images. I saw in some thread that you can call "recycle" or so for bitmaps. I still don't see why it should help if the heap size is way above the taken size.
到您的代码,强制堆扩展。它可能会使它不那么频繁。不幸的是,除了它声称不能分配一定数量的字节外。说1M。如果您查看“空闲”行,您会看到最大的块是 >> 1M。那里有一些奇怪的东西,我无法弄清楚。它甚至与滑动图像的速度无关。我在一些线程中看到,您可以将位图称为“回收”左右。我仍然不明白为什么如果堆大小远高于获取的大小,它会有所帮助。