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

泡在网上的日子 / 文 发表于2014-08-26 11:06 次阅读 bitmap,图库,MediaStore

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方法:

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:

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可以认为是宽和高的最大值。

收藏 赞 (6) 踩 (0)
上一篇:可以用eclipse编译的日历代码Calendar4.0
本项目是基于ics4.0的Calendar编译,代码取自 https://github.com/OpenDroidApps/Calendar-ICS 解决了sdk中没有4.0Calendar所依赖的一些包而无法编译的问题。发现4.3之后的日历在包的依赖上又有很多变化,此项目不适用与4.3以上。 本项目某些操作会崩溃,你
下一篇:Android 2D Graphics学习(二)、Canvas篇1、Canvas基本使用
绘图需要四大基本要素: 1、一个用来保存像素的Bitmap; 2、一个Canvas画布,绘制 Bitmap操作; 3、绘制的东西 4、绘制的画笔Paint(颜色和样式) 1、如何获得一个Canvas对象。 Canvas对象的获取方式有三种: 第一种我们通过重写View.onDraw方法,View中的Ca