zoukankan      html  css  js  c++  java
  • Jni中图片传递的3种方式(转)

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

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

     1 //将bitmap转化为数组,保存到pixels中
     2 Bitmap mOriginalBmp = BitmapFactory.decodeResource(getResources(), R.drawable.test);
     3 int w = mOriginalBmp.getWidth();
     4 int h = mOriginalBmp.getHeight();
     5 int[] pixels = new int[w * h];
     6 mOriginalBmp.getPixels(pixels, 0, w, 0, 0, w, h);
     7  
     8 //调用Native方法获得处理过后的数组,转化为bitmap
     9 int[] resultInt = ImageProc.grayPoc(pixels, w, h);
    10 Bitmap mBuildedBmp = Bitmap.createBitmap(resultInt,w, h,mOriginalBmp.getConfig());
    11 mImageView.setImageBitmap(mBuildedBmp);
    12  
    13 //native方法定义
    14 public static native int[] grayPoc(int[] pixels,int w,int h);
    15  
    16 //native的实现,将图片转化为灰度图
    17 JNIEXPORT jintArray JNICALL Java_com_dengxy_opencvtest_ImageProc_grayPoc(
    18             JNIEnv * env, jclass obj, jintArray buf, int w, int h) {
    19         LOGD("Java_com_dengxy_opencvtest_ImageProc_grayPoc:start");
    20         jint *cbuf;
    21         cbuf = env->GetIntArrayElements(buf, JNI_FALSE);
    22  
    23         if (cbuf == NULL) {
    24  
    25             return 0;
    26  
    27         }
    28         Mat imgData(h, w, CV_8UC4, (unsigned char *) cbuf);
    29         uchar* ptr = imgData.ptr(0);
    30  
    31         for (int i = 0; i < w * h; i++) {
    32  
    33             int grayScale = (int) (ptr[4 * i + 2] * 0.299 + ptr[4 * i + 1] * 0.587 +
    34  
    35             ptr[4 * i + 0] * 0.114);
    36  
    37             ptr[4 * i + 1] = grayScale;
    38  
    39             ptr[4 * i + 2] = grayScale;
    40  
    41             ptr[4 * i + 0] = grayScale;
    42  
    43         }
    44         int size = w * h;
    45         jintArray result = env->NewIntArray(size);
    46         env->SetIntArrayRegion(result, 0, size, cbuf);
    47         env->ReleaseIntArrayElements(buf, cbuf, 0);
    48         LOGD("Java_com_dengxy_opencvtest_ImageProc_grayPoc:end");
    49         return result;
    50     }

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

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

     1 Bitmap mBuildedBmp = BitmapFactory.decodeResource(getResources(), R.drawable.test);
     2 ImageProc.getSobel(mBuildedBmp);
     3 mImageView.setImageBitmap(mBuildedBmp);
     4  
     5 //java接口函数
     6 private static native int getSobel(Bitmap in,Bitmap out);
     7  
     8 //对应的C++文件需要引入头文件 bitmap.h
     9 #include <android/bitmap.h>
    10  
    11  //对应C++函数
    12 JNIEXPORT void JNICALL Java_com_dengxy_opencvtest_ImageProc_getSobel(
    13         JNIEnv * env, jclass obj, jobject bmpIn) {
    14     AndroidBitmapInfo inBmpInfo;
    15     void* inPixelsAddress;
    16     int ret;
    17     if ((ret = AndroidBitmap_getInfo(env, bmpIn, &inBmpInfo)) < 0) {
    18         LOGD("AndroidBitmap_getInfo() failed ! error=%d", ret);
    19         return;
    20     }
    21     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);
    22     if ((ret = AndroidBitmap_lockPixels(env, bmpIn, &inPixelsAddress)) < 0) {
    23         LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
    24     }
    25     Mat inMat(inBmpInfo.height, inBmpInfo.width,
    26             CV_8UC4, inPixelsAddress);
    27     Sobel(inMat, inMat, inMat.depth(), 1, 1);
    28     AndroidBitmap_unlockPixels(env, bmpIn);
    29     LOGI("Return !! ");
    30     return;
    31  
    32 }

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

     1 //Java层代码
     2         Bitmap oldBmp mBuildedBmp = BitmapFactory.decodeResource(getResources(), R.drawable.test);
     3         Mat bmpMat = new Mat();
     4         Utils.bitmapToMat(mBuildedBmp, bmpMat);
     5         long resultAddress = -1;
     6         resultAddress = ImageProc.getLaplacian(bmpMat.getNativeObjAddr());
     7         Log.d(TAG, "doLaplacian:resultAddress="+resultAddress);        
     8         if(resultAddress<0){
     9             return ;
    10         }
    11         Mat resultLaplacianMat = new Mat(resultAddress);
    12         Utils.matToBitmap(resultLaplacianMat, mBuildedBmp);
    13         mImageView.setImageBitmap(mBuildedBmp);
    14  
    15         //jni接口
    16         public static native long getLaplacian(long bitmap);
    17  
    18         //c++实现
    19 JNIEXPORT jlong JNICALL Java_com_dengxy_opencvtest_ImageProc_getLaplacian
    20       (JNIEnv * env, jclass obj, jlong bmAddress){
    21         LOGD("Java_com_dengxy_opencvtest_ImageProc_getLaplacian:start");
    22         Mat *bitmpaMat = (Mat*) bmAddress;
    23         if (NULL == bitmpaMat) {
    24             LOGD("Java_com_dengxy_opencvtest_ImageProc_getLaplacian:the bitmpaMat is Null");
    25             return -1;
    26         }
    27         Laplacian(*bitmpaMat,*bitmpaMat,bitmpaMat->depth());
    28         jlong resultAddress = (jlong)bitmpaMat;
    29         LOGD("Java_com_dengxy_opencvtest_ImageProc_getLaplacian:end");
    30         return resultAddress;
    31     }

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

  • 相关阅读:
    思念
    空白
    curl json string with variable All In One
    virtual scroll list All In One
    corejs & RegExp error All In One
    socket.io All In One
    vue camelCase vs PascalCase vs kebabcase All In One
    element ui 表单校验,非必填字段校验 All In One
    github 定时任务 UTC 时间不准确 bug All In One
    input range & color picker All In One
  • 原文地址:https://www.cnblogs.com/twodog/p/12139030.html
Copyright © 2011-2022 走看看