android:java.lang.OutOfMemoryError: bitmap size exceeds VM budget---缩略图

来源:互联网 发布:什么是网络金融 编辑:程序博客网 时间:2024/05/22 12:44

 

原出处:http://2711082222.blog.163.com/blog/static/10630224920123635918767/

这一个没测试,想来必定能运行。分享和自己学习。

当图片过大,或数量较多时使用BitmapFactory解码图片会出java.lang.OutOfMemoryError: bitmap size exceeds VM budget

android系统中读取位图Bitmap时.分给虚拟机中图片的堆栈大小只有8M。所以不管是如何调用的图片,太多太大虚拟机肯定会报那个错误。


遇到这个问题是因为没有回收资源.
public void distoryBitmap(){ 
    if(null!=bmb&&!bmb.isRecycled()) 
        bmb.recycle();

}

public class GifView extends View implements Runnable { 
    private Bitmap bmb; 

    public GifView(Context context, InputStream inputStream) {
         super(context);
         distoryBitmap();
         bmb = BitmapFactory.decodeStream(is);
     }
 }

调用上面的代码可以基本解决这个问题.但是千万不要在view中的onDraw()中调用.因为onDraw()方法是系统循环调用.只要图片打开.

系统就不停的调用该方法.

最好的解决方案是在自定义的View中添加一个init()初始化方法的头部调用.或者在构造函数的顶部调用:

来自:http://www.apkbus.com/android-1179-1-1.html


当图片过大,或数量较多时使用BitmapFactory解码图片会出java.lang.OutOfMemoryError: bitmap size exceeds VM budget.

一般取缩略图的方法是使用BitmapFactory的decodeFile方法,然后通过传递进去 BitmapFactory.Option类型的参数进行取缩略图,在Option中,属性值inSampleSize表示缩略图大小为原始图片大小的几分之一,即如果这个值为2,则取出的缩略图的宽和高都是原始图片的1/2,图片大小就为原始大小的1/4。

要想正常使用则需分配更少的内存,具体的解决办法是修改采样值BitmapFactory.Options.inSampleSize。

 

修改采样值BitmapFactory.Options.inSampleSize,例如: 
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = 4;
Bitmap bitmap = BitmapFactory.decodeFile(imageFile, opts);


设置恰当的inSampleSize是解决该问题的关键之一。BitmapFactory.Options提供了另一个成员inJustDecodeBounds。
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeFile(imageFile, opts);

设置inJustDecodeBounds为true后,decodeFile并不分配空间,但可计算出原始图片的长度和宽度,即opts.width和opts.height。有了这两个参数,再通过一定的算法,即可得到一个恰当的inSampleSize。

查看Android源码,Android提供了一种动态计算的方法,方法如下面例子

private static int computeInitialSampleSize(BitmapFactory.Options options,int minSideLength, int maxNumOfPixels)

public static int computeSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels)

 

使用该算法,就可动态计算出图片的inSampleSize。

BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imageFile, opts);

opts.inSampleSize = computeSampleSize(opts, -1, 128*128);
opts.inJustDecodeBounds = false;
try {
 Bitmap bmp = BitmapFactory.decodeFile(imageFile, opts);
 imageView.setImageBitmap(bmp);
    } catch (OutOfMemoryError err) {
}

 来自:http://blog.csdn.net/yangxyjd/article/details/6932989


我的应用 eg.

public static final Bitmap getFitBitmap(String path)
    {                
   BitmapFactory.Options opts =  new  BitmapFactory.Options();      
   opts.inJustDecodeBounds =  true ;
   BitmapFactory.decodeFile(path, opts);                      
  
   opts.inSampleSize = computeSampleSize(opts, - 1 ,  1200*800 );    
   Log.e("bili", opts.inSampleSize+"");
   opts.inJustDecodeBounds =  false ; 
        try  {
             Bitmap bmp = BitmapFactory.decodeFile(path, opts);
             return bmp;
   }  catch  (OutOfMemoryError err) {
   
   }
        return null;        
    }
 
 public static int computeSampleSize(BitmapFactory.Options options,     int minSideLength, int maxNumOfPixels) {
        int initialSize = computeInitialSampleSize(options, minSideLength,maxNumOfPixels);
        int roundedSize;
        if (initialSize <= 8 ) {
            roundedSize = 1;
            while (roundedSize < initialSize) {
                roundedSize <<= 1;
            }
        } else {
            roundedSize = (initialSize + 7) / 8 * 8;
        }
        return roundedSize;
    }

    private static int computeInitialSampleSize(BitmapFactory.Options options,int minSideLength, int maxNumOfPixels) {
        double w = options.outWidth;
        double h = options.outHeight;

        int lowerBound = (maxNumOfPixels == -1) ? 1 :
                (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
        int upperBound = (minSideLength == -1) ? 128 :
                (int) Math.min(Math.floor(w / minSideLength), Math.floor(h / minSideLength));

        if (upperBound < lowerBound) {
            // return the larger one when there is no overlapping zone.
            return lowerBound;
        }

        if ((maxNumOfPixels == -1) &&
                (minSideLength == -1)) {
            return 1;
        } else if (minSideLength == -1) {
            return lowerBound;
        } else {
            return upperBound;
        }
    }

      /**
       * change uri to path string
       * @param uri
       * @return
       */
      public String getPath(Uri uri)  
       {    
          String[] projection = {MediaStore.Images.Media.DATA };    
          Cursor cursor = managedQuery(uri, projection, null, null, null);    
          int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);    
          cursor.moveToFirst();    
          return cursor.getString(column_index);    
       }

调用:

 protected void onActivityResult(int requestCode, int resultCode, Intent data) 中

Uri uri1 = data.getData();  
String selectedImagePath1 = getPath(uri1);   

//.......... 
//firstPhoto.setImageURI(uri1);     
//firstPhoto.setImageBitmap(BaseMean.lessenUriImage(selectedImagePath1)); 
btOne =RevoPubAccess.getFitBitmap(selectedImagePath1);

红色处要是添加这句,

Log.e(TAG,  uri1+";;;;"+selectedImagePath1+",,,,"+uri1.getPath()); 

结果如下:
content://media/external/images/media/149;;;;/mnt/sdcard/DCIM/100MEDIA/IMAG0238.jpg,,,,/external/images/media/149