Android開源 - Luban(魯班)可能是最接近微信朋友圈的圖片壓縮算法
前言
Luban 是圖片壓縮工具,通過參考或者自創壓縮規則推求極致的壓縮效果 目前的版本壓縮效果主要參考微信。因為微信用戶量最大,如果壓縮后的圖片越接近微信則越被用戶接受。
說明
目前的 Luban 只是壓縮結果接近微信,自身的算法只是為了達到這個效果而設計的。與微信并無任何聯系,也不敢妄稱是微信的算法。
算法步驟
注:下文所說“比例”統一表示:圖片短邊除以長邊為該圖片比例
第三擋壓縮(參考最新版微信壓縮效果)
-
判斷圖片比例值,是否處于以下區間內;
- [1, 0.5625) 即圖片處于 [1:1 ~ 9:16) 比例范圍內
- [0.5625, 0.5) 即圖片處于 [9:16 ~ 1:2) 比例范圍內
- [0.5, 0) 即圖片處于 [1:2 ~ 1:∞) 比例范圍內
-
判斷圖片最長邊是否過邊界值;
- [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)
-
計算壓縮圖片實際邊長值,以第2步計算結果為準,超過某個邊界值則:width / pow(2, n-1),height/pow(2, n-1)
-
計算壓縮圖片的實際文件大小,以第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為比例值
-
判斷第4步的size是否過小
- [1, 0.5625) 則最小 size 對應 60,60,100
- [0.5625, 0.5) 則最小 size 都為 100
- [0.5, 0) 則最小 size 都為 100
- 將前面求到的值壓縮圖片 width, height, size 傳入壓縮流程,壓縮圖片直到滿足以上數值
效果與對比
內容 | 原圖 | Luban | |
---|---|---|---|
截屏 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 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!