[有关使用Utils.matToBitmap()函数将Mat转换为Bitmap的几篇文章。但是我假设此函数只能在导入Utils类之后在Java层中调用。
我想将数据传输到uint32_t * bmpContent指向的内存地址;在下面的代码中。
JNIEXPORT void JNICALL Java_com_nod_nodcv_NodCVActivity_runfilter(
JNIEnv *env, jclass clazz, jobject outBmp, jbyteArray inData,
jint width, jint height, jint choice, jint filter)
{
int outsz = width*height;
int insz = outsz + outsz/2;
AndroidBitmapInfo bmpInfo;
if (AndroidBitmap_getInfo(env, outBmp, &bmpInfo) < 0) {
throwJavaException(env,"gaussianBlur","Error retrieving bitmap meta data");
return;
}
if (bmpInfo.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
throwJavaException(env,"gaussianBlur","Expecting RGBA_8888 format");
return;
}
uint32_t* bmpContent;
if (AndroidBitmap_lockPixels(env, outBmp,(void**)&bmpContent) < 0) {
throwJavaException(env,"gaussianBlur","Unable to lock bitmap pixels");
return;
}
//This function runs the kernel on the inData and gives a matrix
tester(env, clazz, bmpContent, outsz, inData, insz, width, height);
AndroidBitmap_unlockPixels(env, outBmp);
}
这大致是测试器功能中发生的事情:
jbyte* b_mat = env->GetByteArrayElements(inData, 0);
cv::Mat mdata(h, w, CV_8UC4, (unsigned char *)b_mat);
cv::Mat mat_src = imdecode(mdata,1);
cv::UMat umat_src = mat_src.getUMat(cv::ACCESS_READ, cv::USAGE_ALLOCATE_DEVICE_MEMORY);
cv::UMat umat_dst (mat_src.size(), mat_src.type(), cv::ACCESS_WRITE, cv::USAGE_ALLOCATE_DEVICE_MEMORY);
kernel.args(cv::ocl::KernelArg::ReadOnlyNoSize(umat_src), cv::ocl::KernelArg::ReadWrite(umat_dst));
size_t globalThreads[3] = {static_cast<unsigned int>(mat_src.cols), static_cast<unsigned int>(mat_src.rows), 1 };
bool success = kernel.run(3, globalThreads, NULL, true);
cv::Mat mat_dst = umat_dst.getMat(cv::ACCESS_READ);
mat_dst保存我需要的结果,并且需要在手机上显示。我怎样才能做到这一点?
我假设我需要将数据从mat_dst复制到bmpContent位置,但是我不确定。
使用此将您的Mat转换为位图。
jclass java_bitmap_class = (jclass)env->FindClass("android/graphics/Bitmap");
jmethodID mid = env->GetMethodID(java_bitmap_class, "getConfig", "()Landroid/graphics/Bitmap$Config;");
jobject bitmap_config = env->CallObjectMethod(bitmap, mid);
jobject _bitmap = mat_to_bitmap(env,dst,false,bitmap_config);
AndroidBitmap_unlockPixels(env, bitmap);
return _bitmap;
如果确实需要从JNI层调用此方法,则可以简单地使用OpenCV的原始C ++实现Here。示例代码如下:
#include <jni.h>
#include <string>
#include <android/bitmap.h>
#include "opencv2/opencv.hpp"
// using namespace cv;
void MatToBitmap2 (JNIEnv * env, cv::Mat src, jobject bitmap, bool needPremultiplyAlpha)
{
AndroidBitmapInfo info;
void* pixels = 0;
try {
// LOGD("nMatToBitmap");
CV_Assert( AndroidBitmap_getInfo(env, bitmap, &info) >= 0 );
CV_Assert( info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 ||
info.format == ANDROID_BITMAP_FORMAT_RGB_565 );
CV_Assert( src.dims == 2 && info.height == (uint32_t)src.rows && info.width == (uint32_t)src.cols );
CV_Assert( src.type() == CV_8UC1 || src.type() == CV_8UC3 || src.type() == CV_8UC4 );
CV_Assert( AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0 );
CV_Assert( pixels );
if( info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 )
{
cv::Mat tmp(info.height, info.width, CV_8UC4, pixels);
if(src.type() == CV_8UC1)
{
cvtColor(src, tmp, cv::COLOR_GRAY2RGBA);
} else if(src.type() == CV_8UC3){
cvtColor(src, tmp, cv::COLOR_RGB2RGBA);
} else if(src.type() == CV_8UC4){
if(needPremultiplyAlpha) cvtColor(src, tmp, cv::COLOR_RGBA2mRGBA);
else src.copyTo(tmp);
}
} else {
// info.format == ANDROID_BITMAP_FORMAT_RGB_565
cv::Mat tmp(info.height, info.width, CV_8UC2, pixels);
if(src.type() == CV_8UC1)
{
cvtColor(src, tmp, cv::COLOR_GRAY2BGR565);
} else if(src.type() == CV_8UC3){
cvtColor(src, tmp, cv::COLOR_RGB2BGR565);
} else if(src.type() == CV_8UC4){
cvtColor(src, tmp, cv::COLOR_RGBA2BGR565);
}
}
AndroidBitmap_unlockPixels(env, bitmap);
return;
} catch(const cv::Exception& e) {
AndroidBitmap_unlockPixels(env, bitmap);
jclass je = env->FindClass("java/lang/Exception");
env->ThrowNew(je, e.what());
return;
} catch (...) {
AndroidBitmap_unlockPixels(env, bitmap);
jclass je = env->FindClass("java/lang/Exception");
env->ThrowNew(je, "Unknown exception in JNI code {nMatToBitmap}");
return;
}
}
该函数直接从OpenCV来源采用,并包含对不同格式的一些额外检查。如果您知道将要使用哪种矩阵格式,则可以剥离检查。
mat_dst保存我需要的结果,并且需要在手机上显示。我该怎么办?
您可以呼叫类似:
extern "C"
JNIEXPORT void JNICALL
Java_com_your_package_MainActivity_DoStuff(JNIEnv *env, jobject thiz,
jobject bitmap) {
// Do your stuff with mat_dst.
try {
MatToBitmap2(env, mat_dst, bitmap, false);
}
catch(const cv::Exception& e)
{
jclass je = env->FindClass("java/lang/Exception");
env->ThrowNew(je, e.what());
}
}
并在Java端定义它,如:
public native void DoStuff(Bitmap bitmap);
您不需要将任何东西返回到Java端,因为Bitmap类将是引用类型,而MatToBitmap2方法已经负责锁定和解锁像素缓冲区。