macOS 为 Compose Desktop 构建跨平台图像库:OpenCV + libraw + libheif 实践

一. 前言:为什么你需要自己构建图像处理 .dylib

我正在开发一款桌面端的图像编辑器 Monica(https://github.com/fengzhizi715/Monica),它使用的 UI 框架是 Compose Desktop。

在 Compose Desktop 中开发图像处理应用,往往意味着需要同时兼顾跨平台体验与图像处理性能。虽然 Kotlin 提供了丰富的 UI 构建能力,但在涉及图像编解码(如 HEIF)、图像分析(如 OpenCV)甚至 RAW 文件读取时,Java 层本身的能力极为有限,依赖的第三方库要么过于老旧,要么功能单一,性能表现也不尽如人意。

相比之下,C++ 在图像处理领域已经拥有成熟的生态:OpenCV 提供了全面的计算机视觉能力,libraw 支持绝大多数相机 RAW 文件格式,而 libheif 则是处理 HEIC/HEIF 图像的事实标准。这些库本身稳定且高效,但问题在于:它们并非为 Kotlin 或 Java 生态设计,也无法直接在 Compose Desktop 项目中使用。

我尝试过通过 JNI 来调用这些 C++ 库,但很快就会陷入一系列 macOS 特有的问题:

  • 动态库路径错乱(@rpath、@loader_path 混用)

  • 系统架构不一致(Apple Silicon 与 Intel 的 ABI 差异)

  • Homebrew 依赖冲突

  • 打包后 .dylib 丢失等等。

这些都让简单的图像处理功能变得异常复杂,甚至直接影响了应用的可部署性。

另外,macOS 并没有像 Linux 那样统一的包管理方式可以在所有用户机器上复用 .so 文件,因此最终必须将所需的 .dylib 一并打包。也正因如此,构建一个跨架构、自包含、免安装的图像处理 dylib 成为了解决 Compose Desktop 图像处理问题的关键。本文从源码编译 OpenCV、libheif ,结合 CMake 构建 JNI 接口,并修复所有动态库引用,最终得到一个可以直接部署的图像处理模块。

二. 图像处理库的架构概览

在我的图像编辑器 Monica 中,很多核心的图像处理逻辑都是用 OpenCV C++ 实现的,所以我单独创建了一个项目 https://github.com/fengzhizi715/MonicaImageProcess

它用于实现图像的参数调整(对比度、色调、饱和度、亮度、色温、高光、阴影)、快速验证 OpenCV 算法(如各种滤波、图形增强、形态学操作、模板匹配等)、加载相机 RAW 文件、HEIC 图像等等。

图像处理库.png
图像处理库.png

其项目目录结构如下:

MonicaImageProcess/
├── README.md                        # 项目简介
├── LICENSE                          # 项目许可证文件
├── CMakeLists.txt                   # CMake构建脚本(主)
├── include/                         # 项目公共头文件目录
│   ├── colorcorrection/             # 图像调色相关算法模块的头文件目录
│   ├── matchTemplate/               # 模版匹配的头文件目录
│   └── utils/                       # 工具类模块的头文件目录
├── jni/                             # 给 Java/Kotlin 调用的本地算法
│   ├── cn_netdiscovery_monica_opencv_ImageProcess.h   # jni 对应用层暴露接口的头文件
│   └── cn_netdiscovery_monica_opencv_ImageProcess.cpp # jni 对应用层暴露接口的源文件
├── script/                          # 构建脚本
│   ├── build_libheif_deps.sh        # 从源码编译 libheif 及其依赖的库
│   ├── build_opencv_world_4100.sh   # 从源码编译 opencv 库,包含了 contrib
│   └── fix_dylib_dependencies.sh    # macOS 下修复主库引用 opencv 的路径
├── src/                             # 项目主源代码目录
│   └── colorcorrection/             # 图像调色相关算法模块
│       └── ColorCorrection.cpp      # 图像调色相关算法的源文件
│   └── matchTemplate/               # 模版匹配模块
│       └── MatchTemplate.cpp        # 模版匹配相关算法的源文件
│   ├── utils/                       # 工具类模块
│   ├── CMakeLists.txt               # 本地算法的构建脚本
│   └── library.cpp                  # 常规使用 OpenCV 图像算法相关的源文件
├── thirdparty/                      # 外部依赖库
│   └── heif-suite/                  # libheif 库,需要基于 build_libheif_deps.sh 脚本编译,不同的芯片架构编译出来不同,所以没有放
│   └── libraw/                      # libraw 库
│   └── opencv-install/              # opencv 库,需要基于 build_opencv_world_4100.sh 脚本编译,不同的芯片架构编译出来不同,所以没有放
└── .gitignore                       # git 忽略和不追踪的文件

三. 构建目标明确:跨架构、纯离线部署、适配 Compose Desktop

3.1 支持 Apple Silicon 与 Intel 架构双构建

macOS 正处于从 Intel 向 Apple Silicon(M 系芯片)过渡的阶段,但大量用户与开发者仍在使用 Intel 芯片机器。因此,构建的动态库必须支持 aarch64(arm64)与 x86_64 两种架构,以便在所有用户设备上运行。

这意味着所有依赖库(如 libheif、OpenCV)都必须支持交叉编译或分别构建。

编译参数中要精确控制 -arch 和 CMAKE_OSX_ARCHITECTURES,避免自动识别出错。

3.2 完整的纯离线部署能力

在 Compose Desktop 项目中,Native 动态库并不会像 jar 包那样可以通过 Gradle 自动解析依赖。这就要求打包的 .dylib 是:

  • 自包含的,即所有依赖(如 libopencv_world、libz、libaom 等)都已经通过 @loader_path 正确链接。无需 Homebrew、无需 pkgconfig、无需系统路径解析

  • 可以被直接打包进 Compose Desktop 项目中的 resources,通过 System.loadLibrary() 加载。

为实现这一目标,在我们构建的脚本中专门设置了:

  • 所有库使用 -static 或设置 BUILD_SHARED_LIBS=OFF(除 OpenCV)。

  • 通过 install_name_tool 重写 dylib 引用为 @loader_path。

  • 所有

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值