Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 347|回复: 0

java.lang.OutOfMemoryError: bitmap size exceeds VM budget解决方法

[复制链接]
  • TA的每日心情
    奋斗
    前天 12:49
  • 签到天数: 789 天

    [LV.10]以坛为家III

    2049

    主题

    2107

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    722638
    发表于 2021-6-3 15:23:06 | 显示全部楼层 |阅读模式
    1
    BitmapFactory.decodeFile(imageFile);

    用BitmapFactory解码一张图片时,有时会遇到该错误。这往往是由于图片过大造成的。要想正常使用,则需要分配更少的内存空间来存储。

    BitmapFactory.Options.inSampleSize

    设置恰当的inSampleSize可以使BitmapFactory分配更少的空间以消除该错误。inSampleSize的具体含义请参考SDK文档。例如:

    ?
    1
    2
    3
    BitmapFactory.Options opts = new BitmapFactory.Options();
    opts.inSampleSize = 4 ;
    Bitmap bitmap = BitmapFactory.decodeFile(imageFile, opts);

    如何设置恰当的inSampleSize

    设置恰当的inSampleSize是解决该问题的关键之一。BitmapFactory.Options提供了另一个成员inJustDecodeBounds。

    ?
    1
    2
    3
    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提供了一种动态计算的方法。

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    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;
         }
    }  

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

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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) {
         }

    另外,可以通过Bitmap.recycle()方法来释放位图所占的空间,当然前提是位图没有被使用。

     

    获取缩略图关键代码

     

     

    byte[] imageByte=getImageFromURL(urlPath.trim());

     

     //以下是把图片转化为缩略图再加载

     BitmapFactory.Options options = new BitmapFactory.Options(); 

     options.inJustDecodeBounds = true;      //首先设置.inJustDecodeBounds为true

     Bitmap bitmap=BitmapFactory.decodeByteArray(imageByte, 0, imageByte.length, options);    //这时获取到的bitmap是null的,尚未调用系统内存资源

     options.inJustDecodeBounds = false;        得到图片有宽和高的options对象后,设置.inJustDecodeBounds为false。

     int be = (int)(options.outHeight / (float)200); 

             if (be <= 0)   be = 1; 

             options.inSampleSize = be;          //计算得到图片缩小倍数

     bitmaps=BitmapFactory.decodeByteArray(imageByte, 0, imageByte.length,options);                          //获取真正的图片对象(缩略图)

     /**  

    * 根据图片网络地址获取图片的byte[]类型数据

    * @param urlPath 图片网络地址

     * @return 图片数据

      */  

    1.     public byte[] getImageFromURL(String urlPath){  
    2.         byte[] data=null;  
    3.         InputStream is=null;  
    4.         HttpURLConnection conn=null;  
    5.         try {  
    6.             URL url=new URL(urlPath);  
    7.             conn=(HttpURLConnection) url.openConnection();  
    8.             conn.setDoInput(true);  
    9.             //conn.setDoOutput(true);  
    10.             conn.setRequestMethod("GET" );  
    11.             conn.setConnectTimeout(6000 );  
    12.             is=conn.getInputStream();  
    13.             if(conn.getResponseCode()==200 ){  
    14.                 data=readInputStream(is);  
    15.             }  
    16.             else  System.out.println("发生异常!" );  
    17.               
    18.         } catch (MalformedURLException e) {  
    19.             e.printStackTrace();  
    20.         } catch (IOException e) {  
    21.             e.printStackTrace();  
    22.         }  
    23.         finally{  
    24.             conn.disconnect();  
    25.             try {  
    26.                 is.close();  
    27.             } catch (IOException e) {  
    28.                 e.printStackTrace();  
    29.             }  
    30.         }  
    31.         return data;  
    32.     }  
    33.       
    34.     /**  
    35.      * 读取InputStream数据,转为byte[]数据类型  
    36.      * @param is  InputStream数据  
    37.      * @return  返回byte[]数据  
    38.      */  
    39.     public byte[] readInputStream(InputStream is) {  
    40.         ByteArrayOutputStream baos=new ByteArrayOutputStream();  
    41.         byte[] buffer=new byte[1024 ];  
    42.         int length=-1 ;  
    43.         try {  
    44.             while((length=is.read(buffer))!=-1 ){  
    45.                 baos.write(buffer, 0 , length);  
    46.             }  
    47.             baos.flush();  
    48.         } catch (IOException e) {  
    49.             e.printStackTrace();  
    50.         }  
    51.         byte[] data=baos.toByteArray();  
    52.         try {  
    53.             is.close();  
    54.             baos.close();  
    55.         } catch (IOException e) {  
    56.             e.printStackTrace();  
    57.         }  
    58.         return data;  
    59.     }  
    60.       
    61.     /**  
    62.      * 根据网络图片地址集批量获取网络图片  
    63.      * @param urlPath  网络图片地址数组  
    64.      * @return    返回Bitmap数据类型的数组  
    65.      */  
    66.     public Bitmap[] getBitmapArray(String[] urlPath){  
    67.         int length=urlPath.length;  
    68.         if(urlPath==null||length<1 ){  
    69.             return null;  
    70.         }  
    71.         else{  
    72.             Bitmap[] bitmaps=new Bitmap[length];  
    73.             for (int i = 0 ; i < length; i++) {  
    74.                 byte[] imageByte=getImageFromURL(urlPath.trim());  
    75.                   
    76.                 //以下是把图片转化为缩略图再加载  
    77.                 BitmapFactory.Options options = new BitmapFactory.Options();   
    78.                 options.inJustDecodeBounds = true;  
    79.                 Bitmap bitmap=BitmapFactory.decodeByteArray(imageByte, 0 , imageByte.length, options);  
    80.                 options.inJustDecodeBounds = false;  
    81.                 int be = (int)(options.outHeight / (float)200 );   
    82.                 if (be <= 0 )   be =  1 ;   
    83.                 options.inSampleSize = be;   
    84.                 bitmaps=BitmapFactory.decodeByteArray(imageByte, 0 , imageByte.length,options);  
    85.             }  
    86.             return bitmaps;  
    87.         }  
    88.           
    89.     }  

     

     

     

     

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-9-8 02:46 , Processed in 0.065010 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表