1. 程式人生 > >Android中圖片優化之WebP使用

Android中圖片優化之WebP使用

一、什麼是 WebP?

WebP(發音 weppy,專案主頁),是一種支援有失真壓縮和無失真壓縮的圖片檔案格式,派生自影象編碼格式 VP8。根據 Google 的測試,無失真壓縮後的 WebP 比 PNG 檔案少了 45% 的檔案大小,即使這些 PNG 檔案經過其他壓縮工具壓縮之後,WebP 還是可以減少 28%的檔案大小。

二、當下Android圖片優化之WebP的必然選擇

對於一個好的APP,當然是越小越好,然而,在APP中圖片就佔據了很大的一部分體積,所以圖片的優化是開發人員必須要做的事情,而原有圖片的png、jpeg、GIF等格式的優化已經達到了極致,所以只得另尋出路,因此有了WebP。由於WebP的特性,如果把WebP運用到APP中將會使我們的APP體積大小得到很大程度的縮小,APP也會得到一個質的變化,所以,WebP在APP中的使用將是目前我們圖片優化的不二選擇。

三、WebP的轉換 

 WebP的轉換:WebP與其他常用的圖片格式之間是可以相互轉換的,webp轉換工具有:XnConvet,智圖,ISparta.

四、WebP的相容性

 WebP的相容性:4.2.1+ 對於webp的decode、encode是完全支援的(包含半透明的webp圖)對於4.0+ 到 4.2.1 ,只支援完全不透明的decode、encode的webp圖,4.0 以下,應該是預設不支援webp的(編碼解碼)。

五、Android下WebP的使用

想在APP中使用WebP,首先我們就得解決它的相容性問題。步驟如下:

1、新增webp

的支援,載入so檔案,新增libwebp.jia包

(1)獲取so檔案和libwebp.jia包:可以從https://github.com/EverythingMe/webp-android下載解析庫,然後ndk-build得到so檔案。同時也能在解析庫裡面得到libwebp.jia包。

    (2)得到so檔案和libwebp.jia後拷到專案的app的libs目錄下


     (3在appbuild新增依賴

 

 

新增成功後在app目錄下會生成這樣的一個檔案


自此 so檔案新增依賴成功。

2、第二步,新增WebpUtils檔案,裡面有通過so包來處理webp檔案成為byte陣列的方法。

我們可以通過以下方法來解決相容性問題(4.2.1以下版本也可以顯示webp格式圖片,包括半透明圖片)。

 

關鍵程式碼:

public class WebPDecoder {
    private static WebPDecoder instance = null;

    private WebPDecoder() {
        System.loadLibrary("webp_evme");
    }

    public static WebPDecoder getInstance() {
        if (instance==null) {
            synchronized (WebPDecoder.class) {
                if (instance==null) {
                    instance = new WebPDecoder();
                }
            }
        }

        return instance;
    }

    public BitmapdecodeWebP(byte[] encoded) {
        return decodeWebP(encoded,0,0);
    }

    public BitmapwebpToBitmap(InputStream is) {
        Bitmap bitmap = null;
        if (Build.VERSION.SDK_INT< Build.VERSION_CODES.JELLY_BEAN_MR1) {
            bitmap = WebPDecoder.getInstance().decodeWebP(streamToBytes(is));
        } else {
            bitmap = BitmapFactory.decodeStream(is);
        }
        return bitmap;
    }

    private static byte[] streamToBytes(InputStream is) {
        ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
        byte[]buffer = new byte[1024];
        int len;
        try {
            while ((len= is.read(buffer)) >=0) {
                os.write(buffer, 0, len);
            }
        } catch (java.io.IOExceptione) {
        }
        return os.toByteArray();
    }

 

3、專案裡在需要的地方直接呼叫


final ImageView imageView = (ImageView) findViewById(R.id.imageView);
try {
    imageView.setImageBitmap(WebPDecoder.getInstance().webpToBitmap(getAssets().open("aa.webp")));
} catch (IOException e) {
    e.printStackTrace();
}