最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java調用C++動態(tài)庫DLL實現(xiàn)圖像處理

 更新時間:2025年09月17日 08:35:58   作者:頗有幾分姿色  
這篇文章主要為大家詳細介紹了Java如何調用C++動態(tài)庫DLL實現(xiàn)有圖像有實體處理,文中的示例代碼講解詳細,感興趣的小伙伴可以了解下

前言

相關:Java 調用 C++ 動態(tài)庫(DLL)完整實踐:無圖像無實體處理場景

這里主要介紹如何通過 JNI(Java Native Interface)在 Java 中調用一個用 C++ 編寫的校色算法庫。不涉及圖像和 java 實體處理。環(huán)境如下:

  • 系統(tǒng):Windows 10
  • JDK:1.8
  • IDE:Visual Studio 2022
  • Java 構建工具:Maven
  • 目標平臺:x64

一、整體目標

Java 端通過 JNI 調用算法提供的動態(tài)庫,實現(xiàn)圖像缺色偏色檢測功能。為了方便,我把所有的依賴庫都放在了 jdk 的 bin 目錄,這樣我在調用的時候只需要導入我的自己生成的 jni 庫就可以,如果需要頻繁切換 jdk,那建議自己配置 java.library.path 或將依賴庫放到獨立目錄中 ,處理好動態(tài)庫的依賴關系即可。

二、準備工作

1. C++ 頭文件(API 定義)

這是算法的頭文件,jni 層需要根據(jù)他的方法調用即可。建議和 java 的方法保持一致,不保持一致也可以,自己在 jni 層處理好就可以。

頭文件方法定義:

 //  版本號
 COLORCAST_API int ColorCastGetVersion(char* pOutBuf, int nOutBufSize);

 COLORCAST_API ColorCastResults analyzeImageColorCast(
     unsigned char* pData, int pw, int ph, int pchannels,
     double skin_ratio_threshold = 0.1, double C_threshold = 20.0,
     double Red_threshold = 18.0, double Green_threshold = 5.0,
     double Yellow_threshold = 30.0, double Blue_threshold = 5.0,
     double face_threshold = 0.5);

 COLORCAST_API ContrastColorCastResults contrastImageColorCast(
     unsigned char* tData, int tw, int th, int tchannels,
     unsigned char* pData, int pw, int ph, int pchannels,
     int YCrCb_cbmax = 125,
     int ROIwidthDiv = 6,
     int ROIheightDiv = 100,
     double USwidthRatio = 0.5,
     double USheightRatio = 0.01
 );

結構頭文件:

// 偏色對比結果(雙圖比對)
struct ContrastColorCastResults {

    // 紅色比對色偏指數(shù)
    double Red_Contrast = 999;
    // 綠色比對色偏指數(shù)
    double Green_Contrast = 999;
    // 黃色比對色偏指數(shù)
    double Yellow_Contrast = 999;
    // 藍色比對色偏指數(shù)
    double Blue_Contrast = 999;
    // ROI偏色占比
    double ColorCast_ratio = 999;
};

2. Java 接口類定義

這里示例圖像的三種傳輸方式:

  • Java 層將圖像轉換為 BGR 格式的 byte[],直接傳給 JNI;
  • Java 層傳原始圖像數(shù)據(jù),JNI 使用 OpenCV 解碼;
  • Java 層傳遞文件路徑,JNI 自行讀取文件內容。
package com.emp.empxmrz.util;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

/***
 * @title
 * @author shijiangyong
 * @date 2025/8/27 11:23
 **/
public class ColorCastDetExampleJni {
    static {
        System.loadLibrary("ColorCastDetExampleJni");
    }

    // 獲取版本號
    public static native int getVersion(byte[] buffer, int bufSize);

    // 對比圖偏色檢測
    // 傳圖片數(shù)據(jù),處理成BGR格式
    public static native ColorCastDetExampleJni.ContrastColorCastResults contrastImageColorCast(
            byte[] tData, int tw, int th, int tchannels,
            byte[] photoData, int pw, int ph, int pchannels,
            int yCrCbCbmax, int roiWidthDiv, int roiHeightDiv,
            double usWidthRatio, double usHeightRatio
    );

