开源鸿蒙PC三方库复现:图像处理框架 G‘MIC CLI 上鸿蒙
开源鸿蒙PC三方库复现:图像处理框架 G’MIC CLI 上鸿蒙
欢迎加入开源鸿蒙 PC 社区:https://harmonypc.csdn.net/
开源仓库地址:https://atomgit.com/OpenHarmonyPCDeveloper/ohos_gmic
本篇基于社区作者 Dream-Y.ocean 的《https://dream-yocean.blog.csdn.net/article/details/161322706》整理,结合我自己的复现重新讲述。运行截图复用自原作者公开素材,致谢。
G’MIC 是个什么量级的库
G’MIC(GREYC’s Magic for Image Computing)是法国 GREYC 实验室的 David Tschumperlé 主导的开源数字图像处理框架。它的「卖点」很唬人——号称 1000+ 图像滤镜命令,色彩调整、几何变换、各种艺术滤镜、图像分析、格式转换无所不包,很多专业图像软件(包括 GIMP 的滤镜插件)背后都有它的影子。
它的核心是 CImg——一个轻量的 C++ 图像处理模板库,整个库几乎就是一个巨大的头文件。G’MIC 在 CImg 之上封装了脚本化的命令语言和 CLI 工具。
那么它比前面的 MediaInfo 复杂在哪?我实测下来主要是三点:
- OpenMP 并行:G’MIC 为了性能默认开 OpenMP,这会引入运行时库依赖。
- 自带标准库需要解压:它有个压缩过的标准库文件,运行时要 zlib 解压。
- CImg 巨型头文件:单文件 7 万多行、3MB+,源码拉取或复制时极易出问题。
这三点恰好就是本次适配的三个主战场,下面逐一拆解。
| 项目 | 信息 |
|---|---|
| 库 | G’MIC CLI |
| 版本 | 3.5.0 |
| 协议 | CeCILL-C |
| 依赖 | CMake、CImg、zlib |
| 构建系统 | CMake |
| 构建主机 | WSL Ubuntu 24.04 |
| 架构 | arm64-v8a |

