Eugene Gordin
Eugene Gordin

Reputation: 4107

How to enrich UIImage data with metadata

In my app I'm trying to have image data have metadata (location, timestamp etc.). I'm using UIImagePickerController to do image capture, and the delegate function of which has:

info[UIImagePickerController.InfoKey.originalImage]
info[UIImagePickerController.InfoKey.phAsset] 
info[UIImagePickerController.InfoKey.mediaMetadata]

So for the images picked from the library .phAsset has everything I need. I just use .getDataFromPHAsset function to get the enriched data. However, for the images that were just taken .phAsset is nil. I thought about trying to somehow combine .originalImage and .mediaMetadata together into single Data object, but can't get the result desired. I tried to use this approach: https://gist.github.com/kwylez/a4b6ec261e52970e1fa5dd4ccfe8898f

I know I can also make custom imageCapture controller, using AVCaptureSession, and use AVCapturePhoto function .fileDataRepresentation() on didFinishProcessingPhoto delegate call, but that's not my first choice.

Any kind of help is highly appreciated.

Upvotes: 2

Views: 1127

Answers (1)

Don
Don

Reputation: 529

I'm pretty sure mediaMetadata will not have location info. Use this CLLocation extension.

Then use the function below to add the metadata to the image data:

func addImageProperties(imageData: Data, properties: NSMutableDictionary) -> Data? {
  let dict = NSMutableDictionary()
  dict[(kCGImagePropertyGPSDictionary as String)] = properties

  if let source = CGImageSourceCreateWithData(imageData as CFData, nil) {
    if let uti = CGImageSourceGetType(source) {
      let destinationData = NSMutableData()
      if let destination = CGImageDestinationCreateWithData(destinationData, uti, 1, nil) {
        CGImageDestinationAddImageFromSource(destination, source, 0, dict as CFDictionary)
        if CGImageDestinationFinalize(destination) == false {
          return nil
        }                    
        return destinationData as Data
      }
    }
  }
  return nil
}

Usage:

if let imageData = image.jpegData(compressionQuality: 1.0), let metadata = locationManager.location?.exifMetadata() {
  if let newImageData = addImageProperties(imageData: imageData, properties: metadata) {
    // newImageData now contains exif metadata
  }
}

Upvotes: 3

Related Questions