    // 傳原圖片數(shù)據(jù),不轉格式
    public static native ColorCastDetExampleJni.ContrastColorCastResults contrastImageColorCastOri(
            byte[] tData,
            byte[] photoData,
            int yCrCbCbmax, int roiWidthDiv, int roiHeightDiv,
            double usWidthRatio, double usHeightRatio
    );

    // 傳圖片本地路徑
    public static native ColorCastDetExampleJni.ContrastColorCastResults contrastImageColorCastByPath(
            String tData,
            String photoData,
            int yCrCbCbmax, int roiWidthDiv, int roiHeightDiv,
            double usWidthRatio, double usHeightRatio
    );

    @Data
    public static class ContrastColorCastResults {
        @Schema(description = "紅色比對偏色指數(shù)")
        public double redContrast;

        @Schema(description = "綠色比對偏色指數(shù)")
        public double greenContrast;

        @Schema(description = "黃色比對偏色指數(shù)")
        public double yellowContrast;

        @Schema(description = "藍色比對偏色指數(shù)")
        public double blueContrast;

        @Schema(description = "ROI區(qū)域偏色占比")
        public double colorCastRatio;
    }
}

三、生成 JNI 頭文件

javah -classpath target/classes -d src/main/jni com.emp.empxmrz.util.ColorCastDetExampleJni

這會生成 com_emp_empxmrz_util_ColorCastDetExampleJni.h 和 com_emp_empxmrz_util_ColorCastDetExampleJni_ContrastColorCastResults.h,它定義了 JNI 接口供 C++ 實現(xiàn)。生成之后不能隨便移動類的位置或修改包名、類名等,如果必須調整的話,需要重新生成。

生成的頭文件大概如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_emp_empxmrz_util_ColorCastDetExampleJni */

#ifndef _Included_com_emp_empxmrz_util_ColorCastDetExampleJni
#define _Included_com_emp_empxmrz_util_ColorCastDetExampleJni
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_emp_empxmrz_util_ColorCastDetExampleJni
 * Method:    getVersion
 * Signature: ([BI)I
 */
JNIEXPORT jint JNICALL Java_com_emp_empxmrz_util_ColorCastDetExampleJni_getVersion
  (JNIEnv *, jclass, jbyteArray, jint);

/*
 * Class:     com_emp_empxmrz_util_ColorCastDetExampleJni
 * Method:    contrastImageColorCast
 * Signature: ([BIII[BIIIIIIDD)Lcom/emp/empxmrz/util/ColorCastDetExampleJni/ContrastColorCastResults;
 */
JNIEXPORT jobject JNICALL Java_com_emp_empxmrz_util_ColorCastDetExampleJni_contrastImageColorCast
  (JNIEnv *, jclass, jbyteArray, jint, jint, jint, jbyteArray, jint, jint, jint, jint, jint, jint, jdouble, jdouble);

/*
 * Class:     com_emp_empxmrz_util_ColorCastDetExampleJni
 * Method:    contrastImageColorCastOri
 * Signature: ([B[BIIIDD)Lcom/emp/empxmrz/util/ColorCastDetExampleJni/ContrastColorCastResults;
 */
JNIEXPORT jobject JNICALL Java_com_emp_empxmrz_util_ColorCastDetExampleJni_contrastImageColorCastOri
  (JNIEnv *, jclass, jbyteArray, jbyteArray, jint, jint, jint, jdouble, jdouble);

/*
 * Class:     com_emp_empxmrz_util_ColorCastDetExampleJni
 * Method:    contrastImageColorCastByPath
 * Signature: (Ljava/lang/String;Ljava/lang/String;IIIDD)Lcom/emp/empxmrz/util/ColorCastDetExampleJni/ContrastColorCastResults;
 */
JNIEXPORT jobject JNICALL Java_com_emp_empxmrz_util_ColorCastDetExampleJni_contrastImageColorCastByPath
  (JNIEnv *, jclass, jstring, jstring, jint, jint, jint, jdouble, jdouble);

#ifdef __cplusplus
}
#endif
#endif

