以下功能加载照片,编辑附加到其上的exif元数据并将其保存回来。该功能似乎只适用于已经附加了PHAdjustmentData的照片,即之前已使用其他应用程序编辑过的照片。如果照片尚未编辑,则在performChanges()块中失败并打印
Failed to save. Error: Optional(Error Domain=NSCocoaErrorDomain Code=-1 "(null)").
为什么在这种情况下会失败?浏览Stack Overflow我已经看到了这个问题的许多其他版本,但似乎没有一个得到解决。我知道如果保存的图像是PNG但我的原始图像是JPEG,则失败,因此保存的图像也是JPEG。
func editPhotoProperties(_ asset: PHAsset) {
let options = PHContentEditingInputRequestOptions()
options.canHandleAdjustmentData = { data in
return false
}
asset.requestContentEditingInput(with: options) { input, info in
if let input = input {
let adjustmentData = PHAdjustmentData(formatIdentifier:"viewfinder", formatVersion:"1.0", data:"viewfinder".data(using:.utf8)!)
let output = PHContentEditingOutput(contentEditingInput:input)
output.adjustmentData = adjustmentData
do {
let imageData = try Data(contentsOf:input.fullSizeImageURL!)
} catch {
print("Failed to load data")
return
}
let properties = getImageDataProperties(imageData)!
let properties2 = properties.mutableCopy() as! NSMutableDictionary
// edit properties2
...
let newImageData = addImageProperties(imageData: imageData, properties: properties2)
do {
try newImageData!.write(to: output.renderedContentURL, options: .atomic)
} catch {
print("Failed to write to disk")
return
}
PHPhotoLibrary.shared().performChanges({
let changeRequest = PHAssetChangeRequest(for:asset)
changeRequest.contentEditingOutput = output
}) { success, error in
if !success {
print("Failed to save. Error: \(String(describing:error))")
}
}
}
}
}
func getImageDataProperties(_ data: Data) -> NSDictionary? {
if let imageSource = CGImageSourceCreateWithData(data as CFData, nil) {
if let dictionary = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil) {
return dictionary
}
}
return nil
}
// add image properties (exif, gps etc) to image
func addImageProperties(imageData: Data, properties: NSDictionary?) -> Data? {
// create an imagesourceref
if let source = CGImageSourceCreateWithData(imageData as CFData, nil) {
// this is of type image
if let uti = CGImageSourceGetType(source) {
// create a new data object and write the new image into it
let destinationData = NSMutableData()
if let destination = CGImageDestinationCreateWithData(destinationData, uti, 1, nil) {
// add the image contained in the image source to the destination, overidding the old metadata with our modified metadata
CGImageDestinationAddImageFromSource(destination, source, 0, properties)
if CGImageDestinationFinalize(destination) == false {
return nil
}
return destinationData as Data
}
}
}
return nil
}