Android 关于大图片的处理

在Android上面处理图片一直是一件很麻烦的事情,尤其是一些大图片,例如全景图的展示。

为什么说是一件麻烦的事情,主要有一下几个原因:

1.占内存,容易OOM

比如,一张1000 * 1000的图片,采用ARGB-8888的方式,这种方式,该图片每个px占用4个byte,所以总大小是1000 * 1000 * 4 ,它占用的内存就将近4M。这也不是一张很大的图片,但是却要占用4M内存。

2.使用UI主线程去加载大图片,非常耗APP的性能。很有可能出现响应慢,甚至是ANR的出现。

3.在加载多张图片的时候,如果没有使用缓存,app的流畅性和响应速度都会收到影响。

当然现在市面上也有很多开源框架来处理大图片,比如Glide、 Picasso等等.

但是,虽然我们没必要是重复造轮子,但是我们也有必要知道轮子是怎么造的。下面我们简单了解一下如何有效的展示一张大图。

一、bitmap,我们比较关注的是它的形状以及尺寸,那我们应该如何读取一张图片的形状和尺寸呢?直接看代码

//定义option
BitmapFactory.Options options = new BitmapFactory.Options();
//设置true,避免内存分配
options.inJustDecodeBounds = true;

//获取图片的宽和高
BitmapFactory.decodeResource(getResources(), R.id.image, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;

//获取图片的形状
String imageType = options.outMimeType;

[BitmapFactory]提供了decoding方法,为了防止OOM,在decode之前一定要检查好尺寸。

二、计算合理的样本数据

public static int calculateInSampleSize(
            BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // 获取到图片的宽和高
    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;

        while ((halfHeight / inSampleSize) >= reqHeight
                && (halfWidth / inSampleSize) >= reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}

三、计算样本尺寸并decode

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
        int reqWidth, int reqHeight) {

    // 检查尺寸
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);

    // 计算样本尺寸
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // 按照样本尺寸decode图片
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}

四、显示图片到ImageView

imageView.setImageBitmap(
    decodeSampledBitmapFromResource(getResources(), R.id.image, 200, 200));

总结:这种方式可以轻松地将任意大尺寸的图片以200*200的缩略图的方式显示到ImageView上面。

你可能感兴趣的:(Android 关于大图片的处理)