四、JNI 實現(xiàn)(C++)

這是 jni 的頭文件實現(xiàn),因為我是要調用多個算法,所以使用 vs 創(chuàng)建了一個解決方案,里面創(chuàng)建了多個項目,每個項目都是一種算法的 jni 層,根據(jù)自己的實際情況操作就可以,實現(xiàn)類中需要包含算法頭文件和 jni 頭文件,java實體的頭文件不用添加。項目結構大致如下:

cpp 完整代碼如下:

#include "ColorCast.h"
#include "com_emp_empxmrz_util_ColorCastDetExampleJni.h"

#include <iostream>
#include <stdexcept>
#include <string>
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>

void native_log(const std::string& message) {
    std::cerr << "[NativeLog] " << message << std::endl;
}

void throwJavaException(JNIEnv* env, const char* message) {
    jclass exceptionCls = env->FindClass("java/lang/RuntimeException");
    if (exceptionCls != nullptr) {
        env->ThrowNew(exceptionCls, message);
    }
}

void throwIllegalArgument(JNIEnv* env, const char* message) {
    jclass exClass = env->FindClass("java/lang/IllegalArgumentException");
    if (exClass != nullptr) {
        env->ThrowNew(exClass, message);
    }
}

JNIEXPORT jint JNICALL Java_com_emp_empxmrz_util_ColorCastDetExampleJni_getVersion(JNIEnv* env, jobject obj, jbyteArray buffer, jint bufSize) {
    try {
        jboolean isCopy = JNI_FALSE;
        jbyte* bufPtr = env->GetByteArrayElements(buffer, &isCopy);
        if (bufPtr == nullptr) {
            throwJavaException(env, "Failed to get buffer pointer");
            return 0;
        }

        // 寫入版本號
        int len = ColorCastGetVersion(reinterpret_cast<char*>(bufPtr), static_cast<int>(bufSize));

        // 寫成功,手動同步數(shù)據(jù)回 Java
        env->ReleaseByteArrayElements(buffer, bufPtr, 0);

        return len; 
    }
    catch (const std::exception& e) {
        native_log(e.what());
        throwJavaException(env, e.what());
        return 0;
    }
}


// 構造 ContrastColorCastResults Java 對象
jobject createContrastColorCastResults(JNIEnv* env, const ContrastColorCastResults& result) {
    jclass cls = env->FindClass("com/emp/empxmrz/util/ColorCastDetJni$ContrastColorCastResults");
    if (cls == nullptr) {
        throwJavaException(env, "Failed to find ContrastColorCastResults class");
        return nullptr;
    }
    jmethodID constructor = env->GetMethodID(cls, "<init>", "()V");
    if (constructor == nullptr) {
        throwJavaException(env, "Failed to get constructor for ContrastColorCastResults");
        return nullptr;
    }
    jobject obj = env->NewObject(cls, constructor);

    env->SetDoubleField(obj, env->GetFieldID(cls, "redContrast", "D"), result.Red_Contrast);
    env->SetDoubleField(obj, env->GetFieldID(cls, "greenContrast", "D"), result.Green_Contrast);
    env->SetDoubleField(obj, env->GetFieldID(cls, "yellowContrast", "D"), result.Yellow_Contrast);
    env->SetDoubleField(obj, env->GetFieldID(cls, "blueContrast", "D"), result.Blue_Contrast);
    env->SetDoubleField(obj, env->GetFieldID(cls, "colorCastRatio", "D"), result.ColorCast_ratio);

    return obj;
}




