使用 jni 将位图从 android 相机传递到 C++

Posted

技术标签:

【中文标题】使用 jni 将位图从 android 相机传递到 C++【英文标题】:Passing a bitmap from android camera to C++ with jni 【发布时间】:2018-01-05 23:45:22 【问题描述】:

我有一个用户在其上拍照的应用程序,它以Bitmap bitmap 的形式返回给 java 方法。我想将此位图传递给 C++ 函数以进行一些 OpenCV 处理,只要它被采用。

我无法找到正确的数据格式来将位图传递给方法。我尝试将位图作为 jobect 参数传递,但它不起作用。

这是我想将位图传递到的 jni 方法:

JNIEXPORT jintArray JNICALL Java_com_example_user_digitrecognition_MainActivity_generateAssets(
    JNIEnv *env, jobject thiz, jobject assetManager) 

【问题讨论】:

【参考方案1】:

要从jni访问Bitmap的像素缓冲区,可以调用getPixels:

NewByteArray 一个 byte[] 对象(只需要执行一次并且 GlobalRef/reused) FindClass/GetMethodID/CallVoidMethod 从 c/c++ 调用 getPixels GetByteArrayRegion 将 java byte[] 映射到 c 缓冲区。

可以查看JNI函数here

否则,在 Java 端管理 byte[] 像素缓冲区,并将 byte[](和图像格式/尺寸)传递给 jni 而不是 Bitmap 对象。例如:

JNIEXPORT jintArray JNICALL Java_com_example_user_digitrecognition_jniFacility_handleFrame(
    JNIEnv *env, jobject self, jobject pixels, jint width, jint height, jint format) 
    ...

既然你说你得到了Bitmap,就把位图传给jni:

pixels = new byte[width * height * 4]; // assume RGBA, do once only
...
bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
handleFrame(pixels, bitmap.getWidth(), bitmap.getHeight());

为了获得最佳性能(和现场录制),您可能希望使用 ImageReader 并使用 YUV 图像。


顺便说一句,如果您通过 ImageReader 获取帧,opencv 接受 ImageFormat.YUV_420_888。您可能希望调整大小并仅使用亮度通道进行大多数处理。

【讨论】:

我如何像你在最后一行提到的那样将图像格式/尺寸传递给 jni?我应该使用哪种格式? @Ber12345 为您的查询更新了答案,请注意,如果您将图像设为Bitmap,可能是出于意图,您无法控制格式,您需要使用图像实用程序功能手动转换它.

以上是关于使用 jni 将位图从 android 相机传递到 C++的主要内容,如果未能解决你的问题,请参考以下文章

在YUV_420_888中将图像从Android发送到OpenCV Mat中的JNI的最有效方式

Opencv将Mat从Android传递到JNI错误

Android:如何用相机拍照并将位图转换为字节数组并保存到sqlite db?

从相机/图库加载图像位图时会旋转 [Android 9]

如何将位图从 Activity 传递给服务

Android 位图到 Base64 字符串