You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求非C++环境下读写DNG等文件XMP/IPTC元数据的最优方案

批量处理XMP/IPTC元数据的简洁方案(非C++ Adobe SDK)

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 11:27:07