Search code examples
swiftexif

Some EXIF metadata won't update in Swift


I'm trying to update the metadata of an image but I'm having mixed success. From examples I've found on blogs and Stack Overflow I think I'm doing the correct thing but some values will update, whereas others won't. Can anyone see where I'm going wrong please?

    func writeMetadata(originalImage url: URL) {

        let newDestinationPath = NSTemporaryDirectory().appending("Out.jpg")
        let newDestinationURL = URL(fileURLWithPath: newDestinationPath)

        // Create source and destination
        guard let imageData = try? Data(contentsOf: url),
              let imageSource = CGImageSourceCreateWithData(imageData as CFData, nil),
              let utf = CGImageSourceGetType(imageSource),
              let destination = CGImageDestinationCreateWithURL(newDestinationURL as CFURL, utf, 1, nil) else { return }

        // Get original metadata
        guard let originalImageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil) as? NSDictionary,
              let mutableDictionary = originalImageProperties.mutableCopy() as? NSMutableDictionary,
              let exifDictionary = mutableDictionary[kCGImagePropertyExifDictionary as String] as? NSMutableDictionary else { return }
        print("Original metadata: \(originalImageProperties)")

        // These properties successfully update
        exifDictionary["CameraOwnerName"] = "ADB"
        exifDictionary["ApertureValue"] = 1

        // This property doesn't update
        print("Date Before: \(exifDictionary[kCGImagePropertyExifDateTimeDigitized as String])")
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy:MM:dd HH:mm:ss"
        exifDictionary[kCGImagePropertyExifDateTimeDigitized as String] = dateFormatter.string(from: Date())
        print("Date After: \(exifDictionary[kCGImagePropertyExifDateTimeDigitized as String])")

        // Update original metadata with updated Exif dictionary
        mutableDictionary[kCGImagePropertyExifDictionary as String] = exifDictionary

        // Write new file
        CGImageDestinationAddImageFromSource(destination, imageSource, 0, mutableDictionary as CFDictionary)
        CGImageDestinationFinalize(destination)

        // Fetch updated metadata
        guard let newSource = CGImageSourceCreateWithURL(newDestinationURL as CFURL, nil),
              let newMetadata = CGImageSourceCopyPropertiesAtIndex(newSource, 0, nil) else { return }
        print("Newly updated metadata: \(newMetadata)")
    }

Any guidance much appreciated!


Solution

  • I ran your code, which is running fine and the EXIF data updated as expected for DateTimeDigitized. Would it be possible that you checked the DateTimeOriginal metadata or {TIFF} metadata instead, which you are not updating?

    If you want to set the DateTimeOriginal metadata, it can be done as below using the key kCGImagePropertyExifDateTimeOriginal

    exifDictionary[kCGImagePropertyExifDateTimeOriginal as String] = dateFormatter.string(from: Date())