Android - 在将图像加载到ImageView之前调整其大小以避免OOM问题

4

如何在从相册/照片中选择图像后,缩小ImageView上的图像大小?否则,选择的大型图像会导致OOM问题。

选择意图

SelectImageGallery1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(Intent.createChooser(intent, "Select Image1 From Gallery"), 1);
    }
}

设置 ImageView:

{
    Uri uri = I.getData();
    try {
        bitmap1 = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
        imageView1.setImageBitmap(bitmap1);
    } catch (IOException e) {
        e.printStackTrace();
    }
}
3个回答

1
请查看文档中的“高效加载大型位图”部分,特别是“将缩小版本加载到内存中”(https://developer.android.com/topic/performance/graphics/load-bitmap#load-bitmap)。
通过设置inSampleSize,您可以在加载位图之前控制其大小。
来自文档的说明:
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
        int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}

public static int calculateInSampleSize(
            BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) >= reqHeight
                && (halfWidth / inSampleSize) >= reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}

文档使用资源作为示例,但您应该能够通过获取InputStream并使用BitmapFactory.decodeStream(...)来使用ContentResolver。
ContentResolver cr = getApplicationContext().getContentResolver();
InputStream is = cr.openInputStream(uri);

谢谢@patrick。我已经阅读了所有内容,但我不明白如何实现它。 - NyP

1

我最终使用Glide解决了这个问题,以下是解决方法,供将来需要的人参考。 选择Intent

SelectImageGallery1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(Intent.createChooser(intent, "Select Image1 From Gallery"), 1);
    }
}

使用Glide将图像设置为Imageview
    @Override
    protected void onActivityResult(int RC, int RQC, Intent I) {
        super.onActivityResult(RC, RQC, I);
        if (RC == 1 && RQC == RESULT_OK && I != null && I.getData() != null) {
            Uri uri = I.getData();
            RequestOptions options = new RequestOptions()
                    .format(DecodeFormat.PREFER_RGB_565)
                    .placeholder(R.drawable.ic_launcher_background)
                    .error(R.drawable.ic_launcher_background);

            Glide.with(this)
                    .setDefaultRequestOptions(options)
                    .asBitmap()
                    .load(uri)
                    .centerInside()
                    .into(new CustomTarget<Bitmap>(512, 512) {
                        @Override
                        public void onResourceReady(@NonNull Bitmap bitmap1, @Nullable Transition<? super Bitmap> transition) {
                            imageView1.setImageBitmap(bitmap1);
                            MainActivity.this.bitmap1 = bitmap1;
                        }

                        @Override
                        public void onLoadCleared(@Nullable Drawable placeholder) {
                        }
                    });
        }

0
使用 Picasso 实现此目的。
implementation 'com.squareup.picasso:picasso:2.71828'

要加载图像,请使用以下代码

Picasso.get()
    .load(R.drawable.landing_screen)
    .resize(50, 50)
    .into(imageView1);

欲了解更多信息,请访问以下链接:

https://square.github.io/picasso/

您也可以使用它来异步从网络加载图像,而无需自己发起任何HTTP请求。


谢谢@Abdur Rahman。Picasso代码应该放在哪里?我有几个ImageView。 - NyP

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接