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
相关产品推荐
相关产品推荐

