NDK 開(kāi)發(fā)之 Bitmap 的使用
一、前言
Bitmap 是 Android 中經(jīng)常使用到的圖片操作的一個(gè)類(lèi),它包含了圖片的寬、高、格式、像素等信息。那么我們?cè)趺丛?NDK 中使用它呢。
二、bitmap.h
1. 介紹
NDK 已經(jīng)為我們準(zhǔn)備好了在 NDK 中操作 Bitmap 的相關(guān)頭文件了,它就是
2. AndroidBitmapInfo
一個(gè)包含 Bitmap 常用信息的結(jié)構(gòu)體,定義如下:
/** Bitmap info, see AndroidBitmap_getInfo(). */
typedef struct {
/** The bitmap width in pixels. */
uint32_t width;
/** The bitmap height in pixels. */
uint32_t height;
/** The number of byte per row. */
uint32_t stride;
/** The bitmap pixel format. See {@link AndroidBitmapFormat} */
int32_t format;
/** Unused. */
uint32_t flags; // 0 for now
} AndroidBitmapInfo;
3. AndroidBitmapFormat
Bitmap 的圖片格式枚舉,和 Java 端所對(duì)應(yīng)
/** Bitmap pixel format. */
enum AndroidBitmapFormat {
/** No format. */
ANDROID_BITMAP_FORMAT_NONE = 0,
/** Red: 8 bits, Green: 8 bits, Blue: 8 bits, Alpha: 8 bits. **/
ANDROID_BITMAP_FORMAT_RGBA_8888 = 1,
/** Red: 5 bits, Green: 6 bits, Blue: 5 bits. **/
ANDROID_BITMAP_FORMAT_RGB_565 = 4,
/** Deprecated in API level 13. Because of the poor quality of this configuration, it is advised to use ARGB_8888 instead. **/
ANDROID_BITMAP_FORMAT_RGBA_4444 = 7,
/** Alpha: 8 bits. */
ANDROID_BITMAP_FORMAT_A_8 = 8,
};
4. 接口返回碼
/** AndroidBitmap functions result code. */
enum {
/** Operation was successful. */
ANDROID_BITMAP_RESULT_SUCCESS = 0,
/** Bad parameter. */
ANDROID_BITMAP_RESULT_BAD_PARAMETER = -1,
/** JNI exception occured. */
ANDROID_BITMAP_RESULT_JNI_EXCEPTION = -2,
/** Allocation failed. */
ANDROID_BITMAP_RESULT_ALLOCATION_FAILED = -3,
};
5. 方法
/**
* 給定一個(gè) java 的 bitmap 對(duì)象,獲取到對(duì)應(yīng)的 AndroidBitmapInfo 結(jié)構(gòu)體
*/
int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,
AndroidBitmapInfo* info);
/**
* 將 addrPtr 指向圖片的像素地址。這個(gè)方法會(huì)鎖定圖片的所有像素不能改變,直到調(diào)用AndroidBitmap_unlockPixels 方法
*/
int AndroidBitmap_lockPixels(JNIEnv* env, jobject jbitmap, void** addrPtr);
/**
* 解除對(duì)圖片像素的鎖定
*/
int AndroidBitmap_unlockPixels(JNIEnv* env, jobject jbitmap);
三、實(shí)例操作
1. MainActivity
import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.Log;
import java.nio.Buffer;
import java.nio.ByteBuffer;
public class MainActivity extends Activity {
static {
System.loadLibrary("native-lib");
}
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
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 真實(shí)的存儲(chǔ)順序是 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);
}
public native void passBitmap(Bitmap bitmap); // 傳遞一個(gè) Bitmap 給 NDK
}
主要是創(chuàng)建一個(gè) Bitmap 調(diào)用 passBitmap() 方法傳遞給 NDK。
2. native-lib.cpp
#include
#include
#include "log.hpp"
extern "C" {
JNIEXPORT void JNICALL
Java_com_afei_myapplication_MainActivity_passBitmap(JNIEnv *env, jobject instance, jobject bitmap) {
if (NULL == bitmap) {
LOGE("bitmap is null!");
return;
}
AndroidBitmapInfo info; // create a AndroidBitmapInfo
int result;
// 獲取圖片信息
result = AndroidBitmap_getInfo(env, bitmap, &info);
if (result != ANDROID_BITMAP_RESULT_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;
}
// 執(zhí)行圖片操作的邏輯
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);
}
}
}
主要是接收到 Bitmap 對(duì)象,并且打印出一些信息。
3. 運(yùn)行結(jié)果

通過(guò) JNI_LOG 我們可以看到,NDK 層的圖片信息輸出和 Java 層的是一致的。
四、編譯的問(wèn)題
注意,要使用 的話,必須要鏈接 jnigraphics 庫(kù),否則會(huì)報(bào)類(lèi)似 undefined reference to ‘AndroidBitmap_getInfo’ 這樣的錯(cuò)誤。
1. CMakeLists.txt 中
target_link_libraries( # Specifies the target library.
native-lib
# 加上下面這一行
jnigraphics
# Links the target library to the log library
# included in the NDK.
${log-lib} )2. Android.mk 中
LOCAL_LDLIBS += -ljnigraphics————————————————
版權(quán)聲明:本文為CSDN博主「阿飛__」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/afei__/article/details/81429417
推薦:
全網(wǎng)最全的 Android 音視頻和 OpenGL ES 干貨,都在這了
評(píng)論
圖片
表情
