在android开发过程中图片的存储优化是非常常见,处理不好,时常会造成图片OOM。接下来分享一下我在开发过程中做的相应的处理,仅供各位参考,如有不足还请多多指教。

     首先我们知道图片在app存在形式无非就是:file、stream流、bitmap!

一、接下来列出几个图片OOM的出现情况

    1、在一个页面中一次性加载过多的图片

    2、加载的图片过大

    3、bitmap的错误使用

二、图片优化的处理方式:尺寸压缩、质量压缩、内存复用

   在此我们先知道一张图片的大小=图片的宽x图片的高x一个像素所占的大小。

   1、尺寸压缩

      按照一定的比例减小图片的宽高从而减少单位尺寸的像素值,这样的话可以改变图片在内存中的大小。这种做法只是改变了图片在加载时内存中的大小,但是磁盘中图片的大小是没有发生变化的

   代码示例:

/** 
* @param pathUrl 文件路径 
* @return 
*/
public Bitmap getBitmap(String pathUrl) {
    // 配置压缩的参数
    BitmapFactory.Options options = new BitmapFactory.Options();
    // 开始读入图片,此时把options.inJustDecodeBounds 设为true,方便图片在不加载进内存的情况下获取图片的宽高
    options.inJustDecodeBounds = true;
    Bitmap bitmap = BitmapFactory.decodeFile(pathUrl, options);//这个时候decode的bitmap为null
    options.inJustDecodeBounds = false;//将inJustDecodeBounds设置为false,加载图片数据
    //nSampleSize的作用就是可以把图片的宽和高缩小inSampleSize倍,所占内存缩小inSampleSize的平方
    //例如,inSampleSize = 2,则取出的缩略图的宽和高都是原始图片的1/2,图片大小就为原始大小的1/4。
    options.inSampleSize = calculateInSampleSize(options,400,100);
    bitmap = BitmapFactory.decodeFile(pathUrl, options);//重新读出图片
    return bitmap;
}
/**
 * @param options
 * @param reqWidth  我们期望的图片的宽,单位px
 * @param reqHeight 我们期望的图片的高,单位px
 * @return
 */
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;
}

   1、质量压缩

      质量压缩不会减少图片的像素,它是在保持像素的前提下改变图片的位深及透明度,来达到压缩图片的目的,图片的长,宽,像素都不会改变,它只是改变磁盘中的文件大小,并不能改变加载时内存中的图片大小

   代码示例:

/**
 * @param bitmap bitmap
 * @param int quality
 * @return
 */
public Bitmap qualityBitmap(Bitmap bitmap, int quality){
    //quality,可以调节你压缩的比例,但是质量压缩对png格式这种图片没有作用,因为png是无损压缩。
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.WEBP,100,outputStream);
    while (outputStream.toByteArray().length/1024>quality){
        outputStream.reset();
        bitmap.compress(Bitmap.CompressFormat.WEBP,quality,outputStream);
        if (quality>5)quality-=5;
        else break;
    }
    ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inPreferredConfig=Bitmap.Config.RGB_565;
    Bitmap bitmap1 = BitmapFactory.decodeStream(inputStream, null, options);
    return bitmap1;
}

   3、内存复用inbitmap注意点

    2.3上,bitmap的数据是存储在native的内存区域,并不是在Dalvik的内存堆上。

   3.0开始,系统在BitmapFactory.Options里引入了inBitmap机制来配合缓存机制。如果在载入图片时传入了inBitmap那么载入的图片就是inBitmap里的值。这样可以统一有缓存和无缓存的载入方式。

    使用inBitmap,在4.4之前,只能重用相同大小的bitmap的内存区域,而4.4之后你可以重用任何bitmap的内存区域,只要这块内存比将要分配内存的bitmap大就可以。

    新申请的bitmap与旧的bitmap必须有相同的解码格式

    使用此方法需要inMutable=true,inSampleSize=1

   *例外,bitmap也可以通过缩放法压缩(martix)、createScaledBitmap。

    以上是别人在项目过程中对图片处理一些做法,写的不错,请多多指教