Android开发Bitmap加载大图

  • Android中使用Bitmap加载图片很容易造成OOM,所以要在加载的时候对其做相应的处理。
  • Bitmap的压缩格式
    • ALPHA_8
      表示8位Alpha位图,即A=8,一个像素点占用1个字节,它没有颜色,只有透明度
    • ARGB_4444
      表示16位ARGB位图,即A=4,R=4,G=4,B=4,一个像素点占4+4+4+4=16位,2个字节
    • ARGB_8888
      表示32位ARGB位图,即A=8,R=8,G=8,B=8,一个像素点占8+8+8+8=32位,4个字节
    • RGB_565
      表示16位RGB位图,即R=5,G=6,B=5,它没有透明度,一个像素点占5+6+5=16位,2个字节
  • 了解了Bitmap的压缩格式,这样我们就知道图片加载到手机上所占的内存大小了。
  • 图片的 宽 * 高 * 每个像素所占的大小 = 图片的总大小。
  • 在不进行设置压缩格式的情况下,默认使用 ARGB_8888,每个像素占4个字节。

    创建工程BitmapTest,布局文件中一个按钮,一个ImageView。
    
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:layout_marginTop="10dp"
        android:layout_centerHorizontal="true"
        android:id="@+id/iv_scenery"
        android:layout_width="300dp"
        android:layout_height="300dp" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="直接加载图片"
        android:id="@+id/btn_load"
        android:layout_below="@+id/iv_scenery"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="20dp" />
</RelativeLayout>
创建一个assets文件夹,放入了一个2560*1600分辨率的a.jpg图片。
MainActivity代码如下:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button btn_load;
    private ImageView iv_scenery;

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

        btn_load = (Button) this.findViewById(R.id.btn_load);
        iv_scenery = (ImageView) this.findViewById(R.id.iv_scenery);

        btn_load.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_load:
                try {
                    //拿到图片对应的输入流
                    InputStream inputStream = getResources().getAssets().open("a.jpg");
                    Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                    Log.d("直接加载bitmap","大小:"+bitmap.getByteCount()+"b ,--"+(double)bitmap.getByteCount()/1024/1024+"M --,宽度:"
                            +bitmap.getWidth()+"--,高度:"+bitmap.getHeight());
                    //设置给imageview
                    iv_scenery.setImageBitmap(bitmap);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
        }
    }
}
运行程序,点击 直接加载图片按钮。图片就会加载上去。Log如下。

log

可见直接加载所占的内存为15.625M。也验证了我们计算图片所占内存大小的方法。
2560 * 1600 * 4 = 16384000 。
如果对图片的效果要求不是很高,可以设置图片的格式为RGB_565,这样就可以省一半内存了。
布局文件中新加个按钮 ,
<Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="压缩格式后加载"
        android:id="@+id/btn_compress"
        android:layout_centerHorizontal="true"
        android:layout_below="@+id/btn_load"
MainActivity中对其进行监听。
private Button btn_compress;
     btn_compress = (Button) this.findViewById(R.id.btn_compress);
     btn_compress.setOnClickListener(this);

       case R.id.btn_compress:
                try {
                    //拿到图片对应的输入流
                    InputStream inputStream = getResources().getAssets().open("a.jpg");
                    //首先,如果对图片质量要求不高,可以设置图片的压缩格式为RGB_565
                    BitmapFactory.Options options = new BitmapFactory.Options();
                    options.inPreferredConfig = Bitmap.Config.RGB_565;
                    //矩阵
                    Rect rect = new Rect();
                    //获取到bitmap对象
                    Bitmap bitmap2 = BitmapFactory.decodeStream(inputStream, rect, options);
                    Log.d("压缩格式为RGB_565加载bitmap2", "大小:" +bitmap2.getByteCount()+"b ,--"+ (double) bitmap2.getByteCount() / 1024 / 1024 +
                            "M--,宽度:" + bitmap2.getWidth() + "--,高度:" + bitmap2.getHeight());
                    //设置给imageview
                    iv_scenery.setImageBitmap(bitmap2);
                }catch (IOException e) {
                    e.printStackTrace();
                }
                break;
运行程序点击 压缩格式后加载 按钮,发现图片大小比之前刚好小了一半。Log如下:

log

但是即使这样,图片的大小还是很大的,所以我们在加载的时候要对其进行缩放。
布局文件中添加  压缩并缩放后加载 按钮。
 <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="压缩并缩放后加载"
        android:id="@+id/btn_scale"
        android:layout_below="@+id/btn_compress"
        android:layout_centerHorizontal="true"
        />
MainActivity中对按钮进行监听,图片等比例缩放,这样子就不会影响图片的效果。
  private Button btn_scale;
   btn_scale = (Button) this.findViewById(R.id.btn_scale);
     btn_scale.setOnClickListener(this);

    case R.id.btn_scale:
                try {
                    //拿到图片对应的输入流
                    InputStream inputStream = getResources().getAssets().open("a.jpg");
                    //首先,如果对图片质量要求不高,可以设置图片的压缩格式为RGB_565
                    BitmapFactory.Options options = new BitmapFactory.Options();
                    options.inPreferredConfig = Bitmap.Config.RGB_565;
                    //设置为true,表示解析Bitmap对象,该对象不占内存
                    options.inJustDecodeBounds = true;
                    //矩阵
                    Rect rect = new Rect();
                    BitmapFactory.decodeStream(inputStream,rect,options);
                    //设置缩放比例
                    options.inSampleSize = computeScale(options, iv_scenery);
                    Log.d("比例",options.inSampleSize+"");
                    //拿到比例之后要把options.inJustDecodeBounds重新设置为false
                    options.inJustDecodeBounds = false;
                    //获取到bitmap对象
                    Bitmap bitmap3 = BitmapFactory.decodeStream(inputStream,rect,options);
                    Log.d("压缩并缩放后加载bitmap3","大小:"+bitmap3.getByteCount()+"b ,--"+(double)bitmap3.getByteCount()/1024/1024+"M--,宽度:"+bitmap3.getWidth()+"--,高度:"+bitmap3.getHeight());
                    iv_scenery.setImageBitmap(bitmap3);
                }catch (IOException e) {
                    e.printStackTrace();
                }
                break;

       //计算缩放比例
    private int computeScale(BitmapFactory.Options options, ImageView iv_scenery) {
        int scaleSize = 1;
        if (options.outWidth > iv_scenery.getWidth() ||  options.outHeight >  iv_scenery.getHeight()){
            int widthScale = Math.round((float) options.outWidth / (float) iv_scenery.getWidth());
            int heightScale = Math.round((float) options.outHeight / (float) iv_scenery.getHeight());
            if (widthScale >= heightScale){
                scaleSize = widthScale;
            }else {
                scaleSize = heightScale;
            }
        }
        return scaleSize;
    }
运行程序,点击 压缩并缩放后加载 按钮,发现图片已经小很多了。Log如下:

log

这样图片的大小就只有0.5M了,就不容易造成OOM。
以上就是Bitmap加载大图方式方法。如有错误请指出,谢谢!
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值