Android使用BitmapFactory.Options解决加载大图片内存溢出问题

来源:互联网 发布:宽带网络安装 编辑:程序博客网 时间:2024/06/05 14:50

由于Android对图片使用内存有限制,若是加载几兆的大图片便内存溢出。Bitmap会将图片的所有像素(即长x宽)加载到内存中,如果图片分辨率过大,会直接导致内存溢出(java.lang.OutOfMemoryError),只有在BitmapFactory加载图片时使用BitmapFactory.Options对相关参数进行配置来减少加载的像素。

1、设置缩放大小对图片作处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public Bitmap getBitmapFromFile(File dst,int width, int height) {
    if (null != dst && dst.exists()){
        BitmapFactory.Options opts= null;
        if (width > 0&& height > 0){
            opts = new BitmapFactory.Options();
            opts.inJustDecodeBounds= true;
            BitmapFactory.decodeFile(dst.getPath(), opts);
            // 计算图片缩放比例
            finalint minSideLength = Math.min(width, height);
            opts.inSampleSize= computeSampleSize(opts, minSideLength,
                    width * height);
            opts.inJustDecodeBounds= false;
            opts.inInputShareable= true;
            opts.inPurgeable= true;
        }
        try {
            return BitmapFactory.decodeFile(dst.getPath(), opts);
        } catch(OutOfMemoryError e){
            e.printStackTrace();
        }
    }
    return null;
}
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
publicstatic int computeSampleSize(BitmapFactory.Options options,
        int minSideLength,int maxNumOfPixels){
    int initialSize = computeInitialSampleSize(options, minSideLength,
            maxNumOfPixels);

    int roundedSize;
    if (initialSize <= 8){
        roundedSize = 1;
        while (roundedSize < initialSize){
            roundedSize <<= 1;
        }
    } else{
        roundedSize = (initialSize+ 7)/ 8* 8;
    }

    return roundedSize;
}

private static int computeInitialSampleSize(BitmapFactory.Options options,
        int minSideLength,int maxNumOfPixels){
    double w = options.outWidth;
    double h = options.outHeight;

    int lowerBound = (maxNumOfPixels == -1)? 1: (int)Math.ceil(Math
            .sqrt(w* h / maxNumOfPixels));
    int upperBound = (minSideLength == -1)? 128: (int)Math.min(Math
            .floor(w/ minSideLength), Math.floor(h/ minSideLength));

    if (upperBound < lowerBound){
        // return the larger one when there is no overlapping zone.
        return lowerBound;
    }

    if ((maxNumOfPixels == -1)&& (minSideLength == -1)){
        return 1;
    } elseif (minSideLength == -1){
        return lowerBound;
    } else{
        return upperBound;
    }
}