当前位置:  编程技术>移动开发

Android加载大分辨率图片到手机内存中的实例方法

    来源: 互联网  发布时间:2014-10-21

    本文导语:  还原堆内存溢出的错误首先来还原一下堆内存溢出的错误。首先在SD卡上放一张照片,分辨率为(3776 X 2520),大小为3.88MB,是我自己用相机拍的一张照片。应用的布局很简单,一个Button一个ImageView,然后按照常规的方式,使用...

还原堆内存溢出的错误
首先来还原一下堆内存溢出的错误。首先在SD卡上放一张照片,分辨率为(3776 X 2520),大小为3.88MB,是我自己用相机拍的一张照片。应用的布局很简单,一个Button一个ImageView,然后按照常规的方式,使用BitmapFactory加载一张照片并使用一个ImageView展示。

代码如下:

代码如下:

btn_loadimage.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Bitmap bitmap=BitmapFactory.decodeFile("/sdcard/a.jpg");
                iv_bigimage.setImageBitmap(bitmap);
            }
}

当点击按钮后,程序会报错,查看日志为:

先来分析一下这个错误,首先dalvikvm(Android虚拟机)发现需要的内存38MB大于应用的堆内存24MB,这个时候尝试使用软加载的方式加载数据,我们知道当内存不足的时候dalvikvm会自动进行GC(Garbage Collection),大概清理了55k的空间出来,耗时203毫秒,但是内存还是不够,所以最后发生堆内存溢出的错误。

分析堆内存溢出

Android系统主要用于低能耗的移动设备,所以对内存的管理有很多限制,一个应用程序,Android系统缺省会为其分配最大16MB(某些机型是24MB)的空间作为堆内存空间,我这里使用的模拟器调试的,这个模拟器被设定为24MB,可以在Android Virtual Device Manager中查看到。

而这里的图片明明只有3.88MB,远远小于Android为应用分配的堆内存,而加载到内存中,为什么需要消耗大约38MB的内存呢?
我们都知道,图片是由一个一个点分布组成的(分辨率),通常加载这类数据都会在内存中创建一个二维数组,数组中的每一项代表一个点,而这个图片的分辨率是3776 * 2520,每一点又是由ARGB色组成,每个色素占4个Byte,所以这张图片加载到内存中需要消耗的内存为:
3776 * 2520 * 4byte = 38062080byte
大约需要38MB的内存才能正确加载这张图片,这就是上面错误描述需要38MB的内存空间,大小略有出入,因为图片还有一些Exif信息需要存储,会比仅靠分辨率计算要大一些。

如何加载大分辨率图片
有时候我们确实会需要加载一些大分辨率的图片,但是对于移动设备而言,哪怕加载能成功那么大的内存也是一种浪费(屏幕分辨率限制),所以就需要想办法把图片按照一定比率压缩,使分辨率降低,以至于又不需要耗费很大的堆内存空间,又可以最大的利用设备屏幕的分辨率来显示图片。这里就用到一个BitmapFactory.Options对象,下面来介绍它。
BitmapFactory.Options为BitmapFactory的一个内部类,它主要用于设定与存储BitmapFactory加载图片的一些信息。下面是Options中需要用到的属性:
inJustDecodeBounds:如果设置为true,将不把图片的像素数组加载到内存中,仅加载一些额外的数据到Options中。
outHeight:图片的高度。
outWidth:图片的宽度。
inSampleSize:如果设置,图片将依据此采样率进行加载,不能设置为小于1的数。例如设置为4,分辨率宽和高将为原来的1/4,这个时候整体所占内存将是原来的1/16。

示例Demo

下面通过一个简单的Demo来演示上面提到的内容,代码中注释比较清晰,这里就不再累述了。

代码如下:

package cn.bgxt.loadbigimg;

