Android開源 - Luban(魯班)可能是最接近微信朋友圈的圖片壓縮算法

syicross 8年前發布 | 98K 次閱讀 Android Android開發 移動開發

前言

Luban 是圖片壓縮工具,通過參考或者自創壓縮規則推求極致的壓縮效果 目前的版本壓縮效果主要參考微信。因為微信用戶量最大,如果壓縮后的圖片越接近微信則越被用戶接受。

說明

目前的 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 傳入壓縮流程,壓縮圖片直到滿足以上數值

效果與對比

內容 原圖 Luban Wechat
截屏 720P 720*1280,390k 720*1280,87k 720*1280,56k
截屏 1080P 1080*1920,2.21M 1080*1920,104k 1080*1920,112k
拍照 13M(4:3) 3096*4128,3.12M 1548*2064,141k 1548*2064,147k
拍照 9.6M(16:9) 4128*2322,4.64M 1032*581,97k 1032*581,74k
滾動截屏 1080*6433,1.56M 1080*6433,351k 1080*6433,482k

導入

compile 'io.reactivex:rxandroid:1.2.1'
compile 'io.reactivex:rxjava:1.1.6'

compile 'top.zibin:Luban:1.0.5' </code></pre>

使用

Listener方式

Luban內部采用io線程進行圖片壓縮,外部調用只需設置好結果監聽即可

Luban.get(this)
    .load(File)                     //傳人要壓縮的圖片
    .putGear(Luban.THIRD_GEAR)      //設定壓縮檔次,默認三擋
    .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();    //啟動壓縮

</code></pre>

RxJava方式

RxJava 調用方式請自行隨意控制線程

Luban.get(this)
        .load(file)
        .putGear(Luban.THIRD_GEAR)
        .asObservable()
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .doOnError(new Action1<Throwable>() {
            @Override
            public void call(Throwable throwable) {
                throwable.printStackTrace();
            }
        })
        .onErrorResumeNext(new Func1<Throwable, Observable<? extends File>>() {
            @Override
            public Observable<? extends File> call(Throwable throwable) {
                return Observable.empty();
            }
        })
        .subscribe(new Action1<File>() {
            @Override
            public void call(File file) {
                //TODO 壓縮成功后調用,返回壓縮后的圖片文件
            }
        });

 

 

 本文由用戶 syicross 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!