Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Photo framework: save exif data from picker (aperture, focal length, shutter speed, …)

I'm trying to do the equivalent of writeImageToSavedPhotosAlbum with the new Photo framework.

To save the image, I only do this:

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {

    let image = info[UIImagePickerControllerOriginalImage] as UIImage

    PHPhotoLibrary.sharedPhotoLibrary().performChanges({ () -> Void in
              let changeRequest = PHAssetChangeRequest.creationRequestForAssetFromImage(image)
            }, completionHandler: { (success, error) -> Void in
              //
            })
}

Of course, there's no magic and since I don't do anything of

info[UIImagePickerControllerMediaMetadata]

, the above code doesn't save any metadata to the "Camera Roll", as you can see using the screenshot of the Preview.app when I connect my iPhone to my Mac.

enter image description here

You get that view by opening Preview.app, selecting File > Import from "you device name"; then you can browse your pictures and see that those taken with the Camera app show exif data such as focal length, while those saved with the above code show empty values.

Now the documentation for creationRequestForAssetFromImage says:

To set metadata properties of the newly created asset, use the corresponding properties of the change request (listed in Modifying Assets).

Which links to "+changeRequestForAsset:" and 4 properties (creationDate, location, favorite, hidden), that's a little light. What about the other properties one might want to save (like aperture, focal length, shutter speed, …)?

How are you supposed to save your meta data along the image with the Photo framework?

like image 236
Arnaud Avatar asked Feb 22 '15 22:02

Arnaud


1 Answers

Here's what I ended up doing:

extension UIImage {

  /**
  Gets the metadata from the photo album

  :param: info The picker dictionary
  :param: completionHandler A block to call when the metadata is available
  */
  class func requestMetadata(info: [NSObject : AnyObject], completionHandler: ([NSObject : AnyObject]) -> Void) {
      let assetUrl = info[UIImagePickerControllerReferenceURL] as! NSURL
      let result = PHAsset.fetchAssetsWithALAssetURLs([assetUrl], options: nil)
      if let asset = result.firstObject as? PHAsset {
        let editOptions = PHContentEditingInputRequestOptions()
        editOptions.networkAccessAllowed = true

        asset.requestContentEditingInputWithOptions(editOptions, completionHandler: { (contentEditingInput, _) -> Void in
            let url = contentEditingInput.fullSizeImageURL
            let orientation = contentEditingInput.fullSizeImageOrientation
            var inputImage = CoreImage.CIImage(contentsOfURL: url)
            completionHandler(inputImage.properties())
        })
    } else {
        completionHandler([:])
    }
  }
}
like image 65
Arnaud Avatar answered Nov 12 '22 16:11

Arnaud