import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.view.Menu;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends Activity {
    private Button btn_loadimage;
    private ImageView iv_bigimage;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btn_loadimage = (Button) findViewById(R.id.btn_loadimage);
        iv_bigimage = (ImageView) findViewById(R.id.iv_bigimage);

        btn_loadimage.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // Bitmap bitmap=BitmapFactory.decodeFile("/sdcard/a.jpg");
                // iv_bigimage.setImageBitmap(bitmap);

                BitmapFactory.Options opts = new Options();
                // 不读取像素数组到内存中,仅读取图片的信息
                opts.inJustDecodeBounds = true;
                BitmapFactory.decodeFile("/sdcard/a.jpg", opts);
                // 从Options中获取图片的分辨率
                int imageHeight = opts.outHeight;
                int imageWidth = opts.outWidth;

                // 获取Android屏幕的服务
                WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
                // 获取屏幕的分辨率,getHeight()、getWidth已经被废弃掉了
                // 应该使用getSize(),但是这里为了向下兼容所以依然使用它们
                int windowHeight = wm.getDefaultDisplay().getHeight();
                int windowWidth = wm.getDefaultDisplay().getWidth();

                // 计算采样率
                int scaleX = imageWidth / windowWidth;
                int scaleY = imageHeight / windowHeight;
                int scale = 1;
                // 采样率依照最大的方向为准
                if (scaleX > scaleY && scaleY >= 1) {
                    scale = scaleX;
                }
                if (scaleX < scaleY && scaleX >= 1) {
                    scale = scaleY;
                }

                // false表示读取图片像素数组到内存中,依照设定的采样率
                opts.inJustDecodeBounds = false;
                // 采样率
                opts.inSampleSize = scale;
                Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/a.jpg", opts);
                iv_bigimage.setImageBitmap(bitmap);

            }
        });
    }
}
 

效果展示:

总结
这里讲解了如何加载一个大分辨率的图片到内存中并使用它。不过一般好一点的图片处理软件,都会有图片放大功能,如果仅做此处理,单纯的把处理后的图片放大,会影响显示效果,图片还原度不高。一般会重新获取放大区域的图片的分辨率像素数组,然后重新处理加载到内存中进行显示。


    
 
 

您可能感兴趣的文章:

  • android开发中获取手机分辨率大小的方法
  • 在Android中创建菜单项Menu以及获取手机分辨率的解决方法
  • android根据分辨率自动调整字体大小的实例代码
  • Android的单位以及屏幕分辨率详解
  • android实用工具类分享(获取内存/检查网络/屏幕高度/手机分辨率)
  • android 分辨率适配的方法
  • Android基础之使用Fragment适应不同屏幕和分辨率(分享)
  • android计算pad或手机的分辨率/像素/密度/屏幕尺寸/DPI值的方法
  • Android瀑布流实例 android_waterfall
  • Android的OpenGL编程实例 Android-GL
  • android 简单图片动画播放的实例代码
  • android WakeLock使用方法代码实例
  • Android的OpenGL编程实例 Android-GL iis7站长之家
  • android 弹出提示框的使用(图文实例)
  • 控制Android LED灯颜色的代码实例
  • Android中AnimationDrawable使用的简单实例
  • Android中将View的内容保存为图像的简单实例
  • Android入门之LinearLayout、AbsoluteLayout的用法实例讲解
  • android中Bitmap的放大和缩小实例代码
  • android中写一个内部类来选择文件夹中指定的图片类型实例说明
  • 怎样删除android的gallery中的图片实例说明
  • 在Android中 获取正在运行的Service 实例
  • Android根据电话号码获得联系人头像实例代码
  • Android调用默认浏览器打开指定Url的方法实例
  • android双缓冲技术实例详解
  • ANDROID 完美退出APP的实例代码
  • Android对sdcard扩展卡文件操作实例详解
  • Android 清除SharedPreferences 产生的数据(实例代码)
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • Android 图片加载和缓存库 Glide
  • Android加载对话框同时异步执行实现方法
  • Android 中动态加载.jar的实现步骤
  • Android中自定义加载样式图片的具体实现
  • android动态加载布局文件示例
  • android判断phonegap是否联网且加载super.loadUrl网址
  • 基于android示例程序(bitmapfun) 高效加载图片让人无语地方
  • Android 游戏引擎libgdx 资源加载进度百分比显示案例分析
  • Android 自定义标题栏 显示网页加载进度的方法实例
  • 基于Android ListView之加载使用技巧
  • Android实现加载广告图片和倒计时的开屏布局
  • Android 异步加载图片的实例代码
  • android异步加载图片并缓存到本地实现方法
  • Android 异步加载图片分析总结
  • android 加载本地联系人实现方法
  • android WebView加载html5介绍
  • 申请Android Map 的API Key(v2)的最新申请方式(SHA1密钥)
  • Android系统自带样式 (android:theme)
  • Android开发需要的几点注意事项总结
  • Android网络共享软件 Android Wifi Tether
  • android 4.0 托管进程介绍及优先级和回收机制
  • Android 图标库 Android GraphView
  • Android访问与手机通讯相关类的介绍
  • 轻量级Android开发工具 Android Tools
  • Android及andriod无线网络Wifi开发的几点注意事项
  • Android 开发环境 Android Studio
  • Android 2.3 下StrictMode介绍
  • IDEA的Android开发插件 idea-android
  • Android手机事件提醒 Android Notifier
  • XBMC的Android客户端 android-xbmcremote
  • Android小游戏 Android Shapes


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3