23

在 BitmapFactory 中获取异常。不确定是什么问题。(嗯,我可以猜到这个问题,但不知道为什么会发生)

错误/AndroidRuntime(7906): java.lang.OutOfMemoryError: 位图大小超出 VM 预算

错误/AndroidRuntime(7906):在 android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:295)

我的代码非常简单。我定义了一个带有默认图像的 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) {

bm=Bitmap.createScaledBitmap它在任何想法上都失败了?我在论坛上做了一些研究,它指向了这篇文章 ,我只是不知道为什么它不起作用。任何帮助都会很棒!谢谢,

克里斯。

4

9 回答 9

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 或简单地使用固定大小来减少内存消耗似乎效果更好。

于 2010-03-01T14:23:12.767 回答
5

参考此链接,请注意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;
}
于 2013-02-18T01:34:48.227 回答
4

我最终使用以下代码调整了位图的大小,这似乎已经解决了这个问题。

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap preview_bitmap = BitmapFactory.decodeFile(mPathName, options);
于 2009-10-21T20:21:11.737 回答
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 :(");
}
于 2009-10-22T22:02:43.627 回答
1

我认为它是 - 它说它是什么。您的图像太大,并且由于内存耗尽时将其加载到流中,因此会引发异常。这甚至不是关于你有多少内存的问题,而是你的特定活动有多少可用的问题。

于 2009-10-19T02:31:53.527 回答
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]; 
于 2011-05-04T04:51:51.300 回答
0

你检查过DDMS吗?就我所遇到的情况而言,这可能不是图像的大小,因为 Android 似乎可以很好地处理大图像。如果您使用 DDMS 跟踪堆,您可能会发现您碰巧有很多可用内存。你可以通过添加这个来“扩展”你的堆

static { @SuppressWarnings("unused")
byte dummy[] = new byte[ 8*1024*1024 ]; }    

到您的代码中,以强制堆扩展。它可能会降低它的频率。不幸的是,除了它声称它不能分配一定数量的字节之外。说1M。如果你看一下“free”行,你会看到最大的块是 >> 1M。那里有一些奇怪的东西,我无法弄清楚。它甚至与滑动图像的速度无关。我在一些线程中看到您可以为位图调用“回收”左右。如果堆大小远高于所采用的大小,我仍然不明白为什么它会有所帮助。

于 2010-06-14T06:16:41.737 回答
0

当我开始将图像的大小从 320x240 调整为 64x240(缩小比例),然后导入到我的项目中时,我收到了这个错误(因为我想提高渲染速度,并且在此之前它包含很多无用的 alpha 区域)。

现在最后一个答案很有意义:

你可以通过添加这个 static { @SuppressWarnings("unused") byte dummy[] = new byte[ 8*1024*1024 ]; 来“扩展”你的堆。} 到您的代码中,以强制堆扩展。它可能会降低它的频率。

我想这就是发生在我身上的事情。Android 会自动将可绘制对象解码为位图,(然后存储在堆上,全部在编译时进行?)

当我在运行时使用较小版本的图像时,我开始看到错误(我在运行时放大它们,因为我使用 BitmapFactory.decodeResource 和 Bitmap.createScaledBitmap 编写了带有复古图形的 VGA 游戏)。

一定就像 Marve 说的:在缩小我的可绘制/图像并将其导入我的项目后,堆在我的情况下不够大。

将图像调整回更大尺寸(320x240)时,我能够摆脱我的 OutOfMemoryException,这验证了我猜的问题?

于 2011-11-14T03:16:11.180 回答