1. 程式人生 > 其它 >android sd卡列目錄檔案_android程式設計師高效壓縮圖片(libjpeg)幾種方案

android sd卡列目錄檔案_android程式設計師高效壓縮圖片(libjpeg)幾種方案

技術標籤:android sd卡列目錄檔案

用過ios手機的同學應該很明顯感覺到,ios拍照1M的圖片要比安卓拍照排出來的5M的圖片還要清晰。這是為什麼呢?

這得了解android底層是如何對圖片進行處理的

當時谷歌開發Android的時候,考慮了大部分手機的配置並沒有那麼高,所以對圖片處理是使用的Skia這個開源庫。當然這個庫的底層還是是用的jpeg對圖片進行壓縮處理。但是為了能夠適配低端的手機(這裡的低端是指以前的硬體配置不高的手機,CPU和記憶體在手機上都非常吃緊 效能差),由於哈夫曼演算法非常吃CPU,被迫用了其他的演算法。所以Skia在進行圖片處理並沒有去使用壓縮影象過程中基於影象資料計算哈弗曼表(關於圖片壓縮中的哈弗曼表,請自行查閱相關資料),但是解碼還是保留了哈夫曼演算法。這就導致了圖片處理後文件變大了。

我們使用微信發圖片的時候,會發現發出去的圖片明顯比原圖小很大,但是效果好像差不多,那又是為什麼呢,經過了怎樣的壓縮呢,其實他們是用了哈夫曼演算法進行圖片壓縮;接下來我們就用這演算法進行圖片壓縮:

仿微信終級壓縮

1.下載JPEG引擎使用的庫---libjpeg庫

libjpeg是一個被廣泛使用的JPEG解碼、JPEG編碼和其他的JPEG功能的實現庫.說它使用廣泛,是因為它跨了很多平臺。比如Linux平臺、JDK、Android和其他庫如tess-two等等。libjpeg庫下載地址;

2.編譯android中libjpeg庫使用庫

編譯android中libjpeg庫使用庫,這裡我暫時先不做詳細的請解,後期我會做一個ndk開發專題進行詳細請解,編譯後生成的libjpegbither.so和.h標頭檔案,看如下圖:

fb55ec6a17327c3581911f76481e8037.png

3.匯入libjpeg庫libjpegbither.so及標頭檔案

在專案資料夾新建jni資料夾,把剛才生成的libjpegbither.so及標頭檔案放在此資料夾下;

4.新建BitmapCompressUtils

  • 寫一個native方法,呼叫c方法
 /** * 呼叫底層 bitherlibjni.c中的方法 * * @param bit * @param w * @param h * @param quality * @param fileNameBytes * @param optimize * @return * @Description:函式描述 */public static native String compressBitmap(Bitmap bit, int w, int h, int quality, byte[] fileNameBytes, boolean optimize);
  • 引入庫lib下二個so檔案
 /** * 載入lib下兩個so檔案 */static { System.loadLibrary("jpegbither"); System.loadLibrary("bitherjni");}
  • 寫一個方法,呼叫native方法,便於java層呼叫
 /** * @param image bitmap物件 * @param filePath 要儲存的指定目錄 * @Description: 通過JNI圖片壓縮把Bitmap儲存到指定目錄 */public static void compressBitmap(Bitmap image, String filePath) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 質量壓縮方法,這裡100表示不壓縮,把壓縮後的資料存放到baos中 int options = 20; // JNI呼叫儲存圖片到SD卡 這個關鍵 NativeUtil.saveBitmap(image, options, filePath, true);}

4.編寫bitherjni.cpp

#include "bitherlibjni.h"#include #include #include #include #include #include #include #include //統一編譯方式extern "C" {#include "jpeg/jpeglib.h"#include "jpeg/cdjpeg.h" /* Common decls for cjpeg/djpeg applications */#include "jpeg/jversion.h" /* for version message */#include "jpeg/android/config.h"}#define LOG_TAG "jni"#define LOGW(...) __android_log_write(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)#define true 1#define false 0typedef uint8_t BYTE;char *error;struct my_error_mgr { struct jpeg_error_mgr pub; jmp_buf setjmp_buffer;};typedef struct my_error_mgr * my_error_ptr;METHODDEF(void)my_error_exit (j_common_ptr cinfo){ my_error_ptr myerr = (my_error_ptr) cinfo->err; (*cinfo->err->output_message) (cinfo); error=(char*)myerr->pub.jpeg_message_table[myerr- >pub.msg_code]; LOGE("jpeg_message_table[%d]:%s