【问题标题】:Android - Resize image before loading to ImageView to avoid OOM issuesAndroid - 在加载到 ImageView 之前调整图像大小以避免 OOM 问题
【发布时间】:2020-01-17 17:02:08
【问题描述】:

从图库/照片中选择后,如何在 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();
    }
}

【问题讨论】:

    标签: java android


    【解决方案1】:

    查看文档的Loading Large Bitmaps Efficiently 部分,特别是Load a Scaled Down Version into Memory (https://developer.android.com/topic/performance/graphics/load-bitmap#load-bitmap)

    通过设置inSampleSize,您可以在加载之前控制Bitmap 的大小。

    来自文档:

    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 来使用ContentResolver 并改用BitmapFactory.decodeStream(...)

    ContentResolver cr = getApplicationContext().getContentResolver();
    InputStream is = cr.openInputStream(uri);
    

    【讨论】:

    • 谢谢@patrick。我已经阅读了所有内容,但我不明白如何实现它
    【解决方案2】:

    我终于使用 glide 解决了它,如下所示,以供将来可能需要它的人使用。 选择意图

    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) {
                            }
                        });
            }
    

    【讨论】:

      【解决方案3】:

      为此目的使用毕加索

      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 Ra​​hman。毕加索代码应该放在哪里?我有几个关于这个问题的图像视图。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-08
      • 1970-01-01
      • 2021-04-23
      相关资源
      最近更新 更多