Jni编程会用到的工具函数,做积累
1. 打开文件路径,返回文件描述符给Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
//打开路径文件,并抬FileDescriptor jobject
openFile(JNIEnv *env, jstring path, jint flags){ int fd; jobject
mFileDescriptor; /*
Opening device */ { jboolean
iscopy; const char *path_utf
= env->GetStringUTFChars(path, &iscopy); fd
= open(path_utf, O_RDWR | flags); env->ReleaseStringUTFChars(path,
path_utf); if (fd
== -1) { /*
Throw an exception */ LOGE( "Cannot
open port" ); return NULL; } } /*
Create a corresponding file descriptor */ { jclass
cFileDescriptor = env->FindClass( "java/io/FileDescriptor" ); jmethodID
iFileDescriptor = env->GetMethodID(cFileDescriptor, "<init>" , "()V" ); jfieldID
descriptorID = env->GetFieldID(cFileDescriptor, "descriptor" , "I" ); mFileDescriptor
= env->NewObject(cFileDescriptor, iFileDescriptor); env->SetIntField(mFileDescriptor,
descriptorID, (jint)fd); } return mFileDescriptor; } |
2. Char转换成String
1
2
3
4
5
6
7
8
9
10
11
|
//char
* to string jstring
charToString(JNIEnv *env, const char *chr){ LOGI( "charToString:
%s\n" ,
chr); jclass
strClass = env->FindClass( "java/lang/String" ); jmethodID
strConstruct = env->GetMethodID(strClass, "<init>" , "([BLjava/lang/String;)V" ); jbyteArray
bytes = env->NewByteArray( strlen (chr)); env->SetByteArrayRegion(bytes,
0, strlen (chr),
(jbyte*)chr); jstring
encoding = env->NewStringUTF( "utf-8" ); return (jstring)env->NewObject(strClass,
strConstruct, bytes, encoding); } |
3. String转换为Char
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
//jstring
to char* char *
jstringToChar(JNIEnv* env, jstring jstr) { char *
rtn = NULL; jclass
clsstring = env->FindClass( "java/lang/String" ); jstring
strencode = env->NewStringUTF( "utf-8" ); jmethodID
mid = env->GetMethodID(clsstring, "getBytes" , "(Ljava/lang/String;)[B" ); jbyteArray
barr= (jbyteArray)env->CallObjectMethod(jstr, mid, strencode); jsize
alen = env->GetArrayLength(barr); jbyte*
ba = env->GetByteArrayElements(barr, JNI_FALSE); if (alen
> 0) { rtn
= ( char *) malloc (alen
+ 1); memcpy (rtn,
ba, alen); rtn[alen]
= 0; } env->ReleaseByteArrayElements(barr,
ba, 0); return rtn; } |
4. 上层传一个ByteBuffer给Jni用
Java:
private ByteBuffer mImageBuffer;
mImageBuffer = ByteBuffer.allocateDirect(mImageBufferSize);
ret = setDirectBuffer(mImageBuffer, mImageBufferSize);
Jni:
jint Java_com_camera_simplewebcam_CameraPreview_setDirectBuffer(JNIEnv *env, jobject thiz,
jobject jbuf, jint jlen) {
char *pImageBuf = NULL;
//获取Buffer首地址
pImageBuf = (char *)(*env)->GetDirectBufferAddress(env, jbuf);
if (NULL == pImageBuf) {
LOGE("Failed to get direct buffer");
return -1;
}
return 0;
}
5. 色彩Buffer转换成Bitmap类。
在UVC中把一帧的buffer转换成上层需要显示的Bitmap。Android.mk里要加入库LOCAL_LDLIBS := -ljnigraphics
void
Java_com_camera_simplewebcam_CameraPreview_pixeltobmp( JNIEnv* env,jobject thiz,jobject bitmap){
jboolean bo;
AndroidBitmapInfo info;
void* pixels;
int ret;
int i;
int *colors;
int width=0;
int height=0;
//提取bmp信息
if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) {
LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
return;
}
width = info.width;
height = info.height;
if(!rgb || !ybuf) return;
if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
LOGE("Bitmap format is not RGBA_8888 !");
return;
}
//bitmap提取buf
if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) {
LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
}
colors = (int*)pixels;
int *lrgb =NULL;
lrgb = &rgb[0];
//把目录buf拷贝到bitmap的buffer里
for(i=0 ; i<width*height ; i++){
*colors++ = *lrgb++;
}
AndroidBitmap_unlockPixels(env, bitmap);
}