【Android 内存优化】Android 原生 API 图片压缩原理 ( 图片质量压缩方法 | 查找 Java 源码中的 native 方法对应的 C++ 源码 )
文章目錄
- 一、 圖片質量壓縮方法
- 二、 查找對應的 Native 方法源碼
- 三、 分析 Bitmap.cpp 中動態注冊 Native 方法
在博客 【Android 內存優化】圖片文件壓縮 ( Android 原生 API 提供的圖片壓縮功能能 | 圖片質量壓縮 | 圖片尺寸壓縮 ) 簡要介紹了 圖片文件壓縮格式 , 以及 Android 提供的圖片質量 , 尺寸壓縮原生 API ;
在博客 【Android 內存優化】Android 原生 API 圖片壓縮代碼示例 ( PNG 格式壓縮 | JPEG 格式壓縮 | WEBP 格式壓縮 | 動態權限申請 | Android10 存儲策略 ) 主要使用了上述 Android 原生 API 壓縮圖片功能進行圖片壓縮 ;
本博客中將分析 Android 底層源碼 , 具體分析圖片壓縮的原理 ;
先找到源碼位置 ;
一、 圖片質量壓縮方法
在 【Android 內存優化】圖片文件壓縮 ( Android 原生 API 提供的圖片壓縮功能能 | 圖片質量壓縮 | 圖片尺寸壓縮 ) 三、 Android 原生 API 提供的質量壓縮 章節對圖片質量壓縮方法中的代碼進行了簡要介紹 , 最終調用的方法是 nativeCompress 方法 , 執行實際的圖片壓縮邏輯 ;
// 執行 Native 方法, 壓縮圖片 boolean result = nativeCompress(mNativePtr, format.nativeInt,quality, stream, new byte[WORKING_COMPRESS_STORAGE]);調用的 native 方法 : 查找其在 C++ 代碼的對應函數 , 該 Native 函數定義在 Bitmap.cpp 中 ;
private static native boolean nativeCompress(long nativeBitmap, int format,int quality, OutputStream stream,byte[] tempStorage);源碼位置 frameworks\base\graphics\java\android\graphics\Bitmap.java , 也可以直接在開發環境中查看該源碼 ;
下面開始查找 nativeCompress 方法 , 分析其中的代碼 ;
二、 查找對應的 Native 方法源碼
1. Native 方法源碼查找方法 :
① 文件名相同 : 一般情況下 Java 源碼中的 Java 類的類名與對應的定義 Native 方法的 C++ 源碼文件名稱相同 ;
② 源碼搜索 : 如果找不到 , 還是在 Source Insight 中查找對應的 native 方法 , 即可找到對應的 C++ 源碼 ; 參考 【Android 系統開發】使用 Source InSight 閱讀 Android 源碼 博客 ;
上圖是在 Source Insight 中查找 nativeCompress 關鍵字 , 就可以找到對應的 Bitmap.cpp 源碼 ;
2 . 對應構建腳本分析 : 在 Android 源碼的 frameworks\base\core\jni 目錄下 , 定義了 Bitmap.cpp 編譯成動態庫的構建腳本 Android.mk , 該構建腳本配置編譯了 libandroid_runtime 動態庫 , 其中就包含了 Bitmap.cpp , Bitmap.java 中定義的 native 方法的具體實現就在該 frameworks\base\core\jni\android\graphics\Bitmap.cpp 中 ;
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS)# ... LOCAL_SRC_FILES:= \# ... android/graphics/Bitmap.cpp \android/graphics/BitmapFactory.cpp \# ...LOCAL_C_INCLUDES += \$(JNI_H_INCLUDE) \# ... LOCAL_SHARED_LIBRARIES := \libmemtrack # ...LOCAL_MODULE:= libandroid_runtimeinclude external/stlport/libstlport.mk include $(BUILD_SHARED_LIBRARY)include $(call all-makefiles-under,$(LOCAL_PATH))該構建腳本的源碼位置 \frameworks\base\core\jni\Android.mk
三、 分析 Bitmap.cpp 中動態注冊 Native 方法
參考博客 【Android NDK 開發】JNI 動態注冊 ( 動態注冊流程 | JNI_OnLoad 方法 | JNINativeMethod 結構體 | GetEnv | RegisterNatives ) 內容 , 在該博客中詳細介紹了動態注冊的詳細細節 ;
Bitmap.java 中的 nativeCompress 方法 使用的是動態注冊的方式 與 Bitmap.cpp 中的 Bitmap_compress 方法對應 ;
1. 動態注冊流程 :
① 定義 JNINativeMethod 結構體 : 首先定義了 JNINativeMethod 結構體 , 該結構體由三個成員 , Java 函數名 , java 函數簽名 , C++ 函數簽名 ;
typedef struct {const char* name; //Java 中定義的 Native 方法名 , 注意這是一個 C 字符串const char* signature; //函數簽名 , 可以使用 javap 生成void* fnPtr; //C/C++ 中的 Native 函數簽名} JNINativeMethod;② 獲取 Java 類 : 獲取要注冊的 Java 類名稱 ;
③ 批量注冊 : 最終要調用 JNIEnv 的 RegisterNatives 方法 , 批量注冊代碼 ; 下面代碼中的 android::AndroidRuntime::registerNativeMethods 方法定義在 frameworks\base\core\jni\AndroidRuntime.cpp 中 , 在該方法中又調用了 libnativehelper\JNIHelp.cpp 中的 jniRegisterNativeMethods 方法 , 在該方法中調用了 JNIEnv 的 RegisterNatives 方法注冊了這一批 Bitmap.java 的函數 ;
2. Bitmap.cpp 中完整動態注冊代碼 : 其中對關鍵代碼進行了注釋 ;
// 調用的 register_android_graphics_Bitmap 注冊函數方法定義在該頭文件中 #include <android_runtime/AndroidRuntime.h>// 定義了 JNINativeMethod 結構體數組 static JNINativeMethod gBitmapMethods[] = {{ "nativeCreate", "([IIIIIIZ)Landroid/graphics/Bitmap;",(void*)Bitmap_creator },{ "nativeCopy", "(JIZ)Landroid/graphics/Bitmap;",(void*)Bitmap_copy },{ "nativeDestructor", "(J)V", (void*)Bitmap_destructor },{ "nativeRecycle", "(J)Z", (void*)Bitmap_recycle },{ "nativeReconfigure", "(JIIIIZ)V", (void*)Bitmap_reconfigure },// nativeCompress 圖片壓縮方法// Java 中的方法名是 nativeCompress // Java 中的方法簽名 (JIILjava/io/OutputStream;[B)Z// C++ 中的方法簽名 (void*)Bitmap_compress{ "nativeCompress", "(JIILjava/io/OutputStream;[B)Z",(void*)Bitmap_compress },{ "nativeErase", "(JI)V", (void*)Bitmap_erase },{ "nativeRowBytes", "(J)I", (void*)Bitmap_rowBytes },{ "nativeConfig", "(J)I", (void*)Bitmap_config },{ "nativeHasAlpha", "(J)Z", (void*)Bitmap_hasAlpha },{ "nativeIsPremultiplied", "(J)Z", (void*)Bitmap_isPremultiplied},{ "nativeSetHasAlpha", "(JZZ)V", (void*)Bitmap_setHasAlpha},{ "nativeSetPremultiplied", "(JZ)V", (void*)Bitmap_setPremultiplied},{ "nativeHasMipMap", "(J)Z", (void*)Bitmap_hasMipMap },{ "nativeSetHasMipMap", "(JZ)V", (void*)Bitmap_setHasMipMap },{ "nativeCreateFromParcel","(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",(void*)Bitmap_createFromParcel },{ "nativeWriteToParcel", "(JZILandroid/os/Parcel;)Z",(void*)Bitmap_writeToParcel },{ "nativeExtractAlpha", "(JJ[I)Landroid/graphics/Bitmap;",(void*)Bitmap_extractAlpha },{ "nativeGenerationId", "(J)I", (void*)Bitmap_getGenerationId },{ "nativeGetPixel", "(JII)I", (void*)Bitmap_getPixel },{ "nativeGetPixels", "(J[IIIIIII)V", (void*)Bitmap_getPixels },{ "nativeSetPixel", "(JIII)V", (void*)Bitmap_setPixel },{ "nativeSetPixels", "(J[IIIIIII)V", (void*)Bitmap_setPixels },{ "nativeCopyPixelsToBuffer", "(JLjava/nio/Buffer;)V",(void*)Bitmap_copyPixelsToBuffer },{ "nativeCopyPixelsFromBuffer", "(JLjava/nio/Buffer;)V",(void*)Bitmap_copyPixelsFromBuffer },{ "nativeSameAs", "(JJ)Z", (void*)Bitmap_sameAs },{ "nativePrepareToDraw", "(J)V", (void*)Bitmap_prepareToDraw }, };#define kClassPathName "android/graphics/Bitmap"// 動態注冊函數的實際方法 int register_android_graphics_Bitmap(JNIEnv* env) {// 該方法最終調用了 libnativehelper\JNIHelp.cpp 中的 jniRegisterNativeMethods 方法return android::AndroidRuntime::registerNativeMethods(env, kClassPathName,gBitmapMethods, SK_ARRAY_COUNT(gBitmapMethods)); }源碼位置 \frameworks\base\core\jni\android\graphics\Bitmap.cpp
總結
以上是生活随笔為你收集整理的【Android 内存优化】Android 原生 API 图片压缩原理 ( 图片质量压缩方法 | 查找 Java 源码中的 native 方法对应的 C++ 源码 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Android 内存优化】Androi
- 下一篇: 【Android 内存优化】Androi