Android压缩图片

最近碰到一个图片上传的问题,普通相机拍出的图片基本在1M以上,并不适合用作于图片上传,于是就用到了这个BitmapFactory.compress()方法,来实现对图片进行压缩,来看一下具体的压缩操作。

1.inSampleSize参数

BitmapFactory中有一个内部类BitmapFactory.Options,其中当options.inSampleSize值>1时,根据文档:

If set to a value > 1, requests the decoder to subsample the original image, returning a smaller image to save memory. (1 -> decodes full size; 2 -> decodes 1/4th size; 4 -> decode 1/16th size). Because you rarely need to show and have full size bitmap images on your phone. For manipulations smaller sizes are usually enough.

也就是说,options.inSampleSize是以2的指数的倒数被进行放缩。这样,我们可以依靠inSampleSize的值的设定将图片放缩载入,这样一般情况也就不会出现上述的OOM问题了。现在问题是怎么确定inSampleSize的值?每张图片的放缩大小的比例应该是不一样的!这样的话就要运行时动态确定。在BitmapFactory.Options中提供了另一个成员inJustDecodeBounds

2.inJustDecodeBounds参数

 BitmapFactory.Options option = new BitmapFactory.Options();
        option.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(srcPath, option);

设置inJustDecodeBounds为true后,decodeFile并不分配空间,但可计算出原始图片的长度和宽度,即opts.widthopts.height。有了这两个参数,再通过一定的算法,即可得到一个恰当的inSampleSize

3.具体执行操作

 public static String compressImage(String srcPath) {
    //1.先获取到图片的宽高
        BitmapFactory.Options option = new BitmapFactory.Options();
        option.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(srcPath, option);
        int actualWidth = option.outWidth;
        int actualHeight = option.outHeight;
        //设置想要压缩的图片大小
        int desiredHeight = 800;
        int desiredWidth = 480;

      //2.设置inJustDecodeBounds 为false
        option.inJustDecodeBounds = false;
        option.inSampleSize = findBestSampleSize(actualWidth, actualHeight,
                desiredWidth, desiredHeight);//设置inSampleSize大小

      //3.重新设置Bitmap
        Bitmap tempBitmap = BitmapFactory.decodeFile(srcPath, option);

     //4.压缩流到一定大小(注意,上面的宽高压缩和下面的大小压缩是两个概念,先看下面)
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        tempBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);//100是保留原100%的品质,压缩0% 作用:输出到baos 流里面去

        int options = 90;
        //判断,如果图片大于200kb,继续压缩
        while (baos.toByteArray().length / 1024 > 200) {
            baos.reset();
            tempBitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里才是真正进行压缩
            options -= 10;
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());

      //5.保存到本地,并返回图片的路径
     ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
        byte[] buf = new byte[2048];
        int len = 0;
        FileOutputStream fos = null;
        File file = null;
        try {
            File dir = Constants.me().getExternalDir();
            if (!dir.exists()) {
                dir.mkdirs();
            }
            String filename = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date()) + ".jpeg";
            file = new File(dir, filename);
            fos = new FileOutputStream(file);
            while ((len = isBm.read(buf)) != -1) {
                fos.write(buf, 0, len);
            }
            fos.flush();
        } catch (IOException e) {
            Log4a.e(e);
        } finally {
            if (isBm != null) {
                try {
                    isBm.close();
                } catch (IOException e) {
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                }
            }
            if (tempBitmap != null) {
                tempBitmap.recycle();
            }
        }
        return file == null ? srcPath : file.getAbsolutePath();
    }


      //这个方法用来计算inSampleSize大小
      static int findBestSampleSize(int actualWidth, int actualHeight,
                                  int desiredWidth, int desiredHeight) {
        double wr = (double) actualWidth / desiredWidth;
        double hr = (double) actualHeight / desiredHeight;
        double ratio = Math.min(wr, hr);
        float n = 1.0f;
        //如果最小的还>2 则让比例*2
        while ((n * 2) <= ratio) {
            n *= 2;
        }
        return (int) n;
    }

4.Bitmap占用的存储大小和内存大小区别解释
该链接是例子讲解区别的
一句话总结就是:Bitmap.compress方法确实可以压缩图片,但压缩的是存储大小 如果想要显示的Bitmap占用的内存少一点,还是需要去设置加载的像素长度和宽度(变成缩略图)

你可能感兴趣的:(Android压缩图片)