Android图片常见问题处理

图片常见问题处理

  • 图片占用的内存计算

图片宽度 * 图片高度 * 单位像素占用的字节

单位像素占用的字节和Bitmap.Config有关,常用的有RGB_565和ARGB_8888。RGB_565占2个字节,ARGB_8888占4个字节支持透明度,RGB_565表示的颜色值没有ARGB_8888的多,RGB_565不支持透明度。

  • 如何处理图片占用内存过大导致内存溢出

通过图片占用内存的计算公式可以得知,有两个方法减小图片占用的内存:

  1. 设置Bitmap.Config为RGB_565,这样图片占用的内存为ARGB_8888的一半。
BitmapFactory.Options option = new BitmapFactory.Options();
option.inPreferredConfig = Config.RGB_565;
Bitmap bitmap = BitmapFactory.decodeFile(imgPath, option);
  1. 减小图片的高度和宽度
BitmapFactory.Options option = new BitmapFactory.Options();
//值为0.5代表高度和宽度缩小一半,值为1表示不变
option.inSampleSize = 0.5;
Bitmap bitmap = BitmapFactory.decodeFile(imgPath, option);
  • 实际应用

  1. 实际开发中,我们一般不知道待加载的图片的高度和宽度,如果想让内存中图片的高度和宽度低于200px从而减少图片占用的内存,我们如何设置inSampleSize的值呢?BitmapFactory.Options提供了inJustDecodeBounds参数。当需要获取Bitmap的宽度和高度的时候,把inJustDecodeBounds设置为true,Bitmap创建好后,是不占用内存的,这样可以获取到高度和宽度;当需要获取可以显示的Bitmap时候,再把inJustDecodeBounds设置为false。下面是我项目中封装的方法:
public static Bitmap ratio(String imgPath, float width, float height) {
    BitmapFactory.Options newOpts = new BitmapFactory.Options();
    // 开始读入图片,此时把options.inJustDecodeBounds 设回true,即只读边不读内容
    newOpts.inJustDecodeBounds = true;
    newOpts.inPreferredConfig = Config.RGB_565;
    Bitmap bitmap = BitmapFactory.decodeFile(imgPath, newOpts);
    newOpts.inJustDecodeBounds = false;
    int w = newOpts.outWidth;
    int h = newOpts.outHeight;
    // 想要缩放的目标尺寸
    float hh = height;
    float ww = width;
    // 计算缩放比例
    int be = 1;// be=1表示不缩放
    if (w > h && w > ww) {// 如果宽度大的话根据宽度固定大小缩放
        be = (int) (newOpts.outWidth / ww);
    } else if (w < h && h > hh) {// 如果高度高的话根据宽度固定大小缩放
        be = (int) (newOpts.outHeight / hh);
    }
    if (be <= 0)
        be = 1;
    newOpts.inSampleSize = be;// 设置缩放比例
    // 开始压缩图片,注意此时已经把options.inJustDecodeBounds 设回false了
	bitmap = BitmapFactory.decodeFile(imgPath, newOpts);
	// 这里再进行质量压缩的意义不大,反而耗资源,删除
	return bitmap;
}
  1. 实际开发中,可能需要我们压缩图片的存储大小,比如2M压缩到1M,这叫质量压缩。质量压缩的是图片在存储空间中的大小,和图片加载到内存中占用的内存大小无关。
/**
* 存储Bitmap,并质量压缩,不大于maxSize(kb)
*
* @param image
* @param outPath
* @param maxSize
*
*/
public static void compressAndGenImage(Bitmap image, String outPath,int maxSize) throws IOException {
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    // 压缩度,100为不压缩
    int options = 100;
    image.compress(Bitmap.CompressFormat.JPEG, options, os);
    // 循环压缩
    while (os.toByteArray().length / 1024 > maxSize) {
        // Clean up os
        os.reset();
        // 每次递减10
        options -= 10;
        image.compress(Bitmap.CompressFormat.JPEG, options, os);
    }
    FileOutputStream fos = new FileOutputStream(outPath);  
    fos.write(os.toByteArray());
    fos.flush();
    fos.close();
}

你可能感兴趣的:(android)