JNIEXPORT jobject JNICALL Java_com_emp_empxmrz_util_ColorCastDetExampleJni_contrastImageColorCast
(JNIEnv* env, jobject obj,
    jbyteArray templateData, jint tw, jint th, jint tchannels,
    jbyteArray photoData, jint pw, jint ph, jint pchannels,
    jint cbmax, jint roiWidthDiv, jint roiHeightDiv,
    jdouble usWidthRatio, jdouble usHeightRatio) {
    try {
        jbyte* tData = env->GetByteArrayElements(templateData, nullptr);
        jbyte* pData = env->GetByteArrayElements(photoData, nullptr);

        ContrastColorCastResults result = contrastImageColorCast(
            reinterpret_cast<unsigned char*>(tData), tw, th, tchannels,
            reinterpret_cast<unsigned char*>(pData), pw, ph, pchannels,
            cbmax, roiWidthDiv, roiHeightDiv, usWidthRatio, usHeightRatio
        );

        env->ReleaseByteArrayElements(templateData, tData, 0);
        env->ReleaseByteArrayElements(photoData, pData, 0);

        // 將 ContrastColorCastResults 映射到 Java 對象
        return createContrastColorCastResults(env, result);

    }
    catch (const std::exception& e) {
        native_log(e.what());
        throwJavaException(env, e.what());
        return nullptr;
    }
}

JNIEXPORT jobject JNICALL Java_com_emp_empxmrz_util_ColorCastDetExampleJni_contrastImageColorCastOri
(JNIEnv* env, jobject obj,
    jbyteArray templateData, jbyteArray photoData,
    jint cbmax, jint roiWidthDiv, jint roiHeightDiv,
    jdouble usWidthRatio, jdouble usHeightRatio) {
    try {
        if (templateData == nullptr) {
            throwIllegalArgument(env,"templateData is null");
            return nullptr;
        }

        if (photoData == nullptr) {
            throwIllegalArgument(env, "photoData is null");
            return nullptr;
        }

        jsize tempLen = env->GetArrayLength(templateData);
        if (tempLen <= 0) {
            throwIllegalArgument(env, "templateData is null");
            return nullptr;
        }

        jsize photoLen = env->GetArrayLength(photoData);
        if (photoLen <= 0) {
            throwIllegalArgument(env, "photoData is null");
            return nullptr;
        }

        // Zero-copy: 獲取 JVM 中的數(shù)據(jù)指針(映射)
        jbyte* tData = env->GetByteArrayElements(templateData, nullptr);
        if (tData == nullptr) {
            throwJavaException(env, "templateData Failed to get byte array elements");
            return nullptr;
        }

        // Zero-copy: 獲取 JVM 中的數(shù)據(jù)指針(映射)
        jbyte* pData = env->GetByteArrayElements(photoData, nullptr);
        if (pData == nullptr) {
            throwJavaException(env, "photoData Failed to get byte array elements");
            return nullptr;
        }
        // 原圖
        // 構造一個 OpenCV Mat 來包裝 byte[] 數(shù)據(jù)(不復制)
        cv::Mat tBuf(1, tempLen, CV_8UC1, reinterpret_cast<uchar*>(tData));
        // 解碼為圖像
        cv::Mat tImage = cv::imdecode(tBuf, cv::IMREAD_UNCHANGED);
        
        if (tImage.empty()) {
            env->ReleaseByteArrayElements(photoData, pData, JNI_ABORT);
            throwJavaException(env, "templateData Failed to decode image");
            return nullptr;
        }
        // 目標圖
        cv::Mat pBuf(1, photoLen, CV_8UC1, reinterpret_cast<uchar*>(pData));
        cv::Mat pImage = cv::imdecode(pBuf, cv::IMREAD_UNCHANGED);
        
        if (pImage.empty()) {
            env->ReleaseByteArrayElements(templateData, tData, JNI_ABORT);
            throwJavaException(env, "photoData Failed to decode image");
            return nullptr;
        }

        ContrastColorCastResults result = contrastImageColorCast(
            reinterpret_cast<unsigned char*>(tImage.data), tImage.cols, tImage.rows, tImage.channels(),
            reinterpret_cast<unsigned char*>(pImage.data), pImage.cols, pImage.rows, pImage.channels(),
            cbmax, roiWidthDiv, roiHeightDiv, usWidthRatio, usHeightRatio
        );

        // 釋放映射,不拷貝回 Java(JNI_ABORT)
        env->ReleaseByteArrayElements(templateData, tData, JNI_ABORT);
        env->ReleaseByteArrayElements(photoData, pData, JNI_ABORT);
        // 將 ContrastColorCastResults 映射到 Java 對象
        return createContrastColorCastResults(env, result);

    }
    catch (const std::exception& e) {
        native_log(e.what());
        throwJavaException(env, e.what());
        return nullptr;
    }
}

