Java与C++ 传递参数包括数据,字符串,基本数据类型

项目背景:某项目中需要Java调用底层C++写的算法,底层算法用的是opencv,算法那边提供的接口是传递一个opencv封装的Mat对象,返回的也是处理后的Mat对象,还有一些基本的配置参数,准备直接传图片路径,C++去读取图片转化为Mat,但是考虑到读取IO效率问题,最后决定Java传字节数组,C++接口做预处理转化为Mat对象,解析算法得到处理后的Mat对象,最后转化为base64返回给java后台,最后通过websocket把处理后的图片实时显示到前端页面*

java调用C++实例程序可以参考我上一篇博客

https://blog.csdn.net/kuaidi2883/article/details/107161039

1.Java类

package com.ainnovation.ai.business.jni;

import org.apache.commons.io.IOUtils;
import sun.misc.BASE64Decoder;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;

public class Surface {
	//初始参数
    private int x0;
    private int y0;
    private int x1;
    private int y1;
    private int ignore_x;
    private int ignore_y;

    private String result;

    public native String excute(byte[] image);
    static {
        System.load("D:\\C#Projects\\JniDemo\\JniDemo\\x64\\Debug\\JniDemo.dll");
    }
    static BASE64Decoder decoder = new sun.misc.BASE64Decoder();
    public static void main(String[] args) throws IOException {
        Surface surface = new Surface();
        surface.x0 = 0;
        surface.y0 = 300;
        surface.x1 = 1000;
        surface.y1 = 900;
        surface.ignore_x = 150;
        surface.ignore_y = 800;
		
		//1.获取图片字节流为从相机获取 这里方便演示直接读取本地图片
        File file = new File("C:\\Users\\Admin\\Desktop\\test.png");
        InputStream in = new FileInputStream(file);
        byte[] image = IOUtils.toByteArray(in);
        
        //2.运行dll动态链接库
        String base64Img = surface.excute(image);
		//3.获取图片base64直接通过websocket推送给前端实时显示处理结果,这里为演示保存图片
        byte[] bytes1 = decoder.decodeBuffer(base64Img);
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes1);
        BufferedImage bi1 = ImageIO.read(bais);
        File f1 = new File("d://out1.jpg");
        ImageIO.write(bi1, "jpg", f1);
    }
}

C++实现代码:

#include "com_ainnovation_ai_business_jni_Surface.h"
#include <iostream>
#include "cv.h"
#include "highgui.h"
#include "surface.h"
using namespace std;

//base64编码
std::string base64Encode(const unsigned char* Data, int DataByte) {
	//编码表
	const char EncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
	//返回值
	std::string strEncode;
	unsigned char Tmp[4] = { 0 };
	int LineLength = 0;
	for (int i = 0; i < (int)(DataByte / 3); i++) {
		Tmp[1] = *Data++;
		Tmp[2] = *Data++;
		Tmp[3] = *Data++;
		strEncode += EncodeTable[Tmp[1] >> 2];
		strEncode += EncodeTable[((Tmp[1] << 4) | (Tmp[2] >> 4)) & 0x3F];
		strEncode += EncodeTable[((Tmp[2] << 2) | (Tmp[3] >> 6)) & 0x3F];
		strEncode += EncodeTable[Tmp[3] & 0x3F];
		if (LineLength += 4, LineLength == 76) { strEncode += "\r\n"; LineLength = 0; }
	}
	//对剩余数据进行编码
	int Mod = DataByte % 3;
	if (Mod == 1) {
		Tmp[1] = *Data++;
		strEncode += EncodeTable[(Tmp[1] & 0xFC) >> 2];
		strEncode += EncodeTable[((Tmp[1] & 0x03) << 4)];
		strEncode += "==";
	}
	else if (Mod == 2) {
		Tmp[1] = *Data++;
		Tmp[2] = *Data++;
		strEncode += EncodeTable[(Tmp[1] & 0xFC) >> 2];
		strEncode += EncodeTable[((Tmp[1] & 0x03) << 4) | ((Tmp[2] & 0xF0) >> 4)];
		strEncode += EncodeTable[((Tmp[2] & 0x0F) << 2)];
		strEncode += "=";
	}


	return strEncode;
}

