【Android 內存優化】Android 原生 API 圖片壓縮原理 ( 哈夫曼編碼開關 | 哈夫曼編碼原理 | libjpeg-turbo 函數庫 )



【Android 內存優化】圖片文件壓縮 ( Android 原生 API 提供的圖片壓縮功能能 | 圖片質量壓縮 | 圖片尺寸壓縮 ) 簡要介紹了 圖片文件壓縮格式 , 以及 Android 提供的圖片質量 , 尺寸壓縮原生 API ;


【Android 內存優化】Android 原生 API 圖片壓縮代碼示例 ( PNG 格式壓縮 | JPEG 格式壓縮 | WEBP 格式壓縮 | 動態權限申請 | Android10 存儲策略 ) 主要使用了上述 Android 原生 API 壓縮圖片功能進行圖片壓縮 ;


【Android 內存優化】Android 原生 API 圖片壓縮原理 ( 圖片質量壓縮方法 | 查找 Java 源碼中的 native 方法對應的 C++ 源碼 ) 中主要查找 Bitmap.java 對應的 Native 層的 C++ 類 Bitmap.cpp 源碼文件 , 並分析了其動態註冊 Native 方法的過程 ;


【Android 內存優化】Android 原生 API 圖片壓縮原理 ( Bitmap_compress 方法解析 | Skia 二維圖形庫 | libjpeg 函數庫 | libpng 函數庫 ) 博客中分析了 Bitmap.cpp 中的 Bitmap_compress 方法 ;






一、 哈夫曼編碼開關



上一篇博客 【Android 內存優化】Android 原生 API 圖片壓縮原理 ( Bitmap_compress 方法解析 | Skia 二維圖形庫 | libjpeg 函數庫 | libpng 函數庫 ) 分析到了 實際的圖片壓縮方法是由 Skia 圖形庫執行的 , Skia 圖形庫根據不同的壓縮格式 , 選擇不同的函數庫進行壓縮 , 如果壓縮格式是 JPEG 格式 , 那麼使用 libjpeg 庫進行圖片壓縮 , 如果壓縮格式是 PNG 庫 , 那麼使用 libpng 庫進行壓縮 ;


1. 哈夫曼編碼 : 在 libjpeg 中提供了圖片哈夫曼編碼功能 , 該功能非常消耗 CPU 性能 , 因此早期的 Android 版本禁用了該功能 , 在 7.0 之後的版本 , 此時 Android 設備上的 CPU 性能很高 , 這時纔將哈夫曼編碼功能打開 ; ( SkImageDecoder_libjpeg.cpp 代碼參考 )


2. 打開哈夫曼編碼 : 將 jpeg_compress_struct 結構體的 optimize_coding 成員設置成 TRUE ; 作用是 通知 libjpeg-turbo 爲圖像計算最佳的哈夫曼編碼表 , 該操作可以 提高圖片壓縮比例 , 代價是編碼速度較慢 ;


3. 源碼參考 :

SkImageDecoder_libjpeg.cppSkJPEGImageEncoder 類 ( SkImageEncoder 對應的 JPEG 格式圖片壓縮實現類 ) 中的 onEncode 方法 , 在 7.0 以後的版本 , 打開圖片壓縮哈夫曼編碼功能 ;

// 該類是 SkImageEncoder 的子類 , 在 Bitmap.cpp 中使用的就是
class SkJPEGImageEncoder : public SkImageEncoder {
protected:
    virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) {
		// ... 
		jpeg_compress_struct    cinfo;
		// ... 
        // 打開哈夫曼編碼 
        // 通知 libjpeg-turbo 爲圖像計算最佳的哈夫曼編碼表
        // 該功能可以提高壓縮比例 , 代價是編碼速度較慢
        cinfo.optimize_coding = TRUE;
        // ... 
        return true;
    }
};

源碼位置 7.0.0/external/skia/src/images/SkImageDecoder_libjpeg.cpp ( 7.0.0 以後的源碼才添加了上述功能 )





二、 哈夫曼編碼原理



在 libjpeg 編碼中 , 如果沒有開啓哈夫曼編碼 , 採用的是定長的編碼方式 , 如果打開了哈夫曼編碼 , 採用的就是變長哈夫曼編碼 , 可以大幅度壓縮數據大小 ;


簡介 : 哈夫曼編碼是字符編碼 , 適用於數據文件壓縮場景 , 能大幅度壓縮文件大小 ;


哈夫曼編碼原理 : 每個數據的編碼長度可變 , 文件中出現較多的字符使用短編碼 , 出現較少的字符使用長編碼 , 另外額外維護一張哈夫曼編碼表 , 用於維護字符與編碼的對應關係 , 總體的文件大小會降低 20% 至 90% ;





三、 libjpeg-turbo 函數庫



使用哈夫曼編碼進行圖片壓縮 , 能最大幅度壓縮圖片大小 , 但是 Android 原生編碼中只有 7.0 以後的系統纔打開了哈夫曼編碼功能 , 目前的主流應用都要向下兼容到 android-17 平臺版本 , 對應的系統版本是 Android 4.2 Jelly Bean , 這裏就需要引入第三方庫 libjpeg-turbo 函數庫 , 進行哈夫曼編碼圖片壓縮 , 該函數庫是由 C 語言開發 , 需要在 Ubuntu 中進行交叉編譯成 ARM 架構的函數庫 ( 動態庫 / 靜態庫 ) , 然後導入到 Android Studio 中使用 ;


Android 源碼中有 libjpeg-turbo 庫 , 但是Java 框架中提供的 Bitmap.java 只能調用 Bitmap.cpp 中的代碼 , Bitmap.cpp 中通過 Skia 2D 圖形庫調用 libjpeg 庫 , 在該 C++ 代碼中是固定的 , 開發者無法修改框架層的源碼 , 因此該函數庫無法被開發者調用到 ;


NDK 交叉編譯開發參考 : Android NDK 開發 專欄





四、 libjpeg-turbo 函數庫下載



1. libjpeg-turbo 相關資源鏈接 :


① libjpeg-turbo 官方網站 : https://libjpeg-turbo.org/

② GitHub 地址 : libjpeg-turbo/libjpeg-turbo

③ libjpeg-turbo 文檔 : 文檔地址



2. 下載發佈版本 :


在 Android 工程中使用該函數庫 , 儘量下載發佈的穩定版本 , 最好不要直接下載開發中的 DEBUG 版本 , 可能存在 BUG ;

如下圖 , 找到 release 發佈版本界面 , 下載最新的發佈版本 ; 或者直接點擊 libjpeg-turbo/libjpeg-turbo 項目的 Release 發佈版本地址 進入該界面 ;

在這裏插入圖片描述


進入 Release 界面後 , 查看到目前最新的發佈版本是 2.0.5 版本 , 直接下載該源碼 ; 之後需要到 Ubuntu 中進行交叉編譯 ;

在這裏插入圖片描述


下載這個 Source code (tar.gz) 源碼 , 到 Ubuntu 中進行交叉編譯 ; ( 也可以直接點擊上述連接下載 )

在這裏插入圖片描述

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