寻求非C++环境下读写DNG等文件XMP/IPTC元数据的最优方案
Python 方案(推荐优先级最高)
虽然你提到Exempi相关的Python Toolkit有问题,但可以换用更易用的exiftool相关方案——这是支持性最全面的选择,几乎覆盖所有图像格式的元数据(包括XMP、IPTC、EXIF),且和Adobe的元数据标准完全兼容。
方案1:直接调用ExifTool命令行(最稳定,无库依赖问题)
ExifTool是Perl编写的专业元数据处理工具,你只需先在系统中安装它,再用Python的subprocess直接调用,完全避开Python库的依赖坑:
import subprocess import os def process_directory(dir_path): for filename in os.listdir(dir_path): if filename.lower().endswith(('.jpg', '.png', '.tiff', '.raw')): file_path = os.path.join(dir_path, filename) # 读取指定XMP/IPTC字段 read_result = subprocess.run( ['exiftool', '-XMP:Subject', '-IPTC:Keywords', file_path], capture_output=True, text=True ) print(f"文件 {filename} 元数据:\n{read_result.stdout}") # 特定条件下修改(示例:含目标关键词则追加新关键词) if "目标关键词" in read_result.stdout: subprocess.run( ['exiftool', '-IPTC:Keywords+=新增关键词', '-XMP:Subject+=新增关键词', file_path] ) process_directory('/path/to/your/target/dir')
优势:兼容性拉满,支持所有主流图像格式,元数据处理逻辑和Adobe工具完全一致,无库版本冲突问题。
方案2:使用pyexiftool封装库(代码更简洁)
如果觉得直接写subprocess繁琐,可以用pyexiftool做封装,本质还是调用ExifTool:
pip install pyexiftool
from exiftool import ExifToolHelper import os with ExifToolHelper() as et: for filename in os.listdir('/path/to/target/dir'): if filename.lower().endswith(('.jpg', '.png')): file_path = os.path.join('/path/to/target/dir', filename) # 读取元数据 metadata = et.get_metadata(file_path)[0] xmp_subject = metadata.get('XMP:Subject', []) iptc_keywords = metadata.get('IPTC:Keywords', []) # 条件修改 if "触发关键词" in xmp_subject: et.execute( '-IPTC:Keywords+=更新关键词', '-XMP:Subject+=更新关键词', file_path )
Java 方案
推荐优先调用ExifTool命令行(逻辑和Python一致,用ProcessBuilder实现),如果必须用原生库,可结合metadata-extractor(读取)和Apache Commons Imaging(修改):
读取元数据示例
import com.drew.imaging.ImageMetadataReader; import com.drew.metadata.Metadata; import com.drew.metadata.xmp.XmpDirectory; import com.drew.metadata.iptc.IptcDirectory; import java.io.File; public class MetadataReader { public static void main(String[] args) throws Exception { File dir = new File("/path/to/target/dir"); for (File file : dir.listFiles()) { String ext = file.getName().toLowerCase(); if (ext.endsWith(".jpg") || ext.endsWith(".png")) { Metadata metadata = ImageMetadataReader.readMetadata(file); // 读取XMP主题 XmpDirectory xmpDir = metadata.getFirstDirectoryOfType(XmpDirectory.class); if (xmpDir != null) { String subject = xmpDir.getXmpMeta().getPropertyString("http://purl.org/dc/elements/1.1/", "subject"); System.out.println("XMP Subject: " + subject); } // 读取IPTC关键词 IptcDirectory iptcDir = metadata.getFirstDirectoryOfType(IptcDirectory.class); if (iptcDir != null) { String keywords = iptcDir.getString(IptcDirectory.TAG_KEYWORDS); System.out.println("IPTC Keywords: " + keywords); } } } } }
注意:Java原生修改元数据逻辑较繁琐,优先推荐调用ExifTool命令行。
PHP 方案
直接调用ExifTool命令行是最简洁的选择,无需复杂库依赖:
$dir = '/path/to/target/dir'; $files = scandir($dir); foreach ($files as $file) { $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION)); if (in_array($ext, ['jpg', 'png', 'tiff'])) { $filePath = $dir . '/' . $file; // 读取元数据 $output = shell_exec("exiftool -XMP:Subject -IPTC:Keywords " . escapeshellarg($filePath)); echo "文件 $file 元数据:\n$output\n"; // 条件修改 if (strpos($output, '触发关键词') !== false) { shell_exec("exiftool -IPTC:Keywords+=新增关键词 -XMP:Subject+=新增关键词 " . escapeshellarg($filePath)); } } }
JavaScript/Node.js 方案
使用exiftool-vendored库,它内置了ExifTool二进制文件,无需系统提前安装,开箱即用:
npm install exiftool-vendored
const { ExifTool } = require('exiftool-vendored'); const fs = require('fs').promises; const path = require('path'); async function processDirectory(dirPath) { const exiftool = new ExifTool(); const files = await fs.readdir(dirPath); for (const file of files) { const ext = path.extname(file).toLowerCase(); if (['.jpg', '.png', '.tiff'].includes(ext)) { const filePath = path.join(dirPath, file); // 读取元数据 const metadata = await exiftool.read(filePath); const xmpSubject = metadata.XMPSubject; const iptcKeywords = metadata.IPTCKeywords; console.log(`文件 ${file} 的XMP主题: ${xmpSubject}`); // 条件修改 if (xmpSubject?.includes('触发关键词')) { await exiftool.write(filePath, { IPTCKeywords: [...(iptcKeywords || []), '新增关键词'], XMPSubject: [...(xmpSubject || []), '新增关键词'] }); } } } await exiftool.end(); } processDirectory('/path/to/target/dir');
总结
综合支持性、简洁度和兼容性,优先推荐使用ExifTool命令行+对应语言的调用/封装库——ExifTool是行业标准工具,支持所有主流图像格式的XMP/IPTC元数据,和Adobe的元数据处理逻辑完全兼容,几乎不会出现兼容性问题。
如果是Python环境,直接用subprocess调用ExifTool最稳定;Node.js环境用exiftool-vendored最省心;Java/PHP环境同样优先考虑调用ExifTool命令行,比原生库的修改操作简单得多。
内容的提问来源于stack exchange,提问作者bmdev

