0

How do you set kCGImagePropertyExifUserComment on a CGImageMetadataRef in iOS? These are the only functions I have found and they are only for MacOS

https://github.com/phracker/MacOSX-SDKs/blob/master/MacOSX10.9.sdk/System/Library/Frameworks/ImageIO.framework/Versions/A/Headers/CGImageMetadata.h

Nick Wilkerson
  • 353
  • 2
  • 17

2 Answers2

2

Given image data you can get it's properties with the following

func getImageDataProperties(_ data: Data) -> NSDictionary? {
    if let imageSource = CGImageSourceCreateWithData(imageData as CFData, nil) 
    {
        if let dictionary = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil) {
            return dictionary
        }
    }
    return nil
}

The exif comments can be accessed as follows with the properties

if let properties = getImageDataProperties(data) {
    if let exif = properties[kCGImagePropertyExifDictionary] as? NSDictionary {
        if let comment = exif[kCGImagePropertyExifUserComment] as? String {
            ...
        }
    }
}

Once you have edited the comments you can save your image with the following given you original image data and your altered properties dictionary

// add image properties (exif, gps etc) to image
func addImageProperties(imageData: Data, properties: NSMutableDictionary) -> Data? {

    // create an imagesourceref
    if let source = CGImageSourceCreateWithData(imageData as CFData, nil) {
        // this is of type image
        if let uti = CGImageSourceGetType(source) {

            // create a new data object and write the new image into it
            let destinationData = NSMutableData()
            if let destination = CGImageDestinationCreateWithData(destinationData, uti, 1, nil) {

                // add the image contained in the image source to the destination, overidding the old metadata with our modified metadata
                CGImageDestinationAddImageFromSource(destination, source, 0, properties)
                if CGImageDestinationFinalize(destination) == false {
                    return nil
                }
                return destinationData as Data
            }
        }
    }
    return nil
}
adamfowlerphoto
  • 2,708
  • 1
  • 11
  • 24
  • I should have specified, I am really looking for how to do this with core foundation in C not with swift. – Nick Wilkerson Jun 13 '17 at 21:29
  • I believe all these functions are available in objective C so if you can convert back to objective C it should work. – adamfowlerphoto Jun 13 '17 at 21:31
  • They are available in objective C, but they are not available in Core Foundation which is C. CGImageSourceRef and CGImageMetadataRef are C data types and I don't know how to bridge them to Objective-C or rather, which Objective-C datatypes they can be bridged to. In MacOS, it looks like this is the function used CGImageMetadataSetTagWithPath() but it is not available on iOS. – Nick Wilkerson Jun 13 '17 at 21:47
  • @Spads Why do you create `destinationData = NSMutableData()` and set that as the initial data object for `destination`? Others just pass in the original image data. As shown in this [StackOverflow Swift Answer](https://stackoverflow.com/questions/38132357/swift-custom-camera-save-modified-metadata-with-image/42818232#answer-42818232) – Mudlabs Jul 19 '18 at 23:36
0

Create a mutable copy of the CGImageMetadataRef with CGImageMetadataCreateMutableCopy. Then set the property with

CGImageMetadataSetValueMatchingImageProperty(
    mutableCopy, 
    kCGImagePropertyExifDictionary, 
    kCGImagePropertyExifUserComment, 
    value)

where value is your comment as a CFTypeRef.

heilerich
  • 944
  • 8
  • 14