Android 圖片壓縮之魯班Luban詳解

Android客戶端獲取相冊圖片多張一起上傳服務器時,如果不進行圖片處理,可能會導致內存泄漏問題。這時圖片壓縮就至關重要了。但是又不能影響圖片的清晰度。

 

 

壓縮方式1: 設置圖片格式

 

Android目前常用的圖片格式有png,jpeg和webp。


png:無損壓縮圖片格式,支持Alpha通道,Android切圖素材多采用此格式。


jpeg:有損壓縮圖片格式,不支持背景透明,適用於照片等色彩豐富的大圖壓縮,不適合logo。


webp:是一種同時提供了有損壓縮和無損壓縮的圖片格式,派生自視頻編碼格式VP8,從谷歌官網來看,無損webp平均比png小26%,有損的webp平均比jpeg小25%~34%,無損webp支持Alpha通道,有損webp在一定的條件下同樣支持,有損webp在Android4.0(API 14)之後支持,無損和透明在Android4.3(API18)之後支持。


採用webp能夠在保持圖片清晰度的情況下,可以有效減小圖片所佔有的磁盤空間大小。

 

 

 

壓縮方式2:質量壓縮

 

質量壓縮並不會改變圖片在內存中的大小,僅僅會減小圖片所佔用的磁盤空間的大小,因爲質量壓縮不會改變圖片的分辨率,而圖片在內存中的大小是根據width*height*一個像素的所佔用的字節數計算的,寬高沒變,在內存中佔用的大小自然不會變,質量壓縮的原理是通過改變圖片的位深和透明度來減小圖片佔用的磁盤空間大小,所以不適合作爲縮略圖,可以用於想保持圖片質量的同時減小圖片所佔用的磁盤空間大小。另外,由於png是無損壓縮,所以設置quality無效,以下是實現方式:

 

//format:圖片格式 jpeg,png,webp quality 圖片的質量,0-100,數值越小質量越差
public boolean compress(CompressFormat format, int quality, OutputStream stream) {
        checkRecycled("Can't compress a recycled bitmap");
        // do explicit check before calling the native method
        if (stream == null) {
            throw new NullPointerException();
        }
        if (quality < 0 || quality > 100) {
            throw new IllegalArgumentException("quality must be 0..100");
        }
        StrictMode.noteSlowCall("Compression of a bitmap is slow");
        Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "Bitmap.compress");
        boolean result = nativeCompress(mNativePtr, format.nativeInt,
                quality, stream, new byte[WORKING_COMPRESS_STORAGE]);
        Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
        return result;
    }
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);

 

 

壓縮方式3:LuBan壓縮

 

1.效果與對比

 

 

2.添加依賴

implementation project(':library')

 

3.壓縮

private void lubanMethod(File file){
        Luban.with(this)//上下文對象
                .load(file)//原圖路徑
                .ignoreBy(100)//不壓縮的閾值 單位爲K 即圖片小於此閾值時不壓縮
                .setFocusAlpha(false)//設置是否保留透明通道
                .setTargetDir(setLuBanPath())//設置緩存壓縮圖片路徑
                .filter(new CompressionPredicate() {
                    @Override
                    public boolean apply(String path) {
                        return !(TextUtils.isEmpty(path));//圖片路徑不爲空 返回true壓縮
                    }
                })//設置開啓壓縮條件
                .setCompressListener(new OnCompressListener() {
                    @Override
                    public void onStart() {

                    }

                    @Override
                    public void onSuccess(File file) {
                        addthumbArg(file);
                        Log.d("TAG","壓縮成功後的路徑:"+file.getAbsolutePath());
                    }

                    @Override
                    public void onError(Throwable e) {

                    }
                })//壓縮回調接口
                .setRenameListener(new OnRenameListener() {
                    @Override
                    public String rename(String filePath) {
                        String result=savenum+".jpg";
                        savenum++;
                        return result;
                    }
                })//壓縮前重命名接口
                .launch();//壓縮
    }

 

 

4.效果

 

壓縮前

 

 

壓縮後

 

 

5.原文鏈接:https://github.com/Curzibn/Luban

 

 

6.代碼詳情:https://github.com/wujianning/LuBanDemo

 

 

7.算法:

 

1.前言

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

 

 

2.說明

目前的Luban只是壓縮結果接近微信,自身的算法只是爲了達到這個效果而設計的。與微信並無任何聯繫,也不敢妄稱是微信的算法。

 

 

3.算法步驟

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

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章