exempi 是最稳妥的 xmp 解析库,需正确配置动态库路径、验证 mime 类型、使用完整命名空间(如 "xmp:creatortool")、调用 xmp_files_put_xmp 同步修改并 close 保存,heic 等格式需检查返回值。

用 Exempi 库读取 XMP 是最稳妥的选择
Adobe 官方不提供 C++ 原生 SDK,Exempi 是目前唯一被广泛验证、持续维护的开源 XMP 解析库(基于 Adobe 的 XMP SDK C 封装)。它支持读写 RDF/XML 格式的 XMP 数据包,覆盖 JPEG、PNG、TIFF、PDF 等主流嵌入场景。
编译时注意:必须启用 EXEMPI_BUILD_SHARED(否则 libexempi 静态链接会缺失符号),且依赖 libxml2 和 zlib。macOS 上用 Homebrew 安装后,头文件路径通常是 /opt/homebrew/include/(Apple Silicon)或 /usr/local/include/(Intel)。
常见错误现象:exempi: error while loading shared libraries: libexempi.so.3: cannot open shared object file——说明运行时找不到动态库,需设置 LD_LIBRARY_PATH(Linux)或 DYLD_LIBRARY_PATH(macOS)。
xmp_files_open 打开文件前必须检查 MIME 类型
XMP 不是独立文件,而是嵌入在宿主文件(如 JPEG)中的数据块。Exempi 依赖文件头识别格式,直接传入裸 XML 文件会失败。
实操建议:
- 用
libmagic或简单判断文件头(如 JPEG 是0xFFD8,PNG 是0x89504E47)确认真实类型 - 调用
xmp_files_open时第二个参数必须是正确 MIME 类型字符串,例如"image/jpeg"、"image/tiff",不能填"application/rdf+xml" - 返回值为
nullptr且无报错,大概率是 MIME 类型不匹配或文件无 XMP 包
提取 xmp:CreatorTool 这类标准字段要指定命名空间
XMP 使用 RDF 模型,字段名实际是带前缀的 URI。比如 CreatorTool 对应完整路径是 xmp:CreatorTool,其命名空间为 "http://ns.adobe.com/xap/1.0/"。直接查 "CreatorTool" 会返回空。
正确做法:
- 用
xmp_get_property时,第一个参数是XmpPtr,第二个是完整限定名,如"xmp:CreatorTool" - 若字段属于自定义命名空间(如
my:ProjectID),需先用xmp_register_namespace注册 URI,再使用前缀形式查询 - 返回值是
char*,内容为 UTF-8 编码,记得用xmp_free释放内存
示例片段:
XmpPtr xmp = xmp_files_get_xmp(xmpfile);
char* tool = nullptr;
xmp_get_property(xmp, "xmp:CreatorTool", &tool, nullptr);
if (tool) {
printf("Created by: %s\n", tool);
xmp_free(tool);
}
修改 XMP 后必须调用 xmp_files_put_xmp 并保存到磁盘
所有 xmp_set_* 操作只修改内存中的 XMP 对象,不会自动写回原文件。漏掉这步是新手最高频失误。
关键步骤:
- 修改完后调用
xmp_files_put_xmp(xmpfile, xmp)—— 此函数把内存 XMP 同步进XmpFilePtr内部缓冲区 - 再调用
xmp_files_close(xmpfile),此时库才真正将更新后的 XMP 嵌入原始文件(JPEG/TIFF 等)或生成新文件(PDF 需额外处理) - 对 PDF 文件,
Exempi默认不覆盖原文件,而是生成.xmp侧车文件,需手动合并或改用pdfium+Exempi组合方案
容易被忽略的是:某些格式(如 HEIC)不支持原地写入 XMP,xmp_files_put_xmp 可能静默失败,务必检查其返回值(bool 类型)。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











