精华内容
下载资源
问答
  • Android luban 压缩多图

    2018-07-27 17:49:37
    使用luban压缩,包括单图压缩和多图压缩的工具类
  • android使用luban压缩图片, 里面包含图片选择器的使用 compile 'me.iwf.photopicker:PhotoPicker:0.1.8'
  • Luban压缩源码学习

    千次阅读 2017-04-27 17:52:02
    Android-Luban压缩算法学习,源码解析。

    1.Android图片显示遇到的问题

    在Android应用中加载图片,是一个需要消耗内存的一个动作。也是Android开发者在项目优化中比较头疼的一个问题。

    先了解下加载图片如何消耗内存的

    图片质量 1px所占空间(1byte=8位) 1024*1024图片大小
    ALPHA_8只有透明度,没有颜色,那么一个像素点占8位。 1byte 1M
    RGB_565 即R=5,G=6,B=5,没有透明度,那么一个像素点占5+6+5=16位 2byte 2M
    ARGB_8888由4个8位组成,即A=8,R=8,G=8,B=8,那么一个像素点占8+8+8+8=32位 4byte 4M
    ARGB_4444由4个4位组成,即A=4,R=4,G=4,B=4,那么一个像素点占4+4+4+4=16位 2byte 2M



    而Android系统分配给单个应用的内存空间还是很有限的大致有16M,64M,128M等。如果一个应用加载大量高质量的图片的话就会导致一种情况出现——OOM(内存溢出)。

    所以为了避免这种情况出现,就要对图片进行压缩处理显示。

    对图片压缩处理就是进行裁切以及压缩,但是为了保证处理后的图片尽量达到跟原图效果一致,对图片裁切,压缩的一个度是如何控制呢。

    这里介绍下一个第三方开源库——Luabn(最接近微信朋友圈压缩图片算法)

    2.使用Luban压缩图片效果

    上面两图中的上部分图片是原图,下面部分是经过Luban压缩过后的图片

    效果:

    第一张原图4.55m 尺寸3456x4608。 压缩过后53k 尺寸1152x1536

    第二张原图1.16m 尺寸1080x1920。 压缩过后150k 尺寸360x640

    我们可以发现压缩后的图片在不放大的情况下,图片效果和原图一致,Luban的处理效果特别好。

    如何使用Luban压缩图片

    1.在项目中的build.gradle添加依赖(需要用到RxJava1.0)
    这里写图片描述

    2.在代码中使用Luban压缩方法

    1)Listerner方式。传入图片File,调用设置压缩监听setCompressListerner方法,处理压缩结果。
    这里写图片描述

    2)Rxjava方式,传入图片File,调用asObservable方法返回一个Observable观察者对象,使用RxJava方式来处理压缩结果。
    这里写图片描述

    项目地址

    3.Luban源码分析

    源码中最主要的方法就是thirdCompress(File file),即如何计算得出理想的压缩后宽高,以及图片大小。

    Luban压缩算法思路

    1. 判断图片比例值,是否处于以下区间内;
      • [1, 0.5625) 即图片处于 [1:1 ~ 9:16) 比例范围内
      • [0.5625, 0.5) 即图片处于 [9:16 ~ 1:2) 比例范围内
      • [0.5, 0) 即图片处于 [1:2 ~ 1:∞) 比例范围内
    2. 判断图片最长边是否过边界值;
      • [1, 0.5625) 边界值为:1664 * n(n=1), 4990 * n(n=2), 1280 * pow(2, n-1)(n≥3)
      • [0.5625, 0.5) 边界值为:1280 * pow(2, n-1)(n≥1)
      • [0.5, 0) 边界值为:1280 * pow(2, n-1)(n≥1)
    3. 计算压缩图片实际边长值,以第2步计算结果为准,超过某个边界值则:width / pow(2, n-1),height/pow(2, n-1)
    4. 计算压缩图片的实际文件大小,以第2、3步结果为准,图片比例越大则文件越大。
      size = (newW * newH) / (width * height) * m;
      • [1, 0.5625) 则 width & height 对应 1664,4990,1280 * n(n≥3),m 对应 150,300,300;
      • [0.5625, 0.5) 则 width = 1440,height = 2560, m = 200;
      • [0.5, 0) 则 width = 1280,height = 1280 / scale,m = 500;注:scale为比例值
    5. 判断第4步的size是否过小
      • [1, 0.5625) 则最小 size 对应 60,60,100
      • [0.5625, 0.5) 则最小 size 都为 100
      • [0.5, 0) 则最小 size 都为 100
    6. 将前面求到的值压缩图片 width, height, size 传入压缩流程,压缩图片直到满足以上数值

    源码:

    根据算法计算压缩后的宽高以及图片文件大小,在调用压缩方法compress,传入计算后的宽高以及图片大小

    开始进行压缩,这里分别执行了压缩图片大小compress方法,以及压缩图片质量saveImage方法
    这里写图片描述

    压缩图片至预期大小,配置BitmapFactory.Options中inSampleSize的值来压缩图片的宽高

    图片质量压缩
    这里写图片描述

    4.主要代码分析

    清楚了第三档压缩的实现之后,再了解使用Luban压缩时用到几个方法:

    get()、load(file)、putGear() 、setFileName()、setCompressListener()、launch()、asObservable()

    get(Context context)

    这里写图片描述

    这里写图片描述

    首先调用的是get(this),传入的是一个Context对象,调用私有的构造方法传入一个File对象创建一个Luban对象;File对象生成调用的是getPhotoCacheDir方法,来指定缓存目录。

    路径为:app包名/cache/luban_disk_cache/文件名

    这里写图片描述

    load(File file)

    public Luban load(File file) {
        mFile = file;
        return this;
    }

    这个方法比较容易理解,传入的是我们图片文件。

    putGear(int gear)

    public Luban putGear(int gear) {
            this.gear = gear;
            return this;
    }

    设置压缩等级,源码中只有两种等级:FIRST_GEAR 和 THIRD_GEAR,传入其他值无效。

        private static final int FIRST_GEAR = 1;
        public static final int THIRD_GEAR = 3;

    setFileName(String fileName)

    设置压缩后的图片名称

        public Luban setFilename(String filename) {
            this.filename = filename;
            return this;
        }

    setCompressListener(OnCompressListener listener)

    设置压缩监听 OnCompressListener是一个接口,里面有三个方法,对应三种状态

    public Luban setCompressListener(OnCompressListener listener) {
            compressListener = listener;
            return this;
    }
    public interface OnCompressListener {
    
        /**
         * Fired when the compression is started, override to handle in your own code
         * 压缩开始
         */
        void onStart();
    
        /**
         * Fired when a compression returns successfully, override to handle in your own code
         * 压缩成功
         */
        void onSuccess(File file);
    
        /**
         * Fired when a compression fails to complete, override to handle in your own code
         * 压缩失败
         */
        void onError(Throwable e);
    }

    lanuch()

    开始压缩,方法中使用的RxJava,根据设置的压缩等级来压缩图片


    asObservable()

    使用这个方法的话,采用的Rxjava方式返回一个观察者Observable。

        public Observable<File> asObservable() {
            if (gear == FIRST_GEAR)//判断压缩等级 
                return Observable.just(mFile).map(new Func1<File, File>() {
                    @Override
                    public File call(File file) {
                        return firstCompress(file); //调用第一档压缩方法
                    }
                });
            else if (gear == THIRD_GEAR)
                return Observable.just(mFile).map(new Func1<File, File>() {
                    @Override
                    public File call(File file) {
                        return thirdCompress(file);// 调用第三档压缩方法
                    }
                });
            else return Observable.empty();
        }
    

    Luban存在的不足

    1.不能很好的支持多图片压缩。(出现问题:多图压缩出现OOM)

    2.项目使用中必须添加RxJava依赖。(已在测试项目中剔除掉RxJava依赖 「链接」



    最后感谢作者 郑梓斌

    展开全文
  • 为了使自己的项目在需要使用图片的时候不出现oom,我们或多或少都会使用几个压缩图片的工具,这里就来介绍一个luban压缩工具。这是luban压缩工具的效果和微信压缩效果对比内容原图LubanWechat截屏 720P720*1280,390k...

    为了使自己的项目在需要使用图片的时候不出现oom,我们或多或少都会使用几个压缩图片的工具,这里就来介绍一个luban压缩工具。


    这是luban压缩工具的效果和微信压缩效果对比

    内容原图LubanWechat
    截屏 720P720*1280,390k720*1280,87k720*1280,56k
    截屏 1080P1080*1920,2.21M1080*1920,104k1080*1920,112k
    拍照 13M(4:3)3096*4128,3.12M1548*2064,141k1548*2064,147k
    拍照 9.6M(16:9)4128*2322,4.64M1032*581,97k1032*581,74k
    滚动截屏1080*6433,1.56M1080*6433,351k1080*6433,482k

    那么怎么使用这位大神的工具呐

    首先添加依赖

    implementation 'top.zibin:Luban:1.1.3'

    然后异步调用方式

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

    @Override
    public void onSuccess(File file) {
    // TODO 压缩成功后调用,返回压缩后的图片文件
    }

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


    同步调用

    Flowable.just(photos)
    .observeOn(Schedulers.io())
    .map(new Function<List<String>, List<File>>() {
    @Override public List<File> apply(@NonNull List<String> list) throws Exception {
    // 同步方法直接返回压缩后的文件
    return Luban.with(MainActivity.this).load(list).get();
    }
    })
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe();




    展开全文
  • LuBan压缩图片工具类

    2020-09-24 17:50:39
    1.导入依赖库 implementation 'top.zibin:Luban:1.1.8' 2.API29以上请在XML中的appliction下添加android:requestLegacyExternalStorage="true
  • luban压缩多图路径重复问题解决

    千次阅读 2017-05-26 15:25:46
    最近在自己的项目中添加了luban压缩,出现了压缩多图的时候返回路径重复的情况,去查看了github上的issues,发现有很多人出现了和我一样的情况,我苦恼了很久并没有解决,最终在一个大神小伙伴的帮助下完成了。...

    描述:luban作为目前网上非常流行的一款压缩图片的开源库,在github上也拥有接近5000star的收藏量。 它的使用方便是毋庸置疑的。

    最近在自己的项目中添加了luban压缩,出现了压缩多图的时候返回路径重复的情况,去查看了github上的issues,发现有很多人出现了和我一样的情况,我苦恼了很久并没有解决,最终在一个大神小伙伴的帮助下完成了。

    /**
         * 压缩多图
         *
         * @param pathList 传入的为图片原始路径
         */
        private void compressMore(final List<String> pathList){
            final LinkedList<Runnable> taskList = new LinkedList<>();
            final ArrayList<String> newList = new ArrayList<>();//压缩后的图片路径
            final Handler handler = new Handler();
            class  Task implements Runnable{
                String path;
                Task(String path){
                    this.path = path;
                }
                @Override
                public void run() {
                        Luban.get(context)
                                .load(new File(path))                     //传人要压缩的图片
                                .putGear(Luban.THIRD_GEAR)      //设定压缩档次,默认三挡
                                .setCompressListener(new OnCompressListener() { //设置回调
                                    @Override
                                    public void onStart() {
                                        AppManager.I().currentActivity().showDialog("加载中...");
                                    }
                                    @Override
                                    public void onSuccess(File file) {
                                        newList.add(file.getPath());
                                        if(!taskList.isEmpty()){
                                            Runnable runnable = taskList.pop();
                                            handler.post(runnable);
                                        }else {
                                            //完成之后的个人操作
                                            addPaths(newList);
                                             AppManager.I().currentActivity().dismissDialog();
                                        }
                                    }
    
                                    @Override
                                    public void onError(Throwable e) {
                                    }
                                }).launch();    //启动压缩
                    }
                }
                //循环遍历原始路径 添加至linklist中
            for (String path :pathList){
                taskList.add(new Task(path));
            }
            handler.post(taskList.pop());
        }



    以上仅为个人修改尝试,希望能够帮助一些遇到该情况的小伙伴。(我是一个小菜鸡)

    在此感谢帮助我的小伙伴 --> 土夜  嗯~ 就是这样 

    展开全文
  • implementation 'top.zibin:Luban:1.1.8' implementation 'com.github.tbruyelle:rxpermissions:0.10.2' public abstract class BasePhotoActivity extends BackActivity { private static final int REQUEST_...

     implementation 'top.zibin:Luban:1.1.8'

    implementation 'com.github.tbruyelle:rxpermissions:0.10.2'
    public abstract class BasePhotoActivity extends BackActivity {
        private static final int REQUEST_CODE_PICK_IMAGE = 3;
        private static final int MY_PERMISSIONS_REQUEST_CHOOSE_PHOTO = 7;
    
        /**
         * 从相册选取图片
         */
        protected void choosePhoto() {
            RxPermissions permissions = new RxPermissions(this);
            permissions
                    .request(Manifest.permission.CAMERA,
                            Manifest.permission.WRITE_EXTERNAL_STORAGE,
                            Manifest.permission.READ_EXTERNAL_STORAGE)
                    .subscribe(new Observer<Boolean>() {
                        @Override
                        public void onSubscribe(Disposable d) {
    
                        }
    
                        @Override
                        public void onNext(Boolean aBoolean) {
                            Intent intent = new Intent(Intent.ACTION_PICK);
                            intent.setType("image/*");//相片类型
                            startActivityForResult(intent, REQUEST_CODE_PICK_IMAGE);
                        }
    
                        @Override
                        public void onError(Throwable e) {
    
                        }
    
                        @Override
                        public void onComplete() {
    
                        }
                    });
    
    
        }
    
    
        public String getRealPathFromURI(Uri contentUri) {
            String res = null;
            String[] proj = {MediaStore.Images.Media.DATA};
            Cursor cursor = mContext.getContentResolver().query(contentUri, proj, null, null, null);
            if (cursor.moveToFirst()) {
                int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                res = cursor.getString(column_index);
            }
            cursor.close();
            return res;
        }
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            switch (requestCode) {
                case REQUEST_CODE_PICK_IMAGE:
                    if (resultCode == Activity.RESULT_OK) {
                        try {
                            Uri uri = data.getData();
                            String realPath = getRealPathFromURI(uri);
                            dealWithZipImg(realPath);
                        } catch (Exception e) {
                            e.printStackTrace();
                            Log.d(Constants.TAG, e.getMessage());
                        }
                    } else {
                        Log.d(Constants.TAG, "失败");
                    }
                    break;
            }
        }
    
    
        /**
         * 图片路径
         */
        protected void dealWithZipImg(String realPath) {
            Luban.with(this)
                    .load(realPath)
                    .ignoreBy(1024)
                    .filter(new CompressionPredicate() {
                        @Override
                        public boolean apply(String path) {
                            return !(TextUtils.isEmpty(path) || path.toLowerCase().endsWith(".gif"));
                        }
                    })
                    .setCompressListener(new OnCompressListener() {
                        @Override
                        public void onStart() {
    
                        }
    
                        @Override
                        public void onSuccess(File file) {
                            imagePath(realPath, file.getPath());
                        }
    
                        @Override
                        public void onError(Throwable e) {
    
                        }
                    }).launch();
    
        }
    
    
        /**
         * 压缩之后的图片路径
         *
         * @param srcPath 压缩之前的图片路径
         * @param zipPath 压缩之后的图片路径
         */
        public abstract void imagePath(String srcPath, String zipPath);
    
    
    }
    

    注意:Luban.load(Uri)压缩后为空

    展开全文
  • Luban压缩源码深入学习

    千次阅读 2019-05-17 16:24:17
    很久以前对于图片的压缩一直就使用Luban这个第三方库,主要是它提供的api比较方便,支持同步和异步压缩,也可以同时压缩多张图片,比较好用,效果也比较好。它的内部会根据图片的宽高比例,选择一个合适的压缩算法,...
  • 前言:在安卓开发中,图片压缩是常用的一个...Luban —— Android图片压缩框架,主要是仿微信朋友圈压缩策略 框架的github链接:https://github.com/Curzibn/Luban 接下来来介绍如何使用: 导入 compile 'top....
  • luban压缩library地址:https://github.com/Curzibn/Luban 我使用的是这个版本 implementation 'top.zibin:Luban:1.1.5' 使用方法如下: private <T> void withLs(final List<String> pics) { ...
  • 鲁班压缩图片Android Studio开发版,需要java1.8
  • Flutter实现Luban图片压缩库算法

    千次阅读 2019-01-25 07:34:32
    本项目是基于image库使用纯dart代码实现的Luban压缩算法,压缩效果个人感觉还可以,目前只能算是beta版本,欢迎大家去github下载示例体验 后续需要优化的问题 1、只支持jpg格式 2、压缩时间有待优化 3、压缩过程中...
  • 1,LuBan压缩问题 https://github.com/Curzibn/Luban 之前选择压缩图片库,在github上找的这个star最多的,使用方法是传入图片数组,在异步线程中回调返回的结果。接下来就出现问题了,压缩的图片质量模糊,虽然...

空空如也

空空如也

1 2 3 4 5 ... 13
收藏数 247
精华内容 98
关键字:

luban压缩