最完善,最有用的图片压缩教程

作者: 唠嗑008 | 来源:发表于2017-09-19 12:43 被阅读294次

    github地址
    https://github.com/zhouxu88/ImgCompress

    在开发中,我们经常有这样一种需求,从相册选择图片,上传到服务器。随着手机像素的不断提升,照片也是小一点的3,4兆,大一点的多大10多兆。很明显,如果直接上传原图,会增大服务器压力,而且没有必要,更重要的是如果同时多传几张,这么大的流量,很容易上传失败,所以,在上传之前对图片压缩就显得很必要了。

    下面就为大家带来3种比较常见的压缩方式

    先给出一组数据,

    原图:width:2976; height:2976
    原图实际:--->byte:2299820 Mb:2.19328
    质量压缩 size--->:byte:1599831 kb:1562.33496
    按比例压缩 size--->:byte:191707 kb:187.21387
    鲁班压缩 size--->:byte:143792 kb:140.42188

    压缩效果:鲁班压缩 > 按比例压缩 > 质量压缩

    1、质量压缩

     public void getBitmap(String imgPath, String outPath) {  
            BitmapFactory.Options newOpts = new BitmapFactory.Options();  
            newOpts.inJustDecodeBounds = false;  
            newOpts.inPurgeable = true;  
            newOpts.inInputShareable = true;  
            // Do not compress  
            newOpts.inSampleSize = 1;  
            newOpts.inPreferredConfig = Config.RGB_565;  
            storeImage(bitmap, outPath); //保存图片
        }  
    

    注意

    • 质量压缩不会减少图片的像素,它是在保持像素的前提下改变图片的位深及透明度等,来达到压缩图片的目的,这也是为什么该方法叫质量压缩方法。所以这种方法,很可能不会减少图片的大小
    • 如果是bit.compress(CompressFormat.PNG, quality, baos);这样的png格式,quality就没有作用了,bytes.length不会变化,因为png图片是无损的,不能进行压缩

    保存图片

    /**
         * 把bitmap转化成图片存储在本地
         *
         * @param bitmap
         * @param outPath 本地的存储路径
         * @throws FileNotFoundException
         */
        public static boolean storeImage(Bitmap bitmap, String outPath) throws FileNotFoundException {
            FileOutputStream os = new FileOutputStream(outPath);
            boolean compressResult = bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
            return compressResult;
        }
    

    2、按比例压缩(尺寸压缩、采样率压缩)

    /**
         * 按比例压缩
         *
         * @param path    原图片路径
         * @param targetW 压缩后宽度
         * @param targetH 压缩后高度
         * @return 压缩后的图片的保存路径
         */
        public static String compressScale(String path,, String outPath, int targetW, int targetH) throws FileNotFoundException {
            // 获取option  
            BitmapFactory.Options options = new BitmapFactory.Options();
            // inJustDecodeBounds设置为true,这样使用该option decode出来的Bitmap是null,  
            // 只是把长宽存放到option中  
            options.inJustDecodeBounds = true;
            // 此时bitmap为null  
            Bitmap bitmap = BitmapFactory.decodeFile(path, options);
            int inSampleSize = 1; // 1是不缩放  
            // 计算宽高缩放比例  
            int inSampleSizeW = options.outWidth / targetW;
            int inSampleSizeH = options.outHeight / targetH;
            // 最终取大的那个为缩放比例,这样才能适配,例如宽缩放3倍才能适配屏幕,而  
            // 高不缩放就可以,那样的话如果按高缩放,宽在屏幕内就显示不下了  
            if (inSampleSizeW > inSampleSizeH) {
                inSampleSize = inSampleSizeW;
            } else {
                inSampleSize = inSampleSizeH;
            }
            // 一定要记得将inJustDecodeBounds设为false,否则Bitmap为null  
            options.inJustDecodeBounds = false;
            // 设置缩放比例(采样率)  
            options.inSampleSize = inSampleSize;
            bitmap = BitmapFactory.decodeFile(path, options);
            boolean isSuccess = storeImage(bitmap, outPath);
            if (isSuccess) {
                return outPath;
            }
            return "";
        }
    

    这种方法是设置图片的采样率,降低图片像素,通过缩放图片像素来减少图片大小。

    那么我又是如何来获取图片压缩前后的大小的呢?
    注意:这里的图片的大小是指图片的实际大小,不是bitmap在内存中所占的大小,看压缩效果,就得看图片在文件中所占的大小。

    /**
         * 获取本地文件大小
         *
         * @param imgPath 图片的路径
         * @return 图片实际的大小,单位byte
         */
        public static int getFileSize(String imgPath) {
            int size = 0;
            try {
                FileInputStream fis = new FileInputStream(new File(imgPath));
                size = fis.available();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return size;
        }
    

    3、鲁班压缩(推荐)
    鲁班压缩是根据一种算法得出来的,压缩效果基本上和微信一致,差不多在200k以内,图片不失真。

    鲁班压缩

    build.gradle添加依赖

    compile 'top.zibin:Luban:1.1.3'
    
    private void lunBanPress(String path) {
            String pressPath = Environment.getExternalStorageDirectory().getPath();
            Luban.with(this)
                    .load(path)                                   // 传人要压缩的图片列表
                    .ignoreBy(100)                                  // 忽略不压缩图片的大小
                    .setTargetDir(pressPath)                        // 设置压缩后文件存储位置
                    .setCompressListener(new OnCompressListener() { //设置回调
                        @Override
                        public void onStart() {
                            // TODO 压缩开始前调用,可以在方法内启动 loading UI
                            Log.i(TAG, "onStart:开始鲁班压缩 ");
                        }
    
                        @Override
                        public void onSuccess(File file) {
                            // TODO 压缩成功后调用,返回压缩后的图片文件
                            Glide.with(activity).load(file).into(iv2);
                            Log.i(TAG, "onSuccess: 鲁班压缩成功 :");
                            try {
                                int size = new FileInputStream(file).available();
                                Log.i("tag", "鲁班压缩 size--->:" + "byte:" + size + "    kb:"
                                        + (float) size / 1024);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
    
                        @Override
                        public void onError(Throwable e) {
                            // TODO 当压缩过程出现问题时调用
                            Log.i(TAG, "onError: 鲁班压缩出错");
                        }
                    }).launch();    //启动压缩
        }
    

    相关文章

      网友评论

      本文标题:最完善,最有用的图片压缩教程

      本文链接:https://www.haomeiwen.com/subject/tytwsxtx.html