JNIEXPORT jobject JNICALL Java_com_emp_empxmrz_util_ColorCastDetExampleJni_contrastImageColorCastByPath
(JNIEnv* env, jobject obj,
    jstring templateData,  jstring photoData, 
    jint cbmax, jint roiWidthDiv, jint roiHeightDiv,
    jdouble usWidthRatio, jdouble usHeightRatio) {
    try {
        const char* tImagePath = env->GetStringUTFChars(templateData, nullptr);
        const char* pImagePath = env->GetStringUTFChars(photoData, nullptr);
        // 直接用 OpenCV 讀取圖像
        cv::Mat tImage = cv::imread(tImagePath);
        if (tImage.empty()) {
            env->ReleaseStringUTFChars(templateData, tImagePath); // 釋放資源
            env->ReleaseStringUTFChars(photoData, pImagePath);
            throwJavaException(env, "Failed to load templateData");
            return nullptr;
        }

        cv::Mat pImage = cv::imread(pImagePath);
        if (pImage.empty()) {
            env->ReleaseStringUTFChars(templateData, tImagePath); // 釋放資源
            env->ReleaseStringUTFChars(photoData, pImagePath);
            throwJavaException(env, "Failed to load photoData");
            return nullptr;
        }

        ContrastColorCastResults result = contrastImageColorCast(
            reinterpret_cast<unsigned char*>(tImage.data), tImage.cols, tImage.rows, tImage.channels(),
            reinterpret_cast<unsigned char*>(pImage.data), pImage.cols, pImage.rows, pImage.channels(),
            cbmax, roiWidthDiv, roiHeightDiv, usWidthRatio, usHeightRatio
        );

        env->ReleaseStringUTFChars(templateData, tImagePath);
        env->ReleaseStringUTFChars(photoData, pImagePath);

        // 將 ContrastColorCastResults 映射到 Java 對象
        return createContrastColorCastResults(env, result);

    }
    catch (const std::exception& e) {
        native_log(e.what());
        throwJavaException(env, e.what());
        return nullptr;
    }
}

建議添加異常處理,避免JVM 崩潰,注意資源的釋放。

五、Visual Studio 配置

1. 添加包含目錄

打開【項目屬性】 > C/C++ > 常規(guī) > 附加包含目錄

防止編譯階段報錯。

2. 添加庫目錄

打開【鏈接器】 > 常規(guī) > 附加庫目錄

3. 添加依賴庫

打開【鏈接器】 > 輸入 > 附加依賴項

告訴編譯器如何調用 .dll 中的函數(shù); 出現(xiàn) JNI 方法未導出錯誤,可添加 .def 文件顯式指定導出符號 ,內容如下,其實就是 jni 頭文件方法:

LIBRARY ColorCastDetExampleJni
EXPORTS
    Java_com_emp_empxmrz_util_ColorCastDetExampleJni_getVersion
	Java_com_emp_empxmrz_util_ColorCastDetExampleJni_contrastImageColorCast
    Java_com_emp_empxmrz_util_ColorCastDetExampleJni_contrastImageColorCastOri
	Java_com_emp_empxmrz_util_ColorCastDetExampleJni_contrastImageColorCastByPath

4.生成 DLL

編譯后會生成 ColorCastDetExampleJni.dllColorCastDetExampleJni.lib,將他們復制到 jdk 的 bin 目錄或者你自己定義的目錄下, java 就可以直接調用 ColorCastDetExampleJni了。

六、Java 調用測試

工具類 CustomImgUtilsImageProcessor在這篇文章里,Java 圖像處理傳 JNI 到 C++(OpenCV):兩種高效實現(xiàn)方式對比
java 測試結果是否正確,也可以自己封裝成接口。

service 層:

package com.emp.empxmrz.service;