适配前的调研:先搞清楚它怎么编
我的习惯是动手写 HPKBUILD 之前,先在 Linux 主机上把这个库的原生编译跑通,把它的构建系统、编译开关、依赖关系摸清楚。G’MIC 用 CMake,关键要找的是这几类信息:
- CMakeLists.txt 在哪:是不是在根目录,还是在某个子目录(这决定
-S怎么指)。 - 有哪些编译开关:比如
ENABLE_OPENMP、ENABLE_ZLIB、BUILD_LIB、BUILD_CLI等,每一个都可能影响产物。 - 依赖谁:G’MIC 依赖 CImg(头文件)、zlib(解压标准库),可选依赖一堆图像格式库(libpng、libjpeg、libtiff、fftw 等)。
调研清楚后我就明确了策略:只保留 CLI 工具和最小必要依赖,可选的格式库先全关掉,能编通再说。这又一次印证系列里的「做减法优先」原则——先用最小功能集编出能跑的产物,再按需把功能加回来,比一上来全开导致一堆找不到的依赖要高效得多。
第一战场:libomp.so 找不到(OpenMP 依赖)
问题现象
G’MIC 默认开 OpenMP 来做多核加速。本机编译没问题,但交叉编译出来的产物拷到鸿蒙真机一跑,直接报:
Error loading shared library libomp.so: No such file or directory
原因很清楚:开了 OpenMP 后,产物运行时会动态依赖 libomp.so(OpenMP 运行时库),而鸿蒙系统默认根本没有这个库。
两条路的权衡
摆在面前有两个选择:
- 把 libomp 也交叉编译过来,和 gmic 一起打包分发。这条路能保留多核加速,但要额外适配一个库,还要处理它的签名、rpath 等问题,工作量不小。
- 直接关掉 OpenMP。代价是失去并行加速,但 CLI 批处理场景对这个不那么敏感,而且省去一整个库的适配。
我选了更务实的第二条。在 HPKBUILD 的 cmake 命令里加一行:
-D ENABLE_OPENMP=OFF \
关键:改完一定要清缓存
这里有个新手必栽的坑——改了 HPKBUILD 直接重跑 build.sh,lycium 会因为缓存机制直接跳过构建,你以为关了 OpenMP,其实跑的还是旧产物。必须先清缓存:
# 删构建状态记录
rm -f lycium/usr/hpk_build.csv
# 清旧的源码构建目录和产物
rm -rf thirdparty/gmic/gmic-*
rm -rf lycium/usr/gmic
# 再重新构建
./lycium/build.sh gmic
这个「改配方→清缓存→重编」的三连,是贯穿整个系列的肌肉记忆。
经验沉淀:交叉编译第三方库,遇到「运行时缺某个 .so」,第一反应先判断「这个功能我用不用得上」。用不上就从编译开关层面关掉它,比硬着头皮再适配一个依赖库划算得多。
第二战场:标准库解压不了(zlib 链接问题)
问题现象
G’MIC 有个 gmic_stdlib.gmic 标准库文件,里面就是那 1000+ 滤镜命令的定义。这个文件是压缩存储的,运行时要靠 zlib 把它解开。如果 zlib 没正确链上,真机会报警告:
Could not decompress G'MIC standard library
后果是:gmic 本身还能跑,但所有标准库里的高级滤镜命令都用不了,等于废了大半功能。
根因与解法
我虽然在 cmake 里设了 ENABLE_ZLIB=ON,但在交叉编译环境下,CMake 的自动探测没找到 zlib 的头文件和库文件——因为它默认去主机的系统路径找,而我们要的是鸿蒙 SDK sysroot 里的那份。
解法是显式把路径喂给 CMake,别让它猜:
-D ENABLE_ZLIB=ON \
-D ZLIB_INCLUDE_DIR="${OHOS_SDK}/native/sysroot/usr/include" \
-D ZLIB_LIBRARY="${OHOS_SDK}/native/sysroot/usr/lib/aarch64-linux-ohos/libz.so" \
一个好消息:zlib 鸿蒙 SDK 本身就自带,路径就在 sysroot 下,不用我们自己再交叉编译一份 zlib。这省了不少事。
怎么验证 zlib 真的链上了
两个办法:
- 看运行输出:真机跑
./gmic时不再出现Could not decompress警告,就说明 OK 了。 - 构建环境里用 ldd 查(注意是在构建机的产物上查,看链接关系):
ldd thirdparty/gmic/gmic-3.5.0/arm64-v8a-build/gmic
# 链接列表里应该能看到 libz.so
第三战场:CImg 巨型头文件的处理
G’MIC 依赖 CImg.h 这个模板库。它的特殊之处在于:不是编译成库,而是以纯头文件形式被 #include 进源码,而且单文件就有 7 万多行、3MB 多。
这带来的实际问题是:源码拉取或从 Windows 复制时,这种大文件容易传输不全、或者被工具截断,结果就是编译时一堆「找不到符号 / 未定义」的诡异报错,而且报错信息往往指向不到真正的根因。
我的处理就是确保 CImg.h 完整就位在源码对应目录里,构建时能被正确 include 到。没什么花活,但要养成「拿到源码先核对关键大文件完整性」的习惯。另外 G’MIC 的 CMake 还会强制要求一个 gmic_stdlib_community.h 文件,如果报 Missing gmic_stdlib_community.h,需要从官网下载对应版本:
wget https://gmic.eu/gmic_stdlib_community375.h -O Projects/gmic/src/gmic_stdlib_community.h
hnp.json:这次多了一项 share
前面 MediaInfo 的 hnp.json 只声明了一个 bin 入口。G’MIC 不一样,它要把标准库文件随包发出去,所以 install 里多了 share:
{
"type": "hnp-config",
"name": "gmic",
"version": "3.5.0",
"description": "A full-featured open-source framework for digital image processing (CLI version)",
"license": "CeCILL-C",
"arch": "arm64-v8a",
"install": {
"bin": ["usr/bin/gmic"],
"share": ["usr/share/gmic"]
}
}
usr/share/gmic 里放的就是那个 gmic_stdlib.gmic 标准库文件。这也提醒我:hnp.json 的 install 字段要随产物结构走——产物不只有可执行文件时,别忘了把数据文件、库文件一并声明,否则装到设备上会缺东西。
完整构建流程
# 1. 准备目录和配方文件
cd lycium_plusplus/thirdparty
mkdir -p gmic
cd gmic
vim HPKBUILD # 写入构建配方
# 同目录还要放 hnp.json / README.OpenSource / HPKCHECK
# 2. 清缓存(重编必做)
cd ../../lycium
grep -v 'gmic' usr/hpk_build.csv > usr/hpk_build.csv.tmp
mv usr/hpk_build.csv.tmp usr/hpk_build.csv
rm -rf ../thirdparty/gmic/gmic-3.5.0
rm -rf output/*/gmic*
# 3. 开始构建
./build.sh gmic
构建成功后,产物输出到 output/arm64-v8a/,包含 tar.gz 和 hnp 两种格式。
真机验证:注意它独特的命令行风格
# 解压
tar -zxf gmic_3.5.0.tar.gz
cd usr/bin
# 鸿蒙强制签名
binary-sign-tool sign -inFile gmic -outFile gmic -selfSign "1"
chmod +x gmic
# 直接运行就能看到版本信息
./gmic
# 输出类似:
# gmic: GREYC's Magic for Image Computing: Command-Line Interface
# Version 3.7.5
# 查看版本
./gmic version
# 加载内置 Lena 测试图(图像处理领域的经典测试图)
./gmic sp lena
这里有个我一开始踩的坑:G’MIC 不吃 --help、--version 这种 GNU 风格的双横线参数。它自己的风格是:
- 看帮助:
./gmic help | less -r - 看版本:直接
./gmic(不带任何参数)
习惯了标准 GNU 工具的人,很容易在这里以为「程序坏了」,其实只是命令风格不同。适配一个工具,了解它本身的使用约定也是验证环节的一部分。

常见问题速查(FAQ)
| 现象 | 根因 | 解决 |
|---|---|---|
Missing gmic_stdlib_community.h |
CMake 强制要求该文件 | 从 gmic.eu 下载对应版本放到 src/ |
Error loading shared library libomp.so |
开了 OpenMP,鸿蒙无此库 | -D ENABLE_OPENMP=OFF |
Could not decompress G'MIC standard library |
zlib 没正确链接 | 显式指定 ZLIB_INCLUDE_DIR / ZLIB_LIBRARY |
| 改完 HPKBUILD 不生效 | 构建缓存 | 删 hpk_build.csv 和旧产物 |
./gmic --help 报错 |
G’MIC 不用双横线参数 | 用 ./gmic help |
$'\r': command not found |
CRLF 换行符 | Python 二进制转 LF |
小结
G’MIC 这一篇的两个核心收获,都很有「图像/多媒体类库」的代表性:
- OpenMP 依赖的取舍 —— 关掉 vs 适配 libomp,按场景务实选择;
- zlib 路径的显式喂养 —— 交叉环境别信 CMake 自动探测,把 SDK sysroot 里的路径写死。
再加上 CImg 大头文件的完整性、hnp.json 的 share 声明,这套经验可以直接迁移到 ImageMagick、GraphicsMagick 这类同样依赖图像格式库的工具上。
值得一提的是,从这一篇开始,适配作者换成了 Dream-Y.ocean。接下来两篇他带来的是真正的硬骨头——媒体播放器 mpv 的多层依赖适配,那才是检验适配功力的大考。感谢原创适配作者 Dream-Y.ocean 的开源分享。
更多推荐




所有评论(0)