java层的图片如何传递到c/c+层处理,处理完之后如何传回java层,下面总结了一下用到的三种方法。

1.将Bitmap转为int[]数组对象,将数组作为参数传递到C/C++层,处理完之后再以int[]数组返回。

 //将bitmap转化为数组,保存到pixels中
Bitmap mOriginalBmp = BitmapFactory.decodeResource(getResources(), R.drawable.test);
int w = mOriginalBmp.getWidth();
int h = mOriginalBmp.getHeight();
int[] pixels = new int[w * h];
mOriginalBmp.getPixels(pixels, 0, w, 0, 0, w, h); //调用Native方法获得处理过后的数组,转化为bitmap
int[] resultInt = ImageProc.grayPoc(pixels, w, h);
Bitmap mBuildedBmp = Bitmap.createBitmap(resultInt,w, h,mOriginalBmp.getConfig());
mImageView.setImageBitmap(mBuildedBmp); //native方法定义
public static native int[] grayPoc(int[] pixels,int w,int h); //native的实现,将图片转化为灰度图
JNIEXPORT jintArray JNICALL Java_com_dengxy_opencvtest_ImageProc_grayPoc(
JNIEnv * env, jclass obj, jintArray buf, int w, int h) {
LOGD("Java_com_dengxy_opencvtest_ImageProc_grayPoc:start");
jint *cbuf;
cbuf = env->GetIntArrayElements(buf, JNI_FALSE); if (cbuf == NULL) { return 0; }
Mat imgData(h, w, CV_8UC4, (unsigned char *) cbuf);
uchar* ptr = imgData.ptr(0); for (int i = 0; i < w * h; i++) { int grayScale = (int) (ptr[4 * i + 2] * 0.299 + ptr[4 * i + 1] * 0.587 + ptr[4 * i + 0] * 0.114); ptr[4 * i + 1] = grayScale; ptr[4 * i + 2] = grayScale; ptr[4 * i + 0] = grayScale; }
int size = w * h;
jintArray result = env->NewIntArray(size);
env->SetIntArrayRegion(result, 0, size, cbuf);
env->ReleaseIntArrayElements(buf, cbuf, 0);
LOGD("Java_com_dengxy_opencvtest_ImageProc_grayPoc:end");
return result;
}

这种方法需要重复的拷贝,转化图片数据,空间和时间复杂度较高,效率较低。

2.直接将Bitmap对象传递到底层,C/C++获得Bitmap数据的指针,再转化为Mat,这种方法为底层直接操作bitmap的内存空间,操作前后会锁住该地址空间,完了java层刷新界面就可以了,
这里是一个Sobel边缘检测。用的时候发现要是内存空间有拷贝,操作的不是当前图片所在的内存空间的话,图片是改变不了的。

 Bitmap mBuildedBmp = BitmapFactory.decodeResource(getResources(), R.drawable.test);
ImageProc.getSobel(mBuildedBmp);
mImageView.setImageBitmap(mBuildedBmp); //java接口函数
private static native int getSobel(Bitmap in,Bitmap out); //对应的C++文件需要引入头文件 bitmap.h
#include <android/bitmap.h> //对应C++函数
JNIEXPORT void JNICALL Java_com_dengxy_opencvtest_ImageProc_getSobel(
JNIEnv * env, jclass obj, jobject bmpIn) {
AndroidBitmapInfo inBmpInfo;
void* inPixelsAddress;
int ret;
if ((ret = AndroidBitmap_getInfo(env, bmpIn, &inBmpInfo)) < 0) {
LOGD("AndroidBitmap_getInfo() failed ! error=%d", ret);
return;
}
LOGI("original image :: width is %d; height is %d; stride is %d; format is %d;flags is %d,stride is %u", inBmpInfo.width, inBmpInfo.height, inBmpInfo.stride, inBmpInfo.format, inBmpInfo.flags, inBmpInfo.stride);
if ((ret = AndroidBitmap_lockPixels(env, bmpIn, &inPixelsAddress)) < 0) {
LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
}
Mat inMat(inBmpInfo.height, inBmpInfo.width,
CV_8UC4, inPixelsAddress);
Sobel(inMat, inMat, inMat.depth(), 1, 1);
AndroidBitmap_unlockPixels(env, bmpIn);
LOGI("Return !! ");
return; }

3.直接将Bitmap转化为Mat后,获取mat内存地址传到底层,处理后再返回内存地址到java层,根据地址加载Mat对象转化为bitmap。这种方法较上一种主要是内存空间有改变有可以,但是用的时候发现系统一GC回收图片,底层就出现了空指针,一看是底层MAT的析构函数没做非空判断,于是尝试着自己编译opencv4android,折腾了两天始终编译没通过,泪渀- o -

 //Java层代码
Bitmap oldBmp mBuildedBmp = BitmapFactory.decodeResource(getResources(), R.drawable.test);
Mat bmpMat = new Mat();
Utils.bitmapToMat(mBuildedBmp, bmpMat);
long resultAddress = -1;
resultAddress = ImageProc.getLaplacian(bmpMat.getNativeObjAddr());
Log.d(TAG, "doLaplacian:resultAddress="+resultAddress);
if(resultAddress<0){
return ;
}
Mat resultLaplacianMat = new Mat(resultAddress);
Utils.matToBitmap(resultLaplacianMat, mBuildedBmp);
mImageView.setImageBitmap(mBuildedBmp); //jni接口
public static native long getLaplacian(long bitmap); //c++实现
JNIEXPORT jlong JNICALL Java_com_dengxy_opencvtest_ImageProc_getLaplacian
(JNIEnv * env, jclass obj, jlong bmAddress){
LOGD("Java_com_dengxy_opencvtest_ImageProc_getLaplacian:start");
Mat *bitmpaMat = (Mat*) bmAddress;
if (NULL == bitmpaMat) {
LOGD("Java_com_dengxy_opencvtest_ImageProc_getLaplacian:the bitmpaMat is Null");
return -1;
}
Laplacian(*bitmpaMat,*bitmpaMat,bitmpaMat->depth());
jlong resultAddress = (jlong)bitmpaMat;
LOGD("Java_com_dengxy_opencvtest_ImageProc_getLaplacian:end");
return resultAddress;
}

