关于安卓压缩图片

遇坑过程

想保存Glide的缓存图片(失败)

一开始是想用Glide的硬盘缓存图片的,不过他计算的key值无法获取到(或许我不会),那就无法知道文件名字,这方法不行

自己用BitmapFactory压缩(忽大忽小)

上网看https://blog.csdn.net/jdsjlzx/article/details/44228935,用BitmapFactory压缩,效果是有些图片是尺寸是会变小,可是有些体积反而变大了(这也不太对)

下面是核心代码的使用demo

使用方法save(getimage(imagePath), Environment.getExternalStorageDirectory()+"/2.png", Bitmap.CompressFormat.PNG);


    /**
     * 图片按比例大小压缩方法
     *
     * @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 = 2560f;// 图片最大的高度为
        float ww = 1440f;// 图片最大的宽度为
        // 缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
        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
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片
        return bitmap;
    }

    /**
     * 保存图片
     *
     * @param src      源图片
     * @param filePath 要保存到的文件路径
     * @param format   格式
     * @return {@code true}: 成功<br>{@code false}: 失败
     */
    public static boolean save(Bitmap src, String filePath, Bitmap.CompressFormat format) throws IOException {
        return save(src, (new File(filePath)), format);
    }

    /**
     * 保存图片
     *
     * @param src    源图片
     * @param file   要保存到的文件
     * @param format 格式
     * @return {@code true}: 成功<br>{@code false}: 失败
     */
    public static boolean save(Bitmap src, File file, Bitmap.CompressFormat format) throws IOException {
        return save(src, file, format, false);
    }

    /**
     * 保存图片
     *
     * @param src      源图片
     * @param filePath 要保存到的文件路径
     * @param format   格式
     * @param recycle  是否回收
     * @return {@code true}: 成功<br>{@code false}: 失败
     */
    public static boolean save(Bitmap src, String filePath, Bitmap.CompressFormat format, boolean recycle) throws IOException {
        return save(src, (new File(filePath)), format, recycle);
    }

    /**
     * 保存图片
     *
     * @param src     源图片
     * @param file    要保存到的文件
     * @param format  格式
     * @param recycle 是否回收
     * @return {@code true}: 成功<br>{@code false}: 失败
     */
    public static boolean save(Bitmap src, File file, Bitmap.CompressFormat format, boolean recycle) throws IOException {
        if (isEmptyBitmap(src) || file.exists()) return false;
        System.out.println(src.getWidth() + ", " + src.getHeight());
        OutputStream os = null;
        boolean res = false;
        try {
            os = new BufferedOutputStream(new FileOutputStream(file));
            res = src.compress(format, 100, os);
            if (recycle && !src.isRecycled()) src.recycle();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            os.close();
        }
        return res;
    }

    /**
     * 判断bitmap对象是否为空
     *
     * @param src 源图片
     * @return {@code true}: 是<br>{@code false}: 否
     */
    private static boolean isEmptyBitmap(Bitmap src) {
        return src == null || src.getWidth() == 0 || src.getHeight() == 0;
    }

最后Luban完美解决

最后看到https://github.com/Curzibn/Luban/blob/master/README.md,使用Luban压缩,可以完美解决问题

Luban.with(this)
                    .load(path1)                                   // 传人要压缩的图片列表
                    .ignoreBy(100)                                  // 忽略不压缩图片的大小
                    .setTargetDir(Environment.getExternalStorageDirectory()+"/aaaaa")                        // 设置压缩后文件存储位置
                    .setCompressListener(new OnCompressListener() { //设置回调
                        @Override
                        public void onStart() {
                            // TODO 压缩开始前调用,可以在方法内启动 loading UI
                        }

                        @Override
                        public void onSuccess(File file) {
                            // TODO 压缩成功后调用,返回压缩后的图片文件
                            Log.d(TAG, "onSuccess: "+file.exists());
                        }

                        @Override
                        public void onError(Throwable e) {
                            // TODO 当压缩过程出现问题时调用
                            Log.d(TAG, "onError: "+e);
                        }
                    }).launch();    //启动压缩

总结

因为以前也没想过与研究压缩图片的事情,一开始时候一直想的事情是控制图片尺寸,最后发现尺寸一样的图片,人看上去也一样的图片,而大小可能相差很大。

阅读更多
文章标签: android 压缩 图片
个人分类: 安卓
上一篇Glide添加最新版到项目
下一篇FileProvider对用户体验的改变
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