在BitmapFactory中获取异常。不确定是什么问题。 (我可以猜到这个问题,但不确定为什么会发生这种情况)
ERROR/AndroidRuntime(7906): java.lang.OutOfMemoryError: bitmap size exceeds VM budget ERROR/AndroidRuntime(7906): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:295)
我的代码很简单。我定义了一个带有默认图像的XML布局。我尝试在SD卡上加载一个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) {
bm=Bitmap.createScaledBitmap
任何想法失败了吗?我在论坛上做了一些研究,并指出this post
我只是不知道它为什么不起作用。任何帮助都会很棒!谢谢,
克里斯。
答案 0 :(得分:13)
inSampleSize是一个很好的提示。但固定值通常不能很好地工作,因为来自文件的大位图通常是用户文件,从微缩图到数码相机的12MP图像可能会有所不同。
这是一个快速而肮脏的加载程序。我知道还有改进的余地,比如一个更好的编码循环,使用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;
}
顺便说一下,在较新的API中,还有很多BitmapFactory.Option用于将图像拟合到屏幕DPI,但我不确定它们是否真的简化了任何事情。使用android.util.DisplayMetrics.density或简单的固定大小以减少内存消耗似乎更好地工作。
答案 1 :(得分:5)
请参阅此link,请注意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;
}
答案 2 :(得分:4)
我最后使用以下代码调整了位图大小,这似乎解决了这个问题。
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap preview_bitmap = BitmapFactory.decodeFile(mPathName, options);
答案 3 :(得分:4)
确保保护您的位图创建免受内存错误的影响!在大多数平台上,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 :(");
}
答案 4 :(得分:4)
http://code.google.com/p/android/issues/detail?id=8488
http://mobi-solutions.blogspot.com/2010/08/how-to-if-you-want-to-create-and.html
答案 5 :(得分:1)
我认为它是 - 它说它是什么。您的图像太大,因为当内存耗尽时它会在流中加载,因此抛出异常。这甚至不是你整体记忆的数量,而是你的特定活动有多少。
答案 6 :(得分:1)
在decodefile中使用这些选项。希望你能说明位图超出预算问题..
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];
答案 7 :(得分:0)
您检查过DDMS吗? 根据我遇到的情况,它可能不是图像的大小,因为Android似乎很好地处理大图像。 如果使用DDMS跟踪堆,您可能会发现您碰巧有大量可用内存。 您可以通过添加此
来“扩展”堆static { @SuppressWarnings("unused")
byte dummy[] = new byte[ 8*1024*1024 ]; }
到您的代码,强制堆扩展。它可能会减少频率。 不幸的是,除了它之外,它声称它不能分配一些字节数。说1M。如果您查看“免费”行,您会看到最大的块是>> 1M。 那里有一些奇怪的东西,我无法弄明白。它与扫描图像的速度无关。 我在某个帖子中看到你可以为bitmaps调用“recycle”左右。如果堆大小超过所采用的大小,我仍然不明白为什么它应该有用。
答案 8 :(得分:0)
当我开始将图像从320x240调整为类似64x240(缩小)时,我收到此错误,然后导入到我的项目中(因为我想提高渲染速度并且它包含许多无用的alpha区域,直到这一点)
现在最后一个答案很有意义:
你可以通过添加静态{@SuppressWarnings(“unused”)字节dummy [] = new byte [8 * 1024 * 1024]来“扩展”你的堆。 } 到你的代码,强制堆扩展。它可能会少一些 频繁。
我认为这就是发生在我身上的事。 Android会自动将drawables解码为位图,然后在编译时将所有内容都存储在堆上?
我开始看到错误,当我在运行时使用我的图像的较小版本时(我在运行时缩放它们,因为我使用BitmapFactory.decodeResource和Bitmap.createScaledBitmap编写带有复古图形的VGA游戏)。 p>
它必须像Marve所说的那样:在缩小我的drawable / image并将其导入我的项目之后,Heap在我的情况下还不够大。
在将图像大小调整为更大的尺寸(320x240)时,我能够摆脱我的OutOfMemoryException,这证实了我猜的问题?