从手机中获取图片遇到的OOM问题解析

在安卓开发过程中,一个无可避免的功能就是通过图库或者拍照来获取图片。

在这个过程中,一个最经典的错误就是由于图片过大而造成的OOM问题。

首先调用图库或者是拍照功能

    /**
     * 图库选择
     */
    public static void choicephoto(Activity activity) {
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            Intent intent = new Intent();
            intent.setType(IMAGE_UNSPECIFIED);
            intent.setAction(Intent.ACTION_GET_CONTENT);
            activity.startActivityForResult(intent, CHOICEPHOTO);
        } else {
            Toast.makeText(activity, "请先插入SD卡", Toast.LENGTH_LONG).show();
        }
    }
    /**
     * 拍照
     */
    public static void takephoto(Activity activity) {
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            activity.startActivityForResult(intent, TAKEPHOTO);
        } else {
            Toast.makeText(activity, "请先插入SD卡", Toast.LENGTH_LONG).show();
        }
    }

  • 上面两个方法使用的Activity类型作为参数,如果是在Fragment启用该功能的话,参数处应传递Fragment类型
  • CHOICEPHOTO和TAKEPHOTO和两个int类型常量,可自行定义他们的数值。

当选择图片完成后,通过onActivityResult方法得到返回的数据

 @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        if (resultCode != RESULT_OK || data == null) {
            return;
        }
        switch (requestCode) {
            case CHOICEPHOTO:
                //从图库选择的图片根据手机不同,会有两种返回数据方式
                Uri uri = data.getData();
                if (uri != null) {
                    //OOM问题主要出现在此处,需对Bitmap进行压缩处理后再返回
                    photo = ImageUtils.compressImage(this, uri);
                    //对图片进行展示或者其他操作
                    showImg();
                } else {
                    Bundle extras = data.getExtras();
                    if (extras != null) {
                        photo = extras.getParcelable("data");
                        showImg();
                    }
                }
                break;
            case TAKEPHOTO:
                photo = data.getExtras().getParcelable("data");
                showImg();
                break;
        }
    }


  • 如果此处发生OOM,往往是由于Bitmap的分辨率过大造成的,因此需要对图片分辨率进行压缩处理后,再次展示

ImageUtils.compressImage(this, uri);方法的代码如下

    public static Bitmap compressImage(Context context, Uri uri) {
        //压缩参考尺寸(PX)
        float hh = 1280f;
        float ww = 720f;
        //图片宽高
        BitmapFactory.Options options = new BitmapFactory.Options();
        //开始读入图片,此时把options.inJustDecodeBounds 设为true
        options.inJustDecodeBounds = true;
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        //根据uri得到图片的具体地址
        String path = FileUtils.getImageAbsolutePath(context, uri);
        //此时返回bm为空
        BitmapFactory.decodeFile(path, options);
        //得到图片的宽高
        float w = options.outWidth;
        float h = options.outHeight;
        //压缩倍率
        float be = 1.0f;
        if (w > h) {
            be = ((w / hh + h / ww) / 2.0f);
        } else {
            be = ((w / ww + h / hh) / 2.0f);
        }
        //个人逻辑,仅供参考
        if (be <= 1.5f) {
            be = 1;
        }
        options.inSampleSize = (int) be;//设置缩放比例
        options.inJustDecodeBounds = false;
        //得到处理后的bitmap并返回
        Bitmap bitmap = BitmapFactory.decodeFile(path, options);
        return bitmap;
    }
}

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。