NDK開發(八) :JNI下Bitmap的使用

轉載請以連接形式標明出處: 本文出自:103style的博客java

本文操做以 Android Studio 3.4.2 版本爲例android


NDK開發文章彙總git


目錄

  • NDK 中的 Bitmap
  • 編寫測試代碼
  • 實現JNI下Bitmap使用的邏輯
  • 執行測試代碼

NDK 中的 Bitmap

NDK 已經爲咱們準備好了操做 Bitmap 的相關頭文件了,它就是 <android/bitmap.h>github

  • 像素格式bash

    enum AndroidBitmapFormat {
        ANDROID_BITMAP_FORMAT_NONE      = 0,
        ANDROID_BITMAP_FORMAT_RGBA_8888 = 1,
        ANDROID_BITMAP_FORMAT_RGB_565   = 4,
        ANDROID_BITMAP_FORMAT_RGBA_4444 = 7,
        ANDROID_BITMAP_FORMAT_A_8       = 8,
    };
    複製代碼
  • Bitmap結構體,經過AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap, AndroidBitmapInfo* info)獲取。app

    typedef struct {
        //像素寬度
        uint32_t    width;
        //像素高度
        uint32_t    height;
        //每一行佔幾個字節
        uint32_t    stride;
        //像素格式
        int32_t     format;
        /** Unused. */
        uint32_t    flags;      // 0 for now
    } AndroidBitmapInfo;
    複製代碼
  • 提供的方法ide

    //獲取bitmap的圖片信息
    int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,
                              AndroidBitmapInfo* info);
    //獲取像素信息
    int AndroidBitmap_lockPixels(JNIEnv* env, jobject jbitmap, void** addrPtr);
    //釋放像素信息
    int AndroidBitmap_unlockPixels(JNIEnv* env, jobject jbitmap);
    複製代碼
  • 調用函數返回碼函數

    enum {
        //調用成功
        ANDROID_BITMAP_RESULT_SUCCESS           = 0,
        //參數錯誤
        ANDROID_BITMAP_RESULT_BAD_PARAMETER     = -1,
        //出現異常
        ANDROID_BITMAP_RESULT_JNI_EXCEPTION     = -2,
       //分配失敗
        ANDROID_BITMAP_RESULT_ALLOCATION_FAILED = -3,
    };
    複製代碼

編寫測試代碼

  • 建立類 JniBitmapDemo,編寫對應的測試代碼:
    public class JniBitmapDemo {
        private static final String TAG = "JniBitmapDemo";
        static {
            System.loadLibrary("bitmap");
        }
    
        public native void passBitmap(Bitmap bitmap);
    
        public void test() {
            Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
            bitmap.eraseColor(0xff336699); // AARRGGBB
            byte[] bytes = new byte[bitmap.getWidth() * bitmap.getHeight() * 4];
            Buffer dst = ByteBuffer.wrap(bytes);
            bitmap.copyPixelsToBuffer(dst);
            // ARGB_8888 真實的存儲順序是 R-G-B-A
            Log.d(TAG, "R: " + Integer.toHexString(bytes[0] & 0xff));
            Log.d(TAG, "G: " + Integer.toHexString(bytes[1] & 0xff));
            Log.d(TAG, "B: " + Integer.toHexString(bytes[2] & 0xff));
            Log.d(TAG, "A: " + Integer.toHexString(bytes[3] & 0xff));
    
            passBitmap(bitmap);
        }
    }
    複製代碼
  • 建立bitmap.cpp.
  • 添加如下代碼到CMakeLists.txt
    add_library(
            bitmap
            SHARED
            bitmap.cpp)
    target_link_libraries(
            bitmap
            jnigraphics
            ${log-lib})
    複製代碼

實現JNI下Bitmap使用的邏輯

#include <jni.h>
#include <android/bitmap.h>
#include <android/log.h>
#include <cstring>
#include "LogUtils.h"


extern "C"
JNIEXPORT void JNICALL
Java_com_lxk_ndkdemo_JniBitmapDemo_passBitmap(JNIEnv *env, jobject instance, jobject bitmap) {

    if (nullptr == bitmap) {
        LOGE("bitmap is null");
    }

    AndroidBitmapInfo info;
    int result;

    //獲取圖片信息
    result = AndroidBitmap_getInfo(env, bitmap, &info);

    if (result != ANDROID_BITMAP_RESUT_SUCCESS) {
        LOGE("AndroidBitmap_getInfo failed, result: %d", result);
        return;
    }

    LOGD("bitmap width: %d, height: %d, format: %d, stride: %d", info.width, info.height,
         info.format, info.stride);

    unsigned char *addrPtr;

    // 獲取像素信息
    result = AndroidBitmap_lockPixels(env, bitmap, reinterpret_cast<void **>(&addrPtr));

    if (result != ANDROID_BITMAP_RESULT_SUCCESS) {
        LOGE("AndroidBitmap_lockPixels failed, result: %d", result);
        return;
    }

    // 執行圖片操做的邏輯
    int length = info.stride * info.height;
    for (int i = 0; i < length; ++i) {
        LOGD("value: %x", addrPtr[i]);
    }

    // 像素信息再也不使用後須要解除鎖定
    result = AndroidBitmap_unlockPixels(env, bitmap);
    if (result != ANDROID_BITMAP_RESULT_SUCCESS) {
        LOGE("AndroidBitmap_unlockPixels failed, result: %d", result);
    }

}
複製代碼

執行測試代碼

new JniBitmapDemo().test();
複製代碼

會在控制檯打印Bitmap對應的信息。測試

若是出現undefined reference to AndroidBitmap_getInfo相似的報錯信息。 是由於CMakeLists.txt中沒有添加jnigraphics.ui

target_link_libraries(
        bitmap
        jnigraphics
        ${log-lib})
複製代碼

Demo地址:https://github.com/103style/NDKDoc/tree/master/NDKDemo

若是以爲不錯的話,請幫忙點個讚唄。

以上


掃描下面的二維碼,關注個人公衆號 Android1024, 點關注,不迷路。

Android1024
相關文章
相關標籤/搜索