Android 图片压缩并保存的方法

参考:

    1.https://blog.csdn.net/pbm863521/article/details/74391787

    2.https://www.jianshu.com/p/871f0c1f0006

1.背景:

    最近一个项目的开发,需要用到相机拍照,裁剪(使用的是ucrop,推荐使用),保存,上传图片到七牛云的操作,并在上传的过程中遇到了图片过大,服务器返回溢出的错误,难搞哦。在其中发现,如果调用系统的相机,拍出来的图片会有5M的大小,但是调用美图相机的应用,拍照大小只有500k不到,但是用户的手机不可能每个都装美图相机软件,所以需要对图片进行压缩。

2.方法:

    网上大致的方法分为三种,质量压缩,按比例大小压缩(尺寸压缩),采样率压缩,常用到的有两种,其中采样率压缩不太常用,故不作过多的阐述。主要说一下其他两种。

2.1 质量压缩

    保持像素的前提下改变图片的位深及透明度(即:通过算法抹掉(同化)图片中的一些某点附近 相近的像素)达到降低质量压缩文件的目的。

2.2 尺寸压缩

    通过减少单位尺寸的像素值,真正意义上的降低像素(通过缩放图片像素来减少图片占用内存大小)

2.3 第三方开源库

   近期看资料的时候看到的,鲁班(luban),据说逆向微信图片压缩算法得来的,虽不能完全达到微信效果,但是也很可观了,github上Star已经11K+了,我还没试过,小伙伴可以尝试:https://github.com/Curzibn/Luban

3.代码 (亲测可用)

3.1 指定图片大小,使用缩放,质量压缩的方式将图片压缩到 100 k以内

/**
     * 图片按比例大小压缩方法
     *
     * @param srcPath (根据路径获取图片并压缩)
     * @return
     */
    public static Bitmap getimage(String srcPath) {

        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        // 开始读入图片,此时把options.inJustDecodeBounds 设回true了
        newOpts.inJustDecodeBounds = true;
        Bitmap bitmap = BitmapFactory.decodeFile(srcPath, newOpts);// 此时返回bm为空
        newOpts.inJustDecodeBounds = false;
        int w = newOpts.outWidth;
        int h = newOpts.outHeight;
        float hh = 1920f;// 这里设置高度为1920f
        float ww = 1080f;// 这里设置宽度为1080f
        // 缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
        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(srcPath, newOpts);
        return compressImage(bitmap);// 压缩好比例大小后再进行质量压缩
    }

    /**
     * 质量压缩方法
     *
     * @param image
     * @return
     */
    public static Bitmap compressImage(Bitmap image) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
        int options = 90;
        while (baos.toByteArray().length / 1024 > 100) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
            baos.reset(); // 重置baos即清空baos
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%,把压缩后的数据存放到baos中
            options -= 10;// 每次都减少10
            if (options < 0) {
                break;
            }
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片
        return bitmap;
    }

3.2 将Bitmap保存到本地手机路径

    /**
     * 保存Bitmap到指定文件
     * @param bitmap 需要保存的图片
     * @param file 保存的文件路径
     */
    public static void saveBitmap(Bitmap bitmap, File file) {

        try {
            FileOutputStream fos = new FileOutputStream(file);
            // 这两保存的时候我选择了70的质量
            bitmap.compress(Bitmap.CompressFormat.JPEG, 70, fos);
            fos.flush();
            fos.close();
        } catch (Exception e) {
            PLog.e("saveBitmap err11 = ", e);
        }
    }

 

4.总结

   开发一个项目的过程中,会遇到很多困难,中间会遇到各种各样的问题,会百度各种各种的问题,也会test各种方法,有用或没用,可以在旁边新建一个记事本,将用到的,可用的,方法记录下来,包括参考的博客地址,记录可以杂乱一点,但不影响。这样在项目结束之后,有了充足的时间,然后再去一点点整理,由浅及深,慢慢的去看这些博客,梳理成自己的知识。这样在下次遇到这些问题的时候,就会有一种我遇到过,我知道怎么解决,对于预言项目周期,以及自身成长都有不错的效果。

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