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

iOS Swift应用获取DJI无人机图片Xmp.drone-dji元数据遇阻求助

解决DJI无人机图片Xmp.drone-dji元数据提取问题

问题原因

CGImageSource默认不会主动解析DJI自定义的XMP命名空间(http://www.dji.com/drone-dji/1.0/),所以直接通过常规属性或元数据列表无法获取到Xmp.drone-dji相关字段。

解决方案

以下提供两种可行的实现方式:

方式1:通过CGImageMetadata遍历指定命名空间标签

直接遍历图片元数据,筛选DJI专属命名空间下的所有标签:

result.itemProvider.loadDataRepresentation(forTypeIdentifier: UTType.image.identifier) { data, err in
    guard let data = data else { return }
    
    let src = CGImageSourceCreateWithData(data as CFData, nil)!
    // 获取完整元数据对象
    guard let metadata = CGImageSourceCopyMetadataAtIndex(src, 0, nil) else { return }
    
    // DJI无人机XMP命名空间
    let djiXmpNamespace = "http://www.dji.com/drone-dji/1.0/"
    let tagCount = CGImageMetadataGetCount(metadata)
    
    for i in 0..<tagCount {
        guard let tag = CGImageMetadataCopyTagAtIndex(metadata, i) else { continue }
        let tagNamespace = CGImageMetadataTagCopyNamespace(tag) as? String
        let tagName = CGImageMetadataTagCopyName(tag) as? String
        
        if tagNamespace == djiXmpNamespace {
            let tagValue = CGImageMetadataTagCopyValue(tag)
            print("DJI元数据:\(tagName ?? "") = \(tagValue ?? "")")
            // 这里可以将结果存入字典或模型中
        }
    }
}

方式2:解析原始XMP数据(XML格式)

如果方式1无法获取,直接提取原始XMP数据后用XML解析:

// 先实现XMLParserDelegate协议
class XMPParserDelegate: NSObject, XMLParserDelegate {
    private var djiMetadata = [String: String]()
    private var currentElement = ""
    // DJI命名空间前缀,通常为drone-dji
    private let djiPrefix = "drone-dji:"
    
    func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
        currentElement = elementName
        // 检查是否是DJI命名空间下的元素
        if qName?.hasPrefix(djiPrefix) == true {
            currentElement = qName?.replacingOccurrences(of: djiPrefix, with: "") ?? ""
        }
    }
    
    func parser(_ parser: XMLParser, foundCharacters string: String) {
        let trimmedString = string.trimmingCharacters(in: .whitespacesAndNewlines)
        if !trimmedString.isEmpty && !currentElement.isEmpty {
            djiMetadata[currentElement] = trimmedString
        }
    }
    
    func parserDidEndDocument(_ parser: XMLParser) {
        print("解析到的DJI元数据:\(djiMetadata)")
        // 在这里处理解析后的结果
    }
}

// 调用解析逻辑
result.itemProvider.loadDataRepresentation(forTypeIdentifier: UTType.image.identifier) { data, err in
    guard let data = data else { return }
    
    let src = CGImageSourceCreateWithData(data as CFData, nil)!
    let properties = CGImageSourceCopyPropertiesAtIndex(src, 0, nil) as? [CFString: Any]
    
    // 获取原始XMP数据
    if let xmpData = properties?[kCGImagePropertyXMPData] as? Data {
        let delegate = XMPParserDelegate()
        let parser = XMLParser(data: xmpData)
        parser.delegate = delegate
        parser.parse()
    }
}

注意事项

  • 确保测试图片确实包含DJI的XMP元数据(可通过exiftool、exiv2再次验证)
  • 部分DJI图片可能将元数据存储在其他字段(如EXIF的私有标签),如果上述方法无效,可尝试遍历kCGImagePropertyExifDictionary下的所有键值对排查

内容的提问来源于stack exchange,提问作者rdk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 10:50:23