Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
import UIKit
import MobileCoreServices
import ImageIO
let sourceOptions: [String: AnyObject] = [kCGImageSourceTypeIdentifierHint as String: kUTTypeJPEG]
let cfSourceOptions = sourceOptions as CFDictionary
let image = UIImage(named: "input.jpg")!
let data = UIImageJPEGRepresentation(image, 1.0)
let source: CGImageSource = CGImageSourceCreateWithData(data as! CFData, cfSourceOptions)!
let filepath = NSTemporaryDirectory().appending("out.jpg")
print("Output file:")
print(filepath)
let fileURL: URL = URL(fileURLWithPath: filepath)
let destination: CGImageDestination = CGImageDestinationCreateWithURL(fileURL as CFURL, kUTTypeJPEG, 1, nil)!
var makeTag = CGImageMetadataTagCreate(
kCGImageMetadataNamespaceTIFF, kCGImageMetadataPrefixTIFF, kCGImagePropertyTIFFMake, .string, "Make" as CFString
)!
var modelTag = CGImageMetadataTagCreate(
kCGImageMetadataNamespaceTIFF, kCGImageMetadataPrefixTIFF, kCGImagePropertyTIFFModel, .string, "Model" as CFString
)!
var metaDatas = CGImageMetadataCreateMutable()
var tagPath = "tiff:Make" as CFString
var result = CGImageMetadataSetTagWithPath(metaDatas, nil, tagPath, makeTag)
tagPath = "tiff:Model" as CFString
result = CGImageMetadataSetTagWithPath(metaDatas, nil, tagPath, modelTag)
let destOptions: [String: AnyObject] = [
kCGImageDestinationMergeMetadata as String: NSNumber(value: 1),
kCGImageDestinationMetadata as String: metaDatas
]
let cfDestOptions = destOptions as CFDictionary
var error: Unmanaged<CFError>?
var errorPtr: UnsafeMutablePointer<CFError>
withUnsafeMutablePointer(to: &error, { ptr in
result = CGImageDestinationCopyImageSource(destination, source, cfDestOptions, ptr)
print(String(format: "Write image to file result: %@", result ? "Success" : "Failed"))
print(String(format: "With error: %@", error.debugDescription))
})
let writeResult = CGImageDestinationFinalize(destination)
// This is false, and you may see an error like:
// " ImageIO: finalize:2031: not allowed for image destination that was updated with CGImageDestinationCopyImageSource "
// But, in practice, it works. The file is there and the metadata is correct.
print(writeResult)
@maurymarkowitz

This comment has been minimized.

Copy link

maurymarkowitz commented Mar 15, 2017

What is the purpose of line 52:

var errorPtr: UnsafeMutablePointer

It is not used anywhere, and Xcode complains about that.

@maurymarkowitz

This comment has been minimized.

Copy link

maurymarkowitz commented Mar 15, 2017

And just a note to anyone trying this: you can only add data for tags that are "known". If you try to make your own tags they just disappear. Even the most minor errors in the strings, like the tagPath, will cause the data to disappear when it's saved. To add to the annoyance, Apple's documentation is wrong - most of the possible tags are shown as being CFString types, but there are many that are actually numbers and will fail to be saved if you don't provide a number. An example is TIFFOrientation, where it claims to be a CFString but you must provide a number using NSNumber(value:5) or it simply won't save.

@lacyrhoades

This comment has been minimized.

Copy link
Owner Author

lacyrhoades commented Apr 12, 2017

@maurymarkowitz no idea about errorPtr I ended up not having that line in production. Thanks for the tips too!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.