Jni中图片传递的3种方式(转)
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种方式(转)的更多相关文章
- jQuery中开发插件的两种方式
jQuery中开发插件的两种方式(附Demo) 做web开发的基本上都会用到jQuery,jQuery插件开发两种方式:一种是类扩展的方式开发插件,jQuery添加新的全局函数(jQuery的全局函数 ...
- 城市经纬度 json 理解SignalR Main(string[] args)之args传递的几种方式 串口编程之端口 多线程详细介绍 递归一个List<T>,可自己根据需要改造为通用型。 Sql 优化解决方案
城市经纬度 json https://www.cnblogs.com/innershare/p/10723968.html 理解SignalR ASP .NET SignalR 是一个ASP .NET ...
- linux内核分析作业4:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
系统调用:库函数封装了系统调用,通过库函数和系统调用打交道 用户态:低级别执行状态,代码的掌控范围会受到限制. 内核态:高执行级别,代码可移植性特权指令,访问任意物理地址 为什么划分级别:如果全部特权 ...
- ios页面间传递参数四种方式
ios页面间传递参数四种方式 1.使用SharedApplication,定义一个变量来传递. 2.使用文件,或者NSUserdefault来传递 3.通过一个单例的class来传递 4.通过Dele ...
- 在Windows 10中截取截图的6种方式 简介
在Windows 10中截取截图的6种方式 简介 截图对于不同的目的很重要.它可以用于捕获笔记本电脑上的任何内容的截图.所以,如果你使用Windows 10,你可能不知道如何截图,因为它是比较新的.因 ...
- Json传递数据两种方式(json大全)
1.Json传递数据两种方式(json大全)----------------------------字符串 var list1 = ["number","name&quo ...
- LInux内核分析--使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
实验者:江军 ID:fuchen1994 实验描述: 选择一个系统调用(13号系统调用time除外),系统调用列表参见http://codelab.shiyanlou.com/xref/linux-3 ...
- js中声明Number的五种方式
转载自:http://www.jb51.net/article/34191.htm <!DOCTYPE html> <html> <head> <meta c ...
- Python:实现图片裁剪的两种方式——Pillow和OpenCV
原文:https://blog.csdn.net/hfutdog/article/details/82351549 在这篇文章里我们聊一下Python实现图片裁剪的两种方式,一种利用了Pillow,还 ...
随机推荐
- BZOJ3619 [Zjoi2014]璀灿光华 构造+dfs
题意:有一个\(a^3\)个小正方体组成的大正方体,其中有n个正方体会向上下左右前后六个方向中的一个发出光,正方体是透光的,被照亮的正方体有个美丽值\(g_{i}\),给出正方体的相邻关系,问美丽值之 ...
- spoj 375 query on a tree LCT
这道题是树链剖分的裸题,正在学LCT,用LCT写了,发现LCT代码比树链剖分还短点(但我的LCT跑极限数据用的时间大概是kuangbin大神的树链剖分的1.6倍,所以在spoj上是850ms卡过的). ...
- bzoj 1115: [POI2009]石子游戏Kam -- 博弈论
1115: [POI2009]石子游戏Kam Time Limit: 10 Sec Memory Limit: 162 MB Description 有N堆石子,除了第一堆外,每堆石子个数都不少于前 ...
- bzoj1715 虫洞
Description John在他的农场中闲逛时发现了许多虫洞.虫洞可以看作一条十分奇特的有向边,并可以使你返回到过去的一个时刻(相对你进入虫洞之前).John的每个农场有M条小路(无向边)连接着N ...
- 关于图表第三方Charts的一些理解与总结
最近项目中用到了很多的图表,如柱状图,线状图,饼状图等等.接触到了一个新的第三方Charts,在做图方面确实非常强大,在使用了一段时间后,今天对他进行一个小的总结,也是自己的一点小理解. 关于char ...
- Mahout学习之Mahout简单介绍、安装、配置、入门程序測试
一.Mahout简单介绍 查了Mahout的中文意思--驭象的人,再看看Mahout的logo,好吧,想和小黄象happy地玩耍,得顺便陪陪这位驭象人耍耍了... 附logo: (就是他,骑在象头上的 ...
- JavaScript面试(-------------------------------------------)
this是什么 方法调用模式 构造器调用模式 函数调用模式 apply/call模式 this是什么 —大多语言中,’this’代表由类实例化的当前对象.在JavaScript中,’this’通常表示 ...
- 一个 MVC 框架以 MVVM 之「魂」复活了!
GitHub: https://github.com/houfeng/mokit Mokit 最初编写于 2012 年,是一个面向移动应用的前端 mvc 框架,v3 版本进行了大量的重构或重写,并尽可 ...
- [Android Studio] Android Studio如何查看branch列表及切换branch(转载)
转载地址:http://blog.csdn.net/hyr83960944/article/details/36185231 用Git bash去切换相信大家都会,一行命令行搞定的问题.而在Andro ...
- 数学图形(1.25)cassini曲线
通过这种曲线可以看到一种由8到0的过度 相关软件参见:数学图形可视化工具,使用自己定义语法的脚本代码生成数学图形.该软件免费开源.QQ交流群: 367752815 #http://www.mathcu ...