Applying metadata to image creation causes requestChanges to request an error

I use PhotoKit to edit photos, and I need to save the metadata from the original photo. To do this, I save the metadata and then provide it to the options parameter in CGImageDestinationAddImage . I can complete it and write to disk successfully, but when I call performChanges to complete the asset editing, it fails. If instead of nil for options I will do it successfully. What is wrong here?

 asset.requestContentEditingInputWithOptions(options) { (input: PHContentEditingInput!, _) -> Void in //get full image let url = input.fullSizeImageURL let inputImage = CIImage(contentsOfURL: url) //get orginal photo metadata let originalImageData = NSData(contentsOfURL: url)! let imageSource = CGImageSourceCreateWithData(originalImageData, nil) let metadata: CFDictionaryRef = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil) println(metadata) //prints all the metadata, yay! //do some processing on original photo here and create an output CIImage... //save to disk let dataRef = CFDataCreateMutable(nil, 0) let destination = CGImageDestinationCreateWithData(dataRef, CGImageSourceGetType(imageSource), 1, nil) let eaglContext = EAGLContext(API: .OpenGLES2) let ciContext = CIContext(EAGLContext: eaglContext) let cgImage = ContextStruct.ciContext!.createCGImage(outputPhoto, fromRect: outputPhoto.extent()) CGImageDestinationAddImage(destination, cgImage, metadata) //metadata is problematic - replacing with nil causes it to work if CGImageDestinationFinalize(destination) { let contentEditingOutput = PHContentEditingOutput(contentEditingInput: input) contentEditingOutput.adjustmentData = "something" let imageData: NSData = dataRef let success = imageData.writeToURL(contentEditingOutput.renderedContentURL, options: .AtomicWrite, error: _) if success { PHPhotoLibrary.sharedPhotoLibrary().performChanges({ () -> Void in let request = PHAssetChangeRequest(forAsset: asset) request.contentEditingOutput = contentEditingOutput }, completionHandler: { (success: Bool, error: NSError!) -> Void in if success == false { println('failed to commit image edit: \(error)') } //fails unless metadata is replaced with nil above }) } } }) 

Error: Error Domain=NSCocoaErrorDomain Code=-1 "The operation couldn't be completed. (Cocoa error -1.)

+4
ios metadata ciimage photokit phasset
source share
5 answers

Some keys in the metadata seem to crash. It works:

 NSArray *validMetadataKeys = @[ (NSString *)kCGImagePropertyTIFFDictionary, (NSString *)kCGImagePropertyGIFDictionary, (NSString *)kCGImagePropertyJFIFDictionary, (NSString *)kCGImagePropertyExifDictionary, (NSString *)kCGImagePropertyPNGDictionary, (NSString *)kCGImagePropertyIPTCDictionary, (NSString *)kCGImagePropertyGPSDictionary, (NSString *)kCGImagePropertyRawDictionary, (NSString *)kCGImagePropertyCIFFDictionary, (NSString *)kCGImageProperty8BIMDictionary, (NSString *)kCGImagePropertyDNGDictionary, (NSString *)kCGImagePropertyExifAuxDictionary, ]; NSMutableDictionary *validMetadata = [NSMutableDictionary dictionary]; [metadata enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { if ([validMetadataKeys containsObject:key]) { validMetadata[key] = obj; } }]; // your CGImage stuff CGImageDestinationAddImageFromSource(destination, imgSource, 0, (__bridge CFDictionaryRef)validMetadata); 
+1
source share

I have exactly the same problem and I filed the radar rdar: // 21057247. I am trying to register a case using TSI, but I was told to use the radar.

+1
source share

It seems that filling out the adjustementData property of the adjustementData object is mandatory for photo editing.

0
source share

// If the resource does not allow the requested change type, these methods will throw an exception, call canPerformEditOperation: on the asset to determine whether the type of editing operation is allowed.

  • (instancetype) changeRequestForAsset: (PHAsset *) asset;

I think this is because Apple does not want you to change metadata. You can try this method below, perhaps creating a new one is allowed.

  • (instancetype) creationRequestForAssetFromImage: (UIImage *) image;
  • (instancetype) creationRequestForAssetFromImageAtFileURL: (NSURL *) fileURL;
  • (instancetype) creationRequestForAssetFromVideoAtFileURL: (NSURL *) fileURL;
0
source share

We must write the data for the new image in the URL that we get through

  let theExportURL = output.renderedContentURL 

In my case, I did it ...

  let outputData = UIImagePNGRepresentation(bakedImage) 

And at runtime I was getting an error

 Error Domain=NSCocoaErrorDomain Code=-1 "The operation couldn't be completed. (Cocoa error -1.) 

But when I started exporting data like this ...

 let outputData = UIImageJPEGRepresentation(bakedImage, 1) 

It worked. This is described here ... https://developer.apple.com/library/prerelease/ios/documentation/Photos/Reference/PHContentEditingOutput_Class/index.html

and the same question was given here ... https://stackoverflow.com>

0
source share

All Articles