使用 MediaStore.Images.Media.getBitmap从Uri中获得bitmap以及其缺陷

本文介绍了如何优化MediaStore.Images.Media.getBitmap方法,通过自定义getThumbnail方法来获取指定大小的图片bitmap,避免在处理大图片时的内存消耗,并详细解释了方法实现原理及关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MediaStore.Images.Media.getBitmap(ContentResolver cr,Uri url)方法可以从一个已知的图片Uri中获得图片的bitmap对象,其中ContentResolver通常可以通过在Activity中调用的getContentResolver()方法中获取。Uri地址就是类似 content://media/external/images/media/2 的地址,也就是Content Provider定义的地址形式。但是这种获取bitmap的方式在图片较大的时候并不可取。为什么呢?

从getBitmap的参数可以看出,我们没有传递所要得到的bitmap大小信息,那么getBitmap的返回的bitmap究竟有多大我们就无从知晓,完全取决于getBitmap本身,最乐观的结果是getBitmap能智能的判断我们的需求,返回一个合适的bitmap,但是可能性很小。到底getBitmap中做了什么还是直接去看他的实现源码吧:

android.provider.MediaStore中找到Images.Media的getBitmap方法:

1
2
3
4
5
6
7
public static final Bitmap getBitmap(ContentResolver cr, Uri url)
        throws FileNotFoundException, IOException {
    InputStream input = cr.openInputStream(url);
    Bitmap bitmap = BitmapFactory.decodeStream(input);
    input.close();
    return bitmap;
}

呵呵,以为是一个很复杂的方法,其实它很简单很粗暴,返回的是原始大小的bitmap。

MediaStore.Images.Media自身的getBitmap不是很可靠。那我们来自定义一个getBitmap吧:

取名叫getThumbnail,他能返回一个指定大小的bitmap:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public static Bitmap getThumbnail(Uri uri,int size) throws FileNotFoundException, IOException{
    InputStream input = this.getContentResolver().openInputStream(uri);
    BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();
    onlyBoundsOptions.inJustDecodeBounds = true;
    onlyBoundsOptions.inDither=true;//optional
    onlyBoundsOptions.inPreferredConfig=Bitmap.Config.ARGB_8888;//optional
    BitmapFactory.decodeStream(input, null, onlyBoundsOptions);
    input.close();
    if ((onlyBoundsOptions.outWidth == -1) || (onlyBoundsOptions.outHeight == -1))
        return null;
    int originalSize = (onlyBoundsOptions.outHeight > onlyBoundsOptions.outWidth) ? onlyBoundsOptions.outHeight : onlyBoundsOptions.outWidth;
    double ratio = (originalSize > size) ? (originalSize / size) : 1.0;
    BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
    bitmapOptions.inSampleSize = getPowerOfTwoForSampleRatio(ratio);
    bitmapOptions.inDither=true;//optional
    bitmapOptions.inPreferredConfig=Bitmap.Config.ARGB_8888;//optional
    input = this.getContentResolver().openInputStream(uri);
    Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);
    input.close();
    return bitmap;
}
private static int getPowerOfTwoForSampleRatio(double ratio){
    int k = Integer.highestOneBit((int)Math.floor(ratio));
    if(k==0) return 1;
    else return k;
}


其中参数size可以认为是宽和高的最大值。


转自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0826/1665.html

package com.example.myapplication; import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; import android.os.Bundle; import android.provider.MediaStore; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; import java.io.IOException; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ImageView imageView = findViewById(R.id.image); Button button = findViewById(R.id.btn); button.setOnClickListener(v -> openGallery()); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == 1 && resultCode == RESULT_OK && data != null && data.getData() != null) { // 获取选择的图片URI Uri selectedImageUri = data.getData(); try { // 将URI转换为Bitmap Bitmap bitmap = MediaStore.Images.Media.getBitmap( this.getContentResolver(), selectedImageUri); // 设置到ImageView imageView.setImageBitmap(bitmap); } catch (IOException e) { e.printStackTrace(); } } } public void openGallery() { Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); startActivityForResult(intent,1); } }帮我修改
最新发布
03-13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值