//imgType 包括png bmp jpg jpeg等opencv能够进行编码解码的文件
std::string Mat2Base64(const cv::Mat& img, std::string imgType) {
	//Mat转base64
	std::string img_data;
	std::vector<uchar> vecImg;
	std::vector<int> vecCompression_params;
	vecCompression_params.push_back(CV_IMWRITE_JPEG_QUALITY);
	vecCompression_params.push_back(90);
	imgType = "." + imgType;
	cv::imencode(imgType, img, vecImg, vecCompression_params);
	img_data = base64Encode1(vecImg.data(), vecImg.size());
	return img_data;
}

JNIEXPORT jstring JNICALL Java_com_ainnovation_ai_business_jni_Surface_excute
(JNIEnv *env, jobject obj, jbyteArray jbyteArra)
{

    try
    {  

		//1.获取java端传来的jbyteArray转化为opencv Mat
        //复制java数组到C++
        jsize len = env->GetArrayLength(jbyteArra);
        signed char* pData = new  signed char[len];
        env->GetByteArrayRegion(jbyteArra, 0, len, pData);
        //! 解码内存数据,变成cv::Mat数据
        cv::Mat img_decode;
        vector<uchar> data;
        for (int i = 0; i < len; ++i) {
            data.push_back(pData[i]);
        }
        img_decode = cv::imdecode(data, IMREAD_COLOR);


		//2.获取java端的成员变量数据x0,x1,y0,y1 传入算法获取运行结果
		jclass jclazz = env->GetObjectClass(obj);    //注释(1)
		jfieldID x0_id = env->GetFieldID(jclazz, "x0", "I");//注释(2)
		jint x0 = env->GetIntField(obj, x0_id);

		jfieldID y0_id = env->GetFieldID(jclazz, "y0", "I");//注释(2)
		jint y0 = env->GetIntField(obj, y0_id);

		jfieldID x1_id = env->GetFieldID(jclazz, "x1", "I");//注释(2)
		jint x1 = env->GetIntField(obj, x1_id);

		jfieldID y1_id = env->GetFieldID(jclazz, "y1", "I");//注释(2)
		jint y1 = env->GetIntField(obj, y1_id);

		jfieldID ignore_x_id = env->GetFieldID(jclazz, "ignore_x", "I");//注释(2)
		jint ignore_x = env->GetIntField(obj, ignore_x_id);

		jfieldID ignore_y_id = env->GetFieldID(jclazz, "ignore_y", "I");//注释(2)
		jint ignore_y = env->GetIntField(obj, ignore_y_id);

        vector<int> cut_box = { x0,y0,x1,y1}; // {x0, y0, x1, y1}
        vector<int> ignore_area = { ignore_x,ignore_y};

		//3.调用底层算法将返回的mat类型转化为base64并返回给java服务器端
        Mat image = surface(img_decode, cut_box, ignore_area);
        std::string str = Mat2Base641(image, "jpg");
        char* data1;
        int len1 = str.length();
        data1 = (char*)malloc((len1 + 1) * sizeof(char));
        str.copy(data1, len1, 0);
        jstring rtstr = env->NewStringUTF(data1);

		//4.获取java端成员变量 并赋值最后运行结果
		jfieldID result_id = env->GetFieldID(jclazz, "result", "Ljava/lang/String;");
		env->SetObjectField(obj, result_id, env->NewStringUTF("ng"));
        return rtstr;
    }
    catch (exception e) {
        cerr << "发生错误:" << e.what();
    }

}

运行结果

D盘下面生成了处理后的图片
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值