import com.emp.empxmrz.controller.vo.ColorCastDetExampleReq;
import com.emp.empxmrz.util.ColorCastDetExampleJni;
import com.emp.empxmrz.util.CustomImgUtils;
import com.emp.empxmrz.util.ImageProcessor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;

/***
 * @title
 * @author shijiangyong
 * @date 2025/9/15 10:17
 **/
@Slf4j
@Service
public class ColorCastDetExampleJniServiceImpl implements ColorCastDetExampleJniService{

    @Override
    public String getVersion() {
        byte[] versionBuffer = new byte[12];
        int result = ColorCastDetExampleJni.getVersion(versionBuffer, versionBuffer.length);
        String version = "獲取版本號失敗";
        if (result == 0) {
            version = new String(versionBuffer, StandardCharsets.UTF_8).trim();
            log.info("Algorithm model version number: {}", version);
        } else {

            log.warn("Failed to get version number: {} ", result);
        }
        return version;
    }

    @Override
    public ColorCastDetExampleJni.ContrastColorCastResults contrastImageColorCast(ColorCastDetExampleReq req) {
        MultipartFile sourceFile = req.getSourceFile();
        if (sourceFile == null || sourceFile.isEmpty()) {
            throw new IllegalArgumentException("Source file is null or empty");
        }
        MultipartFile targetFile = req.getTargetFile();
        if (targetFile == null || targetFile.isEmpty()) {
            throw new IllegalArgumentException("Target file is null or empty");
        }

        try {
            byte[] sourceBytes = ImageProcessor.inputStreamToByteArray(sourceFile.getInputStream());
            BufferedImage sourceImage = ImageIO.read(new ByteArrayInputStream(sourceBytes));
            if (sourceImage == null) {
                throw new RuntimeException("圖像讀取失敗");
            }
            byte[] targetBytes = ImageProcessor.inputStreamToByteArray(targetFile.getInputStream());
            BufferedImage targetImage = ImageIO.read(new ByteArrayInputStream(targetBytes));
            if (targetImage == null) {
                throw new RuntimeException("圖像讀取失敗");
            }
            byte[] sourceMatrixBGR = CustomImgUtils.getMatrixBGR(sourceImage);
            byte[] targetMatrixBGR = CustomImgUtils.getMatrixBGR(targetImage);
            return ColorCastDetExampleJni.contrastImageColorCast(sourceMatrixBGR, sourceImage.getWidth(), sourceImage.getHeight(), sourceImage.getColorModel().getNumColorComponents(),
                    targetMatrixBGR, targetImage.getWidth(), targetImage.getHeight(), targetImage.getColorModel().getNumColorComponents(),
                    req.getYCrCbCbmax(), req.getRoiWidthDiv(), req.getRoiHeightDiv(), req.getUsWidthRatio(), req.getUsHeightRatio());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public ColorCastDetExampleJni.ContrastColorCastResults contrastImageColorCastOri(ColorCastDetExampleReq req) {
        String sourceFileUrl = req.getSourceFileUrl();
        if (sourceFileUrl == null || sourceFileUrl.isEmpty()) {
            throw new IllegalArgumentException("Source file url is null or empty");
        }
        String targetFileUrl = req.getTargetFileUrl();
        if (targetFileUrl == null || targetFileUrl.isEmpty()) {
            throw new IllegalArgumentException("Target file url is null or empty");
        }
        try {
            byte[] sourceMatrixBGR = this.getImageBytes(sourceFileUrl);
            byte[] targetMatrixBGR = this.getImageBytes(targetFileUrl);
            return ColorCastDetExampleJni.contrastImageColorCastOri(sourceMatrixBGR, targetMatrixBGR,
                    req.getYCrCbCbmax(), req.getRoiWidthDiv(), req.getRoiHeightDiv(), req.getUsWidthRatio(), req.getUsHeightRatio());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public ColorCastDetExampleJni.ContrastColorCastResults contrastImageColorCastByPath(ColorCastDetExampleReq req) {
        String sourceFileUrl = "E:\\test\\CertifHaed.jpg";
        String targetFileUrl = "E:\\test\\face_big_homepage.jpg";
        return ColorCastDetExampleJni.contrastImageColorCastByPath(sourceFileUrl,targetFileUrl,req.getYCrCbCbmax(), req.getRoiWidthDiv(),
                req.getRoiHeightDiv(), req.getUsWidthRatio(), req.getUsHeightRatio());
    }

    /**
     * http流轉BufferedImage
     * @param req
     * @return
     * @throws IOException
     */
    private BufferedImage getBufferedImage(String req) throws IOException {
        URL url = new URL(req);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setConnectTimeout(5000);
        conn.setReadTimeout(10000);
        return ImageIO.read(conn.getInputStream());
    }

    /**
     * http流轉Byte[]
     * @param req
     * @return
     * @throws IOException
     */
    private byte[] getImageBytes(String req) throws IOException {
        URL url = new URL(req);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setConnectTimeout(5000);
        conn.setReadTimeout(10000);

        try (InputStream inputStream = conn.getInputStream()) {
            return ImageProcessor.inputStreamToByteArray(inputStream);
        }
    }
}

controller 層:

package com.emp.empxmrz.controller;

import com.emp.empxmrz.controller.vo.ColorCastDetExampleReq;
import com.emp.empxmrz.service.ColorCastDetExampleJniService;
import com.emp.empxmrz.util.ColorCastDetExampleJni;
import com.emp.empxmrz.util.R;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/***
 * @title
 * @author shijiangyong
 * @date 2025/9/15 10:47
 **/
@Slf4j
@RestController
@AllArgsConstructor
@Tag(name = "demo示例")
@RequestMapping("/example")
public class ColorCastDetExampleJniController {

    private final ColorCastDetExampleJniService colorCastDetExampleJniService;

    @PostMapping("/getVersion")
    @Operation(summary = "管理后臺-獲取算法版本")
    public R<String> getVersion() {
        return R.ok(colorCastDetExampleJniService.getVersion());
    }


    @PostMapping("/contrast/color/castDet")
    @Operation(summary = "管理后臺-偏色檢測算法")
    public R<ColorCastDetExampleJni.ContrastColorCastResults> contrastImageColorCast(ColorCastDetExampleReq req) {
        return R.ok(colorCastDetExampleJniService.contrastImageColorCast(req));
    }

    @PostMapping("/contrast/color/castDetOri")
    @Operation(summary = "管理后臺-偏色檢測算法")
    public R<ColorCastDetExampleJni.ContrastColorCastResults> contrastImageColorCastOri(ColorCastDetExampleReq req) {
        return R.ok(colorCastDetExampleJniService.contrastImageColorCastOri(req));
    }

    @PostMapping("/contrast/color/castDetByPath")
    @Operation(summary = "管理后臺-偏色檢測算法")
    public R<ColorCastDetExampleJni.ContrastColorCastResults> contrastImageColorCastByPath(ColorCastDetExampleReq req) {
        return R.ok(colorCastDetExampleJniService.contrastImageColorCastByPath(req));
    }
}

調用示例:

路徑去掉 Ori 就是測試上面兩個入?yún)?,加?Ori 就是測試下面兩個入?yún)?,反正到?java 層,就自己隨便玩了。實體類就不貼了。

調試建議

如果報錯找不到 ColorCastDetExampleJni.dll,請將該 DLL 放入:

  • 項目運行目錄;
  • 或者 jdk/bin 目錄;
  • 或者設置 -Djava.library.path。

如果 JNI 函數(shù)名對應不上,請確保:

  • 包名、類名、方法名匹配;
  • DLL 導出的函數(shù)使用 extern "C"
  • JNI 方法未正確導出,可通過.def文件顯式指定導出符號。

七、總結

  • 編寫 Java native 接口;
  • 使用 javah 生成 JNI 頭文件;
  • C++ 實現(xiàn) JNI 方法;
  • 配置 Visual Studio 編譯動態(tài)庫;
  • Java 調用測試。

如果你不想污染自己的JDK bin,可以將 .dll.lib 放到一個統(tǒng)一的目錄下,這樣的話切換 jdk 比較方便,因為我只使用 jdk8,所以貪圖方便放在了 bin 目錄,但這是不規(guī)范滴 。

到此這篇關于Java調用C++動態(tài)庫DLL實現(xiàn)圖像處理的文章就介紹到這了,更多相關Java調用DLL實現(xiàn)圖像處理內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Logback 使用TurboFilter實現(xiàn)日志級別等內容的動態(tài)修改操作

    Logback 使用TurboFilter實現(xiàn)日志級別等內容的動態(tài)修改操作

    這篇文章主要介紹了Logback 使用TurboFilter實現(xiàn)日志級別等內容的動態(tài)修改操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • SpringBoot測試之高級配置方式

    SpringBoot測試之高級配置方式

    這篇文章主要介紹了SpringBoot測試之高級配置方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • 從基礎轉換與高級設置詳解Java中PDF轉換為Excel的完整指南

    從基礎轉換與高級設置詳解Java中PDF轉換為Excel的完整指南

    將 PDF 轉換為 Excel 是一個常見需求,本文將展示如何使用 Java 將 PDF 文件轉換為 Excel,并提供自定義設置以優(yōu)化復雜 PDF 的轉換效果,感興趣的小伙伴了解一下
    2026-03-03
  • 通過java備份恢復mysql數(shù)據(jù)庫的實現(xiàn)代碼

    通過java備份恢復mysql數(shù)據(jù)庫的實現(xiàn)代碼

    這篇文章主要介紹了如何通過java備份恢復mysql數(shù)據(jù)庫,其實一般情況下通過bat或sh就可以,這里主要是介紹了java的實現(xiàn)思路,喜歡的朋友可以參考下
    2013-09-09
  • Java動態(tài)添加Scheduled的實現(xiàn)方式

    Java動態(tài)添加Scheduled的實現(xiàn)方式

    在Java中,動態(tài)添加??Scheduled???定時任務可以通過多種方式實現(xiàn),其中最常見的是使用Spring框架提供的??@Scheduled???注解結合??SchedulingConfigurer???接口,下面將詳細介紹如何在Spring環(huán)境中動態(tài)地添加、修改和取消定時任務,需要的朋友可以參考下
    2025-10-10
  • nexus私服啟動不了問題及解決

    nexus私服啟動不了問題及解決

    這篇文章主要介紹了nexus私服啟動不了問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • Java開發(fā)中最讓人頭疼的十個bug

    Java開發(fā)中最讓人頭疼的十個bug

    這篇文章主要給大家總結介紹了關于Java開發(fā)中最讓人頭疼的十個bug,同樣的bug信息,可能背后有千萬種原因,而我,永遠都不知道到底是哪一個,努力通過代碼積累盡可能多的bug,并將它們進行分類,可以幫你debug節(jié)省了時間,需要的朋友可以參考下
    2021-10-10
  • java Socket實現(xiàn)多人群聊與私聊功能

    java Socket實現(xiàn)多人群聊與私聊功能

    這篇文章主要為大家詳細介紹了java Socket實現(xiàn)多人群聊與私聊功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • 詳解MyBatis XML配置解析

    詳解MyBatis XML配置解析

    這篇文章主要介紹了詳解MyBatis XML配置解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-09-09
  • Java SimpleDateFormat中英文時間格式化轉換詳解

    Java SimpleDateFormat中英文時間格式化轉換詳解

    這篇文章主要為大家詳細介紹了Java SimpleDateFormat中英文時間格式化轉換,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-12-12

最新評論

北流市| 遵义市| 五常市| 涡阳县| 惠东县| 桐梓县| 永济市| 申扎县| 大港区| 库伦旗| 开鲁县| 县级市| 兴化市| 新巴尔虎右旗| 利辛县| 云林县| 五台县| 耒阳市| 忻城县| 天长市| 清河县| 卢龙县| 湛江市| 杭锦旗| 沙洋县| 汾西县| 浮山县| 浙江省| 金寨县| 罗山县| 乌鲁木齐市| 惠来县| 三都| 清镇市| 吴桥县| 张家口市| 潞城市| 清水河县| 苏尼特左旗| 高邮市| 淮安市|