Search code examples
iosswiftuikituiimage

Add GPS data to UIImage


I have a custom in-app build camera. This camera can take photos and videos and after this it saves the photos to the user library. I now want to add the current location from the iPhone while the picture was made to the image. I found this:

func addLocationToImage(image: UIImage, location: CLLocation) throws -> UIImage {
    guard let data = image.jpegData(compressionQuality: 1.0) else {
        throw NSError(domain: "error", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to get JPEG data from image."])
    }

    let metadata = NSMutableDictionary()
    let gpsDict = NSMutableDictionary()

    let latitude = location.coordinate.latitude
    let longitude = location.coordinate.longitude

    gpsDict[(kCGImagePropertyGPSLatitude as String)] = abs(latitude)
    gpsDict[(kCGImagePropertyGPSLatitudeRef as String)] = latitude < 0.0 ? "S" : "N"
    gpsDict[(kCGImagePropertyGPSLongitude as String)] = abs(longitude)
    gpsDict[(kCGImagePropertyGPSLongitudeRef as String)] = longitude < 0.0 ? "W" : "E"

    metadata[(kCGImagePropertyGPSDictionary as String)] = gpsDict

    guard let source = CGImageSourceCreateWithData(data as CFData, nil) else {
        throw NSError(domain: "error", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to create image source from data."])
    }

    let uti = CGImageSourceGetType(source)!
    let mutableData = NSMutableData(data: data)

    guard let destination = CGImageDestinationCreateWithData(mutableData, uti, 1, nil) else {
        throw NSError(domain: "error", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to create image destination."])
    }

    CGImageDestinationAddImageFromSource(destination, source, 0, metadata)

    guard CGImageDestinationFinalize(destination) else {
        throw NSError(domain: "error", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to write image with metadata to data."])
    }

    guard let imageWithGPSData = UIImage(data: mutableData as Data) else {
        throw NSError(domain: "error", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to create image from data with GPS metadata."])
    }

    return imageWithGPSData
}

But this doesn't seem to work. Have I done something wrong, because the location is there but it doesn't get added to the image.


Solution

  • UIImage doesn't have any metadata. Once you go from the updated data (with the added GPS info) back to UIImage, that metadata is lost.

    Update your method to return the updated Data (mutableData) instead of a UIImage. Then you can persist that data as needed so it's saved with the new metadata.