转自:http://www.apkbus.com/forum.php?mod=viewthread&tid=267283&_dsign=760031da

Jni中图片传递的3种方式(转)的更多相关文章

  1. jQuery中开发插件的两种方式

    jQuery中开发插件的两种方式(附Demo) 做web开发的基本上都会用到jQuery,jQuery插件开发两种方式:一种是类扩展的方式开发插件,jQuery添加新的全局函数(jQuery的全局函数 ...

  2. 城市经纬度 json 理解SignalR Main(string[] args)之args传递的几种方式 串口编程之端口 多线程详细介绍 递归一个List<T>,可自己根据需要改造为通用型。 Sql 优化解决方案

    城市经纬度 json https://www.cnblogs.com/innershare/p/10723968.html 理解SignalR ASP .NET SignalR 是一个ASP .NET ...

  3. linux内核分析作业4:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

    系统调用:库函数封装了系统调用,通过库函数和系统调用打交道 用户态:低级别执行状态,代码的掌控范围会受到限制. 内核态:高执行级别,代码可移植性特权指令,访问任意物理地址 为什么划分级别:如果全部特权 ...

  4. ios页面间传递参数四种方式

    ios页面间传递参数四种方式 1.使用SharedApplication,定义一个变量来传递. 2.使用文件,或者NSUserdefault来传递 3.通过一个单例的class来传递 4.通过Dele ...

  5. 在Windows 10中截取截图的6种方式 简介

    在Windows 10中截取截图的6种方式 简介 截图对于不同的目的很重要.它可以用于捕获笔记本电脑上的任何内容的截图.所以,如果你使用Windows 10,你可能不知道如何截图,因为它是比较新的.因 ...

  6. Json传递数据两种方式(json大全)

    1.Json传递数据两种方式(json大全)----------------------------字符串 var list1 = ["number","name&quo ...

  7. LInux内核分析--使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

    实验者:江军 ID:fuchen1994 实验描述: 选择一个系统调用(13号系统调用time除外),系统调用列表参见http://codelab.shiyanlou.com/xref/linux-3 ...

  8. js中声明Number的五种方式

    转载自:http://www.jb51.net/article/34191.htm <!DOCTYPE html> <html> <head> <meta c ...

  9. Python:实现图片裁剪的两种方式——Pillow和OpenCV

    原文:https://blog.csdn.net/hfutdog/article/details/82351549 在这篇文章里我们聊一下Python实现图片裁剪的两种方式,一种利用了Pillow,还 ...

随机推荐

  1. BZOJ3289[JZYZOJP2018]: Mato的文件管理 莫队+树状数组+离散化

            描述 Description     Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号.为了防止他人偷拷,这些资料都是加密过的, ...

  2. web前端 -- onkeydown、onkeypress、onkeyup、onblur、onchange、oninput、onpropertychange的区别

    FROM:http://www.cnblogs.com/svage/archive/2011/11/15/2249954.html onkeydown:按下任何键(字母.数字.系统.tab等)都能触发 ...

  3. SQL的in的参数化查询

    SqlCommand cmd=con.CreateCommand(); cmd.CommandText="exec('select * from novel where novelid in ...

  4. asp.net调用存储过程1

    1,传入参数,传出参数 public int GetTeam1Id(string userId)        {            int team1ID = -1;            st ...

  5. 破解MyEclipse2015 stable3.0(亲测可用)

    整个破解过程最好断网: 1.安装好MyEclipse2015 stable3后,打开设置好工作目录后,退出.2.将plugins文件夹中的文件拷贝到myeclipse安装目录的plugins文件夹下, ...

  6. ZigBee和Z-Wave的区别与未来

    http://tech.c114.net/164/a702667.html ZigBee和Z-Wave短距离无线技术都用于远程监控和控制,但两种技术的规格和应用却不同.在美国应用越来越广泛的家庭局域网 ...

  7. Linux X86-64 进程内存空间布局

    http://blog.csdn.net/woshinia/article/details/41722085 http://www.lenky.info/archives/2012/04/1424 h ...

  8. 解决/dev/fb0无法打开的问题

    最近要在Linux做基于frame Buffer的图形显示,不论我在独立分区的Linux FC6系统中,还是在装有Red hat9的VPC中,都无法打开/dev/fb0.从网上找了很多资料,都没能解决 ...

  9. Appium+python自动化19-iOS模拟器(iOS Simulator)安装自家APP

    前言 做过iOS上app测试的小伙伴应该都知道,普通用户安装app都是从appstore下载安装,安装测试版本的app,一般就是开发给的二维码扫码安装, 或者开发给个.ipa的安装包文件,通过itoo ...

  10. Labeled Faces in the Wild 人脸识别数据集 部分测试数据

    development test set Note: images displayed are original (non-aligned/funneled) images. match pairs ...